/*@ Ox.Editable Editable element () -> Input Element (options) -> Input Element (options, self) -> Input Element options Options object editing If true, loads in editing state format Format function (value) -> Formatted value value Input value self Shared private variable @*/ Ox.Editable = function(options, self) { self = self || {}; var that = Ox.Element({ element: '
', tooltip: options.tooltip }, self) .defaults({ clickLink: null, editable: true, editing: false, format: null, height: 0, placeholder: '', tooltip: '', value: '', width: 0, type: 'input' }) .options(options || {}) .addClass('OxEditableElement') .bind({ click: function() { return false; } }) .bindEvent({ doubleclick: edit, singleclick: function(e) { if ($(e.target).is('a')) { if (self.options.clickLink) { self.options.clickLink(e); } else { document.location.href = $(e.target).attr('href'); } } } }); self.options.value = self.options.value.toString(); self.css = {}; self.$value = Ox.Element(self.options.type == 'input' ? '' : '
') .addClass('OxValue') //.css({background: 'red'}) .html(formatValue()) //[self.options.editing ? 'hide' : 'show']() .appendTo(that); if (self.options.editing) { self.options.editing = false; edit(); } function cancel() { self.options.value = self.originalValue; self.$input.options({value: formatInputValue()}).hide(); self.$test.html(formatTestValue()); self.$value.html(formatValue()).show(); that.triggerEvent('submit', { value: self.options.value }); } function change(event) { var height, width; self.options.value = event.value; self.$value.html(formatValue()); self.$test.html(formatTestValue()); //height = self.options.height || Ox.limit(self.$test.height() + 2, self.minHeight, self.maxHeight); height = self.options.height || Math.max(self.$test.height() + 2, self.minHeight); width = self.options.width || Ox.limit(self.$test.width() + 2, self.minWidth, self.maxWidth); Ox.print(self.options.width, self.$test.width(), 'wxh', width, height) if (self.options.type == 'input') { self.$input.options({ width: width }); self.$input.find('input').css({width: width + 'px'}); } else { self.$input.options({ height: height, width: width// + Ox.UI.SCROLLBAR_SIZE }); self.$input.find('textarea').css({ height: height + 'px', width: width /*+ Ox.UI.SCROLLBAR_SIZE*/ + 'px' }); } //self.$input.find('input').css({width: width + 2}) /* that.triggerEvent('change', { value: event.value }); */ } function edit() { var height, width; if (self.options.editable && !self.options.editing) { self.originalValue = self.options.value; self.minWidth = 8; self.maxWidth = that.parent().width(); self.minHeight = 14; self.maxHeight = that.parent().height(); height = self.options.height || self.$value.height(); width = self.options.width || self.$value.width(); self.$value.hide(); Ox.print('H:::', self.options.height, height) if (!self.$test) { self.$test = self.$value.$element.clone() .css(Ox.extend({display: 'inline-block'}, self.css)) .html(formatTestValue()) .hide() .appendTo(that.$element); self.$input = Ox.Input({ changeOnKeypress: true, style: 'square', type: self.options.type, value: formatInputValue(), }) .css(self.css) .bindEvent({ blur: submit, cancel: cancel, change: change //submit: submit }) .appendTo(that.$element); self.$input.find('input').css(self.css); } self.$input.options({ width: width, height: height }) .show(); if (self.options.type == 'input') { self.$input.find('input').css({ height: height + 'px', width: width + 'px' }); } else { self.$input.find('textarea').css({ height: height + 'px', width: width + 'px' }); } // fixme: why can't this be chained? setTimeout(function() { self.$input.focusInput(false); }, 0); self.options.editing = true; that.triggerEvent('edit', {editing: true}); } } function formatInputValue() { return Ox.decodeHTML( self.options.type == 'input' ? self.options.value : self.options.value.replace(//g, '\n\n') ); } function formatTestValue() { return self.options.type == 'input' ? self.options.value.replace(/ /g, ' ') : Ox.parseHTML(self.options.value || ' ') .replace(/$/, '
 '); } function formatValue() { return self.options.format ? self.options.format(self.options.value) : self.options.value } function submit() { self.options.value = Ox.parseHTML(self.$input.value()); self.$input.options({value: formatInputValue()}).hide(); self.$test.html(formatTestValue()); self.$value.html(formatValue()).show(); self.options.editing = false; that.triggerEvent('submit', { value: self.options.value }); } that.css = function(css) { self.css = css; that.$element.css(css); self.$value.css(css); self.$test && self.$test.css(css); self.$input && self.$input.css(css); return that; }; return that; };