Merge branch 'master' of binarity.cz:/opt/git/internal/cms/minicms

This commit is contained in:
Michal Kváček
2018-03-25 11:23:38 +02:00
2 changed files with 167 additions and 0 deletions
@@ -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
};
}