xl-infinite-tree
Version:
A browser-ready tree library that can efficiently display a large amount of data using infinite scrolling.
1,497 lines (1,211 loc) • 136 kB
JavaScript
/*! xl-infinite-tree v1.14.14 | (c) 2020 Cheton Wu <cheton@gmail.com> | MIT | https://github.com/cheton/infinite-tree */
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["InfiniteTree"] = factory();
else
root["InfiniteTree"] = factory();
})(typeof self !== 'undefined' ? self : this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 7);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
// 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 R = typeof Reflect === 'object' ? Reflect : null
var ReflectApply = R && typeof R.apply === 'function'
? R.apply
: function ReflectApply(target, receiver, args) {
return Function.prototype.apply.call(target, receiver, args);
}
var ReflectOwnKeys
if (R && typeof R.ownKeys === 'function') {
ReflectOwnKeys = R.ownKeys
} else if (Object.getOwnPropertySymbols) {
ReflectOwnKeys = function ReflectOwnKeys(target) {
return Object.getOwnPropertyNames(target)
.concat(Object.getOwnPropertySymbols(target));
};
} else {
ReflectOwnKeys = function ReflectOwnKeys(target) {
return Object.getOwnPropertyNames(target);
};
}
function ProcessEmitWarning(warning) {
if (console && console.warn) console.warn(warning);
}
var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {
return value !== value;
}
function EventEmitter() {
EventEmitter.init.call(this);
}
module.exports = EventEmitter;
// Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter;
EventEmitter.prototype._events = undefined;
EventEmitter.prototype._eventsCount = 0;
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;
function checkListener(listener) {
if (typeof listener !== 'function') {
throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
}
}
Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
enumerable: true,
get: function() {
return defaultMaxListeners;
},
set: function(arg) {
if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.');
}
defaultMaxListeners = arg;
}
});
EventEmitter.init = function() {
if (this._events === undefined ||
this._events === Object.getPrototypeOf(this)._events) {
this._events = Object.create(null);
this._eventsCount = 0;
}
this._maxListeners = this._maxListeners || undefined;
};
// 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 || NumberIsNaN(n)) {
throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.');
}
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);
};
EventEmitter.prototype.emit = function emit(type) {
var args = [];
for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);
var doError = (type === 'error');
var events = this._events;
if (events !== undefined)
doError = (doError && events.error === undefined);
else if (!doError)
return false;
// If there is no 'error' event listener then throw.
if (doError) {
var er;
if (args.length > 0)
er = args[0];
if (er instanceof Error) {
// Note: The comments on the `throw` lines are intentional, they show
// up in Node's output if this results in an unhandled exception.
throw er; // Unhandled 'error' event
}
// At least give some kind of context to the user
var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));
err.context = er;
throw err; // Unhandled 'error' event
}
var handler = events[type];
if (handler === undefined)
return false;
if (typeof handler === 'function') {
ReflectApply(handler, this, args);
} else {
var len = handler.length;
var listeners = arrayClone(handler, len);
for (var i = 0; i < len; ++i)
ReflectApply(listeners[i], this, args);
}
return true;
};
function _addListener(target, type, listener, prepend) {
var m;
var events;
var existing;
checkListener(listener);
events = target._events;
if (events === undefined) {
events = target._events = Object.create(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 !== undefined) {
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 === undefined) {
// 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];
// If we've already got an array, just append.
} else if (prepend) {
existing.unshift(listener);
} else {
existing.push(listener);
}
// Check for listener leak
m = _getMaxListeners(target);
if (m > 0 && existing.length > m && !existing.warned) {
existing.warned = true;
// No error code for this since it is a Warning
// eslint-disable-next-line no-restricted-syntax
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;
ProcessEmitWarning(w);
}
}
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;
if (arguments.length === 0)
return this.listener.call(this.target);
return this.listener.apply(this.target, arguments);
}
}
function _onceWrap(target, type, listener) {
var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
var wrapped = onceWrapper.bind(state);
wrapped.listener = listener;
state.wrapFn = wrapped;
return wrapped;
}
EventEmitter.prototype.once = function once(type, listener) {
checkListener(listener);
this.on(type, _onceWrap(this, type, listener));
return this;
};
EventEmitter.prototype.prependOnceListener =
function prependOnceListener(type, listener) {
checkListener(listener);
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;
checkListener(listener);
events = this._events;
if (events === undefined)
return this;
list = events[type];
if (list === undefined)
return this;
if (list === listener || list.listener === listener) {
if (--this._eventsCount === 0)
this._events = Object.create(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 !== undefined)
this.emit('removeListener', type, originalListener || listener);
}
return this;
};
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
EventEmitter.prototype.removeAllListeners =
function removeAllListeners(type) {
var listeners, events, i;
events = this._events;
if (events === undefined)
return this;
// not listening for removeListener, no need to emit
if (events.removeListener === undefined) {
if (arguments.length === 0) {
this._events = Object.create(null);
this._eventsCount = 0;
} else if (events[type] !== undefined) {
if (--this._eventsCount === 0)
this._events = Object.create(null);
else
delete events[type];
}
return this;
}
// emit removeListener for all listeners on all events
if (arguments.length === 0) {
var keys = Object.keys(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 = Object.create(null);
this._eventsCount = 0;
return this;
}
listeners = events[type];
if (typeof listeners === 'function') {
this.removeListener(type, listeners);
} else if (listeners !== undefined) {
// 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 === undefined)
return [];
var evlistener = events[type];
if (evlistener === undefined)
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 !== undefined) {
var evlistener = events[type];
if (typeof evlistener === 'function') {
return 1;
} else if (evlistener !== undefined) {
return evlistener.length;
}
}
return 0;
}
EventEmitter.prototype.eventNames = function eventNames() {
return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
};
function arrayClone(arr, n) {
var copy = new Array(n);
for (var i = 0; i < n; ++i)
copy[i] = arr[i];
return copy;
}
function spliceOne(list, index) {
for (; index + 1 < list.length; index++)
list[index] = list[index + 1];
list.pop();
}
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;
}
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
Copyright (c) 2017 Jed Watson.
Licensed under the MIT License (MIT), see
http://jedwatson.github.io/classnames
*/
/* global define */
(function () {
'use strict';
var hasOwn = {}.hasOwnProperty;
function classNames () {
var classes = [];
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
if (!arg) continue;
var argType = typeof arg;
if (argType === 'string' || argType === 'number') {
classes.push(arg);
} else if (Array.isArray(arg) && arg.length) {
var inner = classNames.apply(null, arg);
if (inner) {
classes.push(inner);
}
} else if (argType === 'object') {
for (var key in arg) {
if (hasOwn.call(arg, key) && arg[key]) {
classes.push(key);
}
}
}
}
return classes.join(' ');
}
if (typeof module !== 'undefined' && module.exports) {
classNames.default = classNames;
module.exports = classNames;
} else if (true) {
// register as 'classnames', consistent with npm package name
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function () {
return classNames;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
} else {
window.classNames = classNames;
}
}());
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
/* eslint no-restricted-syntax: 0 */
var extend = function extend(target) {
for (var _len = arguments.length, sources = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
sources[_key - 1] = arguments[_key];
}
if (target === undefined || target === null) {
throw new TypeError('Cannot convert undefined or null to object');
}
var output = Object(target);
for (var index = 0; index < sources.length; index++) {
var source = sources[index];
if (source !== undefined && source !== null) {
for (var key in source) {
if (source.hasOwnProperty(key)) {
output[key] = source[key];
}
}
}
}
return output;
};
exports['default'] = extend;
/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
var _extend = __webpack_require__(2);
var _extend2 = _interopRequireDefault(_extend);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Node = function () {
function Node(node) {
_classCallCheck(this, Node);
this.id = null;
this.parent = null;
this.children = [];
this.state = {};
(0, _extend2['default'])(this, node);
this.children = this.children || [];
}
// Returns a boolean value indicating whether a node is a descendant of a given node or not.
// @param {object} node Specifies the node that may be contained by (a descendant of) a specified node.
// @return {boolean} Returns true if a node is a descendant of a specified node, otherwise false. A descendant can be a child, grandchild, great-grandchild, and so on.
Node.prototype.contains = function contains(node) {
while (node instanceof Node && node !== this) {
if (node.parent === this) {
return true;
}
node = node.parent;
}
return false;
};
// Gets a child node at the specified index.
// @param {number} The index of the child node.
// @return {object} Returns an object that defines the node, null otherwise.
Node.prototype.getChildAt = function getChildAt(index) {
var node = null;
if (this.children.length > 0 && index >= 0 && index < this.children.length) {
node = this.children[index];
}
return node;
};
// Gets the child nodes.
// @return {array} Returns an array of objects that define the nodes.
Node.prototype.getChildren = function getChildren() {
return this.children;
};
// Gets the first child node.
// @return {object} Returns an object that defines the node, null otherwise.
Node.prototype.getFirstChild = function getFirstChild() {
var node = null;
if (this.children.length > 0) {
node = this.children[0];
}
return node;
};
// Gets the last child node.
// @return {object} Returns an object that defines the node, null otherwise.
Node.prototype.getLastChild = function getLastChild() {
var node = null;
if (this.children.length > 0) {
node = this.children[this.children.length - 1];
}
return node;
};
// Gets the next sibling node.
// @return {object} Returns an object that defines the node, null otherwise.
Node.prototype.getNextSibling = function getNextSibling() {
var node = null;
if (this.parent) {
var index = this.parent.children.indexOf(this);
if (index >= 0 && index < this.parent.children.length - 1) {
node = this.parent.children[index + 1];
}
}
return node;
};
// Gets the parent node.
// @return {object} Returns an object that defines the node, null otherwise.
Node.prototype.getParent = function getParent() {
return this.parent;
};
// Gets the previous sibling node.
// @return {object} Returns an object that defines the node, null otherwise.
Node.prototype.getPreviousSibling = function getPreviousSibling() {
var node = null;
if (this.parent) {
var index = this.parent.children.indexOf(this);
if (index > 0 && index < this.parent.children.length) {
node = this.parent.children[index - 1];
}
}
return node;
};
// Checks whether this node has children.
// @return {boolean} Returns true if the node has children, false otherwise.
Node.prototype.hasChildren = function hasChildren() {
return this.children.length > 0;
};
// Checks whether this node is the last child of its parent.
// @return {boolean} Returns true if the node is the last child of its parent, false otherwise.
Node.prototype.isLastChild = function isLastChild() {
var hasNextSibling = this.getNextSibling();
return !hasNextSibling;
};
return Node;
}();
exports['default'] = Node;
/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
var ensureArray = function ensureArray() {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
if (args.length === 0 || args[0] === undefined || args[0] === null) {
return [];
}
if (args.length === 1) {
return [].concat(args[0]);
}
return [].concat(args);
};
exports["default"] = ensureArray;
/***/ }),
/* 5 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
var getElementStyle = function getElementStyle(el, prop) {
return window.getComputedStyle ? window.getComputedStyle(el)[prop] : el.currentStyle[prop];
};
var preventDefault = function preventDefault(e) {
if (typeof e.preventDefault !== 'undefined') {
e.preventDefault();
} else {
e.returnValue = false;
}
};
var stopPropagation = function stopPropagation(e) {
if (typeof e.stopPropagation !== 'undefined') {
e.stopPropagation();
} else {
e.cancelBubble = true;
}
};
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Compatibility
var addEventListener = function addEventListener(target, type, listener) {
if (target.addEventListener) {
// Standard
target.addEventListener(type, listener, false);
} else if (target.attachEvent) {
// IE8
// In Internet Explorer versions before IE 9, you have to use attachEvent rather than the standard addEventListener.
target.attachEvent('on' + type, listener);
}
};
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
var removeEventListener = function removeEventListener(target, type, listener) {
if (target.removeEventListener) {
// Standard
target.removeEventListener(type, listener, false);
} else if (target.detachEvent) {
// IE8
// In Internet Explorer versions before IE 9, you have to use detachEvent rather than the standard removeEventListener.
target.detachEvent('on' + type, listener);
}
};
exports.getElementStyle = getElementStyle;
exports.preventDefault = preventDefault;
exports.stopPropagation = stopPropagation;
exports.addEventListener = addEventListener;
exports.removeEventListener = removeEventListener;
/***/ }),
/* 6 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/*!
* escape-html
* Copyright(c) 2012-2013 TJ Holowaychuk
* Copyright(c) 2015 Andreas Lubbe
* Copyright(c) 2015 Tiancheng "Timothy" Gu
* MIT Licensed
*/
/**
* Module variables.
* @private
*/
var matchHtmlRegExp = /["'&<>]/;
/**
* Module exports.
* @public
*/
module.exports = escapeHtml;
/**
* Escape special characters in the given string of html.
*
* @param {string} string The string to escape for inserting into HTML
* @return {string}
* @public
*/
function escapeHtml(string) {
var str = '' + string;
var match = matchHtmlRegExp.exec(str);
if (!match) {
return str;
}
var escape;
var html = '';
var index = 0;
var lastIndex = 0;
for (index = match.index; index < str.length; index++) {
switch (str.charCodeAt(index)) {
case 34: // "
escape = '"';
break;
case 38: // &
escape = '&';
break;
case 39: // '
escape = ''';
break;
case 60: // <
escape = '<';
break;
case 62: // >
escape = '>';
break;
default:
continue;
}
if (lastIndex !== index) {
html += str.substring(lastIndex, index);
}
lastIndex = index + 1;
html += escape;
}
return lastIndex !== index
? html + str.substring(lastIndex, index)
: html;
}
/***/ }),
/* 7 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _infiniteTree = __webpack_require__(8);
var _infiniteTree2 = _interopRequireDefault(_infiniteTree);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
module.exports = _infiniteTree2['default'];
/***/ }),
/* 8 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _events = __webpack_require__(0);
var _events2 = _interopRequireDefault(_events);
var _classnames = __webpack_require__(1);
var _classnames2 = _interopRequireDefault(_classnames);
var _elementClass = __webpack_require__(9);
var _elementClass2 = _interopRequireDefault(_elementClass);
var _isDom = __webpack_require__(10);
var _isDom2 = _interopRequireDefault(_isDom);
var _flattree = __webpack_require__(13);
var _clusterize = __webpack_require__(15);
var _clusterize2 = _interopRequireDefault(_clusterize);
var _ensureArray = __webpack_require__(4);
var _ensureArray2 = _interopRequireDefault(_ensureArray);
var _extend = __webpack_require__(17);
var _extend2 = _interopRequireDefault(_extend);
var _utilities = __webpack_require__(18);
var _lookupTable = __webpack_require__(19);
var _lookupTable2 = _interopRequireDefault(_lookupTable);
var _renderer = __webpack_require__(20);
var _dom = __webpack_require__(5);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* eslint no-continue: 0 */
/* eslint operator-assignment: 0 */
var noop = function noop() {};
var error = function error(format) {
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
var argIndex = 0;
var message = 'Error: ' + format.replace(/%s/g, function () {
return args[argIndex++];
});
if (console && console.error) {
console.error(message);
}
try {
// This error was thrown as a convenience so that you can use this stack
// to find the callsite that caused this error to fire.
throw new Error(message);
} catch (e) {
// Ignore
}
};
var ensureNodeInstance = function ensureNodeInstance(node) {
if (!node) {
// undefined or null
return false;
}
if (!(node instanceof _flattree.Node)) {
error('The node must be a Node object.');
return false;
}
return true;
};
var createRootNode = function createRootNode(rootNode) {
return (0, _extend2['default'])(rootNode || new _flattree.Node(), {
parent: null,
children: [],
state: {
depth: -1,
open: true, // always open
path: '',
prefixMask: '',
total: 0
}
});
};
var InfiniteTree = function (_events$EventEmitter) {
_inherits(InfiniteTree, _events$EventEmitter);
// Creates new InfiniteTree object.
function InfiniteTree(el, options) {
_classCallCheck(this, InfiniteTree);
var _this = _possibleConstructorReturn(this, _events$EventEmitter.call(this));
_this.options = {
autoOpen: false,
blocksInCluster: 4,
droppable: false,
shouldLoadNodes: null,
loadNodes: null,
rowRenderer: _renderer.defaultRowRenderer,
selectable: true,
shouldSelectNode: null,
// When el is not specified, the tree will run in the stealth mode
el: null,
// The following options will have no effect in the stealth mode
layout: 'div',
noDataClass: 'infinite-tree-no-data',
noDataText: 'No data',
nodeIdAttr: 'data-id',
togglerClass: 'infinite-tree-toggler'
};
_this.state = {
openNodes: [],
rootNode: createRootNode(),
selectedNode: null
};
_this.clusterize = null;
_this.nodeTable = new _lookupTable2['default']();
_this.nodes = [];
_this.rows = [];
_this.filtered = false;
_this.scrollElement = null;
_this.contentElement = null;
_this.draggableTarget = null;
_this.droppableTarget = null;
_this.contentListener = {
'click': function click(event) {
event = event || window.event;
// Wrap stopPropagation that allows click event handler to stop execution
// by setting the cancelBubble property
var stopPropagation = event.stopPropagation;
event.stopPropagation = function () {
// Setting the cancelBubble property in browsers that don't support it doesn't hurt.
// Of course it doesn't actually cancel the bubbling, but the assignment itself is safe.
event.cancelBubble = true;
if (stopPropagation) {
stopPropagation.call(event);
}
};
// Call setTimeout(fn, 0) to re-queues the execution of subsequent calls, it allows the
// click event to bubble up to higher level event handlers before handling tree events.
setTimeout(function () {
// Stop execution if the cancelBubble property is set to true by higher level event handlers
if (event.cancelBubble === true) {
return;
}
// Emit a "click" event
_this.emit('click', event);
// Stop execution if the cancelBubble property is set to true after emitting the click event
if (event.cancelBubble === true) {
return;
}
var itemTarget = null;
var clickToggler = false;
if (event.target) {
itemTarget = event.target !== event.currentTarget ? event.target : null;
} else if (event.srcElement) {
// IE8
itemTarget = event.srcElement;
}
while (itemTarget && itemTarget.parentElement !== _this.contentElement) {
if ((0, _elementClass2['default'])(itemTarget).has(_this.options.togglerClass)) {
clickToggler = true;
}
itemTarget = itemTarget.parentElement;
}
if (!itemTarget || itemTarget.hasAttribute('disabled')) {
return;
}
var id = itemTarget.getAttribute(_this.options.nodeIdAttr);
var node = _this.getNodeById(id);
if (!node) {
return;
}
// Click on the toggler to open/close a tree node
if (clickToggler) {
_this.toggleNode(node, { async: true });
return;
}
_this.selectNode(node); // selectNode will re-render the tree
}, 0);
},
'dblclick': function dblclick(event) {
// Emit a "doubleClick" event
_this.emit('doubleClick', event);
},
'keydown': function keydown(event) {
// Emit a "keyDown" event
_this.emit('keyDown', event);
},
'keyup': function keyup(event) {
// Emit a "keyUp" event
_this.emit('keyUp', event);
},
// https://developer.mozilla.org/en-US/docs/Web/Events/dragstart
// The dragstart event is fired when the user starts dragging an element or text selection.
'dragstart': function dragstart(event) {
event = event || window.event;
_this.draggableTarget = event.target || event.srcElement;
},
// https://developer.mozilla.org/en-US/docs/Web/Events/dragend
// The dragend event is fired when a drag operation is being ended (by releasing a mouse button or hitting the escape key).
'dragend': function dragend(event) {
event = event || window.event;
var _this$options$droppab = _this.options.droppable.hoverClass,
hoverClass = _this$options$droppab === undefined ? '' : _this$options$droppab;
// Draggable
_this.draggableTarget = null;
// Droppable
if (_this.droppableTarget) {
(0, _elementClass2['default'])(_this.droppableTarget).remove(hoverClass);
_this.droppableTarget = null;
}
},
// https://developer.mozilla.org/en-US/docs/Web/Events/dragenter
// The dragenter event is fired when a dragged element or text selection enters a valid drop target.
'dragenter': function dragenter(event) {
event = event || window.event;
var itemTarget = null;
if (event.target) {
itemTarget = event.target !== event.currentTarget ? event.target : null;
} else if (event.srcElement) {
// IE8
itemTarget = event.srcElement;
}
while (itemTarget && itemTarget.parentElement !== _this.contentElement) {
itemTarget = itemTarget.parentElement;
}
if (!itemTarget) {
return;
}
if (_this.droppableTarget === itemTarget) {
return;
}
var _this$options$droppab2 = _this.options.droppable,
accept = _this$options$droppab2.accept,
_this$options$droppab3 = _this$options$droppab2.hoverClass,
hoverClass = _this$options$droppab3 === undefined ? '' : _this$options$droppab3;
(0, _elementClass2['default'])(_this.droppableTarget).remove(hoverClass);
_this.droppableTarget = null;
var canDrop = true; // Defaults to true
if (typeof accept === 'function') {
var id = itemTarget.getAttribute(_this.options.nodeIdAttr);
var node = _this.getNodeById(id);
canDrop = !!accept.call(_this, event, {
type: 'dragenter',
draggableTarget: _this.draggableTarget,
droppableTarget: itemTarget,
node: node
});
}
if (canDrop) {
(0, _elementClass2['default'])(itemTarget).add(hoverClass);
_this.droppableTarget = itemTarget;
}
},
// https://developer.mozilla.org/en-US/docs/Web/Events/dragover
// The dragover event is fired when an element or text selection is being dragged over a valid drop target (every few hundred milliseconds).
'dragover': function dragover(event) {
event = event || window.event;
(0, _dom.preventDefault)(event);
},
// https://developer.mozilla.org/en-US/docs/Web/Events/drop
// The drop event is fired when an element or text selection is dropped on a valid drop target.
'drop': function drop(event) {
event = event || window.event;
// prevent default action (open as link for some elements)
(0, _dom.preventDefault)(event);
if (!(_this.draggableTarget && _this.droppableTarget)) {
return;
}
var _this$options$droppab4 = _this.options.droppable,
accept = _this$options$droppab4.accept,
drop = _this$options$droppab4.drop,
_this$options$droppab5 = _this$options$droppab4.hoverClass,
hoverClass = _this$options$droppab5 === undefined ? '' : _this$options$droppab5;
var id = _this.droppableTarget.getAttribute(_this.options.nodeIdAttr);
var node = _this.getNodeById(id);
var canDrop = true; // Defaults to true
if (typeof accept === 'function') {
canDrop = !!accept.call(_this, event, {
type: 'drop',
draggableTarget: _this.draggableTarget,
droppableTarget: _this.droppableTarget,
node: node
});
}
if (canDrop && typeof drop === 'function') {
drop.call(_this, event, {
draggableTarget: _this.draggableTarget,
droppableTarget: _this.droppableTarget,
node: node
});
}
(0, _elementClass2['default'])(_this.droppableTarget).remove(hoverClass);
_this.droppableTarget = null;
}
};
if ((0, _isDom2['default'])(el)) {
options = _extends({}, options, { el: el });
} else if (el && (typeof el === 'undefined' ? 'undefined' : _typeof(el)) === 'object') {
options = el;
}
// Assign options
_this.options = _extends({}, _this.options, options);
_this.create();
// Load tree data if it's provided
if (_this.options.data) {
_this.loadData(_this.options.data);
}
return _this;
}
// The following elements will have no effect in the stealth mode
InfiniteTree.prototype.create = function create() {
var _this2 = this;
if (this.options.el) {
var tag = null;
this.scrollElement = document.createElement('div');
if (this.options.layout === 'table') {
var tableElement = document.createElement('table');
tableElement.className = (0, _classnames2['default'])('infinite-tree', 'infinite-tree-table');
var contentElement = document.createElement('tbody');
tableElement.appendChild(contentElement);
this.scrollElement.appendChild(tableElement);
this.contentElement = contentElement;
// The tag name for supporting elements
tag = 'tr';
} else {
var _contentElement = document.createElement('div');
this.scrollElement.appendChild(_contentElement);
this.contentElement = _contentElement;
// The tag name for supporting elements
tag = 'div';
}
this.scrollElement.className = (0, _classnames2['default'])('infinite-tree', 'infinite-tree-scroll');
this.contentElement.className = (0, _classnames2['default'])('infinite-tree', 'infinite-tree-content');
this.options.el.appendChild(this.scrollElement);
this.clusterize = new _clusterize2['default']({
tag: tag,
rows: [],
scrollElement: this.scrollElement,
contentElement: this.contentElement,
emptyText: this.options.noDataText,
emptyClass: this.options.noDataClass,
blocksInCluster: this.options.blocksInCluster
});
this.clusterize.on('clusterWillChange', function () {
_this2.emit('clusterWillChange');
});
this.clusterize.on('clusterDidChange', function () {
_this2.emit('clusterDidChange');
});
(0, _dom.addEventListener)(this.contentElement, 'click', this.contentListener.click);
(0, _dom.addEventListener)(this.contentElement, 'dblclick', this.contentListener.dblclick);
(0, _dom.addEventListener)(this.contentElement, 'keydown', this.contentListener.keydown);
(0, _dom.addEventListener)(this.contentElement, 'keyup', this.contentListener.keyup);
if (this.options.droppable) {
(0, _dom.addEventListener)(document, 'dragstart', this.contentListener.dragstart);
(0, _dom.addEventListener)(document, 'dragend', this.contentListener.dragend);
(0, _dom.addEventListener)(this.contentElement, 'dragenter', this.contentListener.dragenter);
(0, _dom.addEventListener)(this.contentElement, 'dragleave', this.contentListener.dragleave);
(0, _dom.addEventListener)(this.contentElement, 'dragover', this.contentListener.dragover);
(0, _dom.addEventListener)(this.contentElement, 'drop', this.contentListener.drop);
}
}
};
InfiniteTree.prototype.destroy = function destroy() {
this.clear();
if (this.options.el) {
(0, _dom.removeEventListener)(this.contentElement, 'click', this.contentListener.click);
(0, _dom.removeEventListener)(this.contentElement, 'dblclick', this.contentListener.dblclick);
(0, _dom.removeEventListener)(this.contentElement, 'keydown', this.contentListener.keydown);
(0, _dom.removeEventListener)(this.contentElement, 'keyup', this.contentListener.keyup);
if (this.options.droppable) {
(0, _dom.removeEventListener)(document, 'dragstart', this.contentListener.dragstart);
(0, _dom.removeEventListener)(document, 'dragend', this.contentListener.dragend);
(0, _dom.removeEventListener)(this.contentElement, 'dragenter', this.contentListener.dragenter);
(0, _dom.removeEventListener)(this.contentElement, 'dragleave', this.contentListener.dragleave);
(0, _dom.removeEventListener)(this.contentElement, 'dragover', this.contentListener.dragover);
(0, _dom.removeEventListener)(this.contentElement, 'drop', this.contentListener.drop);
}
if (this.clusterize) {
this.clusterize.destroy(true); // True to remove all data from the list
this.clusterize = null;
}
// Remove all child nodes
while (this.contentElement.firstChild) {
this.contentElement.removeChild(this.contentElement.firstChild);
}
while (this.scrollElement.firstChild) {
this.scrollElement.removeChild(this.scrollElement.firstChild);
}
var containerElement = this.options.el;
while (containerElement.firstChild) {
containerElement.removeChild(containerElement.firstChild);
}
this.contentElement = null;
this.scrollElement = null;
}
};
// Adds an array of new child nodes to a parent node at the specified index.
// * If the parent is null or undefined, inserts new childs at the specified index in the top-level.
// * If the parent has children, the method adds the new child to it at the specified index.
// * If the parent does not have children, the method adds the new child to the parent.
// * If the index value is greater than or equal to the number of children in the parent, the method adds the child at the end of the children.
// @param {Array} newNodes An array of new child nodes.
// @param {number} [index] The 0-based index of where to insert the child node.
// @param {Node} parentNode The Node object that defines the parent node.
// @return {boolean} Returns true on success, false otherwise.
InfiniteTree.prototype.addChildNodes = function addChildNodes(newNodes, index, parentNode) {
var _this3 = this;
newNodes = [].concat(newNodes || []); // Ensure array
if (newNodes.length === 0) {
return false;
}
parentNode = parentNode || this.state.rootNode; // Defaults to rootNode if not specified
if (index === undefined) {
index = parentNode.children.length;
}
if (!ensureNodeInstance(parentNode)) {
return false;
}
// Assign parent
newNodes.forEach(function (newNode) {
newNode.parent = parentNode;
});
// Insert new child node at the specified index
parentNode.children.splice.apply(parentNode.children, [index, 0].concat(newNodes));
// Get the index of the first new node within the array of child nodes
index = parentNode.children.indexOf(newNodes[0]);
var deleteCount = parentNode.state.total;
var nodes = (0, _flattree.flatten)(parentNode.children, { openNodes: this.state.openNodes });
var rows = [];
// Update rows
rows.length = nodes.length;
for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i];
rows[i] = this.options.rowRenderer(node, this.options);
}
if (parentNode === this.state.rootNode) {
this.nodes = nodes;
this.rows = rows;
} else {
var parentOffset = this.nodes.indexOf(parentNode);
if (parentOffset >= 0) {