Show:
                            var BaseOptionsCellEditor,
                            
                                L = A.Lang,
                            
                                AEscape = A.Escape,
                            
                                CSS_CELLEDITOR_EDIT = A.getClassName('celleditor', 'edit'),
                                CSS_CELLEDITOR_EDIT_ADD_OPTION = A.getClassName('celleditor', 'edit', 'add', 'option'),
                                CSS_CELLEDITOR_EDIT_DD_HANDLE = A.getClassName('celleditor', 'edit', 'dd', 'handle'),
                                CSS_CELLEDITOR_EDIT_DELETE_OPTION = A.getClassName('celleditor', 'edit', 'delete', 'option'),
                                CSS_CELLEDITOR_EDIT_HIDE_OPTION = A.getClassName('celleditor', 'edit', 'hide', 'option'),
                                CSS_CELLEDITOR_EDIT_INPUT_NAME = A.getClassName('celleditor', 'edit', 'input', 'name'),
                                CSS_CELLEDITOR_EDIT_INPUT_VALUE = A.getClassName('celleditor', 'edit', 'input', 'value'),
                                CSS_CELLEDITOR_EDIT_LABEL = A.getClassName('celleditor', 'edit', 'label'),
                                CSS_CELLEDITOR_EDIT_LINK = A.getClassName('celleditor', 'edit', 'link'),
                                CSS_CELLEDITOR_EDIT_OPTION_ROW = A.getClassName('celleditor', 'edit', 'option', 'row'),
                                CSS_ICON = A.getClassName('glyphicon'),
                                CSS_ICON_GRIP_DOTTED_VERTICAL = A.getClassName('glyphicon', 'resize', 'vertical');
                            
                            /**
                             * Abstract class `A.BaseOptionsCellEditor` for options attribute support.
                             *
                             * @class A.BaseOptionsCellEditor
                             * @extends A.BaseCellEditor
                             * @param {Object} config Object literal specifying widget configuration
                             * properties.
                             * @constructor
                             */
                            BaseOptionsCellEditor = A.Component.create({
                            
                                /**
                                 * Static property provides a string to identify the class.
                                 *
                                 * @property NAME
                                 * @type String
                                 * @static
                                 */
                                NAME: 'optionsCellEditor',
                            
                                /**
                                 * Static property used to define the default attribute configuration
                                 * for the `A.BaseOptionsCellEditor`.
                                 *
                                 * @property ATTRS
                                 * @type Object
                                 * @static
                                 */
                                ATTRS: {
                                    /**
                                     * Static property of input formatter for modifying the data values
                                     * for showing on the UI.
                                     *
                                     * Default `null` Function will not modify the value.
                                     *
                                     * @attribute inputFormatter
                                     * @default null
                                     */
                                    inputFormatter: {
                                        value: null
                                    },
                            
                                    /**
                                     * Indicates if the options Edit Container is hidden on the `save` event.
                                     *
                                     * @attribute hideEditContainerOnSave
                                     * @default true
                                     * @type Boolean
                                     */
                                    hideEditContainerOnSave: {
                                        value: true,
                                        validator: A.Lang.isBoolean
                                    },
                            
                                    /**
                                     * Array or Object which defines the available options for the
                                     * `A.BaseOptionsCellEditor`.
                                     *
                                     * @attribute options
                                     * @default {}
                                     * @type Object|Array
                                     */
                                    options: {
                                        setter: '_setOptions',
                                        value: {},
                                        validator: L.isObject
                                    },
                            
                                    /**
                                     * Defines the custom rules used to validate options.
                                     *
                                     * @attribute optionsValidatorCustomRules
                                     * @type Object
                                     */
                                    optionsValidatorCustomRules: {
                                        validator: A.Lang.isObject,
                                        valueFn: function() {
                                            var instance = this;
                            
                                            return {
                                                'uniqueValue': {
                                                    condition: function(fieldValue, fieldNode) {
                                                        var instance = this;
                            
                                                        var editContainerNode = fieldNode.ancestor('.' + CSS_CELLEDITOR_EDIT);
                            
                                                        var inputValueNodelist = editContainerNode.all('.' + CSS_CELLEDITOR_EDIT_INPUT_VALUE);
                            
                                                        var validate = function (validateNode, nodelist, recurse) {
                                                            var duplicates = false;
                            
                                                            nodelist.each(
                                                                function(node){
                                                                    if (validateNode !== node) {
                                                                        if (validateNode.val() === node.val()) {
                                                                            instance.highlight(validateNode);
                                                                            instance.addFieldError(validateNode, 'uniqueValue');
                            
                                                                            duplicates = true;
                                                                        }
                            
                                                                        if (recurse) {
                                                                            validate(node, inputValueNodelist, false);
                                                                        }
                                                                    }
                                                                }
                                                            );
                            
                                                            if (!duplicates) {
                                                                instance.resetField(validateNode);
                                                                instance.highlight(validateNode, true);
                                                            }
                            
                                                            return !duplicates;
                                                        };
                            
                                                        return validate(fieldNode, inputValueNodelist, true);
                                                    },
                                                    errorMessage: instance.getStrings().valueNotUnique
                                                }
                                            };
                                        }
                                    },
                            
                                    /**
                                     * Defines the initial rules used to validate options.
                                     *
                                     * @attribute optionsValidatorInputRules
                                     * @default {custom: true, uniqueValue: true}
                                     * @type Object
                                     */
                                    optionsValidatorInputRules: {
                                        validator: A.Lang.isObject,
                                        value: {
                                            custom: true,
                                            uniqueValue: true
                                        }
                                    },
                            
                                    /**
                                     * Static property of output formatter for modifying the data values
                                     * for output.
                                     *
                                     * Default `null` Function will not modify the value.
                                     *
                                     * @attribute outputFormatter
                                     * @default null
                                     */
                                    outputFormatter: {
                                        value: null
                                    },
                            
                                    /**
                                     * Defines the selected state of an option.
                                     *
                                     * @attribute selectedAttrName
                                     * @default 'selected'
                                     * @type String
                                     */
                                    selectedAttrName: {
                                        value: 'selected',
                                        validator: L.isString
                                    },
                            
                                    /**
                                     * Collection of strings used to label elements of UI.
                                     *
                                     * @attribute strings
                                     * @type Object
                                     */
                                    strings: {
                                        value: {
                                            add: 'Add',
                                            addOption: 'Add option',
                                            cancel: 'Cancel',
                                            edit: 'Edit options',
                                            editOptions: 'Edit option(s)',
                                            name: 'Name',
                                            optionName: 'Option Name',
                                            optionValue: 'Option Value',
                                            remove: 'Remove',
                                            save: 'Save',
                                            stopEditing: 'Stop editing',
                                            value: 'Value',
                                            valueNotUnique: 'Value not unique.'
                                        }
                                    }
                                },
                            
                                /**
                                 * Static property used to define which component it extends.
                                 *
                                 * @property EXTENDS
                                 * @type Object
                                 * @static
                                 */
                                EXTENDS: A.BaseCellEditor,
                            
                                /**
                                 * Static property used to define the UI attributes.
                                 *
                                 * @property UI_ATTRS
                                 * @type Array
                                 * @static
                                 */
                                UI_ATTRS: ['options'],
                            
                                prototype: {
                                    EDIT_TEMPLATE: '<div class="' + CSS_CELLEDITOR_EDIT + '"></div>',
                            
                                    EDIT_OPTION_ROW_TEMPLATE: '<div class="form-inline ' + CSS_CELLEDITOR_EDIT_OPTION_ROW + '">' +
                                            '<div class="form-group">' +
                                                '<span class="' + [CSS_CELLEDITOR_EDIT_DD_HANDLE, CSS_ICON, CSS_ICON_GRIP_DOTTED_VERTICAL].join(' ') + '"></span>' +
                                            '</div>' +
                                            '<div class="form-group">' +
                                                '<label class="sr-only" for="{optionValueName}_name">{labelOptionName}</label>' +
                                                '<input class="' + CSS_CELLEDITOR_EDIT_INPUT_NAME + ' form-control input-sm" size="7" id="{optionValueName}_name"' +
                                                'placeholder="{titleName}" title="{titleName}" type="text" value="{valueName}" /> ' +
                                            '</div>' +
                                            '<div class="form-group">' +
                                                '<label class="sr-only" for="{optionValueName}">{labelOptionValue}</label>' +
                                                '<input class="' + CSS_CELLEDITOR_EDIT_INPUT_VALUE + ' form-control input-sm" id="{optionValueName}"' +
                                                ' name="{optionValueName}" placeholder="{titleValue}" size="7" title="{titleValue}" type="text" value="{valueValue}" /> ' +
                                            '</div>' +
                                            '<div class="form-group">' +
                                                '<button aria-label="{remove}" class="close ' + [CSS_CELLEDITOR_EDIT_LINK, CSS_CELLEDITOR_EDIT_DELETE_OPTION].join(' ') +
                                                '" type="button"><span aria-hidden="true">&times;</span></button>' +
                                            '</div>' +
                                        '</div>' +
                                    '</div>',
                            
                                    EDIT_ADD_LINK_TEMPLATE: '<div class="form-group"><a class="' + [CSS_CELLEDITOR_EDIT_LINK, CSS_CELLEDITOR_EDIT_ADD_OPTION].join(
                                        ' ') + '" href="javascript:void(0);">{addOption}</a></div> ',
                                    EDIT_LABEL_TEMPLATE: '<div class="' + CSS_CELLEDITOR_EDIT_LABEL + '">{editOptions}</div>',
                            
                                    editContainer: null,
                                    editSortable: null,
                                    options: null,
                            
                                    /**
                                     * Construction logic executed during `A.BaseOptionsCellEditor`
                                     * instantiation. Lifecycle.
                                     *
                                     * @method initializer
                                     * @protected
                                     */
                                    initializer: function() {
                                        var instance = this;
                            
                                        instance.on('edit', instance._onEditEvent);
                                        instance.on('save', instance._onSave);
                                        instance.after('initToolbar', instance._afterInitToolbar);
                            
                                        A.FormValidator.addCustomRules(instance.get('optionsValidatorCustomRules'));
                                    },
                            
                                    /**
                                     * Adds a new option to the `A.BaseOptionsCellEditor`.
                                     *
                                     * If `name` or `value` is omitted, a blank string is used in it's
                                     * place.
                                     *
                                     * @method addNewOption
                                     * @param name
                                     * @param value
                                     */
                                    addNewOption: function(name, value) {
                                        var instance = this;
                                        var addOptionLink = instance.editContainer.one('.' + CSS_CELLEDITOR_EDIT_ADD_OPTION);
                                        var newRow = A.Node.create(
                                            instance._createEditOption(
                                                name || '',
                                                value || ''
                                            )
                                        );
                            
                                        addOptionLink.placeBefore(newRow);
                                        newRow.one('input').focus();
                                    },
                            
                                    /**
                                     * Removes the given `optionRow` Node from `A.BaseOptionsCellEditor`.
                                     *
                                     * @method removeOption
                                     * @param optionRow
                                     */
                                    removeOption: function(optionRow) {
                                        optionRow.remove();
                                    },
                            
                                    /**
                                     * Saves the `BaseOptionsCellEditor` `options` property.
                                     *
                                     * @method saveOptions
                                     */
                                    saveOptions: function() {
                                        var instance = this;
                                        var editContainer = instance.editContainer;
                            
                                        if (editContainer && !editContainer.hasAttribute('hidden')) {
                                            var names = editContainer.all('.' + CSS_CELLEDITOR_EDIT_INPUT_NAME);
                                            var values = editContainer.all('.' + CSS_CELLEDITOR_EDIT_INPUT_VALUE);
                                            var options = {};
                            
                                            names.each(function(inputName, index) {
                                                var name = inputName.val();
                                                var value = values.item(index).val();
                            
                                                options[value] = name;
                                            });
                            
                                            instance.set('options', options);
                            
                                            if (instance.get('hideEditContainerOnSave')) {
                                                instance.toggleEdit();
                                            }
                                        }
                                    },
                            
                                    /**
                                     * Toggles the display of the `A.BaseOptionsCellEditor`.
                                     *
                                     * @method toggleEdit
                                     */
                                    toggleEdit: function() {
                                        var instance = this;
                            
                                        instance.editContainer.toggle();
                                    },
                            
                                    /**
                                     * Creates option elements and stores a reference to them in
                                     * the `option` property.
                                     * TODO. Rewrite this method.
                                     *
                                     * @method _createOptions
                                     * @param {Array} val
                                     * @protected
                                     */
                                    _createOptions: function(val) {
                                        var instance = this;
                                        var elements = instance.elements;
                                        var optionsBuffer = [];
                                        var wrappersBuffer = [];
                                        var optionTpl = instance.OPTION_TEMPLATE;
                                        var optionWrapperTpl = instance.OPTION_WRAPPER;
                            
                                        A.each(val, function(oLabel, oValue) {
                                            var values = {
                                                id: A.guid(),
                                                label: AEscape.html(oLabel),
                                                name: AEscape.html(oValue),
                                                value: AEscape.html(oValue)
                                            };
                            
                                            if (optionTpl) {
                                                optionsBuffer.push(L.sub(optionTpl, values));
                                            }
                            
                                            if (optionWrapperTpl) {
                                                wrappersBuffer.push(L.sub(optionWrapperTpl, values));
                                            }
                                        });
                            
                                        var optionsNodeList = A.NodeList.create(optionsBuffer.join(''));
                                        var wrappersNodeList = A.NodeList.create(wrappersBuffer.join(''));
                            
                                        if (wrappersNodeList.size()) {
                                            wrappersNodeList.each(function(wrapper, i) {
                                                wrapper.prepend(optionsNodeList.item(i));
                                            });
                            
                                            elements.setContent(wrappersNodeList);
                                        }
                                        else {
                                            elements.setContent(optionsNodeList);
                                        }
                            
                                        instance.options = optionsNodeList;
                                    },
                            
                                    /**
                                     * Create edit buffer.
                                     *
                                     * @method _createEditBuffer
                                     * @protected
                                     * @return {String} HTML string for the `A.BaseOptionsCellEditor`.
                                     */
                                    _createEditBuffer: function() {
                                        var instance = this;
                                        var strings = instance.getStrings();
                                        var buffer = [];
                            
                                        buffer.push(
                                            L.sub(instance.EDIT_LABEL_TEMPLATE, {
                                                editOptions: strings.editOptions
                                            })
                                        );
                            
                                        A.each(instance.get('options'), function(name, value) {
                                            buffer.push(instance._createEditOption(name, value));
                                        });
                            
                                        buffer.push(
                                            L.sub(instance.EDIT_ADD_LINK_TEMPLATE, {
                                                addOption: strings.addOption
                                            })
                                        );
                            
                                        return buffer.join('');
                                    },
                            
                                    /**
                                     * Create Edit option.
                                     *
                                     * @method _createEditOption
                                     * @param {String} name
                                     * @param {String} value
                                     * @protected
                                     * @return {String} HTML string for the `A.BaseOptionsCellEditor` input
                                     * option.
                                     */
                                    _createEditOption: function(name, value) {
                                        var instance = this;
                                        var fieldName = A.guid() + '_value';
                                        var strings = instance.getStrings();
                            
                                        instance.validator.get('rules')[fieldName] = instance.get('optionsValidatorInputRules');
                            
                                        return L.sub(
                                            instance.EDIT_OPTION_ROW_TEMPLATE, {
                                                labelOptionName: AEscape.html(strings.optionName),
                                                labelOptionValue: AEscape.html(strings.optionValue),
                                                optionValueName: AEscape.html(fieldName),
                                                remove: strings.remove,
                                                titleName: AEscape.html(strings.name),
                                                titleValue: AEscape.html(strings.value),
                                                valueName: AEscape.html(name),
                                                valueValue: AEscape.html(value)
                                            }
                                        );
                                    },
                            
                                    /**
                                     * Default callback for `initEdit` event of `A.BaseOptionsCellEditor`.
                                     *
                                     * @method _defInitEditFn
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _defInitEditFn: function() {
                                        var instance = this;
                                        var editContainer = A.Node.create(instance.EDIT_TEMPLATE);
                            
                                        editContainer.delegate('click', A.bind(instance._onEditLinkClickEvent, instance), '.' +
                                            CSS_CELLEDITOR_EDIT_LINK);
                                        editContainer.delegate('keydown', A.bind(instance._onEditKeyEvent, instance), 'input');
                            
                                        instance.editContainer = editContainer;
                            
                                        instance.setStdModContent(
                                            A.WidgetStdMod.BODY,
                                            editContainer.hide(),
                                            A.WidgetStdMod.AFTER
                                        );
                            
                                        instance.editSortable = new A.Sortable({
                                            container: editContainer,
                                            handles: ['.' + CSS_CELLEDITOR_EDIT_DD_HANDLE],
                                            nodes: '.' + CSS_CELLEDITOR_EDIT_OPTION_ROW,
                                            opacity: '.3'
                                        }).delegate.dd.plug(A.Plugin.DDConstrained, {
                                            constrain: editContainer,
                                            stickY: true
                                        });
                            
                                        instance._syncEditOptionsUI();
                                    },
                            
                                    /**
                                     * Getter for the selected options.
                                     *
                                     * @method _getSelectedOptions
                                     * @protected
                                     * @return {NodeList} Selected options.
                                     */
                                    _getSelectedOptions: function() {
                                        var instance = this;
                                        var options = [];
                            
                                        instance.options.each(function(option) {
                                            if (option.get(instance.get('selectedAttrName'))) {
                                                options.push(option);
                                            }
                                        });
                            
                                        return A.all(options);
                                    },
                            
                                    /**
                                     * Fires on `edit` event, loading the editing UI.
                                     *
                                     * @method _onEditEvent
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _onEditEvent: function() {
                                        var instance = this;
                            
                                        instance._handleInitEditEvent();
                            
                                        instance.toggleEdit();
                            
                                        instance._syncEditOptionsUI();
                                    },
                            
                                    /**
                                     * Updates the option state on the UI on event `click` on the edit link.
                                     *
                                     * @method _onEditLinkClickEvent
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _onEditLinkClickEvent: function(event) {
                                        var instance = this;
                                        var currentTarget = event.currentTarget;
                            
                                        if (currentTarget.test('.' + CSS_CELLEDITOR_EDIT_ADD_OPTION)) {
                                            instance.addNewOption();
                                        }
                                        else if (currentTarget.test('.' + CSS_CELLEDITOR_EDIT_HIDE_OPTION)) {
                                            instance.toggleEdit();
                                        }
                                        else if (currentTarget.test('.' + CSS_CELLEDITOR_EDIT_DELETE_OPTION)) {
                                            instance.removeOption(
                                                currentTarget.ancestor('.' + CSS_CELLEDITOR_EDIT_OPTION_ROW)
                                            );
                                        }
                            
                                        event.halt();
                                    },
                            
                                    /**
                                     * Listen to `keydown` event on `A.BaseOptionsCellEditor` to focus on
                                     * the next option.
                                     *
                                     * @method _onEditKeyEvent
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _onEditKeyEvent: function(event) {
                                        var instance = this;
                                        var currentTarget = event.currentTarget;
                            
                                        if (event.isKey('return')) {
                                            var nextInput = currentTarget.next('input');
                            
                                            if (nextInput) {
                                                nextInput.selectText();
                                            }
                                            else {
                                                instance.addNewOption();
                                            }
                            
                                            event.halt();
                                        }
                                    },
                            
                                    /**
                                     * Fires on `save` event. Save the options.
                                     *
                                     * @method _onSave
                                     * @param {EventFacade} event
                                     * @protected
                                     */
                                    _onSave: function() {
                                        var instance = this;
                            
                                        instance.saveOptions();
                                    },
                            
                                    /**
                                     * Determines the proper format for the `options` attribute.
                                     *
                                     * @method _setOptions
                                     * @param {Array} val
                                     * @protected
                                     */
                                    _setOptions: function(val) {
                                        var options = {};
                            
                                        if (L.isArray(val)) {
                                            A.Array.each(val, function(value) {
                                                options[value] = value;
                                            });
                                        }
                                        else if (L.isObject(val)) {
                                            options = val;
                                        }
                            
                                        return options;
                                    },
                            
                                    /**
                                     * Sync edit options UI.
                                     *
                                     * @method _syncEditOptionsUI
                                     * @protected
                                     */
                                    _syncEditOptionsUI: function() {
                                        var instance = this;
                            
                                        instance.editContainer.setContent(instance._createEditBuffer());
                                    },
                            
                                    /**
                                     * Set UI Options values.
                                     *
                                     * @method _uiSetOptions
                                     * @param {Array} val
                                     * @protected
                                     */
                                    _uiSetOptions: function(val) {
                                        var instance = this;
                            
                                        instance._createOptions(val);
                                        instance._uiSetValue(instance.get('value'));
                                        instance._syncElementsName();
                                    },
                            
                                    /**
                                     * Sets the `selectedAttrName` (`selected`) attribute on the option
                                     * elements matching `val`.
                                     *
                                     * @method _uiSetValue
                                     * @param {Array|String} val
                                     * @protected
                                     * @return {Array} Resulting new values.
                                     */
                                    _uiSetValue: function(val) {
                                        var instance = this;
                            
                                        var optionsNodeList = instance.options;
                            
                                        if (optionsNodeList && optionsNodeList.size()) {
                                            optionsNodeList.set(instance.get('selectedAttrName'), false);
                            
                                            if (L.isValue(val)) {
                                                if (!L.isArray(val)) {
                                                    val = String(val).split(',');
                                                }
                            
                                                A.Array.each(val, function(value) {
                                                    optionsNodeList.filter('[value="' + AEscape.html(L.trim(value)) + '"]').set(instance.get(
                                                        'selectedAttrName'), true);
                                                });
                                            }
                                        }
                            
                                        return val;
                                    }
                                }
                            });
                            
                            A.BaseOptionsCellEditor = BaseOptionsCellEditor;