From ddae98d2336ece6191c1ae9290209182d867ab26 Mon Sep 17 00:00:00 2001 From: Peter Hrdlica Date: Sun, 15 Oct 2017 15:54:21 +0200 Subject: [PATCH] multiselect component --- .../multiselectcomponent.html | 46 +++++++ .../multiselectcomponent.js | 121 ++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 public/custom/multiselectcomponent/multiselectcomponent.html create mode 100644 public/custom/multiselectcomponent/multiselectcomponent.js diff --git a/public/custom/multiselectcomponent/multiselectcomponent.html b/public/custom/multiselectcomponent/multiselectcomponent.html new file mode 100644 index 00000000..c49e3bff --- /dev/null +++ b/public/custom/multiselectcomponent/multiselectcomponent.html @@ -0,0 +1,46 @@ + + + + + + +
+ + + + + \ No newline at end of file diff --git a/public/custom/multiselectcomponent/multiselectcomponent.js b/public/custom/multiselectcomponent/multiselectcomponent.js new file mode 100644 index 00000000..65bdd36b --- /dev/null +++ b/public/custom/multiselectcomponent/multiselectcomponent.js @@ -0,0 +1,121 @@ + +/** + * 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 + }; +} \ No newline at end of file