/*@ 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.$value = Ox.Element(self.options.type == 'input' ? '' : '
') .addClass('OxValue') .css(self.options.type == 'input' ? { //height: '14px', //padding: '1px 4px 1px 4px', //border: '1px solid transparent' } : { //padding: '0 4px 0 4px' //width: self.options.width + 'px' }) //.css({background: 'red'}) .html(formatValue()) //[self.options.editing ? 'hide' : 'show']() .appendTo(that); self.$test = self.$value.$element.clone() .css({ display: 'inline-block', //position: 'absolute', //left: 200, //top: 200 }) .html(formatTestValue()) .hide() .appendTo(that.$element); self.$input = Ox.Input(Ox.extend({ changeOnKeypress: true, style: 'square', type: self.options.type, value: formatInputValue() }, self.options.type == 'textarea' ? { width: self.options.width } : {})) .css({ display: 'none', }) .bindEvent({ blur: submit, cancel: cancel, change: change //submit: submit }) //[self.options.editing ? 'show' : 'hide']() .hide() .appendTo(that.$element); 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, self.maxHeight, height) self.$input.options({ height: height, width: width }).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(obj) { that.$element.css(obj); self.$value.css(obj); self.$test.css(obj).hide(); self.$input.css(obj).hide(); self.$input.find('input').css(obj); //self.$value.css.apply(this, arguments); //self.$input.css.apply(this, arguments); return that }; return that; };