Skip to content

Instantly share code, notes, and snippets.

@randito
Created December 14, 2011 02:03
Show Gist options
  • Save randito/1474893 to your computer and use it in GitHub Desktop.
Save randito/1474893 to your computer and use it in GitHub Desktop.
Backbone source from http://chopapp.com/ => Extracted from http://chopapp.com/assets/all.js?1320423538
var CodeSnip = Backbone.Model.extend({
urlRoot: 'code_snips',
defaults: {
},
initialize: function () {
}
});
var Comment = Backbone.Model.extend({
defaults: {
text: ''
}
});
var Note = Backbone.Model.extend({
defaults: {
text: ''
},
toJSON: function () {
var attributes = Backbone.Model.prototype.toJSON.call(this);
attributes.isNew = this.isNew();
return attributes;
}
});
var CommentsCollection = Backbone.Collection.extend({
model: Comment,
url: '/comments'
});
var NotesCollection = Backbone.Collection.extend({
model: Note,
url: '/notes'
});
var NoteView = Backbone.View.extend({
tagName: 'li',
className: 'note read-only',
template: JST['note'],
events: {
'click .add-comment': 'clickAddComment'
},
initialize: function (options) {
_.bindAll(this, 'render', 'addComment', 'commentSaved');
this.model.bind('change:text', this.render);
this.comments = new CommentsCollection(this.model.get('comments'));
this.comments.bind('add', this.addComment);
},
render: function () {
$(this.el).html(this.template(this.model.toJSON()));
this.comments.each(this.addComment);
return this;
},
clickAddComment: function (event) {
var comment = new Comment({
note_id: this.model.get('id'),
user_name: $.cookie('name'),
owner_cookie_id: $.cookie('id')
});
event.preventDefault();
this.comments.add(comment);
this.$('.add-comment').hide();
},
addComment: function (comment) {
var commentView = new CommentView({model: comment, note: this.model});
this.$('.add-comment').before(commentView.render().el);
commentView.$('.text-edit').select();
commentView.bind('saved', this.commentSaved);
},
commentSaved: function () {
this.$('.add-comment').show();
}
});
var EditableNoteView = NoteView.extend({
className: 'note',
events: {
'click .save.note': 'save',
'keypress': 'keypress',
'click .note.text': 'startEditing',
'click .delete': 'destroy',
'click': 'dontpropagate'
},
initialize: function (options) {
NoteView.prototype.initialize.call(this, options);
_.bindAll(this, 'stopEditing', 'remove', 'clickDocument', 'dontpropagate', 'destroy');
},
render: function () {
NoteView.prototype.render.call(this);
if (this.model.isNew()) {
this.startEditing();
} else {
$(this.el).removeClass('editing');
}
return this;
},
save: function () {
$(this.el).addClass('loading');
this.model.save(
{text: this.$('.note.text-edit').val()},
{success: this.stopEditing}
);
},
destroy: function (event) {
event.preventDefault();
if (this.model.isNew()) {
this.model.collection.remove(this.model);
} else {
this.model.destroy();
}
$(document).unbind('click.cancel-note', this.clickDocument);
},
startEditing: function () {
$(document).bind('click.cancel-note', this.clickDocument);
$(this.el).addClass('editing');
this.$('.note.text-edit').select();
},
clickDocument: function (event) {
if (this.model.isNew()) {
this.destroy(event);
} else {
this.stopEditing();
}
},
dontpropagate: function (event) {
event.stopPropagation();
},
stopEditing: function () {
$(this.el).removeClass('editing loading');
this.render();
$(document).unbind('click.cancel-note', this.clickDocument);
},
keypress: function (event) {
if (event.which === 13) {
event.preventDefault();
this.save();
}
}
});
var CodeSnipView = Backbone.View.extend({
template: JST['code_snip'],
noteViewClass: NoteView,
initialize: function (options) {
_.bindAll(this, 'render', 'addNote', 'fetchModel', 'fetchModelSuccess', 'changeNotes', 'saveName');
this.notes = new NotesCollection(this.model.get('notes'));
// _.delay(this.fetchModel, 2000);
this.model.bind('change:notes', this.changeNotes);
this.setCookieId();
},
render: function () {
var self = this;
$(this.el).html(this.template(this.model.toJSON()));
this.notes.each(function (note, collection, wtfobj) {
self.addNote(note, collection, wtfobj, true);
});
this.$('#nameModal form').bind('submit', this.saveName);
if ($.cookie('name') === null) {
this.$('#nameModal').reveal({animation: 'none'});
}
return this;
},
saveName: function (event) {
event.preventDefault();
$.cookie('name', this.$('#nameModal input').val(), {expires: 365});
this.$('#nameModal').trigger('reveal:close');
},
addNote: function (note, collection, wtfobj, skipAnimation) {
var noteView = new this.noteViewClass({model: note}),
$lines = this.$('.line'),
$firstLine = $lines.eq(note.get('line_start')),
$lastLine = $lines.eq(note.get('line_end')),
$chopper = $('<div class="chop-it"></div>');
if (typeof skipAnimation === 'undefined') {
skipAnimation = false;
}
$lines.slice(note.get('line_start') + 1, note.get('line_end')).addClass('annotated');
$firstLine.addClass('first annotated');
$lastLine.addClass('last annotated');
$chopper.css({
left: -this.$('#choppinBroccoli').offset().left + 20 + 'px',
top: $firstLine.position().top + 'px',
height: $lastLine.position().top - $firstLine.position().top + $lastLine.height() + 'px'
});
this.$('#choppinBroccoli').prepend($chopper);
if (skipAnimation) {
$lastLine.after(noteView.render().el);
$chopper.animate({left: '-13px'}, 0);
} else if (note.isNew()) {
$chopper.animate({left: '-13px'}, 350, 'easeInQuint', function () {
$lastLine.after(noteView.render().el);
noteView.$('.text-edit').select();
});
} else {
$lastLine.after(noteView.render().el);
$chopper.animate({left: '-13px'}, 350, 'easeInQuint');
}
},
fetchModel: function () {
this.model.fetch({success: this.fetchModelSuccess});
},
fetchModelSuccess: function () {
_.delay(this.fetchModel, 10000);
},
changeNotes: function (model, notes) {
this.notes.refresh(notes);
this.render();
},
setCookieId: function () {
if ($.cookie('id') === null) {
$.cookie('id', (new Date).valueOf(), {expires: 365});
}
}
});
var EditableCodeSnipView = CodeSnipView.extend({
noteViewClass: EditableNoteView,
className: 'editable',
events: {
'mousedown .line:not(.annotated)': 'mousedown',
'mouseenter .line': 'mouseenter',
'mouseleave': 'mouseleave',
'mouseup .line': 'mouseup'
},
initialize: function(options) {
CodeSnipView.prototype.initialize.call(this, options);
this.notes.bind('add', this.addNote);
this.notes.bind('remove', this.render);
},
mousedown: function (event) {
if (this.isLeftClick(event)) {
event.preventDefault();
$(event.currentTarget).addClass('start-drag selected');
this.dragging = true;
}
},
mouseup: function (event) {
if (this.isLeftClick(event) && this.dragging) {
var $lines = this.$('.line'),
note = new Note({
code_snip_id: this.model.get('token'),
line_start: $lines.index($lines.filter('.selected:first')),
line_end: $lines.index($lines.filter('.selected:last')),
owner_cookie_id: $.cookie('id')
});
this.stopSelecting();
this.notes.add(note);
}
},
mouseleave: function (event) {
this.stopSelecting();
},
mouseenter: function (event) {
var $lines = this.$('.line'),
startIndex,
endIndex,
oldStartIndex;
if (this.dragging) {
$lines.removeClass('end-drag');
$(event.currentTarget).addClass('end-drag');
startIndex = $lines.index($lines.filter('.start-drag'));
endIndex = $lines.index($lines.filter('.end-drag'));
if (endIndex < startIndex) {
oldStartIndex = startIndex;
startIndex = endIndex;
endIndex = oldStartIndex;
}
$lines.removeClass('selected first last');
$lines.slice(startIndex, endIndex + 1).addClass('selected');
$lines.filter('.selected:first').addClass('first');
$lines.filter('.selected:last').addClass('last');
}
},
stopSelecting: function () {
this.dragging = false;
this.$('.line').removeClass('selected start-drag end-drag');
},
isLeftClick: function (event) {
return event.which === 1;
}
});
var NewCodeSnipView = Backbone.View.extend({
template: JST['new'],
initialize: function() {
_.bindAll(this, 'render', 'create', 'createSuccess');
},
events: {
'click #langToggle li': 'clickLanguage',
'click #langToggle li.more li': 'showHiddenLanguange',
'click #captureFromUrl': 'showCaptireFromUrl',
'click textarea, #langToggle': 'showPaste',
'click .close-url': 'showPaste'
},
render: function() {
$(this.el).html(this.template({}));
this.$('form').bind('submit', this.create);
this.$('input[placeholder],textarea[placeholder]').placeholder();
return this;
},
create: function (event) {
var $form = $(event.currentTarget),
self = this,
codeSnip;
event.preventDefault();
CHOP.controller.transitionOut(function () {
//// Need to post this manually because of bug with Rails correctly handling JSON encoding of double linebreaks
//// http://stackoverflow.com/questions/5074034/activesupportjson-decode-does-not-properly-handle-literal-line-breaks
// codeSnip = new CodeSnip({
// code: $form.find('[name=code]').val(),
// language: $form.find('[name=language]').val(),
// url: $form.find('[name=url]').val()
// });
// codeSnip.save({}, {success: self.createSuccess});
$.post(
$form.attr('action'),
$form.serialize(),
self.createSuccess
);
});
},
createSuccess: function (codeSnipAttributes) {
var codeSnip = new CodeSnip(codeSnipAttributes),
editableCodeSnipView = new EditableCodeSnipView({model: codeSnip});
CHOP.controller.transitionIn(function () {
return editableCodeSnipView.render().el;
});
Backbone.history.saveLocation(codeSnip.get('token'));
},
clickLanguage: function (event) {
var $this = $(event.currentTarget);
event.preventDefault();
$this.siblings().removeClass('active');
$this.addClass('active');
this.$('#langInput').val($this.data('value'));
},
showHiddenLanguange: function (event) {
var $selectedLi = $(event.currentTarget);
event.preventDefault();
event.stopPropagation();
$selectedLi.closest('.more').replaceWith($selectedLi);
$selectedLi.trigger('click');
},
showCaptireFromUrl: function (event) {
event.preventDefault();
$(event.currentTarget).closest('.page-bubble').addClass('with-url');
},
showPaste: function (event) {
event.preventDefault();
$(event.currentTarget).closest('.page-bubble').removeClass('with-url');
}
});
var CommentView = Backbone.View.extend({
className: 'comment',
template: JST['comment'],
events: {
'click .save': 'save',
'keypress': 'keypress'
},
initialize: function(options) {
_.bindAll(this, 'render', 'stopEditing');
this.note = options.note;
this.model.bind('change:text', this.render);
},
render: function () {
$(this.el).html(this.template(this.model.toJSON()));
if (this.model.isNew()) {
$(this.el).addClass('editing');
} else {
$(this.el).removeClass('editing');
}
if (this.model.get('owner_cookie_id') === this.note.get('owner_cookie_id')) {
$(this.el).addClass('owner-comment')
}
return this;
},
save: function () {
$(this.el).addClass('loading');
this.model.save(
{text: this.$('.text-edit').val()},
{success: this.stopEditing}
);
},
stopEditing: function () {
$(this.el).removeClass('editing loading');
this.trigger('saved');
},
keypress: function (event) {
if (event.which === 13) {
event.preventDefault();
this.save();
}
}
});
var CodeSnipController = Backbone.Controller.extend({
routes: {
"": "new",
"about": "about",
":id": "show"
},
'new': function() {
var newCodeSnipView = new NewCodeSnipView();
this.transition(function () {
return newCodeSnipView.render().el;
});
},
show: function(id) {
var codeSnip = new CodeSnip({id: id})
self = this;
this.transitionOut(function () {
codeSnip.fetch({success: function (model, response) {
var codeSnipView = new CodeSnipView({model: codeSnip});
self.transitionIn(function () {
return codeSnipView.el;
}, function () {
codeSnipView.render();
});
}});
});
},
about: function () {
this.transition(function () {
return JST['about']({});
});
},
transitionOut: function (callback) {
callback = callback || $.noop;
$('#applicationContainer').fadeOutAndSlide({complete: callback});
},
transitionIn: function (contentCallback, callback) {
callback = callback || $.noop;
$('#applicationContainer')
.html(contentCallback())
.fadeInAndSlide();
callback();
},
transition: function (contentCallback) {
this.transitionOut(_.bind(this.transitionIn, this, contentCallback));
}
});
var CHOP = {};
$(document).ready(function () {
CHOP.controller = new CodeSnipController;
Backbone.history.start();
});
@randito
Copy link
Author

randito commented Dec 14, 2011

Extracted from the wonderful Zurb chopapp.com single page app: http://chopapp.com/assets/all.js?1320423538

Posted to review some backbone.js code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment