UNPKG

qgraph

Version:

A Graph Manipulation and Visualization Library

1,244 lines (1,074 loc) 267 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("lodash")); else if(typeof define === 'function' && define.amd) define("qgraph", ["lodash"], factory); else if(typeof exports === 'object') exports["qgraph"] = factory(require("lodash")); else root["qgraph"] = factory(root["_"]); })((typeof window !== 'undefined' ? window : this), function(__WEBPACK_EXTERNAL_MODULE_lodash__) { 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, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // 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 = "./src/index.js"); /******/ }) /************************************************************************/ /******/ ({ /***/ "./lib/bean.js": /*!*********************!*\ !*** ./lib/bean.js ***! \*********************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } /*! * Bean - copyright (c) Jacob Thornton 2011-2012 * https://github.com/fat/bean * MIT license */ (function (name, context, definition) { if ( true && module.exports) module.exports = definition();else if (true) !(__WEBPACK_AMD_DEFINE_FACTORY__ = (definition), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));else {} })('bean', this, function (name, context) { name = name || 'bean'; context = context || this; var win = typeof window !== 'undefined' ? window : this, old = context[name], namespaceRegex = /[^\.]*(?=\..*)\.|.*/, nameRegex = /\..*/, addEvent = 'addEventListener', removeEvent = 'removeEventListener', doc = typeof document !== 'undefined' ? document : {}, nav = typeof navigator !== 'undefined' ? navigator : {}, root = doc.documentElement || {}, W3C_MODEL = root[addEvent], eventSupport = W3C_MODEL ? addEvent : 'attachEvent', ONE = {} // singleton for quick matching making add() do one() , slice = Array.prototype.slice, str2arr = function str2arr(s, d) { return s.split(d || ' '); }, isString = function isString(o) { return typeof o == 'string'; }, isFunction = function isFunction(o) { return typeof o == 'function'; } // events that we consider to be 'native', anything not in this list will // be treated as a custom event , standardNativeEvents = 'click dblclick mouseup mousedown contextmenu ' + // mouse buttons 'mousewheel mousemultiwheel DOMMouseScroll ' + // mouse wheel 'mouseover mouseout mousemove selectstart selectend ' + // mouse movement 'keydown keypress keyup ' + // keyboard 'orientationchange ' + // mobile 'focus blur change reset select submit ' + // form elements 'load unload beforeunload resize move DOMContentLoaded ' + // window 'readystatechange message ' + // window 'error abort scroll ' // misc // element.fireEvent('onXYZ'... is not forgiving if we try to fire an event // that doesn't actually exist, so make sure we only do these on newer browsers , w3cNativeEvents = 'show ' + // mouse buttons 'input invalid ' + // form elements 'touchstart touchmove touchend touchcancel ' + // touch 'gesturestart gesturechange gestureend ' + // gesture 'textinput ' + // TextEvent 'readystatechange pageshow pagehide popstate ' + // window 'hashchange offline online ' + // window 'afterprint beforeprint ' + // printing 'dragstart dragenter dragover dragleave drag drop dragend ' + // dnd 'loadstart progress suspend emptied stalled loadmetadata ' + // media 'loadeddata canplay canplaythrough playing waiting seeking ' + // media 'seeked ended durationchange timeupdate play pause ratechange ' + // media 'volumechange cuechange ' + // media 'checking noupdate downloading cached updateready obsolete ' // appcache // convert to a hash for quick lookups , nativeEvents = function (hash, events, i) { for (i = 0; i < events.length; i++) { events[i] && (hash[events[i]] = 1); } return hash; }({}, str2arr(standardNativeEvents + (W3C_MODEL ? w3cNativeEvents : ''))) // custom events are events that we *fake*, they are not provided natively but // we can use native events to generate them , customEvents = function () { var isAncestor = 'compareDocumentPosition' in root ? function (element, container) { return container.compareDocumentPosition && (container.compareDocumentPosition(element) & 16) === 16; } : 'contains' in root ? function (element, container) { container = container.nodeType === 9 || container === window ? root : container; return container !== element && container.contains(element); } : function (element, container) { while (element = element.parentNode) { if (element === container) return 1; } return 0; }, check = function check(event) { var related = event.relatedTarget; return !related ? related == null : related !== this && related.prefix !== 'xul' && !/document/.test(this.toString()) && !isAncestor(related, this); }; return { mouseenter: { base: 'mouseover', condition: check }, mouseleave: { base: 'mouseout', condition: check }, mousewheel: { base: /Firefox/.test(nav.userAgent) ? 'DOMMouseScroll' : 'mousewheel' } }; }() // we provide a consistent Event object across browsers by taking the actual DOM // event object and generating a new one from its properties. , Event = function () { // a whitelist of properties (for different event types) tells us what to check for and copy var commonProps = str2arr('altKey attrChange attrName bubbles cancelable ctrlKey currentTarget ' + 'detail eventPhase getModifierState isTrusted metaKey relatedNode relatedTarget shiftKey ' + 'srcElement target timeStamp type view which propertyName'), mouseProps = commonProps.concat(str2arr('button buttons clientX clientY dataTransfer ' + 'fromElement offsetX offsetY pageX pageY screenX screenY toElement')), mouseWheelProps = mouseProps.concat(str2arr('wheelDelta wheelDeltaX wheelDeltaY wheelDeltaZ ' + 'axis')) // 'axis' is FF specific , keyProps = commonProps.concat(str2arr('char charCode key keyCode keyIdentifier ' + 'keyLocation location')), textProps = commonProps.concat(str2arr('data')), touchProps = commonProps.concat(str2arr('touches targetTouches changedTouches scale rotation')), messageProps = commonProps.concat(str2arr('data origin source')), stateProps = commonProps.concat(str2arr('state')), overOutRegex = /over|out/ // some event types need special handling and some need special properties, do that all here , typeFixers = [{ // key events reg: /key/i, fix: function fix(event, newEvent) { newEvent.keyCode = event.keyCode || event.which; return keyProps; } }, { // mouse events reg: /click|mouse(?!(.*wheel|scroll))|menu|drag|drop/i, fix: function fix(event, newEvent, type) { newEvent.rightClick = event.which === 3 || event.button === 2; newEvent.pos = { x: 0, y: 0 }; if (event.pageX || event.pageY) { newEvent.clientX = event.pageX; newEvent.clientY = event.pageY; } else if (event.clientX || event.clientY) { newEvent.clientX = event.clientX + doc.body.scrollLeft + root.scrollLeft; newEvent.clientY = event.clientY + doc.body.scrollTop + root.scrollTop; } if (overOutRegex.test(type)) { newEvent.relatedTarget = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element']; } return mouseProps; } }, { // mouse wheel events reg: /mouse.*(wheel|scroll)/i, fix: function fix() { return mouseWheelProps; } }, { // TextEvent reg: /^text/i, fix: function fix() { return textProps; } }, { // touch and gesture events reg: /^touch|^gesture/i, fix: function fix() { return touchProps; } }, { // message events reg: /^message$/i, fix: function fix() { return messageProps; } }, { // popstate events reg: /^popstate$/i, fix: function fix() { return stateProps; } }, { // everything else reg: /.*/, fix: function fix() { return commonProps; } }], typeFixerMap = {} // used to map event types to fixer functions (above), a basic cache mechanism , Event = function Event(event, element, isNative) { if (!arguments.length) return; event = event || ((element.ownerDocument || element.document || element).parentWindow || win).event; this.originalEvent = event; this.isNative = isNative; this.isBean = true; if (!event) return; var type = event.type, target = event.target || event.srcElement, i, l, p, props, fixer; this.target = target && target.nodeType === 3 ? target.parentNode : target; if (isNative) { // we only need basic augmentation on custom events, the rest expensive & pointless fixer = typeFixerMap[type]; if (!fixer) { // haven't encountered this event type before, map a fixer function for it for (i = 0, l = typeFixers.length; i < l; i++) { if (typeFixers[i].reg.test(type)) { // guaranteed to match at least one, last is .* typeFixerMap[type] = fixer = typeFixers[i].fix; break; } } } props = fixer(event, this, type); for (i = props.length; i--;) { if (!((p = props[i]) in this) && p in event) this[p] = event[p]; } } }; // preventDefault() and stopPropagation() are a consistent interface to those functions // on the DOM, stop() is an alias for both of them together Event.prototype.preventDefault = function () { if (this.originalEvent.preventDefault) this.originalEvent.preventDefault();else this.originalEvent.returnValue = false; }; Event.prototype.stopPropagation = function () { if (this.originalEvent.stopPropagation) this.originalEvent.stopPropagation();else this.originalEvent.cancelBubble = true; }; Event.prototype.stop = function () { this.preventDefault(); this.stopPropagation(); this.stopped = true; }; // stopImmediatePropagation() has to be handled internally because we manage the event list for // each element // note that originalElement may be a Bean#Event object in some situations Event.prototype.stopImmediatePropagation = function () { if (this.originalEvent.stopImmediatePropagation) this.originalEvent.stopImmediatePropagation(); this.isImmediatePropagationStopped = function () { return true; }; }; Event.prototype.isImmediatePropagationStopped = function () { return this.originalEvent.isImmediatePropagationStopped && this.originalEvent.isImmediatePropagationStopped(); }; Event.prototype.clone = function (currentTarget) { //TODO: this is ripe for optimisation, new events are *expensive* // improving this will speed up delegated events var ne = new Event(this, this.element, this.isNative); ne.currentTarget = currentTarget; return ne; }; return Event; }() // if we're in old IE we can't do onpropertychange on doc or win so we use doc.documentElement for both , targetElement = function targetElement(element, isNative) { return !W3C_MODEL && !isNative && (element === doc || element === win) ? root : element; } /** * Bean maintains an internal registry for event listeners. We don't touch elements, objects * or functions to identify them, instead we store everything in the registry. * Each event listener has a RegEntry object, we have one 'registry' for the whole instance. */ , RegEntry = function () { // each handler is wrapped so we can handle delegation and custom events var wrappedHandler = function wrappedHandler(element, fn, condition, args) { var call = function call(event, eargs) { return fn.apply(element, args ? slice.call(eargs, event ? 0 : 1).concat(args) : eargs); }, findTarget = function findTarget(event, eventElement) { return fn.__beanDel ? fn.__beanDel.ft(event.target, element) : eventElement; }, handler = condition ? function (event) { var target = findTarget(event, this); // deleated event if (condition.apply(target, arguments)) { if (event) event.currentTarget = target; return call(event, arguments); } } : function (event) { if (fn.__beanDel) event = event.clone(findTarget(event)); // delegated event, fix the fix return call(event, arguments); }; handler.__beanDel = fn.__beanDel; return handler; }, RegEntry = function RegEntry(element, type, handler, original, namespaces, args, root) { var customType = customEvents[type], isNative; if (type == 'unload') { // self clean-up handler = once(removeListener, element, type, handler, original); } if (customType) { if (customType.condition) { handler = wrappedHandler(element, handler, customType.condition, args); } type = customType.base || type; } this.isNative = isNative = nativeEvents[type] && !!element[eventSupport]; this.customType = !W3C_MODEL && !isNative && type; this.element = element; this.type = type; this.original = original; this.namespaces = namespaces; this.eventType = W3C_MODEL || isNative ? type : 'propertychange'; this.target = targetElement(element, isNative); this[eventSupport] = !!this.target[eventSupport]; this.root = root; this.handler = wrappedHandler(element, handler, null, args); }; // given a list of namespaces, is our entry in any of them? RegEntry.prototype.inNamespaces = function (checkNamespaces) { var i, j, c = 0; if (!checkNamespaces) return true; if (!this.namespaces) return false; for (i = checkNamespaces.length; i--;) { for (j = this.namespaces.length; j--;) { if (checkNamespaces[i] == this.namespaces[j]) c++; } } return checkNamespaces.length === c; }; // match by element, original fn (opt), handler fn (opt) RegEntry.prototype.matches = function (checkElement, checkOriginal, checkHandler) { return this.element === checkElement && (!checkOriginal || this.original === checkOriginal) && (!checkHandler || this.handler === checkHandler); }; return RegEntry; }(), registry = function () { // our map stores arrays by event type, just because it's better than storing // everything in a single array. // uses '$' as a prefix for the keys for safety and 'r' as a special prefix for // rootListeners so we can look them up fast var map = {} // generic functional search of our registry for matching listeners, // `fn` returns false to break out of the loop , forAll = function forAll(element, type, original, handler, root, fn) { var pfx = root ? 'r' : '$'; if (!type || type == '*') { // search the whole registry for (var t in map) { if (t.charAt(0) == pfx) { forAll(element, t.substr(1), original, handler, root, fn); } } } else { var i = 0, l, list = map[pfx + type], all = element == '*'; if (!list) return; for (l = list.length; i < l; i++) { if ((all || list[i].matches(element, original, handler)) && !fn(list[i], list, i, type)) return; } } }, has = function has(element, type, original, root) { // we're not using forAll here simply because it's a bit slower and this // needs to be fast var i, list = map[(root ? 'r' : '$') + type]; if (list) { for (i = list.length; i--;) { if (!list[i].root && list[i].matches(element, original, null)) return true; } } return false; }, get = function get(element, type, original, root) { var entries = []; forAll(element, type, original, null, root, function (entry) { return entries.push(entry); }); return entries; }, put = function put(entry) { var has = !entry.root && !this.has(entry.element, entry.type, null, false), key = (entry.root ? 'r' : '$') + entry.type; (map[key] || (map[key] = [])).push(entry); return has; }, del = function del(entry) { forAll(entry.element, entry.type, null, entry.handler, entry.root, function (entry, list, i) { list.splice(i, 1); entry.removed = true; if (list.length === 0) delete map[(entry.root ? 'r' : '$') + entry.type]; return false; }); } // dump all entries, used for onunload , entries = function entries() { var t, entries = []; for (t in map) { if (t.charAt(0) == '$') entries = entries.concat(map[t]); } return entries; }; return { has: has, get: get, put: put, del: del, entries: entries }; }() // we need a selector engine for delegated events, use querySelectorAll if it exists // but for older browsers we need Qwery, Sizzle or similar , selectorEngine, setSelectorEngine = function setSelectorEngine(e) { if (!arguments.length) { selectorEngine = doc.querySelectorAll ? function (s, r) { return r.querySelectorAll(s); } : function () { throw new Error('Bean: No selector engine installed'); // eeek }; } else { selectorEngine = e; } } // we attach this listener to each DOM event that we need to listen to, only once // per event type per DOM element , rootListener = function rootListener(event, type) { if (!W3C_MODEL && type && event && event.propertyName != '_on' + type) return; var listeners = registry.get(this, type || event.type, null, false), l = listeners.length, i = 0; event = new Event(event, this, true); if (type) event.type = type; // iterate through all handlers registered for this type, calling them unless they have // been removed by a previous handler or stopImmediatePropagation() has been called for (; i < l && !event.isImmediatePropagationStopped(); i++) { if (!listeners[i].removed) listeners[i].handler.call(this, event); } } // add and remove listeners to DOM elements , listener = W3C_MODEL ? function (element, type, add) { // new browsers element[add ? addEvent : removeEvent](type, rootListener, false); } : function (element, type, add, custom) { // IE8 and below, use attachEvent/detachEvent and we have to piggy-back propertychange events // to simulate event bubbling etc. var entry; if (add) { registry.put(entry = new RegEntry(element, custom || type, function (event) { // handler rootListener.call(element, event, custom); }, rootListener, null, null, true // is root )); if (custom && element['_on' + custom] == null) element['_on' + custom] = 0; entry.target.attachEvent('on' + entry.eventType, entry.handler); } else { entry = registry.get(element, custom || type, rootListener, true)[0]; if (entry) { entry.target.detachEvent('on' + entry.eventType, entry.handler); registry.del(entry); } } }, once = function once(rm, element, type, fn, originalFn) { // wrap the handler in a handler that does a remove as well return function () { fn.apply(this, arguments); rm(element, type, originalFn); }; }, removeListener = function removeListener(element, orgType, handler, namespaces) { var type = orgType && orgType.replace(nameRegex, ''), handlers = registry.get(element, type, null, false), removed = {}, i, l; for (i = 0, l = handlers.length; i < l; i++) { if ((!handler || handlers[i].original === handler) && handlers[i].inNamespaces(namespaces)) { // TODO: this is problematic, we have a registry.get() and registry.del() that // both do registry searches so we waste cycles doing this. Needs to be rolled into // a single registry.forAll(fn) that removes while finding, but the catch is that // we'll be splicing the arrays that we're iterating over. Needs extra tests to // make sure we don't screw it up. @rvagg registry.del(handlers[i]); if (!removed[handlers[i].eventType] && handlers[i][eventSupport]) removed[handlers[i].eventType] = { t: handlers[i].eventType, c: handlers[i].type }; } } // check each type/element for removed listeners and remove the rootListener where it's no longer needed for (i in removed) { if (!registry.has(element, removed[i].t, null, false)) { // last listener of this type, remove the rootListener listener(element, removed[i].t, false, removed[i].c); } } } // set up a delegate helper using the given selector, wrap the handler function , delegate = function delegate(selector, fn) { //TODO: findTarget (therefore $) is called twice, once for match and once for // setting e.currentTarget, fix this so it's only needed once var findTarget = function findTarget(target, root) { var i, array = isString(selector) ? selectorEngine(selector, root) : selector; for (; target && target !== root; target = target.parentNode) { for (i = array.length; i--;) { if (array[i] === target) return target; } } }, handler = function handler(e) { var match = findTarget(e.target, this); if (match) fn.apply(match, arguments); }; // __beanDel isn't pleasant but it's a private function, not exposed outside of Bean handler.__beanDel = { ft: findTarget // attach it here for customEvents to use too , selector: selector }; return handler; }, fireListener = W3C_MODEL ? function (isNative, type, element) { // modern browsers, do a proper dispatchEvent() var evt = doc.createEvent(isNative ? 'HTMLEvents' : 'UIEvents'); evt[isNative ? 'initEvent' : 'initUIEvent'](type, true, true, win, 1); element.dispatchEvent(evt); } : function (isNative, type, element) { // old browser use onpropertychange, just increment a custom property to trigger the event element = targetElement(element, isNative); isNative ? element.fireEvent('on' + type, doc.createEventObject()) : element['_on' + type]++; } /** * Public API: off(), on(), add(), (remove()), one(), fire(), clone() */ /** * off(element[, eventType(s)[, handler ]]) */ , off = function off(element, typeSpec, fn) { var isTypeStr = isString(typeSpec), k, type, namespaces, i; if (isTypeStr && typeSpec.indexOf(' ') > 0) { // off(el, 't1 t2 t3', fn) or off(el, 't1 t2 t3') typeSpec = str2arr(typeSpec); for (i = typeSpec.length; i--;) { off(element, typeSpec[i], fn); } return element; } type = isTypeStr && typeSpec.replace(nameRegex, ''); if (type && customEvents[type]) type = customEvents[type].base; if (!typeSpec || isTypeStr) { // off(el) or off(el, t1.ns) or off(el, .ns) or off(el, .ns1.ns2.ns3) if (namespaces = isTypeStr && typeSpec.replace(namespaceRegex, '')) namespaces = str2arr(namespaces, '.'); removeListener(element, type, fn, namespaces); } else if (isFunction(typeSpec)) { // off(el, fn) removeListener(element, null, typeSpec); } else { // off(el, { t1: fn1, t2, fn2 }) for (k in typeSpec) { if (typeSpec.hasOwnProperty(k)) off(element, k, typeSpec[k]); } } return element; } /** * on(element, eventType(s)[, selector], handler[, args ]) */ , on = function on(element, events, selector, fn) { var originalFn, type, types, i, args, entry, first; //TODO: the undefined check means you can't pass an 'args' argument, fix this perhaps? if (selector === undefined && _typeof(events) == 'object') { //TODO: this can't handle delegated events for (type in events) { if (events.hasOwnProperty(type)) { on.call(this, element, type, events[type]); } } return; } if (!isFunction(selector)) { // delegated event originalFn = fn; args = slice.call(arguments, 4); fn = delegate(selector, originalFn, selectorEngine); } else { args = slice.call(arguments, 3); fn = originalFn = selector; } types = str2arr(events); // special case for one(), wrap in a self-removing handler if (this === ONE) { fn = once(off, element, events, fn, originalFn); } for (i = types.length; i--;) { // add new handler to the registry and check if it's the first for this element/type first = registry.put(entry = new RegEntry(element, types[i].replace(nameRegex, '') // event type , fn, originalFn, str2arr(types[i].replace(namespaceRegex, ''), '.') // namespaces , args, false // not root )); if (entry[eventSupport] && first) { // first event of this type on this element, add root listener listener(element, entry.eventType, true, entry.customType); } } return element; } /** * add(element[, selector], eventType(s), handler[, args ]) * * Deprecated: kept (for now) for backward-compatibility */ , add = function add(element, events, fn, delfn) { return on.apply(null, !isString(fn) ? slice.call(arguments) : [element, fn, events, delfn].concat(arguments.length > 3 ? slice.call(arguments, 5) : [])); } /** * one(element, eventType(s)[, selector], handler[, args ]) */ , one = function one() { return on.apply(ONE, arguments); } /** * fire(element, eventType(s)[, args ]) * * The optional 'args' argument must be an array, if no 'args' argument is provided * then we can use the browser's DOM event system, otherwise we trigger handlers manually */ , fire = function fire(element, type, args) { var types = str2arr(type), i, j, l, names, handlers; for (i = types.length; i--;) { type = types[i].replace(nameRegex, ''); if (names = types[i].replace(namespaceRegex, '')) names = str2arr(names, '.'); if (!names && !args && element[eventSupport]) { fireListener(nativeEvents[type], type, element); } else { // non-native event, either because of a namespace, arguments or a non DOM element // iterate over all listeners and manually 'fire' handlers = registry.get(element, type, null, false); args = [false].concat(args); for (j = 0, l = handlers.length; j < l; j++) { if (handlers[j].inNamespaces(names)) { handlers[j].handler.apply(element, args); } } } } return element; } /** * clone(dstElement, srcElement[, eventType ]) * * TODO: perhaps for consistency we should allow the same flexibility in type specifiers? */ , clone = function clone(element, from, type) { var handlers = registry.get(from, type, null, false), l = handlers.length, i = 0, args, beanDel; for (; i < l; i++) { if (handlers[i].original) { args = [element, handlers[i].type]; if (beanDel = handlers[i].handler.__beanDel) args.push(beanDel.selector); args.push(handlers[i].original); on.apply(null, args); } } return element; }, bean = { 'on': on, 'add': add, 'one': one, 'off': off, 'remove': off, 'clone': clone, 'fire': fire, 'Event': Event, 'setSelectorEngine': setSelectorEngine, 'noConflict': function noConflict() { context[name] = old; return this; } // for IE, clean up on unload to avoid leaks }; if (win.attachEvent) { var cleanup = function cleanup() { var i, entries = registry.entries(); for (i in entries) { if (entries[i].type && entries[i].type !== 'unload') off(entries[i].element, entries[i].type); } win.detachEvent('onunload', cleanup); win.CollectGarbage && win.CollectGarbage(); }; win.attachEvent('onunload', cleanup); } // initialize selector engine to internal default (qSA or throw Error) setSelectorEngine(); return bean; }); /***/ }), /***/ "./src/behavior/Behavior.js": /*!**********************************!*\ !*** ./src/behavior/Behavior.js ***! \**********************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return Behavior; }); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } var Behavior = /*#__PURE__*/ function () { function Behavior(renderer) { _classCallCheck(this, Behavior); this.renderer = renderer; } _createClass(Behavior, [{ key: "destroy", value: function destroy() { delete this.renderer; } }]); return Behavior; }(); /***/ }), /***/ "./src/behavior/GraphBehavior.js": /*!***************************************!*\ !*** ./src/behavior/GraphBehavior.js ***! \***************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony import */ var _Behavior__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Behavior */ "./src/behavior/Behavior.js"); function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } /** * Created by tong on 6/28/2016. */ /** * Graph handler handles Panning and Zoom and rubber band selection */ var GraphBehavior = /*#__PURE__*/ function (_Behavior) { _inherits(GraphBehavior, _Behavior); function GraphBehavior(renderer) { var _this; _classCallCheck(this, GraphBehavior); _this = _possibleConstructorReturn(this, _getPrototypeOf(GraphBehavior).call(this, renderer)); var dispatcher = renderer.dispatcher; // TODO: // let f = function(type, ns, graph, pos, event) { // //Cursor.updateCursor(type, ns, graph, event); // }; dispatcher.register(/^drag.*\.graph$/, _this.handleDrag, _assertThisInitialized(_this)); dispatcher.register(/^zoom/, _this.handleZoom, _assertThisInitialized(_this)); // dispatcher.register(['mousedown.graph', 'mouseenter.graph', 'mouseleave.graph'], f); _this.offset = null; return _this; } _createClass(GraphBehavior, [{ key: "handleZoom", value: function handleZoom(type, ns, graph, pos, event) { this.renderer.transform(null, null, event.scale); } }, { key: "handleDrag", value: function handleDrag(type, ns, graph, pos, event) { if (type == 'dragstart') { var pan = this.renderer.prop('defaultClickMode') == 'pan' ^ (event.ctrlKey || event.shiftKey); if (!pan) return; var t = this.renderer.translate; this.offset = [t[0] - pos[0], t[1] - pos[1]]; return; } if (!this.offset) return; this.renderer.transform(pos[0] + this.offset[0], pos[1] + this.offset[1]); if (type == 'dragend') { // Cursor.updateCursor('mouseup', ns, graph, event); delete this.offset; } } }]); return GraphBehavior; }(_Behavior__WEBPACK_IMPORTED_MODULE_0__["default"]); /* harmony default export */ __webpack_exports__["default"] = (GraphBehavior); /***/ }), /***/ "./src/behavior/SelectionBehavior.js": /*!*******************************************!*\ !*** ./src/behavior/SelectionBehavior.js ***! \*******************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony import */ var _geometry_Rectangle__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../geometry/Rectangle */ "./src/geometry/Rectangle.js"); /* harmony import */ var _graph_Cell__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../graph/Cell */ "./src/graph/Cell.js"); /* harmony import */ var _Behavior__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Behavior */ "./src/behavior/Behavior.js"); function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); } function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } var SelectionBehavior = /*#__PURE__*/ function (_Behavior) { _inherits(SelectionBehavior, _Behavior); function SelectionBehavior(renderer) { var _this; _classCallCheck(this, SelectionBehavior); _this = _possibleConstructorReturn(this, _getPrototypeOf(SelectionBehavior).call(this, renderer)); var dispatcher = renderer.dispatcher; dispatcher.register('mousedown.*', _this.selectCell, _assertThisInitialized(_this)); dispatcher.register('mouseup.*', _this.unselectCell, _assertThisInitialized(_this)); dispatcher.register('drag*.graph', _this.handleMultiSelect, _assertThisInitialized(_this)); // graph.on(Graph.EVENT_TYPES.SELECTION_CHANGE, this.updateSelections, this) _this.selectedNodes = null; _this.selectedLinks = null; _this.attachedLinks = null; return _this; } _createClass(SelectionBehavior, [{ key: "updateSelections", value: function updateSelections() { if (this.selectedNodes) { this.selectedNodes.classed('selected', false); } if (this.selectedLinks) { this.selectedLinks.classed('selected', false); } this.selectedNodes = null; this.selectedLinks = null; this.attachedLinks = null; if (this.graph.selectedVertices && this.graph.selectedVertices.length > 0) { this.selectedNodes = this.graph.renderer.getShapes(this.graph.selectedVertices); this.attachedLinks = this.graph.renderer.getShapes(this.graph.getAttachedEdges()); this.selectedNodes.classed('selected', true); } if (this.graph.selectedEdges && this.graph.selectedEdges.length > 0) { this.selectedLinks = this.graph.renderer.getShapes(this.graph.selectedEdges); this.selectedLinks.classed('selected', true); } } }, { key: "selectCell", value: function selectCell(type, ns, data, pos, event) { var cell = data === this.graph ? null : data; if (cell && !(cell instanceof _graph_Cell__WEBPACK_IMPORTED_MODULE_1__["default"])) return; var toggle = event.ctrlKey || event.shiftKey; if (cell && cell instanceof _graph_Cell__WEBPACK_IMPORTED_MODULE_1__["default"]) { if (!this.graph.isSelected(cell)) { delete cell._firstSelection; } else { cell._firstSelection = true; } d3.select(event.dataTarget).moveToFront(); this.graph.setSelection(cell, toggle); } } }, { key: "unselectCell", value: function unselectCell(type, ns, data, pos, event) { var cell = data === this.graph ? null : data; if (cell && !(cell instanceof _graph_Cell__WEBPACK_IMPORTED_MODULE_1__["default"])) return; var ctrlKey = event.ctrlKey || event.shiftKey; if (!cell) { this.graph.setSelection(cell, ctrlKey); } } }, { key: "handleMultiSelect", value: function handleMultiSelect(type, ns, data, pos, event) { pos = util.scale(this.graph, pos); if (type === 'dragstart') { var select = this.graph.getProperty('defaultClickMode') == 'select' ^ (event.ctrlKey || event.shiftKey); if (!select) return; this.startPt = new Point(pos[0], pos[1]); return; } if (!this.startPt) return; var rect = _geometry_Rectangle__WEBPACK_IMPORTED_MODULE_0__["default"].getBoundingRectangle([new Point(pos[0], pos[1]), this.startPt]); var renderer = this.graph.renderer; if (!this.rubberband) { this.rubberband = d3.select(renderer.appendNode(renderer.getCellLayer(), { template: _.template('<g><rect x="0" y="0" width="100" height="100" stroke="#000000" fill="none" stroke-dasharray="3 3"/></g>') }, false)); } if (type == 'dragend') { var cells = this.graph.getCurrentRoot().children; // TODO: Define if we want to select vertexes / edges or both cells = _.filter(cells, function (cell) { var box = cell.getBounds(); if (rect.contains(box)) { return true; } return false; }); // TODO: Set selection this.graph.setSelection(cells, event.ctrlKey); this.rubberband.remove(); delete this.startPt; delete this.rubberband; return; } this.rubberband.select('rect').attr({ x: rect.x, y: rect.y, width: rect.width, height: rect.height }); } }, { key: "destroy", value: function destroy() { _get(_getPrototypeOf(SelectionBehavior.prototype), "destroy", this).call(this); delete this.selectedNodes; delete this.selectedLinks; delete this.attachedLinks; } }]); return SelectionBehavior; }(_Behavior__WEBPACK_IMPORTED_MODULE_2__["default"]); /* harmony default export */ __webpack_exports__["default"] = (SelectionBehavior); /***/ }), /***/ "./src/event/event-dispatcher.js": /*!***************************************!*\ !*** ./src/event/event-dispatcher.js ***! \***************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return EventDispatcher; }); /* harmony import */ var lodash__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! lodash */ "lodash"); /* harmony import */ var lodash__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(lodash__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _lib_bean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../lib/bean */ "./lib/bean.js"); /* harmony import */ var _lib_bean__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_lib_bean__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _key_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./key-utils */ "./src/event/key-utils.js"); /* harmony import */ var _util_dom_utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../util/dom-utils */ "./src/util/dom-utils.js"); /* harmony import */ var _util_string_buffer__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../util/string-buffer */ "./src/util/string-buffer.js"); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } // import Utils from '../util/Utils' var DEFAULTS = { stopPropagation: false }; var win = typeof window !== 'undefined' ? window : { addEventHandler: function addEventHandler() {} }; var doc = typeof document !== 'undefined' ? document : {}