haste-server/static/application.js
Michael Macias 1950cc8db0 Refactor frontend
* restructured JavaScript using backbone.js
* replaced highlight.js with CodeMirror for its editor
* added CodeMirror Solarized (dark) theme based on Ethan Schoonover's solarized.vim
* changed `POST /document` to accept real JSON
* cleaned up template and stylesheet
2012-02-18 02:40:56 -06:00

172 lines
3.7 KiB
JavaScript

window.Haste = {
Models: {},
Views: {},
Routers: {},
extensionMap: {
clj: 'clojure', coffee: 'coffeescript', css: 'css', diff: 'diff', go: 'go',
hs: 'haskell', html: 'htmlmixed', js: 'javascript', lua: 'lua',
md: 'markdown', markdown: 'markdown', sql: 'mysql', pl: 'perl', php: 'php',
py: 'python', r: 'r', rb: 'ruby', scm: 'scheme', xml: 'xml', yml: 'yaml'
},
init: function() {
new Haste.Routers.Document();
Backbone.history.start({ pushState: true });
}
};
Haste.Models.Document = Backbone.Model.extend({
idAttribute: 'key',
urlRoot: '/documents'
});
Haste.Routers.Document = Backbone.Router.extend({
routes: {
':id.:extension': 'show',
':id': 'show',
'': 'new'
},
initialize: function() {
this.editor = new Haste.Views.EditorView();
},
show: function(id, extension) {
this.editor.load(id, extension);
},
new: function() {
this.editor.new();
}
});
Haste.Views.ActionsView = Backbone.View.extend({
el: 'header',
events: {
'click .new': 'new',
'click .save': 'save',
'click .edit': 'edit',
'click .raw': 'raw',
'click .twitter': 'raw'
},
initialize: function() {
this.parent = this.options.parent;
},
toggleActions: function() {
var klass = 'disabled';
if (this.parent.model.isNew()) {
$('.save', this.el).removeClass(klass);
$('.edit, .raw, .twitter', this.el).addClass(klass);
} else {
$('.save', this.el).addClass(klass);
$('.edit, .raw, .twitter', this.el).removeClass(klass);
}
this.setLink('.raw', 'raw/' + this.parent.model.id);
this.setLink('.twitter', 'https://twitter.com/share?url=' + encodeURI(window.location.href));
},
setLink: function(el, href) {
if (this.parent.model.isNew()) {
href = '#';
}
$(el, this.el).attr('href', href);
},
new: function(event) {
event.preventDefault();
this.parent.new();
Backbone.history.navigate('');
},
save: function(event) {
event.preventDefault();
if (!this.parent.model.isNew()) { return; }
this.parent.save();
},
edit: function(event) {
event.preventDefault();
if (this.parent.model.isNew()) { return; }
this.parent.model.set('key', null);
Backbone.history.navigate('/');
},
raw: function(event) {
if (this.model.isNew()) {
event.preventDefault();
}
},
});
Haste.Views.EditorView = Backbone.View.extend({
el: 'textarea',
initialize: function() {
this.codeMirror = CodeMirror.fromTextArea(this.el, {
mode: 'null',
lineNumbers: true,
theme: 'solarized-dark'
});
this.actionsView = new Haste.Views.ActionsView({ parent: this });
},
render: function() {
this.codeMirror.setOption('mode', this.model.get('mode') || 'null');
this.codeMirror.setValue(this.model.get('data') || '');
return this;
},
new: function() {
this.model = new Haste.Models.Document();
this.model.on('change', this.render, this);
this.model.on('change', this.toggleLock, this);
this.model.on('change', this.actionsView.toggleActions, this.actionsView);
this.model.trigger('change');
},
load: function(key, extension) {
this.new();
var mode = Haste.extensionMap[extension];
this.model.set({ key: key, mode: mode }, { silent: true });
this.model.fetch();
},
save: function() {
var data = this.codeMirror.getValue();
if (!data) { return; }
this.model.save('data', data, {
success: function(model, response) {
Backbone.history.navigate(model.id);
}
});
},
toggleLock: function() {
this.codeMirror.setOption('readOnly', !this.model.isNew());
this.actionsView.toggleActions();
}
});
$(function() {
Haste.init();
});