multiselect component
This commit is contained in:
@@ -0,0 +1,46 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<script src="multiselectcomponent.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div style="width: 50%; float: left;" id="left"></div>
|
||||||
|
<div style="width: 50%; float: right;" id="right"></div>
|
||||||
|
|
||||||
|
<script type="application/javascript">
|
||||||
|
// Sample data.
|
||||||
|
var data1 = [
|
||||||
|
{id: 1, name: 'Peter', surname: 'Hrdlica'},
|
||||||
|
{id: 6, name: 'Vojtěch', surname: 'Hrdlica'},
|
||||||
|
{id: 2, name: 'Michal', surname: 'Kváček'},
|
||||||
|
{id: 19, name: 'Miček', surname: 'Je kokot!'},
|
||||||
|
{id: 13, name: 'Mirek', surname: 'Mráček'},
|
||||||
|
{id: 11, name: 'Naděžda', surname: 'Zímová'}
|
||||||
|
];
|
||||||
|
|
||||||
|
var data2 = [
|
||||||
|
{id: 2, name: 'wanna', surname: 'know'},
|
||||||
|
{id: 6, name: 'Batman', surname: 'insulted'},
|
||||||
|
{id: 58, name: 'scream', surname: 'pushed'},
|
||||||
|
{id: 19, name: 'Mob', surname: 'why'},
|
||||||
|
{id: 63, name: 'eight', surname: 'begin'},
|
||||||
|
{id: 4, name: 'you', surname: 'emotions'}
|
||||||
|
];
|
||||||
|
data1.sort(function(a, b) { return a.id > b.id; }); // Sort by ID, lowest first.
|
||||||
|
data2.sort(function(a, b) { return a.id > b.id; }); // Sort by ID, lowest first.
|
||||||
|
|
||||||
|
// Js component instance
|
||||||
|
var mscL = new MultiSelectComponent('contacts', data1, 'id', function(item) { return item.name + ' ' + item.surname; });
|
||||||
|
var mscR = new MultiSelectComponent('users', data2, 'id', function(item) { return item.name + ' ' + item.surname; });
|
||||||
|
// Generated data added to template
|
||||||
|
var left = document.getElementById('left');
|
||||||
|
var right = document.getElementById('right');
|
||||||
|
left.innerHTML = mscL.createTemplate();
|
||||||
|
right.innerHTML = mscR.createTemplate();
|
||||||
|
|
||||||
|
// Initialization. May be done in more elegant way if the template is created ie. on server.
|
||||||
|
mscL.init();
|
||||||
|
mscR.init();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -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 = '<select data-ms-select="'+identifier+'">';
|
||||||
|
|
||||||
|
for(var idx in data) {
|
||||||
|
if(data.hasOwnProperty(idx)) {
|
||||||
|
html += '<option value="'+data[idx][field]+'">'+itemString(data[idx])+'</value>' //createSelectOption(data[idx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return html += '</select><input type="button" data-ms-add="'+identifier+'" value="add"><div data-ms-list="'+identifier+'"></div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method creates an item list item that works as visual representation of selected values.
|
||||||
|
*/
|
||||||
|
function createItemListItem (value) {
|
||||||
|
return html = '<span>'+itemString(getDataItem(value))+
|
||||||
|
' <span data-ms-remove="'+identifier+'" data-ms-value="'+value+'">x</span>'+
|
||||||
|
'<input style="display: none" type="checkbox" value="'+value+'" name="'+identifier+'[]" checked>'+
|
||||||
|
'</span>';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a requested data item that matches <field> (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
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user