Trying to gather thoughts and code coherently.
Added client-side architecture model. Playing with UI code.
This commit is contained in:
parent
9025a2f8f6
commit
302bc9ccdd
Binary file not shown.
Binary file not shown.
34
doc/model.txt
Normal file
34
doc/model.txt
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
Data
|
||||||
|
----
|
||||||
|
UserModel
|
||||||
|
TimelineModel
|
||||||
|
TimelineListModel
|
||||||
|
EntryListModel
|
||||||
|
EntryModel
|
||||||
|
|
||||||
|
|
||||||
|
Views
|
||||||
|
-----
|
||||||
|
EntryView
|
||||||
|
NewEntryInput
|
||||||
|
TimelineListView
|
||||||
|
TimelineView
|
||||||
|
UserView
|
||||||
|
|
||||||
|
|
||||||
|
Data Dependencies
|
||||||
|
-----------------
|
||||||
|
UserModel: none
|
||||||
|
TimelineModel: UserModel
|
||||||
|
TimelineListModel: UserModel
|
||||||
|
EntryModel: TimelineModel
|
||||||
|
EntryListModel: TimelineModel
|
||||||
|
|
||||||
|
|
||||||
|
View Dependencies
|
||||||
|
-----------------
|
||||||
|
UserView: UserModel
|
||||||
|
TimelineView: TimelineModel, UserView
|
||||||
|
TimelineListView: TimelineListModel, UserView
|
||||||
|
EntryView: EntryModel, EntryListView
|
||||||
|
EntryListView: EntryListModel, TimelineView
|
BIN
doc/model.xcf
Normal file
BIN
doc/model.xcf
Normal file
Binary file not shown.
@ -34,10 +34,12 @@ body {
|
|||||||
display: inline-block; }
|
display: inline-block; }
|
||||||
#user.fullname-edit .fullname {
|
#user.fullname-edit .fullname {
|
||||||
display: none; }
|
display: none; }
|
||||||
#user ul#user-controls {
|
#user .drop-menu {
|
||||||
|
display: inline-block; }
|
||||||
|
#user .drop-menu .drop-menu-items {
|
||||||
float: right;
|
float: right;
|
||||||
list-style: none; }
|
list-style: none; }
|
||||||
#user ul#user-controls li {
|
#user .drop-menu .drop-menu-items li {
|
||||||
float: right;
|
float: right;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-right: 1em; }
|
padding-right: 1em; }
|
||||||
@ -54,13 +56,25 @@ body {
|
|||||||
#timeline .timeline-desc {
|
#timeline .timeline-desc {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 70%; }
|
width: 70%; }
|
||||||
|
#timeline .timeline-desc-input {
|
||||||
|
width: 70%; }
|
||||||
#timeline .timeline-id {
|
#timeline .timeline-id {
|
||||||
display: inline-block; }
|
display: inline-block; }
|
||||||
#timeline .timeline-menu {
|
#timeline .timeline-desc-input, #timeline .timeline-id-input {
|
||||||
|
display: none; }
|
||||||
|
#timeline.edit-id .timeline-id-input {
|
||||||
|
display: inline-block; }
|
||||||
|
#timeline.edit-id .timeline-id {
|
||||||
|
display: none; }
|
||||||
|
#timeline.edit-desc .timeline-desc-input {
|
||||||
|
display: inline-block; }
|
||||||
|
#timeline.edit-desc .timeline-desc {
|
||||||
|
display: none; }
|
||||||
|
#timeline .drop-menu {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 29%; }
|
width: 29%; }
|
||||||
#timeline .timeline-menu .drop-menu-items {
|
#timeline .drop-menu .drop-menu-items {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
right: 0; }
|
right: 0; }
|
||||||
|
|
||||||
|
@ -48,7 +48,10 @@ body {
|
|||||||
.fullname { display: none; }
|
.fullname { display: none; }
|
||||||
}
|
}
|
||||||
|
|
||||||
ul#user-controls {
|
.drop-menu { display: inline-block; }
|
||||||
|
|
||||||
|
.drop-menu .drop-menu-items {
|
||||||
|
|
||||||
float: right;
|
float: right;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
|
||||||
@ -81,9 +84,23 @@ body {
|
|||||||
width: 70%;
|
width: 70%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.timeline-desc-input { width: 70% }
|
||||||
|
|
||||||
.timeline-id { display: inline-block; }
|
.timeline-id { display: inline-block; }
|
||||||
|
|
||||||
.timeline-menu {
|
.timeline-desc-input, .timeline-id-input { display: none; }
|
||||||
|
|
||||||
|
&.edit-id {
|
||||||
|
.timeline-id-input { display: inline-block; }
|
||||||
|
.timeline-id { display: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
&.edit-desc {
|
||||||
|
.timeline-desc-input { display: inline-block; }
|
||||||
|
.timeline-desc { display: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.drop-menu {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 29%;
|
width: 29%;
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>TimeStamper - Simple Time Tracking</title>
|
<title>TimeStamper - Simple Time Tracking</title>
|
||||||
<link href='http://fonts.googleapis.com/css?family=Arvo|Bentham|Cuprum|Cantarell|Geo|Josefin+Sans' rel='stylesheet' type='text/css'>
|
<link href='http://fonts.googleapis.com/css?family=Arvo|Bentham|Cuprum|Cantarell|Geo|Josefin+Sans' rel='stylesheet' type='text/css'>
|
||||||
<link rel="stylesheet" media="screen" href="css/dot-luv/jquery-ui-1.8.10.custom.css" type="text/css"/>
|
<link rel="stylesheet" media="screen" href="/css/dot-luv/jquery-ui-1.8.10.custom.css" type="text/css"/>
|
||||||
<link rel="stylesheet" media="screen" href="css/ts-screen.css" type="text/css"/>
|
<link rel="stylesheet" media="screen" href="/css/ts-screen.css" type="text/css"/>
|
||||||
<!-- Needed for IE, but I'm not sure if I'm going to support IE with this tool. -->
|
<!-- Needed for IE, but I'm not sure if I'm going to support IE with this tool. -->
|
||||||
<!--<script type="text/javascript" src="/js/json2.js"></script>-->
|
<!--<script type="text/javascript" src="/js/json2.js"></script>-->
|
||||||
<!-- PROD -->
|
<!-- PROD -->
|
||||||
@ -13,44 +13,54 @@
|
|||||||
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/jquery-ui.min.js"></script>
|
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/jquery-ui.min.js"></script>
|
||||||
-->
|
-->
|
||||||
<!-- DEV -->
|
<!-- DEV -->
|
||||||
<script type="text/javascript" src="js/jquery-1.5.min.js"></script>
|
<script type="text/javascript" src="/js/jquery-1.5.js"></script>
|
||||||
<script type="text/javascript" src="js/jquery-ui-1.8.10.custom.min.js"></script>
|
<script type="text/javascript" src="/js/jquery-ui-1.8.10.custom.min.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="js/underscore-min.js"></script>
|
<script type="text/javascript" src="/js/underscore.js"></script>
|
||||||
<script type="text/javascript" src="js/ICanHaz.js"></script>
|
<script type="text/javascript" src="/js/ICanHaz.js"></script>
|
||||||
<script type="text/javascript" src="js/backbone-min.js"></script>
|
<script type="text/javascript" src="/js/backbone.js"></script>
|
||||||
<script type="text/javascript" src="js/ts.js"></script>
|
<script type="text/javascript" src="/js/ts.js"></script>
|
||||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||||
|
|
||||||
<script id="timelineLink" type="test/html">
|
<script id="timelineLink" type="text/html">
|
||||||
<li><a href="#">{{id}}</a></li>
|
<li><a href="#">{{id}}</a></li>
|
||||||
</script>
|
</script>
|
||||||
|
<script id="entry" type="text/html">
|
||||||
|
<div class="entry">
|
||||||
|
<div class="mark">{{mark}}</div>
|
||||||
|
<input class="mark-input" type="text">{{mark}}</input>
|
||||||
|
<div class="timestamp">{{timestamp}}</div>
|
||||||
|
<input class="timestamp-input" type="text">{{timestamp}}</input>
|
||||||
|
<div class="duration">4<span class="tick-tock">:</span>03<span class="tick-tock">:</span>57</div>
|
||||||
|
<div class="notes">{{notes}}</div>
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div id="top">
|
<div id="top">
|
||||||
<div id="timeline">
|
<div id="timeline">
|
||||||
<span class="timeline-desc">Work-related events.</span>
|
<span class="timeline-desc">No timeline loaded.</span>
|
||||||
<input class="timeline-desc-input" type="text"/>
|
<input class="timeline-desc-input" type="text"/>
|
||||||
<div class="timeline-menu" class="drop-menu">
|
<div class="drop-menu">
|
||||||
<div class="timeline-id">( work )</div>
|
<div class="timeline-id">( none )</div>
|
||||||
<input class="timeline-id-input" type="text"/>
|
<input class="timeline-id-input" type="text"/>
|
||||||
<ul class="drop-menu-items">
|
<ul class="drop-menu-items">
|
||||||
<li>jdb-labs</li>
|
|
||||||
<li>timestamper</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="user">
|
<div id="user">
|
||||||
<div class="fullname">Jonathan Bernard</div>
|
<div class="fullname">Not Logged In</div>
|
||||||
<input class='fullname-input' type='text'/>
|
<input class='fullname-input' type='text'/>
|
||||||
<div class="username"> - jdbernard</div>
|
<div class='drop-menu'>
|
||||||
<ul class="user-controls">
|
<div class="username"> - not_logged_in</div>
|
||||||
<li><a href="#">logout</a></li>
|
<ul class="drop-menu-items">
|
||||||
<li><a href="#">user info</a></li>
|
<li><a href="#">logout</a></li>
|
||||||
</ul>
|
<li><a href="#">user info</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -74,6 +84,20 @@
|
|||||||
<div class="footer">
|
<div class="footer">
|
||||||
Copyright 2011 <a href="http://www.jdb-labs.com"><span class="logo">JDB Labs</span> LLC.</a>
|
Copyright 2011 <a href="http://www.jdb-labs.com"><span class="logo">JDB Labs</span> LLC.</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="login-dialog" title="Login">
|
||||||
|
<form>
|
||||||
|
<fieldset>
|
||||||
|
<label for="login-name">Username:</label>
|
||||||
|
<input type="text" name="login-name" id="login-name"
|
||||||
|
class="text ui-widget-content ui-corner-all"></input>
|
||||||
|
<label for="login-password">Password:</label>
|
||||||
|
<input type="password" name="login-password" id="login-password"
|
||||||
|
class="text ui-widget-content ui-corner-all"></input>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
<p class="validate-tips"></p>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
102
www/js/ts.js
102
www/js/ts.js
@ -35,7 +35,11 @@ $(document).ready(function(){
|
|||||||
* - join_date
|
* - join_date
|
||||||
*/
|
*/
|
||||||
TS.UserModel = Backbone.Model.extend({
|
TS.UserModel = Backbone.Model.extend({
|
||||||
|
url: function() { return '/ts_api/users/' + this.get('id'); },
|
||||||
|
|
||||||
|
initialize: function(attrs, options) {
|
||||||
|
_.bind(this, 'url');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
TS.EntryList = Backbone.Collection.extend({
|
TS.EntryList = Backbone.Collection.extend({
|
||||||
@ -84,7 +88,7 @@ $(document).ready(function(){
|
|||||||
events: {
|
events: {
|
||||||
"dblclick div.mark" : "editMark",
|
"dblclick div.mark" : "editMark",
|
||||||
"dblclick div.timestamp" : "editTimestamp",
|
"dblclick div.timestamp" : "editTimestamp",
|
||||||
"keypress .mark-input" : "updateOnEnter"
|
"keypress .mark-input" : "updateOnEnter",
|
||||||
"keypress .timestamp-input" : "updateOnEnter"
|
"keypress .timestamp-input" : "updateOnEnter"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -181,7 +185,7 @@ $(document).ready(function(){
|
|||||||
$(this.el).addClass('edit-desc');
|
$(this.el).addClass('edit-desc');
|
||||||
this.$('.timeline-desc-input').focus();
|
this.$('.timeline-desc-input').focus();
|
||||||
return this;
|
return this;
|
||||||
};
|
},
|
||||||
|
|
||||||
close: function() {
|
close: function() {
|
||||||
this.model.save({
|
this.model.save({
|
||||||
@ -195,40 +199,9 @@ $(document).ready(function(){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
TS.TimelineListView = Backbone.View.extend({
|
|
||||||
|
|
||||||
el: $("#timeline .drop-menu-items"),
|
|
||||||
|
|
||||||
events: {
|
|
||||||
'click #timeline .drop-menu-items a': 'selectTimeline'
|
|
||||||
},
|
|
||||||
|
|
||||||
initialize: function() {
|
|
||||||
_.bindAll(this, 'addOne', 'render');
|
|
||||||
this.collection.bind('add', this.addOne);
|
|
||||||
this.collection.bind('refresh', this.refresh);
|
|
||||||
this.collection.view = this;
|
|
||||||
},
|
|
||||||
|
|
||||||
addOne: function(timeline) {
|
|
||||||
$(this.el).append(ich.timelineLink(timeline.toJSON()));
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
$(this.el).empty();
|
|
||||||
this.collection.each(this.addOne);
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
selectTimeline: function() {
|
|
||||||
// note that this refers to the element that initiated this event
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
TS.UserView = Backbone.View.extend({
|
TS.UserView = Backbone.View.extend({
|
||||||
|
|
||||||
el: $("user"),
|
el: $("#user"),
|
||||||
|
|
||||||
model: TS.UserModel,
|
model: TS.UserModel,
|
||||||
|
|
||||||
@ -245,7 +218,7 @@ $(document).ready(function(){
|
|||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
this.$('.fullname').text(this.model.get('name'));
|
this.$('.fullname').text(this.model.get('name'));
|
||||||
this.$('.username').text(this.model.get('id'));
|
this.$('.username').text(" - " + this.model.get('id'));
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -266,6 +239,37 @@ $(document).ready(function(){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
TS.AppView = Backbone.View.extend({
|
||||||
|
|
||||||
|
el: $("body"),
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'click #timeline .drop-menu-items a': 'selectTimeline',
|
||||||
|
'keypress #new-entry-input' : 'newTimestamp',
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function() {
|
||||||
|
_.bindAll(this, 'render');
|
||||||
|
},
|
||||||
|
|
||||||
|
renderTimelineList: function() {
|
||||||
|
var tlUL = this.$('#timeline ul.drop-menu-items');
|
||||||
|
//var curTimeline =
|
||||||
|
//var remTimelines = TS.user.timelines.filter(function(timeline)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// wire the login dialog using jQuery UI
|
||||||
|
$("#login-dialog").dialog({
|
||||||
|
autoOpen: false,
|
||||||
|
height: 400,
|
||||||
|
width: 400,
|
||||||
|
modal: true,
|
||||||
|
buttons: { Login: function(){login()} }
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#login-dialog').dialog('open');
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
function login() {
|
function login() {
|
||||||
@ -296,35 +300,15 @@ function login() {
|
|||||||
|
|
||||||
// create the user model
|
// create the user model
|
||||||
TS.user = new TS.UserModel({
|
TS.user = new TS.UserModel({
|
||||||
id: name.val();,
|
id: name.val(),
|
||||||
name: '' });
|
name: '' });
|
||||||
|
|
||||||
// create the user view
|
|
||||||
new TS.UserView({model: TS.user});
|
|
||||||
|
|
||||||
// fetch the initial user data from the server
|
// fetch the initial user data from the server
|
||||||
TS.user.fetch();
|
TS.user.fetch();
|
||||||
|
|
||||||
// create the user's timelines
|
// create the user view
|
||||||
TS.timelineList = new TS.TimelineList([], {user: TS.user});
|
new TS.UserView({model: TS.user});
|
||||||
|
TS.user.view.render();
|
||||||
|
|
||||||
// create the timeline list view
|
|
||||||
new TS.TimelineListView({collection: TS.timelineList});
|
|
||||||
TS.timelineList.fetch();
|
|
||||||
|
|
||||||
// load the current timeline
|
|
||||||
TS.currentTimeline = TS.timelineList.at(0);
|
|
||||||
|
|
||||||
// create the timeline view
|
|
||||||
new TS.TimelineView({model: TS.currentTimeline});
|
|
||||||
|
|
||||||
// render the timeline view
|
|
||||||
TS.currentTimeline.view.render();
|
|
||||||
|
|
||||||
// load the entries for this timeline
|
|
||||||
TS.entryList = new TS.EntryList([], {timeline: TS.currentTimeline});
|
|
||||||
|
|
||||||
// create the new entry list view
|
|
||||||
new TS.EntryListView
|
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user