Ox.EditableContent = function(options, self) { self = self || {}; var that = Ox.Element({ element: options.type == 'div' ? '
' : '', tooltip: options.tooltip }, self) .defaults({ clickLink: null, editable: true, editing: false, format: null, highlight: null, placeholder: '', replaceTags: {}, submitOnBlur: true, tags: null, tooltip: '', type: 'span', value: '' }) .options(options || {}) .update({ highlight: function() { !self.options.editing && self.$value.html(formatValue()); }, value: function() { !self.options.editing && self.$value.html(formatValue()); } }) .addClass('OxEditableContent') .on({ click: function(e) { var $target = $(e.target); if (!e.shiftKey && ($target.is('a') || ($target = $target.parents('a')).length)) { e.preventDefault(); if (self.options.clickLink) { e.target = $target[0]; self.options.clickLink(e); } else { document.location.href = $target.attr('href'); } } return false; } }) .bindEvent({ doubleclick: edit }); self.options.value = self.options.value.toString(); self.$value = Ox.Element(self.options.type == 'span' ? '' : '
') .html(formatValue()) .on({ blur: self.options.submitOnBlur ? submit : blur, keydown: function(e) { if (self.options.editing) { if (e.keyCode == 13 && self.options.type == 'span') { submit(); return false; } else if (e.keyCode == 27) { cancel(); return false; } } } }) .appendTo(that); function blur() { Ox.print('BLUR!') } function cancel() { if (self.options.editing) { Ox.print('CANCEL!') that.loseFocus(); self.options.editing = false; self.$value .attr({contenteditable: false}) .removeClass('OxEditableContentInput') .html(formatValue()); that.triggerEvent('cancel', {value: self.options.value}); } } function edit() { if (self.options.editable && !self.options.editing) { Ox.print('EDIT!') var value = formatInputValue(); self.$value .addClass('OxEditableContentInput') .attr({contenteditable: true}); if (value) { self.$value.text(value); } else { self.$value.html(' '); } self.options.editing = true; that.gainFocus(); setTimeout(updateSelection, 50); } } function formatInputValue() { return Ox.decodeHTMLEntities( self.options.type == 'span' ? self.options.value : self.options.value.replace(//g, '\n\n') ); } function formatValue() { var value = self.options.value; that.removeClass('OxPlaceholder'); if (self.options.value === '' && self.options.placeholder) { value = self.options.placeholder; that.addClass('OxPlaceholder'); } else if (self.options.format) { value = self.options.format(self.options.value); } if (self.options.highlight) { value = Ox.highlight( value, self.options.highlight, 'OxHighlight', true ); } return value; } function parseValue() { var value = Ox.clean( self.$value.text().replace(/\n\n+/g, '\0') ).replace(/\0/g, '\n\n').trim(); return ( self.options.type == 'span' ? Ox.encodeHTMLEntities(value) : Ox.sanitizeHTML(value, self.options.tags, self.options.replaceTags) ); } function setCSS() { } function submit() { if (self.options.editing) { Ox.print('SUBMIT!') that.loseFocus(); self.options.editing = false; self.options.value = self.$value.text(); if (self.options.value.charCodeAt(0) == 160) { // remove nbsp self.options.value = self.options.value.substr(1); } self.$value .attr({contenteditable: false}) .removeClass('OxEditableContentInput') .html(formatValue()); that.triggerEvent('submit', {value: self.options.value}); } } function updateSelection() { var range, selection; self.$value[0].focus(); selection = window.getSelection(); selection.removeAllRanges(); range = document.createRange(); range.selectNodeContents(self.$value[0]); selection.addRange(range); if (self.options.type == 'div') { setTimeout(function() { selection.collapseToEnd(); }, 0); } } that.css = function(css) { that.$element.css(css); self.$value.css(css); return that; } return that; };