(function (window, document) { 'use strict'; var DropdownGrid = {}; var activeRoot = null; var activeClone = null; var selectionCounter = 1; DropdownGrid.initAll = function () { var grids = document.querySelectorAll('[data-dropdown-grid="true"]'); for (var i = 0; i < grids.length; i++) { DropdownGrid.init(grids[i]); } }; DropdownGrid.init = function (root) { if (!root) return; if (root.getAttribute('data-dropdown-grid-init') === 'true') return; root.setAttribute('data-dropdown-grid-init', 'true'); DropdownGrid.initializeSelectedOrder(root.querySelector('.dropdown-grid-table-box')); var input = root.querySelector('[data-dropdown-search="true"]'); if (input) { input.removeAttribute('readonly'); input.removeAttribute('disabled'); input.addEventListener('mousedown', function (e) { e.stopPropagation(); }); input.addEventListener('click', function (e) { e.stopPropagation(); if (activeRoot !== root) { DropdownGrid.show(root, true); } }); input.addEventListener('focus', function () { if (activeRoot !== root) { DropdownGrid.show(root, true); } }); input.addEventListener('input', function () { if (activeRoot !== root) { DropdownGrid.show(root, false); } DropdownGrid.filter(root, input.value); }); input.addEventListener('keydown', function (e) { if (e.key === 'Escape') { e.preventDefault(); DropdownGrid.hideAll(true); input.blur(); } }); } root.addEventListener('click', function (e) { e.stopPropagation(); var target = e.target; if (target.classList.contains('dropdown-grid-chip-remove')) { e.preventDefault(); DropdownGrid.removeValue(root, target.getAttribute('data-value')); } }); DropdownGrid.updateDisplay(root); DropdownGrid.moveSelectedRowsTop(root.querySelector('.dropdown-grid-table-box')); }; DropdownGrid.show = function (root, clearInput) { var input = root.querySelector('[data-dropdown-search="true"]'); var originalGrid = root.querySelector('.dropdown-grid-table-box'); if (!input || !originalGrid) return; DropdownGrid.hideAll(false); DropdownGrid.moveSelectedRowsTop(originalGrid); activeRoot = root; activeClone = originalGrid.cloneNode(true); activeClone.classList.add('dropdown-grid-floating'); activeClone.setAttribute('data-dropdown-grid-floating', 'true'); activeClone.style.display = 'block'; document.body.appendChild(activeClone); if (clearInput === true) input.value = ''; DropdownGrid.positionClone(root); DropdownGrid.bindCloneEvents(root, activeClone); DropdownGrid.syncCloneFromOriginal(root, activeClone); DropdownGrid.moveSelectedRowsTop(activeClone); DropdownGrid.syncCloneFromOriginal(root, activeClone); DropdownGrid.filter(root, input.value); setTimeout(function () { input.focus(); }, 0); }; DropdownGrid.hideAll = function (restoreText) { var rootToRestore = activeRoot; var clones = document.querySelectorAll('[data-dropdown-grid-floating="true"]'); for (var i = 0; i < clones.length; i++) { if (clones[i].parentNode) clones[i].parentNode.removeChild(clones[i]); } if (restoreText === true && rootToRestore) { DropdownGrid.restoreInputText(rootToRestore); } activeRoot = null; activeClone = null; }; DropdownGrid.positionClone = function (root) { if (!activeClone) return; var input = root.querySelector('[data-dropdown-search="true"]'); if (!input) return; var rect = input.getBoundingClientRect(); activeClone.style.position = 'fixed'; activeClone.style.left = rect.left + 'px'; activeClone.style.top = (rect.bottom + 2) + 'px'; activeClone.style.minWidth = rect.width + 'px'; activeClone.style.zIndex = '999999'; }; DropdownGrid.bindCloneEvents = function (root, clone) { clone.addEventListener('mousedown', function (e) { e.stopPropagation(); }); clone.addEventListener('click', function (e) { e.stopPropagation(); var target = e.target; var row = DropdownGrid.getRow(target); if (target.classList.contains('dropdown-grid-select-all')) { setTimeout(function () { DropdownGrid.cloneSelectAllChanged(root, clone, target.checked); }, 0); return; } if (!row) return; var check = row.querySelector('.dropdown-grid-check'); if (!check) return; if (target !== check) { e.preventDefault(); check.checked = !check.checked; } setTimeout(function () { DropdownGrid.applyValue(root, check.value, check.checked); }, 0); }); }; DropdownGrid.applyValue = function (root, value, checked) { var multiple = root.getAttribute('data-multiple') === 'true'; var originalGrid = root.querySelector('.dropdown-grid-table-box'); if (!originalGrid) return; if (!multiple && checked) { DropdownGrid.setAllChecks(originalGrid, false); if (activeRoot === root && activeClone) { DropdownGrid.setAllChecks(activeClone, false); } } var realCheck = originalGrid.querySelector( '.dropdown-grid-check[value="' + cssEscape(value) + '"]' ); if (realCheck) { realCheck.checked = checked; var realRow = DropdownGrid.getRow(realCheck); if (checked && realRow) { realRow.setAttribute('data-selected-order', selectionCounter++); } else if (realRow) { realRow.removeAttribute('data-selected-order'); } } DropdownGrid.refreshHidden(root); DropdownGrid.updateDisplay(root); DropdownGrid.moveSelectedRowsTop(originalGrid); if (activeRoot === root && activeClone) { DropdownGrid.rebuildClone(root); var input = root.querySelector('[data-dropdown-search="true"]'); if (input) DropdownGrid.filter(root, input.value); } }; DropdownGrid.rebuildClone = function (root) { var originalGrid = root.querySelector('.dropdown-grid-table-box'); if (!originalGrid || !activeClone) return; var oldClone = activeClone; activeClone = originalGrid.cloneNode(true); activeClone.classList.add('dropdown-grid-floating'); activeClone.setAttribute('data-dropdown-grid-floating', 'true'); activeClone.style.display = 'block'; if (oldClone.parentNode) { oldClone.parentNode.replaceChild(activeClone, oldClone); } else { document.body.appendChild(activeClone); } DropdownGrid.positionClone(root); DropdownGrid.bindCloneEvents(root, activeClone); DropdownGrid.syncCloneFromOriginal(root, activeClone); DropdownGrid.moveSelectedRowsTop(activeClone); DropdownGrid.syncCloneFromOriginal(root, activeClone); }; DropdownGrid.setAllChecks = function (container, checked) { if (!container) return; var checks = container.querySelectorAll('.dropdown-grid-check'); for (var i = 0; i < checks.length; i++) { checks[i].checked = checked; var row = DropdownGrid.getRow(checks[i]); if (row) row.removeAttribute('data-selected-order'); } }; DropdownGrid.getRow = function (target) { while (target && target !== document) { if (target.tagName && target.tagName.toLowerCase() === 'tr') return target; target = target.parentNode; } return null; }; DropdownGrid.cloneSelectAllChanged = function (root, clone, checked) { var cloneRows = clone.querySelectorAll('tbody tr'); for (var i = 0; i < cloneRows.length; i++) { if (cloneRows[i].style.display === 'none') continue; var cloneCheck = cloneRows[i].querySelector('.dropdown-grid-check'); if (!cloneCheck) continue; DropdownGrid.applyValue(root, cloneCheck.value, checked); } DropdownGrid.refreshHidden(root); DropdownGrid.updateDisplay(root); DropdownGrid.moveSelectedRowsTop(root.querySelector('.dropdown-grid-table-box')); if (activeClone) { DropdownGrid.rebuildClone(root); } }; DropdownGrid.syncCloneFromOriginal = function (root, clone) { if (!clone) return; var originalChecks = root.querySelectorAll('.dropdown-grid-table-box .dropdown-grid-check'); for (var i = 0; i < originalChecks.length; i++) { var cloneCheck = clone.querySelector( '.dropdown-grid-check[value="' + cssEscape(originalChecks[i].value) + '"]' ); if (!cloneCheck) continue; cloneCheck.checked = originalChecks[i].checked; var originalRow = DropdownGrid.getRow(originalChecks[i]); var cloneRow = DropdownGrid.getRow(cloneCheck); if (originalRow && cloneRow) { var order = originalRow.getAttribute('data-selected-order'); if (order) cloneRow.setAttribute('data-selected-order', order); else cloneRow.removeAttribute('data-selected-order'); } } }; DropdownGrid.initializeSelectedOrder = function (container) { if (!container) return; var checks = container.querySelectorAll('.dropdown-grid-check:checked'); for (var i = 0; i < checks.length; i++) { var row = DropdownGrid.getRow(checks[i]); if (row && !row.getAttribute('data-selected-order')) { row.setAttribute('data-selected-order', selectionCounter++); } } }; DropdownGrid.moveSelectedRowsTop = function (container) { if (!container) return; var tbody = container.querySelector('tbody'); if (!tbody) return; var rows = Array.prototype.slice.call(tbody.querySelectorAll('tr')); var selected = []; var unselected = []; for (var i = 0; i < rows.length; i++) { var check = rows[i].querySelector('.dropdown-grid-check'); if (check && check.checked) selected.push(rows[i]); else unselected.push(rows[i]); } selected.sort(function (a, b) { var ao = parseInt(a.getAttribute('data-selected-order') || '0', 10); var bo = parseInt(b.getAttribute('data-selected-order') || '0', 10); return bo - ao; }); for (var s = 0; s < selected.length; s++) { tbody.appendChild(selected[s]); } for (var u = 0; u < unselected.length; u++) { tbody.appendChild(unselected[u]); } }; DropdownGrid.filter = function (root, value) { value = (value || '').toLowerCase(); var container = activeRoot === root && activeClone ? activeClone : root.querySelector('.dropdown-grid-table-box'); if (!container) return; var rows = container.querySelectorAll('tbody tr'); for (var i = 0; i < rows.length; i++) { var search = rows[i].getAttribute('data-search') || ''; rows[i].style.display = search.indexOf(value) >= 0 ? '' : 'none'; } }; DropdownGrid.refreshHidden = function (root) { var hidden = root.querySelector('input[type="hidden"]'); var checks = root.querySelectorAll('.dropdown-grid-table-box .dropdown-grid-check:checked'); var selected = []; for (var i = 0; i < checks.length; i++) { selected.push(checks[i].value); } if (hidden) hidden.value = selected.join(','); }; DropdownGrid.removeValue = function (root, value) { DropdownGrid.applyValue(root, value, false); }; DropdownGrid.updateDisplay = function (root) { var hidden = root.querySelector('input[type="hidden"]'); var input = root.querySelector('[data-dropdown-search="true"]'); var chips = root.querySelector('.dropdown-grid-chips'); if (!hidden) return; var multiple = root.getAttribute('data-multiple') === 'true'; var values = hidden.value ? hidden.value.split(',') : []; if (!multiple || values.length <= 1) { if (chips) { chips.innerHTML = ''; chips.style.display = 'none'; } if (input && activeRoot !== root) { if (values.length === 1) { var row = root.querySelector( '.dropdown-grid-table-box tr[data-key="' + cssEscape(values[0]) + '"]' ); input.value = row ? row.getAttribute('data-text') || '' : ''; } else { input.value = ''; } } return; } if (input && activeRoot !== root) input.value = ''; if (!chips) return; chips.innerHTML = ''; chips.style.display = ''; for (var i = 0; i < values.length; i++) { var rowChip = root.querySelector( '.dropdown-grid-table-box tr[data-key="' + cssEscape(values[i]) + '"]' ); if (!rowChip) continue; var text = rowChip.getAttribute('data-text') || values[i]; var chip = document.createElement('span'); chip.className = 'dropdown-grid-chip'; var label = document.createElement('span'); label.innerHTML = text; var remove = document.createElement('a'); remove.href = '#'; remove.className = 'dropdown-grid-chip-remove'; remove.setAttribute('data-value', values[i]); remove.innerHTML = ' ×'; chip.appendChild(label); chip.appendChild(remove); chips.appendChild(chip); } }; DropdownGrid.restoreInputText = function (root) { var hidden = root.querySelector('input[type="hidden"]'); var input = root.querySelector('[data-dropdown-search="true"]'); if (!hidden || !input) return; var values = hidden.value ? hidden.value.split(',') : []; if (values.length === 1) { var row = root.querySelector( '.dropdown-grid-table-box tr[data-key="' + cssEscape(values[0]) + '"]' ); input.value = row ? row.getAttribute('data-text') || '' : ''; } else { input.value = ''; } }; function cssEscape(value) { if (window.CSS && CSS.escape) return CSS.escape(value); return String(value).replace(/["\\]/g, '\\$&'); } document.addEventListener('mousedown', function (e) { if (activeRoot && activeRoot.contains(e.target)) return; if (activeClone && activeClone.contains(e.target)) return; DropdownGrid.hideAll(true); }); document.addEventListener('keydown', function (e) { if (e.key === 'Escape') { DropdownGrid.hideAll(true); } }); window.addEventListener('resize', function () { if (activeRoot && activeClone) DropdownGrid.positionClone(activeRoot); }); window.addEventListener('scroll', function () { if (activeRoot && activeClone) DropdownGrid.positionClone(activeRoot); }, true); window.DropdownGrid = DropdownGrid; })(window, document);