81 lines
1.8 KiB
JavaScript
81 lines
1.8 KiB
JavaScript
|
|
function ListSelect(options) {
|
|
var elem = options.elem;
|
|
|
|
var lastClickedLi = null;
|
|
|
|
elem.onmousedown = function() {
|
|
return false;
|
|
};
|
|
|
|
elem.onclick = function(e) {
|
|
var li = e.target.closest('li');
|
|
if (!li) return;
|
|
|
|
if(e.metaKey || e.ctrlKey) { // для Mac проверяем Cmd, т.к. Ctrl + click там контекстное меню
|
|
toggleSelect(li);
|
|
} else if (e.shiftKey) {
|
|
selectFromLast(li);
|
|
} else {
|
|
selectSingle(li);
|
|
}
|
|
|
|
dispatchEvent();
|
|
|
|
lastClickedLi = li;
|
|
}
|
|
|
|
function deselectAll() {
|
|
[].forEach.call(elem.children, function(child) {
|
|
child.classList.remove('selected')
|
|
});
|
|
}
|
|
|
|
function toggleSelect(li) {
|
|
li.classList.toggle('selected');
|
|
}
|
|
|
|
function selectSingle(li) {
|
|
deselectAll();
|
|
li.classList.add('selected');
|
|
}
|
|
|
|
function selectFromLast(target) {
|
|
var startElem = lastClickedLi || elem.children[0];
|
|
|
|
target.classList.add('selected');
|
|
if (startElem == target) {
|
|
// клик на том же элементе, что и раньше
|
|
// это особый случай
|
|
return;
|
|
}
|
|
|
|
var isLastClickedBefore = startElem.compareDocumentPosition(target) & 4;
|
|
|
|
if (isLastClickedBefore) {
|
|
for(var elem = startElem; elem != target; elem = elem.nextElementSibling) {
|
|
elem.classList.add('selected');
|
|
}
|
|
} else {
|
|
for(var elem = startElem; elem != target; elem = elem.previousElementSibling) {
|
|
elem.classList.add('selected');
|
|
}
|
|
}
|
|
}
|
|
|
|
function dispatchEvent() {
|
|
var widgetEvent = new CustomEvent("select", {
|
|
bubbles: true,
|
|
detail: getSelected()
|
|
});
|
|
elem.dispatchEvent(widgetEvent);
|
|
}
|
|
|
|
function getSelected() {
|
|
return [].map.call(elem.querySelectorAll('.selected'), function(li) {
|
|
return li.innerHTML;
|
|
});
|
|
};
|
|
|
|
this.getSelected = getSelected;
|
|
}
|