en.javascript.info/2-ui/5-widgets/5-custom-events/2-selectable-list-evented/solution.view/listSelect.js
2015-02-21 00:59:02 +03:00

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;
}