'use strict'; /*@ Ox.ArrayEditable Array Editable Object @*/ Ox.ArrayEditable = function(options, self) { self = self || {}; var that = Ox.Element(options.editable === false ? {} : { tooltip: 'Doubleclick to add ' + (options.itemName || 'item') }, self) .defaults({ clickLink: null, editable: true, itemName: 'item', items: [], maxHeight: void 0, placeholder: '', position: -1, selected: '', separator: ',', sort: [], submitOnBlur: true, type: 'input', width: 256 }) .options(options || {}) .addClass('OxArrayEditable OxArrayEditable' + Ox.toTitleCase(self.options.type)) .css({width: self.options.width - (self.options.type == 'input' ? 8 : 0) + 'px'}) // 2 x 4 px padding .bindEvent({ anyclick: anyclick, doubleclick: doubleclick, key_delete: deleteItem, key_enter: function() { // make sure the newline does // not end up in the textarea setTimeout(function() { that.editItem(); }, 0); }, key_escape: selectNone, key_down: self.options.type == 'input' ? selectLast : selectNext, key_left: self.options.type == 'input' ? selectPrevious : selectFirst, key_right: self.options.type == 'input' ? selectNext : selectLast, key_up: self.options.type == 'input' ? selectFirst : selectPrevious }); self.$items = []; self.editing = false; renderItems(); self.selected = getSelectedPosition(); function anyclick(e) { Ox.print('SELF EDITING', self.editing) var $target = $(e.target), $parent = $target.parent(), position = $parent.data('position'); if (!$target.is('.OxInput')) { Ox.print('BLURRED EDITING', self.blurred, self.editing) if ($parent.is('.OxEditableElement')) { if (!$parent.is('.OxSelected')) { // select another item selectItem( e.metaKey && position == self.selected ? '' : $parent.data('position') ); } } else if (!self.blurred) { // if there wasn't an active input element if (self.editing) { // blur if still in editing mode that.blurItem(); } else { // othewise deselect selected selectNone(); } } that.gainFocus(); } } function deleteItem() { if (self.options.editable) { self.options.items.splice(self.selected, 1); renderItems(); that.triggerEvent('delete', { id: self.options.selected }); self.selected = -1; self.options.selected = ''; } } function doubleclick(e) { var $target = $(e.target), $parent = $target.parent(); if ($parent.is('.OxEditableElement')) { that.editItem(); } else if (!$target.is('.OxInput')) { that.triggerEvent('add'); } } function getSelectedId() { return self.selected > -1 ? self.options.items[self.selected].id : ''; } function getSelectedPosition() { return Ox.getIndexById(self.options.items, self.options.selected); } function renderItems(blur) { if (self.editing) { self.options.items[getSelectedPosition()].value = that.find(self.options.type + ':visible').val(); } that.empty(); if (self.options.items.length == 0) { Ox.Editable({ clickLink: self.options.clickLink, editable: false, type: 'text', value: self.options.placeholder }) .addClass('OxPlaceholder') .appendTo(that); } else { sortItems(); self.options.items.forEach(function(item, i) { if (i && self.options.type == 'input') { $('') .addClass('OxSeparator') .html(self.options.separator + ' ') .appendTo(that); } self.$items[i] = Ox.Editable({ blurred: self.editing && i == self.selected ? blur : false, clickLink: self.options.clickLink, editable: self.options.editable && item.editable, editing: self.editing && i == self.selected, /* format: function(value) { return value || ' ' }, */ maxHeight: self.options.maxHeight, submitOnBlur: self.options.submitOnBlur, tooltip: 'Click to select' + ( item.editable ? ', doubleclick to edit' : '' ), type: self.options.type, value: item.value, width: self.options.type == 'input' ? 0 : self.options.width - 9 }) .addClass(item.id == self.options.selected ? 'OxSelected' : '') //.css(self.options.type == 'textarea' ? {padding: '4px'} : {}) .data({id: item.id, position: i}) .bindEvent({ blur: function(data) { // fixme: remove data that.gainFocus(); that.triggerEvent('blur', { id: item.id, value: data.value }); self.blurred = true; setTimeout(function() { self.blurred = false; }, 250); }, cancel: function(data) { self.editing = false; that.gainFocus(); that.triggerEvent('blur', data); }, change: function(data) { that.triggerEvent('change', { id: item.id, value: data.value }); }, edit: function(data) { self.editing = true; that.triggerEvent('edit', data); }, submit: function(data) { self.editing = false; that.gainFocus(); submitItem(i, data.value); } }) .appendTo(that); }); } //self.editing && that.editItem(blur); } function selectFirst() { self.selected > -1 && selectItem(0); } function selectItem(idOrPosition) { if (Ox.isString(idOrPosition)) { self.options.selected = idOrPosition; self.selected = getSelectedPosition(); } else { self.selected = idOrPosition; self.options.selected = getSelectedId(); } if (/*self.options.selected == '' && */self.editing) { self.editing = false; that.blurItem(); } Ox.print('SELECT ITEM', self.options.selected, self.selected); that.find('.OxSelected').removeClass('OxSelected'); self.selected > -1 && self.$items[self.selected].addClass('OxSelected'); triggerSelectEvent(); } function selectLast() { self.selected > -1 && selectItem(self.options.items.length - 1); } function selectNext() { self.selected > -1 && self.selected < self.options.items.length - 1 && selectItem(self.selected + 1); } function selectNone() { selectItem(-1); } function selectPrevious() { self.selected > 0 && selectItem(self.selected - 1); } function sortItems() { if (!Ox.isEmpty(self.options.sort)) { self.options.items = Ox.sortBy(self.options.items, self.options.sort); self.selected = getSelectedPosition(); } } function submitItem(position, value) { var item = self.options.items[position]; if (value === '') { deleteItem(); } else { that.triggerEvent(item.value === value ? 'blur' : 'submit', { id: item.id, value: value }); item.value = value; } } function triggerSelectEvent() { if (!self.triggered) { that.triggerEvent('select', { id: self.options.selected }); self.triggered = true; setTimeout(function() { self.triggered = false; }, 250); } } self.setOption = function(key, value) { if (key == 'items') { if (self.options.selected && getSelectedPosition() == -1) { selectNone(); } renderItems(true); } else if (key == 'selected') { selectItem(value); } else if (key == 'sort') { renderItems(); } else if (key == 'width') { that.css({width: value - 8 + 'px'}); // 2 x 4 px padding self.options.type == 'textarea' && self.$items.forEach(function($item) { $item.options({width: value}) }); } } that.addItem = function(position, item) { if (self.options.editable) { self.options.items.splice(position, 0, item); renderItems(); } return that; //that.triggerEvent('add'); /* self.values = Ox.filter(values, function(value) { return value; }); self.values.push(''); renderItems(); Ox.last(self.$items).triggerEvent('doubleclick'); */ }; that.blurItem = function() { /* if (self.options.selected) { self.$items[self.selected].options({editing: false}); } else { */ self.editing = false; self.$items.forEach(function($item) { $item.options({editing: false}); }); //} return that; }; that.editItem = function() { Ox.print('AE EDIT ITEM') if (self.options.editable && self.options.selected) { self.editing = true; self.$items[self.selected].options({editing: true}); } return that; }; that.reloadItems = function() { renderItems(); return that; }; that.removeItem = function(position) { if (self.options.editable) { } return that; }; /* that.submitItem = function() { if (self.editing) { self.editing = false; self.$items[self.selected].options({editing: false}); } } */ return that; };