Skip to content

Instantly share code, notes, and snippets.

@Abdillah
Created November 14, 2017 11:44
Show Gist options
  • Save Abdillah/b87e5a9f5c45a410513487c49a5be4a8 to your computer and use it in GitHub Desktop.
Save Abdillah/b87e5a9f5c45a410513487c49a5be4a8 to your computer and use it in GitHub Desktop.
HTML editable text without `<input>`
(function($) {
$.fn.editable = function(options = {}) {
var elements = $(this);
if (options == false) {
var option = {};
option.action = 'inactivate';
}
// TODO: Skip this when not in initialization to enhance speed
// console.debug('[EditableText::] parsing options..');
option = $.extend({
properties: {
'input': {
'container-class': 'column large-12',
'class': '',
'text': '',
'placeholder': 'Type in some text here'
},
'hint': {
'class': 'hint',
'text': 'Press Enter when you\'re done.'
}
},
srcEditable: '<div class="{{input.container-class}}">'
+ ' <input type="text" class="{{input.class}}" placeholder="{{input.placeholder}}" value="{{input.text}}"/>'
+ ' <div class="{{hint.class}}">{{hint.text}}</div>'
+ '</div>',
init: function() {
this.onFocusOutReverseTransform = (function(ev) {
var element = $(ev.currentTarget);
// console.debug('[EditableText::on-focus-out-reverse-transform] start');
if (!element.hasClass('editable')) {
element = element.parents('.editable').first() || element.find('.editable').first();
if (!element) {
// console.error('[EditableText::reverse-transform()] Invalid element, ensure it has editable class');
return;
}
}
// console.debug('[EditableText::on-focus-out-reverse-transform] call reverse-transform');
this.action = 'reverse-transform';
element.editable(this);
}).bind(this);
// console.debug('[EditableText::option-init] onFocusOutReverseTransform:');
// console.debug(this.onFocusOutReverseTransform.toSource());
this.onClickTransform = (function(ev) {
var element = $(ev.currentTarget);
// console.debug('[EditableText::transform()] Clicked the ' + element.html().trim());
// Get current value
this.properties['input']['text'] = element.text().trim();
this.action = 'transform';
element.editable(this);
}).bind(this);
this.onSave = function(ev, element) {
// console.debug('[EditableText::on-save] Saving...');
};
return this;
}
}.init(), options);
// console.debug('[EditableText] Option');
// console.debug(option.srcEditable);
switch (option.action) {
case 'transform': {
elements.each(function() {
// Compile source
option.create = Handlebars.compile(option.srcEditable);
var element = $(this).filter('.editable');
element.data('editabletext-text', element.text()); // save text
var view = option.create(option.properties);
view = $(view);
element.empty();
element.append(view);
element.addClass('editable-transformed');
// Focus and assign focusout event
view.find('input').focus()
.keypress((function(ev) {
// console.debug('[EditableText::keypress-event-handler] Key pressed ' + ev.which);
// When enter pressed
if (ev.which == 13) {
// console.debug('[EditableText::save-trigger] option.onSave');
// console.debug(option.onSave.toSource());
element.trigger('save', element);
}
}).bind(option)).on('focusout', option.onFocusOutReverseTransform);
// console.debug("view input:");
// console.debug(view.find('input'));
// console.debug("option:");
// console.debug(option);
element.off('click');
});
break;
}
case 'reverse-transform': {
elements.each(function() {
var element = $(this).filter('.editable');
if (element.hasClass('editable-transformed')) {
// console.debug('[EditableText::reverse-transform] Has class!');
var oldText = element.data('editabletext-text');
if (oldText) {
element.text(oldText); // reload old text
}
element.first().children().detach();
element.removeClass('editable-transformed');
element.click(option.onClickTransform);
}
});
break;
}
case 'inactivate': {
// Uninstall
elements.each(function() {
var element = $(this).filter('.editable');
option.action = 'reverse-transform';
element.editable(option);
element.off('save');
element.off('click');
});
break;
}
case 'activate':
default: {
elements.each(function() {
var element = $(this).filter('.editable');
if (typeof(element) == 'undefined') {
// console.debug('[EditableText::activate] Element undefined.');
return;
}
// Event onSave handling
element.on('save', function(ev, parent) {
var success = option.onSave(ev, parent);
if (success) {
// console.debug('[EditableText::on-save] Success saving!');
element.text($(parent).find('input').val());
element.removeData('editabletext-text')
option.onFocusOutReverseTransform(ev);
}
});
// console.debug('[EditableText::activate] Setup onClick transformer on ');
// console.debug(element);
element.click(option.onClickTransform);
});
}
}
this.option = option;
return this;
};
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment