qgraph
Version:
A Graph Manipulation and Visualization Library
1,244 lines (1,074 loc) • 267 kB
JavaScript
(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 : {}