visjs-network
Version:
A dynamic, browser-based network visualization library.
1,766 lines (1,571 loc) • 1.28 MB
JavaScript
/**
* vis.js
* https://github.com/almende/vis
*
* A dynamic, browser-based visualization library.
*
* @version 4.24.11
* @date 2019-10-24
*
* @license
* Copyright (C) 2011-2017 Almende B.V, http://almende.com
*
* Vis.js is dual licensed under both
*
* * The Apache 2.0 License
* http://www.apache.org/licenses/LICENSE-2.0
*
* and
*
* * The MIT License
* http://opensource.org/licenses/MIT
*
* Vis.js may be distributed under either license.
*/
(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["vis"] = factory();
else
root["vis"] = 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 = 85);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
exports.default = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
var _defineProperty = __webpack_require__(130);
var _defineProperty2 = _interopRequireDefault(_defineProperty);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.default = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
(0, _defineProperty2.default)(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _getIterator2 = __webpack_require__(58);
var _getIterator3 = _interopRequireDefault(_getIterator2);
var _create = __webpack_require__(31);
var _create2 = _interopRequireDefault(_create);
var _keys = __webpack_require__(9);
var _keys2 = _interopRequireDefault(_keys);
var _typeof2 = __webpack_require__(7);
var _typeof3 = _interopRequireDefault(_typeof2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
// utility functions
// first check if moment.js is already loaded in the browser window, if so,
// use this instance. Else, load via commonjs.
var moment = __webpack_require__(71);
var uuid = __webpack_require__(119);
/**
* Test whether given object is a number
* @param {*} object
* @return {Boolean} isNumber
*/
exports.isNumber = function (object) {
return object instanceof Number || typeof object == 'number';
};
/**
* Remove everything in the DOM object
* @param {Element} DOMobject
*/
exports.recursiveDOMDelete = function (DOMobject) {
if (DOMobject) {
while (DOMobject.hasChildNodes() === true) {
exports.recursiveDOMDelete(DOMobject.firstChild);
DOMobject.removeChild(DOMobject.firstChild);
}
}
};
/**
* Test whether given object is a string
* @param {*} object
* @return {Boolean} isString
*/
exports.isString = function (object) {
return object instanceof String || typeof object == 'string';
};
/**
* Test whether given object is a Date, or a String containing a Date
* @param {Date | String} object
* @return {Boolean} isDate
*/
exports.isDate = function (object) {
if (object instanceof Date) {
return true;
} else if (exports.isString(object)) {
// test whether this string contains a date
var match = ASPDateRegex.exec(object);
if (match) {
return true;
} else if (!isNaN(Date.parse(object))) {
return true;
}
}
return false;
};
/**
* Create a UUID
* @return {string} uuid
*/
exports.randomUUID = function () {
return uuid.v4();
};
/**
* Copy property from b to a if property present in a.
* If property in b explicitly set to null, delete it if `allowDeletion` set.
*
* Internal helper routine, should not be exported. Not added to `exports` for that reason.
*
* @param {object} a target object
* @param {object} b source object
* @param {string} prop name of property to copy to a
* @param {boolean} allowDeletion if true, delete property in a if explicitly set to null in b
* @private
*/
function copyOrDelete(a, b, prop, allowDeletion) {
var doDeletion = false;
if (allowDeletion === true) {
doDeletion = b[prop] === null && a[prop] !== undefined;
}
if (doDeletion) {
delete a[prop];
} else {
a[prop] = b[prop]; // Remember, this is a reference copy!
}
}
/**
* Fill an object with a possibly partially defined other object.
*
* Only copies values for the properties already present in a.
* That means an object is not created on a property if only the b object has it.
*
* @param {object} a
* @param {object} b
* @param {boolean} [allowDeletion=false] if true, delete properties in a that are explicitly set to null in b
*/
exports.fillIfDefined = function (a, b) {
var allowDeletion = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
// NOTE: iteration of properties of a
// NOTE: prototype properties iterated over as well
for (var prop in a) {
if (b[prop] !== undefined) {
if (b[prop] === null || (0, _typeof3['default'])(b[prop]) !== 'object') {
// Note: typeof null === 'object'
copyOrDelete(a, b, prop, allowDeletion);
} else {
if ((0, _typeof3['default'])(a[prop]) === 'object') {
exports.fillIfDefined(a[prop], b[prop], allowDeletion);
}
}
}
}
};
/**
* Extend object a with the properties of object b or a series of objects
* Only properties with defined values are copied
* @param {Object} a
* @param {...Object} b
* @return {Object} a
*/
exports.extend = function (a /* b */) {
// eslint-disable-line no-unused-vars
for (var i = 1; i < arguments.length; i++) {
var other = arguments[i];
for (var prop in other) {
if (other.hasOwnProperty(prop)) {
a[prop] = other[prop];
}
}
}
return a;
};
/**
* Extend object a with selected properties of object b or a series of objects
* Only properties with defined values are copied
* @param {Array.<string>} props
* @param {Object} a
* @param {Object} b
* @return {Object} a
*/
exports.selectiveExtend = function (props, a /* b */) {
// eslint-disable-line no-unused-vars
if (!Array.isArray(props)) {
throw new Error('Array with property names expected as first argument');
}
for (var i = 2; i < arguments.length; i++) {
var other = arguments[i];
for (var p = 0; p < props.length; p++) {
var prop = props[p];
if (other && other.hasOwnProperty(prop)) {
a[prop] = other[prop];
}
}
}
return a;
};
/**
* Extend object a with selected properties of object b.
* Only properties with defined values are copied.
*
* **Note:** Previous version of this routine implied that multiple source objects
* could be used; however, the implementation was **wrong**.
* Since multiple (>1) sources weren't used anywhere in the `vis.js` code,
* this has been removed
*
* @param {Array.<string>} props names of first-level properties to copy over
* @param {object} a target object
* @param {object} b source object
* @param {boolean} [allowDeletion=false] if true, delete property in a if explicitly set to null in b
* @returns {Object} a
*/
exports.selectiveDeepExtend = function (props, a, b) {
var allowDeletion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
// TODO: add support for Arrays to deepExtend
if (Array.isArray(b)) {
throw new TypeError('Arrays are not supported by deepExtend');
}
for (var p = 0; p < props.length; p++) {
var prop = props[p];
if (b.hasOwnProperty(prop)) {
if (b[prop] && b[prop].constructor === Object) {
if (a[prop] === undefined) {
a[prop] = {};
}
if (a[prop].constructor === Object) {
exports.deepExtend(a[prop], b[prop], false, allowDeletion);
} else {
copyOrDelete(a, b, prop, allowDeletion);
}
} else if (Array.isArray(b[prop])) {
throw new TypeError('Arrays are not supported by deepExtend');
} else {
copyOrDelete(a, b, prop, allowDeletion);
}
}
}
return a;
};
/**
* Extend object `a` with properties of object `b`, ignoring properties which are explicitly
* specified to be excluded.
*
* The properties of `b` are considered for copying.
* Properties which are themselves objects are are also extended.
* Only properties with defined values are copied
*
* @param {Array.<string>} propsToExclude names of properties which should *not* be copied
* @param {Object} a object to extend
* @param {Object} b object to take properties from for extension
* @param {boolean} [allowDeletion=false] if true, delete properties in a that are explicitly set to null in b
* @return {Object} a
*/
exports.selectiveNotDeepExtend = function (propsToExclude, a, b) {
var allowDeletion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
// TODO: add support for Arrays to deepExtend
// NOTE: array properties have an else-below; apparently, there is a problem here.
if (Array.isArray(b)) {
throw new TypeError('Arrays are not supported by deepExtend');
}
for (var prop in b) {
if (!b.hasOwnProperty(prop)) continue; // Handle local properties only
if (propsToExclude.indexOf(prop) !== -1) continue; // In exclusion list, skip
if (b[prop] && b[prop].constructor === Object) {
if (a[prop] === undefined) {
a[prop] = {};
}
if (a[prop].constructor === Object) {
exports.deepExtend(a[prop], b[prop]); // NOTE: allowDeletion not propagated!
} else {
copyOrDelete(a, b, prop, allowDeletion);
}
} else if (Array.isArray(b[prop])) {
a[prop] = [];
for (var i = 0; i < b[prop].length; i++) {
a[prop].push(b[prop][i]);
}
} else {
copyOrDelete(a, b, prop, allowDeletion);
}
}
return a;
};
/**
* Deep extend an object a with the properties of object b
*
* @param {Object} a
* @param {Object} b
* @param {boolean} [protoExtend=false] If true, the prototype values will also be extended.
* (ie. the options objects that inherit from others will also get the inherited options)
* @param {boolean} [allowDeletion=false] If true, the values of fields that are null will be deleted
* @returns {Object}
*/
exports.deepExtend = function (a, b) {
var protoExtend = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var allowDeletion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
for (var prop in b) {
if (b.hasOwnProperty(prop) || protoExtend === true) {
if (b[prop] && b[prop].constructor === Object) {
if (a[prop] === undefined) {
a[prop] = {};
}
if (a[prop].constructor === Object) {
exports.deepExtend(a[prop], b[prop], protoExtend); // NOTE: allowDeletion not propagated!
} else {
copyOrDelete(a, b, prop, allowDeletion);
}
} else if (Array.isArray(b[prop])) {
a[prop] = [];
for (var i = 0; i < b[prop].length; i++) {
a[prop].push(b[prop][i]);
}
} else {
copyOrDelete(a, b, prop, allowDeletion);
}
}
}
return a;
};
/**
* Test whether all elements in two arrays are equal.
* @param {Array} a
* @param {Array} b
* @return {boolean} Returns true if both arrays have the same length and same
* elements.
*/
exports.equalArray = function (a, b) {
if (a.length != b.length) return false;
for (var i = 0, len = a.length; i < len; i++) {
if (a[i] != b[i]) return false;
}
return true;
};
/**
* Convert an object to another type
* @param {boolean | number | string | Date | Moment | Null | undefined} object
* @param {string | undefined} type Name of the type. Available types:
* 'Boolean', 'Number', 'String',
* 'Date', 'Moment', ISODate', 'ASPDate'.
* @return {*} object
* @throws Error
*/
exports.convert = function (object, type) {
var match;
if (object === undefined) {
return undefined;
}
if (object === null) {
return null;
}
if (!type) {
return object;
}
if (!(typeof type === 'string') && !(type instanceof String)) {
throw new Error('Type must be a string');
}
//noinspection FallthroughInSwitchStatementJS
switch (type) {
case 'boolean':
case 'Boolean':
return Boolean(object);
case 'number':
case 'Number':
if (exports.isString(object) && !isNaN(Date.parse(object))) {
return moment(object).valueOf();
} else {
return Number(object.valueOf());
}
case 'string':
case 'String':
return String(object);
case 'Date':
if (exports.isNumber(object)) {
return new Date(object);
}
if (object instanceof Date) {
return new Date(object.valueOf());
} else if (moment.isMoment(object)) {
return new Date(object.valueOf());
}
if (exports.isString(object)) {
match = ASPDateRegex.exec(object);
if (match) {
// object is an ASP date
return new Date(Number(match[1])); // parse number
} else {
return moment(new Date(object)).toDate(); // parse string
}
} else {
throw new Error('Cannot convert object of type ' + exports.getType(object) + ' to type Date');
}
case 'Moment':
if (exports.isNumber(object)) {
return moment(object);
}
if (object instanceof Date) {
return moment(object.valueOf());
} else if (moment.isMoment(object)) {
return moment(object);
}
if (exports.isString(object)) {
match = ASPDateRegex.exec(object);
if (match) {
// object is an ASP date
return moment(Number(match[1])); // parse number
} else {
return moment(object); // parse string
}
} else {
throw new Error('Cannot convert object of type ' + exports.getType(object) + ' to type Date');
}
case 'ISODate':
if (exports.isNumber(object)) {
return new Date(object);
} else if (object instanceof Date) {
return object.toISOString();
} else if (moment.isMoment(object)) {
return object.toDate().toISOString();
} else if (exports.isString(object)) {
match = ASPDateRegex.exec(object);
if (match) {
// object is an ASP date
return new Date(Number(match[1])).toISOString(); // parse number
} else {
return moment(object).format(); // ISO 8601
}
} else {
throw new Error('Cannot convert object of type ' + exports.getType(object) + ' to type ISODate');
}
case 'ASPDate':
if (exports.isNumber(object)) {
return '/Date(' + object + ')/';
} else if (object instanceof Date) {
return '/Date(' + object.valueOf() + ')/';
} else if (exports.isString(object)) {
match = ASPDateRegex.exec(object);
var value;
if (match) {
// object is an ASP date
value = new Date(Number(match[1])).valueOf(); // parse number
} else {
value = new Date(object).valueOf(); // parse string
}
return '/Date(' + value + ')/';
} else {
throw new Error('Cannot convert object of type ' + exports.getType(object) + ' to type ASPDate');
}
default:
throw new Error('Unknown type "' + type + '"');
}
};
// parse ASP.Net Date pattern,
// for example '/Date(1198908717056)/' or '/Date(1198908717056-0700)/'
// code from http://momentjs.com/
var ASPDateRegex = /^\/?Date\((\-?\d+)/i;
/**
* Get the type of an object, for example exports.getType([]) returns 'Array'
* @param {*} object
* @return {string} type
*/
exports.getType = function (object) {
var type = typeof object === 'undefined' ? 'undefined' : (0, _typeof3['default'])(object);
if (type == 'object') {
if (object === null) {
return 'null';
}
if (object instanceof Boolean) {
return 'Boolean';
}
if (object instanceof Number) {
return 'Number';
}
if (object instanceof String) {
return 'String';
}
if (Array.isArray(object)) {
return 'Array';
}
if (object instanceof Date) {
return 'Date';
}
return 'Object';
} else if (type == 'number') {
return 'Number';
} else if (type == 'boolean') {
return 'Boolean';
} else if (type == 'string') {
return 'String';
} else if (type === undefined) {
return 'undefined';
}
return type;
};
/**
* Used to extend an array and copy it. This is used to propagate paths recursively.
*
* @param {Array} arr
* @param {*} newValue
* @returns {Array}
*/
exports.copyAndExtendArray = function (arr, newValue) {
var newArr = [];
for (var i = 0; i < arr.length; i++) {
newArr.push(arr[i]);
}
newArr.push(newValue);
return newArr;
};
/**
* Used to extend an array and copy it. This is used to propagate paths recursively.
*
* @param {Array} arr
* @returns {Array}
*/
exports.copyArray = function (arr) {
var newArr = [];
for (var i = 0; i < arr.length; i++) {
newArr.push(arr[i]);
}
return newArr;
};
/**
* Retrieve the absolute left value of a DOM element
* @param {Element} elem A dom element, for example a div
* @return {number} left The absolute left position of this element
* in the browser page.
*/
exports.getAbsoluteLeft = function (elem) {
return elem.getBoundingClientRect().left;
};
exports.getAbsoluteRight = function (elem) {
return elem.getBoundingClientRect().right;
};
/**
* Retrieve the absolute top value of a DOM element
* @param {Element} elem A dom element, for example a div
* @return {number} top The absolute top position of this element
* in the browser page.
*/
exports.getAbsoluteTop = function (elem) {
return elem.getBoundingClientRect().top;
};
/**
* add a className to the given elements style
* @param {Element} elem
* @param {string} classNames
*/
exports.addClassName = function (elem, classNames) {
var classes = elem.className.split(' ');
var newClasses = classNames.split(' ');
classes = classes.concat(newClasses.filter(function (className) {
return classes.indexOf(className) < 0;
}));
elem.className = classes.join(' ');
};
/**
* add a className to the given elements style
* @param {Element} elem
* @param {string} classNames
*/
exports.removeClassName = function (elem, classNames) {
var classes = elem.className.split(' ');
var oldClasses = classNames.split(' ');
classes = classes.filter(function (className) {
return oldClasses.indexOf(className) < 0;
});
elem.className = classes.join(' ');
};
/**
* For each method for both arrays and objects.
* In case of an array, the built-in Array.forEach() is applied. (**No, it's not!**)
* In case of an Object, the method loops over all properties of the object.
* @param {Object | Array} object An Object or Array
* @param {function} callback Callback method, called for each item in
* the object or array with three parameters:
* callback(value, index, object)
*/
exports.forEach = function (object, callback) {
var i, len;
if (Array.isArray(object)) {
// array
for (i = 0, len = object.length; i < len; i++) {
callback(object[i], i, object);
}
} else {
// object
for (i in object) {
if (object.hasOwnProperty(i)) {
callback(object[i], i, object);
}
}
}
};
/**
* Convert an object into an array: all objects properties are put into the
* array. The resulting array is unordered.
* @param {Object} object
* @returns {Array} array
*/
exports.toArray = function (object) {
var array = [];
for (var prop in object) {
if (object.hasOwnProperty(prop)) array.push(object[prop]);
}
return array;
};
/**
* Update a property in an object
* @param {Object} object
* @param {string} key
* @param {*} value
* @return {Boolean} changed
*/
exports.updateProperty = function (object, key, value) {
if (object[key] !== value) {
object[key] = value;
return true;
} else {
return false;
}
};
/**
* Throttle the given function to be only executed once per animation frame
* @param {function} fn
* @returns {function} Returns the throttled function
*/
exports.throttle = function (fn) {
var scheduled = false;
return function throttled() {
if (!scheduled) {
scheduled = true;
requestAnimationFrame(function () {
scheduled = false;
fn();
});
}
};
};
/**
* Add and event listener. Works for all browsers
* @param {Element} element An html element
* @param {string} action The action, for example "click",
* without the prefix "on"
* @param {function} listener The callback function to be executed
* @param {boolean} [useCapture]
*/
exports.addEventListener = function (element, action, listener, useCapture) {
if (element.addEventListener) {
if (useCapture === undefined) useCapture = false;
if (action === 'mousewheel' && navigator.userAgent.indexOf('Firefox') >= 0) {
action = 'DOMMouseScroll'; // For Firefox
}
element.addEventListener(action, listener, useCapture);
} else {
element.attachEvent('on' + action, listener); // IE browsers
}
};
/**
* Remove an event listener from an element
* @param {Element} element An html dom element
* @param {string} action The name of the event, for example "mousedown"
* @param {function} listener The listener function
* @param {boolean} [useCapture]
*/
exports.removeEventListener = function (element, action, listener, useCapture) {
if (element.removeEventListener) {
// non-IE browsers
if (useCapture === undefined) useCapture = false;
if (action === 'mousewheel' && navigator.userAgent.indexOf('Firefox') >= 0) {
action = 'DOMMouseScroll'; // For Firefox
}
element.removeEventListener(action, listener, useCapture);
} else {
// IE browsers
element.detachEvent('on' + action, listener);
}
};
/**
* Cancels the event if it is cancelable, without stopping further propagation of the event.
* @param {Event} event
*/
exports.preventDefault = function (event) {
if (!event) event = window.event;
if (event.preventDefault) {
event.preventDefault(); // non-IE browsers
} else {
event.returnValue = false; // IE browsers
}
};
/**
* Get HTML element which is the target of the event
* @param {Event} event
* @return {Element} target element
*/
exports.getTarget = function (event) {
// code from http://www.quirksmode.org/js/events_properties.html
if (!event) {
event = window.event;
}
var target;
if (event.target) {
target = event.target;
} else if (event.srcElement) {
target = event.srcElement;
}
if (target.nodeType != undefined && target.nodeType == 3) {
// defeat Safari bug
target = target.parentNode;
}
return target;
};
/**
* Check if given element contains given parent somewhere in the DOM tree
* @param {Element} element
* @param {Element} parent
* @returns {boolean}
*/
exports.hasParent = function (element, parent) {
var e = element;
while (e) {
if (e === parent) {
return true;
}
e = e.parentNode;
}
return false;
};
exports.option = {};
/**
* Convert a value into a boolean
* @param {Boolean | function | undefined} value
* @param {boolean} [defaultValue]
* @returns {Boolean} bool
*/
exports.option.asBoolean = function (value, defaultValue) {
if (typeof value == 'function') {
value = value();
}
if (value != null) {
return value != false;
}
return defaultValue || null;
};
/**
* Convert a value into a number
* @param {Boolean | function | undefined} value
* @param {number} [defaultValue]
* @returns {number} number
*/
exports.option.asNumber = function (value, defaultValue) {
if (typeof value == 'function') {
value = value();
}
if (value != null) {
return Number(value) || defaultValue || null;
}
return defaultValue || null;
};
/**
* Convert a value into a string
* @param {string | function | undefined} value
* @param {string} [defaultValue]
* @returns {String} str
*/
exports.option.asString = function (value, defaultValue) {
if (typeof value == 'function') {
value = value();
}
if (value != null) {
return String(value);
}
return defaultValue || null;
};
/**
* Convert a size or location into a string with pixels or a percentage
* @param {string | number | function | undefined} value
* @param {string} [defaultValue]
* @returns {String} size
*/
exports.option.asSize = function (value, defaultValue) {
if (typeof value == 'function') {
value = value();
}
if (exports.isString(value)) {
return value;
} else if (exports.isNumber(value)) {
return value + 'px';
} else {
return defaultValue || null;
}
};
/**
* Convert a value into a DOM element
* @param {HTMLElement | function | undefined} value
* @param {HTMLElement} [defaultValue]
* @returns {HTMLElement | null} dom
*/
exports.option.asElement = function (value, defaultValue) {
if (typeof value == 'function') {
value = value();
}
return value || defaultValue || null;
};
/**
* http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
*
* @param {string} hex
* @returns {{r: *, g: *, b: *}} | 255 range
*/
exports.hexToRGB = function (hex) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function (m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
};
/**
* This function takes color in hex format or rgb() or rgba() format and overrides the opacity. Returns rgba() string.
* @param {string} color
* @param {number} opacity
* @returns {String}
*/
exports.overrideOpacity = function (color, opacity) {
var rgb;
if (color.indexOf('rgba') != -1) {
return color;
} else if (color.indexOf('rgb') != -1) {
rgb = color.substr(color.indexOf('(') + 1).replace(')', '').split(',');
return 'rgba(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ',' + opacity + ')';
} else {
rgb = exports.hexToRGB(color);
if (rgb == null) {
return color;
} else {
return 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + opacity + ')';
}
}
};
/**
*
* @param {number} red 0 -- 255
* @param {number} green 0 -- 255
* @param {number} blue 0 -- 255
* @returns {String}
* @constructor
*/
exports.RGBToHex = function (red, green, blue) {
return '#' + ((1 << 24) + (red << 16) + (green << 8) + blue).toString(16).slice(1);
};
/**
* Parse a color property into an object with border, background, and
* highlight colors
* @param {Object | String} color
* @return {Object} colorObject
*/
exports.parseColor = function (color) {
var c;
if (exports.isString(color) === true) {
if (exports.isValidRGB(color) === true) {
var rgb = color.substr(4).substr(0, color.length - 5).split(',').map(function (value) {
return parseInt(value);
});
color = exports.RGBToHex(rgb[0], rgb[1], rgb[2]);
}
if (exports.isValidHex(color) === true) {
var hsv = exports.hexToHSV(color);
var lighterColorHSV = {
h: hsv.h,
s: hsv.s * 0.8,
v: Math.min(1, hsv.v * 1.02)
};
var darkerColorHSV = {
h: hsv.h,
s: Math.min(1, hsv.s * 1.25),
v: hsv.v * 0.8
};
var darkerColorHex = exports.HSVToHex(darkerColorHSV.h, darkerColorHSV.s, darkerColorHSV.v);
var lighterColorHex = exports.HSVToHex(lighterColorHSV.h, lighterColorHSV.s, lighterColorHSV.v);
c = {
background: color,
border: darkerColorHex,
highlight: {
background: lighterColorHex,
border: darkerColorHex
},
hover: {
background: lighterColorHex,
border: darkerColorHex
}
};
} else {
c = {
background: color,
border: color,
highlight: {
background: color,
border: color
},
hover: {
background: color,
border: color
}
};
}
} else {
c = {};
c.background = color.background || undefined;
c.border = color.border || undefined;
if (exports.isString(color.highlight)) {
c.highlight = {
border: color.highlight,
background: color.highlight
};
} else {
c.highlight = {};
c.highlight.background = color.highlight && color.highlight.background || undefined;
c.highlight.border = color.highlight && color.highlight.border || undefined;
}
if (exports.isString(color.hover)) {
c.hover = {
border: color.hover,
background: color.hover
};
} else {
c.hover = {};
c.hover.background = color.hover && color.hover.background || undefined;
c.hover.border = color.hover && color.hover.border || undefined;
}
}
return c;
};
/**
* http://www.javascripter.net/faq/rgb2hsv.htm
*
* @param {number} red
* @param {number} green
* @param {number} blue
* @returns {{h: number, s: number, v: number}}
* @constructor
*/
exports.RGBToHSV = function (red, green, blue) {
red = red / 255;
green = green / 255;
blue = blue / 255;
var minRGB = Math.min(red, Math.min(green, blue));
var maxRGB = Math.max(red, Math.max(green, blue));
// Black-gray-white
if (minRGB == maxRGB) {
return { h: 0, s: 0, v: minRGB };
}
// Colors other than black-gray-white:
var d = red == minRGB ? green - blue : blue == minRGB ? red - green : blue - red;
var h = red == minRGB ? 3 : blue == minRGB ? 1 : 5;
var hue = 60 * (h - d / (maxRGB - minRGB)) / 360;
var saturation = (maxRGB - minRGB) / maxRGB;
var value = maxRGB;
return { h: hue, s: saturation, v: value };
};
var cssUtil = {
// split a string with css styles into an object with key/values
split: function split(cssText) {
var styles = {};
cssText.split(';').forEach(function (style) {
if (style.trim() != '') {
var parts = style.split(':');
var key = parts[0].trim();
var value = parts[1].trim();
styles[key] = value;
}
});
return styles;
},
// build a css text string from an object with key/values
join: function join(styles) {
return (0, _keys2['default'])(styles).map(function (key) {
return key + ': ' + styles[key];
}).join('; ');
}
/**
* Append a string with css styles to an element
* @param {Element} element
* @param {string} cssText
*/
};exports.addCssText = function (element, cssText) {
var currentStyles = cssUtil.split(element.style.cssText);
var newStyles = cssUtil.split(cssText);
var styles = exports.extend(currentStyles, newStyles);
element.style.cssText = cssUtil.join(styles);
};
/**
* Remove a string with css styles from an element
* @param {Element} element
* @param {string} cssText
*/
exports.removeCssText = function (element, cssText) {
var styles = cssUtil.split(element.style.cssText);
var removeStyles = cssUtil.split(cssText);
for (var key in removeStyles) {
if (removeStyles.hasOwnProperty(key)) {
delete styles[key];
}
}
element.style.cssText = cssUtil.join(styles);
};
/**
* https://gist.github.com/mjijackson/5311256
* @param {number} h
* @param {number} s
* @param {number} v
* @returns {{r: number, g: number, b: number}}
* @constructor
*/
exports.HSVToRGB = function (h, s, v) {
var r, g, b;
var i = Math.floor(h * 6);
var f = h * 6 - i;
var p = v * (1 - s);
var q = v * (1 - f * s);
var t = v * (1 - (1 - f) * s);
switch (i % 6) {
case 0:
;r = v, g = t, b = p;
break;
case 1:
;r = q, g = v, b = p;
break;
case 2:
;r = p, g = v, b = t;
break;
case 3:
;r = p, g = q, b = v;
break;
case 4:
;r = t, g = p, b = v;
break;
case 5:
;r = v, g = p, b = q;
break;
}
return {
r: Math.floor(r * 255),
g: Math.floor(g * 255),
b: Math.floor(b * 255)
};
};
exports.HSVToHex = function (h, s, v) {
var rgb = exports.HSVToRGB(h, s, v);
return exports.RGBToHex(rgb.r, rgb.g, rgb.b);
};
exports.hexToHSV = function (hex) {
var rgb = exports.hexToRGB(hex);
return exports.RGBToHSV(rgb.r, rgb.g, rgb.b);
};
exports.isValidHex = function (hex) {
var isOk = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(hex);
return isOk;
};
exports.isValidRGB = function (rgb) {
rgb = rgb.replace(' ', '');
var isOk = /rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/i.test(rgb);
return isOk;
};
exports.isValidRGBA = function (rgba) {
rgba = rgba.replace(' ', '');
var isOk = /rgba\((\d{1,3}),(\d{1,3}),(\d{1,3}),(.{1,3})\)/i.test(rgba);
return isOk;
};
/**
* This recursively redirects the prototype of JSON objects to the referenceObject
* This is used for default options.
*
* @param {Array.<string>} fields
* @param {Object} referenceObject
* @returns {*}
*/
exports.selectiveBridgeObject = function (fields, referenceObject) {
if (referenceObject !== null && (typeof referenceObject === 'undefined' ? 'undefined' : (0, _typeof3['default'])(referenceObject)) === 'object') {
// !!! typeof null === 'object'
var objectTo = (0, _create2['default'])(referenceObject);
for (var i = 0; i < fields.length; i++) {
if (referenceObject.hasOwnProperty(fields[i])) {
if ((0, _typeof3['default'])(referenceObject[fields[i]]) == 'object') {
objectTo[fields[i]] = exports.bridgeObject(referenceObject[fields[i]]);
}
}
}
return objectTo;
} else {
return null;
}
};
/**
* This recursively redirects the prototype of JSON objects to the referenceObject
* This is used for default options.
*
* @param {Object} referenceObject
* @returns {*}
*/
exports.bridgeObject = function (referenceObject) {
if (referenceObject !== null && (typeof referenceObject === 'undefined' ? 'undefined' : (0, _typeof3['default'])(referenceObject)) === 'object') {
// !!! typeof null === 'object'
var objectTo = (0, _create2['default'])(referenceObject);
if (referenceObject instanceof Element) {
// Avoid bridging DOM objects
objectTo = referenceObject;
} else {
objectTo = (0, _create2['default'])(referenceObject);
for (var i in referenceObject) {
if (referenceObject.hasOwnProperty(i)) {
if ((0, _typeof3['default'])(referenceObject[i]) == 'object') {
objectTo[i] = exports.bridgeObject(referenceObject[i]);
}
}
}
}
return objectTo;
} else {
return null;
}
};
/**
* This method provides a stable sort implementation, very fast for presorted data
*
* @param {Array} a the array
* @param {function} compare an order comparator
* @returns {Array}
*/
exports.insertSort = function (a, compare) {
for (var i = 0; i < a.length; i++) {
var k = a[i];
for (var j = i; j > 0 && compare(k, a[j - 1]) < 0; j--) {
a[j] = a[j - 1];
}
a[j] = k;
}
return a;
};
/**
* This is used to set the options of subobjects in the options object.
*
* A requirement of these subobjects is that they have an 'enabled' element
* which is optional for the user but mandatory for the program.
*
* The added value here of the merge is that option 'enabled' is set as required.
*
*
* @param {object} mergeTarget | either this.options or the options used for the groups.
* @param {object} options | options
* @param {string} option | option key in the options argument
* @param {object} globalOptions | global options, passed in to determine value of option 'enabled'
*/
exports.mergeOptions = function (mergeTarget, options, option) {
var globalOptions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
// Local helpers
var isPresent = function isPresent(obj) {
return obj !== null && obj !== undefined;
};
var isObject = function isObject(obj) {
return obj !== null && (typeof obj === 'undefined' ? 'undefined' : (0, _typeof3['default'])(obj)) === 'object';
};
// https://stackoverflow.com/a/34491287/1223531
var isEmpty = function isEmpty(obj) {
for (var x in obj) {
if (obj.hasOwnProperty(x)) return false;
}
return true;
};
// Guards
if (!isObject(mergeTarget)) {
throw new Error('Parameter mergeTarget must be an object');
}
if (!isObject(options)) {
throw new Error('Parameter options must be an object');
}
if (!isPresent(option)) {
throw new Error('Parameter option must have a value');
}
if (!isObject(globalOptions)) {
throw new Error('Parameter globalOptions must be an object');
}
//
// Actual merge routine, separated from main logic
// Only a single level of options is merged. Deeper levels are ref'd. This may actually be an issue.
//
var doMerge = function doMerge(target, options, option) {
if (!isObject(target[option])) {
target[option] = {};
}
var src = options[option];
var dst = target[option];
for (var prop in src) {
if (src.hasOwnProperty(prop)) {
dst[prop] = src[prop];
}
}
};
// Local initialization
var srcOption = options[option];
var globalPassed = isObject(globalOptions) && !isEmpty(globalOptions);
var globalOption = globalPassed ? globalOptions[option] : undefined;
var globalEnabled = globalOption ? globalOption.enabled : undefined;
/////////////////////////////////////////
// Main routine
/////////////////////////////////////////
if (srcOption === undefined) {
return; // Nothing to do
}
if (typeof srcOption === 'boolean') {
if (!isObject(mergeTarget[option])) {
mergeTarget[option] = {};
}
mergeTarget[option].enabled = srcOption;
return;
}
if (srcOption === null && !isObject(mergeTarget[option])) {
// If possible, explicit copy from globals
if (isPresent(globalOption)) {
mergeTarget[option] = (0, _create2['default'])(globalOption);
} else {
return; // Nothing to do
}
}
if (!isObject(srcOption)) {
return;
}
//
// Ensure that 'enabled' is properly set. It is required internally
// Note that the value from options will always overwrite the existing value
//
var enabled = true; // default value
if (srcOption.enabled !== undefined) {
enabled = srcOption.enabled;
} else {
// Take from globals, if present
if (globalEnabled !== undefined) {
enabled = globalOption.enabled;
}
}
doMerge(mergeTarget, options, option);
mergeTarget[option].enabled = enabled;
};
/**
* This function does a binary search for a visible item in a sorted list. If we find a visible item, the code that uses
* this function will then iterate in both directions over this sorted list to find all visible items.
*
* @param {Item[]} orderedItems | Items ordered by start
* @param {function} comparator | -1 is lower, 0 is equal, 1 is higher
* @param {string} field
* @param {string} field2
* @returns {number}
* @private
*/
exports.binarySearchCustom = function (orderedItems, comparator, field, field2) {
var maxIterations = 10000;
var iteration = 0;
var low = 0;
var high = orderedItems.length - 1;
while (low <= high && iteration < maxIterations) {
var middle = Math.floor((low + high) / 2);
var item = orderedItems[middle];
var value = field2 === undefined ? item[field] : item[field][field2];
var searchResult = comparator(value);
if (searchResult == 0) {
// jihaa, found a visible item!
return middle;
} else if (searchResult == -1) {
// it is too small --> increase low
low = middle + 1;
} else {
// it is too big --> decrease high
high = middle - 1;
}
iteration++;
}
return -1;
};
/**
* This function does a binary search for a specific value in a sorted array. If it does not exist but is in between of
* two values, we return either the one before or the one after, depending on user input
* If it is found, we return the index, else -1.
*
* @param {Array} orderedItems
* @param {{start: number, end: number}} target
* @param {string} field
* @param {string} sidePreference 'before' or 'after'
* @param {function} comparator an optional comparator, returning -1,0,1 for <,==,>.
* @returns {number}
* @private
*/
exports.binarySearchValue = function (orderedItems, target, field, sidePreference, comparator) {
var maxIterations = 10000;
var iteration = 0;
var low = 0;
var high = orderedItems.length - 1;
var prevValue, value, nextValue, middle;
comparator = comparator != undefined ? comparator : function (a, b) {
return a == b ? 0 : a < b ? -1 : 1;
};
while (low <= high && iteration < maxIterations) {
// get a new guess
middle = Math.floor(0.5 * (high + low));
prevValue = orderedItems[Math.max(0, middle - 1)][field];
value = orderedItems[middle][field];
nextValue = orderedItems[Math.min(orderedItems.length - 1, middle + 1)][field];
if (comparator(value, target) == 0) {
// we found the target
return middle;
} else if (comparator(prevValue, target) < 0 && comparator(value, target) > 0) {
// target is in between of the previous and the current
return sidePreference == 'before' ? Math.max(0, middle - 1) : middle;
} else if (comparator(value, target) < 0 && comparator(nextValue, target) > 0) {
// target is in between of the current and the next
return sidePreference == 'before' ? middle : Math.min(orderedItems.length - 1, middle + 1);
} else {
// didnt find the target, we need to change our boundaries.
if (comparator(value, target) < 0) {
// it is too small --> increase low
low = middle + 1;
} else {
// it is too big --> decrease high
high = middle - 1;
}
}
iteration++;
}
// didnt find anything. Return -1.
return -1;
};
/*
* Easing Functions - inspired from http://gizma.com/easing/
* only considering the t value for the range [0, 1] => [0, 1]
* https://gist.github.com/gre/1650294
*/
exports.easingFunctions = {
// no easing, no acceleration
linear: function linear(t) {
return t;
},
// accelerating from zero velocity
easeInQuad: function easeInQuad(t) {
return t * t;
},
// decelerating to zero velocity
easeOutQuad: function easeOutQuad(t) {
return t * (2 - t);
},
// acceleration until halfway, then deceleration
easeInOutQuad: function easeInOutQuad(t) {
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
},
// accelerating from zero velocity
easeInCubic: function easeInCubic(t) {
return t * t * t;
},
// decelerating to zero velocity
easeOutCubic: function easeOutCubic(t) {
return --t * t * t + 1;
},
// acceleration until halfway, then deceleration
easeInOutCubic: function easeInOutCubic(t) {
return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
},
// accelerating from zero velocity
easeInQuart: function easeInQuart(t) {
return t * t * t * t;
},
// decelerating to zero velocity
easeOutQuart: function easeOutQuart(t) {
return 1 - --t * t * t * t;
},
// acceleration until halfway, then deceleration
easeInOutQuart: function easeInOutQuart(t) {
return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t;
},
// accelerating from zero velocity
easeInQuint: function easeInQuint(t) {
return t * t * t * t * t;
},
// decelerating to zero velocity
easeOutQuint: function easeOutQuint(t) {
return 1 + --t * t * t * t * t;
},
// acceleration until halfway, then deceleration
easeInOutQuint: function easeInOutQuint(t) {
return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t;
}
};
exports.getScrollBarWidth = function () {
var inner = document.createElement('p');
inner.style.width = '100%';
inner.style.height = '200px';
var outer = document.createElement('div');
outer.style.position = 'absolute';
outer.style.top = '0px';
outer.style.left = '0px';
outer.style.visibility = 'hidden';
outer.style.width = '200px';
outer.style.height = '150px';
outer.style.overflow = 'hidden';
outer.appendChild(inner);
document.body.appendChild(outer);
var w1 = inner.offsetWidth;
outer.style.overflow = 'scroll';
var w2 = inner.offsetWidth;
if (w1 == w2) w2 = outer.clientWidth;
document.body.removeChild(outer);
return w1 - w2;
};
exports.topMost = function (pile, accessors) {
var candidate = void 0;
if (!Array.isArray(accessors)) {
accessors = [accessors];
}
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = (0, _getIterator3['default'])(pile), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var member = _step.value;
if (member) {
candidate = member[accessors[0]];
for (var i = 1; i < accessors.length; i++) {
if (candidate) {
candidate = candidate[accessors[i]];
}
}
if (typeof candidate != 'undefined') {
break;
}
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator['return']) {
_iterator['return']();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return candidate;
};
/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
module.exports = { "default": __webpack_require__(145), __esModule: true };
/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
exports.__esModule = true;
var _typeof2 = __webpack_require__(7);
var _typeof3 = _interopRequireDefault(_typeof2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.default = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && ((typeof call ===