'use strict'; /*@ Ox.ArrayInput Array input options Options object input Optional functions for complex input elements label string, '' max integer, maximum number of items, 0 for all sort fixme: this should probably be removed value <[]> value width width self Shared private variable ([options[, self]]) -> Array input change change @*/ Ox.ArrayInput = function(options, self) { self = self || {}; var that = Ox.Element({}, self) .defaults({ input: { get: Ox.Input, getEmpty: function() { return ''; }, isEmpty: function(value) { return value === ''; }, setWidth: function($input, width) { $input.options({width: width}); } }, label: '', max: 0, sort: false, // fixme: this should probably be removed value: [], width: 256 }) .options(options || {}) .update({ value: setValue, width: setWidths }); self.options.value = self.options.value || []; if (self.options.label) { self.$label = Ox.Label({ title: self.options.label, width: self.options.width }) .appendTo(that); } self.$element = []; self.$input = []; self.$removeButton = []; self.$addButton = []; ( self.options.value.length ? self.options.value : [self.options.input.getEmpty()] ).forEach(function(value, i) { addInput(i, value); }); self.options.value = getValue(); function addInput(index, value, focus) { self.$element.splice(index, 0, Ox.Element() .css({ height: '16px', marginTop: self.options.label || index > 0 ? '8px' : 0 }) .data({index: index})); if (index == 0) { self.$element[index].appendTo(that); } else { self.$element[index].insertAfter(self.$element[index - 1]); } self.$input.splice( index, 0, self.options.input.get({ width: self.options.width - 48 }) .css({float: 'left'}) .bindEvent({ change: function(data) { if ( self.options.sort && !self.options.input.isEmpty(data.value) ) { sortInputs(); } self.options.value = getValue(); that.triggerEvent('change', { value: self.options.value }); } }) .appendTo(self.$element[index])); if (value) { self.$input[index].options({value: value}) } if (focus && self.$input[index].focusInput) { self.$input[index].focusInput(true); } self.$removeButton.splice(index, 0, Ox.Button({ title: self.$input.length == 1 ? 'close' : 'remove', type: 'image' }) .css({float: 'left', marginLeft: '8px'}) .on({ click: function() { var index = $(this).parent().data('index'); if (!self.options.input.isEmpty(self.$input[index])) { self.$input[index].value(self.options.input.getEmpty()); self.options.value = getValue(); that.triggerEvent('change', { value: self.options.value }); } if (self.$input.length == 1) { if (self.$input[0].focusInput) { self.$input[0].focusInput(true); } } else { removeInput(index); that.triggerEvent('remove'); } } }) .appendTo(self.$element[index])); self.$addButton.splice(index, 0, Ox.Button({ disabled: index == self.options.max - 1, title: 'add', type: 'image' }) .css({float: 'left', marginLeft: '8px'}) .on({ click: function() { var index = $(this).parent().data('index'); addInput(index + 1, self.options.input.getEmpty(), true); that.triggerEvent('add'); } }) .appendTo(self.$element[index])); updateInputs(); } function getValue() { return Ox.map(self.$input, function($input) { return $input.value(); }).filter(function(value) { return !self.options.input.isEmpty(value); }); }; function removeInput(index) { Ox.Log('Form', 'remove', index); [ 'input', 'removeButton', 'addButton', 'element' ].forEach(function(element) { var key = '$' + element; self[key][index].remove(); self[key].splice(index, 1); }); updateInputs(); } function setValue() { while (self.$input.length) { removeInput(0); } ( self.options.value.length ? self.options.value : [self.options.input.getEmpty()] ).forEach(function(value, i) { addInput(i, value); }); } function setWidths() { self.$label && self.$label.options({width: self.options.width}); self.$element.forEach(function($element, i) { $element.css({width: self.options.width + 'px'}); self.options.input.setWidth(self.$input[i], self.options.width - 48); }); } function sortInputs() { Ox.sort(self.$element, function($element) { return self.$input[$element.data('index')].value(); }).forEach(function($element) { $element.detach(); }); self.$element.forEach(function($element, i) { $element.data({index: i}).appendTo(that); }); } function updateInputs() { self.$element.forEach(function($element, i) { $element.data({index: i}); self.$removeButton[i].options({ title: self.$element.length == 1 ? 'close' : 'remove' }); self.$addButton[i].options({ disabled: self.$element.length == self.options.max }); }); } /*@ setErrors setErrors (values) -> set errors @*/ that.setErrors = function(values) { self.$input.forEach(function($input) { $input[ values.indexOf($input.value()) > -1 ? 'addClass' : 'removeClass' ]('OxError'); }); }; return that; };