356 lines
9.6 KiB
JavaScript
Raw Normal View History

// TimeStamper namespace
var TS = {};
/* Setup after the document is ready for manipulation. */
$(document).ready(function(){
// ======== DEFINE MODELS ========//
/* Entry model.
* Attributes
* - id
* - mark
* - notes
* - start
*/
TS.EntryModel = Backbone.Model.extend({
});
/* Timeline model.
* Attributes:
* - id
* - desc
* - created
*/
TS.TimelineModel = Backbone.Model.extend({
});
/* User model.
* Attributes:
* - username
* - fullname
* - email
* - join_date
*/
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({
model: TS.EntryModel,
comparator: function(entry) { return entry.get('timestamp'); },
initialize: function(model, options) {
if (options.timeline == undefined) {
throw "Cannot create an EntryList without a TimelineModel reference."
} else { this.timeline = options.timeline; }
_.bindAll(this, "url");
},
url: function() {
return "/entries/" + this.timeline.get('user_id') + "/" + this.timeline.get('id');
}
});
TS.TimelineList = Backbone.Collection.extend({
model: TS.TimelineModel,
initialize: function(models, options) {
if (options.user == undefined) {
throw "Cannot create a TimelineList without a UserModel reference.";
} else { this.user = options.user; }
_.bindAll(this, 'url');
},
comparator: function(timeline) {
return timeline.get('id');
},
url: function() {
return "/ts_api/timelines/" + this.user.get('id');
}
});
// ======== DEFINE VIEWS ========//
/* Entry view
*/
TS.EntryView = Backbone.View.extend({
model: TS.EntryModel,
events: {
"dblclick div.mark" : "editMark",
"dblclick div.timestamp" : "editTimestamp",
"keypress .mark-input" : "updateOnEnter",
"keypress .timestamp-input" : "updateOnEnter"
},
initialize: function() {
_.bindAll(this, 'render', 'close', 'editTImestamp',
'editMark', 'updateOnEnter');
this.model.bind('change', this.render);
this.model.view = this;
},
render: function() {
$(this.el).html(ich.entry(this.model.toJSON()));
return this;
},
editMark: function() {
$(this.el).addClass('edit-mark');
this.$('.mark-input').focus();
return this;
},
editTimestamp: function() {
$(this.el).addClass('edit-timestamp');
this.$('timestamp-input').focus();
return this;
},
close: function() {
this.model.save({
mark: this.$('.mark-input').val(),
timestamp: this.$('.timestamp-input').val()});
$(this.el).removeClass('edit-mark edit-timestamp');
},
updateOnEnter: function(e) {
if(e.keyCode == 13) this.close();
}
});
TS.EntryListView = Backbone.View.extend({
el: $("#entry-list"),
events: {
"#new-entry" : "createNewEntry"
},
initialize: function() {
_.bindAll(this, 'addOne', 'createNewEntry', 'render');
this.collection.bind('add', this.addOne);
this.collection.bind('refresh', this.render);
this.collection.view = this;
this.entryContainer = this.$("#entries")
},
addOne: function(entry) {
if (!entry.view) { new TS.EntryView({model: entry}); }
this.entryContainer.prepend(entry.view.render().el);
},
createNewEntry: function() {
var entryMark = this.$("#new-entry-input").val();
var newEntry = TS.EntryModel({mark: entryMark});
this.collection.create({mark: entryMark}).fetch();
},
render: function() {
this.entryContainer.empty();
this.collection.each(this.addOne);
}
});
TS.TimelineView = Backbone.View.extend({
el: $("#timeline"),
model: TS.TimelineModel,
events: {
"dblclick .timeline-id" : "editId",
"dblclick .timeline-desc" : "editDesc",
"keypress .timeline-id-input" : "updateOnEnter",
"keypress .timeline-desc-input" : "updateOnEnter"
},
initialize: function() {
_.bindAll(this, 'render', 'close', 'editId', 'editDesc',
'updateOnEnter');
this.model.bind('change', this.render);
this.model.view = this;
},
render: function() {
this.$('.timeline-id').html('( ' +
this.model.get('id') + ' )');
this.$('.timeline-desc').text(this.model.get('desc'));
return this;
},
editId: function() {
$(this.el).addClass('edit-id');
this.$('.timeline-id-input').focus();
return this;
},
editDesc: function() {
$(this.el).addClass('edit-desc');
this.$('.timeline-desc-input').focus();
return this;
},
close: function() {
this.model.save({
id: this.$('timeline-id-input').val(),
desc: this.$('.timeline-desc-input').val()});
$(this.el).removeClass('.edit-id .edit-desc');
},
updateOnEnter: function(e) {
if (e.keyCode == 13) this.close();
}
});
2011-02-13 11:38:50 -06:00
TS.TimelineListView = Backbone.View.extend({
el: $("#timeline .drop-menu-items"),
collection: TS.TimelineList,
initialize: function() {
_.bindAll(this, 'render', 'renderOne');
this.collection.bind('add', this.renderOne);
this.collection.bind('refresh', this.render);
this.collection.view = this;
},
renderOne: function(timeline) {
if (!timeline.view) { new TS.TimelineView(timeline); }
$(this.el).append(ich.timelineLink(timeline.toJSON()));
},
render: function() {
$(this.el).remove(".timeline-link");
this.collection.each(this.renderOne);
return this;
}
});
TS.UserView = Backbone.View.extend({
el: $("#user"),
model: TS.UserModel,
events: {
'dblclick .fullname': 'editFullname',
'keypress .fullname-input': 'updateOnEnter'
},
initialize: function() {
_.bindAll(this, 'render', 'close', 'editFullname', 'updateOnEnter');
this.model.bind('change', this.render);
this.model.view = this;
},
render: function() {
this.$('.fullname').text(this.model.get('name'));
this.$('.username').text(" - " + this.model.get('id'));
return this;
},
editFullname: function() {
$(this.el).addClass('.edit-fullname');
this.$('.fullname-input').focus();
return this;
},
close: function() {
this.model.set({name: this.$('.fullname-input').val()});
this.model.save();
$(this.el).removeClass('.edit-fullname');
},
updateOnEnter: function(e) {
if (keyCode == 13) this.close();
}
});
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() {
// lookup the login dialog elements
var name = $("#login-name");
var pwd = $("#login-password");
// call the API via AJAX
$.ajax({
url: "/ts_api/login",
processData: false,
data: JSON.stringify({username: name.val(), password: pwd.val()}),
type: "POST",
error: function(jqXHR, textStatus, error) {
// assuming bad credentials (possible server error or bad request,
// we should check that, FIXME
var tips = $(".validate-tips");
tips.text("Incorrect username/password combination.");
tips.addClass("ui-state-error");
tips.slideDown();
},
success: function(data, textStatus, jqXHR) {
// initialize the app data
// TODO: possiblty replace by script generated server-side
// create the user model
TS.user = new TS.UserModel({
id: name.val(),
name: '' });
// fetch the initial user data from the server
TS.user.fetch();
// create the user view
new TS.UserView({model: TS.user});
TS.user.view.render();
}});
}