Created
February 9, 2012 04:29
-
-
Save jbenet/1777302 to your computer and use it in GitHub Desktop.
Backbone EditableText Component
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define([ | |
'jquery', | |
'underscore', | |
'backbone', | |
'handlebars', | |
'ich', | |
'util/resource', | |
'order!libs/bootstrap/bootstrap-twipsy', | |
'order!libs/bootstrap/bootstrap-popover', | |
], function($, _, Backbone, Handlebars, ich, Res) { | |
var random_id = function() { | |
return 'editabletext' + Math.round(Math.random() * 100000000); | |
} | |
var EditableTextComponent = {}; | |
// Setup template. | |
EditableTextComponent.html = " \ | |
<div class='editabletext' id='{{id}}'> \ | |
<div id='{{id}}_text'> \ | |
{{{html}}} \ | |
{{#if addToggle}}<small id='toggle'>edit</small>{{/if}} \ | |
</div> \ | |
{{#if multiline}} \ | |
<textarea id='{{id}}_edit' style='display: none;'>{{text}}</textarea> \ | |
{{else}} \ | |
<input type='text' id='{{id}}_edit' \ | |
style='display: none;' value='{{text}}' /> \ | |
{{/if}} \ | |
</div> \ | |
"; | |
ich.addTemplate('editabletext', EditableTextComponent.html); | |
EditableTextComponent.template = ich.editabletext; | |
// Setup view. | |
EditableTextComponent.View = Backbone.View.extend({ | |
template: EditableTextComponent.template, | |
// Delegated events for creating new items, and clearing completed ones. | |
events: { | |
"keypress textarea": "saveOnEnter", | |
"keypress input": "saveOnEnter", | |
"click #toggle": "toggle" | |
}, | |
initialize: function() { | |
_.bindAll(this, 'saveOnEnter', 'toggle'); | |
if (!this.options.textFn) { | |
throw new Error("EditableTextComponent requires option textFn."); | |
} | |
this.options.html = this.options.html || function(_) { return _; } | |
this.options.multiline = !!this.options.multiline; | |
this.options.addToggle = !!this.options.addToggle; | |
}, | |
render: function() { | |
var text_ = this.options.textFn(); | |
$(this.el).html(this.template({ | |
id: this.options.id || random_id(), | |
text: text_, | |
html: this.html(text_), | |
multiline: this.options.multiline, | |
addToggle: this.options.addToggle | |
})); | |
if (this.options.help) { | |
this.find(".editabletext > #edit").popover(this.options.help); | |
} | |
Res.rendered(this.find(".editabletext > #text")); | |
}, | |
find: function(sel) { | |
// add the randomly generated id in between. | |
var id = $(this.el).find('.editabletext').attr('id'); | |
return $(this.el).find(sel.replace(/#/g, '#' + id + '_')); | |
}, | |
// add any transforms from text to display html. | |
html: function(text) { | |
return this.options.html(text); | |
}, | |
is_editing: false, | |
edit: function() { | |
var field = this.find(".editabletext > #edit"); | |
var text = this.find(".editabletext > #text"); | |
field.css("width", text.css("width") || '10'); | |
field.css("height", text.css("height") || '10'); | |
field.css("font", text.css("font")); | |
field.css("margin-left", parseInt(text.css("margin-left")) - 5); | |
field.css("margin-top", parseInt(text.css("margin-top")) - 5); | |
text.hide(); | |
field.show(); | |
field.focus(); | |
field.value = field.value; // to move cursor to end. | |
this.is_editing = true; | |
if (this.options.onEdit) | |
this.options.onEdit(); | |
}, | |
saveText: function() { | |
return this.find(".editabletext > #edit").val() | |
}, | |
save: function() { | |
var text = this.saveText(); | |
// close popover | |
this.find(".editabletext > #edit").popover('hide'); | |
// Attempt to validate | |
if (this.options.validate) { | |
var result = this.options.validate(text); | |
if (result) { | |
// validation failed. show help, and return | |
this.find(".editabletext > #edit").popover(result); | |
this.find(".editabletext > #edit").popover('show'); | |
return; | |
} | |
} | |
// save and render | |
this.options.textFn(text); | |
this.render(); | |
this.is_editing = false; | |
if (this.options.onSave) | |
this.options.onSave(); | |
}, | |
toggle: function() { | |
this.is_editing ? this.save() : this.edit(); | |
}, | |
saveOnEnter: function(e) { | |
if (e.keyCode == 13 && this.is_editing) { | |
this.save(); | |
return false; | |
} | |
}, | |
alert: function(text) { | |
this.find('.editabletext > #edit').css("class", "error"); | |
this.find('.editabletext > #edit').popover({ | |
title: "Error: invalid text.", | |
body: text, | |
trigger: 'manual', | |
}); | |
} | |
}); | |
return EditableTextComponent; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment