UNPKG

dnd-tree-view

Version:
1,073 lines (1,002 loc) 41.1 kB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.TreeView = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. var objectCreate = Object.create || objectCreatePolyfill var objectKeys = Object.keys || objectKeysPolyfill var bind = Function.prototype.bind || functionBindPolyfill function EventEmitter() { if (!this._events || !Object.prototype.hasOwnProperty.call(this, '_events')) { this._events = objectCreate(null); this._eventsCount = 0; } this._maxListeners = this._maxListeners || undefined; } module.exports = EventEmitter; // Backwards-compat with node 0.10.x EventEmitter.EventEmitter = EventEmitter; EventEmitter.prototype._events = undefined; EventEmitter.prototype._maxListeners = undefined; // By default EventEmitters will print a warning if more than 10 listeners are // added to it. This is a useful default which helps finding memory leaks. var defaultMaxListeners = 10; var hasDefineProperty; try { var o = {}; if (Object.defineProperty) Object.defineProperty(o, 'x', { value: 0 }); hasDefineProperty = o.x === 0; } catch (err) { hasDefineProperty = false } if (hasDefineProperty) { Object.defineProperty(EventEmitter, 'defaultMaxListeners', { enumerable: true, get: function() { return defaultMaxListeners; }, set: function(arg) { // check whether the input is a positive number (whose value is zero or // greater and not a NaN). if (typeof arg !== 'number' || arg < 0 || arg !== arg) throw new TypeError('"defaultMaxListeners" must be a positive number'); defaultMaxListeners = arg; } }); } else { EventEmitter.defaultMaxListeners = defaultMaxListeners; } // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { if (typeof n !== 'number' || n < 0 || isNaN(n)) throw new TypeError('"n" argument must be a positive number'); this._maxListeners = n; return this; }; function $getMaxListeners(that) { if (that._maxListeners === undefined) return EventEmitter.defaultMaxListeners; return that._maxListeners; } EventEmitter.prototype.getMaxListeners = function getMaxListeners() { return $getMaxListeners(this); }; // These standalone emit* functions are used to optimize calling of event // handlers for fast cases because emit() itself often has a variable number of // arguments and can be deoptimized because of that. These functions always have // the same number of arguments and thus do not get deoptimized, so the code // inside them can execute faster. function emitNone(handler, isFn, self) { if (isFn) handler.call(self); else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].call(self); } } function emitOne(handler, isFn, self, arg1) { if (isFn) handler.call(self, arg1); else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].call(self, arg1); } } function emitTwo(handler, isFn, self, arg1, arg2) { if (isFn) handler.call(self, arg1, arg2); else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].call(self, arg1, arg2); } } function emitThree(handler, isFn, self, arg1, arg2, arg3) { if (isFn) handler.call(self, arg1, arg2, arg3); else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].call(self, arg1, arg2, arg3); } } function emitMany(handler, isFn, self, args) { if (isFn) handler.apply(self, args); else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].apply(self, args); } } EventEmitter.prototype.emit = function emit(type) { var er, handler, len, args, i, events; var doError = (type === 'error'); events = this._events; if (events) doError = (doError && events.error == null); else if (!doError) return false; // If there is no 'error' event listener then throw. if (doError) { if (arguments.length > 1) er = arguments[1]; if (er instanceof Error) { throw er; // Unhandled 'error' event } else { // At least give some kind of context to the user var err = new Error('Unhandled "error" event. (' + er + ')'); err.context = er; throw err; } return false; } handler = events[type]; if (!handler) return false; var isFn = typeof handler === 'function'; len = arguments.length; switch (len) { // fast cases case 1: emitNone(handler, isFn, this); break; case 2: emitOne(handler, isFn, this, arguments[1]); break; case 3: emitTwo(handler, isFn, this, arguments[1], arguments[2]); break; case 4: emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); break; // slower default: args = new Array(len - 1); for (i = 1; i < len; i++) args[i - 1] = arguments[i]; emitMany(handler, isFn, this, args); } return true; }; function _addListener(target, type, listener, prepend) { var m; var events; var existing; if (typeof listener !== 'function') throw new TypeError('"listener" argument must be a function'); events = target._events; if (!events) { events = target._events = objectCreate(null); target._eventsCount = 0; } else { // To avoid recursion in the case that type === "newListener"! Before // adding it to the listeners, first emit "newListener". if (events.newListener) { target.emit('newListener', type, listener.listener ? listener.listener : listener); // Re-assign `events` because a newListener handler could have caused the // this._events to be assigned to a new object events = target._events; } existing = events[type]; } if (!existing) { // Optimize the case of one listener. Don't need the extra array object. existing = events[type] = listener; ++target._eventsCount; } else { if (typeof existing === 'function') { // Adding the second element, need to change to array. existing = events[type] = prepend ? [listener, existing] : [existing, listener]; } else { // If we've already got an array, just append. if (prepend) { existing.unshift(listener); } else { existing.push(listener); } } // Check for listener leak if (!existing.warned) { m = $getMaxListeners(target); if (m && m > 0 && existing.length > m) { existing.warned = true; var w = new Error('Possible EventEmitter memory leak detected. ' + existing.length + ' "' + String(type) + '" listeners ' + 'added. Use emitter.setMaxListeners() to ' + 'increase limit.'); w.name = 'MaxListenersExceededWarning'; w.emitter = target; w.type = type; w.count = existing.length; if (typeof console === 'object' && console.warn) { console.warn('%s: %s', w.name, w.message); } } } } return target; } EventEmitter.prototype.addListener = function addListener(type, listener) { return _addListener(this, type, listener, false); }; EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.prependListener = function prependListener(type, listener) { return _addListener(this, type, listener, true); }; function onceWrapper() { if (!this.fired) { this.target.removeListener(this.type, this.wrapFn); this.fired = true; switch (arguments.length) { case 0: return this.listener.call(this.target); case 1: return this.listener.call(this.target, arguments[0]); case 2: return this.listener.call(this.target, arguments[0], arguments[1]); case 3: return this.listener.call(this.target, arguments[0], arguments[1], arguments[2]); default: var args = new Array(arguments.length); for (var i = 0; i < args.length; ++i) args[i] = arguments[i]; this.listener.apply(this.target, args); } } } function _onceWrap(target, type, listener) { var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; var wrapped = bind.call(onceWrapper, state); wrapped.listener = listener; state.wrapFn = wrapped; return wrapped; } EventEmitter.prototype.once = function once(type, listener) { if (typeof listener !== 'function') throw new TypeError('"listener" argument must be a function'); this.on(type, _onceWrap(this, type, listener)); return this; }; EventEmitter.prototype.prependOnceListener = function prependOnceListener(type, listener) { if (typeof listener !== 'function') throw new TypeError('"listener" argument must be a function'); this.prependListener(type, _onceWrap(this, type, listener)); return this; }; // Emits a 'removeListener' event if and only if the listener was removed. EventEmitter.prototype.removeListener = function removeListener(type, listener) { var list, events, position, i, originalListener; if (typeof listener !== 'function') throw new TypeError('"listener" argument must be a function'); events = this._events; if (!events) return this; list = events[type]; if (!list) return this; if (list === listener || list.listener === listener) { if (--this._eventsCount === 0) this._events = objectCreate(null); else { delete events[type]; if (events.removeListener) this.emit('removeListener', type, list.listener || listener); } } else if (typeof list !== 'function') { position = -1; for (i = list.length - 1; i >= 0; i--) { if (list[i] === listener || list[i].listener === listener) { originalListener = list[i].listener; position = i; break; } } if (position < 0) return this; if (position === 0) list.shift(); else spliceOne(list, position); if (list.length === 1) events[type] = list[0]; if (events.removeListener) this.emit('removeListener', type, originalListener || listener); } return this; }; EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) { var listeners, events, i; events = this._events; if (!events) return this; // not listening for removeListener, no need to emit if (!events.removeListener) { if (arguments.length === 0) { this._events = objectCreate(null); this._eventsCount = 0; } else if (events[type]) { if (--this._eventsCount === 0) this._events = objectCreate(null); else delete events[type]; } return this; } // emit removeListener for all listeners on all events if (arguments.length === 0) { var keys = objectKeys(events); var key; for (i = 0; i < keys.length; ++i) { key = keys[i]; if (key === 'removeListener') continue; this.removeAllListeners(key); } this.removeAllListeners('removeListener'); this._events = objectCreate(null); this._eventsCount = 0; return this; } listeners = events[type]; if (typeof listeners === 'function') { this.removeListener(type, listeners); } else if (listeners) { // LIFO order for (i = listeners.length - 1; i >= 0; i--) { this.removeListener(type, listeners[i]); } } return this; }; function _listeners(target, type, unwrap) { var events = target._events; if (!events) return []; var evlistener = events[type]; if (!evlistener) return []; if (typeof evlistener === 'function') return unwrap ? [evlistener.listener || evlistener] : [evlistener]; return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); } EventEmitter.prototype.listeners = function listeners(type) { return _listeners(this, type, true); }; EventEmitter.prototype.rawListeners = function rawListeners(type) { return _listeners(this, type, false); }; EventEmitter.listenerCount = function(emitter, type) { if (typeof emitter.listenerCount === 'function') { return emitter.listenerCount(type); } else { return listenerCount.call(emitter, type); } }; EventEmitter.prototype.listenerCount = listenerCount; function listenerCount(type) { var events = this._events; if (events) { var evlistener = events[type]; if (typeof evlistener === 'function') { return 1; } else if (evlistener) { return evlistener.length; } } return 0; } EventEmitter.prototype.eventNames = function eventNames() { return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; }; // About 1.5x faster than the two-arg version of Array#splice(). function spliceOne(list, index) { for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) list[i] = list[k]; list.pop(); } function arrayClone(arr, n) { var copy = new Array(n); for (var i = 0; i < n; ++i) copy[i] = arr[i]; return copy; } function unwrapListeners(arr) { var ret = new Array(arr.length); for (var i = 0; i < ret.length; ++i) { ret[i] = arr[i].listener || arr[i]; } return ret; } function objectCreatePolyfill(proto) { var F = function() {}; F.prototype = proto; return new F; } function objectKeysPolyfill(obj) { var keys = []; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { keys.push(k); } return k; } function functionBindPolyfill(context) { var fn = this; return function () { return fn.apply(context, arguments); }; } },{}],2:[function(require,module,exports){ "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var events_1 = require("events"); var TreeView = /** @class */ (function (_super) { __extends(TreeView, _super); function TreeView(container, options) { var _this = _super.call(this) || this; _this.onClick = function (event) { // Toggle groups var element = event.target; if (element.className === "toggle") { if (element.parentElement.tagName === "LI" && element.parentElement.classList.contains("group")) { element.parentElement.classList.toggle("collapsed"); return; } } // Update selection if (element.tagName === "BUTTON" || element.tagName === "INPUT" || element.tagName === "SELECT") return; if (_this.updateSelection(event)) _this.emit("selectionChange"); }; _this.onDoubleClick = function (event) { if (_this.selectedNodes.length !== 1) return; var element = event.target; if (element.tagName === "BUTTON" || element.tagName === "INPUT" || element.tagName === "SELECT") return; if (element.className === "toggle") return; _this.emit("activate"); }; _this.onKeyDown = function (event) { if (document.activeElement !== _this.treeRoot) return; if (_this.firstSelectedNode == null) { // TODO: Remove once we have this.focusedNode if (event.keyCode === 40) { _this.addToSelection(_this.treeRoot.firstElementChild); _this.emit("selectionChange"); event.preventDefault(); } return; } switch (event.keyCode) { case 38: // up case 40: // down _this.moveVertically(event.keyCode === 40 ? 1 : -1); event.preventDefault(); break; case 37: // left case 39: // right _this.moveHorizontally(event.keyCode === 39 ? 1 : -1); event.preventDefault(); break; case 13: if (_this.selectedNodes.length !== 1) return; _this.emit("activate"); event.preventDefault(); break; } }; _this.moveHorizontally = function (offset) { // TODO: this.focusedNode; var node = _this.firstSelectedNode; if (offset === -1) { if (!node.classList.contains("group") || node.classList.contains("collapsed")) { if (!node.parentElement.classList.contains("children")) return; node = node.parentElement.previousElementSibling; } else if (node.classList.contains("group")) { node.classList.add("collapsed"); } } else { if (node.classList.contains("group")) { if (node.classList.contains("collapsed")) node.classList.remove("collapsed"); else node = node.nextSibling.firstChild; } } if (node == null) return; _this.clearSelection(); _this.addToSelection(node); _this.scrollIntoView(node); _this.emit("selectionChange"); }; _this.onDragStart = function (event) { var element = event.target; if (element.tagName !== "LI") return false; if (!element.classList.contains("item") && !element.classList.contains("group")) return false; if (_this.selectedNodes.indexOf(element) === -1) { _this.clearSelection(); _this.addToSelection(element); _this.emit("selectionChange"); } if (_this.dragStartCallback != null && !_this.dragStartCallback(event, element)) return false; _this.isDraggingNodes = true; return true; }; _this.onDragEnd = function (event) { _this.previousDropLocation = null; _this.isDraggingNodes = false; }; _this.onDragOver = function (event) { var dropLocation = _this.getDropLocation(event); // Prevent dropping onto null if (dropLocation == null) return false; // If we're dragging nodes from the current tree view // Prevent dropping into descendant if (_this.isDraggingNodes) { if (dropLocation.where === "inside" && _this.selectedNodes.indexOf(dropLocation.target) !== -1) return false; for (var _i = 0, _a = _this.selectedNodes; _i < _a.length; _i++) { var selectedNode = _a[_i]; if (selectedNode.classList.contains("group") && selectedNode.nextSibling.contains(dropLocation.target)) return false; } } _this.hasDraggedOverAfterLeaving = true; if (_this.previousDropLocation == null || _this.previousDropLocation.where != dropLocation.where || _this.previousDropLocation.target != dropLocation.target) { _this.clearDropClasses(); dropLocation.target.classList.add("drop-" + dropLocation.where); } _this.previousDropLocation = dropLocation; event.preventDefault(); }; _this.onDragLeave = function (event) { _this.hasDraggedOverAfterLeaving = false; setTimeout(function () { if (!_this.hasDraggedOverAfterLeaving) _this.clearDropClasses(); }, 300); }; _this.onDrop = function (event) { _this.previousDropLocation = null; event.preventDefault(); var dropLocation = _this.getDropLocation(event); if (dropLocation == null) return; _this.clearDropClasses(); if (!_this.isDraggingNodes) { _this.dropCallback(event, dropLocation, null); return false; } var children = _this.selectedNodes[0].parentElement.children; var orderedNodes = []; for (var i = 0; i < children.length; i++) { var child = children[i]; if (_this.selectedNodes.indexOf(child) !== -1) orderedNodes.push(child); } var reparent = (_this.dropCallback != null) ? _this.dropCallback(event, dropLocation, orderedNodes) : true; if (!reparent) return; var newParent; var referenceElt; switch (dropLocation.where) { case "inside": if (!dropLocation.target.classList.contains("group")) return; newParent = dropLocation.target.nextSibling; referenceElt = null; break; case "below": newParent = dropLocation.target.parentElement; referenceElt = dropLocation.target.nextSibling; if (referenceElt != null && referenceElt.tagName === "OL") referenceElt = referenceElt.nextSibling; break; case "above": newParent = dropLocation.target.parentElement; referenceElt = dropLocation.target; break; } var draggedChildren; for (var _i = 0, orderedNodes_1 = orderedNodes; _i < orderedNodes_1.length; _i++) { var selectedNode = orderedNodes_1[_i]; if (selectedNode.classList.contains("group")) { draggedChildren = selectedNode.nextSibling; draggedChildren.parentElement.removeChild(draggedChildren); } if (referenceElt === selectedNode) { referenceElt = selectedNode.nextSibling; } selectedNode.parentElement.removeChild(selectedNode); newParent.insertBefore(selectedNode, referenceElt); referenceElt = selectedNode.nextSibling; if (draggedChildren != null) { newParent.insertBefore(draggedChildren, referenceElt); referenceElt = draggedChildren.nextSibling; } } }; if (options == null) options = {}; _this.multipleSelection = (options.multipleSelection != null) ? options.multipleSelection : true; _this.dragStartCallback = options.dragStartCallback; _this.dropCallback = options.dropCallback; _this.treeRoot = document.createElement("ol"); _this.treeRoot.tabIndex = 0; _this.treeRoot.classList.add("tree"); container.appendChild(_this.treeRoot); _this.selectedNodes = []; _this.firstSelectedNode = null; _this.treeRoot.addEventListener("click", _this.onClick); _this.treeRoot.addEventListener("dblclick", _this.onDoubleClick); _this.treeRoot.addEventListener("keydown", _this.onKeyDown); container.addEventListener("keydown", function (event) { if (event.keyCode === 37 || event.keyCode === 39) event.preventDefault(); }); if (_this.dragStartCallback != null) { _this.treeRoot.addEventListener("dragstart", _this.onDragStart); _this.treeRoot.addEventListener("dragend", _this.onDragEnd); } if (_this.dropCallback != null) { _this.treeRoot.addEventListener("dragover", _this.onDragOver); _this.treeRoot.addEventListener("dragleave", _this.onDragLeave); _this.treeRoot.addEventListener("drop", _this.onDrop); } return _this; } TreeView.prototype.clearSelection = function () { for (var _i = 0, _a = this.selectedNodes; _i < _a.length; _i++) { var selectedNode = _a[_i]; selectedNode.classList.remove("selected"); } this.selectedNodes.length = 0; this.firstSelectedNode = null; }; TreeView.prototype.addToSelection = function (element) { if (this.selectedNodes.indexOf(element) !== -1) return; this.selectedNodes.push(element); element.classList.add("selected"); if (this.selectedNodes.length === 1) this.firstSelectedNode = element; }; TreeView.prototype.scrollIntoView = function (element) { var ancestor = element.parentElement; while (ancestor != null && ancestor.className === "children") { ancestor.previousElementSibling.classList.remove("collapsed"); ancestor = ancestor.parentElement; } var elementRect = element.getBoundingClientRect(); var containerRect = this.treeRoot.parentElement.getBoundingClientRect(); if (elementRect.top < containerRect.top) element.scrollIntoView(true); else if (elementRect.bottom > containerRect.bottom) element.scrollIntoView(false); }; TreeView.prototype.clear = function () { this.treeRoot.innerHTML = ""; this.selectedNodes.length = 0; this.firstSelectedNode = null; this.hasDraggedOverAfterLeaving = false; this.isDraggingNodes = false; }; TreeView.prototype.append = function (element, type, parentGroupElement) { if (type !== "item" && type !== "group") throw new Error("Invalid type"); var childrenElt; var siblingsElt; if (parentGroupElement != null) { if (parentGroupElement.tagName !== "LI" || !parentGroupElement.classList.contains("group")) throw new Error("Invalid parent group"); siblingsElt = parentGroupElement.nextSibling; } else { siblingsElt = this.treeRoot; } if (!element.classList.contains(type)) { element.classList.add(type); if (this.dragStartCallback != null) element.draggable = true; if (type === "group") { var toggleElt = document.createElement("div"); toggleElt.classList.add("toggle"); element.insertBefore(toggleElt, element.firstChild); childrenElt = document.createElement("ol"); childrenElt.classList.add("children"); } } else if (type === "group") { childrenElt = element.nextSibling; } siblingsElt.appendChild(element); if (childrenElt != null) siblingsElt.appendChild(childrenElt); return element; }; TreeView.prototype.insertBefore = function (element, type, referenceElement) { if (type !== "item" && type !== "group") throw new Error("Invalid type"); if (referenceElement == null) throw new Error("A reference element is required"); if (referenceElement.tagName !== "LI") throw new Error("Invalid reference element"); var childrenElt; if (!element.classList.contains(type)) { element.classList.add(type); if (this.dragStartCallback != null) element.draggable = true; if (type === "group") { var toggleElt = document.createElement("div"); toggleElt.classList.add("toggle"); element.insertBefore(toggleElt, element.firstChild); childrenElt = document.createElement("ol"); childrenElt.classList.add("children"); } } else if (type === "group") { childrenElt = element.nextSibling; } referenceElement.parentElement.insertBefore(element, referenceElement); if (childrenElt != null) referenceElement.parentElement.insertBefore(childrenElt, element.nextSibling); return element; }; TreeView.prototype.insertAt = function (element, type, index, parentElement) { var referenceElt; if (index != null) { referenceElt = (parentElement != null) ? parentElement.nextSibling.querySelector(":scope > li:nth-of-type(" + (index + 1) + ")") : this.treeRoot.querySelector(":scope > li:nth-of-type(" + (index + 1) + ")"); } if (referenceElt != null) this.insertBefore(element, type, referenceElt); else this.append(element, type, parentElement); }; TreeView.prototype.remove = function (element) { var selectedIndex = this.selectedNodes.indexOf(element); if (selectedIndex !== -1) { element.classList.remove("selected"); this.selectedNodes.splice(selectedIndex, 1); } if (this.firstSelectedNode === element) this.firstSelectedNode = this.selectedNodes[0]; if (element.classList.contains("group")) { var childrenElement = element.nextSibling; var removedSelectedNodes = []; for (var _i = 0, _a = this.selectedNodes; _i < _a.length; _i++) { var selectedNode = _a[_i]; if (childrenElement.contains(selectedNode)) { removedSelectedNodes.push(selectedNode); } } for (var _b = 0, removedSelectedNodes_1 = removedSelectedNodes; _b < removedSelectedNodes_1.length; _b++) { var removedSelectedNode = removedSelectedNodes_1[_b]; removedSelectedNode.classList.remove("selected"); this.selectedNodes.splice(this.selectedNodes.indexOf(removedSelectedNode), 1); if (this.firstSelectedNode === removedSelectedNode) this.firstSelectedNode = this.selectedNodes[0]; } element.parentElement.removeChild(childrenElement); } element.parentElement.removeChild(element); }; // Returns whether the selection changed TreeView.prototype.updateSelection = function (event) { var selectionChanged = false; if ((!this.multipleSelection || (!event.shiftKey && !event.ctrlKey)) && this.selectedNodes.length > 0) { this.clearSelection(); selectionChanged = true; } var ancestorElement = event.target; while (ancestorElement.tagName !== "LI" || (!ancestorElement.classList.contains("item") && !ancestorElement.classList.contains("group"))) { if (ancestorElement === this.treeRoot) return selectionChanged; ancestorElement = ancestorElement.parentElement; } var element = ancestorElement; if (this.selectedNodes.length > 0 && this.selectedNodes[0].parentElement !== element.parentElement) { return selectionChanged; } if (this.multipleSelection && event.shiftKey && this.selectedNodes.length > 0) { var startElement = this.firstSelectedNode; var elements = []; var inside = false; for (var i = 0; i < element.parentElement.children.length; i++) { var child = element.parentElement.children[i]; if (child === startElement || child === element) { if (inside || startElement === element) { elements.push(child); break; } inside = true; } if (inside && child.tagName === "LI") elements.push(child); } this.clearSelection(); this.selectedNodes = elements; this.firstSelectedNode = startElement; for (var _i = 0, _a = this.selectedNodes; _i < _a.length; _i++) { var selectedNode = _a[_i]; selectedNode.classList.add("selected"); } return true; } var index; if (event.ctrlKey && (index = this.selectedNodes.indexOf(element)) !== -1) { this.selectedNodes.splice(index, 1); element.classList.remove("selected"); if (this.firstSelectedNode === element) { this.firstSelectedNode = this.selectedNodes[0]; } return true; } this.addToSelection(element); return true; }; TreeView.prototype.moveVertically = function (offset) { // TODO: this.focusedNode; var node = this.firstSelectedNode; if (offset === -1) { if (node.previousElementSibling != null) { var target = node.previousElementSibling; while (target.classList.contains("children")) { if (!target.previousElementSibling.classList.contains("collapsed") && target.childElementCount > 0) target = target.lastElementChild; else target = target.previousElementSibling; } node = target; } else if (node.parentElement.classList.contains("children")) node = node.parentElement.previousElementSibling; else return; } else { var walkUp = false; if (node.classList.contains("group")) { if (!node.classList.contains("collapsed") && node.nextElementSibling.childElementCount > 0) node = node.nextElementSibling.firstElementChild; else if (node.nextElementSibling.nextElementSibling != null) node = node.nextElementSibling.nextElementSibling; else walkUp = true; } else { if (node.nextElementSibling != null) node = node.nextElementSibling; else walkUp = true; } if (walkUp) { if (node.parentElement.classList.contains("children")) { var target = node.parentElement; while (target.nextElementSibling == null) { target = target.parentElement; if (!target.classList.contains("children")) return; } node = target.nextElementSibling; } else return; } } if (node == null) return; this.clearSelection(); this.addToSelection(node); this.scrollIntoView(node); this.emit("selectionChange"); }; ; TreeView.prototype.getDropLocation = function (event) { var element = event.target; if (element.tagName === "OL" && element.classList.contains("children")) { element = element.parentElement; } if (element === this.treeRoot) { element = element.lastChild; if (element == null) return { target: this.treeRoot, where: "inside" }; if (element.tagName === "OL") element = element.previousSibling; return { target: element, where: "below" }; } while (element.tagName !== "LI" || (!element.classList.contains("item") && !element.classList.contains("group"))) { if (element === this.treeRoot) return null; element = element.parentElement; } var where = this.getInsertionPoint(element, event.pageY); if (where === "below") { if (element.classList.contains("item") && element.nextSibling != null && element.nextSibling.tagName === "LI") { element = element.nextSibling; where = "above"; } else if (element.classList.contains("group") && element.nextSibling.nextSibling != null && element.nextSibling.nextSibling.tagName === "LI") { element = element.nextSibling.nextSibling; where = "above"; } } return { target: element, where: where }; }; TreeView.prototype.getInsertionPoint = function (element, y) { var rect = element.getBoundingClientRect(); var offset = y - rect.top; if (offset < rect.height / 4) return "above"; if (offset > rect.height * 3 / 4) return (element.classList.contains("group") && element.nextSibling.childElementCount > 0) ? "inside" : "below"; return element.classList.contains("item") ? "below" : "inside"; }; TreeView.prototype.clearDropClasses = function () { var dropAbove = this.treeRoot.querySelector(".drop-above"); if (dropAbove != null) dropAbove.classList.remove("drop-above"); var dropInside = this.treeRoot.querySelector(".drop-inside"); if (dropInside != null) dropInside.classList.remove("drop-inside"); var dropBelow = this.treeRoot.querySelector(".drop-below"); if (dropBelow != null) dropBelow.classList.remove("drop-below"); // For the rare case where we're dropping a foreign item into an empty tree view this.treeRoot.classList.remove("drop-inside"); }; return TreeView; }(events_1.EventEmitter)); module.exports = TreeView; },{"events":1}]},{},[2])(2) });