/*@ 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 || {}; that = Ox.Element('
', self) .defaults({ editing: false, format: null, value: '', width: 256, type: 'input' }) .options(options || {}) .addClass('OxEditable') .bindEvent({ doubleclick: edit }); 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' }) .html( self.options.format ? self.options.format(self.options.value) : self.options.value ) //[self.options.editing ? 'hide' : 'show']() .appendTo(that); self.$test = self.$value.$element.clone() .html(self.options.value.replace(/ /g, ' ')) .css({ display: 'table-cell', //position: 'absolute', //left: 200, //top: 200 }) .hide() .appendTo(that.$element); self.$input = Ox.Input(Ox.extend({ changeOnKeypress: true, style: 'square', type: self.options.type, value: self.options.value }, self.options.type == 'textarea' ? { width: self.options.width } : {})) .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.$input.hide(); self.$value.show(); self.options.editing = false; } function change(event) { var height, width; self.options.value = formatValue(event.value); self.$value.html( self.options.format ? self.options.format(self.options.value) : self.options.value ); self.$test.html(self.options.value.replace(/ /g, ' ')); height = self.$test.height(); height = Math.max(self.$test.height(), 14); width = Math.max(self.$test.width() + 2, 8); Ox.print('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.editing) { height = self.$value.height(); width = self.$value.width(); self.$value.hide(); self.$input.options({ height: height, width: width }).show(); if (self.options.type == 'input') { self.$input.find('input').css({width: width + 'px'}); } else { self.$input.find('textarea').css({ height: height + 'px', width: width + Ox.UI.SCROLLBAR_SIZE + 'px' }); } // fixme: why can't this be chained? setTimeout(function() { self.$input.focusInput(false); }, 0); self.options.editing = true; } } function formatValue(value) { if (self.options.type == 'input') { value = value.replace(/ /g, ' '); } else { value = value.replace(/\n/g, '
') .replace(/$/, '
 '); } return value; } function submit() { self.options.value = self.$input.value(); self.$value.html( self.options.format ? self.options.format(self.options.value) : self.options.value ); cancel(); } that.css = function(obj) { that.$element.css(obj); self.$value.css(obj); self.$input.css(obj); self.$input.find('input').css(obj); //self.$value.css.apply(this, arguments); //self.$input.css.apply(this, arguments); return that }; return that; };