/** * Multi-select component * * @param identifier Identifier parameter that makes each instance unique and is used in DOM datasets used by this component. * @param data Data (array of objects) * @param field Field parameter that will be send as list with form * @param itemString String that should be shown as selector in select and a item label in item list */ function MultiSelectComponent(identifier, data, field, itemString) { // Private variables var selectBox, addButton, itemHolder; /** * This is the method that generates template for multiselect component. * This method is easily rewriteable into PHP. * It is necessary to keep html datasets with prefix data-ms- intact for the javascript component to work. * ECMAScript 5 version, does not need any compilers, nor jQuery or other framework. * This method is not required to stay inside the MultiSelectComponent and may be rendered in any way; * * identifier is inherited from the instance creation. * data is inherited from the instance creation. * field is inherited from the instance creation. * itemString is inherited from the instance creation. * */ function createTemplate () { var html = '
'; } /** * This method creates an item list item that works as visual representation of selected values. */ function createItemListItem (value) { return html = ''+itemString(getDataItem(value))+ ' x'+ ''+ ''; } /** * Returns a requested data item that matches (class instance variable field) value of passed value. */ function getDataItem (value) { for(var idx in data) { if(data.hasOwnProperty(idx)){ if(data[idx][field] == value){ return data[idx]; } } } } /** * By selecting an item, that item is removed from list of available items and is added to list of selected items. * If no more items are available for adding, add button and selectbox are disabled and list gets an informative item. */ function selectItem (value) { selectBox.removeChild(selectBox.querySelector('option[value="' + value + '"]')); itemHolder.innerHTML += createItemListItem(value); if(selectBox.children.length === 0) { selectBox.options.add(new Option('no more items to add', 0)); addButton.setAttribute('disabled', 'disabled'); selectBox.setAttribute('disabled', 'disabled'); } } /** * By deselecting (removing) an item, that item is removed from selected list and added again into select box of available items; * If add button was disabled (mostly because of no selectable items in list) it and the selectbox are now re-enabled and informative item is removed. */ function deselectItem (element) { var id = element.getAttribute('data-ms-value'); selectBox.options.add(new Option(itemString(getDataItem(id)), id)); itemHolder.removeChild(element.parentNode); if(addButton.getAttribute('disabled')) { selectBox.options.remove(0); addButton.removeAttribute('disabled'); selectBox.removeAttribute('disabled'); } } /** * Initializes javascript part of the component. */ function init () { // Cached elements only for JS to be a little more optimized. selectBox = document.querySelector('[data-ms-select="'+identifier+'"]'); addButton = document.querySelector('[data-ms-add="'+identifier+'"]'); itemHolder = document.querySelector('[data-ms-list="'+identifier+'"]'); // Add button addButton.addEventListener('click', function() { selectItem(selectBox.value); }); // Remove item button itemHolder.addEventListener('click', function(e) { if(e.target.getAttribute('data-ms-remove')) { deselectItem(e.target); } }) } // Publicly exposed static methods and variables. return { init: init, createTemplate: createTemplate }; }