{"version":3,"sources":["node_modules/browser-pack/_prelude.js","src/animation.js","src/collection/algorithms/a-star.js","src/collection/algorithms/bellman-ford.js","src/collection/algorithms/betweenness-centrality.js","src/collection/algorithms/bfs-dfs.js","src/collection/algorithms/closeness-centrality.js","src/collection/algorithms/degree-centrality.js","src/collection/algorithms/floyd-warshall.js","src/collection/algorithms/index.js","src/collection/algorithms/kerger-stein.js","src/collection/algorithms/page-rank.js","src/collection/animation.js","src/collection/class.js","src/collection/comparators.js","src/collection/compounds.js","src/collection/data.js","src/collection/degree.js","src/collection/dimensions.js","src/collection/element.js","src/collection/events.js","src/collection/filter.js","src/collection/group.js","src/collection/index.js","src/collection/iteration.js","src/collection/layout.js","src/collection/style.js","src/collection/switch-functions.js","src/collection/traversing.js","src/collection/zsort.js","src/core/add-remove.js","src/core/animation.js","src/core/events.js","src/core/export.js","src/core/index.js","src/core/layout.js","src/core/notification.js","src/core/renderer.js","src/core/search.js","src/core/style.js","src/core/viewport.js","src/define.js","src/event.js","src/extension.js","src/extensions/index.js","src/extensions/layout/breadthfirst.js","src/extensions/layout/circle.js","src/extensions/layout/concentric.js","src/extensions/layout/cose.js","src/extensions/layout/grid.js","src/extensions/layout/index.js","src/extensions/layout/null.js","src/extensions/layout/preset.js","src/extensions/layout/random.js","src/extensions/renderer/base/arrow-shapes.js","src/extensions/renderer/base/cached-eles.js","src/extensions/renderer/base/coord-ele-math.js","src/extensions/renderer/base/images.js","src/extensions/renderer/base/index.js","src/extensions/renderer/base/load-listeners.js","src/extensions/renderer/base/node-shapes.js","src/extensions/renderer/base/redraw.js","src/extensions/renderer/canvas/arrow-shapes.js","src/extensions/renderer/canvas/drawing-edges.js","src/extensions/renderer/canvas/drawing-images.js","src/extensions/renderer/canvas/drawing-label-text.js","src/extensions/renderer/canvas/drawing-nodes.js","src/extensions/renderer/canvas/drawing-redraw.js","src/extensions/renderer/canvas/drawing-shapes.js","src/extensions/renderer/canvas/export-image.js","src/extensions/renderer/canvas/index.js","src/extensions/renderer/canvas/node-shapes.js","src/extensions/renderer/index.js","src/extensions/renderer/null/index.js","src/fabric.js","src/heap.js","src/index.js","src/is.js","src/jquery-plugin.js","src/math.js","src/promise.js","src/selector.js","src/style/apply.js","src/style/bypass.js","src/style/container.js","src/style/get-for-ele.js","src/style/index.js","src/style/json.js","src/style/parse.js","src/style/properties.js","src/style/string-sheet.js","src/stylesheet.js","src/thread.js","src/util/colors.js","src/util/index.js","src/util/maps.js","src/util/memoize.js","src/util/regex.js","src/util/strings.js","src/util/timing.js","src/window.js"],"names":[],"mappings":"AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3LA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtoBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnrBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjcA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzjBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3hBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxyBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9yCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChqDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACp1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7XA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClqBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3YA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACp4BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACl4BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3kBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACleA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzJA;AACA","file":"cytoscape.js","sourceRoot":"/source/","sourcesContent":["(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o 0) {\n var minPos = findMin(openSet, fScore);\n var cMin = cy.getElementById( openSet[minPos] );\n steps++;\n\n // If we've found our goal, then we are done\n if (cMin.id() == target.id()) {\n var rPath = reconstructPath(source.id(), target.id(), cameFrom, []);\n rPath.reverse();\n return {\n found : true,\n distance : gScore[cMin.id()],\n path : eles.spawn(rPath),\n steps : steps\n };\n }\n\n // Add cMin to processed nodes\n closedSet.push(cMin.id());\n // Remove cMin from boundary nodes\n openSet.splice(minPos, 1);\n\n // Update scores for neighbors of cMin\n // Take into account if graph is directed or not\n var vwEdges = cMin.connectedEdges();\n if( directed ){ vwEdges = vwEdges.stdFilter(function(ele){ return ele.data('source') === cMin.id(); }); }\n vwEdges = vwEdges.intersect(edges);\n\n for (var i = 0; i < vwEdges.length; i++) {\n var e = vwEdges[i];\n var w = e.connectedNodes().stdFilter(function(n){ return n.id() !== cMin.id(); }).intersect(nodes);\n\n // if node is in closedSet, ignore it\n if (closedSet.indexOf(w.id()) != -1) {\n continue;\n }\n\n // New tentative score for node w\n var tempScore = gScore[cMin.id()] + weightFn.apply(e, [e]);\n\n // Update gScore for node w if:\n // w not present in openSet\n // OR\n // tentative gScore is less than previous value\n\n // w not in openSet\n if (openSet.indexOf(w.id()) == -1) {\n gScore[w.id()] = tempScore;\n fScore[w.id()] = tempScore + heuristic(w);\n openSet.push(w.id()); // Add node to openSet\n cameFrom[w.id()] = cMin.id();\n cameFromEdge[w.id()] = e.id();\n continue;\n }\n // w already in openSet, but with greater gScore\n if (tempScore < gScore[w.id()]) {\n gScore[w.id()] = tempScore;\n fScore[w.id()] = tempScore + heuristic(w);\n cameFrom[w.id()] = cMin.id();\n }\n\n } // End of neighbors update\n\n } // End of main loop\n\n // If we've reached here, then we've not reached our goal\n return {\n found : false,\n distance : undefined,\n path : undefined,\n steps : steps\n };\n }\n\n}); // elesfn\n\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../../is');\nvar util = require('../../util');\n\nvar elesfn = ({\n\n // Implemented from pseudocode from wikipedia\n bellmanFord: function(options) {\n var eles = this;\n\n options = options || {};\n\n // Weight function - optional\n if (options.weight != null && is.fn(options.weight)) {\n var weightFn = options.weight;\n } else {\n // If not specified, assume each edge has equal weight (1)\n var weightFn = function(e) {return 1;};\n }\n\n // directed - optional\n if (options.directed != null) {\n var directed = options.directed;\n } else {\n var directed = false;\n }\n\n // root - mandatory!\n if (options.root != null) {\n if (is.string(options.root)) {\n // use it as a selector, e.g. \"#rootID\n var source = this.filter(options.root)[0];\n } else {\n var source = options.root[0];\n }\n } else {\n return undefined;\n }\n\n var cy = this._private.cy;\n var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });\n var nodes = this.nodes();\n var numNodes = nodes.length;\n\n // mapping: node id -> position in nodes array\n var id2position = {};\n for (var i = 0; i < numNodes; i++) {\n id2position[nodes[i].id()] = i;\n }\n\n // Initializations\n var cost = [];\n var predecessor = [];\n var predEdge = [];\n\n for (var i = 0; i < numNodes; i++) {\n if (nodes[i].id() === source.id()) {\n cost[i] = 0;\n } else {\n cost[i] = Infinity;\n }\n predecessor[i] = undefined;\n }\n\n // Edges relaxation\n var flag = false;\n for (var i = 1; i < numNodes; i++) {\n flag = false;\n for (var e = 0; e < edges.length; e++) {\n var sourceIndex = id2position[edges[e].source().id()];\n var targetIndex = id2position[edges[e].target().id()];\n var weight = weightFn.apply(edges[e], [edges[e]]);\n\n var temp = cost[sourceIndex] + weight;\n if (temp < cost[targetIndex]) {\n cost[targetIndex] = temp;\n predecessor[targetIndex] = sourceIndex;\n predEdge[targetIndex] = edges[e];\n flag = true;\n }\n\n // If undirected graph, we need to take into account the 'reverse' edge\n if (!directed) {\n var temp = cost[targetIndex] + weight;\n if (temp < cost[sourceIndex]) {\n cost[sourceIndex] = temp;\n predecessor[sourceIndex] = targetIndex;\n predEdge[sourceIndex] = edges[e];\n flag = true;\n }\n }\n }\n\n if (!flag) {\n break;\n }\n }\n\n if (flag) {\n // Check for negative weight cycles\n for (var e = 0; e < edges.length; e++) {\n var sourceIndex = id2position[edges[e].source().id()];\n var targetIndex = id2position[edges[e].target().id()];\n var weight = weightFn.apply(edges[e], [edges[e]]);\n\n if (cost[sourceIndex] + weight < cost[targetIndex]) {\n util.error(\"Graph contains a negative weight cycle for Bellman-Ford\");\n return { pathTo: undefined,\n distanceTo: undefined,\n hasNegativeWeightCycle: true};\n }\n }\n }\n\n // Build result object\n var position2id = [];\n for (var i = 0; i < numNodes; i++) {\n position2id.push(nodes[i].id());\n }\n\n\n var res = {\n distanceTo : function(to) {\n if (is.string(to)) {\n // to is a selector string\n var toId = (cy.filter(to)[0]).id();\n } else {\n // to is a node\n var toId = to.id();\n }\n\n return cost[id2position[toId]];\n },\n\n pathTo : function(to) {\n\n var reconstructPathAux = function(predecessor, fromPos, toPos, position2id, acumPath, predEdge) {\n for(;;){\n // Add toId to path\n acumPath.push( cy.getElementById(position2id[toPos]) );\n acumPath.push( predEdge[toPos] );\n\n if (fromPos === toPos) {\n // reached starting node\n return acumPath;\n }\n\n // If no path exists, discart acumulated path and return undefined\n var predPos = predecessor[toPos];\n if (typeof predPos === \"undefined\") {\n return undefined;\n }\n\n toPos = predPos;\n }\n\n };\n\n if (is.string(to)) {\n // to is a selector string\n var toId = (cy.filter(to)[0]).id();\n } else {\n // to is a node\n var toId = to.id();\n }\n var path = [];\n\n // This returns a reversed path\n var res = reconstructPathAux(predecessor,\n id2position[source.id()],\n id2position[toId],\n position2id,\n path,\n predEdge);\n\n // Get it in the correct order and return it\n if (res != null) {\n res.reverse();\n }\n\n return eles.spawn(res);\n },\n\n hasNegativeWeightCycle: false\n };\n\n return res;\n\n } // bellmanFord\n\n}); // elesfn\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../../is');\n\nvar elesfn = ({\n\n // Implemented from the algorithm in the paper \"On Variants of Shortest-Path Betweenness Centrality and their Generic Computation\" by Ulrik Brandes\n betweennessCentrality: function (options) {\n options = options || {};\n\n // Weight - optional\n if (options.weight != null && is.fn(options.weight)) {\n var weightFn = options.weight;\n var weighted = true;\n } else {\n var weighted = false;\n }\n\n // Directed - default false\n if (options.directed != null && is.bool(options.directed)) {\n var directed = options.directed;\n } else {\n var directed = false;\n }\n\n var priorityInsert = function (queue, ele) {\n queue.unshift(ele);\n for (var i = 0; d[queue[i]] < d[queue[i + 1]] && i < queue.length - 1; i++) {\n var tmp = queue[i];\n queue[i] = queue[i + 1];\n queue[i + 1] = tmp;\n }\n };\n\n var cy = this._private.cy;\n\n // starting\n var V = this.nodes();\n var A = {};\n var C = {};\n\n // A contains the neighborhoods of every node\n for (var i = 0; i < V.length; i++) {\n if (directed) {\n A[V[i].id()] = V[i].outgoers(\"node\"); // get outgoers of every node\n } else {\n A[V[i].id()] = V[i].openNeighborhood(\"node\"); // get neighbors of every node\n }\n }\n\n // C contains the betweenness values\n for (var i = 0; i < V.length; i++) {\n C[V[i].id()] = 0;\n }\n\n for (var s = 0; s < V.length; s++) {\n var S = []; // stack\n var P = {};\n var g = {};\n var d = {};\n var Q = []; // queue\n\n // init dictionaries\n for (var i = 0; i < V.length; i++) {\n P[V[i].id()] = [];\n g[V[i].id()] = 0;\n d[V[i].id()] = Number.POSITIVE_INFINITY;\n }\n\n g[V[s].id()] = 1; // sigma\n d[V[s].id()] = 0; // distance to s\n\n Q.unshift(V[s].id());\n\n while (Q.length > 0) {\n var v = Q.pop();\n S.push(v);\n if (weighted) {\n A[v].forEach(function (w) {\n if (cy.$('#' + v).edgesTo(w).length > 0) {\n var edge = cy.$('#' + v).edgesTo(w)[0];\n } else {\n var edge = w.edgesTo('#' + v)[0];\n }\n\n var edgeWeight = weightFn.apply(edge, [edge]);\n\n if (d[w.id()] > d[v] + edgeWeight) {\n d[w.id()] = d[v] + edgeWeight;\n if (Q.indexOf(w.id()) < 0) { //if w is not in Q\n priorityInsert(Q, w.id());\n } else { // update position if w is in Q\n Q.splice(Q.indexOf(w.id()), 1);\n priorityInsert(Q, w.id());\n }\n g[w.id()] = 0;\n P[w.id()] = [];\n }\n if (d[w.id()] == d[v] + edgeWeight) {\n g[w.id()] = g[w.id()] + g[v];\n P[w.id()].push(v);\n }\n });\n } else {\n A[v].forEach(function (w) {\n if (d[w.id()] == Number.POSITIVE_INFINITY) {\n Q.unshift(w.id());\n d[w.id()] = d[v] + 1;\n }\n if (d[w.id()] == d[v] + 1) {\n g[w.id()] = g[w.id()] + g[v];\n P[w.id()].push(v);\n }\n });\n }\n }\n\n var e = {};\n for (var i = 0; i < V.length; i++) {\n e[V[i].id()] = 0;\n }\n\n while (S.length > 0) {\n var w = S.pop();\n P[w].forEach(function (v) {\n e[v] = e[v] + (g[v] / g[w]) * (1 + e[w]);\n if (w != V[s].id())\n C[w] = C[w] + e[w];\n });\n }\n }\n\n var max = 0;\n for (var key in C) {\n if (max < C[key])\n max = C[key];\n }\n\n var ret = {\n betweenness: function (node) {\n if (is.string(node)) {\n var node = (cy.filter(node)[0]).id();\n } else {\n var node = node.id();\n }\n\n return C[node];\n },\n\n betweennessNormalized: function (node) {\n if (is.string(node)) {\n var node = (cy.filter(node)[0]).id();\n } else {\n var node = node.id();\n }\n\n return C[node] / max;\n }\n };\n\n // alias\n ret.betweennessNormalised = ret.betweennessNormalized;\n\n return ret;\n } // betweennessCentrality\n\n}); // elesfn\n\n// nice, short mathemathical alias\nelesfn.bc = elesfn.betweennessCentrality;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../../is');\nvar Heap = require('../../heap');\n\nvar defineSearch = function( params ){\n params = {\n bfs: params.bfs || !params.dfs,\n dfs: params.dfs || !params.bfs\n };\n\n // from pseudocode on wikipedia\n return function searchFn( roots, fn, directed ){\n var options;\n var std;\n var thisArg;\n if( is.plainObject(roots) && !is.elementOrCollection(roots) ){\n options = roots;\n roots = options.roots || options.root;\n fn = options.visit;\n directed = options.directed;\n std = options.std;\n thisArg = options.thisArg;\n }\n\n directed = arguments.length === 2 && !is.fn(fn) ? fn : directed;\n fn = is.fn(fn) ? fn : function(){};\n\n var cy = this._private.cy;\n var v = roots = is.string(roots) ? this.filter(roots) : roots;\n var Q = [];\n var connectedNodes = [];\n var connectedBy = {};\n var id2depth = {};\n var V = {};\n var j = 0;\n var found;\n var nodes = this.nodes();\n var edges = this.edges();\n\n // enqueue v\n for( var i = 0; i < v.length; i++ ){\n if( v[i].isNode() ){\n Q.unshift( v[i] );\n\n if( params.bfs ){\n V[ v[i].id() ] = true;\n\n connectedNodes.push( v[i] );\n }\n\n id2depth[ v[i].id() ] = 0;\n }\n }\n\n while( Q.length !== 0 ){\n var v = params.bfs ? Q.shift() : Q.pop();\n\n if( params.dfs ){\n if( V[ v.id() ] ){ continue; }\n\n V[ v.id() ] = true;\n\n connectedNodes.push( v );\n }\n\n var depth = id2depth[ v.id() ];\n var prevEdge = connectedBy[ v.id() ];\n var prevNode = prevEdge == null ? undefined : prevEdge.connectedNodes().not( v )[0];\n var ret;\n\n if( std ){\n ret = fn.call(thisArg, v, prevEdge, prevNode, j++, depth);\n } else {\n ret = fn.call(v, j++, depth, v, prevEdge, prevNode);\n }\n\n if( ret === true ){\n found = v;\n break;\n }\n\n if( ret === false ){\n break;\n }\n\n var vwEdges = v.connectedEdges(directed ? function(){ return this.data('source') === v.id(); } : undefined).intersect( edges );\n for( var i = 0; i < vwEdges.length; i++ ){\n var e = vwEdges[i];\n var w = e.connectedNodes(function(){ return this.id() !== v.id(); }).intersect( nodes );\n\n if( w.length !== 0 && !V[ w.id() ] ){\n w = w[0];\n\n Q.push( w );\n\n if( params.bfs ){\n V[ w.id() ] = true;\n\n connectedNodes.push( w );\n }\n\n connectedBy[ w.id() ] = e;\n\n id2depth[ w.id() ] = id2depth[ v.id() ] + 1;\n }\n }\n\n }\n\n var connectedEles = [];\n\n for( var i = 0; i < connectedNodes.length; i++ ){\n var node = connectedNodes[i];\n var edge = connectedBy[ node.id() ];\n\n if( edge ){\n connectedEles.push( edge );\n }\n\n connectedEles.push( node );\n }\n\n return {\n path: cy.collection( connectedEles, { unique: true } ),\n found: cy.collection( found )\n };\n };\n};\n\n// search, spanning trees, etc\nvar elesfn = ({\n\n breadthFirstSearch: defineSearch({ bfs: true }),\n depthFirstSearch: defineSearch({ dfs: true }),\n\n // kruskal's algorithm (finds min spanning tree, assuming undirected graph)\n // implemented from pseudocode from wikipedia\n kruskal: function( weightFn ){\n var cy = this.cy();\n\n weightFn = is.fn(weightFn) ? weightFn : function(){ return 1; }; // if not specified, assume each edge has equal weight (1)\n\n function findSet(ele){\n for( var i = 0; i < forest.length; i++ ){\n var eles = forest[i];\n\n if( eles.anySame(ele) ){\n return {\n eles: eles,\n index: i\n };\n }\n }\n }\n\n var A = cy.collection(cy, []);\n var forest = [];\n var nodes = this.nodes();\n\n for( var i = 0; i < nodes.length; i++ ){\n forest.push( nodes[i].collection() );\n }\n\n var edges = this.edges();\n var S = edges.toArray().sort(function(a, b){\n var weightA = weightFn.call(a, a);\n var weightB = weightFn.call(b, b);\n\n return weightA - weightB;\n });\n\n for(var i = 0; i < S.length; i++){\n var edge = S[i];\n var u = edge.source()[0];\n var v = edge.target()[0];\n var setU = findSet(u);\n var setV = findSet(v);\n\n if( setU.index !== setV.index ){\n A = A.add( edge );\n\n // combine forests for u and v\n forest[ setU.index ] = setU.eles.add( setV.eles );\n forest.splice( setV.index, 1 );\n }\n }\n\n return nodes.add( A );\n\n },\n\n dijkstra: function( root, weightFn, directed ){\n var options;\n if( is.plainObject(root) && !is.elementOrCollection(root) ){\n options = root;\n root = options.root;\n weightFn = options.weight;\n directed = options.directed;\n }\n\n var cy = this._private.cy;\n weightFn = is.fn(weightFn) ? weightFn : function(){ return 1; }; // if not specified, assume each edge has equal weight (1)\n\n var source = is.string(root) ? this.filter(root)[0] : root[0];\n var dist = {};\n var prev = {};\n var knownDist = {};\n\n var edges = this.edges().filter(function(){ return !this.isLoop(); });\n var nodes = this.nodes();\n\n var getDist = function(node){\n return dist[ node.id() ];\n };\n\n var setDist = function(node, d){\n dist[ node.id() ] = d;\n\n Q.updateItem( node );\n };\n\n var Q = new Heap(function( a, b ){\n return getDist(a) - getDist(b);\n });\n\n for( var i = 0; i < nodes.length; i++ ){\n var node = nodes[i];\n\n dist[ node.id() ] = node.same( source ) ? 0 : Infinity;\n Q.push( node );\n }\n\n var distBetween = function(u, v){\n var uvs = ( directed ? u.edgesTo(v) : u.edgesWith(v) ).intersect(edges);\n var smallestDistance = Infinity;\n var smallestEdge;\n\n for( var i = 0; i < uvs.length; i++ ){\n var edge = uvs[i];\n var weight = weightFn.apply( edge, [edge] );\n\n if( weight < smallestDistance || !smallestEdge ){\n smallestDistance = weight;\n smallestEdge = edge;\n }\n }\n\n return {\n edge: smallestEdge,\n dist: smallestDistance\n };\n };\n\n while( Q.size() > 0 ){\n var u = Q.pop();\n var smalletsDist = getDist(u);\n var uid = u.id();\n\n knownDist[uid] = smalletsDist;\n\n if( smalletsDist === Math.Infinite ){\n break;\n }\n\n var neighbors = u.neighborhood().intersect(nodes);\n for( var i = 0; i < neighbors.length; i++ ){\n var v = neighbors[i];\n var vid = v.id();\n var vDist = distBetween(u, v);\n\n var alt = smalletsDist + vDist.dist;\n\n if( alt < getDist(v) ){\n setDist(v, alt);\n\n prev[ vid ] = {\n node: u,\n edge: vDist.edge\n };\n }\n } // for\n } // while\n\n return {\n distanceTo: function(node){\n var target = is.string(node) ? nodes.filter(node)[0] : node[0];\n\n return knownDist[ target.id() ];\n },\n\n pathTo: function(node){\n var target = is.string(node) ? nodes.filter(node)[0] : node[0];\n var S = [];\n var u = target;\n\n if( target.length > 0 ){\n S.unshift( target );\n\n while( prev[ u.id() ] ){\n var p = prev[ u.id() ];\n\n S.unshift( p.edge );\n S.unshift( p.node );\n\n u = p.node;\n }\n }\n\n return cy.collection( S );\n }\n };\n }\n});\n\n// nice, short mathemathical alias\nelesfn.bfs = elesfn.breadthFirstSearch;\nelesfn.dfs = elesfn.depthFirstSearch;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../../is');\n\nvar elesfn = ({\n\n closenessCentralityNormalized: function (options) {\n options = options || {};\n\n var cy = this.cy();\n\n var harmonic = options.harmonic;\n if( harmonic === undefined ){\n harmonic = true;\n }\n\n var closenesses = {};\n var maxCloseness = 0;\n var nodes = this.nodes();\n var fw = this.floydWarshall({ weight: options.weight, directed: options.directed });\n\n // Compute closeness for every node and find the maximum closeness\n for(var i = 0; i < nodes.length; i++){\n var currCloseness = 0;\n for (var j = 0; j < nodes.length; j++) {\n if (i != j) {\n var d = fw.distance(nodes[i], nodes[j]);\n\n if( harmonic ){\n currCloseness += 1 / d;\n } else {\n currCloseness += d;\n }\n }\n }\n\n if( !harmonic ){\n currCloseness = 1 / currCloseness;\n }\n\n if (maxCloseness < currCloseness){\n maxCloseness = currCloseness;\n }\n\n closenesses[nodes[i].id()] = currCloseness;\n }\n\n return {\n closeness: function (node) {\n if (is.string(node)) {\n // from is a selector string\n var node = (cy.filter(node)[0]).id();\n } else {\n // from is a node\n var node = node.id();\n }\n\n return closenesses[node] / maxCloseness;\n }\n };\n },\n\n // Implemented from pseudocode from wikipedia\n closenessCentrality: function (options) {\n options = options || {};\n\n // root - mandatory!\n if (options.root != null) {\n if (is.string(options.root)) {\n // use it as a selector, e.g. \"#rootID\n var root = this.filter(options.root)[0];\n } else {\n var root = options.root[0];\n }\n } else {\n return undefined;\n }\n\n // weight - optional\n if (options.weight != null && is.fn(options.weight)) {\n var weight = options.weight;\n } else {\n var weight = function(){return 1;};\n }\n\n // directed - optional\n if (options.directed != null && is.bool(options.directed)) {\n var directed = options.directed;\n } else {\n var directed = false;\n }\n\n var harmonic = options.harmonic;\n if( harmonic === undefined ){\n harmonic = true;\n }\n\n // we need distance from this node to every other node\n var dijkstra = this.dijkstra({\n root: root,\n weight: weight,\n directed: directed\n });\n var totalDistance = 0;\n\n var nodes = this.nodes();\n for (var i = 0; i < nodes.length; i++){\n if (nodes[i].id() != root.id()){\n var d = dijkstra.distanceTo(nodes[i]);\n\n if( harmonic ){\n totalDistance += 1 / d;\n } else {\n totalDistance += d;\n }\n }\n }\n\n return harmonic ? totalDistance : 1 / totalDistance;\n } // closenessCentrality\n\n}); // elesfn\n\n// nice, short mathemathical alias\nelesfn.cc = elesfn.closenessCentrality;\nelesfn.ccn = elesfn.closenessCentralityNormalised = elesfn.closenessCentralityNormalized;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../../is');\nvar util = require('../../util');\n\nvar elesfn = ({\n\n degreeCentralityNormalized: function (options) {\n options = options || {};\n\n var cy = this.cy();\n\n // directed - optional\n if (options.directed != null) {\n var directed = options.directed;\n } else {\n var directed = false;\n }\n\n var nodes = this.nodes();\n var numNodes = nodes.length;\n\n if (!directed) {\n var degrees = {};\n var maxDegree = 0;\n\n for (var i = 0; i < numNodes; i++) {\n var node = nodes[i];\n // add current node to the current options object and call degreeCentrality\n var currDegree = this.degreeCentrality(util.extend({}, options, {root: node}));\n if (maxDegree < currDegree.degree)\n maxDegree = currDegree.degree;\n\n degrees[node.id()] = currDegree.degree;\n }\n\n return {\n degree: function (node) {\n if (is.string(node)) {\n // from is a selector string\n var node = (cy.filter(node)[0]).id();\n } else {\n // from is a node\n var node = node.id();\n }\n\n return degrees[node] / maxDegree;\n }\n };\n } else {\n var indegrees = {};\n var outdegrees = {};\n var maxIndegree = 0;\n var maxOutdegree = 0;\n\n for (var i = 0; i < numNodes; i++) {\n var node = nodes[i];\n // add current node to the current options object and call degreeCentrality\n var currDegree = this.degreeCentrality(util.extend({}, options, {root: node}));\n\n if (maxIndegree < currDegree.indegree)\n maxIndegree = currDegree.indegree;\n\n if (maxOutdegree < currDegree.outdegree)\n maxOutdegree = currDegree.outdegree;\n\n indegrees[node.id()] = currDegree.indegree;\n outdegrees[node.id()] = currDegree.outdegree;\n }\n\n return {\n indegree: function (node) {\n if (is.string(node)) {\n // from is a selector string\n var node = (cy.filter(node)[0]).id();\n } else {\n // from is a node\n var node = node.id();\n }\n\n return indegrees[node] / maxIndegree;\n },\n outdegree: function (node) {\n if (is.string(node)) {\n // from is a selector string\n var node = (cy.filter(node)[0]).id();\n } else {\n // from is a node\n var node = node.id();\n }\n\n return outdegrees[node] / maxOutdegree;\n }\n\n };\n }\n\n }, // degreeCentralityNormalized\n\n // Implemented from the algorithm in Opsahl's paper\n // \"Node centrality in weighted networks: Generalizing degree and shortest paths\"\n // check the heading 2 \"Degree\"\n degreeCentrality: function (options) {\n options = options || {};\n\n var callingEles = this;\n\n // root - mandatory!\n if (options != null && options.root != null) {\n var root = is.string(options.root) ? this.filter(options.root)[0] : options.root[0];\n } else {\n return undefined;\n }\n\n // weight - optional\n if (options.weight != null && is.fn(options.weight)) {\n var weightFn = options.weight;\n } else {\n // If not specified, assume each edge has equal weight (1)\n var weightFn = function (e) {\n return 1;\n };\n }\n\n // directed - optional\n if (options.directed != null) {\n var directed = options.directed;\n } else {\n var directed = false;\n }\n\n // alpha - optional\n if (options.alpha != null && is.number(options.alpha)) {\n var alpha = options.alpha;\n } else {\n alpha = 0;\n }\n\n\n if (!directed) {\n var connEdges = root.connectedEdges().intersection( callingEles );\n var k = connEdges.length;\n var s = 0;\n\n // Now, sum edge weights\n for (var i = 0; i < connEdges.length; i++) {\n var edge = connEdges[i];\n s += weightFn.apply(edge, [edge]);\n }\n\n return {\n degree: Math.pow(k, 1 - alpha) * Math.pow(s, alpha)\n };\n } else {\n var incoming = root.connectedEdges('edge[target = \"' + root.id() + '\"]').intersection( callingEles );\n var outgoing = root.connectedEdges('edge[source = \"' + root.id() + '\"]').intersection( callingEles );\n var k_in = incoming.length;\n var k_out = outgoing.length;\n var s_in = 0;\n var s_out = 0;\n\n // Now, sum incoming edge weights\n for (var i = 0; i < incoming.length; i++) {\n var edge = incoming[i];\n s_in += weightFn.apply(edge, [edge]);\n }\n\n // Now, sum outgoing edge weights\n for (var i = 0; i < outgoing.length; i++) {\n var edge = outgoing[i];\n s_out += weightFn.apply(edge, [edge]);\n }\n\n return {\n indegree: Math.pow(k_in, 1 - alpha) * Math.pow(s_in, alpha),\n outdegree: Math.pow(k_out, 1 - alpha) * Math.pow(s_out, alpha)\n };\n }\n } // degreeCentrality\n\n}); // elesfn\n\n// nice, short mathemathical alias\nelesfn.dc = elesfn.degreeCentrality;\nelesfn.dcn = elesfn.degreeCentralityNormalised = elesfn.degreeCentralityNormalized;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../../is');\n\nvar elesfn = ({\n\n // Implemented from pseudocode from wikipedia\n floydWarshall: function(options) {\n options = options || {};\n\n var cy = this.cy();\n\n // Weight function - optional\n if (options.weight != null && is.fn(options.weight)) {\n var weightFn = options.weight;\n } else {\n // If not specified, assume each edge has equal weight (1)\n var weightFn = function(e) {return 1;};\n }\n\n // directed - optional\n if (options.directed != null) {\n var directed = options.directed;\n } else {\n var directed = false;\n }\n\n var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });\n var nodes = this.nodes();\n var numNodes = nodes.length;\n\n // mapping: node id -> position in nodes array\n var id2position = {};\n for (var i = 0; i < numNodes; i++) {\n id2position[nodes[i].id()] = i;\n }\n\n // Initialize distance matrix\n var dist = [];\n for (var i = 0; i < numNodes; i++) {\n var newRow = new Array(numNodes);\n for (var j = 0; j < numNodes; j++) {\n if (i == j) {\n newRow[j] = 0;\n } else {\n newRow[j] = Infinity;\n }\n }\n dist.push(newRow);\n }\n\n // Initialize matrix used for path reconstruction\n // Initialize distance matrix\n var next = [];\n var edgeNext = [];\n\n var initMatrix = function(next){\n for (var i = 0; i < numNodes; i++) {\n var newRow = new Array(numNodes);\n for (var j = 0; j < numNodes; j++) {\n newRow[j] = undefined;\n }\n next.push(newRow);\n }\n };\n\n initMatrix(next);\n initMatrix(edgeNext);\n\n // Process edges\n for (var i = 0; i < edges.length ; i++) {\n var sourceIndex = id2position[edges[i].source().id()];\n var targetIndex = id2position[edges[i].target().id()];\n var weight = weightFn.apply(edges[i], [edges[i]]);\n\n // Check if already process another edge between same 2 nodes\n if (dist[sourceIndex][targetIndex] > weight) {\n dist[sourceIndex][targetIndex] = weight;\n next[sourceIndex][targetIndex] = targetIndex;\n edgeNext[sourceIndex][targetIndex] = edges[i];\n }\n }\n\n // If undirected graph, process 'reversed' edges\n if (!directed) {\n for (var i = 0; i < edges.length ; i++) {\n var sourceIndex = id2position[edges[i].target().id()];\n var targetIndex = id2position[edges[i].source().id()];\n var weight = weightFn.apply(edges[i], [edges[i]]);\n\n // Check if already process another edge between same 2 nodes\n if (dist[sourceIndex][targetIndex] > weight) {\n dist[sourceIndex][targetIndex] = weight;\n next[sourceIndex][targetIndex] = targetIndex;\n edgeNext[sourceIndex][targetIndex] = edges[i];\n }\n }\n }\n\n // Main loop\n for (var k = 0; k < numNodes; k++) {\n for (var i = 0; i < numNodes; i++) {\n for (var j = 0; j < numNodes; j++) {\n if (dist[i][k] + dist[k][j] < dist[i][j]) {\n dist[i][j] = dist[i][k] + dist[k][j];\n next[i][j] = next[i][k];\n }\n }\n }\n }\n\n // Build result object\n var position2id = [];\n for (var i = 0; i < numNodes; i++) {\n position2id.push(nodes[i].id());\n }\n\n var res = {\n distance: function(from, to) {\n if (is.string(from)) {\n // from is a selector string\n var fromId = (cy.filter(from)[0]).id();\n } else {\n // from is a node\n var fromId = from.id();\n }\n\n if (is.string(to)) {\n // to is a selector string\n var toId = (cy.filter(to)[0]).id();\n } else {\n // to is a node\n var toId = to.id();\n }\n\n return dist[id2position[fromId]][id2position[toId]];\n },\n\n path: function(from, to) {\n var reconstructPathAux = function(from, to, next, position2id, edgeNext) {\n if (from === to) {\n return cy.getElementById( position2id[from] );\n }\n if (next[from][to] === undefined) {\n return undefined;\n }\n\n var path = [ cy.getElementById(position2id[from]) ];\n var prev = from;\n while (from !== to) {\n prev = from;\n from = next[from][to];\n\n var edge = edgeNext[prev][from];\n path.push( edge );\n\n path.push( cy.getElementById(position2id[from]) );\n }\n return path;\n };\n\n if (is.string(from)) {\n // from is a selector string\n var fromId = (cy.filter(from)[0]).id();\n } else {\n // from is a node\n var fromId = from.id();\n }\n\n if (is.string(to)) {\n // to is a selector string\n var toId = (cy.filter(to)[0]).id();\n } else {\n // to is a node\n var toId = to.id();\n }\n\n var pathArr = reconstructPathAux(id2position[fromId],\n id2position[toId],\n next,\n position2id,\n edgeNext);\n\n return cy.collection( pathArr );\n }\n };\n\n return res;\n\n } // floydWarshall\n\n}); // elesfn\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar util = require('../../util');\n\nvar elesfn = {};\n\n[\n require('./bfs-dfs'),\n require('./a-star'),\n require('./floyd-warshall'),\n require('./bellman-ford'),\n require('./kerger-stein'),\n require('./page-rank'),\n require('./degree-centrality'),\n require('./closeness-centrality'),\n require('./betweenness-centrality')\n].forEach(function( props ){\n util.extend( elesfn, props );\n});\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar util = require('../../util');\n\nvar elesfn = ({\n\n // Computes the minimum cut of an undirected graph\n // Returns the correct answer with high probability\n kargerStein: function(options) {\n var eles = this;\n\n options = options || {};\n\n // Function which colapses 2 (meta) nodes into one\n // Updates the remaining edge lists\n // Receives as a paramater the edge which causes the collapse\n var colapse = function(edgeIndex, nodeMap, remainingEdges) {\n var edgeInfo = remainingEdges[edgeIndex];\n var sourceIn = edgeInfo[1];\n var targetIn = edgeInfo[2];\n var partition1 = nodeMap[sourceIn];\n var partition2 = nodeMap[targetIn];\n\n // Delete all edges between partition1 and partition2\n var newEdges = remainingEdges.filter(function(edge) {\n if (nodeMap[edge[1]] === partition1 && nodeMap[edge[2]] === partition2) {\n return false;\n }\n if (nodeMap[edge[1]] === partition2 && nodeMap[edge[2]] === partition1) {\n return false;\n }\n return true;\n });\n\n // All edges pointing to partition2 should now point to partition1\n for (var i = 0; i < newEdges.length; i++) {\n var edge = newEdges[i];\n if (edge[1] === partition2) { // Check source\n newEdges[i] = edge.slice(0);\n newEdges[i][1] = partition1;\n } else if (edge[2] === partition2) { // Check target\n newEdges[i] = edge.slice(0);\n newEdges[i][2] = partition1;\n }\n }\n\n // Move all nodes from partition2 to partition1\n for (var i = 0; i < nodeMap.length; i++) {\n if (nodeMap[i] === partition2) {\n nodeMap[i] = partition1;\n }\n }\n\n return newEdges;\n };\n\n\n // Contracts a graph until we reach a certain number of meta nodes\n var contractUntil = function(metaNodeMap,\n remainingEdges,\n size,\n sizeLimit) {\n // Stop condition\n if (size <= sizeLimit) {\n return remainingEdges;\n }\n\n // Choose an edge randomly\n var edgeIndex = Math.floor((Math.random() * remainingEdges.length));\n\n // Colapse graph based on edge\n var newEdges = colapse(edgeIndex, metaNodeMap, remainingEdges);\n\n return contractUntil(metaNodeMap,\n newEdges,\n size - 1,\n sizeLimit);\n };\n\n var cy = this._private.cy;\n var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });\n var nodes = this.nodes();\n var numNodes = nodes.length;\n var numEdges = edges.length;\n var numIter = Math.ceil(Math.pow(Math.log(numNodes) / Math.LN2, 2));\n var stopSize = Math.floor(numNodes / Math.sqrt(2));\n\n if (numNodes < 2) {\n util.error(\"At least 2 nodes are required for Karger-Stein algorithm\");\n return undefined;\n }\n\n // Create numerical identifiers for each node\n // mapping: node id -> position in nodes array\n // for reverse mapping, simply use nodes array\n var id2position = {};\n for (var i = 0; i < numNodes; i++) {\n id2position[nodes[i].id()] = i;\n }\n\n // Now store edge destination as indexes\n // Format for each edge (edge index, source node index, target node index)\n var edgeIndexes = [];\n for (var i = 0; i < numEdges; i++) {\n var e = edges[i];\n edgeIndexes.push([i, id2position[e.source().id()], id2position[e.target().id()]]);\n }\n\n // We will store the best cut found here\n var minCutSize = Infinity;\n var minCut;\n\n // Initial meta node partition\n var originalMetaNode = [];\n for (var i = 0; i < numNodes; i++) {\n originalMetaNode.push(i);\n }\n\n // Main loop\n for (var iter = 0; iter <= numIter; iter++) {\n // Create new meta node partition\n var metaNodeMap = originalMetaNode.slice(0);\n\n // Contract until stop point (stopSize nodes)\n var edgesState = contractUntil(metaNodeMap, edgeIndexes, numNodes, stopSize);\n\n // Create a copy of the colapsed nodes state\n var metaNodeMap2 = metaNodeMap.slice(0);\n\n // Run 2 iterations starting in the stop state\n var res1 = contractUntil(metaNodeMap, edgesState, stopSize, 2);\n var res2 = contractUntil(metaNodeMap2, edgesState, stopSize, 2);\n\n // Is any of the 2 results the best cut so far?\n if (res1.length <= res2.length && res1.length < minCutSize) {\n minCutSize = res1.length;\n minCut = [res1, metaNodeMap];\n } else if (res2.length <= res1.length && res2.length < minCutSize) {\n minCutSize = res2.length;\n minCut = [res2, metaNodeMap2];\n }\n } // end of main loop\n\n\n // Construct result\n var resEdges = (minCut[0]).map(function(e){ return edges[e[0]]; });\n var partition1 = [];\n var partition2 = [];\n\n // traverse metaNodeMap for best cut\n var witnessNodePartition = minCut[1][0];\n for (var i = 0; i < minCut[1].length; i++) {\n var partitionId = minCut[1][i];\n if (partitionId === witnessNodePartition) {\n partition1.push(nodes[i]);\n } else {\n partition2.push(nodes[i]);\n }\n }\n\n var ret = {\n cut: eles.spawn(cy, resEdges),\n partition1: eles.spawn(partition1),\n partition2: eles.spawn(partition2)\n };\n\n return ret;\n }\n}); // elesfn\n\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../../is');\n\nvar elesfn = ({\n\n pageRank: function(options) {\n options = options || {};\n\n var normalizeVector = function(vector) {\n var length = vector.length;\n\n // First, get sum of all elements\n var total = 0;\n for (var i = 0; i < length; i++) {\n total += vector[i];\n }\n\n // Now, divide each by the sum of all elements\n for (var i = 0; i < length; i++) {\n vector[i] = vector[i] / total;\n }\n };\n\n // dampingFactor - optional\n if (options != null &&\n options.dampingFactor != null) {\n var dampingFactor = options.dampingFactor;\n } else {\n var dampingFactor = 0.8; // Default damping factor\n }\n\n // desired precision - optional\n if (options != null &&\n options.precision != null) {\n var epsilon = options.precision;\n } else {\n var epsilon = 0.000001; // Default precision\n }\n\n // Max number of iterations - optional\n if (options != null &&\n options.iterations != null) {\n var numIter = options.iterations;\n } else {\n var numIter = 200; // Default number of iterations\n }\n\n // Weight function - optional\n if (options != null &&\n options.weight != null &&\n is.fn(options.weight)) {\n var weightFn = options.weight;\n } else {\n // If not specified, assume each edge has equal weight (1)\n var weightFn = function(e) {return 1;};\n }\n\n var cy = this._private.cy;\n var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });\n var nodes = this.nodes();\n var numNodes = nodes.length;\n var numEdges = edges.length;\n\n // Create numerical identifiers for each node\n // mapping: node id -> position in nodes array\n // for reverse mapping, simply use nodes array\n var id2position = {};\n for (var i = 0; i < numNodes; i++) {\n id2position[nodes[i].id()] = i;\n }\n\n // Construct transposed adjacency matrix\n // First lets have a zeroed matrix of the right size\n // We'll also keep track of the sum of each column\n var matrix = [];\n var columnSum = [];\n var additionalProb = (1 - dampingFactor) / numNodes;\n\n // Create null matric\n for (var i = 0; i < numNodes; i++) {\n var newRow = [];\n for (var j = 0; j < numNodes; j++) {\n newRow.push(0.0);\n }\n matrix.push(newRow);\n columnSum.push(0.0);\n }\n\n // Now, process edges\n for (var i = 0; i < numEdges; i++) {\n var edge = edges[i];\n var s = id2position[edge.source().id()];\n var t = id2position[edge.target().id()];\n var w = weightFn.apply(edge, [edge]);\n\n // Update matrix\n matrix[t][s] += w;\n\n // Update column sum\n columnSum[s] += w;\n }\n\n // Add additional probability based on damping factor\n // Also, take into account columns that have sum = 0\n var p = 1.0 / numNodes + additionalProb; // Shorthand\n // Traverse matrix, column by column\n for (var j = 0; j < numNodes; j++) {\n if (columnSum[j] === 0) {\n // No 'links' out from node jth, assume equal probability for each possible node\n for (var i = 0; i < numNodes; i++) {\n matrix[i][j] = p;\n }\n } else {\n // Node jth has outgoing link, compute normalized probabilities\n for (var i = 0; i < numNodes; i++) {\n matrix[i][j] = matrix[i][j] / columnSum[j] + additionalProb;\n }\n }\n }\n\n // Compute dominant eigenvector using power method\n var eigenvector = [];\n var nullVector = [];\n var previous;\n\n // Start with a vector of all 1's\n // Also, initialize a null vector which will be used as shorthand\n for (var i = 0; i < numNodes; i++) {\n eigenvector.push(1.0);\n nullVector.push(0.0);\n }\n\n for (var iter = 0; iter < numIter; iter++) {\n // New array with all 0's\n var temp = nullVector.slice(0);\n\n // Multiply matrix with previous result\n for (var i = 0; i < numNodes; i++) {\n for (var j = 0; j < numNodes; j++) {\n temp[i] += matrix[i][j] * eigenvector[j];\n }\n }\n\n normalizeVector(temp);\n previous = eigenvector;\n eigenvector = temp;\n\n var diff = 0;\n // Compute difference (squared module) of both vectors\n for (var i = 0; i < numNodes; i++) {\n diff += Math.pow(previous[i] - eigenvector[i], 2);\n }\n\n // If difference is less than the desired threshold, stop iterating\n if (diff < epsilon) {\n break;\n }\n }\n\n // Construct result\n var res = {\n rank : function(node) {\n if (is.string(node)) {\n // is a selector string\n var nodeId = (cy.filter(node)[0]).id();\n } else {\n // is a node object\n var nodeId = node.id();\n }\n return eigenvector[id2position[nodeId]];\n }\n };\n\n\n return res;\n } // pageRank\n\n}); // elesfn\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar define = require('../define');\n\nvar elesfn = ({\n animate: define.animate(),\n animation: define.animation(),\n animated: define.animated(),\n clearQueue: define.clearQueue(),\n delay: define.delay(),\n delayAnimation: define.delayAnimation(),\n stop: define.stop()\n});\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar util = require('../util');\n\nvar elesfn = ({\n classes: function( classes ){\n classes = classes.match(/\\S+/g) || [];\n var self = this;\n var changed = [];\n var classesMap = {};\n\n // fill in classes map\n for( var i = 0; i < classes.length; i++ ){\n var cls = classes[i];\n\n classesMap[ cls ] = true;\n }\n\n // check and update each ele\n for( var j = 0; j < self.length; j++ ){\n var ele = self[j];\n var _p = ele._private;\n var eleClasses = _p.classes;\n var changedEle = false;\n\n // check if ele has all of the passed classes\n for( var i = 0; i < classes.length; i++ ){\n var cls = classes[i];\n var eleHasClass = eleClasses[ cls ];\n\n if( !eleHasClass ){\n changedEle = true;\n break;\n }\n }\n\n // check if ele has classes outside of those passed\n if( !changedEle ){ for( var eleCls in eleClasses ){\n var eleHasClass = eleClasses[ eleCls ];\n var specdClass = classesMap[ eleCls ]; // i.e. this class is passed to the function\n\n if( eleHasClass && !specdClass ){\n changedEle = true;\n break;\n }\n } }\n\n if( changedEle ){\n _p.classes = util.copy( classesMap );\n\n changed.push( ele );\n }\n }\n\n // trigger update style on those eles that had class changes\n if( changed.length > 0 ){\n this.spawn(changed)\n .updateStyle()\n .trigger('class')\n ;\n }\n\n return self;\n },\n\n addClass: function( classes ){\n return this.toggleClass( classes, true );\n },\n\n hasClass: function( className ){\n var ele = this[0];\n return ( ele != null && ele._private.classes[className] ) ? true : false;\n },\n\n toggleClass: function( classesStr, toggle ){\n var classes = classesStr.match(/\\S+/g) || [];\n var self = this;\n var changed = []; // eles who had classes changed\n\n for( var i = 0, il = self.length; i < il; i++ ){\n var ele = self[i];\n var changedEle = false;\n\n for( var j = 0; j < classes.length; j++ ){\n var cls = classes[j];\n var eleClasses = ele._private.classes;\n var hasClass = eleClasses[cls];\n var shouldAdd = toggle || (toggle === undefined && !hasClass);\n\n if( shouldAdd ){\n eleClasses[cls] = true;\n\n if( !hasClass && !changedEle ){\n changed.push(ele);\n changedEle = true;\n }\n } else { // then remove\n eleClasses[cls] = false;\n\n if( hasClass && !changedEle ){\n changed.push(ele);\n changedEle = true;\n }\n }\n\n } // for j classes\n } // for i eles\n\n // trigger update style on those eles that had class changes\n if( changed.length > 0 ){\n this.spawn(changed)\n .updateStyle()\n .trigger('class')\n ;\n }\n\n return self;\n },\n\n removeClass: function( classes ){\n return this.toggleClass( classes, false );\n },\n\n flashClass: function( classes, duration ){\n var self = this;\n\n if( duration == null ){\n duration = 250;\n } else if( duration === 0 ){\n return self; // nothing to do really\n }\n\n self.addClass( classes );\n setTimeout(function(){\n self.removeClass( classes );\n }, duration);\n\n return self;\n }\n});\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar elesfn = ({\n allAre: function( selector ){\n return this.filter(selector).length === this.length;\n },\n\n is: function( selector ){\n return this.filter(selector).length > 0;\n },\n\n some: function( fn, thisArg ){\n for( var i = 0; i < this.length; i++ ){\n var ret = !thisArg ? fn( this[i], i, this ) : fn.apply( thisArg, [ this[i], i, this ] );\n\n if( ret ){\n return true;\n }\n }\n\n return false;\n },\n\n every: function( fn, thisArg ){\n for( var i = 0; i < this.length; i++ ){\n var ret = !thisArg ? fn( this[i], i, this ) : fn.apply( thisArg, [ this[i], i, this ] );\n\n if( !ret ){\n return false;\n }\n }\n\n return true;\n },\n\n same: function( collection ){\n collection = this.cy().collection( collection );\n\n // cheap extra check\n if( this.length !== collection.length ){\n return false;\n }\n\n return this.intersect( collection ).length === this.length;\n },\n\n anySame: function( collection ){\n collection = this.cy().collection( collection );\n\n return this.intersect( collection ).length > 0;\n },\n\n allAreNeighbors: function( collection ){\n collection = this.cy().collection( collection );\n\n return this.neighborhood().intersect( collection ).length === collection.length;\n }\n});\n\nelesfn.allAreNeighbours = elesfn.allAreNeighbors;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar elesfn = ({\n parent: function( selector ){\n var parents = [];\n var cy = this._private.cy;\n\n for( var i = 0; i < this.length; i++ ){\n var ele = this[i];\n var parent = cy.getElementById( ele._private.data.parent );\n\n if( parent.size() > 0 ){\n parents.push( parent );\n }\n }\n\n return this.spawn( parents, { unique: true } ).filter( selector );\n },\n\n parents: function( selector ){\n var parents = [];\n\n var eles = this.parent();\n while( eles.nonempty() ){\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n parents.push( ele );\n }\n\n eles = eles.parent();\n }\n\n return this.spawn( parents, { unique: true } ).filter( selector );\n },\n\n commonAncestors: function( selector ){\n var ancestors;\n\n for( var i = 0; i < this.length; i++ ){\n var ele = this[i];\n var parents = ele.parents();\n\n ancestors = ancestors || parents;\n\n ancestors = ancestors.intersect( parents ); // current list must be common with current ele parents set\n }\n\n return ancestors.filter( selector );\n },\n\n orphans: function( selector ){\n return this.stdFilter(function( ele ){\n return ele.isNode() && ele.parent().empty();\n }).filter( selector );\n },\n\n nonorphans: function( selector ){\n return this.stdFilter(function( ele ){\n return ele.isNode() && ele.parent().nonempty();\n }).filter( selector );\n },\n\n children: function( selector ){\n var children = [];\n\n for( var i = 0; i < this.length; i++ ){\n var ele = this[i];\n children = children.concat( ele._private.children );\n }\n\n return this.spawn( children, { unique: true } ).filter( selector );\n },\n\n siblings: function( selector ){\n return this.parent().children().not( this ).filter( selector );\n },\n\n isParent: function(){\n var ele = this[0];\n\n if( ele ){\n return ele._private.children.length !== 0;\n }\n },\n\n isChild: function(){\n var ele = this[0];\n\n if( ele ){\n return ele._private.data.parent !== undefined && ele.parent().length !== 0;\n }\n },\n\n descendants: function( selector ){\n var elements = [];\n\n function add( eles ){\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n\n elements.push( ele );\n\n if( ele.children().nonempty() ){\n add( ele.children() );\n }\n }\n }\n\n add( this.children() );\n\n return this.spawn( elements, { unique: true } ).filter( selector );\n }\n});\n\n// aliases\nelesfn.ancestors = elesfn.parents;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar define = require('../define');\nvar fn, elesfn;\n\nfn = elesfn = ({\n\n data: define.data({\n field: 'data',\n bindingEvent: 'data',\n allowBinding: true,\n allowSetting: true,\n settingEvent: 'data',\n settingTriggersEvent: true,\n triggerFnName: 'trigger',\n allowGetting: true,\n immutableKeys: {\n 'id': true,\n 'source': true,\n 'target': true,\n 'parent': true\n },\n updateStyle: true\n }),\n\n removeData: define.removeData({\n field: 'data',\n event: 'data',\n triggerFnName: 'trigger',\n triggerEvent: true,\n immutableKeys: {\n 'id': true,\n 'source': true,\n 'target': true,\n 'parent': true\n },\n updateStyle: true\n }),\n\n scratch: define.data({\n field: 'scratch',\n bindingEvent: 'scratch',\n allowBinding: true,\n allowSetting: true,\n settingEvent: 'scratch',\n settingTriggersEvent: true,\n triggerFnName: 'trigger',\n allowGetting: true,\n updateStyle: true\n }),\n\n removeScratch: define.removeData({\n field: 'scratch',\n event: 'scratch',\n triggerFnName: 'trigger',\n triggerEvent: true,\n updateStyle: true\n }),\n\n rscratch: define.data({\n field: 'rscratch',\n allowBinding: false,\n allowSetting: true,\n settingTriggersEvent: false,\n allowGetting: true\n }),\n\n removeRscratch: define.removeData({\n field: 'rscratch',\n triggerEvent: false\n }),\n\n id: function(){\n var ele = this[0];\n\n if( ele ){\n return ele._private.data.id;\n }\n }\n\n});\n\n// aliases\nfn.attr = fn.data;\nfn.removeAttr = fn.removeData;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar util = require('../util');\n\nvar elesfn = {};\n\nfunction defineDegreeFunction(callback){\n return function( includeLoops ){\n var self = this;\n\n if( includeLoops === undefined ){\n includeLoops = true;\n }\n\n if( self.length === 0 ){ return; }\n\n if( self.isNode() && !self.removed() ){\n var degree = 0;\n var node = self[0];\n var connectedEdges = node._private.edges;\n\n for( var i = 0; i < connectedEdges.length; i++ ){\n var edge = connectedEdges[i];\n\n if( !includeLoops && edge.isLoop() ){\n continue;\n }\n\n degree += callback( node, edge );\n }\n\n return degree;\n } else {\n return;\n }\n };\n}\n\nutil.extend(elesfn, {\n degree: defineDegreeFunction(function(node, edge){\n if( edge.source().same( edge.target() ) ){\n return 2;\n } else {\n return 1;\n }\n }),\n\n indegree: defineDegreeFunction(function(node, edge){\n if( edge.target().same(node) ){\n return 1;\n } else {\n return 0;\n }\n }),\n\n outdegree: defineDegreeFunction(function(node, edge){\n if( edge.source().same(node) ){\n return 1;\n } else {\n return 0;\n }\n })\n});\n\nfunction defineDegreeBoundsFunction(degreeFn, callback){\n return function( includeLoops ){\n var ret;\n var nodes = this.nodes();\n\n for( var i = 0; i < nodes.length; i++ ){\n var ele = nodes[i];\n var degree = ele[degreeFn]( includeLoops );\n if( degree !== undefined && (ret === undefined || callback(degree, ret)) ){\n ret = degree;\n }\n }\n\n return ret;\n };\n}\n\nutil.extend(elesfn, {\n minDegree: defineDegreeBoundsFunction('degree', function(degree, min){\n return degree < min;\n }),\n\n maxDegree: defineDegreeBoundsFunction('degree', function(degree, max){\n return degree > max;\n }),\n\n minIndegree: defineDegreeBoundsFunction('indegree', function(degree, min){\n return degree < min;\n }),\n\n maxIndegree: defineDegreeBoundsFunction('indegree', function(degree, max){\n return degree > max;\n }),\n\n minOutdegree: defineDegreeBoundsFunction('outdegree', function(degree, min){\n return degree < min;\n }),\n\n maxOutdegree: defineDegreeBoundsFunction('outdegree', function(degree, max){\n return degree > max;\n })\n});\n\nutil.extend(elesfn, {\n totalDegree: function( includeLoops ){\n var total = 0;\n var nodes = this.nodes();\n\n for( var i = 0; i < nodes.length; i++ ){\n total += nodes[i].degree( includeLoops );\n }\n\n return total;\n }\n});\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar define = require('../define');\nvar is = require('../is');\nvar util = require('../util');\nvar fn, elesfn;\n\nfn = elesfn = ({\n\n position: define.data({\n field: 'position',\n bindingEvent: 'position',\n allowBinding: true,\n allowSetting: true,\n settingEvent: 'position',\n settingTriggersEvent: true,\n triggerFnName: 'rtrigger',\n allowGetting: true,\n validKeys: ['x', 'y'],\n onSet: function( eles ){\n var updatedEles = eles.updateCompoundBounds();\n updatedEles.rtrigger('position');\n },\n canSet: function( ele ){\n return !ele.locked() && !ele.isParent();\n }\n }),\n\n // position but no notification to renderer\n silentPosition: define.data({\n field: 'position',\n bindingEvent: 'position',\n allowBinding: false,\n allowSetting: true,\n settingEvent: 'position',\n settingTriggersEvent: false,\n triggerFnName: 'trigger',\n allowGetting: true,\n validKeys: ['x', 'y'],\n onSet: function( eles ){\n eles.updateCompoundBounds();\n },\n canSet: function( ele ){\n return !ele.locked() && !ele.isParent();\n }\n }),\n\n positions: function( pos, silent ){\n if( is.plainObject(pos) ){\n this.position(pos);\n\n } else if( is.fn(pos) ){\n var fn = pos;\n\n for( var i = 0; i < this.length; i++ ){\n var ele = this[i];\n\n var pos = fn.apply(ele, [i, ele]);\n\n if( pos && !ele.locked() && !ele.isParent() ){\n var elePos = ele._private.position;\n elePos.x = pos.x;\n elePos.y = pos.y;\n }\n }\n\n var updatedEles = this.updateCompoundBounds();\n var toTrigger = updatedEles.length > 0 ? this.add( updatedEles ) : this;\n\n if( silent ){\n toTrigger.trigger('position');\n } else {\n toTrigger.rtrigger('position');\n }\n }\n\n return this; // chaining\n },\n\n silentPositions: function( pos ){\n return this.positions( pos, true );\n },\n\n // get/set the rendered (i.e. on screen) positon of the element\n renderedPosition: function( dim, val ){\n var ele = this[0];\n var cy = this.cy();\n var zoom = cy.zoom();\n var pan = cy.pan();\n var rpos = is.plainObject( dim ) ? dim : undefined;\n var setting = rpos !== undefined || ( val !== undefined && is.string(dim) );\n\n if( ele && ele.isNode() ){ // must have an element and must be a node to return position\n if( setting ){\n for( var i = 0; i < this.length; i++ ){\n var ele = this[i];\n\n if( val !== undefined ){ // set one dimension\n ele._private.position[dim] = ( val - pan[dim] )/zoom;\n } else if( rpos !== undefined ){ // set whole position\n ele._private.position = {\n x: ( rpos.x - pan.x ) /zoom,\n y: ( rpos.y - pan.y ) /zoom\n };\n }\n }\n\n this.rtrigger('position');\n } else { // getting\n var pos = ele._private.position;\n rpos = {\n x: pos.x * zoom + pan.x,\n y: pos.y * zoom + pan.y\n };\n\n if( dim === undefined ){ // then return the whole rendered position\n return rpos;\n } else { // then return the specified dimension\n return rpos[ dim ];\n }\n }\n } else if( !setting ){\n return undefined; // for empty collection case\n }\n\n return this; // chaining\n },\n\n // get/set the position relative to the parent\n relativePosition: function( dim, val ){\n var ele = this[0];\n var cy = this.cy();\n var ppos = is.plainObject( dim ) ? dim : undefined;\n var setting = ppos !== undefined || ( val !== undefined && is.string(dim) );\n var hasCompoundNodes = cy.hasCompoundNodes();\n\n if( ele && ele.isNode() ){ // must have an element and must be a node to return position\n if( setting ){\n for( var i = 0; i < this.length; i++ ){\n var ele = this[i];\n var parent = hasCompoundNodes ? ele.parent() : null;\n var hasParent = parent && parent.length > 0;\n var relativeToParent = hasParent;\n\n if( hasParent ){\n parent = parent[0];\n }\n\n var origin = relativeToParent ? parent._private.position : { x: 0, y: 0 };\n\n if( val !== undefined ){ // set one dimension\n ele._private.position[dim] = val + origin[dim];\n } else if( ppos !== undefined ){ // set whole position\n ele._private.position = {\n x: ppos.x + origin.x,\n y: ppos.y + origin.y\n };\n }\n }\n\n this.rtrigger('position');\n\n } else { // getting\n var pos = ele._private.position;\n var parent = hasCompoundNodes ? ele.parent() : null;\n var hasParent = parent && parent.length > 0;\n var relativeToParent = hasParent;\n\n if( hasParent ){\n parent = parent[0];\n }\n\n var origin = relativeToParent ? parent._private.position : { x: 0, y: 0 };\n\n ppos = {\n x: pos.x - origin.x,\n y: pos.y - origin.y\n };\n\n if( dim === undefined ){ // then return the whole rendered position\n return ppos;\n } else { // then return the specified dimension\n return ppos[ dim ];\n }\n }\n } else if( !setting ){\n return undefined; // for empty collection case\n }\n\n return this; // chaining\n },\n\n renderedBoundingBox: function( options ){\n var bb = this.boundingBox( options );\n var cy = this.cy();\n var zoom = cy.zoom();\n var pan = cy.pan();\n\n var x1 = bb.x1 * zoom + pan.x;\n var x2 = bb.x2 * zoom + pan.x;\n var y1 = bb.y1 * zoom + pan.y;\n var y2 = bb.y2 * zoom + pan.y;\n\n return {\n x1: x1,\n x2: x2,\n y1: y1,\n y2: y2,\n w: x2 - x1,\n h: y2 - y1\n };\n },\n\n updateCompoundBounds: function(){\n var cy = this.cy();\n\n if( !cy.styleEnabled() || !cy.hasCompoundNodes() ){ return cy.collection(); } // save cycles for non compound graphs or when style disabled\n\n var updated = [];\n\n function update( parent ){\n var children = parent.children();\n var style = parent._private.style;\n var includeLabels = style['compound-sizing-wrt-labels'].value === 'include';\n var bb = children.boundingBox({ includeLabels: includeLabels, includeEdges: true });\n var padding = {\n top: style['padding-top'].pfValue,\n bottom: style['padding-bottom'].pfValue,\n left: style['padding-left'].pfValue,\n right: style['padding-right'].pfValue\n };\n var pos = parent._private.position;\n var didUpdate = false;\n\n if( style['width'].value === 'auto' ){\n parent._private.autoWidth = bb.w;\n pos.x = (bb.x1 + bb.x2 - padding.left + padding.right)/2;\n didUpdate = true;\n }\n\n if( style['height'].value === 'auto' ){\n parent._private.autoHeight = bb.h;\n pos.y = (bb.y1 + bb.y2 - padding.top + padding.bottom)/2;\n didUpdate = true;\n }\n\n if( didUpdate ){\n updated.push( parent );\n }\n }\n\n // go up, level by level\n var eles = this.parent();\n while( eles.nonempty() ){\n\n // update each parent node in this level\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n\n update( ele );\n }\n\n // next level\n eles = eles.parent();\n }\n\n // return changed\n return this.spawn( updated );\n },\n\n // get the bounding box of the elements (in raw model position)\n boundingBox: function( options ){\n var eles = this;\n var cy = eles._private.cy;\n var cy_p = cy._private;\n var styleEnabled = cy_p.styleEnabled;\n\n options = options || util.staticEmptyObject();\n\n var includeNodes = options.includeNodes === undefined ? true : options.includeNodes;\n var includeEdges = options.includeEdges === undefined ? true : options.includeEdges;\n var includeLabels = options.includeLabels === undefined ? true : options.includeLabels;\n\n // recalculate projections etc\n if( styleEnabled ){\n cy_p.renderer.recalculateRenderedStyle( this );\n }\n\n var x1 = Infinity;\n var x2 = -Infinity;\n var y1 = Infinity;\n var y2 = -Infinity;\n\n // find bounds of elements\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n var _p = ele._private;\n var style = _p.style;\n var display = styleEnabled ? _p.style['display'].value : 'element';\n var isNode = _p.group === 'nodes';\n var ex1, ex2, ey1, ey2, x, y;\n var includedEle = false;\n\n if( display === 'none' ){ continue; } // then ele doesn't take up space\n\n if( isNode && includeNodes ){\n includedEle = true;\n\n var pos = _p.position;\n x = pos.x;\n y = pos.y;\n var w = ele.outerWidth();\n var halfW = w/2;\n var h = ele.outerHeight();\n var halfH = h/2;\n\n // handle node dimensions\n /////////////////////////\n\n ex1 = x - halfW;\n ex2 = x + halfW;\n ey1 = y - halfH;\n ey2 = y + halfH;\n\n x1 = ex1 < x1 ? ex1 : x1;\n x2 = ex2 > x2 ? ex2 : x2;\n y1 = ey1 < y1 ? ey1 : y1;\n y2 = ey2 > y2 ? ey2 : y2;\n\n } else if( ele.isEdge() && includeEdges ){\n includedEle = true;\n\n var n1 = _p.source;\n var n1_p = n1._private;\n var n1pos = n1_p.position;\n\n var n2 = _p.target;\n var n2_p = n2._private;\n var n2pos = n2_p.position;\n\n\n // handle edge dimensions (rough box estimate)\n //////////////////////////////////////////////\n\n var rstyle = _p.rstyle || {};\n var w = 0;\n var wHalf = 0;\n\n if( styleEnabled ){\n w = style['width'].pfValue;\n wHalf = w/2;\n }\n\n ex1 = n1pos.x;\n ex2 = n2pos.x;\n ey1 = n1pos.y;\n ey2 = n2pos.y;\n\n if( ex1 > ex2 ){\n var temp = ex1;\n ex1 = ex2;\n ex2 = temp;\n }\n\n if( ey1 > ey2 ){\n var temp = ey1;\n ey1 = ey2;\n ey2 = temp;\n }\n\n // take into account edge width\n ex1 -= wHalf;\n ex2 += wHalf;\n ey1 -= wHalf;\n ey2 += wHalf;\n\n x1 = ex1 < x1 ? ex1 : x1;\n x2 = ex2 > x2 ? ex2 : x2;\n y1 = ey1 < y1 ? ey1 : y1;\n y2 = ey2 > y2 ? ey2 : y2;\n\n // handle points along edge (sanity check)\n //////////////////////////////////////////\n\n if( styleEnabled ){\n var pts = rstyle.bezierPts || rstyle.linePts || [];\n\n for( var j = 0; j < pts.length; j++ ){\n var pt = pts[j];\n\n ex1 = pt.x - wHalf;\n ex2 = pt.x + wHalf;\n ey1 = pt.y - wHalf;\n ey2 = pt.y + wHalf;\n\n x1 = ex1 < x1 ? ex1 : x1;\n x2 = ex2 > x2 ? ex2 : x2;\n y1 = ey1 < y1 ? ey1 : y1;\n y2 = ey2 > y2 ? ey2 : y2;\n }\n }\n\n // precise haystacks (sanity check)\n ///////////////////////////////////\n\n if( styleEnabled && style['curve-style'].strValue === 'haystack' ){\n var hpts = rstyle.haystackPts;\n\n ex1 = hpts[0].x;\n ey1 = hpts[0].y;\n ex2 = hpts[1].x;\n ey2 = hpts[1].y;\n\n if( ex1 > ex2 ){\n var temp = ex1;\n ex1 = ex2;\n ex2 = temp;\n }\n\n if( ey1 > ey2 ){\n var temp = ey1;\n ey1 = ey2;\n ey2 = temp;\n }\n\n x1 = ex1 < x1 ? ex1 : x1;\n x2 = ex2 > x2 ? ex2 : x2;\n y1 = ey1 < y1 ? ey1 : y1;\n y2 = ey2 > y2 ? ey2 : y2;\n }\n\n } // edges\n\n\n // handle label dimensions\n //////////////////////////\n\n if( styleEnabled ){\n\n var _p = ele._private;\n var style = _p.style;\n var rstyle = _p.rstyle;\n var label = style['label'].strValue;\n var fontSize = style['font-size'];\n var halign = style['text-halign'];\n var valign = style['text-valign'];\n var labelWidth = rstyle.labelWidth;\n var labelHeight = rstyle.labelHeight;\n var labelX = rstyle.labelX;\n var labelY = rstyle.labelY;\n var isEdge = ele.isEdge();\n var autorotate = style['edge-text-rotation'].strValue === 'autorotate';\n\n if( includeLabels && label && fontSize && labelHeight != null && labelWidth != null && labelX != null && labelY != null && halign && valign ){\n var lh = labelHeight;\n var lw = labelWidth;\n var lx1, lx2, ly1, ly2;\n\n if( isEdge ){\n lx1 = labelX - lw/2;\n lx2 = labelX + lw/2;\n ly1 = labelY - lh/2;\n ly2 = labelY + lh/2;\n\n if( autorotate ){\n var theta = _p.rscratch.labelAngle;\n var cos = Math.cos( theta );\n var sin = Math.sin( theta );\n\n var rotate = function( x, y ){\n x = x - labelX;\n y = y - labelY;\n\n return {\n x: x*cos - y*sin + labelX,\n y: x*sin + y*cos + labelY\n };\n };\n\n var px1y1 = rotate( lx1, ly1 );\n var px1y2 = rotate( lx1, ly2 );\n var px2y1 = rotate( lx2, ly1 );\n var px2y2 = rotate( lx2, ly2 );\n\n lx1 = Math.min( px1y1.x, px1y2.x, px2y1.x, px2y2.x );\n lx2 = Math.max( px1y1.x, px1y2.x, px2y1.x, px2y2.x );\n ly1 = Math.min( px1y1.y, px1y2.y, px2y1.y, px2y2.y );\n ly2 = Math.max( px1y1.y, px1y2.y, px2y1.y, px2y2.y );\n }\n } else {\n switch( halign.value ){\n case 'left':\n lx1 = labelX - lw;\n lx2 = labelX;\n break;\n\n case 'center':\n lx1 = labelX - lw/2;\n lx2 = labelX + lw/2;\n break;\n\n case 'right':\n lx1 = labelX;\n lx2 = labelX + lw;\n break;\n }\n\n switch( valign.value ){\n case 'top':\n ly1 = labelY - lh;\n ly2 = labelY;\n break;\n\n case 'center':\n ly1 = labelY - lh/2;\n ly2 = labelY + lh/2;\n break;\n\n case 'bottom':\n ly1 = labelY;\n ly2 = labelY + lh;\n break;\n }\n }\n\n x1 = lx1 < x1 ? lx1 : x1;\n x2 = lx2 > x2 ? lx2 : x2;\n y1 = ly1 < y1 ? ly1 : y1;\n y2 = ly2 > y2 ? ly2 : y2;\n }\n } // style enabled for labels\n } // for\n\n var noninf = function(x){\n if( x === Infinity || x === -Infinity ){\n return 0;\n }\n\n return x;\n };\n\n x1 = noninf(x1);\n x2 = noninf(x2);\n y1 = noninf(y1);\n y2 = noninf(y2);\n\n return {\n x1: x1,\n x2: x2,\n y1: y1,\n y2: y2,\n w: x2 - x1,\n h: y2 - y1\n };\n }\n});\n\nvar defineDimFns = function( opts ){\n opts.uppercaseName = util.capitalize( opts.name );\n opts.autoName = 'auto' + opts.uppercaseName;\n opts.labelName = 'label' + opts.uppercaseName;\n opts.outerName = 'outer' + opts.uppercaseName;\n opts.uppercaseOuterName = util.capitalize( opts.outerName );\n\n fn[ opts.name ] = function dimImpl(){\n var ele = this[0];\n var _p = ele._private;\n var cy = _p.cy;\n var styleEnabled = cy._private.styleEnabled;\n\n if( ele ){\n if( styleEnabled ){\n var d = _p.style[ opts.name ];\n\n switch( d.strValue ){\n case 'auto':\n return _p[ opts.autoName ] || 0;\n case 'label':\n return _p.rstyle[ opts.labelName ] || 0;\n default:\n return d.pfValue;\n }\n } else {\n return 1;\n }\n }\n };\n\n fn[ 'outer' + opts.uppercaseName ] = function outerDimImpl(){\n var ele = this[0];\n var _p = ele._private;\n var cy = _p.cy;\n var styleEnabled = cy._private.styleEnabled;\n\n if( ele ){\n if( styleEnabled ){\n var style = _p.style;\n var dim = ele[ opts.name ]();\n var border = style['border-width'].pfValue;\n var padding = style[ opts.paddings[0] ].pfValue + style[ opts.paddings[1] ].pfValue;\n\n return dim + border + padding;\n } else {\n return 1;\n }\n }\n };\n\n fn[ 'rendered' + opts.uppercaseName ] = function renderedDimImpl(){\n var ele = this[0];\n\n if( ele ){\n var d = ele[ opts.name ]();\n return d * this.cy().zoom();\n }\n };\n\n fn[ 'rendered' + opts.uppercaseOuterName ] = function renderedOuterDimImpl(){\n var ele = this[0];\n\n if( ele ){\n var od = ele[ opts.outerName ]();\n return od * this.cy().zoom();\n }\n };\n};\n\ndefineDimFns({\n name: 'width',\n paddings: ['padding-left', 'padding-right']\n});\n\ndefineDimFns({\n name: 'height',\n paddings: ['padding-top', 'padding-bottom']\n});\n\n// aliases\nfn.modelPosition = fn.point = fn.position;\nfn.modelPositions = fn.points = fn.positions;\nfn.renderedPoint = fn.renderedPosition;\nfn.relativePoint = fn.relativePosition;\nfn.boundingbox = fn.boundingBox;\nfn.renderedBoundingbox = fn.renderedBoundingBox;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar util = require('../util');\nvar is = require('../is');\n\n// represents a node or an edge\nvar Element = function(cy, params, restore){\n if( !(this instanceof Element) ){\n return new Element(cy, params, restore);\n }\n\n var self = this;\n restore = (restore === undefined || restore ? true : false);\n\n if( cy === undefined || params === undefined || !is.core(cy) ){\n util.error('An element must have a core reference and parameters set');\n return;\n }\n\n var group = params.group;\n\n // try to automatically infer the group if unspecified\n if( group == null ){\n if( params.data.source != null && params.data.target != null ){\n group = 'edges';\n } else {\n group = 'nodes';\n }\n }\n\n // validate group\n if( group !== 'nodes' && group !== 'edges' ){\n util.error('An element must be of type `nodes` or `edges`; you specified `' + group + '`');\n return;\n }\n\n // make the element array-like, just like a collection\n this.length = 1;\n this[0] = this;\n\n // NOTE: when something is added here, add also to ele.json()\n this._private = {\n cy: cy,\n single: true, // indicates this is an element\n data: params.data || {}, // data object\n position: params.position || {}, // (x, y) position pair\n autoWidth: undefined, // width and height of nodes calculated by the renderer when set to special 'auto' value\n autoHeight: undefined,\n listeners: [], // array of bound listeners\n group: group, // string; 'nodes' or 'edges'\n style: {}, // properties as set by the style\n rstyle: {}, // properties for style sent from the renderer to the core\n styleCxts: [], // applied style contexts from the styler\n removed: true, // whether it's inside the vis; true if removed (set true here since we call restore)\n selected: params.selected ? true : false, // whether it's selected\n selectable: params.selectable === undefined ? true : ( params.selectable ? true : false ), // whether it's selectable\n locked: params.locked ? true : false, // whether the element is locked (cannot be moved)\n grabbed: false, // whether the element is grabbed by the mouse; renderer sets this privately\n grabbable: params.grabbable === undefined ? true : ( params.grabbable ? true : false ), // whether the element can be grabbed\n active: false, // whether the element is active from user interaction\n classes: {}, // map ( className => true )\n animation: { // object for currently-running animations\n current: [],\n queue: []\n },\n rscratch: {}, // object in which the renderer can store information\n scratch: params.scratch || {}, // scratch objects\n edges: [], // array of connected edges\n children: [] // array of children\n };\n\n // renderedPosition overrides if specified\n if( params.renderedPosition ){\n var rpos = params.renderedPosition;\n var pan = cy.pan();\n var zoom = cy.zoom();\n\n this._private.position = {\n x: (rpos.x - pan.x)/zoom,\n y: (rpos.y - pan.y)/zoom\n };\n }\n\n if( is.string(params.classes) ){\n var classes = params.classes.split(/\\s+/);\n for( var i = 0, l = classes.length; i < l; i++ ){\n var cls = classes[i];\n if( !cls || cls === '' ){ continue; }\n\n self._private.classes[cls] = true;\n }\n }\n\n if( params.style || params.css ){\n cy.style().applyBypass( this, params.style || params.css );\n }\n\n if( restore === undefined || restore ){\n this.restore();\n }\n\n};\n\nmodule.exports = Element;\n","'use strict';\n\nvar define = require('../define');\n\nvar elesfn = ({\n on: define.on(), // .on( events [, selector] [, data], handler)\n one: define.on({ unbindSelfOnTrigger: true }),\n once: define.on({ unbindAllBindersOnTrigger: true }),\n off: define.off(), // .off( events [, selector] [, handler] )\n trigger: define.trigger(), // .trigger( events [, extraParams] )\n\n rtrigger: function(event, extraParams){ // for internal use only\n if( this.length === 0 ){ return; } // empty collections don't need to notify anything\n\n // notify renderer\n this.cy().notify({\n type: event,\n collection: this\n });\n\n this.trigger(event, extraParams);\n return this;\n }\n});\n\n// aliases:\ndefine.eventAliasesOn( elesfn );\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../is');\nvar Selector = require('../selector');\n\nvar elesfn = ({\n nodes: function( selector ){\n return this.filter(function(i, element){\n return element.isNode();\n }).filter(selector);\n },\n\n edges: function( selector ){\n return this.filter(function(i, element){\n return element.isEdge();\n }).filter(selector);\n },\n\n filter: function( filter ){\n if( is.fn(filter) ){\n var elements = [];\n\n for( var i = 0; i < this.length; i++ ){\n var ele = this[i];\n\n if( filter.apply(ele, [i, ele]) ){\n elements.push(ele);\n }\n }\n\n return this.spawn(elements);\n\n } else if( is.string(filter) || is.elementOrCollection(filter) ){\n return Selector(filter).filter(this);\n\n } else if( filter === undefined ){\n return this;\n }\n\n return this.spawn(); // if not handled by above, give 'em an empty collection\n },\n\n not: function( toRemove ){\n if( !toRemove ){\n return this;\n } else {\n\n if( is.string( toRemove ) ){\n toRemove = this.filter( toRemove );\n }\n\n var elements = [];\n\n for( var i = 0; i < this.length; i++ ){\n var element = this[i];\n\n var remove = toRemove._private.ids[ element.id() ];\n if( !remove ){\n elements.push( element );\n }\n }\n\n return this.spawn( elements );\n }\n\n },\n\n absoluteComplement: function(){\n var cy = this._private.cy;\n\n return cy.elements().not( this );\n },\n\n intersect: function( other ){\n // if a selector is specified, then filter by it instead\n if( is.string(other) ){\n var selector = other;\n return this.filter( selector );\n }\n\n var elements = [];\n var col1 = this;\n var col2 = other;\n var col1Smaller = this.length < other.length;\n // var ids1 = col1Smaller ? col1._private.ids : col2._private.ids;\n var ids2 = col1Smaller ? col2._private.ids : col1._private.ids;\n var col = col1Smaller ? col1 : col2;\n\n for( var i = 0; i < col.length; i++ ){\n var id = col[i]._private.data.id;\n var ele = ids2[ id ];\n\n if( ele ){\n elements.push( ele );\n }\n }\n\n return this.spawn( elements );\n },\n\n xor: function( other ){\n var cy = this._private.cy;\n\n if( is.string(other) ){\n other = cy.$( other );\n }\n\n var elements = [];\n var col1 = this;\n var col2 = other;\n\n var add = function( col, other ){\n\n for( var i = 0; i < col.length; i++ ){\n var ele = col[i];\n var id = ele._private.data.id;\n var inOther = other._private.ids[ id ];\n\n if( !inOther ){\n elements.push( ele );\n }\n }\n\n };\n\n add( col1, col2 );\n add( col2, col1 );\n\n return this.spawn( elements );\n },\n\n diff: function( other ){\n var cy = this._private.cy;\n\n if( is.string(other) ){\n other = cy.$( other );\n }\n\n var left = [];\n var right = [];\n var both = [];\n var col1 = this;\n var col2 = other;\n\n var add = function( col, other, retEles ){\n\n for( var i = 0; i < col.length; i++ ){\n var ele = col[i];\n var id = ele._private.data.id;\n var inOther = other._private.ids[ id ];\n\n if( inOther ){\n both.push( ele );\n } else {\n retEles.push( ele );\n }\n }\n\n };\n\n add( col1, col2, left );\n add( col2, col1, right );\n\n return {\n left: this.spawn( left, { unique: true } ),\n right: this.spawn( right, { unique: true } ),\n both: this.spawn( both, { unique: true } )\n };\n },\n\n add: function( toAdd ){\n var cy = this._private.cy;\n\n if( !toAdd ){\n return this;\n }\n\n if( is.string(toAdd) ){\n var selector = toAdd;\n toAdd = cy.elements(selector);\n }\n\n var elements = [];\n\n for( var i = 0; i < this.length; i++ ){\n elements.push( this[i] );\n }\n\n for( var i = 0; i < toAdd.length; i++ ){\n\n var add = !this._private.ids[ toAdd[i].id() ];\n if( add ){\n elements.push( toAdd[i] );\n }\n }\n\n return this.spawn(elements);\n },\n\n // in place merge on calling collection\n merge: function( toAdd ){\n var _p = this._private;\n var cy = _p.cy;\n\n if( !toAdd ){\n return this;\n }\n\n if( is.string(toAdd) ){\n var selector = toAdd;\n toAdd = cy.elements(selector);\n }\n\n for( var i = 0; i < toAdd.length; i++ ){\n var toAddEle = toAdd[i];\n var id = toAddEle.id();\n var add = !_p.ids[ id ];\n\n if( add ){\n var index = this.length++;\n\n this[ index ] = toAddEle;\n _p.ids[ id ] = toAddEle;\n _p.indexes[ id ] = index;\n }\n }\n\n return this; // chaining\n },\n\n // remove single ele in place in calling collection\n unmergeOne: function( ele ){\n ele = ele[0];\n\n var _p = this._private;\n var id = ele.id();\n var i = _p.indexes[ id ];\n\n if( i == null ){\n return this; // no need to remove\n }\n\n // remove ele\n this[i] = undefined;\n _p.ids[ id ] = undefined;\n _p.indexes[ id ] = undefined;\n\n var unmergedLastEle = i === this.length - 1;\n\n // replace empty spot with last ele in collection\n if( this.length > 1 && !unmergedLastEle ){\n var lastEleI = this.length - 1;\n var lastEle = this[ lastEleI ];\n\n this[ lastEleI ] = undefined;\n this[i] = lastEle;\n _p.indexes[ lastEle.id() ] = i;\n }\n\n // the collection is now 1 ele smaller\n this.length--;\n\n return this;\n },\n\n // remove eles in place on calling collection\n unmerge: function( toRemove ){\n var cy = this._private.cy;\n\n if( !toRemove ){\n return this;\n }\n\n if( is.string(toRemove) ){\n var selector = toRemove;\n toRemove = cy.elements(selector);\n }\n\n for( var i = 0; i < toRemove.length; i++ ){\n this.unmergeOne( toRemove[i] );\n }\n\n return this; // chaining\n },\n\n map: function( mapFn, thisArg ){\n var arr = [];\n var eles = this;\n\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n var ret = thisArg ? mapFn.apply( thisArg, [ele, i, eles] ) : mapFn( ele, i, eles );\n\n arr.push( ret );\n }\n\n return arr;\n },\n\n stdFilter: function( fn, thisArg ){\n var filterEles = [];\n var eles = this;\n\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n var include = thisArg ? fn.apply( thisArg, [ele, i, eles] ) : fn( ele, i, eles );\n\n if( include ){\n filterEles.push( ele );\n }\n }\n\n return this.spawn( filterEles );\n },\n\n max: function( valFn, thisArg ){\n var max = -Infinity;\n var maxEle;\n var eles = this;\n\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n var val = thisArg ? valFn.apply( thisArg, [ ele, i, eles ] ) : valFn( ele, i, eles );\n\n if( val > max ){\n max = val;\n maxEle = ele;\n }\n }\n\n return {\n value: max,\n ele: maxEle\n };\n },\n\n min: function( valFn, thisArg ){\n var min = Infinity;\n var minEle;\n var eles = this;\n\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n var val = thisArg ? valFn.apply( thisArg, [ ele, i, eles ] ) : valFn( ele, i, eles );\n\n if( val < min ){\n min = val;\n minEle = ele;\n }\n }\n\n return {\n value: min,\n ele: minEle\n };\n }\n});\n\n// aliases\nvar fn = elesfn;\nfn['u'] = fn['|'] = fn['+'] = fn.union = fn.or = fn.add;\nfn['\\\\'] = fn['!'] = fn['-'] = fn.difference = fn.relativeComplement = fn.subtract = fn.not;\nfn['n'] = fn['&'] = fn['.'] = fn.and = fn.intersection = fn.intersect;\nfn['^'] = fn['(+)'] = fn['(-)'] = fn.symmetricDifference = fn.symdiff = fn.xor;\nfn.fnFilter = fn.filterFn = fn.stdFilter;\nfn.complement = fn.abscomp = fn.absoluteComplement;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar elesfn = ({\n isNode: function(){\n return this.group() === 'nodes';\n },\n\n isEdge: function(){\n return this.group() === 'edges';\n },\n\n isLoop: function(){\n return this.isEdge() && this.source().id() === this.target().id();\n },\n\n isSimple: function(){\n return this.isEdge() && this.source().id() !== this.target().id();\n },\n\n group: function(){\n var ele = this[0];\n\n if( ele ){\n return ele._private.group;\n }\n }\n});\n\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar util = require('../util');\nvar is = require('../is');\n\nvar Element = require('./element');\n\n// factory for generating edge ids when no id is specified for a new element\nvar idFactory = {\n prefix: 'ele',\n id: 0,\n generate: function(cy, element, tryThisId){\n var json = is.element( element ) ? element._private : element;\n var id = tryThisId != null ? tryThisId : this.prefix + this.id;\n\n if( cy.getElementById(id).empty() ){\n this.id++; // we've used the current id, so move it up\n } else { // otherwise keep trying successive unused ids\n while( !cy.getElementById(id).empty() ){\n id = this.prefix + ( ++this.id );\n }\n }\n\n return id;\n }\n};\n\n// represents a set of nodes, edges, or both together\nvar Collection = function(cy, elements, options){\n if( !(this instanceof Collection) ){\n return new Collection(cy, elements, options);\n }\n\n if( cy === undefined || !is.core(cy) ){\n util.error('A collection must have a reference to the core');\n return;\n }\n\n var ids = {};\n var indexes = {};\n var createdElements = false;\n\n if( !elements ){\n elements = [];\n } else if( elements.length > 0 && is.plainObject( elements[0] ) && !is.element( elements[0] ) ){\n createdElements = true;\n\n // make elements from json and restore all at once later\n var eles = [];\n var elesIds = {};\n\n for( var i = 0, l = elements.length; i < l; i++ ){\n var json = elements[i];\n\n if( json.data == null ){\n json.data = {};\n }\n\n var data = json.data;\n\n // make sure newly created elements have valid ids\n if( data.id == null ){\n data.id = idFactory.generate( cy, json );\n } else if( cy.getElementById( data.id ).length !== 0 || elesIds[ data.id ] ){\n continue; // can't create element if prior id already exists\n }\n\n var ele = new Element( cy, json, false );\n eles.push( ele );\n elesIds[ data.id ] = true;\n }\n\n elements = eles;\n }\n\n this.length = 0;\n\n for( var i = 0, l = elements.length; i < l; i++ ){\n var element = elements[i];\n if( !element ){ continue; }\n\n var id = element._private.data.id;\n\n if( !options || (options.unique && !ids[ id ] ) ){\n ids[ id ] = element;\n indexes[ id ] = this.length;\n\n this[ this.length ] = element;\n this.length++;\n }\n }\n\n this._private = {\n cy: cy,\n ids: ids,\n indexes: indexes\n };\n\n // restore the elements if we created them from json\n if( createdElements ){\n this.restore();\n }\n};\n\n// Functions\n////////////////////////////////////////////////////////////////////////////////////////////////////\n\n// keep the prototypes in sync (an element has the same functions as a collection)\n// and use elefn and elesfn as shorthands to the prototypes\nvar elesfn = Element.prototype = Collection.prototype;\n\nelesfn.instanceString = function(){\n return 'collection';\n};\n\nelesfn.spawn = function( cy, eles, opts ){\n if( !is.core(cy) ){ // cy is optional\n opts = eles;\n eles = cy;\n cy = this.cy();\n }\n\n return new Collection( cy, eles, opts );\n};\n\nelesfn.cy = function(){\n return this._private.cy;\n};\n\nelesfn.element = function(){\n return this[0];\n};\n\nelesfn.collection = function(){\n if( is.collection(this) ){\n return this;\n } else { // an element\n return new Collection( this._private.cy, [this] );\n }\n};\n\nelesfn.unique = function(){\n return new Collection( this._private.cy, this, { unique: true } );\n};\n\nelesfn.getElementById = function( id ){\n var cy = this._private.cy;\n var ele = this._private.ids[ id ];\n\n return ele ? ele : new Collection(cy); // get ele or empty collection\n};\n\nelesfn.json = function( obj ){\n var ele = this.element();\n var cy = this.cy();\n\n if( ele == null && obj ){ return this; } // can't set to no eles\n\n if( ele == null ){ return undefined; } // can't get from no eles\n\n var p = ele._private;\n\n if( is.plainObject(obj) ){ // set\n\n cy.startBatch();\n\n if( obj.data ){\n ele.data( obj.data );\n }\n\n if( obj.position ){\n ele.position( obj.position );\n }\n\n // ignore group -- immutable\n\n var checkSwitch = function( k, trueFnName, falseFnName ){\n var obj_k = obj[k];\n\n if( obj_k != null && obj_k !== p[k] ){\n if( obj_k ){\n ele[ trueFnName ]();\n } else {\n ele[ falseFnName ]();\n }\n }\n };\n\n checkSwitch( 'removed', 'remove', 'restore' );\n\n checkSwitch( 'selected', 'select', 'unselect' );\n\n checkSwitch( 'selectable', 'selectify', 'unselectify' );\n\n checkSwitch( 'locked', 'lock', 'unlock' );\n\n checkSwitch( 'grabbable', 'grabify', 'ungrabify' );\n\n if( obj.classes != null ){\n ele.classes( obj.classes );\n }\n\n cy.endBatch();\n\n return this;\n\n } else if( obj === undefined ){ // get\n\n var json = {\n data: util.copy( p.data ),\n position: util.copy( p.position ),\n group: p.group,\n removed: p.removed,\n selected: p.selected,\n selectable: p.selectable,\n locked: p.locked,\n grabbable: p.grabbable,\n classes: null\n };\n\n var classes = [];\n for( var cls in p.classes ){\n if( p.classes[cls] ){\n classes.push(cls);\n }\n }\n json.classes = classes.join(' ');\n\n return json;\n }\n};\n\nelesfn.jsons = function(){\n var jsons = [];\n\n for( var i = 0; i < this.length; i++ ){\n var ele = this[i];\n var json = ele.json();\n\n jsons.push( json );\n }\n\n return jsons;\n};\n\nelesfn.clone = function(){\n var cy = this.cy();\n var elesArr = [];\n\n for( var i = 0; i < this.length; i++ ){\n var ele = this[i];\n var json = ele.json();\n var clone = new Element(cy, json, false); // NB no restore\n\n elesArr.push( clone );\n }\n\n return new Collection( cy, elesArr );\n};\nelesfn.copy = elesfn.clone;\n\nelesfn.restore = function( notifyRenderer ){\n var self = this;\n var restored = [];\n var cy = self.cy();\n\n if( notifyRenderer === undefined ){\n notifyRenderer = true;\n }\n\n // create arrays of nodes and edges, since we need to\n // restore the nodes first\n var elements = [];\n var nodes = [], edges = [];\n var numNodes = 0;\n var numEdges = 0;\n for( var i = 0, l = self.length; i < l; i++ ){\n var ele = self[i];\n\n // keep nodes first in the array and edges after\n if( ele.isNode() ){ // put to front of array if node\n nodes.push( ele );\n numNodes++;\n } else { // put to end of array if edge\n edges.push( ele );\n numEdges++;\n }\n }\n\n elements = nodes.concat( edges );\n\n // now, restore each element\n for( var i = 0, l = elements.length; i < l; i++ ){\n var ele = elements[i];\n\n if( !ele.removed() ){\n // don't need to do anything\n continue;\n }\n\n var _private = ele._private;\n var data = _private.data;\n\n // set id and validate\n if( data.id === undefined ){\n data.id = idFactory.generate( cy, ele );\n\n } else if( is.number(data.id) ){\n data.id = '' + data.id; // now it's a string\n\n } else if( is.emptyString(data.id) || !is.string(data.id) ){\n util.error('Can not create element with invalid string ID `' + data.id + '`');\n\n // can't create element if it has empty string as id or non-string id\n continue;\n } else if( cy.getElementById( data.id ).length !== 0 ){\n util.error('Can not create second element with ID `' + data.id + '`');\n\n // can't create element if one already has that id\n continue;\n }\n\n var id = data.id; // id is finalised, now let's keep a ref\n\n if( ele.isNode() ){ // extra checks for nodes\n var node = ele;\n var pos = _private.position;\n\n // make sure the nodes have a defined position\n\n if( pos.x == null ){\n pos.x = 0;\n }\n\n if( pos.y == null ){\n pos.y = 0;\n }\n }\n\n if( ele.isEdge() ){ // extra checks for edges\n\n var edge = ele;\n var fields = ['source', 'target'];\n var fieldsLength = fields.length;\n var badSourceOrTarget = false;\n for(var j = 0; j < fieldsLength; j++){\n\n var field = fields[j];\n var val = data[field];\n\n if( is.number(val) ){\n val = data[field] = '' + data[field]; // now string\n }\n\n if( val == null || val === '' ){\n // can't create if source or target is not defined properly\n util.error('Can not create edge `' + id + '` with unspecified ' + field);\n badSourceOrTarget = true;\n } else if( cy.getElementById(val).empty() ){\n // can't create edge if one of its nodes doesn't exist\n util.error('Can not create edge `' + id + '` with nonexistant ' + field + ' `' + val + '`');\n badSourceOrTarget = true;\n }\n }\n\n if( badSourceOrTarget ){ continue; } // can't create this\n\n var src = cy.getElementById( data.source );\n var tgt = cy.getElementById( data.target );\n\n src._private.edges.push( edge );\n tgt._private.edges.push( edge );\n\n edge._private.source = src;\n edge._private.target = tgt;\n\n } // if is edge\n\n // create mock ids map for element so it can be used like collections\n _private.ids = {};\n _private.ids[ id ] = ele;\n\n _private.removed = false;\n cy.addToPool( ele );\n\n restored.push( ele );\n } // for each element\n\n // do compound node sanity checks\n for( var i = 0; i < numNodes; i++ ){ // each node\n var node = elements[i];\n var data = node._private.data;\n\n if( is.number(data.parent) ){ // then automake string\n data.parent = '' + data.parent;\n }\n\n var parentId = data.parent;\n\n var specifiedParent = parentId != null;\n\n if( specifiedParent ){\n var parent = cy.getElementById( parentId );\n\n if( parent.empty() ){\n // non-existant parent; just remove it\n data.parent = undefined;\n } else {\n var selfAsParent = false;\n var ancestor = parent;\n while( !ancestor.empty() ){\n if( node.same(ancestor) ){\n // mark self as parent and remove from data\n selfAsParent = true;\n data.parent = undefined; // remove parent reference\n\n // exit or we loop forever\n break;\n }\n\n ancestor = ancestor.parent();\n }\n\n if( !selfAsParent ){\n // connect with children\n parent[0]._private.children.push( node );\n node._private.parent = parent[0];\n\n // let the core know we have a compound graph\n cy._private.hasCompoundNodes = true;\n }\n } // else\n } // if specified parent\n } // for each node\n\n restored = new Collection( cy, restored );\n if( restored.length > 0 ){\n\n var toUpdateStyle = restored.add( restored.connectedNodes() ).add( restored.parent() );\n toUpdateStyle.updateStyle( notifyRenderer );\n\n if( notifyRenderer ){\n restored.rtrigger('add');\n } else {\n restored.trigger('add');\n }\n }\n\n return self; // chainability\n};\n\nelesfn.removed = function(){\n var ele = this[0];\n return ele && ele._private.removed;\n};\n\nelesfn.inside = function(){\n var ele = this[0];\n return ele && !ele._private.removed;\n};\n\nelesfn.remove = function( notifyRenderer ){\n var self = this;\n var removed = [];\n var elesToRemove = [];\n var elesToRemoveIds = {};\n var cy = self._private.cy;\n\n if( notifyRenderer === undefined ){\n notifyRenderer = true;\n }\n\n // add connected edges\n function addConnectedEdges(node){\n var edges = node._private.edges;\n for( var i = 0; i < edges.length; i++ ){\n add( edges[i] );\n }\n }\n\n\n // add descendant nodes\n function addChildren(node){\n var children = node._private.children;\n\n for( var i = 0; i < children.length; i++ ){\n add( children[i] );\n }\n }\n\n function add( ele ){\n var alreadyAdded = elesToRemoveIds[ ele.id() ];\n if( alreadyAdded ){\n return;\n } else {\n elesToRemoveIds[ ele.id() ] = true;\n }\n\n if( ele.isNode() ){\n elesToRemove.push( ele ); // nodes are removed last\n\n addConnectedEdges( ele );\n addChildren( ele );\n } else {\n elesToRemove.unshift( ele ); // edges are removed first\n }\n }\n\n // make the list of elements to remove\n // (may be removing more than specified due to connected edges etc)\n\n for( var i = 0, l = self.length; i < l; i++ ){\n var ele = self[i];\n\n add( ele );\n }\n\n function removeEdgeRef(node, edge){\n var connectedEdges = node._private.edges;\n for( var j = 0; j < connectedEdges.length; j++ ){\n var connectedEdge = connectedEdges[j];\n\n if( edge === connectedEdge ){\n connectedEdges.splice( j, 1 );\n break;\n }\n }\n }\n\n function removeChildRef(parent, ele){\n ele = ele[0];\n parent = parent[0];\n var children = parent._private.children;\n\n for( var j = 0; j < children.length; j++ ){\n if( children[j][0] === ele[0] ){\n children.splice(j, 1);\n break;\n }\n }\n }\n\n for( var i = 0; i < elesToRemove.length; i++ ){\n var ele = elesToRemove[i];\n\n // mark as removed\n ele._private.removed = true;\n\n // remove from core pool\n cy.removeFromPool( ele );\n\n // add to list of removed elements\n removed.push( ele );\n\n if( ele.isEdge() ){ // remove references to this edge in its connected nodes\n var src = ele.source()[0];\n var tgt = ele.target()[0];\n\n removeEdgeRef( src, ele );\n removeEdgeRef( tgt, ele );\n\n } else { // remove reference to parent\n var parent = ele.parent();\n\n if( parent.length !== 0 ){\n removeChildRef(parent, ele);\n }\n }\n }\n\n // check to see if we have a compound graph or not\n var elesStillInside = cy._private.elements;\n cy._private.hasCompoundNodes = false;\n for( var i = 0; i < elesStillInside.length; i++ ){\n var ele = elesStillInside[i];\n\n if( ele.isParent() ){\n cy._private.hasCompoundNodes = true;\n break;\n }\n }\n\n var removedElements = new Collection( this.cy(), removed );\n if( removedElements.size() > 0 ){\n // must manually notify since trigger won't do this automatically once removed\n\n if( notifyRenderer ){\n this.cy().notify({\n type: 'remove',\n collection: removedElements\n });\n }\n\n removedElements.trigger('remove');\n }\n\n // check for empty remaining parent nodes\n var checkedParentId = {};\n for( var i = 0; i < elesToRemove.length; i++ ){\n var ele = elesToRemove[i];\n var isNode = ele._private.group === 'nodes';\n var parentId = ele._private.data.parent;\n\n if( isNode && parentId !== undefined && !checkedParentId[ parentId ] ){\n checkedParentId[ parentId ] = true;\n var parent = cy.getElementById( parentId );\n\n if( parent && parent.length !== 0 && !parent._private.removed && parent.children().length === 0 ){\n parent.updateStyle();\n }\n }\n }\n\n return new Collection( cy, removed );\n};\n\nelesfn.move = function( struct ){\n var cy = this._private.cy;\n\n if( struct.source !== undefined || struct.target !== undefined ){\n var srcId = struct.source;\n var tgtId = struct.target;\n var srcExists = cy.getElementById( srcId ).length > 0;\n var tgtExists = cy.getElementById( tgtId ).length > 0;\n\n if( srcExists || tgtExists ){\n var jsons = this.jsons();\n\n this.remove();\n\n for( var i = 0; i < jsons.length; i++ ){\n var json = jsons[i];\n\n if( json.group === 'edges' ){\n if( srcExists ){ json.data.source = srcId; }\n if( tgtExists ){ json.data.target = tgtId; }\n }\n }\n\n return cy.add( jsons );\n }\n\n } else if( struct.parent !== undefined ){ // move node to new parent\n var parentId = struct.parent;\n var parentExists = parentId === null || cy.getElementById( parentId ).length > 0;\n\n if( parentExists ){\n var jsons = this.jsons();\n var descs = this.descendants();\n var descsEtc = descs.merge( descs.add(this).connectedEdges() );\n\n this.remove(); // NB: also removes descendants and their connected edges\n\n for( var i = 0; i < this.length; i++ ){\n var json = jsons[i];\n\n if( json.group === 'nodes' ){\n json.data.parent = parentId === null ? undefined : parentId;\n }\n }\n }\n\n return cy.add( jsons ).merge( descsEtc.restore() );\n }\n\n return this; // if nothing done\n};\n\n[\n require('./algorithms'),\n require('./animation'),\n require('./class'),\n require('./comparators'),\n require('./compounds'),\n require('./data'),\n require('./degree'),\n require('./dimensions'),\n require('./events'),\n require('./filter'),\n require('./group'),\n require('./index'),\n require('./iteration'),\n require('./layout'),\n require('./style'),\n require('./switch-functions'),\n require('./traversing')\n].forEach(function( props ){\n util.extend( elesfn, props );\n});\n\nmodule.exports = Collection;\n","'use strict';\n\nvar is = require('../is');\nvar zIndexSort = require('./zsort');\n\nvar elesfn = ({\n each: function(fn){\n if( is.fn(fn) ){\n for(var i = 0; i < this.length; i++){\n var ele = this[i];\n var ret = fn.apply( ele, [ i, ele ] );\n\n if( ret === false ){ break; } // exit each early on return false\n }\n }\n return this;\n },\n\n forEach: function(fn, thisArg){\n if( is.fn(fn) ){\n\n for(var i = 0; i < this.length; i++){\n var ele = this[i];\n var ret = thisArg ? fn.apply( thisArg, [ ele, i, this ] ) : fn( ele, i, this );\n\n if( ret === false ){ break; } // exit each early on return false\n }\n }\n\n return this;\n },\n\n toArray: function(){\n var array = [];\n\n for(var i = 0; i < this.length; i++){\n array.push( this[i] );\n }\n\n return array;\n },\n\n slice: function(start, end){\n var array = [];\n var thisSize = this.length;\n\n if( end == null ){\n end = thisSize;\n }\n\n if( start == null ){\n start = 0;\n }\n\n if( start < 0 ){\n start = thisSize + start;\n }\n\n if( end < 0 ){\n end = thisSize + end;\n }\n\n for(var i = start; i >= 0 && i < end && i < thisSize; i++){\n array.push( this[i] );\n }\n\n return this.spawn(array);\n },\n\n size: function(){\n return this.length;\n },\n\n eq: function(i){\n return this[i] || this.spawn();\n },\n\n first: function(){\n return this[0] || this.spawn();\n },\n\n last: function(){\n return this[ this.length - 1 ] || this.spawn();\n },\n\n empty: function(){\n return this.length === 0;\n },\n\n nonempty: function(){\n return !this.empty();\n },\n\n sort: function( sortFn ){\n if( !is.fn( sortFn ) ){\n return this;\n }\n\n var sorted = this.toArray().sort( sortFn );\n\n return this.spawn(sorted);\n },\n\n sortByZIndex: function(){\n return this.sort( zIndexSort );\n },\n\n zDepth: function(){\n var ele = this[0];\n if( !ele ){ return undefined; }\n\n // var cy = ele.cy();\n var _p = ele._private;\n var group = _p.group;\n\n if( group === 'nodes' ){\n var depth = _p.data.parent ? ele.parents().size() : 0;\n\n if( !ele.isParent() ){\n return Number.MAX_VALUE; // childless nodes always on top\n }\n\n return depth;\n } else {\n var src = _p.source;\n var tgt = _p.target;\n var srcDepth = src.zDepth();\n var tgtDepth = tgt.zDepth();\n\n return Math.max( srcDepth, tgtDepth, 0 ); // depth of deepest parent\n }\n }\n});\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../is');\nvar util = require('../util');\n\nvar elesfn = ({\n\n // using standard layout options, apply position function (w/ or w/o animation)\n layoutPositions: function( layout, options, fn ){\n var nodes = this.nodes();\n var cy = this.cy();\n\n layout.trigger({ type: 'layoutstart', layout: layout });\n\n layout.animations = [];\n\n if( options.animate ){\n for( var i = 0; i < nodes.length; i++ ){\n var node = nodes[i];\n var lastNode = i === nodes.length - 1;\n\n var newPos = fn.call( node, i, node );\n var pos = node.position();\n\n if( !is.number(pos.x) || !is.number(pos.y) ){\n node.silentPosition({ x: 0, y: 0 });\n }\n\n var ani = node.animation({\n position: newPos,\n duration: options.animationDuration,\n easing: options.animationEasing,\n step: !lastNode ? undefined : function(){\n if( options.fit ){\n cy.fit( options.eles, options.padding );\n }\n },\n complete: !lastNode ? undefined : function(){\n if( options.zoom != null ){\n cy.zoom( options.zoom );\n }\n\n if( options.pan ){\n cy.pan( options.pan );\n }\n\n if( options.fit ){\n cy.fit( options.eles, options.padding );\n }\n\n layout.one('layoutstop', options.stop);\n layout.trigger({ type: 'layoutstop', layout: layout });\n }\n });\n\n layout.animations.push( ani );\n\n ani.play();\n }\n\n layout.one('layoutready', options.ready);\n layout.trigger({ type: 'layoutready', layout: layout });\n } else {\n nodes.positions( fn );\n\n if( options.fit ){\n cy.fit( options.eles, options.padding );\n }\n\n if( options.zoom != null ){\n cy.zoom( options.zoom );\n }\n\n if( options.pan ){\n cy.pan( options.pan );\n }\n\n layout.one('layoutready', options.ready);\n layout.trigger({ type: 'layoutready', layout: layout });\n\n layout.one('layoutstop', options.stop);\n layout.trigger({ type: 'layoutstop', layout: layout });\n }\n\n return this; // chaining\n },\n\n layout: function( options ){\n var cy = this.cy();\n\n cy.layout( util.extend({}, options, {\n eles: this\n }) );\n\n return this;\n },\n\n makeLayout: function( options ){\n var cy = this.cy();\n\n return cy.makeLayout( util.extend({}, options, {\n eles: this\n }) );\n }\n\n});\n\n// aliases:\nelesfn.createLayout = elesfn.makeLayout;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar is = require('../is');\n\nvar elesfn = ({\n\n // fully updates (recalculates) the style for the elements\n updateStyle: function( notifyRenderer ){\n var cy = this._private.cy;\n\n if( !cy.styleEnabled() ){ return this; }\n\n if( cy._private.batchingStyle ){\n var bEles = cy._private.batchStyleEles;\n\n bEles.merge( this );\n\n return this; // chaining and exit early when batching\n }\n\n var style = cy.style();\n notifyRenderer = notifyRenderer || notifyRenderer === undefined ? true : false;\n\n style.apply( this );\n\n var updatedCompounds = this.updateCompoundBounds();\n var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;\n\n if( notifyRenderer ){\n toNotify.rtrigger('style'); // let renderer know we changed style\n } else {\n toNotify.trigger('style'); // just fire the event\n }\n return this; // chaining\n },\n\n // just update the mappers in the elements' styles; cheaper than eles.updateStyle()\n updateMappers: function( notifyRenderer ){\n var cy = this._private.cy;\n var style = cy.style();\n notifyRenderer = notifyRenderer || notifyRenderer === undefined ? true : false;\n\n if( !cy.styleEnabled() ){ return this; }\n\n style.updateMappers( this );\n\n var updatedCompounds = this.updateCompoundBounds();\n var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;\n\n if( notifyRenderer ){\n toNotify.rtrigger('style'); // let renderer know we changed style\n } else {\n toNotify.trigger('style'); // just fire the event\n }\n return this; // chaining\n },\n\n // get the specified css property as a rendered value (i.e. on-screen value)\n // or get the whole rendered style if no property specified (NB doesn't allow setting)\n renderedCss: function( property ){\n var cy = this.cy();\n if( !cy.styleEnabled() ){ return this; }\n\n var ele = this[0];\n\n if( ele ){\n var renstyle = ele.cy().style().getRenderedStyle( ele );\n\n if( property === undefined ){\n return renstyle;\n } else {\n return renstyle[ property ];\n }\n }\n },\n\n // read the calculated css style of the element or override the style (via a bypass)\n css: function( name, value ){\n var cy = this.cy();\n\n if( !cy.styleEnabled() ){ return this; }\n\n var updateTransitions = false;\n var style = cy.style();\n\n if( is.plainObject(name) ){ // then extend the bypass\n var props = name;\n style.applyBypass( this, props, updateTransitions );\n\n var updatedCompounds = this.updateCompoundBounds();\n var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;\n toNotify.rtrigger('style'); // let the renderer know we've updated style\n\n } else if( is.string(name) ){\n\n if( value === undefined ){ // then get the property from the style\n var ele = this[0];\n\n if( ele ){\n return style.getStylePropertyValue( ele, name );\n } else { // empty collection => can't get any value\n return;\n }\n\n } else { // then set the bypass with the property value\n style.applyBypass( this, name, value, updateTransitions );\n\n var updatedCompounds = this.updateCompoundBounds();\n var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;\n toNotify.rtrigger('style'); // let the renderer know we've updated style\n }\n\n } else if( name === undefined ){\n var ele = this[0];\n\n if( ele ){\n return style.getRawStyle( ele );\n } else { // empty collection => can't get any value\n return;\n }\n }\n\n return this; // chaining\n },\n\n removeCss: function( names ){\n var cy = this.cy();\n\n if( !cy.styleEnabled() ){ return this; }\n\n var updateTransitions = false;\n var style = cy.style();\n var eles = this;\n\n if( names === undefined ){\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n\n style.removeAllBypasses( ele, updateTransitions );\n }\n } else {\n names = names.split(/\\s+/);\n\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n\n style.removeBypasses( ele, names, updateTransitions );\n }\n }\n\n var updatedCompounds = this.updateCompoundBounds();\n var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;\n toNotify.rtrigger('style'); // let the renderer know we've updated style\n\n return this; // chaining\n },\n\n show: function(){\n this.css('display', 'element');\n return this; // chaining\n },\n\n hide: function(){\n this.css('display', 'none');\n return this; // chaining\n },\n\n visible: function(){\n var cy = this.cy();\n if( !cy.styleEnabled() ){ return true; }\n\n var ele = this[0];\n var hasCompoundNodes = cy.hasCompoundNodes();\n\n if( ele ){\n var style = ele._private.style;\n\n if(\n style['visibility'].value !== 'visible'\n || style['display'].value !== 'element'\n ){\n return false;\n }\n\n if( ele._private.group === 'nodes' ){\n if( !hasCompoundNodes ){ return true; }\n\n var parents = ele._private.data.parent ? ele.parents() : null;\n\n if( parents ){\n for( var i = 0; i < parents.length; i++ ){\n var parent = parents[i];\n var pStyle = parent._private.style;\n var pVis = pStyle['visibility'].value;\n var pDis = pStyle['display'].value;\n\n if( pVis !== 'visible' || pDis !== 'element' ){\n return false;\n }\n }\n }\n\n return true;\n } else {\n var src = ele._private.source;\n var tgt = ele._private.target;\n\n return src.visible() && tgt.visible();\n }\n\n }\n },\n\n hidden: function(){\n var ele = this[0];\n\n if( ele ){\n return !ele.visible();\n }\n },\n\n effectiveOpacity: function(){\n var cy = this.cy();\n if( !cy.styleEnabled() ){ return 1; }\n\n var hasCompoundNodes = cy.hasCompoundNodes();\n var ele = this[0];\n\n if( ele ){\n var _p = ele._private;\n var parentOpacity = _p.style.opacity.value;\n\n if( !hasCompoundNodes ){ return parentOpacity; }\n\n var parents = !_p.data.parent ? null : ele.parents();\n\n if( parents ){\n for( var i = 0; i < parents.length; i++ ){\n var parent = parents[i];\n var opacity = parent._private.style.opacity.value;\n\n parentOpacity = opacity * parentOpacity;\n }\n }\n\n return parentOpacity;\n }\n },\n\n transparent: function(){\n var cy = this.cy();\n if( !cy.styleEnabled() ){ return false; }\n\n var ele = this[0];\n var hasCompoundNodes = ele.cy().hasCompoundNodes();\n\n if( ele ){\n if( !hasCompoundNodes ){\n return ele._private.style.opacity.value === 0;\n } else {\n return ele.effectiveOpacity() === 0;\n }\n }\n },\n\n isFullAutoParent: function(){\n var cy = this.cy();\n if( !cy.styleEnabled() ){ return false; }\n\n var ele = this[0];\n\n if( ele ){\n var autoW = ele._private.style['width'].value === 'auto';\n var autoH = ele._private.style['height'].value === 'auto';\n\n return ele.isParent() && autoW && autoH;\n }\n },\n\n backgrounding: function(){\n var cy = this.cy();\n if( !cy.styleEnabled() ){ return false; }\n\n var ele = this[0];\n\n return ele._private.backgrounding ? true : false;\n }\n\n});\n\n\nelesfn.bypass = elesfn.style = elesfn.css;\nelesfn.renderedStyle = elesfn.renderedCss;\nelesfn.removeBypass = elesfn.removeStyle = elesfn.removeCss;\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar elesfn = {};\n\nfunction defineSwitchFunction(params){\n return function(){\n var args = arguments;\n var changedEles = [];\n\n // e.g. cy.nodes().select( data, handler )\n if( args.length === 2 ){\n var data = args[0];\n var handler = args[1];\n this.bind( params.event, data, handler );\n }\n\n // e.g. cy.nodes().select( handler )\n else if( args.length === 1 ){\n var handler = args[0];\n this.bind( params.event, handler );\n }\n\n // e.g. cy.nodes().select()\n else if( args.length === 0 ){\n for( var i = 0; i < this.length; i++ ){\n var ele = this[i];\n var able = !params.ableField || ele._private[params.ableField];\n var changed = ele._private[params.field] != params.value;\n\n if( params.overrideAble ){\n var overrideAble = params.overrideAble(ele);\n\n if( overrideAble !== undefined ){\n able = overrideAble;\n\n if( !overrideAble ){ return this; } // to save cycles assume not able for all on override\n }\n }\n\n if( able ){\n ele._private[params.field] = params.value;\n\n if( changed ){\n changedEles.push( ele );\n }\n }\n }\n\n var changedColl = this.spawn( changedEles );\n changedColl.updateStyle(); // change of state => possible change of style\n changedColl.trigger( params.event );\n }\n\n return this;\n };\n}\n\nfunction defineSwitchSet( params ){\n elesfn[ params.field ] = function(){\n var ele = this[0];\n\n if( ele ){\n if( params.overrideField ){\n var val = params.overrideField(ele);\n\n if( val !== undefined ){\n return val;\n }\n }\n\n return ele._private[ params.field ];\n }\n };\n\n elesfn[ params.on ] = defineSwitchFunction({\n event: params.on,\n field: params.field,\n ableField: params.ableField,\n overrideAble: params.overrideAble,\n value: true\n });\n\n elesfn[ params.off ] = defineSwitchFunction({\n event: params.off,\n field: params.field,\n ableField: params.ableField,\n overrideAble: params.overrideAble,\n value: false\n });\n}\n\ndefineSwitchSet({\n field: 'locked',\n overrideField: function(ele){\n return ele.cy().autolock() ? true : undefined;\n },\n on: 'lock',\n off: 'unlock'\n});\n\ndefineSwitchSet({\n field: 'grabbable',\n overrideField: function(ele){\n return ele.cy().autoungrabify() ? false : undefined;\n },\n on: 'grabify',\n off: 'ungrabify'\n});\n\ndefineSwitchSet({\n field: 'selected',\n ableField: 'selectable',\n overrideAble: function(ele){\n return ele.cy().autounselectify() ? false : undefined;\n },\n on: 'select',\n off: 'unselect'\n});\n\ndefineSwitchSet({\n field: 'selectable',\n overrideField: function(ele){\n return ele.cy().autounselectify() ? false : undefined;\n },\n on: 'selectify',\n off: 'unselectify'\n});\n\nelesfn.deselect = elesfn.unselect;\n\nelesfn.grabbed = function(){\n var ele = this[0];\n if( ele ){\n return ele._private.grabbed;\n }\n};\n\ndefineSwitchSet({\n field: 'active',\n on: 'activate',\n off: 'unactivate'\n});\n\nelesfn.inactive = function(){\n var ele = this[0];\n if( ele ){\n return !ele._private.active;\n }\n};\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar util = require('../util');\nvar is = require('../is');\n\nvar elesfn = {};\n\nutil.extend(elesfn, {\n // get the root nodes in the DAG\n roots: function( selector ){\n var eles = this;\n var roots = [];\n\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n if( !ele.isNode() ){\n continue;\n }\n\n var hasEdgesPointingIn = ele.connectedEdges(function(){\n return this.data('target') === ele.id() && this.data('source') !== ele.id();\n }).length > 0;\n\n if( !hasEdgesPointingIn ){\n roots.push( ele );\n }\n }\n\n return this.spawn( roots, { unique: true } ).filter( selector );\n },\n\n // get the leaf nodes in the DAG\n leaves: function( selector ){\n var eles = this;\n var leaves = [];\n\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n if( !ele.isNode() ){\n continue;\n }\n\n var hasEdgesPointingOut = ele.connectedEdges(function(){\n return this.data('source') === ele.id() && this.data('target') !== ele.id();\n }).length > 0;\n\n if( !hasEdgesPointingOut ){\n leaves.push( ele );\n }\n }\n\n return this.spawn( leaves, { unique: true } ).filter( selector );\n },\n\n // normally called children in graph theory\n // these nodes =edges=> outgoing nodes\n outgoers: function( selector ){\n var eles = this;\n var oEles = [];\n\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n var eleId = ele.id();\n\n if( !ele.isNode() ){ continue; }\n\n var edges = ele._private.edges;\n for( var j = 0; j < edges.length; j++ ){\n var edge = edges[j];\n var srcId = edge._private.data.source;\n var tgtId = edge._private.data.target;\n\n if( srcId === eleId && tgtId !== eleId ){\n oEles.push( edge );\n oEles.push( edge.target()[0] );\n }\n }\n }\n\n return this.spawn( oEles, { unique: true } ).filter( selector );\n },\n\n // aka DAG descendants\n successors: function( selector ){\n var eles = this;\n var sEles = [];\n var sElesIds = {};\n\n for(;;){\n var outgoers = eles.outgoers();\n\n if( outgoers.length === 0 ){ break; } // done if no outgoers left\n\n var newOutgoers = false;\n for( var i = 0; i < outgoers.length; i++ ){\n var outgoer = outgoers[i];\n var outgoerId = outgoer.id();\n\n if( !sElesIds[ outgoerId ] ){\n sElesIds[ outgoerId ] = true;\n sEles.push( outgoer );\n newOutgoers = true;\n }\n }\n\n if( !newOutgoers ){ break; } // done if touched all outgoers already\n\n eles = outgoers;\n }\n\n return this.spawn( sEles, { unique: true } ).filter( selector );\n },\n\n // normally called parents in graph theory\n // these nodes <=edges= incoming nodes\n incomers: function( selector ){\n var eles = this;\n var oEles = [];\n\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n var eleId = ele.id();\n\n if( !ele.isNode() ){ continue; }\n\n var edges = ele._private.edges;\n for( var j = 0; j < edges.length; j++ ){\n var edge = edges[j];\n var srcId = edge._private.data.source;\n var tgtId = edge._private.data.target;\n\n if( tgtId === eleId && srcId !== eleId ){\n oEles.push( edge );\n oEles.push( edge.source()[0] );\n }\n }\n }\n\n return this.spawn( oEles, { unique: true } ).filter( selector );\n },\n\n // aka DAG ancestors\n predecessors: function( selector ){\n var eles = this;\n var pEles = [];\n var pElesIds = {};\n\n for(;;){\n var incomers = eles.incomers();\n\n if( incomers.length === 0 ){ break; } // done if no incomers left\n\n var newIncomers = false;\n for( var i = 0; i < incomers.length; i++ ){\n var incomer = incomers[i];\n var incomerId = incomer.id();\n\n if( !pElesIds[ incomerId ] ){\n pElesIds[ incomerId ] = true;\n pEles.push( incomer );\n newIncomers = true;\n }\n }\n\n if( !newIncomers ){ break; } // done if touched all incomers already\n\n eles = incomers;\n }\n\n return this.spawn( pEles, { unique: true } ).filter( selector );\n }\n});\n\n\n// Neighbourhood functions\n//////////////////////////\n\nutil.extend(elesfn, {\n neighborhood: function(selector){\n var elements = [];\n var nodes = this.nodes();\n\n for( var i = 0; i < nodes.length; i++ ){ // for all nodes\n var node = nodes[i];\n var connectedEdges = node.connectedEdges();\n\n // for each connected edge, add the edge and the other node\n for( var j = 0; j < connectedEdges.length; j++ ){\n var edge = connectedEdges[j];\n var src = edge._private.source;\n var tgt = edge._private.target;\n var otherNode = node === src ? tgt : src;\n\n // need check in case of loop\n if( otherNode.length > 0 ){\n elements.push( otherNode[0] ); // add node 1 hop away\n }\n\n // add connected edge\n elements.push( edge[0] );\n }\n\n }\n\n return ( this.spawn( elements, { unique: true } ) ).filter( selector );\n },\n\n closedNeighborhood: function(selector){\n return this.neighborhood().add( this ).filter( selector );\n },\n\n openNeighborhood: function(selector){\n return this.neighborhood( selector );\n }\n});\n\n// aliases\nelesfn.neighbourhood = elesfn.neighborhood;\nelesfn.closedNeighbourhood = elesfn.closedNeighborhood;\nelesfn.openNeighbourhood = elesfn.openNeighborhood;\n\n// Edge functions\n/////////////////\n\nutil.extend(elesfn, {\n source: function( selector ){\n var ele = this[0];\n var src;\n\n if( ele ){\n src = ele._private.source;\n }\n\n return src && selector ? src.filter( selector ) : src;\n },\n\n target: function( selector ){\n var ele = this[0];\n var tgt;\n\n if( ele ){\n tgt = ele._private.target;\n }\n\n return tgt && selector ? tgt.filter( selector ) : tgt;\n },\n\n sources: defineSourceFunction({\n attr: 'source'\n }),\n\n targets: defineSourceFunction({\n attr: 'target'\n })\n});\n\nfunction defineSourceFunction( params ){\n return function( selector ){\n var sources = [];\n\n for( var i = 0; i < this.length; i++ ){\n var ele = this[i];\n var src = ele._private[ params.attr ];\n\n if( src ){\n sources.push( src );\n }\n }\n\n return this.spawn( sources, { unique: true } ).filter( selector );\n };\n}\n\nutil.extend(elesfn, {\n edgesWith: defineEdgesWithFunction(),\n\n edgesTo: defineEdgesWithFunction({\n thisIs: 'source'\n })\n});\n\nfunction defineEdgesWithFunction( params ){\n\n return function edgesWithImpl( otherNodes ){\n var elements = [];\n var cy = this._private.cy;\n var p = params || {};\n\n // get elements if a selector is specified\n if( is.string(otherNodes) ){\n otherNodes = cy.$( otherNodes );\n }\n\n var thisIds = this._private.ids;\n var otherIds = otherNodes._private.ids;\n\n for( var h = 0; h < otherNodes.length; h++ ){\n var edges = otherNodes[h]._private.edges;\n\n for( var i = 0; i < edges.length; i++ ){\n var edge = edges[i];\n var edgeData = edge._private.data;\n var thisToOther = thisIds[ edgeData.source ] && otherIds[ edgeData.target ];\n var otherToThis = otherIds[ edgeData.source ] && thisIds[ edgeData.target ];\n var edgeConnectsThisAndOther = thisToOther || otherToThis;\n\n if( !edgeConnectsThisAndOther ){ continue; }\n\n if( p.thisIs ){\n if( p.thisIs === 'source' && !thisToOther ){ continue; }\n\n if( p.thisIs === 'target' && !otherToThis ){ continue; }\n }\n\n elements.push( edge );\n }\n }\n\n return this.spawn( elements, { unique: true } );\n };\n}\n\nutil.extend(elesfn, {\n connectedEdges: function( selector ){\n var retEles = [];\n\n var eles = this;\n for( var i = 0; i < eles.length; i++ ){\n var node = eles[i];\n if( !node.isNode() ){ continue; }\n\n var edges = node._private.edges;\n\n for( var j = 0; j < edges.length; j++ ){\n var edge = edges[j];\n retEles.push( edge );\n }\n }\n\n return this.spawn( retEles, { unique: true } ).filter( selector );\n },\n\n connectedNodes: function( selector ){\n var retEles = [];\n\n var eles = this;\n for( var i = 0; i < eles.length; i++ ){\n var edge = eles[i];\n if( !edge.isEdge() ){ continue; }\n\n retEles.push( edge.source()[0] );\n retEles.push( edge.target()[0] );\n }\n\n return this.spawn( retEles, { unique: true } ).filter( selector );\n },\n\n parallelEdges: defineParallelEdgesFunction(),\n\n codirectedEdges: defineParallelEdgesFunction({\n codirected: true\n })\n});\n\nfunction defineParallelEdgesFunction(params){\n var defaults = {\n codirected: false\n };\n params = util.extend({}, defaults, params);\n\n return function( selector ){\n var elements = [];\n var edges = this.edges();\n var p = params;\n\n // look at all the edges in the collection\n for( var i = 0; i < edges.length; i++ ){\n var edge1 = edges[i];\n var src1 = edge1.source()[0];\n var srcid1 = src1.id();\n var tgt1 = edge1.target()[0];\n var tgtid1 = tgt1.id();\n var srcEdges1 = src1._private.edges;\n\n // look at edges connected to the src node of this edge\n for( var j = 0; j < srcEdges1.length; j++ ){\n var edge2 = srcEdges1[j];\n var edge2data = edge2._private.data;\n var tgtid2 = edge2data.target;\n var srcid2 = edge2data.source;\n\n var codirected = tgtid2 === tgtid1 && srcid2 === srcid1;\n var oppdirected = srcid1 === tgtid2 && tgtid1 === srcid2;\n\n if( (p.codirected && codirected) || (!p.codirected && (codirected || oppdirected)) ){\n elements.push( edge2 );\n }\n }\n }\n\n return this.spawn( elements, { unique: true } ).filter( selector );\n };\n\n}\n\n// Misc functions\n/////////////////\n\nutil.extend(elesfn, {\n components: function(){\n var cy = this.cy();\n var visited = cy.collection();\n var unvisited = this.nodes();\n var components = [];\n\n var visitInComponent = function( node, component ){\n visited.merge( node );\n unvisited.unmerge( node );\n component.merge( node );\n };\n\n do {\n var component = cy.collection();\n components.push( component );\n\n var root = unvisited[0];\n visitInComponent( root, component );\n\n this.bfs({\n directed: false,\n roots: root,\n visit: function( i, depth, v, e, u ){\n visitInComponent( v, component );\n }\n });\n\n } while( unvisited.length > 0 );\n\n return components.map(function( component ){\n var connectedEdges = component.connectedEdges().stdFilter(function( edge ){\n return component.anySame( edge.source() ) && component.anySame( edge.target() );\n });\n\n return component.union( connectedEdges );\n });\n }\n});\n\nmodule.exports = elesfn;\n","'use strict';\n\nvar zIndexSort = function( a, b ){\n var cy = a.cy();\n var a_p = a._private;\n var b_p = b._private;\n var zDiff = a_p.style['z-index'].value - b_p.style['z-index'].value;\n var depthA = 0;\n var depthB = 0;\n var hasCompoundNodes = cy.hasCompoundNodes();\n var aIsNode = a_p.group === 'nodes';\n var aIsEdge = a_p.group === 'edges';\n var bIsNode = b_p.group === 'nodes';\n var bIsEdge = b_p.group === 'edges';\n\n // no need to calculate element depth if there is no compound node\n if( hasCompoundNodes ){\n depthA = a.zDepth();\n depthB = b.zDepth();\n }\n\n var depthDiff = depthA - depthB;\n var sameDepth = depthDiff === 0;\n\n if( sameDepth ){\n\n if( aIsNode && bIsEdge ){\n return 1; // 'a' is a node, it should be drawn later\n\n } else if( aIsEdge && bIsNode ){\n return -1; // 'a' is an edge, it should be drawn first\n\n } else { // both nodes or both edges\n if( zDiff === 0 ){ // same z-index => compare indices in the core (order added to graph w/ last on top)\n return a_p.index - b_p.index;\n } else {\n return zDiff;\n }\n }\n\n // elements on different level\n } else {\n return depthDiff; // deeper element should be drawn later\n }\n\n};\n\nmodule.exports = zIndexSort;\n","'use strict';\n\nvar is = require('../is');\nvar util = require('../util');\nvar Collection = require('../collection');\nvar Element = require('../collection/element');\nvar window = require('../window');\nvar document = window ? window.document : null;\nvar NullRenderer = require('../extensions/renderer/null');\n\nvar corefn = {\n add: function(opts){\n\n var elements;\n var cy = this;\n\n // add the elements\n if( is.elementOrCollection(opts) ){\n var eles = opts;\n\n if( eles._private.cy === cy ){ // same instance => just restore\n elements = eles.restore();\n\n } else { // otherwise, copy from json\n var jsons = [];\n\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n jsons.push( ele.json() );\n }\n\n elements = new Collection( cy, jsons );\n }\n }\n\n // specify an array of options\n else if( is.array(opts) ){\n var jsons = opts;\n\n elements = new Collection(cy, jsons);\n }\n\n // specify via opts.nodes and opts.edges\n else if( is.plainObject(opts) && (is.array(opts.nodes) || is.array(opts.edges)) ){\n var elesByGroup = opts;\n var jsons = [];\n\n var grs = ['nodes', 'edges'];\n for( var i = 0, il = grs.length; i < il; i++ ){\n var group = grs[i];\n var elesArray = elesByGroup[group];\n\n if( is.array(elesArray) ){\n\n for( var j = 0, jl = elesArray.length; j < jl; j++ ){\n var json = util.extend( { group: group }, elesArray[j] );\n\n jsons.push( json );\n }\n }\n }\n\n elements = new Collection(cy, jsons);\n }\n\n // specify options for one element\n else {\n var json = opts;\n elements = (new Element( cy, json )).collection();\n }\n\n return elements;\n },\n\n remove: function(collection){\n if( is.elementOrCollection(collection) ){\n collection = collection;\n } else if( is.string(collection) ){\n var selector = collection;\n collection = this.$( selector );\n }\n\n return collection.remove();\n },\n\n load: function(elements, onload, ondone){\n var cy = this;\n\n cy.notifications(false);\n\n // remove old elements\n var oldEles = cy.elements();\n if( oldEles.length > 0 ){\n oldEles.remove();\n }\n\n if( elements != null ){\n if( is.plainObject(elements) || is.array(elements) ){\n cy.add( elements );\n }\n }\n\n cy.one('layoutready', function(e){\n cy.notifications(true);\n cy.trigger(e); // we missed this event by turning notifications off, so pass it on\n\n cy.notify({\n type: 'load',\n collection: cy.elements()\n });\n\n cy.one('load', onload);\n cy.trigger('load');\n }).one('layoutstop', function(){\n cy.one('done', ondone);\n cy.trigger('done');\n });\n\n var layoutOpts = util.extend({}, cy._private.options.layout);\n layoutOpts.eles = cy.$();\n\n cy.layout( layoutOpts );\n\n return this;\n }\n};\n\nmodule.exports = corefn;\n","'use strict';\n\nvar define = require('../define');\nvar util = require('../util');\nvar is = require('../is');\n\nvar corefn = ({\n\n // pull in animation functions\n animate: define.animate(),\n animation: define.animation(),\n animated: define.animated(),\n clearQueue: define.clearQueue(),\n delay: define.delay(),\n delayAnimation: define.delayAnimation(),\n stop: define.stop(),\n\n addToAnimationPool: function( eles ){\n var cy = this;\n\n if( !cy.styleEnabled() ){ return; } // save cycles when no style used\n\n cy._private.aniEles.merge( eles );\n },\n\n stopAnimationLoop: function(){\n this._private.animationsRunning = false;\n },\n\n startAnimationLoop: function(){\n var cy = this;\n\n cy._private.animationsRunning = true;\n\n if( !cy.styleEnabled() ){ return; } // save cycles when no style used\n\n // NB the animation loop will exec in headless environments if style enabled\n // and explicit cy.destroy() is necessary to stop the loop\n\n function globalAnimationStep(){\n if( !cy._private.animationsRunning ){ return; }\n\n util.requestAnimationFrame(function(now){\n handleElements(now);\n globalAnimationStep();\n });\n }\n\n globalAnimationStep(); // first call\n\n function handleElements( now ){\n var eles = cy._private.aniEles;\n var doneEles = [];\n\n function handleElement( ele, isCore ){\n var _p = ele._private;\n var current = _p.animation.current;\n var queue = _p.animation.queue;\n var ranAnis = false;\n\n // if nothing currently animating, get something from the queue\n if( current.length === 0 ){\n var next = queue.shift();\n\n if( next ){\n current.push( next );\n }\n }\n\n var callbacks = function( callbacks ){\n for( var j = callbacks.length - 1; j >= 0; j-- ){\n var cb = callbacks[j];\n\n cb();\n }\n\n callbacks.splice( 0, callbacks.length );\n };\n\n // step and remove if done\n for( var i = current.length - 1; i >= 0; i-- ){\n var ani = current[i];\n var ani_p = ani._private;\n\n if( ani_p.stopped ){\n current.splice( i, 1 );\n\n ani_p.hooked = false;\n ani_p.playing = false;\n ani_p.started = false;\n\n callbacks( ani_p.frames );\n\n continue;\n }\n\n if( !ani_p.playing && !ani_p.applying ){ continue; }\n\n // an apply() while playing shouldn't do anything\n if( ani_p.playing && ani_p.applying ){\n ani_p.applying = false;\n }\n\n if( !ani_p.started ){\n startAnimation( ele, ani, now );\n }\n\n step( ele, ani, now, isCore );\n\n if( ani_p.applying ){\n ani_p.applying = false;\n }\n\n callbacks( ani_p.frames );\n\n if( ani.completed() ){\n current.splice(i, 1);\n\n ani_p.hooked = false;\n ani_p.playing = false;\n ani_p.started = false;\n\n callbacks( ani_p.completes );\n }\n\n ranAnis = true;\n }\n\n if( !isCore && current.length === 0 && queue.length === 0 ){\n doneEles.push( ele );\n }\n\n return ranAnis;\n } // handleElement\n\n // handle all eles\n var ranEleAni = false;\n for( var e = 0; e < eles.length; e++ ){\n var ele = eles[e];\n var handledThisEle = handleElement( ele );\n\n ranEleAni = ranEleAni || handledThisEle;\n } // each element\n\n var ranCoreAni = handleElement( cy, true );\n\n // notify renderer\n if( ranEleAni || ranCoreAni ){\n var toNotify;\n\n if( eles.length > 0 ){\n var updatedEles = eles.updateCompoundBounds();\n toNotify = updatedEles.length > 0 ? eles.add( updatedEles ) : eles;\n }\n\n cy.notify({\n type: 'draw',\n collection: toNotify\n });\n }\n\n // remove elements from list of currently animating if its queues are empty\n eles.unmerge( doneEles );\n\n } // handleElements\n\n function startAnimation( self, ani, now ){\n var isCore = is.core( self );\n var isEles = !isCore;\n var ele = self;\n var style = cy._private.style;\n var ani_p = ani._private;\n\n if( isEles ){\n var pos = ele._private.position;\n\n ani_p.startPosition = ani_p.startPosition || {\n x: pos.x,\n y: pos.y\n };\n\n ani_p.startStyle = ani_p.startStyle || style.getValueStyle( ele );\n }\n\n if( isCore ){\n var pan = cy._private.pan;\n\n ani_p.startPan = ani_p.startPan || {\n x: pan.x,\n y: pan.y\n };\n\n ani_p.startZoom = ani_p.startZoom != null ? ani_p.startZoom : cy._private.zoom;\n }\n\n ani_p.started = true;\n ani_p.startTime = now - ani_p.progress * ani_p.duration;\n }\n\n function step( self, ani, now, isCore ){\n var style = cy._private.style;\n var isEles = !isCore;\n var _p = self._private;\n var ani_p = ani._private;\n var pEasing = ani_p.easing;\n var startTime = ani_p.startTime;\n\n if( !ani_p.easingImpl ){\n\n if( pEasing == null ){ // use default\n ani_p.easingImpl = easings['linear'];\n\n } else { // then define w/ name\n var easingVals;\n\n if( is.string( pEasing ) ){\n var easingProp = style.parse('transition-timing-function', pEasing);\n\n easingVals = easingProp.value;\n\n } else { // then assume preparsed array\n easingVals = pEasing;\n }\n\n var name, args;\n\n if( is.string( easingVals ) ){\n name = easingVals;\n args = [];\n } else {\n name = easingVals[1];\n args = easingVals.slice(2).map(function(n){ return +n; });\n }\n\n if( args.length > 0 ){ // create with args\n if( name === 'spring' ){\n args.push( ani_p.duration ); // need duration to generate spring\n }\n\n ani_p.easingImpl = easings[ name ].apply( null, args );\n } else { // static impl by name\n ani_p.easingImpl = easings[ name ];\n }\n }\n\n }\n\n var easing = ani_p.easingImpl;\n var percent;\n\n if( ani_p.duration === 0 ){\n percent = 1;\n } else {\n percent = (now - startTime) / ani_p.duration;\n }\n\n if( ani_p.applying ){\n percent = ani_p.progress;\n }\n\n if( percent < 0 ){\n percent = 0;\n } else if( percent > 1 ){\n percent = 1;\n }\n\n if( ani_p.delay == null ){ // then update\n\n var startPos = ani_p.startPosition;\n var endPos = ani_p.position;\n var pos = _p.position;\n if( endPos && isEles ){\n if( valid( startPos.x, endPos.x ) ){\n pos.x = ease( startPos.x, endPos.x, percent, easing );\n }\n\n if( valid( startPos.y, endPos.y ) ){\n pos.y = ease( startPos.y, endPos.y, percent, easing );\n }\n }\n\n var startPan = ani_p.startPan;\n var endPan = ani_p.pan;\n var pan = _p.pan;\n var animatingPan = endPan != null && isCore;\n if( animatingPan ){\n if( valid( startPan.x, endPan.x ) ){\n pan.x = ease( startPan.x, endPan.x, percent, easing );\n }\n\n if( valid( startPan.y, endPan.y ) ){\n pan.y = ease( startPan.y, endPan.y, percent, easing );\n }\n\n self.trigger('pan');\n }\n\n var startZoom = ani_p.startZoom;\n var endZoom = ani_p.zoom;\n var animatingZoom = endZoom != null && isCore;\n if( animatingZoom ){\n if( valid( startZoom, endZoom ) ){\n _p.zoom = ease( startZoom, endZoom, percent, easing );\n }\n\n self.trigger('zoom');\n }\n\n if( animatingPan || animatingZoom ){\n self.trigger('viewport');\n }\n\n var props = ani_p.style;\n if( props && isEles ){\n\n for( var i = 0; i < props.length; i++ ){\n var prop = props[i];\n var name = prop.name;\n var end = prop;\n\n var start = ani_p.startStyle[ name ];\n var easedVal = ease( start, end, percent, easing );\n\n style.overrideBypass( self, name, easedVal );\n } // for props\n\n } // if\n\n }\n\n if( is.fn(ani_p.step) ){\n ani_p.step.apply( self, [ now ] );\n }\n\n ani_p.progress = percent;\n\n return percent;\n }\n\n function valid(start, end){\n if( start == null || end == null ){\n return false;\n }\n\n if( is.number(start) && is.number(end) ){\n return true;\n } else if( (start) && (end) ){\n return true;\n }\n\n return false;\n }\n\n // assumes p0 = 0, p3 = 1\n function evalCubicBezier( p1, p2, t ){\n var one_t = 1 - t;\n var tsq = t*t;\n\n return ( 3 * one_t * one_t * t * p1 ) + ( 3 * one_t * tsq * p2 ) + tsq * t;\n }\n\n function cubicBezier( p1, p2 ){\n return function( start, end, percent ){\n return start + (end - start) * evalCubicBezier( p1, p2, percent );\n };\n }\n\n /*! Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */\n /* Given a tension, friction, and duration, a simulation at 60FPS will first run without a defined duration in order to calculate the full path. A second pass\n then adjusts the time delta -- using the relation between actual time and duration -- to calculate the path for the duration-constrained animation. */\n var generateSpringRK4 = (function () {\n function springAccelerationForState (state) {\n return (-state.tension * state.x) - (state.friction * state.v);\n }\n\n function springEvaluateStateWithDerivative (initialState, dt, derivative) {\n var state = {\n x: initialState.x + derivative.dx * dt,\n v: initialState.v + derivative.dv * dt,\n tension: initialState.tension,\n friction: initialState.friction\n };\n\n return { dx: state.v, dv: springAccelerationForState(state) };\n }\n\n function springIntegrateState (state, dt) {\n var a = {\n dx: state.v,\n dv: springAccelerationForState(state)\n },\n b = springEvaluateStateWithDerivative(state, dt * 0.5, a),\n c = springEvaluateStateWithDerivative(state, dt * 0.5, b),\n d = springEvaluateStateWithDerivative(state, dt, c),\n dxdt = 1.0 / 6.0 * (a.dx + 2.0 * (b.dx + c.dx) + d.dx),\n dvdt = 1.0 / 6.0 * (a.dv + 2.0 * (b.dv + c.dv) + d.dv);\n\n state.x = state.x + dxdt * dt;\n state.v = state.v + dvdt * dt;\n\n return state;\n }\n\n return function springRK4Factory (tension, friction, duration) {\n\n var initState = {\n x: -1,\n v: 0,\n tension: null,\n friction: null\n },\n path = [0],\n time_lapsed = 0,\n tolerance = 1 / 10000,\n DT = 16 / 1000,\n have_duration, dt, last_state;\n\n tension = parseFloat(tension) || 500;\n friction = parseFloat(friction) || 20;\n duration = duration || null;\n\n initState.tension = tension;\n initState.friction = friction;\n\n have_duration = duration !== null;\n\n /* Calculate the actual time it takes for this animation to complete with the provided conditions. */\n if (have_duration) {\n /* Run the simulation without a duration. */\n time_lapsed = springRK4Factory(tension, friction);\n /* Compute the adjusted time delta. */\n dt = time_lapsed / duration * DT;\n } else {\n dt = DT;\n }\n\n while (true) {\n /* Next/step function .*/\n last_state = springIntegrateState(last_state || initState, dt);\n /* Store the position. */\n path.push(1 + last_state.x);\n time_lapsed += 16;\n /* If the change threshold is reached, break. */\n if (!(Math.abs(last_state.x) > tolerance && Math.abs(last_state.v) > tolerance)) {\n break;\n }\n }\n\n /* If duration is not defined, return the actual time required for completing this animation. Otherwise, return a closure that holds the\n computed path and returns a snapshot of the position according to a given percentComplete. */\n return !have_duration ? time_lapsed : function(percentComplete) { return path[ (percentComplete * (path.length - 1)) | 0 ]; };\n };\n }());\n\n var easings = {\n 'linear': function( start, end, percent ){\n return start + (end - start) * percent;\n },\n\n // default easings\n 'ease': cubicBezier( 0.25, 0.1, 0.25, 1 ),\n 'ease-in': cubicBezier( 0.42, 0, 1, 1 ),\n 'ease-out': cubicBezier( 0, 0, 0.58, 1 ),\n 'ease-in-out': cubicBezier( 0.42, 0, 0.58, 1 ),\n\n // sine\n 'ease-in-sine': cubicBezier( 0.47, 0, 0.745, 0.715 ),\n 'ease-out-sine': cubicBezier( 0.39, 0.575, 0.565, 1 ),\n 'ease-in-out-sine': cubicBezier( 0.445, 0.05, 0.55, 0.95 ),\n\n // quad\n 'ease-in-quad': cubicBezier( 0.55, 0.085, 0.68, 0.53 ),\n 'ease-out-quad': cubicBezier( 0.25, 0.46, 0.45, 0.94 ),\n 'ease-in-out-quad': cubicBezier( 0.455, 0.03, 0.515, 0.955 ),\n\n // cubic\n 'ease-in-cubic': cubicBezier( 0.55, 0.055, 0.675, 0.19 ),\n 'ease-out-cubic': cubicBezier( 0.215, 0.61, 0.355, 1 ),\n 'ease-in-out-cubic': cubicBezier( 0.645, 0.045, 0.355, 1 ),\n\n // quart\n 'ease-in-quart': cubicBezier( 0.895, 0.03, 0.685, 0.22 ),\n 'ease-out-quart': cubicBezier( 0.165, 0.84, 0.44, 1 ),\n 'ease-in-out-quart': cubicBezier( 0.77, 0, 0.175, 1 ),\n\n // quint\n 'ease-in-quint': cubicBezier( 0.755, 0.05, 0.855, 0.06 ),\n 'ease-out-quint': cubicBezier( 0.23, 1, 0.32, 1 ),\n 'ease-in-out-quint': cubicBezier( 0.86, 0, 0.07, 1 ),\n\n // expo\n 'ease-in-expo': cubicBezier( 0.95, 0.05, 0.795, 0.035 ),\n 'ease-out-expo': cubicBezier( 0.19, 1, 0.22, 1 ),\n 'ease-in-out-expo': cubicBezier( 1, 0, 0, 1 ),\n\n // circ\n 'ease-in-circ': cubicBezier( 0.6, 0.04, 0.98, 0.335 ),\n 'ease-out-circ': cubicBezier( 0.075, 0.82, 0.165, 1 ),\n 'ease-in-out-circ': cubicBezier( 0.785, 0.135, 0.15, 0.86 ),\n\n\n // user param easings...\n\n 'spring': function( tension, friction, duration ){\n var spring = generateSpringRK4( tension, friction, duration );\n\n return function( start, end, percent ){\n return start + (end - start) * spring( percent );\n };\n },\n\n 'cubic-bezier': function( x1, y1, x2, y2 ){\n return cubicBezier( x1, y1, x2, y2 );\n }\n };\n\n function ease( startProp, endProp, percent, easingFn ){\n if( percent < 0 ){\n percent = 0;\n } else if( percent > 1 ){\n percent = 1;\n }\n\n var start, end;\n\n if( startProp.pfValue != null || startProp.value != null ){\n start = startProp.pfValue != null ? startProp.pfValue : startProp.value;\n } else {\n start = startProp;\n }\n\n if( endProp.pfValue != null || endProp.value != null ){\n end = endProp.pfValue != null ? endProp.pfValue : endProp.value;\n } else {\n end = endProp;\n }\n\n if( is.number(start) && is.number(end) ){\n return easingFn( start, end, percent );\n\n } else if( is.array(start) && is.array(end) ){\n var easedArr = [];\n\n for( var i = 0; i < end.length; i++ ){\n var si = start[i];\n var ei = end[i];\n\n if( si != null && ei != null ){\n var val = easingFn(si, ei, percent);\n\n if( startProp.roundValue ){ val = Math.round( val ); }\n\n easedArr.push( val );\n } else {\n easedArr.push( ei );\n }\n }\n\n return easedArr;\n }\n\n return undefined;\n }\n\n }\n\n});\n\nmodule.exports = corefn;\n","'use strict';\n\nvar define = require('../define');\n\nvar corefn = ({\n on: define.on(), // .on( events [, selector] [, data], handler)\n one: define.on({ unbindSelfOnTrigger: true }),\n once: define.on({ unbindAllBindersOnTrigger: true }),\n off: define.off(), // .off( events [, selector] [, handler] )\n trigger: define.trigger() // .trigger( events [, extraParams] )\n});\n\ndefine.eventAliasesOn( corefn );\n\nmodule.exports = corefn;\n","'use strict';\n\nvar corefn = ({\n\n png: function( options ){\n var renderer = this._private.renderer;\n options = options || {};\n\n return renderer.png( options );\n },\n\n jpg: function( options ){\n var renderer = this._private.renderer;\n options = options || {};\n\n options.bg = options.bg || '#fff';\n\n return renderer.jpg( options );\n }\n\n});\n\ncorefn.jpeg = corefn.jpg;\n\nmodule.exports = corefn;\n","'use strict';\n\nvar window = require('../window');\nvar util = require('../util');\nvar Collection = require('../collection');\nvar is = require('../is');\nvar Promise = require('../promise');\nvar define = require('../define');\n\nvar Core = function( opts ){\n if( !(this instanceof Core) ){\n return new Core(opts);\n }\n var cy = this;\n\n opts = util.extend({}, opts);\n\n var container = opts.container;\n\n // allow for passing a wrapped jquery object\n // e.g. cytoscape({ container: $('#cy') })\n if( container && !is.htmlElement( container ) && is.htmlElement( container[0] ) ){\n container = container[0];\n }\n\n var reg = container ? container._cyreg : null; // e.g. already registered some info (e.g. readies) via jquery\n reg = reg || {};\n\n if( reg && reg.cy ){\n reg.cy.destroy();\n\n reg = {}; // old instance => replace reg completely\n }\n\n var readies = reg.readies = reg.readies || [];\n\n if( container ){ container._cyreg = reg; } // make sure container assoc'd reg points to this cy\n reg.cy = cy;\n\n var head = window !== undefined && container !== undefined && !opts.headless;\n var options = opts;\n options.layout = util.extend( { name: head ? 'grid' : 'null' }, options.layout );\n options.renderer = util.extend( { name: head ? 'canvas' : 'null' }, options.renderer );\n\n var defVal = function( def, val, altVal ){\n if( val !== undefined ){\n return val;\n } else if( altVal !== undefined ){\n return altVal;\n } else {\n return def;\n }\n };\n\n var _p = this._private = {\n container: container, // html dom ele container\n ready: false, // whether ready has been triggered\n initrender: false, // has initrender has been triggered\n options: options, // cached options\n elements: [], // array of elements\n id2index: {}, // element id => index in elements array\n listeners: [], // list of listeners\n onRenders: [], // rendering listeners\n aniEles: Collection(this), // elements being animated\n scratch: {}, // scratch object for core\n layout: null,\n renderer: null,\n notificationsEnabled: true, // whether notifications are sent to the renderer\n minZoom: 1e-50,\n maxZoom: 1e50,\n zoomingEnabled: defVal(true, options.zoomingEnabled),\n userZoomingEnabled: defVal(true, options.userZoomingEnabled),\n panningEnabled: defVal(true, options.panningEnabled),\n userPanningEnabled: defVal(true, options.userPanningEnabled),\n boxSelectionEnabled: defVal(true, options.boxSelectionEnabled),\n autolock: defVal(false, options.autolock, options.autolockNodes),\n autoungrabify: defVal(false, options.autoungrabify, options.autoungrabifyNodes),\n autounselectify: defVal(false, options.autounselectify),\n styleEnabled: options.styleEnabled === undefined ? head : options.styleEnabled,\n zoom: is.number(options.zoom) ? options.zoom : 1,\n pan: {\n x: is.plainObject(options.pan) && is.number(options.pan.x) ? options.pan.x : 0,\n y: is.plainObject(options.pan) && is.number(options.pan.y) ? options.pan.y : 0\n },\n animation: { // object for currently-running animations\n current: [],\n queue: []\n },\n hasCompoundNodes: false,\n deferredExecQueue: []\n };\n\n // set selection type\n var selType = options.selectionType;\n if( selType === undefined || (selType !== 'additive' && selType !== 'single') ){\n // then set default\n\n _p.selectionType = 'single';\n } else {\n _p.selectionType = selType;\n }\n\n // init zoom bounds\n if( is.number(options.minZoom) && is.number(options.maxZoom) && options.minZoom < options.maxZoom ){\n _p.minZoom = options.minZoom;\n _p.maxZoom = options.maxZoom;\n } else if( is.number(options.minZoom) && options.maxZoom === undefined ){\n _p.minZoom = options.minZoom;\n } else if( is.number(options.maxZoom) && options.minZoom === undefined ){\n _p.maxZoom = options.maxZoom;\n }\n\n var loadExtData = function( next ){\n var anyIsPromise = false;\n\n for( var i = 0; i < extData.length; i++ ){\n var datum = extData[i];\n\n if( is.promise(datum) ){\n anyIsPromise = true;\n break;\n }\n }\n\n if( anyIsPromise ){\n return Promise.all( extData ).then( next ); // load all data asynchronously, then exec rest of init\n } else {\n next( extData ); // exec synchronously for convenience\n }\n };\n\n // create the renderer\n cy.initRenderer( util.extend({\n hideEdgesOnViewport: options.hideEdgesOnViewport,\n hideLabelsOnViewport: options.hideLabelsOnViewport,\n textureOnViewport: options.textureOnViewport,\n wheelSensitivity: is.number(options.wheelSensitivity) && options.wheelSensitivity > 0 ? options.wheelSensitivity : 1,\n motionBlur: options.motionBlur === undefined ? true : options.motionBlur, // on by default\n motionBlurOpacity: options.motionBlurOpacity === undefined ? 0.05 : options.motionBlurOpacity,\n pixelRatio: is.number(options.pixelRatio) && options.pixelRatio > 0 ? options.pixelRatio : undefined,\n desktopTapThreshold: options.desktopTapThreshold === undefined ? 4 : options.desktopTapThreshold,\n touchTapThreshold: options.touchTapThreshold === undefined ? 8 : options.touchTapThreshold\n }, options.renderer) );\n\n var extData = [ options.style, options.elements ];\n loadExtData(function( thens ){\n var initStyle = thens[0];\n var initEles = thens[1];\n\n // init style\n if( _p.styleEnabled ){\n cy.setStyle( initStyle );\n }\n\n // trigger the passed function for the `initrender` event\n if( options.initrender ){\n cy.on('initrender', options.initrender);\n cy.on('initrender', function(){\n _p.initrender = true;\n });\n }\n\n // initial load\n cy.load(initEles, function(){ // onready\n cy.startAnimationLoop();\n _p.ready = true;\n\n // if a ready callback is specified as an option, the bind it\n if( is.fn( options.ready ) ){\n cy.on('ready', options.ready);\n }\n\n // bind all the ready handlers registered before creating this instance\n for( var i = 0; i < readies.length; i++ ){\n var fn = readies[i];\n cy.on('ready', fn);\n }\n if( reg ){ reg.readies = []; } // clear b/c we've bound them all and don't want to keep it around in case a new core uses the same div etc\n\n cy.trigger('ready');\n }, options.done);\n\n });\n};\n\nvar corefn = Core.prototype; // short alias\n\nutil.extend(corefn, {\n instanceString: function(){\n return 'core';\n },\n\n isReady: function(){\n return this._private.ready;\n },\n\n ready: function( fn ){\n if( this.isReady() ){\n this.trigger('ready', [], fn); // just calls fn as though triggered via ready event\n } else {\n this.on('ready', fn);\n }\n\n return this;\n },\n\n initrender: function(){\n return this._private.initrender;\n },\n\n destroy: function(){\n var cy = this;\n\n cy.stopAnimationLoop();\n\n cy.notify({ type: 'destroy' }); // destroy the renderer\n\n var domEle = cy.container();\n if( domEle ){\n domEle._cyreg = null;\n\n while( domEle.childNodes.length > 0 ){\n domEle.removeChild( domEle.childNodes[0] );\n }\n }\n\n return cy;\n },\n\n getElementById: function( id ){\n var index = this._private.id2index[ id ];\n if( index !== undefined ){\n return this._private.elements[ index ];\n }\n\n // worst case, return an empty collection\n return Collection( this );\n },\n\n selectionType: function(){\n return this._private.selectionType;\n },\n\n hasCompoundNodes: function(){\n return this._private.hasCompoundNodes;\n },\n\n styleEnabled: function(){\n return this._private.styleEnabled;\n },\n\n addToPool: function( eles ){\n var elements = this._private.elements;\n var id2index = this._private.id2index;\n\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n\n var id = ele._private.data.id;\n var index = id2index[ id ];\n var alreadyInPool = index !== undefined;\n\n if( !alreadyInPool ){\n index = elements.length;\n elements.push( ele );\n id2index[ id ] = index;\n ele._private.index = index;\n }\n }\n\n return this; // chaining\n },\n\n removeFromPool: function( eles ){\n var elements = this._private.elements;\n var id2index = this._private.id2index;\n\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n\n var id = ele._private.data.id;\n var index = id2index[ id ];\n var inPool = index !== undefined;\n\n if( inPool ){\n this._private.id2index[ id ] = undefined;\n elements.splice(index, 1);\n\n // adjust the index of all elements past this index\n for( var j = index; j < elements.length; j++ ){\n var jid = elements[j]._private.data.id;\n id2index[ jid ]--;\n elements[j]._private.index--;\n }\n }\n }\n },\n\n container: function(){\n return this._private.container;\n },\n\n options: function(){\n return util.copy( this._private.options );\n },\n\n json: function( obj ){\n var cy = this;\n var _p = cy._private;\n\n if( is.plainObject(obj) ){ // set\n\n cy.startBatch();\n\n if( obj.elements ){\n var idInJson = {};\n\n var updateEles = function( jsons, gr ){\n for( var i = 0; i < jsons.length; i++ ){\n var json = jsons[i];\n var id = json.data.id;\n var ele = cy.getElementById( id );\n\n idInJson[ id ] = true;\n\n if( ele.length !== 0 ){ // existing element should be updated\n ele.json( json );\n } else { // otherwise should be added\n if( gr ){\n cy.add( util.extend({ group: gr }, json) );\n } else {\n cy.add( json );\n }\n }\n }\n };\n\n if( is.array(obj.elements) ){ // elements: []\n updateEles( obj.elements );\n\n } else { // elements: { nodes: [], edges: [] }\n var grs = ['nodes', 'edges'];\n for( var i = 0; i < grs.length; i++ ){\n var gr = grs[i];\n var elements = obj.elements[ gr ];\n\n if( is.array(elements) ){\n updateEles( elements, gr );\n }\n }\n }\n\n // elements not specified in json should be removed\n cy.elements().stdFilter(function( ele ){\n return !idInJson[ ele.id() ];\n }).remove();\n }\n\n if( obj.style ){\n cy.style( obj.style );\n }\n\n if( obj.zoom != null && obj.zoom !== _p.zoom ){\n cy.zoom( obj.zoom );\n }\n\n if( obj.pan ){\n if( obj.pan.x !== _p.pan.x || obj.pan.y !== _p.pan.y ){\n cy.pan( obj.pan );\n }\n }\n\n var fields = [\n 'minZoom', 'maxZoom', 'zoomingEnabled', 'userZoomingEnabled',\n 'panningEnabled', 'userPanningEnabled',\n 'boxSelectionEnabled',\n 'autolock', 'autoungrabify', 'autounselectify'\n ];\n\n for( var i = 0; i < fields.length; i++ ){\n var f = fields[i];\n\n if( obj[f] != null ){\n cy[f]( obj[f] );\n }\n }\n\n cy.endBatch();\n\n return this; // chaining\n } else if( obj === undefined ){ // get\n var json = {};\n\n json.elements = {};\n cy.elements().each(function(i, ele){\n var group = ele.group();\n\n if( !json.elements[group] ){\n json.elements[group] = [];\n }\n\n json.elements[group].push( ele.json() );\n });\n\n if( this._private.styleEnabled ){\n json.style = cy.style().json();\n }\n\n json.zoomingEnabled = cy._private.zoomingEnabled;\n json.userZoomingEnabled = cy._private.userZoomingEnabled;\n json.zoom = cy._private.zoom;\n json.minZoom = cy._private.minZoom;\n json.maxZoom = cy._private.maxZoom;\n json.panningEnabled = cy._private.panningEnabled;\n json.userPanningEnabled = cy._private.userPanningEnabled;\n json.pan = util.copy( cy._private.pan );\n json.boxSelectionEnabled = cy._private.boxSelectionEnabled;\n json.renderer = util.copy( cy._private.options.renderer );\n json.hideEdgesOnViewport = cy._private.options.hideEdgesOnViewport;\n json.hideLabelsOnViewport = cy._private.options.hideLabelsOnViewport;\n json.textureOnViewport = cy._private.options.textureOnViewport;\n json.wheelSensitivity = cy._private.options.wheelSensitivity;\n json.motionBlur = cy._private.options.motionBlur;\n\n return json;\n }\n },\n\n scratch: define.data({\n field: 'scratch',\n bindingEvent: 'scratch',\n allowBinding: true,\n allowSetting: true,\n settingEvent: 'scratch',\n settingTriggersEvent: true,\n triggerFnName: 'trigger',\n allowGetting: true\n }),\n\n removeScratch: define.removeData({\n field: 'scratch',\n event: 'scratch',\n triggerFnName: 'trigger',\n triggerEvent: true\n })\n\n});\n\n[\n require('./add-remove'),\n require('./animation'),\n require('./events'),\n require('./export'),\n require('./layout'),\n require('./notification'),\n require('./renderer'),\n require('./search'),\n require('./style'),\n require('./viewport')\n].forEach(function( props ){\n util.extend( corefn, props );\n});\n\nmodule.exports = Core;\n","'use strict';\n\nvar util = require('../util');\nvar is = require('../is');\n\nvar corefn = ({\n\n layout: function( params ){\n var layout = this._private.prevLayout = ( params == null ? this._private.prevLayout : this.makeLayout( params ) );\n\n layout.run();\n\n return this; // chaining\n },\n\n makeLayout: function( options ){\n var cy = this;\n\n if( options == null ){\n util.error('Layout options must be specified to make a layout');\n return;\n }\n\n if( options.name == null ){\n util.error('A `name` must be specified to make a layout');\n return;\n }\n\n var name = options.name;\n var Layout = cy.extension('layout', name);\n\n if( Layout == null ){\n util.error('Can not apply layout: No such layout `' + name + '` found; did you include its JS file?');\n return;\n }\n\n var eles;\n if( is.string( options.eles ) ){\n eles = cy.$( options.eles );\n } else {\n eles = options.eles != null ? options.eles : cy.$();\n }\n\n var layout = new Layout( util.extend({}, options, {\n cy: cy,\n eles: eles\n }) );\n\n return layout;\n }\n\n});\n\ncorefn.createLayout = corefn.makeLayout;\n\nmodule.exports = corefn;\n","'use strict';\n\nvar corefn = ({\n notify: function( params ){\n var _p = this._private;\n\n if( _p.batchingNotify ){\n var bEles = _p.batchNotifyEles;\n var bTypes = _p.batchNotifyTypes;\n\n if( params.collection ){\n bEles.merge( params.collection );\n }\n\n if( !bTypes.ids[ params.type ] ){\n bTypes.push( params.type );\n }\n\n return; // notifications are disabled during batching\n }\n\n if( !_p.notificationsEnabled ){ return; } // exit on disabled\n\n var renderer = this.renderer();\n\n renderer.notify(params);\n },\n\n notifications: function( bool ){\n var p = this._private;\n\n if( bool === undefined ){\n return p.notificationsEnabled;\n } else {\n p.notificationsEnabled = bool ? true : false;\n }\n },\n\n noNotifications: function( callback ){\n this.notifications(false);\n callback();\n this.notifications(true);\n },\n\n startBatch: function(){\n var _p = this._private;\n\n if( _p.batchCount == null ){\n _p.batchCount = 0;\n }\n\n if( _p.batchCount === 0 ){\n _p.batchingStyle = _p.batchingNotify = true;\n _p.batchStyleEles = this.collection();\n _p.batchNotifyEles = this.collection();\n _p.batchNotifyTypes = [];\n\n _p.batchNotifyTypes.ids = {};\n }\n\n _p.batchCount++;\n\n return this;\n },\n\n endBatch: function(){\n var _p = this._private;\n\n _p.batchCount--;\n\n if( _p.batchCount === 0 ){\n // update style for dirty eles\n _p.batchingStyle = false;\n _p.batchStyleEles.updateStyle();\n\n // notify the renderer of queued eles and event types\n _p.batchingNotify = false;\n this.notify({\n type: _p.batchNotifyTypes,\n collection: _p.batchNotifyEles\n });\n }\n\n return this;\n },\n\n batch: function( callback ){\n this.startBatch();\n callback();\n this.endBatch();\n\n return this;\n },\n\n // for backwards compatibility\n batchData: function( map ){\n var cy = this;\n\n return this.batch(function(){\n for( var id in map ){\n var data = map[id];\n var ele = cy.getElementById( id );\n\n ele.data( data );\n }\n });\n }\n});\n\nmodule.exports = corefn;\n","'use strict';\n\nvar util = require('../util');\n\nvar corefn = ({\n\n renderTo: function( context, zoom, pan, pxRatio ){\n var r = this._private.renderer;\n\n r.renderTo( context, zoom, pan, pxRatio );\n return this;\n },\n\n renderer: function(){\n return this._private.renderer;\n },\n\n forceRender: function(){\n this.notify({\n type: 'draw'\n });\n\n return this;\n },\n\n resize: function(){\n this.notify({\n type: 'resize'\n });\n\n this.trigger('resize');\n\n return this;\n },\n\n initRenderer: function( options ){\n var cy = this;\n\n var RendererProto = cy.extension('renderer', options.name);\n if( RendererProto == null ){\n util.error('Can not initialise: No such renderer `%s` found; did you include its JS file?', options.name);\n return;\n }\n\n var rOpts = util.extend({}, options, {\n cy: cy\n });\n var renderer = cy._private.renderer = new RendererProto( rOpts );\n\n renderer.init( rOpts );\n\n },\n\n triggerOnRender: function(){\n var cbs = this._private.onRenders;\n\n for( var i = 0; i < cbs.length; i++ ){\n var cb = cbs[i];\n\n cb();\n }\n\n return this;\n },\n\n onRender: function( cb ){\n this._private.onRenders.push( cb );\n\n return this;\n },\n\n offRender: function( fn ){\n var cbs = this._private.onRenders;\n\n if( fn == null ){ // unbind all\n this._private.onRenders = [];\n return this;\n }\n\n for( var i = 0; i < cbs.length; i++ ){ // unbind specified\n var cb = cbs[i];\n\n if( fn === cb ){\n cbs.splice( i, 1 );\n break;\n }\n }\n\n return this;\n }\n\n});\n\ncorefn.invalidateDimensions = corefn.resize;\n\nmodule.exports = corefn;\n","'use strict';\n\nvar is = require('../is');\nvar Collection = require('../collection');\n\nvar corefn = ({\n\n // get a collection\n // - empty collection on no args\n // - collection of elements in the graph on selector arg\n // - guarantee a returned collection when elements or collection specified\n collection: function( eles, opts ){\n\n if( is.string( eles ) ){\n return this.$( eles );\n\n } else if( is.elementOrCollection( eles ) ){\n return eles.collection();\n\n } else if( is.array( eles ) ){\n return Collection( this, eles, opts );\n }\n\n return Collection( this );\n },\n\n nodes: function( selector ){\n var nodes = this.$(function(){\n return this.isNode();\n });\n\n if( selector ){\n return nodes.filter( selector );\n }\n\n return nodes;\n },\n\n edges: function( selector ){\n var edges = this.$(function(){\n return this.isEdge();\n });\n\n if( selector ){\n return edges.filter( selector );\n }\n\n return edges;\n },\n\n // search the graph like jQuery\n $: function( selector ){\n var eles = new Collection( this, this._private.elements );\n\n if( selector ){\n return eles.filter( selector );\n }\n\n return eles;\n }\n\n});\n\n// aliases\ncorefn.elements = corefn.filter = corefn.$;\n\nmodule.exports = corefn;\n","'use strict';\n\nvar is = require('../is');\nvar Style = require('../style');\n\nvar corefn = ({\n\n style: function( newStyle ){\n if( newStyle ){\n var s = this.setStyle( newStyle );\n\n s.update();\n }\n\n return this._private.style;\n },\n\n setStyle: function( style ){\n var _p = this._private;\n\n if( is.stylesheet(style) ){\n _p.style = style.generateStyle(this);\n\n } else if( is.array(style) ) {\n _p.style = Style.fromJson(this, style);\n\n } else if( is.string(style) ){\n _p.style = Style.fromString(this, style);\n\n } else {\n _p.style = Style( this );\n }\n\n return _p.style;\n }\n});\n\nmodule.exports = corefn;\n","'use strict';\n\nvar is = require('../is');\n\nvar corefn = ({\n\n autolock: function(bool){\n if( bool !== undefined ){\n this._private.autolock = bool ? true : false;\n } else {\n return this._private.autolock;\n }\n\n return this; // chaining\n },\n\n autoungrabify: function(bool){\n if( bool !== undefined ){\n this._private.autoungrabify = bool ? true : false;\n } else {\n return this._private.autoungrabify;\n }\n\n return this; // chaining\n },\n\n autounselectify: function(bool){\n if( bool !== undefined ){\n this._private.autounselectify = bool ? true : false;\n } else {\n return this._private.autounselectify;\n }\n\n return this; // chaining\n },\n\n panningEnabled: function( bool ){\n if( bool !== undefined ){\n this._private.panningEnabled = bool ? true : false;\n } else {\n return this._private.panningEnabled;\n }\n\n return this; // chaining\n },\n\n userPanningEnabled: function( bool ){\n if( bool !== undefined ){\n this._private.userPanningEnabled = bool ? true : false;\n } else {\n return this._private.userPanningEnabled;\n }\n\n return this; // chaining\n },\n\n zoomingEnabled: function( bool ){\n if( bool !== undefined ){\n this._private.zoomingEnabled = bool ? true : false;\n } else {\n return this._private.zoomingEnabled;\n }\n\n return this; // chaining\n },\n\n userZoomingEnabled: function( bool ){\n if( bool !== undefined ){\n this._private.userZoomingEnabled = bool ? true : false;\n } else {\n return this._private.userZoomingEnabled;\n }\n\n return this; // chaining\n },\n\n boxSelectionEnabled: function( bool ){\n if( bool !== undefined ){\n this._private.boxSelectionEnabled = bool ? true : false;\n } else {\n return this._private.boxSelectionEnabled;\n }\n\n return this; // chaining\n },\n\n pan: function(){\n var args = arguments;\n var pan = this._private.pan;\n var dim, val, dims, x, y;\n\n switch( args.length ){\n case 0: // .pan()\n return pan;\n\n case 1:\n\n if( is.string( args[0] ) ){ // .pan('x')\n dim = args[0];\n return pan[ dim ];\n\n } else if( is.plainObject( args[0] ) ) { // .pan({ x: 0, y: 100 })\n if( !this._private.panningEnabled ){\n return this;\n }\n\n dims = args[0];\n x = dims.x;\n y = dims.y;\n\n if( is.number(x) ){\n pan.x = x;\n }\n\n if( is.number(y) ){\n pan.y = y;\n }\n\n this.trigger('pan viewport');\n }\n break;\n\n case 2: // .pan('x', 100)\n if( !this._private.panningEnabled ){\n return this;\n }\n\n dim = args[0];\n val = args[1];\n\n if( (dim === 'x' || dim === 'y') && is.number(val) ){\n pan[dim] = val;\n }\n\n this.trigger('pan viewport');\n break;\n\n default:\n break; // invalid\n }\n\n this.notify({ // notify the renderer that the viewport changed\n type: 'viewport'\n });\n\n return this; // chaining\n },\n\n panBy: function(params){\n var args = arguments;\n var pan = this._private.pan;\n var dim, val, dims, x, y;\n\n if( !this._private.panningEnabled ){\n return this;\n }\n\n switch( args.length ){\n case 1:\n\n if( is.plainObject( args[0] ) ) { // .panBy({ x: 0, y: 100 })\n dims = args[0];\n x = dims.x;\n y = dims.y;\n\n if( is.number(x) ){\n pan.x += x;\n }\n\n if( is.number(y) ){\n pan.y += y;\n }\n\n this.trigger('pan viewport');\n }\n break;\n\n case 2: // .panBy('x', 100)\n dim = args[0];\n val = args[1];\n\n if( (dim === 'x' || dim === 'y') && is.number(val) ){\n pan[dim] += val;\n }\n\n this.trigger('pan viewport');\n break;\n\n default:\n break; // invalid\n }\n\n this.notify({ // notify the renderer that the viewport changed\n type: 'viewport'\n });\n\n return this; // chaining\n },\n\n fit: function( elements, padding ){\n var viewportState = this.getFitViewport( elements, padding );\n\n if( viewportState ){\n var _p = this._private;\n _p.zoom = viewportState.zoom;\n _p.pan = viewportState.pan;\n\n this.trigger('pan zoom viewport');\n\n this.notify({ // notify the renderer that the viewport changed\n type: 'viewport'\n });\n }\n\n return this; // chaining\n },\n\n getFitViewport: function( elements, padding ){\n if( is.number(elements) && padding === undefined ){ // elements is optional\n padding = elements;\n elements = undefined;\n }\n\n if( !this._private.panningEnabled || !this._private.zoomingEnabled ){\n return;\n }\n\n var bb;\n\n if( is.string(elements) ){\n var sel = elements;\n elements = this.$( sel );\n\n } else if( is.boundingBox(elements) ){ // assume bb\n var bbe = elements;\n bb = {\n x1: bbe.x1,\n y1: bbe.y1,\n x2: bbe.x2,\n y2: bbe.y2\n };\n\n bb.w = bb.x2 - bb.x1;\n bb.h = bb.y2 - bb.y1;\n\n } else if( !is.elementOrCollection(elements) ){\n elements = this.elements();\n }\n\n bb = bb || elements.boundingBox();\n\n var w = this.width();\n var h = this.height();\n var zoom;\n padding = is.number(padding) ? padding : 0;\n\n if( !isNaN(w) && !isNaN(h) && w > 0 && h > 0 && !isNaN(bb.w) && !isNaN(bb.h) && bb.w > 0 && bb.h > 0 ){\n zoom = Math.min( (w - 2*padding)/bb.w, (h - 2*padding)/bb.h );\n\n // crop zoom\n zoom = zoom > this._private.maxZoom ? this._private.maxZoom : zoom;\n zoom = zoom < this._private.minZoom ? this._private.minZoom : zoom;\n\n var pan = { // now pan to middle\n x: (w - zoom*( bb.x1 + bb.x2 ))/2,\n y: (h - zoom*( bb.y1 + bb.y2 ))/2\n };\n\n return {\n zoom: zoom,\n pan: pan\n };\n }\n\n return;\n },\n\n minZoom: function( zoom ){\n if( zoom === undefined ){\n return this._private.minZoom;\n } else if( is.number(zoom) ){\n this._private.minZoom = zoom;\n }\n\n return this;\n },\n\n maxZoom: function( zoom ){\n if( zoom === undefined ){\n return this._private.maxZoom;\n } else if( is.number(zoom) ){\n this._private.maxZoom = zoom;\n }\n\n return this;\n },\n\n zoom: function( params ){\n var pos; // in rendered px\n var zoom;\n\n if( params === undefined ){ // then get the zoom\n return this._private.zoom;\n\n } else if( is.number(params) ){ // then set the zoom\n zoom = params;\n\n } else if( is.plainObject(params) ){ // then zoom about a point\n zoom = params.level;\n\n if( params.position ){\n var p = params.position;\n var pan = this._private.pan;\n var z = this._private.zoom;\n\n pos = { // convert to rendered px\n x: p.x * z + pan.x,\n y: p.y * z + pan.y\n };\n } else if( params.renderedPosition ){\n pos = params.renderedPosition;\n }\n\n if( pos && !this._private.panningEnabled ){\n return this; // panning disabled\n }\n }\n\n if( !this._private.zoomingEnabled ){\n return this; // zooming disabled\n }\n\n if( !is.number(zoom) || ( pos && (!is.number(pos.x) || !is.number(pos.y)) ) ){\n return this; // can't zoom with invalid params\n }\n\n // crop zoom\n zoom = zoom > this._private.maxZoom ? this._private.maxZoom : zoom;\n zoom = zoom < this._private.minZoom ? this._private.minZoom : zoom;\n\n if( pos ){ // set zoom about position\n var pan1 = this._private.pan;\n var zoom1 = this._private.zoom;\n var zoom2 = zoom;\n\n var pan2 = {\n x: -zoom2/zoom1 * (pos.x - pan1.x) + pos.x,\n y: -zoom2/zoom1 * (pos.y - pan1.y) + pos.y\n };\n\n this._private.zoom = zoom;\n this._private.pan = pan2;\n\n var posChanged = pan1.x !== pan2.x || pan1.y !== pan2.y;\n this.trigger(' zoom ' + (posChanged ? ' pan ' : '') + ' viewport ' );\n\n } else { // just set the zoom\n this._private.zoom = zoom;\n this.trigger('zoom viewport');\n }\n\n this.notify({ // notify the renderer that the viewport changed\n type: 'viewport'\n });\n\n return this; // chaining\n },\n\n viewport: function( opts ){\n var _p = this._private;\n var zoomDefd = true;\n var panDefd = true;\n var events = []; // to trigger\n var zoomFailed = false;\n var panFailed = false;\n\n if( !opts ){ return this; }\n if( !is.number(opts.zoom) ){ zoomDefd = false; }\n if( !is.plainObject(opts.pan) ){ panDefd = false; }\n if( !zoomDefd && !panDefd ){ return this; }\n\n if( zoomDefd ){\n var z = opts.zoom;\n\n if( z < _p.minZoom || z > _p.maxZoom || !_p.zoomingEnabled ){\n zoomFailed = true;\n\n } else {\n _p.zoom = z;\n\n events.push('zoom');\n }\n }\n\n if( panDefd && (!zoomFailed || !opts.cancelOnFailedZoom) && _p.panningEnabled ){\n var p = opts.pan;\n\n if( is.number(p.x) ){\n _p.pan.x = p.x;\n panFailed = false;\n }\n\n if( is.number(p.y) ){\n _p.pan.y = p.y;\n panFailed = false;\n }\n\n if( !panFailed ){\n events.push('pan');\n }\n }\n\n if( events.length > 0 ){\n events.push('viewport');\n this.trigger( events.join(' ') );\n\n this.notify({\n type: 'viewport'\n });\n }\n\n return this; // chaining\n },\n\n center: function( elements ){\n var pan = this.getCenterPan( elements );\n\n if( pan ){\n this._private.pan = pan;\n\n this.trigger('pan viewport');\n\n this.notify({ // notify the renderer that the viewport changed\n type: 'viewport'\n });\n }\n\n return this; // chaining\n },\n\n getCenterPan: function( elements, zoom ){\n if( !this._private.panningEnabled ){\n return;\n }\n\n if( is.string(elements) ){\n var selector = elements;\n elements = this.elements( selector );\n } else if( !is.elementOrCollection(elements) ){\n elements = this.elements();\n }\n\n var bb = elements.boundingBox();\n var w = this.width();\n var h = this.height();\n zoom = zoom === undefined ? this._private.zoom : zoom;\n\n var pan = { // middle\n x: (w - zoom*( bb.x1 + bb.x2 ))/2,\n y: (h - zoom*( bb.y1 + bb.y2 ))/2\n };\n\n return pan;\n },\n\n reset: function(){\n if( !this._private.panningEnabled || !this._private.zoomingEnabled ){\n return this;\n }\n\n this.viewport({\n pan: { x: 0, y: 0 },\n zoom: 1\n });\n\n return this; // chaining\n },\n\n width: function(){\n var container = this._private.container;\n\n if( container ){\n return container.clientWidth;\n }\n\n return 1; // fallback if no container (not 0 b/c can be used for dividing etc)\n },\n\n height: function(){\n var container = this._private.container;\n\n if( container ){\n return container.clientHeight;\n }\n\n return 1; // fallback if no container (not 0 b/c can be used for dividing etc)\n },\n\n extent: function(){\n var pan = this._private.pan;\n var zoom = this._private.zoom;\n var rb = this.renderedExtent();\n\n var b = {\n x1: ( rb.x1 - pan.x )/zoom,\n x2: ( rb.x2 - pan.x )/zoom,\n y1: ( rb.y1 - pan.y )/zoom,\n y2: ( rb.y2 - pan.y )/zoom\n };\n\n b.w = b.x2 - b.x1;\n b.h = b.y2 - b.y1;\n\n return b;\n },\n\n renderedExtent: function(){\n var width = this.width();\n var height = this.height();\n\n return {\n x1: 0,\n y1: 0,\n x2: width,\n y2: height,\n w: width,\n h: height\n };\n }\n});\n\n// aliases\ncorefn.centre = corefn.center;\n\n// backwards compatibility\ncorefn.autolockNodes = corefn.autolock;\ncorefn.autoungrabifyNodes = corefn.autoungrabify;\n\nmodule.exports = corefn;\n","'use strict';\n\n// use this module to cherry pick functions into your prototype\n// (useful for functions shared between the core and collections, for example)\n\n// e.g.\n// var foo = define.foo({ /* params... */ })\n\nvar util = require('./util');\nvar is = require('./is');\nvar Selector = require('./selector');\nvar Promise = require('./promise');\nvar Event = require('./event');\nvar Animation = require('./animation');\n\nvar define = {\n\n // access data field\n data: function( params ){\n var defaults = {\n field: 'data',\n bindingEvent: 'data',\n allowBinding: false,\n allowSetting: false,\n allowGetting: false,\n settingEvent: 'data',\n settingTriggersEvent: false,\n triggerFnName: 'trigger',\n immutableKeys: {}, // key => true if immutable\n updateStyle: false,\n onSet: function( self ){},\n canSet: function( self ){ return true; }\n };\n params = util.extend({}, defaults, params);\n\n return function dataImpl( name, value ){\n var p = params;\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n var single = selfIsArrayLike ? self[0] : self;\n\n // .data('foo', ...)\n if( is.string(name) ){ // set or get property\n\n // .data('foo')\n if( p.allowGetting && value === undefined ){ // get\n\n var ret;\n if( single ){\n ret = single._private[ p.field ][ name ];\n }\n return ret;\n\n // .data('foo', 'bar')\n } else if( p.allowSetting && value !== undefined ) { // set\n var valid = !p.immutableKeys[name];\n if( valid ){\n for( var i = 0, l = all.length; i < l; i++ ){\n if( p.canSet( all[i] ) ){\n all[i]._private[ p.field ][ name ] = value;\n }\n }\n\n // update mappers if asked\n if( p.updateStyle ){ self.updateStyle(); }\n\n // call onSet callback\n p.onSet( self );\n\n if( p.settingTriggersEvent ){\n self[ p.triggerFnName ]( p.settingEvent );\n }\n }\n }\n\n // .data({ 'foo': 'bar' })\n } else if( p.allowSetting && is.plainObject(name) ){ // extend\n var obj = name;\n var k, v;\n\n for( k in obj ){\n v = obj[ k ];\n\n var valid = !p.immutableKeys[k];\n if( valid ){\n for( var i = 0, l = all.length; i < l; i++ ){\n if( p.canSet( all[i] ) ){\n all[i]._private[ p.field ][ k ] = v;\n }\n }\n }\n }\n\n // update mappers if asked\n if( p.updateStyle ){ self.updateStyle(); }\n\n // call onSet callback\n p.onSet( self );\n\n if( p.settingTriggersEvent ){\n self[ p.triggerFnName ]( p.settingEvent );\n }\n\n // .data(function(){ ... })\n } else if( p.allowBinding && is.fn(name) ){ // bind to event\n var fn = name;\n self.bind( p.bindingEvent, fn );\n\n // .data()\n } else if( p.allowGetting && name === undefined ){ // get whole object\n var ret;\n if( single ){\n ret = single._private[ p.field ];\n }\n return ret;\n }\n\n return self; // maintain chainability\n }; // function\n }, // data\n\n // remove data field\n removeData: function( params ){\n var defaults = {\n field: 'data',\n event: 'data',\n triggerFnName: 'trigger',\n triggerEvent: false,\n immutableKeys: {} // key => true if immutable\n };\n params = util.extend({}, defaults, params);\n\n return function removeDataImpl( names ){\n var p = params;\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n\n // .removeData('foo bar')\n if( is.string(names) ){ // then get the list of keys, and delete them\n var keys = names.split(/\\s+/);\n var l = keys.length;\n\n for( var i = 0; i < l; i++ ){ // delete each non-empty key\n var key = keys[i];\n if( is.emptyString(key) ){ continue; }\n\n var valid = !p.immutableKeys[ key ]; // not valid if immutable\n if( valid ){\n for( var i_a = 0, l_a = all.length; i_a < l_a; i_a++ ){\n all[ i_a ]._private[ p.field ][ key ] = undefined;\n }\n }\n }\n\n if( p.triggerEvent ){\n self[ p.triggerFnName ]( p.event );\n }\n\n // .removeData()\n } else if( names === undefined ){ // then delete all keys\n\n for( var i_a = 0, l_a = all.length; i_a < l_a; i_a++ ){\n var _privateFields = all[ i_a ]._private[ p.field ];\n\n for( var key in _privateFields ){\n var validKeyToDelete = !p.immutableKeys[ key ];\n\n if( validKeyToDelete ){\n _privateFields[ key ] = undefined;\n }\n }\n }\n\n if( p.triggerEvent ){\n self[ p.triggerFnName ]( p.event );\n }\n }\n\n return self; // maintain chaining\n }; // function\n }, // removeData\n\n // event function reusable stuff\n event: {\n regex: /(\\w+)(\\.\\w+)?/, // regex for matching event strings (e.g. \"click.namespace\")\n optionalTypeRegex: /(\\w+)?(\\.\\w+)?/,\n falseCallback: function(){ return false; }\n },\n\n // event binding\n on: function( params ){\n var defaults = {\n unbindSelfOnTrigger: false,\n unbindAllBindersOnTrigger: false\n };\n params = util.extend({}, defaults, params);\n\n return function onImpl(events, selector, data, callback){\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n var eventsIsString = is.string(events);\n var p = params;\n\n if( is.plainObject(selector) ){ // selector is actually data\n callback = data;\n data = selector;\n selector = undefined;\n } else if( is.fn(selector) || selector === false ){ // selector is actually callback\n callback = selector;\n data = undefined;\n selector = undefined;\n }\n\n if( is.fn(data) || data === false ){ // data is actually callback\n callback = data;\n data = undefined;\n }\n\n // if there isn't a callback, we can't really do anything\n // (can't speak for mapped events arg version)\n if( !(is.fn(callback) || callback === false) && eventsIsString ){\n return self; // maintain chaining\n }\n\n if( eventsIsString ){ // then convert to map\n var map = {};\n map[ events ] = callback;\n events = map;\n }\n\n for( var evts in events ){\n callback = events[evts];\n if( callback === false ){\n callback = define.event.falseCallback;\n }\n\n if( !is.fn(callback) ){ continue; }\n\n evts = evts.split(/\\s+/);\n for( var i = 0; i < evts.length; i++ ){\n var evt = evts[i];\n if( is.emptyString(evt) ){ continue; }\n\n var match = evt.match( define.event.regex ); // type[.namespace]\n\n if( match ){\n var type = match[1];\n var namespace = match[2] ? match[2] : undefined;\n\n var listener = {\n callback: callback, // callback to run\n data: data, // extra data in eventObj.data\n delegated: selector ? true : false, // whether the evt is delegated\n selector: selector, // the selector to match for delegated events\n selObj: new Selector(selector), // cached selector object to save rebuilding\n type: type, // the event type (e.g. 'click')\n namespace: namespace, // the event namespace (e.g. \".foo\")\n unbindSelfOnTrigger: p.unbindSelfOnTrigger,\n unbindAllBindersOnTrigger: p.unbindAllBindersOnTrigger,\n binders: all // who bound together\n };\n\n for( var j = 0; j < all.length; j++ ){\n var _p = all[j]._private;\n\n _p.listeners = _p.listeners || [];\n _p.listeners.push( listener );\n }\n }\n } // for events array\n } // for events map\n\n return self; // maintain chaining\n }; // function\n }, // on\n\n eventAliasesOn: function( proto ){\n var p = proto;\n\n p.addListener = p.listen = p.bind = p.on;\n p.removeListener = p.unlisten = p.unbind = p.off;\n p.emit = p.trigger;\n\n // this is just a wrapper alias of .on()\n p.pon = p.promiseOn = function( events, selector ){\n var self = this;\n var args = Array.prototype.slice.call( arguments, 0 );\n\n return new Promise(function( resolve, reject ){\n var callback = function( e ){\n self.off.apply( self, offArgs );\n\n resolve( e );\n };\n\n var onArgs = args.concat([ callback ]);\n var offArgs = onArgs.concat([]);\n\n self.on.apply( self, onArgs );\n });\n };\n },\n\n off: function offImpl( params ){\n var defaults = {\n };\n params = util.extend({}, defaults, params);\n\n return function(events, selector, callback){\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n var eventsIsString = is.string(events);\n\n if( arguments.length === 0 ){ // then unbind all\n\n for( var i = 0; i < all.length; i++ ){\n all[i]._private.listeners = [];\n }\n\n return self; // maintain chaining\n }\n\n if( is.fn(selector) || selector === false ){ // selector is actually callback\n callback = selector;\n selector = undefined;\n }\n\n if( eventsIsString ){ // then convert to map\n var map = {};\n map[ events ] = callback;\n events = map;\n }\n\n for( var evts in events ){\n callback = events[evts];\n\n if( callback === false ){\n callback = define.event.falseCallback;\n }\n\n evts = evts.split(/\\s+/);\n for( var h = 0; h < evts.length; h++ ){\n var evt = evts[h];\n if( is.emptyString(evt) ){ continue; }\n\n var match = evt.match( define.event.optionalTypeRegex ); // [type][.namespace]\n if( match ){\n var type = match[1] ? match[1] : undefined;\n var namespace = match[2] ? match[2] : undefined;\n\n for( var i = 0; i < all.length; i++ ){ //\n var listeners = all[i]._private.listeners = all[i]._private.listeners || [];\n\n for( var j = 0; j < listeners.length; j++ ){\n var listener = listeners[j];\n var nsMatches = !namespace || namespace === listener.namespace;\n var typeMatches = !type || listener.type === type;\n var cbMatches = !callback || callback === listener.callback;\n var listenerMatches = nsMatches && typeMatches && cbMatches;\n\n // delete listener if it matches\n if( listenerMatches ){\n listeners.splice(j, 1);\n j--;\n }\n } // for listeners\n } // for all\n } // if match\n } // for events array\n\n } // for events map\n\n return self; // maintain chaining\n }; // function\n }, // off\n\n trigger: function( params ){\n var defaults = {};\n params = util.extend({}, defaults, params);\n\n return function triggerImpl(events, extraParams, fnToTrigger){\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n var eventsIsString = is.string(events);\n var eventsIsObject = is.plainObject(events);\n var eventsIsEvent = is.event(events);\n var cy = this._private.cy || ( is.core(this) ? this : null );\n var hasCompounds = cy ? cy.hasCompoundNodes() : false;\n\n if( eventsIsString ){ // then make a plain event object for each event name\n var evts = events.split(/\\s+/);\n events = [];\n\n for( var i = 0; i < evts.length; i++ ){\n var evt = evts[i];\n if( is.emptyString(evt) ){ continue; }\n\n var match = evt.match( define.event.regex ); // type[.namespace]\n var type = match[1];\n var namespace = match[2] ? match[2] : undefined;\n\n events.push( {\n type: type,\n namespace: namespace\n } );\n }\n } else if( eventsIsObject ){ // put in length 1 array\n var eventArgObj = events;\n\n events = [ eventArgObj ];\n }\n\n if( extraParams ){\n if( !is.array(extraParams) ){ // make sure extra params are in an array if specified\n extraParams = [ extraParams ];\n }\n } else { // otherwise, we've got nothing\n extraParams = [];\n }\n\n for( var i = 0; i < events.length; i++ ){ // trigger each event in order\n var evtObj = events[i];\n\n for( var j = 0; j < all.length; j++ ){ // for each\n var triggerer = all[j];\n var listeners = triggerer._private.listeners = triggerer._private.listeners || [];\n var triggererIsElement = is.element(triggerer);\n var bubbleUp = triggererIsElement || params.layout;\n\n // create the event for this element from the event object\n var evt;\n\n if( eventsIsEvent ){ // then just get the object\n evt = evtObj;\n\n evt.cyTarget = evt.cyTarget || triggerer;\n evt.cy = evt.cy || cy;\n\n } else { // then we have to make one\n evt = new Event( evtObj, {\n cyTarget: triggerer,\n cy: cy,\n namespace: evtObj.namespace\n } );\n }\n\n // if a layout was specified, then put it in the typed event\n if( evtObj.layout ){\n evt.layout = evtObj.layout;\n }\n\n // if triggered by layout, put in event\n if( params.layout ){\n evt.layout = triggerer;\n }\n\n // create a rendered position based on the passed position\n if( evt.cyPosition ){\n var pos = evt.cyPosition;\n var zoom = cy.zoom();\n var pan = cy.pan();\n\n evt.cyRenderedPosition = {\n x: pos.x * zoom + pan.x,\n y: pos.y * zoom + pan.y\n };\n }\n\n if( fnToTrigger ){ // then override the listeners list with just the one we specified\n listeners = [{\n namespace: evt.namespace,\n type: evt.type,\n callback: fnToTrigger\n }];\n }\n\n for( var k = 0; k < listeners.length; k++ ){ // check each listener\n var lis = listeners[k];\n var nsMatches = !lis.namespace || lis.namespace === evt.namespace;\n var typeMatches = lis.type === evt.type;\n var targetMatches = lis.delegated ? ( triggerer !== evt.cyTarget && is.element(evt.cyTarget) && lis.selObj.matches(evt.cyTarget) ) : (true); // we're not going to validate the hierarchy; that's too expensive\n var listenerMatches = nsMatches && typeMatches && targetMatches;\n\n if( listenerMatches ){ // then trigger it\n var args = [ evt ];\n args = args.concat( extraParams ); // add extra params to args list\n\n if( lis.data ){ // add on data plugged into binding\n evt.data = lis.data;\n } else { // or clear it in case the event obj is reused\n evt.data = undefined;\n }\n\n if( lis.unbindSelfOnTrigger || lis.unbindAllBindersOnTrigger ){ // then remove listener\n listeners.splice(k, 1);\n k--;\n }\n\n if( lis.unbindAllBindersOnTrigger ){ // then delete the listener for all binders\n var binders = lis.binders;\n for( var l = 0; l < binders.length; l++ ){\n var binder = binders[l];\n if( !binder || binder === triggerer ){ continue; } // already handled triggerer or we can't handle it\n\n var binderListeners = binder._private.listeners;\n for( var m = 0; m < binderListeners.length; m++ ){\n var binderListener = binderListeners[m];\n\n if( binderListener === lis ){ // delete listener from list\n binderListeners.splice(m, 1);\n m--;\n }\n }\n }\n }\n\n // run the callback\n var context = lis.delegated ? evt.cyTarget : triggerer;\n var ret = lis.callback.apply( context, args );\n\n if( ret === false || evt.isPropagationStopped() ){\n // then don't bubble\n bubbleUp = false;\n\n if( ret === false ){\n // returning false is a shorthand for stopping propagation and preventing the def. action\n evt.stopPropagation();\n evt.preventDefault();\n }\n }\n } // if listener matches\n } // for each listener\n\n // bubble up event for elements\n if( bubbleUp ){\n var parent = hasCompounds ? triggerer._private.parent : null;\n var hasParent = parent != null && parent.length !== 0;\n\n if( hasParent ){ // then bubble up to parent\n parent = parent[0];\n parent.trigger(evt);\n } else { // otherwise, bubble up to the core\n cy.trigger(evt);\n }\n }\n\n } // for each of all\n } // for each event\n\n return self; // maintain chaining\n }; // function\n }, // trigger\n\n animated: function( fnParams ){\n var defaults = {};\n fnParams = util.extend({}, defaults, fnParams);\n\n return function animatedImpl(){\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n var cy = this._private.cy || this;\n\n if( !cy.styleEnabled() ){ return false; }\n\n var ele = all[0];\n\n if( ele ){\n return ele._private.animation.current.length > 0;\n }\n };\n }, // animated\n\n clearQueue: function( fnParams ){\n var defaults = {};\n fnParams = util.extend({}, defaults, fnParams);\n\n return function clearQueueImpl(){\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n var cy = this._private.cy || this;\n\n if( !cy.styleEnabled() ){ return this; }\n\n for( var i = 0; i < all.length; i++ ){\n var ele = all[i];\n ele._private.animation.queue = [];\n }\n\n return this;\n };\n }, // clearQueue\n\n delay: function( fnParams ){\n var defaults = {};\n fnParams = util.extend({}, defaults, fnParams);\n\n return function delayImpl( time, complete ){\n var cy = this._private.cy || this;\n\n if( !cy.styleEnabled() ){ return this; }\n\n return this.animate({\n delay: time,\n duration: time,\n complete: complete\n });\n };\n }, // delay\n\n delayAnimation: function( fnParams ){\n var defaults = {};\n fnParams = util.extend({}, defaults, fnParams);\n\n return function delayAnimationImpl( time, complete ){\n var cy = this._private.cy || this;\n\n if( !cy.styleEnabled() ){ return this; }\n\n return this.animation({\n delay: time,\n duration: time,\n complete: complete\n });\n };\n }, // delay\n\n animation: function( fnParams ){\n var defaults = {};\n fnParams = util.extend({}, defaults, fnParams);\n\n return function animationImpl( properties, params ){\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n var cy = this._private.cy || this;\n var isCore = !selfIsArrayLike;\n var isEles = !isCore;\n\n if( !cy.styleEnabled() ){ return this; }\n\n var style = cy.style();\n\n properties = util.extend( {}, properties, params );\n\n if( properties.duration === undefined ){\n properties.duration = 400;\n }\n\n switch( properties.duration ){\n case 'slow':\n properties.duration = 600;\n break;\n case 'fast':\n properties.duration = 200;\n break;\n }\n\n var propertiesEmpty = true;\n if( properties ){ for( var i in properties ){ // jshint ignore:line\n propertiesEmpty = false;\n break;\n } }\n\n if( propertiesEmpty ){\n return new Animation( all[0], properties ); // nothing to animate\n }\n\n if( isEles ){\n properties.style = style.getPropsList( properties.style || properties.css );\n\n properties.css = undefined;\n }\n\n if( properties.renderedPosition && isEles ){\n var rpos = properties.renderedPosition;\n var pan = cy.pan();\n var zoom = cy.zoom();\n\n properties.position = {\n x: ( rpos.x - pan.x ) /zoom,\n y: ( rpos.y - pan.y ) /zoom\n };\n }\n\n // override pan w/ panBy if set\n if( properties.panBy && isCore ){\n var panBy = properties.panBy;\n var cyPan = cy.pan();\n\n properties.pan = {\n x: cyPan.x + panBy.x,\n y: cyPan.y + panBy.y\n };\n }\n\n // override pan w/ center if set\n var center = properties.center || properties.centre;\n if( center && isCore ){\n var centerPan = cy.getCenterPan( center.eles, properties.zoom );\n\n if( centerPan ){\n properties.pan = centerPan;\n }\n }\n\n // override pan & zoom w/ fit if set\n if( properties.fit && isCore ){\n var fit = properties.fit;\n var fitVp = cy.getFitViewport( fit.eles || fit.boundingBox, fit.padding );\n\n if( fitVp ){\n properties.pan = fitVp.pan;\n properties.zoom = fitVp.zoom;\n }\n }\n\n return new Animation( all[0], properties );\n };\n }, // animate\n\n animate: function( fnParams ){\n var defaults = {};\n fnParams = util.extend({}, defaults, fnParams);\n\n return function animateImpl( properties, params ){\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n var cy = this._private.cy || this;\n\n if( !cy.styleEnabled() ){ return this; }\n\n if( params ){\n properties = util.extend( {}, properties, params );\n }\n\n // manually hook and run the animation\n for( var i = 0; i < all.length; i++ ){\n var ele = all[i];\n var queue = ele.animated() && (properties.queue === undefined || properties.queue);\n\n var ani = ele.animation( properties, (queue ? { queue: true } : undefined) );\n\n ani.play();\n }\n\n return this; // chaining\n };\n }, // animate\n\n stop: function( fnParams ){\n var defaults = {};\n fnParams = util.extend({}, defaults, fnParams);\n\n return function stopImpl( clearQueue, jumpToEnd ){\n var self = this;\n var selfIsArrayLike = self.length !== undefined;\n var all = selfIsArrayLike ? self : [self]; // put in array if not array-like\n var cy = this._private.cy || this;\n\n if( !cy.styleEnabled() ){ return this; }\n\n for( var i = 0; i < all.length; i++ ){\n var ele = all[i];\n var _p = ele._private;\n var anis = _p.animation.current;\n\n for( var j = 0; j < anis.length; j++ ){\n var ani = anis[j];\n var ani_p = ani._private;\n\n if( jumpToEnd ){\n // next iteration of the animation loop, the animation\n // will go straight to the end and be removed\n ani_p.duration = 0;\n }\n }\n\n // clear the queue of future animations\n if( clearQueue ){\n _p.animation.queue = [];\n }\n\n if( !jumpToEnd ){\n _p.animation.current = [];\n }\n }\n\n // we have to notify (the animation loop doesn't do it for us on `stop`)\n cy.notify({\n collection: this,\n type: 'draw'\n });\n\n return this;\n };\n } // stop\n\n}; // define\n\nmodule.exports = define;\n","'use strict';\n\n/*!\nEvent object based on jQuery events, MIT license\n\nhttps://jquery.org/license/\nhttps://tldrlegal.com/license/mit-license\nhttps://github.com/jquery/jquery/blob/master/src/event.js\n*/\n\nvar Event = function( src, props ) {\n // Allow instantiation without the 'new' keyword\n if ( !(this instanceof Event) ) {\n return new Event( src, props );\n }\n\n // Event object\n if ( src && src.type ) {\n this.originalEvent = src;\n this.type = src.type;\n\n // Events bubbling up the document may have been marked as prevented\n // by a handler lower down the tree; reflect the correct value.\n this.isDefaultPrevented = ( src.defaultPrevented ) ? returnTrue : returnFalse;\n\n // Event type\n } else {\n this.type = src;\n }\n\n // Put explicitly provided properties onto the event object\n if ( props ) {\n // util.extend( this, props );\n\n // more efficient to manually copy fields we use\n this.type = props.type !== undefined ? props.type : this.type;\n this.cy = props.cy;\n this.cyTarget = props.cyTarget;\n this.cyPosition = props.cyPosition;\n this.cyRenderedPosition = props.cyRenderedPosition;\n this.namespace = props.namespace;\n this.layout = props.layout;\n this.data = props.data;\n this.message = props.message;\n }\n\n // Create a timestamp if incoming event doesn't have one\n this.timeStamp = src && src.timeStamp || Date.now();\n};\n\nfunction returnFalse() {\n return false;\n}\n\nfunction returnTrue() {\n return true;\n}\n\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\nEvent.prototype = {\n instanceString: function(){\n return 'event';\n },\n\n preventDefault: function() {\n this.isDefaultPrevented = returnTrue;\n\n var e = this.originalEvent;\n if ( !e ) {\n return;\n }\n\n // if preventDefault exists run it on the original event\n if ( e.preventDefault ) {\n e.preventDefault();\n }\n },\n\n stopPropagation: function() {\n this.isPropagationStopped = returnTrue;\n\n var e = this.originalEvent;\n if ( !e ) {\n return;\n }\n\n // if stopPropagation exists run it on the original event\n if ( e.stopPropagation ) {\n e.stopPropagation();\n }\n },\n\n stopImmediatePropagation: function() {\n this.isImmediatePropagationStopped = returnTrue;\n this.stopPropagation();\n },\n\n isDefaultPrevented: returnFalse,\n isPropagationStopped: returnFalse,\n isImmediatePropagationStopped: returnFalse\n};\n\nmodule.exports = Event;\n","'use strict';\n\nvar util = require('./util');\nvar define = require('./define');\nvar Collection = require('./collection');\nvar Core = require('./core');\nvar incExts = require('./extensions');\nvar is = require('./is');\n\n// registered extensions to cytoscape, indexed by name\nvar extensions = {};\n\n// registered modules for extensions, indexed by name\nvar modules = {};\n\nfunction setExtension( type, name, registrant ){\n\n var ext = registrant;\n\n if( type === 'core' ){\n Core.prototype[ name ] = registrant;\n\n } else if( type === 'collection' ){\n Collection.prototype[ name ] = registrant;\n\n } else if( type === 'layout' ){\n // fill in missing layout functions in the prototype\n\n var Layout = function( options ){\n this.options = options;\n\n registrant.call( this, options );\n\n // make sure layout has _private for use w/ std apis like .on()\n if( !is.plainObject(this._private) ){\n this._private = {};\n }\n\n this._private.cy = options.cy;\n this._private.listeners = [];\n };\n\n var layoutProto = Layout.prototype = Object.create( registrant.prototype );\n\n var optLayoutFns = [];\n\n for( var i = 0; i < optLayoutFns.length; i++ ){\n var fnName = optLayoutFns[i];\n\n layoutProto[fnName] = layoutProto[fnName] || function(){ return this; };\n }\n\n // either .start() or .run() is defined, so autogen the other\n if( layoutProto.start && !layoutProto.run ){\n layoutProto.run = function(){ this.start(); return this; };\n } else if( !layoutProto.start && layoutProto.run ){\n layoutProto.start = function(){ this.run(); return this; };\n }\n\n if( !layoutProto.stop ){\n layoutProto.stop = function(){\n var opts = this.options;\n\n if( opts && opts.animate ){\n var anis = this.animations;\n for( var i = 0; i < anis.length; i++ ){\n anis[i].stop();\n }\n }\n\n this.trigger('layoutstop');\n\n return this;\n };\n }\n\n if( !layoutProto.destroy ){\n layoutProto.destroy = function(){\n return this;\n };\n }\n\n layoutProto.on = define.on({ layout: true });\n layoutProto.one = define.on({ layout: true, unbindSelfOnTrigger: true });\n layoutProto.once = define.on({ layout: true, unbindAllBindersOnTrigger: true });\n layoutProto.off = define.off({ layout: true });\n layoutProto.trigger = define.trigger({ layout: true });\n\n define.eventAliasesOn( layoutProto );\n\n ext = Layout; // replace with our wrapped layout\n\n } else if( type === 'renderer' && name !== 'null' && name !== 'base' ){\n // user registered renderers inherit from base\n\n var bProto = getExtension( 'renderer', 'base' ).prototype;\n var rProto = registrant.prototype;\n\n for( var pName in bProto ){\n var pVal = bProto[ pName ];\n var existsInR = rProto[ pName ] != null;\n\n if( existsInR ){\n util.error('Can not register renderer `' + name + '` since it overrides `' + pName + '` in its prototype');\n return;\n }\n\n rProto[ pName ] = pVal; // take impl from base\n }\n\n bProto.clientFunctions.forEach(function( name ){\n rProto[ name ] = rProto[ name ] || function(){\n util.error('Renderer does not implement `renderer.' + name + '()` on its prototype');\n };\n });\n\n }\n\n return util.setMap({\n map: extensions,\n keys: [ type, name ],\n value: ext\n });\n}\n\nfunction getExtension(type, name){\n return util.getMap({\n map: extensions,\n keys: [ type, name ]\n });\n}\n\nfunction setModule(type, name, moduleType, moduleName, registrant){\n return util.setMap({\n map: modules,\n keys: [ type, name, moduleType, moduleName ],\n value: registrant\n });\n}\n\nfunction getModule(type, name, moduleType, moduleName){\n return util.getMap({\n map: modules,\n keys: [ type, name, moduleType, moduleName ]\n });\n}\n\nvar extension = function(){\n // e.g. extension('renderer', 'svg')\n if( arguments.length === 2 ){\n return getExtension.apply(null, arguments);\n }\n\n // e.g. extension('renderer', 'svg', { ... })\n else if( arguments.length === 3 ){\n return setExtension.apply(null, arguments);\n }\n\n // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse')\n else if( arguments.length === 4 ){\n return getModule.apply(null, arguments);\n }\n\n // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse', { ... })\n else if( arguments.length === 5 ){\n return setModule.apply(null, arguments);\n }\n\n else {\n util.error('Invalid extension access syntax');\n }\n\n};\n\n// allows a core instance to access extensions internally\nCore.prototype.extension = extension;\n\n// included extensions\nincExts.forEach(function( group ){\n group.extensions.forEach(function( ext ){\n setExtension( group.type, ext.name, ext.impl );\n });\n});\n\nmodule.exports = extension;\n","'use strict';\n\nmodule.exports = [\n {\n type: 'layout',\n extensions: require('./layout')\n },\n\n {\n type: 'renderer',\n extensions: require('./renderer')\n }\n];\n","'use strict';\n\nvar util = require('../../util');\nvar math = require('../../math');\nvar is = require('../../is');\n\nvar defaults = {\n fit: true, // whether to fit the viewport to the graph\n directed: false, // whether the tree is directed downwards (or edges can point in any direction if false)\n padding: 30, // padding on fit\n circle: false, // put depths in concentric circles if true, put depths top down if false\n spacingFactor: 1.75, // positive spacing factor, larger => more space between nodes (N.B. n/a if causes overlap)\n boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space\n roots: undefined, // the roots of the trees\n maximalAdjustments: 0, // how many times to try to position the nodes in a maximal way (i.e. no backtracking)\n animate: false, // whether to transition the node positions\n animationDuration: 500, // duration of animation in ms if enabled\n animationEasing: undefined, // easing of animation if enabled\n ready: undefined, // callback on layoutready\n stop: undefined // callback on layoutstop\n};\n\nfunction BreadthFirstLayout( options ){\n this.options = util.extend({}, defaults, options);\n}\n\nBreadthFirstLayout.prototype.run = function(){\n var params = this.options;\n var options = params;\n\n var cy = params.cy;\n var eles = options.eles;\n var nodes = eles.nodes().not(':parent');\n var graph = eles;\n\n var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n x1: 0, y1: 0, w: cy.width(), h: cy.height()\n } );\n\n var roots;\n if( is.elementOrCollection(options.roots) ){\n roots = options.roots;\n } else if( is.array(options.roots) ){\n var rootsArray = [];\n\n for( var i = 0; i < options.roots.length; i++ ){\n var id = options.roots[i];\n var ele = cy.getElementById( id );\n rootsArray.push( ele );\n }\n\n roots = cy.collection( rootsArray );\n } else if( is.string(options.roots) ){\n roots = cy.$( options.roots );\n\n } else {\n if( options.directed ){\n roots = nodes.roots();\n } else {\n var components = [];\n var unhandledNodes = nodes;\n\n while( unhandledNodes.length > 0 ){\n var currComp = cy.collection();\n\n eles.bfs({\n roots: unhandledNodes[0],\n visit: function(i, depth, node, edge, pNode){\n currComp = currComp.add( node );\n },\n directed: false\n });\n\n unhandledNodes = unhandledNodes.not( currComp );\n components.push( currComp );\n }\n\n roots = cy.collection();\n for( var i = 0; i < components.length; i++ ){\n var comp = components[i];\n var maxDegree = comp.maxDegree( false );\n var compRoots = comp.filter(function(){\n return this.degree(false) === maxDegree;\n });\n\n roots = roots.add( compRoots );\n }\n\n }\n }\n\n\n var depths = [];\n var foundByBfs = {};\n var id2depth = {};\n var prevNode = {};\n var prevEdge = {};\n var successors = {};\n\n // find the depths of the nodes\n graph.bfs({\n roots: roots,\n directed: options.directed,\n visit: function(i, depth, node, edge, pNode){\n var ele = this[0];\n var id = ele.id();\n\n if( !depths[depth] ){\n depths[depth] = [];\n }\n\n depths[depth].push( ele );\n foundByBfs[ id ] = true;\n id2depth[ id ] = depth;\n prevNode[ id ] = pNode;\n prevEdge[ id ] = edge;\n\n if( pNode ){\n var prevId = pNode.id();\n var succ = successors[ prevId ] = successors[ prevId ] || [];\n\n succ.push( node );\n }\n }\n });\n\n // check for nodes not found by bfs\n var orphanNodes = [];\n for( var i = 0; i < nodes.length; i++ ){\n var ele = nodes[i];\n\n if( foundByBfs[ ele.id() ] ){\n continue;\n } else {\n orphanNodes.push( ele );\n }\n }\n\n // assign orphan nodes a depth from their neighborhood\n var maxChecks = orphanNodes.length * 3;\n var checks = 0;\n while( orphanNodes.length !== 0 && checks < maxChecks ){\n var node = orphanNodes.shift();\n var neighbors = node.neighborhood().nodes();\n var assignedDepth = false;\n\n for( var i = 0; i < neighbors.length; i++ ){\n var depth = id2depth[ neighbors[i].id() ];\n\n if( depth !== undefined ){\n depths[depth].push( node );\n assignedDepth = true;\n break;\n }\n }\n\n if( !assignedDepth ){\n orphanNodes.push( node );\n }\n\n checks++;\n }\n\n // assign orphan nodes that are still left to the depth of their subgraph\n while( orphanNodes.length !== 0 ){\n var node = orphanNodes.shift();\n //var subgraph = graph.bfs( node ).path;\n var assignedDepth = false;\n\n // for( var i = 0; i < subgraph.length; i++ ){\n // var depth = id2depth[ subgraph[i].id() ];\n\n // if( depth !== undefined ){\n // depths[depth].push( node );\n // assignedDepth = true;\n // break;\n // }\n // }\n\n if( !assignedDepth ){ // worst case if the graph really isn't tree friendly, then just dump it in 0\n if( depths.length === 0 ){\n depths.push([]);\n }\n\n depths[0].push( node );\n }\n }\n\n // assign the nodes a depth and index\n var assignDepthsToEles = function(){\n for( var i = 0; i < depths.length; i++ ){\n var eles = depths[i];\n\n for( var j = 0; j < eles.length; j++ ){\n var ele = eles[j];\n\n ele._private.scratch.breadthfirst = {\n depth: i,\n index: j\n };\n }\n }\n };\n assignDepthsToEles();\n\n\n var intersectsDepth = function( node ){ // returns true if has edges pointing in from a higher depth\n var edges = node.connectedEdges(function(){\n return this.data('target') === node.id();\n });\n var thisInfo = node._private.scratch.breadthfirst;\n var highestDepthOfOther = 0;\n var highestOther;\n for( var i = 0; i < edges.length; i++ ){\n var edge = edges[i];\n var otherNode = edge.source()[0];\n var otherInfo = otherNode._private.scratch.breadthfirst;\n\n if( thisInfo.depth <= otherInfo.depth && highestDepthOfOther < otherInfo.depth ){\n highestDepthOfOther = otherInfo.depth;\n highestOther = otherNode;\n }\n }\n\n return highestOther;\n };\n\n // make maximal if so set by adjusting depths\n for( var adj = 0; adj < options.maximalAdjustments; adj++ ){\n\n var nDepths = depths.length;\n var elesToMove = [];\n for( var i = 0; i < nDepths; i++ ){\n var depth = depths[i];\n\n var nDepth = depth.length;\n for( var j = 0; j < nDepth; j++ ){\n var ele = depth[j];\n var info = ele._private.scratch.breadthfirst;\n var intEle = intersectsDepth(ele);\n\n if( intEle ){\n info.intEle = intEle;\n elesToMove.push( ele );\n }\n }\n }\n\n for( var i = 0; i < elesToMove.length; i++ ){\n var ele = elesToMove[i];\n var info = ele._private.scratch.breadthfirst;\n var intEle = info.intEle;\n var intInfo = intEle._private.scratch.breadthfirst;\n\n depths[ info.depth ].splice( info.index, 1 ); // remove from old depth & index\n\n // add to end of new depth\n var newDepth = intInfo.depth + 1;\n while( newDepth > depths.length - 1 ){\n depths.push([]);\n }\n depths[ newDepth ].push( ele );\n\n info.depth = newDepth;\n info.index = depths[newDepth].length - 1;\n }\n\n assignDepthsToEles();\n }\n\n // find min distance we need to leave between nodes\n var minDistance = 0;\n if( options.avoidOverlap ){\n for( var i = 0; i < nodes.length; i++ ){\n var n = nodes[i];\n var nbb = n.boundingBox();\n var w = nbb.w;\n var h = nbb.h;\n\n minDistance = Math.max(minDistance, w, h);\n }\n minDistance *= options.spacingFactor; // just to have some nice spacing\n }\n\n // get the weighted percent for an element based on its connectivity to other levels\n var cachedWeightedPercent = {};\n var getWeightedPercent = function( ele ){\n if( cachedWeightedPercent[ ele.id() ] ){\n return cachedWeightedPercent[ ele.id() ];\n }\n\n var eleDepth = ele._private.scratch.breadthfirst.depth;\n var neighbors = ele.neighborhood().nodes().not(':parent');\n var percent = 0;\n var samples = 0;\n\n for( var i = 0; i < neighbors.length; i++ ){\n var neighbor = neighbors[i];\n var bf = neighbor._private.scratch.breadthfirst;\n var index = bf.index;\n var depth = bf.depth;\n var nDepth = depths[depth].length;\n\n if( eleDepth > depth || eleDepth === 0 ){ // only get influenced by elements above\n percent += index / nDepth;\n samples++;\n }\n }\n\n samples = Math.max(1, samples);\n percent = percent / samples;\n\n if( samples === 0 ){ // so lone nodes have a \"don't care\" state in sorting\n percent = undefined;\n }\n\n cachedWeightedPercent[ ele.id() ] = percent;\n return percent;\n };\n\n\n // rearrange the indices in each depth level based on connectivity\n\n var sortFn = function(a, b){\n var apct = getWeightedPercent( a );\n var bpct = getWeightedPercent( b );\n\n return apct - bpct;\n };\n\n for( var times = 0; times < 3; times++ ){ // do it a few times b/c the depths are dynamic and we want a more stable result\n\n for( var i = 0; i < depths.length; i++ ){\n depths[i] = depths[i].sort( sortFn );\n }\n assignDepthsToEles(); // and update\n\n }\n\n var biggestDepthSize = 0;\n for( var i = 0; i < depths.length; i++ ){\n biggestDepthSize = Math.max( depths[i].length, biggestDepthSize );\n }\n\n var center = {\n x: bb.x1 + bb.w/2,\n y: bb.x1 + bb.h/2\n };\n\n var getPosition = function( ele, isBottomDepth ){\n var info = ele._private.scratch.breadthfirst;\n var depth = info.depth;\n var index = info.index;\n var depthSize = depths[depth].length;\n\n var distanceX = Math.max( bb.w / (depthSize + 1), minDistance );\n var distanceY = Math.max( bb.h / (depths.length + 1), minDistance );\n var radiusStepSize = Math.min( bb.w / 2 / depths.length, bb.h / 2 / depths.length );\n radiusStepSize = Math.max( radiusStepSize, minDistance );\n\n if( !options.circle ){\n\n var epos = {\n x: center.x + (index + 1 - (depthSize + 1)/2) * distanceX,\n y: (depth + 1) * distanceY\n };\n\n if( isBottomDepth ){\n return epos;\n }\n\n // var succs = successors[ ele.id() ];\n // if( succs ){\n // epos.x = 0;\n //\n // for( var i = 0 ; i < succs.length; i++ ){\n // var spos = pos[ succs[i].id() ];\n //\n // epos.x += spos.x;\n // }\n //\n // epos.x /= succs.length;\n // } else {\n // //debugger;\n // }\n\n return epos;\n\n } else {\n if( options.circle ){\n var radius = radiusStepSize * depth + radiusStepSize - (depths.length > 0 && depths[0].length <= 3 ? radiusStepSize/2 : 0);\n var theta = 2 * Math.PI / depths[depth].length * index;\n\n if( depth === 0 && depths[0].length === 1 ){\n radius = 1;\n }\n\n return {\n x: center.x + radius * Math.cos(theta),\n y: center.y + radius * Math.sin(theta)\n };\n\n } else {\n return {\n x: center.x + (index + 1 - (depthSize + 1)/2) * distanceX,\n y: (depth + 1) * distanceY\n };\n }\n }\n\n };\n\n // get positions in reverse depth order\n var pos = {};\n for( var i = depths.length - 1; i >=0; i-- ){\n var depth = depths[i];\n\n for( var j = 0; j < depth.length; j++ ){\n var node = depth[j];\n\n pos[ node.id() ] = getPosition( node, i === depths.length - 1 );\n }\n }\n\n nodes.layoutPositions(this, options, function(){\n return pos[ this.id() ];\n });\n\n return this; // chaining\n};\n\nmodule.exports = BreadthFirstLayout;\n","'use strict';\n\nvar util = require('../../util');\nvar math = require('../../math');\nvar is = require('../../is');\n\nvar defaults = {\n fit: true, // whether to fit the viewport to the graph\n padding: 30, // the padding on fit\n boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n avoidOverlap: true, // prevents node overlap, may overflow boundingBox and radius if not enough space\n radius: undefined, // the radius of the circle\n startAngle: 3/2 * Math.PI, // where nodes start in radians\n sweep: undefined, // how many radians should be between the first and last node (defaults to full circle)\n clockwise: true, // whether the layout should go clockwise (true) or counterclockwise/anticlockwise (false)\n sort: undefined, // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }\n animate: false, // whether to transition the node positions\n animationDuration: 500, // duration of animation in ms if enabled\n animationEasing: undefined, // easing of animation if enabled\n ready: undefined, // callback on layoutready\n stop: undefined // callback on layoutstop\n};\n\nfunction CircleLayout( options ){\n this.options = util.extend({}, defaults, options);\n}\n\nCircleLayout.prototype.run = function(){\n var params = this.options;\n var options = params;\n\n var cy = params.cy;\n var eles = options.eles;\n\n var clockwise = options.counterclockwise !== undefined ? !options.counterclockwise : options.clockwise;\n\n var nodes = eles.nodes().not(':parent');\n\n if( options.sort ){\n nodes = nodes.sort( options.sort );\n }\n\n var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n x1: 0, y1: 0, w: cy.width(), h: cy.height()\n } );\n\n var center = {\n x: bb.x1 + bb.w/2,\n y: bb.y1 + bb.h/2\n };\n\n var sweep = options.sweep === undefined ? 2*Math.PI - 2*Math.PI/nodes.length : options.sweep;\n\n var dTheta = sweep / ( Math.max(1, nodes.length - 1) );\n var r;\n\n var minDistance = 0;\n for( var i = 0; i < nodes.length; i++ ){\n var n = nodes[i];\n var nbb = n.boundingBox();\n var w = nbb.w;\n var h = nbb.h;\n\n minDistance = Math.max(minDistance, w, h);\n }\n\n if( is.number(options.radius) ){\n r = options.radius;\n } else if( nodes.length <= 1 ){\n r = 0;\n } else {\n r = Math.min( bb.h, bb.w )/2 - minDistance;\n }\n\n // calculate the radius\n if( nodes.length > 1 && options.avoidOverlap ){ // but only if more than one node (can't overlap)\n minDistance *= 1.75; // just to have some nice spacing\n\n var dcos = Math.cos(dTheta) - Math.cos(0);\n var dsin = Math.sin(dTheta) - Math.sin(0);\n var rMin = Math.sqrt( minDistance * minDistance / ( dcos*dcos + dsin*dsin ) ); // s.t. no nodes overlapping\n r = Math.max( rMin, r );\n }\n\n var getPos = function( i, ele ){\n var theta = options.startAngle + i * dTheta * ( clockwise ? 1 : -1 );\n\n var rx = r * Math.cos( theta );\n var ry = r * Math.sin( theta );\n var pos = {\n x: center.x + rx,\n y: center.y + ry\n };\n\n return pos;\n };\n\n nodes.layoutPositions( this, options, getPos );\n\n return this; // chaining\n};\n\nmodule.exports = CircleLayout;\n","'use strict';\n\nvar util = require('../../util');\nvar math = require('../../math');\n\nvar defaults = {\n fit: true, // whether to fit the viewport to the graph\n padding: 30, // the padding on fit\n startAngle: 3/2 * Math.PI, // where nodes start in radians\n sweep: undefined, // how many radians should be between the first and last node (defaults to full circle)\n clockwise: true, // whether the layout should go clockwise (true) or counterclockwise/anticlockwise (false)\n equidistant: false, // whether levels have an equal radial distance betwen them, may cause bounding box overflow\n minNodeSpacing: 10, // min spacing between outside of nodes (used for radius adjustment)\n boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space\n height: undefined, // height of layout area (overrides container height)\n width: undefined, // width of layout area (overrides container width)\n concentric: function(node){ // returns numeric value for each node, placing higher nodes in levels towards the centre\n return node.degree();\n },\n levelWidth: function(nodes){ // the variation of concentric values in each level\n return nodes.maxDegree() / 4;\n },\n animate: false, // whether to transition the node positions\n animationDuration: 500, // duration of animation in ms if enabled\n animationEasing: undefined, // easing of animation if enabled\n ready: undefined, // callback on layoutready\n stop: undefined // callback on layoutstop\n};\n\nfunction ConcentricLayout( options ){\n this.options = util.extend({}, defaults, options);\n}\n\nConcentricLayout.prototype.run = function(){\n var params = this.options;\n var options = params;\n\n var clockwise = options.counterclockwise !== undefined ? !options.counterclockwise : options.clockwise;\n\n var cy = params.cy;\n\n var eles = options.eles;\n var nodes = eles.nodes().not(':parent');\n\n var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n x1: 0, y1: 0, w: cy.width(), h: cy.height()\n } );\n\n var center = {\n x: bb.x1 + bb.w/2,\n y: bb.y1 + bb.h/2\n };\n\n var nodeValues = []; // { node, value }\n var theta = options.startAngle;\n var maxNodeSize = 0;\n\n for( var i = 0; i < nodes.length; i++ ){\n var node = nodes[i];\n var value;\n\n // calculate the node value\n value = options.concentric.apply(node, [ node ]);\n nodeValues.push({\n value: value,\n node: node\n });\n\n // for style mapping\n node._private.scratch.concentric = value;\n }\n\n // in case we used the `concentric` in style\n nodes.updateStyle();\n\n // calculate max size now based on potentially updated mappers\n for( var i = 0; i < nodes.length; i++ ){\n var node = nodes[i];\n var nbb = node.boundingBox();\n\n maxNodeSize = Math.max( maxNodeSize, nbb.w, nbb.h );\n }\n\n // sort node values in descreasing order\n nodeValues.sort(function(a, b){\n return b.value - a.value;\n });\n\n var levelWidth = options.levelWidth( nodes );\n\n // put the values into levels\n var levels = [ [] ];\n var currentLevel = levels[0];\n for( var i = 0; i < nodeValues.length; i++ ){\n var val = nodeValues[i];\n\n if( currentLevel.length > 0 ){\n var diff = Math.abs( currentLevel[0].value - val.value );\n\n if( diff >= levelWidth ){\n currentLevel = [];\n levels.push( currentLevel );\n }\n }\n\n currentLevel.push( val );\n }\n\n // create positions from levels\n\n var minDist = maxNodeSize + options.minNodeSpacing; // min dist between nodes\n\n if( !options.avoidOverlap ){ // then strictly constrain to bb\n var firstLvlHasMulti = levels.length > 0 && levels[0].length > 1;\n var maxR = ( Math.min(bb.w, bb.h) / 2 - minDist );\n var rStep = maxR / ( levels.length + firstLvlHasMulti ? 1 : 0 );\n\n minDist = Math.min( minDist, rStep );\n }\n\n // find the metrics for each level\n var r = 0;\n for( var i = 0; i < levels.length; i++ ){\n var level = levels[i];\n var sweep = options.sweep === undefined ? 2*Math.PI - 2*Math.PI/level.length : options.sweep;\n var dTheta = level.dTheta = sweep / ( Math.max(1, level.length - 1) );\n\n // calculate the radius\n if( level.length > 1 && options.avoidOverlap ){ // but only if more than one node (can't overlap)\n var dcos = Math.cos(dTheta) - Math.cos(0);\n var dsin = Math.sin(dTheta) - Math.sin(0);\n var rMin = Math.sqrt( minDist * minDist / ( dcos*dcos + dsin*dsin ) ); // s.t. no nodes overlapping\n\n r = Math.max( rMin, r );\n }\n\n level.r = r;\n\n r += minDist;\n }\n\n if( options.equidistant ){\n var rDeltaMax = 0;\n var r = 0;\n\n for( var i = 0; i < levels.length; i++ ){\n var level = levels[i];\n var rDelta = level.r - r;\n\n rDeltaMax = Math.max( rDeltaMax, rDelta );\n }\n\n r = 0;\n for( var i = 0; i < levels.length; i++ ){\n var level = levels[i];\n\n if( i === 0 ){\n r = level.r;\n }\n\n level.r = r;\n\n r += rDeltaMax;\n }\n }\n\n // calculate the node positions\n var pos = {}; // id => position\n for( var i = 0; i < levels.length; i++ ){\n var level = levels[i];\n var dTheta = level.dTheta;\n var r = level.r;\n\n for( var j = 0; j < level.length; j++ ){\n var val = level[j];\n var theta = options.startAngle + (clockwise ? 1 : -1) * dTheta * j;\n\n var p = {\n x: center.x + r * Math.cos(theta),\n y: center.y + r * Math.sin(theta)\n };\n\n pos[ val.node.id() ] = p;\n }\n }\n\n // position the nodes\n nodes.layoutPositions(this, options, function(){\n var id = this.id();\n\n return pos[id];\n });\n\n return this; // chaining\n};\n\nmodule.exports = ConcentricLayout;\n","'use strict';\n\n/*\nThe CoSE layout was written by Gerardo Huck.\nhttps://www.linkedin.com/in/gerardohuck/\n\nBased on the following article:\nhttp://dl.acm.org/citation.cfm?id=1498047\n\nModifications tracked on Github.\n*/\n\nvar util = require('../../util');\nvar math = require('../../math');\nvar Thread = require('../../thread');\nvar is = require('../../is');\n\nvar DEBUG;\n\n/**\n * @brief : default layout options\n */\nvar defaults = {\n // Called on `layoutready`\n ready : function() {},\n\n // Called on `layoutstop`\n stop : function() {},\n\n // Whether to animate while running the layout\n animate : true,\n\n // The layout animates only after this many milliseconds\n // (prevents flashing on fast runs)\n animationThreshold : 250,\n\n // Number of iterations between consecutive screen positions update\n // (0 -> only updated on the end)\n refresh : 20,\n\n // Whether to fit the network view after when done\n fit : true,\n\n // Padding on fit\n padding : 30,\n\n // Constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n boundingBox : undefined,\n\n // Extra spacing between components in non-compound graphs\n componentSpacing : 100,\n\n // Node repulsion (non overlapping) multiplier\n nodeRepulsion : function( node ){ return 400000; },\n\n // Node repulsion (overlapping) multiplier\n nodeOverlap : 10,\n\n // Ideal edge (non nested) length\n idealEdgeLength : function( edge ){ return 10; },\n\n // Divisor to compute edge forces\n edgeElasticity : function( edge ){ return 100; },\n\n // Nesting factor (multiplier) to compute ideal edge length for nested edges\n nestingFactor : 5,\n\n // Gravity force (constant)\n gravity : 80,\n\n // Maximum number of iterations to perform\n numIter : 1000,\n\n // Initial temperature (maximum node displacement)\n initialTemp : 200,\n\n // Cooling factor (how the temperature is reduced between consecutive iterations\n coolingFactor : 0.95,\n\n // Lower temperature threshold (below this point the layout will end)\n minTemp : 1.0,\n\n // Whether to use threading to speed up the layout\n useMultitasking : true\n};\n\n\n/**\n * @brief : constructor\n * @arg options : object containing layout options\n */\nfunction CoseLayout(options) {\n this.options = util.extend({}, defaults, options);\n\n this.options.layout = this;\n}\n\n\n/**\n * @brief : runs the layout\n */\nCoseLayout.prototype.run = function() {\n var options = this.options;\n var cy = options.cy;\n var layout = this;\n var thread = this.thread;\n\n if( !thread || thread.stopped() ){\n thread = this.thread = Thread({ disabled: !options.useMultitasking });\n }\n\n layout.stopped = false;\n\n layout.trigger({ type: 'layoutstart', layout: layout });\n\n // Set DEBUG - Global variable\n if (true === options.debug) {\n DEBUG = true;\n } else {\n DEBUG = false;\n }\n\n // Initialize layout info\n var layoutInfo = createLayoutInfo(cy, layout, options);\n\n // Show LayoutInfo contents if debugging\n if (DEBUG) {\n printLayoutInfo(layoutInfo);\n }\n\n // If required, randomize node positions\n // if (true === options.randomize) {\n randomizePositions(layoutInfo, cy);\n // }\n\n var startTime = Date.now();\n var refreshRequested = false;\n var refresh = function( rOpts ){\n rOpts = rOpts || {};\n\n if( refreshRequested ){\n return;\n }\n\n if( !rOpts.force && Date.now() - startTime < options.animationThreshold ){\n return;\n }\n\n refreshRequested = true;\n\n util.requestAnimationFrame(function(){\n refreshPositions(layoutInfo, cy, options);\n\n // Fit the graph if necessary\n if (true === options.fit) {\n cy.fit( options.padding );\n }\n\n refreshRequested = false;\n\n if( rOpts.next ){ rOpts.next(); }\n });\n };\n\n thread.on('message', function( e ){\n var layoutNodes = e.message;\n\n layoutInfo.layoutNodes = layoutNodes;\n refresh();\n });\n\n thread.pass({\n layoutInfo: layoutInfo,\n options: {\n animate: options.animate,\n refresh: options.refresh,\n componentSpacing: options.componentSpacing,\n nodeOverlap: options.nodeOverlap,\n nestingFactor: options.nestingFactor,\n gravity: options.gravity,\n numIter: options.numIter,\n initialTemp: options.initialTemp,\n coolingFactor: options.coolingFactor,\n minTemp: options.minTemp\n }\n }).run(function( pass ){\n var layoutInfo = pass.layoutInfo;\n var options = pass.options;\n var stopped = false;\n\n /**\n * @brief : Performs one iteration of the physical simulation\n * @arg layoutInfo : LayoutInfo object already initialized\n * @arg cy : Cytoscape object\n * @arg options : Layout options\n */\n var step = function(layoutInfo, options, step) {\n // var s = \"\\n\\n###############################\";\n // s += \"\\nSTEP: \" + step;\n // s += \"\\n###############################\\n\";\n // logDebug(s);\n\n // Calculate node repulsions\n calculateNodeForces(layoutInfo, options);\n // Calculate edge forces\n calculateEdgeForces(layoutInfo, options);\n // Calculate gravity forces\n calculateGravityForces(layoutInfo, options);\n // Propagate forces from parent to child\n propagateForces(layoutInfo, options);\n // Update positions based on calculated forces\n updatePositions(layoutInfo, options);\n };\n\n /**\n * @brief : Computes the node repulsion forces\n */\n var calculateNodeForces = function(layoutInfo, options) {\n // Go through each of the graphs in graphSet\n // Nodes only repel each other if they belong to the same graph\n // var s = 'calculateNodeForces';\n // logDebug(s);\n for (var i = 0; i < layoutInfo.graphSet.length; i ++) {\n var graph = layoutInfo.graphSet[i];\n var numNodes = graph.length;\n\n // s = \"Set: \" + graph.toString();\n // logDebug(s);\n\n // Now get all the pairs of nodes\n // Only get each pair once, (A, B) = (B, A)\n for (var j = 0; j < numNodes; j++) {\n var node1 = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[j]]];\n\n for (var k = j + 1; k < numNodes; k++) {\n var node2 = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[k]]];\n\n nodeRepulsion(node1, node2, layoutInfo, options);\n }\n }\n }\n };\n\n /**\n * @brief : Compute the node repulsion forces between a pair of nodes\n */\n var nodeRepulsion = function(node1, node2, layoutInfo, options) {\n // var s = \"Node repulsion. Node1: \" + node1.id + \" Node2: \" + node2.id;\n\n var cmptId1 = node1.cmptId;\n var cmptId2 = node2.cmptId;\n\n if( cmptId1 !== cmptId2 && !layoutInfo.isCompound ){ return; }\n\n // Get direction of line connecting both node centers\n var directionX = node2.positionX - node1.positionX;\n var directionY = node2.positionY - node1.positionY;\n // s += \"\\ndirectionX: \" + directionX + \", directionY: \" + directionY;\n\n // If both centers are the same, apply a random force\n if (0 === directionX && 0 === directionY) {\n // s += \"\\nNodes have the same position.\";\n return; // TODO could be improved with random force\n }\n\n var overlap = nodesOverlap(node1, node2, directionX, directionY);\n\n if (overlap > 0) {\n // s += \"\\nNodes DO overlap.\";\n // s += \"\\nOverlap: \" + overlap;\n // If nodes overlap, repulsion force is proportional\n // to the overlap\n var force = options.nodeOverlap * overlap;\n\n // Compute the module and components of the force vector\n var distance = Math.sqrt(directionX * directionX + directionY * directionY);\n // s += \"\\nDistance: \" + distance;\n var forceX = force * directionX / distance;\n var forceY = force * directionY / distance;\n\n } else {\n // s += \"\\nNodes do NOT overlap.\";\n // If there's no overlap, force is inversely proportional\n // to squared distance\n\n // Get clipping points for both nodes\n var point1 = findClippingPoint(node1, directionX, directionY);\n var point2 = findClippingPoint(node2, -1 * directionX, -1 * directionY);\n\n // Use clipping points to compute distance\n var distanceX = point2.x - point1.x;\n var distanceY = point2.y - point1.y;\n var distanceSqr = distanceX * distanceX + distanceY * distanceY;\n var distance = Math.sqrt(distanceSqr);\n // s += \"\\nDistance: \" + distance;\n\n // Compute the module and components of the force vector\n var force = ( node1.nodeRepulsion + node2.nodeRepulsion ) / distanceSqr;\n var forceX = force * distanceX / distance;\n var forceY = force * distanceY / distance;\n }\n\n // Apply force\n if( !node1.isLocked ){\n node1.offsetX -= forceX;\n node1.offsetY -= forceY;\n }\n\n if( !node2.isLocked ){\n node2.offsetX += forceX;\n node2.offsetY += forceY;\n }\n\n // s += \"\\nForceX: \" + forceX + \" ForceY: \" + forceY;\n // logDebug(s);\n\n return;\n };\n\n /**\n * @brief : Determines whether two nodes overlap or not\n * @return : Amount of overlapping (0 => no overlap)\n */\n var nodesOverlap = function(node1, node2, dX, dY) {\n\n if (dX > 0) {\n var overlapX = node1.maxX - node2.minX;\n } else {\n var overlapX = node2.maxX - node1.minX;\n }\n\n if (dY > 0) {\n var overlapY = node1.maxY - node2.minY;\n } else {\n var overlapY = node2.maxY - node1.minY;\n }\n\n if (overlapX >= 0 && overlapY >= 0) {\n return Math.sqrt(overlapX * overlapX + overlapY * overlapY);\n } else {\n return 0;\n }\n };\n\n /**\n * @brief : Finds the point in which an edge (direction dX, dY) intersects\n * the rectangular bounding box of it's source/target node\n */\n var findClippingPoint = function(node, dX, dY) {\n\n // Shorcuts\n var X = node.positionX;\n var Y = node.positionY;\n var H = node.height || 1;\n var W = node.width || 1;\n var dirSlope = dY / dX;\n var nodeSlope = H / W;\n\n // var s = 'Computing clipping point of node ' + node.id +\n // \" . Height: \" + H + \", Width: \" + W +\n // \"\\nDirection \" + dX + \", \" + dY;\n //\n // Compute intersection\n var res = {};\n do {\n // Case: Vertical direction (up)\n if (0 === dX && 0 < dY) {\n res.x = X;\n // s += \"\\nUp direction\";\n res.y = Y + H / 2;\n break;\n }\n\n // Case: Vertical direction (down)\n if (0 === dX && 0 > dY) {\n res.x = X;\n res.y = Y + H / 2;\n // s += \"\\nDown direction\";\n break;\n }\n\n // Case: Intersects the right border\n if (0 < dX &&\n -1 * nodeSlope <= dirSlope &&\n dirSlope <= nodeSlope) {\n res.x = X + W / 2;\n res.y = Y + (W * dY / 2 / dX);\n // s += \"\\nRightborder\";\n break;\n }\n\n // Case: Intersects the left border\n if (0 > dX &&\n -1 * nodeSlope <= dirSlope &&\n dirSlope <= nodeSlope) {\n res.x = X - W / 2;\n res.y = Y - (W * dY / 2 / dX);\n // s += \"\\nLeftborder\";\n break;\n }\n\n // Case: Intersects the top border\n if (0 < dY &&\n ( dirSlope <= -1 * nodeSlope ||\n dirSlope >= nodeSlope )) {\n res.x = X + (H * dX / 2 / dY);\n res.y = Y + H / 2;\n // s += \"\\nTop border\";\n break;\n }\n\n // Case: Intersects the bottom border\n if (0 > dY &&\n ( dirSlope <= -1 * nodeSlope ||\n dirSlope >= nodeSlope )) {\n res.x = X - (H * dX / 2 / dY);\n res.y = Y - H / 2;\n // s += \"\\nBottom border\";\n break;\n }\n\n } while (false);\n\n // s += \"\\nClipping point found at \" + res.x + \", \" + res.y;\n // logDebug(s);\n return res;\n };\n\n /**\n * @brief : Calculates all edge forces\n */\n var calculateEdgeForces = function(layoutInfo, options) {\n // Iterate over all edges\n for (var i = 0; i < layoutInfo.edgeSize; i++) {\n // Get edge, source & target nodes\n var edge = layoutInfo.layoutEdges[i];\n var sourceIx = layoutInfo.idToIndex[edge.sourceId];\n var source = layoutInfo.layoutNodes[sourceIx];\n var targetIx = layoutInfo.idToIndex[edge.targetId];\n var target = layoutInfo.layoutNodes[targetIx];\n\n // Get direction of line connecting both node centers\n var directionX = target.positionX - source.positionX;\n var directionY = target.positionY - source.positionY;\n\n // If both centers are the same, do nothing.\n // A random force has already been applied as node repulsion\n if (0 === directionX && 0 === directionY) {\n return;\n }\n\n // Get clipping points for both nodes\n var point1 = findClippingPoint(source, directionX, directionY);\n var point2 = findClippingPoint(target, -1 * directionX, -1 * directionY);\n\n\n var lx = point2.x - point1.x;\n var ly = point2.y - point1.y;\n var l = Math.sqrt(lx * lx + ly * ly);\n\n var force = Math.pow(edge.idealLength - l, 2) / edge.elasticity;\n\n if (0 !== l) {\n var forceX = force * lx / l;\n var forceY = force * ly / l;\n } else {\n var forceX = 0;\n var forceY = 0;\n }\n\n // Add this force to target and source nodes\n if( !source.isLocked ){\n source.offsetX += forceX;\n source.offsetY += forceY;\n }\n\n if( !target.isLocked ){\n target.offsetX -= forceX;\n target.offsetY -= forceY;\n }\n\n // var s = 'Edge force between nodes ' + source.id + ' and ' + target.id;\n // s += \"\\nDistance: \" + l + \" Force: (\" + forceX + \", \" + forceY + \")\";\n // logDebug(s);\n }\n };\n\n /**\n * @brief : Computes gravity forces for all nodes\n */\n var calculateGravityForces = function(layoutInfo, options) {\n var distThreshold = 1;\n\n // var s = 'calculateGravityForces';\n // logDebug(s);\n for (var i = 0; i < layoutInfo.graphSet.length; i ++) {\n var graph = layoutInfo.graphSet[i];\n var numNodes = graph.length;\n\n // s = \"Set: \" + graph.toString();\n // logDebug(s);\n\n // Compute graph center\n if (0 === i) {\n var centerX = layoutInfo.clientHeight / 2;\n var centerY = layoutInfo.clientWidth / 2;\n } else {\n // Get Parent node for this graph, and use its position as center\n var temp = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[0]]];\n var parent = layoutInfo.layoutNodes[layoutInfo.idToIndex[temp.parentId]];\n var centerX = parent.positionX;\n var centerY = parent.positionY;\n }\n // s = \"Center found at: \" + centerX + \", \" + centerY;\n // logDebug(s);\n\n // Apply force to all nodes in graph\n for (var j = 0; j < numNodes; j++) {\n var node = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[j]]];\n // s = \"Node: \" + node.id;\n\n if( node.isLocked ){ continue; }\n\n var dx = centerX - node.positionX;\n var dy = centerY - node.positionY;\n var d = Math.sqrt(dx * dx + dy * dy);\n if (d > distThreshold) {\n var fx = options.gravity * dx / d;\n var fy = options.gravity * dy / d;\n node.offsetX += fx;\n node.offsetY += fy;\n // s += \": Applied force: \" + fx + \", \" + fy;\n } else {\n // s += \": skypped since it's too close to center\";\n }\n // logDebug(s);\n }\n }\n };\n\n /**\n * @brief : This function propagates the existing offsets from\n * parent nodes to its descendents.\n * @arg layoutInfo : layoutInfo Object\n * @arg cy : cytoscape Object\n * @arg options : Layout options\n */\n var propagateForces = function(layoutInfo, options) {\n // Inline implementation of a queue, used for traversing the graph in BFS order\n var queue = [];\n var start = 0; // Points to the start the queue\n var end = -1; // Points to the end of the queue\n\n // logDebug('propagateForces');\n\n // Start by visiting the nodes in the root graph\n queue.push.apply(queue, layoutInfo.graphSet[0]);\n end += layoutInfo.graphSet[0].length;\n\n // Traverse the graph, level by level,\n while (start <= end) {\n // Get the node to visit and remove it from queue\n var nodeId = queue[start++];\n var nodeIndex = layoutInfo.idToIndex[nodeId];\n var node = layoutInfo.layoutNodes[nodeIndex];\n var children = node.children;\n\n // We only need to process the node if it's compound\n if (0 < children.length && !node.isLocked) {\n var offX = node.offsetX;\n var offY = node.offsetY;\n\n // var s = \"Propagating offset from parent node : \" + node.id +\n // \". OffsetX: \" + offX + \". OffsetY: \" + offY;\n // s += \"\\n Children: \" + children.toString();\n // logDebug(s);\n\n for (var i = 0; i < children.length; i++) {\n var childNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[children[i]]];\n // Propagate offset\n childNode.offsetX += offX;\n childNode.offsetY += offY;\n // Add children to queue to be visited\n queue[++end] = children[i];\n }\n\n // Reset parent offsets\n node.offsetX = 0;\n node.offsetY = 0;\n }\n\n }\n };\n\n /**\n * @brief : Updates the layout model positions, based on\n * the accumulated forces\n */\n var updatePositions = function(layoutInfo, options) {\n // var s = 'Updating positions';\n // logDebug(s);\n\n // Reset boundaries for compound nodes\n for (var i = 0; i < layoutInfo.nodeSize; i++) {\n var n = layoutInfo.layoutNodes[i];\n if (0 < n.children.length) {\n // logDebug(\"Resetting boundaries of compound node: \" + n.id);\n n.maxX = undefined;\n n.minX = undefined;\n n.maxY = undefined;\n n.minY = undefined;\n }\n }\n\n for (var i = 0; i < layoutInfo.nodeSize; i++) {\n var n = layoutInfo.layoutNodes[i];\n if (0 < n.children.length || n.isLocked) {\n // No need to set compound or locked node position\n // logDebug(\"Skipping position update of node: \" + n.id);\n continue;\n }\n // s = \"Node: \" + n.id + \" Previous position: (\" +\n // n.positionX + \", \" + n.positionY + \").\";\n\n // Limit displacement in order to improve stability\n var tempForce = limitForce(n.offsetX, n.offsetY, layoutInfo.temperature);\n n.positionX += tempForce.x;\n n.positionY += tempForce.y;\n n.offsetX = 0;\n n.offsetY = 0;\n n.minX = n.positionX - n.width;\n n.maxX = n.positionX + n.width;\n n.minY = n.positionY - n.height;\n n.maxY = n.positionY + n.height;\n // s += \" New Position: (\" + n.positionX + \", \" + n.positionY + \").\";\n // logDebug(s);\n\n // Update ancestry boudaries\n updateAncestryBoundaries(n, layoutInfo);\n }\n\n // Update size, position of compund nodes\n for (var i = 0; i < layoutInfo.nodeSize; i++) {\n var n = layoutInfo.layoutNodes[i];\n if ( 0 < n.children.length && !n.isLocked ) {\n n.positionX = (n.maxX + n.minX) / 2;\n n.positionY = (n.maxY + n.minY) / 2;\n n.width = n.maxX - n.minX;\n n.height = n.maxY - n.minY;\n // s = \"Updating position, size of compound node \" + n.id;\n // s += \"\\nPositionX: \" + n.positionX + \", PositionY: \" + n.positionY;\n // s += \"\\nWidth: \" + n.width + \", Height: \" + n.height;\n // logDebug(s);\n }\n }\n };\n\n /**\n * @brief : Limits a force (forceX, forceY) to be not\n * greater (in modulo) than max.\n 8 Preserves force direction.\n */\n var limitForce = function(forceX, forceY, max) {\n // var s = \"Limiting force: (\" + forceX + \", \" + forceY + \"). Max: \" + max;\n var force = Math.sqrt(forceX * forceX + forceY * forceY);\n\n if (force > max) {\n var res = {\n x : max * forceX / force,\n y : max * forceY / force\n };\n\n } else {\n var res = {\n x : forceX,\n y : forceY\n };\n }\n\n // s += \".\\nResult: (\" + res.x + \", \" + res.y + \")\";\n // logDebug(s);\n\n return res;\n };\n\n /**\n * @brief : Function used for keeping track of compound node\n * sizes, since they should bound all their subnodes.\n */\n var updateAncestryBoundaries = function(node, layoutInfo) {\n // var s = \"Propagating new position/size of node \" + node.id;\n var parentId = node.parentId;\n if (null == parentId) {\n // If there's no parent, we are done\n // s += \". No parent node.\";\n // logDebug(s);\n return;\n }\n\n // Get Parent Node\n var p = layoutInfo.layoutNodes[layoutInfo.idToIndex[parentId]];\n var flag = false;\n\n // MaxX\n if (null == p.maxX || node.maxX + p.padRight > p.maxX) {\n p.maxX = node.maxX + p.padRight;\n flag = true;\n // s += \"\\nNew maxX for parent node \" + p.id + \": \" + p.maxX;\n }\n\n // MinX\n if (null == p.minX || node.minX - p.padLeft < p.minX) {\n p.minX = node.minX - p.padLeft;\n flag = true;\n // s += \"\\nNew minX for parent node \" + p.id + \": \" + p.minX;\n }\n\n // MaxY\n if (null == p.maxY || node.maxY + p.padBottom > p.maxY) {\n p.maxY = node.maxY + p.padBottom;\n flag = true;\n // s += \"\\nNew maxY for parent node \" + p.id + \": \" + p.maxY;\n }\n\n // MinY\n if (null == p.minY || node.minY - p.padTop < p.minY) {\n p.minY = node.minY - p.padTop;\n flag = true;\n // s += \"\\nNew minY for parent node \" + p.id + \": \" + p.minY;\n }\n\n // If updated boundaries, propagate changes upward\n if (flag) {\n // logDebug(s);\n return updateAncestryBoundaries(p, layoutInfo);\n }\n\n // s += \". No changes in boundaries/position of parent node \" + p.id;\n // logDebug(s);\n return;\n };\n\n var separateComponents = function(layutInfo, options){\n var nodes = layoutInfo.layoutNodes;\n var components = [];\n\n for( var i = 0; i < nodes.length; i++ ){\n var node = nodes[i];\n var cid = node.cmptId;\n var component = components[ cid ] = components[ cid ] || [];\n\n component.push( node );\n }\n\n var totalA = 0;\n\n for( var i = 0; i < components.length; i++ ){\n var c = components[i];\n c.x1 = Infinity;\n c.x2 = -Infinity;\n c.y1 = Infinity;\n c.y2 = -Infinity;\n\n for( var j = 0; j < c.length; j++ ){\n var n = c[j];\n\n c.x1 = Math.min( c.x1, n.positionX - n.width/2 );\n c.x2 = Math.max( c.x2, n.positionX + n.width/2 );\n c.y1 = Math.min( c.y1, n.positionY - n.height/2 );\n c.y2 = Math.max( c.y2, n.positionY + n.height/2 );\n }\n\n c.w = c.x2 - c.x1;\n c.h = c.y2 - c.y1;\n\n totalA += c.w * c.h;\n }\n\n components.sort(function( c1, c2 ){\n return c2.w*c2.h - c1.w*c1.h;\n });\n\n var x = 0;\n var y = 0;\n var usedW = 0;\n var rowH = 0;\n var maxRowW = Math.sqrt( totalA ) * layoutInfo.clientWidth / layoutInfo.clientHeight;\n\n for( var i = 0; i < components.length; i++ ){\n var c = components[i];\n\n for( var j = 0; j < c.length; j++ ){\n var n = c[j];\n\n if( !n.isLocked ){\n n.positionX += x;\n n.positionY += y;\n }\n }\n\n x += c.w + options.componentSpacing;\n usedW += c.w + options.componentSpacing;\n rowH = Math.max( rowH, c.h );\n\n if( usedW > maxRowW ){\n y += rowH + options.componentSpacing;\n x = 0;\n usedW = 0;\n rowH = 0;\n }\n }\n };\n\n var mainLoop = function(i){\n if( stopped ){\n // logDebug(\"Layout manually stopped. Stopping computation in step \" + i);\n return false;\n }\n\n // Do one step in the phisical simulation\n step(layoutInfo, options, i);\n\n // Update temperature\n layoutInfo.temperature = layoutInfo.temperature * options.coolingFactor;\n // logDebug(\"New temperature: \" + layoutInfo.temperature);\n\n if (layoutInfo.temperature < options.minTemp) {\n // logDebug(\"Temperature drop below minimum threshold. Stopping computation in step \" + i);\n return false;\n }\n\n return true;\n };\n\n var i = 0;\n var loopRet;\n\n do {\n var f = 0;\n\n while( f < options.refresh && i < options.numIter ){\n var loopRet = mainLoop(i);\n if( !loopRet ){ break; }\n\n f++;\n i++;\n }\n\n if( options.animate ){\n broadcast( layoutInfo.layoutNodes ); // jshint ignore:line\n }\n\n } while ( loopRet && i + 1 < options.numIter );\n\n separateComponents( layoutInfo, options );\n\n return layoutInfo;\n }).then(function( layoutInfoUpdated ){\n layoutInfo.layoutNodes = layoutInfoUpdated.layoutNodes; // get the positions\n\n thread.stop();\n done();\n });\n\n var done = function(){\n refresh({ \n force: true,\n next: function(){\n // Layout has finished\n layout.one('layoutstop', options.stop);\n layout.trigger({ type: 'layoutstop', layout: layout });\n }\n });\n };\n\n return this; // chaining\n};\n\n\n/**\n * @brief : called on continuous layouts to stop them before they finish\n */\nCoseLayout.prototype.stop = function(){\n this.stopped = true;\n\n if( this.thread ){\n this.thread.stop();\n }\n\n this.trigger('layoutstop');\n\n return this; // chaining\n};\n\nCoseLayout.prototype.destroy = function(){\n if( this.thread ){\n this.thread.stop();\n }\n\n return this; // chaining\n};\n\n\n/**\n * @brief : Creates an object which is contains all the data\n * used in the layout process\n * @arg cy : cytoscape.js object\n * @return : layoutInfo object initialized\n */\nvar createLayoutInfo = function(cy, layout, options) {\n // Shortcut\n var edges = options.eles.edges();\n var nodes = options.eles.nodes();\n\n var layoutInfo = {\n isCompound : cy.hasCompoundNodes(),\n layoutNodes : [],\n idToIndex : {},\n nodeSize : nodes.size(),\n graphSet : [],\n indexToGraph : [],\n layoutEdges : [],\n edgeSize : edges.size(),\n temperature : options.initialTemp,\n clientWidth : cy.width(),\n clientHeight : cy.width(),\n boundingBox : math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n x1: 0, y1: 0, w: cy.width(), h: cy.height()\n } )\n };\n\n var components = options.eles.components();\n var id2cmptId = {};\n\n for( var i = 0; i < components.length; i++ ){\n var component = components[i];\n\n for( var j = 0; j < component.length; j++ ){\n var node = component[j];\n\n id2cmptId[ node.id() ] = i;\n }\n }\n\n // Iterate over all nodes, creating layout nodes\n for (var i = 0; i < layoutInfo.nodeSize; i++) {\n var n = nodes[i];\n var nbb = n.boundingBox();\n\n var tempNode = {};\n tempNode.isLocked = n.locked();\n tempNode.id = n.data('id');\n tempNode.parentId = n.data('parent');\n tempNode.cmptId = id2cmptId[ n.id() ];\n tempNode.children = [];\n tempNode.positionX = n.position('x');\n tempNode.positionY = n.position('y');\n tempNode.offsetX = 0;\n tempNode.offsetY = 0;\n tempNode.height = nbb.w;\n tempNode.width = nbb.h;\n tempNode.maxX = tempNode.positionX + tempNode.width / 2;\n tempNode.minX = tempNode.positionX - tempNode.width / 2;\n tempNode.maxY = tempNode.positionY + tempNode.height / 2;\n tempNode.minY = tempNode.positionY - tempNode.height / 2;\n tempNode.padLeft = parseFloat( n.style('padding-left') );\n tempNode.padRight = parseFloat( n.style('padding-right') );\n tempNode.padTop = parseFloat( n.style('padding-top') );\n tempNode.padBottom = parseFloat( n.style('padding-bottom') );\n\n // forces\n tempNode.nodeRepulsion = is.fn( options.nodeRepulsion ) ? options.nodeRepulsion.call( n, n ) : options.nodeRepulsion;\n\n // Add new node\n layoutInfo.layoutNodes.push(tempNode);\n // Add entry to id-index map\n layoutInfo.idToIndex[tempNode.id] = i;\n }\n\n // Inline implementation of a queue, used for traversing the graph in BFS order\n var queue = [];\n var start = 0; // Points to the start the queue\n var end = -1; // Points to the end of the queue\n\n var tempGraph = [];\n\n // Second pass to add child information and\n // initialize queue for hierarchical traversal\n for (var i = 0; i < layoutInfo.nodeSize; i++) {\n var n = layoutInfo.layoutNodes[i];\n var p_id = n.parentId;\n // Check if node n has a parent node\n if (null != p_id) {\n // Add node Id to parent's list of children\n layoutInfo.layoutNodes[layoutInfo.idToIndex[p_id]].children.push(n.id);\n } else {\n // If a node doesn't have a parent, then it's in the root graph\n queue[++end] = n.id;\n tempGraph.push(n.id);\n }\n }\n\n // Add root graph to graphSet\n layoutInfo.graphSet.push(tempGraph);\n\n // Traverse the graph, level by level,\n while (start <= end) {\n // Get the node to visit and remove it from queue\n var node_id = queue[start++];\n var node_ix = layoutInfo.idToIndex[node_id];\n var node = layoutInfo.layoutNodes[node_ix];\n var children = node.children;\n if (children.length > 0) {\n // Add children nodes as a new graph to graph set\n layoutInfo.graphSet.push(children);\n // Add children to que queue to be visited\n for (var i = 0; i < children.length; i++) {\n queue[++end] = children[i];\n }\n }\n }\n\n // Create indexToGraph map\n for (var i = 0; i < layoutInfo.graphSet.length; i++) {\n var graph = layoutInfo.graphSet[i];\n for (var j = 0; j < graph.length; j++) {\n var index = layoutInfo.idToIndex[graph[j]];\n layoutInfo.indexToGraph[index] = i;\n }\n }\n\n // Iterate over all edges, creating Layout Edges\n for (var i = 0; i < layoutInfo.edgeSize; i++) {\n var e = edges[i];\n var tempEdge = {};\n tempEdge.id = e.data('id');\n tempEdge.sourceId = e.data('source');\n tempEdge.targetId = e.data('target');\n\n // Compute ideal length\n var idealLength = is.fn( options.idealEdgeLength ) ? options.idealEdgeLength.call( e, e ) : options.idealEdgeLength;\n var elasticity = is.fn( options.edgeElasticity ) ? options.edgeElasticity.call( e, e ) : options.edgeElasticity;\n\n // Check if it's an inter graph edge\n var sourceIx = layoutInfo.idToIndex[tempEdge.sourceId];\n var targetIx = layoutInfo.idToIndex[tempEdge.targetId];\n var sourceGraph = layoutInfo.indexToGraph[sourceIx];\n var targetGraph = layoutInfo.indexToGraph[targetIx];\n\n if (sourceGraph != targetGraph) {\n // Find lowest common graph ancestor\n var lca = findLCA(tempEdge.sourceId, tempEdge.targetId, layoutInfo);\n\n // Compute sum of node depths, relative to lca graph\n var lcaGraph = layoutInfo.graphSet[lca];\n var depth = 0;\n\n // Source depth\n var tempNode = layoutInfo.layoutNodes[sourceIx];\n while ( -1 === lcaGraph.indexOf(tempNode.id) ) {\n tempNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[tempNode.parentId]];\n depth++;\n }\n\n // Target depth\n tempNode = layoutInfo.layoutNodes[targetIx];\n while ( -1 === lcaGraph.indexOf(tempNode.id) ) {\n tempNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[tempNode.parentId]];\n depth++;\n }\n\n // logDebug('LCA of nodes ' + tempEdge.sourceId + ' and ' + tempEdge.targetId +\n // \". Index: \" + lca + \" Contents: \" + lcaGraph.toString() +\n // \". Depth: \" + depth);\n\n // Update idealLength\n idealLength *= depth * options.nestingFactor;\n }\n\n tempEdge.idealLength = idealLength;\n tempEdge.elasticity = elasticity;\n\n layoutInfo.layoutEdges.push(tempEdge);\n }\n\n // Finally, return layoutInfo object\n return layoutInfo;\n};\n\n\n/**\n * @brief : This function finds the index of the lowest common\n * graph ancestor between 2 nodes in the subtree\n * (from the graph hierarchy induced tree) whose\n * root is graphIx\n *\n * @arg node1: node1's ID\n * @arg node2: node2's ID\n * @arg layoutInfo: layoutInfo object\n *\n */\nvar findLCA = function(node1, node2, layoutInfo) {\n // Find their common ancester, starting from the root graph\n var res = findLCA_aux(node1, node2, 0, layoutInfo);\n if (2 > res.count) {\n // If aux function couldn't find the common ancester,\n // then it is the root graph\n return 0;\n } else {\n return res.graph;\n }\n};\n\n\n/**\n * @brief : Auxiliary function used for LCA computation\n *\n * @arg node1 : node1's ID\n * @arg node2 : node2's ID\n * @arg graphIx : subgraph index\n * @arg layoutInfo : layoutInfo object\n *\n * @return : object of the form {count: X, graph: Y}, where:\n * X is the number of ancesters (max: 2) found in\n * graphIx (and it's subgraphs),\n * Y is the graph index of the lowest graph containing\n * all X nodes\n */\nvar findLCA_aux = function(node1, node2, graphIx, layoutInfo) {\n var graph = layoutInfo.graphSet[graphIx];\n // If both nodes belongs to graphIx\n if (-1 < graph.indexOf(node1) && -1 < graph.indexOf(node2)) {\n return {count:2, graph:graphIx};\n }\n\n // Make recursive calls for all subgraphs\n var c = 0;\n for (var i = 0; i < graph.length; i++) {\n var nodeId = graph[i];\n var nodeIx = layoutInfo.idToIndex[nodeId];\n var children = layoutInfo.layoutNodes[nodeIx].children;\n\n // If the node has no child, skip it\n if (0 === children.length) {\n continue;\n }\n\n var childGraphIx = layoutInfo.indexToGraph[layoutInfo.idToIndex[children[0]]];\n var result = findLCA_aux(node1, node2, childGraphIx, layoutInfo);\n if (0 === result.count) {\n // Neither node1 nor node2 are present in this subgraph\n continue;\n } else if (1 === result.count) {\n // One of (node1, node2) is present in this subgraph\n c++;\n if (2 === c) {\n // We've already found both nodes, no need to keep searching\n break;\n }\n } else {\n // Both nodes are present in this subgraph\n return result;\n }\n }\n\n return {count:c, graph:graphIx};\n};\n\n\n/**\n * @brief: printsLayoutInfo into js console\n * Only used for debbuging\n */\nvar printLayoutInfo = function(layoutInfo) {\n /* jshint ignore:start */\n\n if (!DEBUG) {\n return;\n }\n console.debug(\"layoutNodes:\");\n for (var i = 0; i < layoutInfo.nodeSize; i++) {\n var n = layoutInfo.layoutNodes[i];\n var s =\n \"\\nindex: \" + i +\n \"\\nId: \" + n.id +\n \"\\nChildren: \" + n.children.toString() +\n \"\\nparentId: \" + n.parentId +\n \"\\npositionX: \" + n.positionX +\n \"\\npositionY: \" + n.positionY +\n \"\\nOffsetX: \" + n.offsetX +\n \"\\nOffsetY: \" + n.offsetY +\n \"\\npadLeft: \" + n.padLeft +\n \"\\npadRight: \" + n.padRight +\n \"\\npadTop: \" + n.padTop +\n \"\\npadBottom: \" + n.padBottom;\n\n console.debug(s);\n }\n\n console.debug('idToIndex');\n for (var i in layoutInfo.idToIndex) {\n console.debug(\"Id: \" + i + \"\\nIndex: \" + layoutInfo.idToIndex[i]);\n }\n\n console.debug('Graph Set');\n var set = layoutInfo.graphSet;\n for (var i = 0; i < set.length; i ++) {\n console.debug(\"Set : \" + i + \": \" + set[i].toString());\n }\n\n var s = 'IndexToGraph';\n for (var i = 0; i < layoutInfo.indexToGraph.length; i ++) {\n s += \"\\nIndex : \" + i + \" Graph: \"+ layoutInfo.indexToGraph[i];\n }\n console.debug(s);\n\n s = 'Layout Edges';\n for (var i = 0; i < layoutInfo.layoutEdges.length; i++) {\n var e = layoutInfo.layoutEdges[i];\n s += \"\\nEdge Index: \" + i + \" ID: \" + e.id +\n \" SouceID: \" + e.sourceId + \" TargetId: \" + e.targetId +\n \" Ideal Length: \" + e.idealLength;\n }\n console.debug(s);\n\n s = \"nodeSize: \" + layoutInfo.nodeSize;\n s += \"\\nedgeSize: \" + layoutInfo.edgeSize;\n s += \"\\ntemperature: \" + layoutInfo.temperature;\n console.debug(s);\n\n return;\n /* jshint ignore:end */\n};\n\n\n/**\n * @brief : Randomizes the position of all nodes\n */\nvar randomizePositions = function(layoutInfo, cy) {\n var width = layoutInfo.clientWidth;\n var height = layoutInfo.clientHeight;\n\n for (var i = 0; i < layoutInfo.nodeSize; i++) {\n var n = layoutInfo.layoutNodes[i];\n\n // No need to randomize compound nodes or locked nodes\n if ( 0 === n.children.length && !n.isLocked ) {\n n.positionX = Math.random() * width;\n n.positionY = Math.random() * height;\n }\n }\n};\n\n\n/**\n * @brief : Updates the positions of nodes in the network\n * @arg layoutInfo : LayoutInfo object\n * @arg cy : Cytoscape object\n * @arg options : Layout options\n */\nvar refreshPositions = function(layoutInfo, cy, options) {\n // var s = 'Refreshing positions';\n // logDebug(s);\n\n var layout = options.layout;\n var nodes = options.eles.nodes();\n var bb = layoutInfo.boundingBox;\n var coseBB = { x1: Infinity, x2: -Infinity, y1: Infinity, y2: -Infinity };\n\n if( options.boundingBox ){\n nodes.forEach(function( node ){\n var lnode = layoutInfo.layoutNodes[layoutInfo.idToIndex[node.data('id')]];\n\n coseBB.x1 = Math.min( coseBB.x1, lnode.positionX );\n coseBB.x2 = Math.max( coseBB.x2, lnode.positionX );\n\n coseBB.y1 = Math.min( coseBB.y1, lnode.positionY );\n coseBB.y2 = Math.max( coseBB.y2, lnode.positionY );\n });\n\n coseBB.w = coseBB.x2 - coseBB.x1;\n coseBB.h = coseBB.y2 - coseBB.y1;\n }\n\n nodes.positions(function(i, ele) {\n var lnode = layoutInfo.layoutNodes[layoutInfo.idToIndex[ele.data('id')]];\n // s = \"Node: \" + lnode.id + \". Refreshed position: (\" +\n // lnode.positionX + \", \" + lnode.positionY + \").\";\n // logDebug(s);\n\n if( options.boundingBox ){ // then add extra bounding box constraint\n var pctX = (lnode.positionX - coseBB.x1) / coseBB.w;\n var pctY = (lnode.positionY - coseBB.y1) / coseBB.h;\n\n return {\n x: bb.x1 + pctX * bb.w,\n y: bb.y1 + pctY * bb.h\n };\n } else {\n return {\n x: lnode.positionX,\n y: lnode.positionY\n };\n }\n });\n\n // Trigger layoutReady only on first call\n if (true !== layoutInfo.ready) {\n // s = 'Triggering layoutready';\n // logDebug(s);\n layoutInfo.ready = true;\n layout.one('layoutready', options.ready);\n layout.trigger({ type: 'layoutready', layout: this });\n }\n};\n\n/**\n * @brief : Logs a debug message in JS console, if DEBUG is ON\n */\n// var logDebug = function(text) {\n// if (DEBUG) {\n// console.debug(text);\n// }\n// };\n\nmodule.exports = CoseLayout;\n","'use strict';\n\nvar util = require('../../util');\nvar math = require('../../math');\n\nvar defaults = {\n fit: true, // whether to fit the viewport to the graph\n padding: 30, // padding used on fit\n boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space\n avoidOverlapPadding: 10, // extra spacing around nodes when avoidOverlap: true\n condense: false, // uses all available space on false, uses minimal space on true\n rows: undefined, // force num of rows in the grid\n cols: undefined, // force num of columns in the grid\n position: function( node ){}, // returns { row, col } for element\n sort: undefined, // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }\n animate: false, // whether to transition the node positions\n animationDuration: 500, // duration of animation in ms if enabled\n animationEasing: undefined, // easing of animation if enabled\n ready: undefined, // callback on layoutready\n stop: undefined // callback on layoutstop\n};\n\nfunction GridLayout( options ){\n this.options = util.extend({}, defaults, options);\n}\n\nGridLayout.prototype.run = function(){\n var params = this.options;\n var options = params;\n\n var cy = params.cy;\n var eles = options.eles;\n var nodes = eles.nodes().not(':parent');\n\n if( options.sort ){\n nodes = nodes.sort( options.sort );\n }\n\n var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n x1: 0, y1: 0, w: cy.width(), h: cy.height()\n } );\n\n if( bb.h === 0 || bb.w === 0){\n nodes.layoutPositions(this, options, function(){\n return { x: bb.x1, y: bb.y1 };\n });\n\n } else {\n\n // width/height * splits^2 = cells where splits is number of times to split width\n var cells = nodes.size();\n var splits = Math.sqrt( cells * bb.h/bb.w );\n var rows = Math.round( splits );\n var cols = Math.round( bb.w/bb.h * splits );\n\n var small = function(val){\n if( val == null ){\n return Math.min(rows, cols);\n } else {\n var min = Math.min(rows, cols);\n if( min == rows ){\n rows = val;\n } else {\n cols = val;\n }\n }\n };\n\n var large = function(val){\n if( val == null ){\n return Math.max(rows, cols);\n } else {\n var max = Math.max(rows, cols);\n if( max == rows ){\n rows = val;\n } else {\n cols = val;\n }\n }\n };\n\n var oRows = options.rows;\n var oCols = options.cols != null ? options.cols : options.columns;\n\n // if rows or columns were set in options, use those values\n if( oRows != null && oCols != null ){\n rows = oRows;\n cols = oCols;\n } else if( oRows != null && oCols == null ){\n rows = oRows;\n cols = Math.ceil( cells / rows );\n } else if( oRows == null && oCols != null ){\n cols = oCols;\n rows = Math.ceil( cells / cols );\n }\n\n // otherwise use the automatic values and adjust accordingly\n\n // if rounding was up, see if we can reduce rows or columns\n else if( cols * rows > cells ){\n var sm = small();\n var lg = large();\n\n // reducing the small side takes away the most cells, so try it first\n if( (sm - 1) * lg >= cells ){\n small(sm - 1);\n } else if( (lg - 1) * sm >= cells ){\n large(lg - 1);\n }\n } else {\n\n // if rounding was too low, add rows or columns\n while( cols * rows < cells ){\n var sm = small();\n var lg = large();\n\n // try to add to larger side first (adds less in multiplication)\n if( (lg + 1) * sm >= cells ){\n large(lg + 1);\n } else {\n small(sm + 1);\n }\n }\n }\n\n var cellWidth = bb.w / cols;\n var cellHeight = bb.h / rows;\n\n if( options.condense ){\n cellWidth = 0;\n cellHeight = 0;\n }\n\n if( options.avoidOverlap ){\n for( var i = 0; i < nodes.length; i++ ){\n var node = nodes[i];\n var pos = node._private.position;\n\n if( pos.x == null || pos.y == null ){ // for bb\n pos.x = 0;\n pos.y = 0;\n }\n\n var nbb = node.boundingBox();\n var p = options.avoidOverlapPadding;\n\n var w = nbb.w + p;\n var h = nbb.h + p;\n\n cellWidth = Math.max( cellWidth, w );\n cellHeight = Math.max( cellHeight, h );\n }\n }\n\n var cellUsed = {}; // e.g. 'c-0-2' => true\n\n var used = function(row, col){\n return cellUsed['c-' + row + '-' + col] ? true : false;\n };\n\n var use = function(row, col){\n cellUsed['c-' + row + '-' + col] = true;\n };\n\n // to keep track of current cell position\n var row = 0;\n var col = 0;\n var moveToNextCell = function(){\n col++;\n if( col >= cols ){\n col = 0;\n row++;\n }\n };\n\n // get a cache of all the manual positions\n var id2manPos = {};\n for( var i = 0; i < nodes.length; i++ ){\n var node = nodes[i];\n var rcPos = options.position( node );\n\n if( rcPos && (rcPos.row !== undefined || rcPos.col !== undefined) ){ // must have at least row or col def'd\n var pos = {\n row: rcPos.row,\n col: rcPos.col\n };\n\n if( pos.col === undefined ){ // find unused col\n pos.col = 0;\n\n while( used(pos.row, pos.col) ){\n pos.col++;\n }\n } else if( pos.row === undefined ){ // find unused row\n pos.row = 0;\n\n while( used(pos.row, pos.col) ){\n pos.row++;\n }\n }\n\n id2manPos[ node.id() ] = pos;\n use( pos.row, pos.col );\n }\n }\n\n var getPos = function(i, element){\n var x, y;\n\n if( element.locked() || element.isFullAutoParent() ){\n return false;\n }\n\n // see if we have a manual position set\n var rcPos = id2manPos[ element.id() ];\n if( rcPos ){\n x = rcPos.col * cellWidth + cellWidth/2 + bb.x1;\n y = rcPos.row * cellHeight + cellHeight/2 + bb.y1;\n\n } else { // otherwise set automatically\n\n while( used(row, col) ){\n moveToNextCell();\n }\n\n x = col * cellWidth + cellWidth/2 + bb.x1;\n y = row * cellHeight + cellHeight/2 + bb.y1;\n use( row, col );\n\n moveToNextCell();\n }\n\n return { x: x, y: y };\n\n };\n\n nodes.layoutPositions( this, options, getPos );\n }\n\n return this; // chaining\n\n};\n\nmodule.exports = GridLayout;\n","'use strict';\n\nmodule.exports = [\n { name: 'breadthfirst', impl: require('./breadthfirst') },\n { name: 'circle', impl: require('./circle') },\n { name: 'concentric',impl: require('./concentric') },\n { name: 'cose', impl: require('./cose') },\n { name: 'grid', impl: require('./grid') },\n { name: 'null', impl: require('./null') },\n { name: 'preset', impl: require('./preset') },\n { name: 'random', impl: require('./random') }\n];\n","'use strict';\n\nvar util = require('../../util');\n\n// default layout options\nvar defaults = {\n ready: function(){}, // on layoutready\n stop: function(){} // on layoutstop\n};\n\n// constructor\n// options : object containing layout options\nfunction NullLayout( options ){\n this.options = util.extend({}, defaults, options);\n}\n\n// runs the layout\nNullLayout.prototype.run = function(){\n var options = this.options;\n var eles = options.eles; // elements to consider in the layout\n var layout = this;\n\n // cy is automatically populated for us in the constructor\n var cy = options.cy; // jshint ignore:line\n\n layout.trigger('layoutstart');\n\n // puts all nodes at (0, 0)\n eles.nodes().positions(function(){\n return {\n x: 0,\n y: 0\n };\n });\n\n // trigger layoutready when each node has had its position set at least once\n layout.one('layoutready', options.ready);\n layout.trigger('layoutready');\n\n // trigger layoutstop when the layout stops (e.g. finishes)\n layout.one('layoutstop', options.stop);\n layout.trigger('layoutstop');\n\n return this; // chaining\n};\n\n// called on continuous layouts to stop them before they finish\nNullLayout.prototype.stop = function(){\n return this; // chaining\n};\n\nmodule.exports = NullLayout;\n","'use strict';\n\nvar util = require('../../util');\nvar is = require('../../is');\n\nvar defaults = {\n positions: undefined, // map of (node id) => (position obj); or function(node){ return somPos; }\n zoom: undefined, // the zoom level to set (prob want fit = false if set)\n pan: undefined, // the pan level to set (prob want fit = false if set)\n fit: true, // whether to fit to viewport\n padding: 30, // padding on fit\n animate: false, // whether to transition the node positions\n animationDuration: 500, // duration of animation in ms if enabled\n animationEasing: undefined, // easing of animation if enabled\n ready: undefined, // callback on layoutready\n stop: undefined // callback on layoutstop\n};\n\nfunction PresetLayout( options ){\n this.options = util.extend({}, defaults, options);\n}\n\nPresetLayout.prototype.run = function(){\n var options = this.options;\n var eles = options.eles;\n\n var nodes = eles.nodes();\n var posIsFn = is.fn( options.positions );\n\n function getPosition(node){\n if( options.positions == null ){\n return null;\n }\n\n if( posIsFn ){\n return options.positions.apply( node, [ node ] );\n }\n\n var pos = options.positions[node._private.data.id];\n\n if( pos == null ){\n return null;\n }\n\n return pos;\n }\n\n nodes.layoutPositions(this, options, function(i, node){\n var position = getPosition(node);\n\n if( node.locked() || position == null ){\n return false;\n }\n\n return position;\n });\n\n return this; // chaining\n};\n\nmodule.exports = PresetLayout;\n","'use strict';\n\nvar util = require('../../util');\nvar math = require('../../math');\n\nvar defaults = {\n fit: true, // whether to fit to viewport\n padding: 30, // fit padding\n boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }\n animate: false, // whether to transition the node positions\n animationDuration: 500, // duration of animation in ms if enabled\n animationEasing: undefined, // easing of animation if enabled\n ready: undefined, // callback on layoutready\n stop: undefined // callback on layoutstop\n};\n\nfunction RandomLayout( options ){\n this.options = util.extend({}, defaults, options);\n}\n\nRandomLayout.prototype.run = function(){\n var options = this.options;\n var cy = options.cy;\n var eles = options.eles;\n var nodes = eles.nodes().not(':parent');\n\n var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {\n x1: 0, y1: 0, w: cy.width(), h: cy.height()\n } );\n\n var getPos = function( i, node ){\n return {\n x: bb.x1 + Math.round( Math.random() * bb.w ),\n y: bb.y1 + Math.round( Math.random() * bb.h )\n };\n };\n\n nodes.layoutPositions( this, options, getPos );\n\n return this; // chaining\n};\n\nmodule.exports = RandomLayout;\n","'use strict';\n\nvar math = require('../../../math');\nvar is = require('../../../is');\nvar util = require('../../../util');\n\nvar BRp = {};\n\nBRp.arrowShapeHeight = 0.3;\n\nBRp.registerArrowShapes = function(){\n var arrowShapes = this.arrowShapes = {};\n var renderer = this;\n\n // Contract for arrow shapes:\n // 0, 0 is arrow tip\n // (0, 1) is direction towards node\n // (1, 0) is right\n //\n // functional api:\n // collide: check x, y in shape\n // roughCollide: called before collide, no false negatives\n // draw: draw\n // spacing: dist(arrowTip, nodeBoundary)\n // gap: dist(edgeTip, nodeBoundary), edgeTip may != arrowTip\n\n var bbCollide = function( x, y, size, angle, translation, padding ){\n var x1 = translation.x - size/2 - padding;\n var x2 = translation.x + size/2 + padding;\n var y1 = translation.y - size/2 - padding;\n var y2 = translation.y + size/2 + padding;\n\n var inside = (x1 <= x && x <= x2) && (y1 <= y && y <= y2);\n\n return inside;\n };\n\n var transform = function( x, y, size, angle, translation ){\n var xRotated = x * Math.cos(angle) - y * Math.sin(angle);\n var yRotated = x * Math.sin(angle) + y * Math.cos(angle);\n\n var xScaled = xRotated * size;\n var yScaled = yRotated * size;\n\n var xTranslated = xScaled + translation.x;\n var yTranslated = yScaled + translation.y;\n\n return {\n x: xTranslated,\n y: yTranslated\n };\n };\n\n var transformPoints = function( pts, size, angle, translation ){\n var retPts = [];\n\n for( var i = 0; i < pts.length; i += 2 ){\n var x = pts[i];\n var y = pts[i + 1];\n\n retPts.push( transform(x, y, size, angle, translation) );\n }\n\n return retPts;\n };\n\n var pointsToArr = function( pts ){\n var ret = [];\n\n for( var i = 0; i < pts.length; i++ ){\n var p = pts[i];\n\n ret.push( p.x, p.y );\n }\n\n return ret;\n };\n\n var defineArrowShape = function( name, defn ){\n if( is.string(defn) ){\n defn = arrowShapes[ defn ];\n }\n\n arrowShapes[ name ] = util.extend( {\n name: name,\n\n points: [\n -0.15, -0.3,\n 0.15, -0.3,\n 0.15, 0.3,\n -0.15, 0.3\n ],\n\n collide: function( x, y, size, angle, translation, padding ){\n var points = pointsToArr( transformPoints( this.points, size + 2*padding, angle, translation ) );\n var inside = math.pointInsidePolygonPoints( x, y, points );\n\n return inside;\n },\n\n roughCollide: bbCollide,\n\n draw: function( context, size, angle, translation ){\n var points = transformPoints( this.points, size, angle, translation );\n\n renderer.arrowShapeImpl('polygon')( context, points );\n },\n\n spacing: function( edge ){\n return 0;\n },\n\n gap: function( edge ){\n return edge._private.style['width'].pfValue * 2;\n }\n }, defn );\n };\n\n defineArrowShape( 'none', {\n collide: util.falsify,\n\n roughCollide: util.falsify,\n\n draw: util.noop,\n\n spacing: util.zeroify,\n\n gap: util.zeroify\n } );\n\n defineArrowShape( 'triangle', {\n points: [\n -0.15, -0.3,\n 0, 0,\n 0.15, -0.3\n ]\n } );\n\n defineArrowShape( 'arrow', 'triangle' );\n\n defineArrowShape( 'triangle-backcurve', {\n points: arrowShapes['triangle'].points,\n\n controlPoint: [ 0, -0.15 ],\n\n roughCollide: bbCollide,\n\n draw: function( context, size, angle, translation ){\n var ptsTrans = transformPoints( this.points, size, angle, translation );\n var ctrlPt = this.controlPoint;\n var ctrlPtTrans = transform( ctrlPt[0], ctrlPt[1], size, angle, translation );\n\n renderer.arrowShapeImpl( this.name )( context, ptsTrans, ctrlPtTrans );\n },\n\n gap: function( edge ){\n return edge._private.style['width'].pfValue;\n }\n } );\n\n\n defineArrowShape( 'triangle-tee', {\n points: [\n -0.15, -0.3,\n 0, 0,\n 0.15, -0.3,\n -0.15, -0.3\n ],\n\n pointsTee: [\n -0.15, -0.4,\n -0.15, -0.5,\n 0.15, -0.5,\n 0.15, -0.4\n ],\n\n collide: function( x, y, size, angle, translation, padding ){\n var triPts = pointsToArr( transformPoints( this.points, size + 2*padding, angle, translation ) );\n var teePts = pointsToArr( transformPoints( this.pointsTee, size + 2*padding, angle, translation ) );\n\n var inside = math.pointInsidePolygonPoints( x, y, triPts ) || math.pointInsidePolygonPoints( x, y, teePts );\n\n return inside;\n },\n\n draw: function( context, size, angle, translation ){\n var triPts = transformPoints( this.points, size, angle, translation );\n var teePts = transformPoints( this.pointsTee, size, angle, translation );\n\n renderer.arrowShapeImpl( this.name )( context, triPts, teePts );\n }\n } );\n\n defineArrowShape( 'vee', {\n points: [\n -0.15, -0.3,\n 0, 0,\n 0.15, -0.3,\n 0, -0.15\n ],\n\n gap: function( edge ){\n return edge._private.style['width'].pfValue;\n }\n } );\n\n defineArrowShape( 'half-triangle-overshot', {\n points: [\n 0, -0.25,\n -0.5, -0.25,\n 0.5, 0.25\n ],\n\n leavePathOpen: true,\n\n matchEdgeWidth: true\n } );\n\n defineArrowShape( 'circle', {\n radius: 0.15,\n\n collide: function( x, y, size, angle, translation, padding ){\n var t = translation;\n var inside = ( Math.pow(t.x - x, 2) + Math.pow(t.y - y, 2) <= Math.pow((size + 2*padding) * this.radius, 2) );\n\n return inside;\n },\n\n draw: function( context, size, angle, translation ){\n renderer.arrowShapeImpl( this.name )( context, translation.x, translation.y, this.radius * size );\n },\n\n spacing: function( edge ){\n return renderer.getArrowWidth(edge._private.style['width'].pfValue)\n * this.radius;\n }\n } );\n\n defineArrowShape( 'inhibitor', {\n points: [\n -0.25, 0,\n -0.25, -0.1,\n 0.25, -0.1,\n 0.25, 0\n ],\n\n spacing: function( edge ){\n return 1;\n },\n\n gap: function( edge ){\n return 1;\n }\n } );\n\n defineArrowShape( 'tee', 'inhibitor' );\n\n defineArrowShape( 'square', {\n points: [\n -0.15, 0.00,\n 0.15, 0.00,\n 0.15, -0.3,\n -0.15, -0.3\n ]\n } );\n\n defineArrowShape( 'diamond', {\n points: [\n -0.15, -0.15,\n 0, -0.3,\n 0.15, -0.15,\n 0, 0\n ],\n\n gap: function( edge ){\n return edge._private.style['width'].pfValue;\n }\n } );\n\n};\n\nmodule.exports = BRp;\n","'use strict';\n\nvar BRp = {};\n\nvar delEleCache = function( r ){\n r.eleEache = null;\n};\n\nvar getEleCache = function( r ){\n if( !r.eleEache ){\n r.eleEache = {\n nodes: r.cy.nodes(),\n edges: r.cy.edges()\n };\n }\n\n return r.eleEache;\n};\n\nBRp.getCachedElements = function(){\n return getEleCache( this );\n};\n\nBRp.getCachedNodes = function(){\n return getEleCache( this ).nodes;\n};\n\nBRp.getCachedEdges = function(){\n return getEleCache( this ).edges;\n};\n\nBRp.updateElementsCache = function(){\n var r = this;\n\n delEleCache( r );\n\n return getEleCache( r );\n};\n\nmodule.exports = BRp;\n","'use strict';\n\nvar math = require('../../../math');\nvar is = require('../../../is');\nvar zIndexSort = require('../../../collection/zsort');\n\nvar BRp = {};\n\n// Project mouse\nBRp.projectIntoViewport = function(clientX, clientY) {\n var offsets = this.findContainerClientCoords();\n var offsetLeft = offsets[0];\n var offsetTop = offsets[1];\n\n var x = clientX - offsetLeft;\n var y = clientY - offsetTop;\n\n x -= this.cy.pan().x; y -= this.cy.pan().y; x /= this.cy.zoom(); y /= this.cy.zoom();\n return [x, y];\n};\n\nBRp.findContainerClientCoords = function() {\n var container = this.container;\n\n var bb = this.containerBB = this.containerBB || container.getBoundingClientRect();\n\n return [bb.left, bb.top, bb.right - bb.left, bb.bottom - bb.top];\n};\n\nBRp.invalidateContainerClientCoordsCache = function(){\n this.containerBB = null;\n};\n\n// Find nearest element\nBRp.findNearestElement = function(x, y, visibleElementsOnly, isTouch){\n var self = this;\n var r = this;\n var eles = r.getCachedZSortedEles();\n var near = [];\n var zoom = r.cy.zoom();\n var hasCompounds = r.cy.hasCompoundNodes();\n var edgeThreshold = (isTouch ? 24 : 8) / zoom;\n var nodeThreshold = (isTouch ? 8 : 2) / zoom;\n var labelThreshold = (isTouch ? 8 : 2) / zoom;\n\n function checkNode(node){\n var _p = node._private;\n\n if( _p.style['events'].strValue === 'no' ){ return; }\n\n var width = node.outerWidth() + 2*nodeThreshold;\n var height = node.outerHeight() + 2*nodeThreshold;\n var hw = width/2;\n var hh = height/2;\n var pos = _p.position;\n\n if(\n pos.x - hw <= x && x <= pos.x + hw // bb check x\n &&\n pos.y - hh <= y && y <= pos.y + hh // bb check y\n ){\n var visible = !visibleElementsOnly || ( node.visible() && !node.transparent() );\n\n // exit early if invisible edge and must be visible\n if( visibleElementsOnly && !visible ){\n return;\n }\n\n var shape = r.nodeShapes[ self.getNodeShape(node) ];\n\n if(\n shape.checkPoint(x, y, 0, width, height, pos.x, pos.y)\n ){\n near.push( node );\n }\n\n }\n }\n\n function checkEdge(edge){\n var _p = edge._private;\n\n if( _p.style['events'].strValue === 'no' ){ return; }\n\n var rs = _p.rscratch;\n var style = _p.style;\n var width = style['width'].pfValue/2 + edgeThreshold; // more like a distance radius from centre\n var widthSq = width * width;\n var width2 = width * 2;\n var src = _p.source;\n var tgt = _p.target;\n var inEdgeBB = false;\n var sqDist;\n\n // exit early if invisible edge and must be visible\n var passedVisibilityCheck;\n var passesVisibilityCheck = function(){\n if( passedVisibilityCheck !== undefined ){\n return passedVisibilityCheck;\n }\n\n if( !visibleElementsOnly ){\n passedVisibilityCheck = true;\n return true;\n }\n\n var visible = edge.visible() && !edge.transparent();\n if( visible ){\n passedVisibilityCheck = true;\n return true;\n }\n\n passedVisibilityCheck = false;\n return false;\n };\n\n if( rs.edgeType === 'segments' || rs.edgeType === 'straight' || rs.edgeType === 'haystack' ){\n var pts = rs.allpts;\n\n for( var i = 0; i + 3 < pts.length; i += 2 ){\n if(\n (inEdgeBB = math.inLineVicinity(x, y, pts[i], pts[i+1], pts[i+2], pts[i+3], width2))\n && passesVisibilityCheck() &&\n widthSq > ( sqDist = math.sqDistanceToFiniteLine(x, y, pts[i], pts[i+1], pts[i+2], pts[i+3]) )\n ){\n near.push( edge );\n }\n }\n\n } else if( rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' ){\n var pts = rs.allpts;\n for( var i = 0; i + 5 < rs.allpts.length; i += 4 ){\n if(\n (inEdgeBB = math.inBezierVicinity(x, y, pts[i], pts[i+1], pts[i+2], pts[i+3], pts[i+4], pts[i+5], width2))\n && passesVisibilityCheck() &&\n (widthSq > (sqDist = math.sqDistanceToQuadraticBezier(x, y, pts[i], pts[i+1], pts[i+2], pts[i+3], pts[i+4], pts[i+5])) )\n ){\n near.push( edge );\n }\n }\n }\n\n // if we're close to the edge but didn't hit it, maybe we hit its arrows\n if( inEdgeBB && passesVisibilityCheck() && near.length === 0 || near[near.length - 1] !== edge ){\n var src = src || _p.source;\n var tgt = tgt || _p.target;\n\n var eWidth = style['width'].pfValue;\n var arSize = self.getArrowWidth( eWidth );\n\n var arrows = [\n { name: 'source', x: rs.arrowStartX, y: rs.arrowStartY, angle: rs.srcArrowAngle },\n { name: 'target', x: rs.arrowEndX, y: rs.arrowEndY, angle: rs.tgtArrowAngle },\n { name: 'mid-source', x: rs.midX, y: rs.midY, angle: rs.midsrcArrowAngle },\n { name: 'mid-target', x: rs.midX, y: rs.midY, angle: rs.midtgtArrowAngle }\n ];\n\n for( var i = 0; i < arrows.length; i++ ){\n var ar = arrows[i];\n var shape = r.arrowShapes[ style[ar.name+'-arrow-shape'].value ];\n\n if(\n shape.roughCollide(x, y, arSize, ar.angle, { x: ar.x, y: ar.y }, edgeThreshold)\n &&\n shape.collide(x, y, arSize, ar.angle, { x: ar.x, y: ar.y }, edgeThreshold)\n ){\n near.push( edge );\n break;\n }\n }\n }\n\n // for compound graphs, hitting edge may actually want a connected node instead (b/c edge may have greater z-index precedence)\n if( hasCompounds && near.length > 0 && near[ near.length - 1 ] === edge ){\n checkNode( src );\n checkNode( tgt );\n }\n }\n\n function checkLabel(ele){\n var _p = ele._private;\n var th = labelThreshold;\n\n if( _p.style['text-events'].strValue === 'no' ){ return; }\n\n // adjust bb w/ angle\n if( _p.group === 'edges' && _p.style['edge-text-rotation'].strValue === 'autorotate' ){\n\n var rstyle = _p.rstyle;\n var lw = rstyle.labelWidth + 2*th;\n var lh = rstyle.labelHeight + 2*th;\n var lx = rstyle.labelX;\n var ly = rstyle.labelY;\n\n var theta = _p.rscratch.labelAngle;\n var cos = Math.cos( theta );\n var sin = Math.sin( theta );\n\n var rotate = function( x, y ){\n x = x - lx;\n y = y - ly;\n\n return {\n x: x*cos - y*sin + lx,\n y: x*sin + y*cos + ly\n };\n };\n\n var lx1 = lx - lw/2;\n var lx2 = lx + lw/2;\n var ly1 = ly - lh/2;\n var ly2 = ly + lh/2;\n\n var px1y1 = rotate( lx1, ly1 );\n var px1y2 = rotate( lx1, ly2 );\n var px2y1 = rotate( lx2, ly1 );\n var px2y2 = rotate( lx2, ly2 );\n\n var points = [\n px1y1.x, px1y1.y,\n px2y1.x, px2y1.y,\n px2y2.x, px2y2.y,\n px1y2.x, px1y2.y\n ];\n\n if( math.pointInsidePolygonPoints( x, y, points ) ){\n near.push( ele );\n }\n\n } else {\n var bb = ele.boundingBox({\n includeLabels: true,\n includeNodes: false,\n includeEdges: false\n });\n\n // adjust bb w/ threshold\n bb.x1 -= th;\n bb.y1 -= th;\n bb.x2 += th;\n bb.y2 += th;\n bb.w = bb.x2 - bb.x1;\n bb.h = bb.y2 - bb.y1;\n\n if( math.inBoundingBox( bb, x, y ) ){\n near.push( ele );\n }\n }\n\n }\n\n for( var i = eles.length - 1; i >= 0; i-- ){ // reverse order for precedence\n var ele = eles[i];\n var _p = ele._private;\n\n if( near.length > 0 ){ break; } // since we check in z-order, first found is top and best result => exit early\n\n if( _p.group === 'nodes' ){\n checkNode( ele );\n\n } else { // then edge\n checkEdge( ele );\n }\n\n checkLabel( ele );\n\n }\n\n\n if( near.length > 0 ){\n return near[ near.length - 1 ];\n } else {\n return null;\n }\n};\n\n// 'Give me everything from this box'\nBRp.getAllInBox = function(x1, y1, x2, y2) {\n var nodes = this.getCachedNodes();\n var edges = this.getCachedEdges();\n var box = [];\n\n var x1c = Math.min(x1, x2);\n var x2c = Math.max(x1, x2);\n var y1c = Math.min(y1, y2);\n var y2c = Math.max(y1, y2);\n\n x1 = x1c;\n x2 = x2c;\n y1 = y1c;\n y2 = y2c;\n\n var boxBb = math.makeBoundingBox({\n x1: x1, y1: y1,\n x2: x2, y2: y2\n });\n\n for ( var i = 0; i < nodes.length; i++ ){\n var node = nodes[i];\n var nodeBb = node.boundingBox({\n includeNodes: true,\n includeEdges: false,\n includeLabels: false\n });\n\n if( math.boundingBoxesIntersect(boxBb, nodeBb) ){\n box.push(nodes[i]);\n }\n }\n\n for( var e = 0; e < edges.length; e++ ){\n var edge = edges[e];\n var _p = edge._private;\n var rs = _p.rscratch;\n\n if( rs.startX != null && rs.startY != null && !math.inBoundingBox( boxBb, rs.startX, rs.startY ) ){ continue; }\n if( rs.endX != null && rs.endY != null && !math.inBoundingBox( boxBb, rs.endX, rs.endY ) ){ continue; }\n\n if( rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' || rs.edgeType === 'segments' || rs.edgeType === 'haystack' ){\n\n var pts = _p.rstyle.bezierPts || _p.rstyle.linePts || _p.rstyle.haystackPts;\n var allInside = true;\n\n for( var i = 0; i < pts.length; i++ ){\n if( !math.pointInBoundingBox( boxBb, pts[i] ) ){\n allInside = false;\n break;\n }\n }\n\n if( allInside ){\n box.push( edge );\n }\n\n } else if( rs.edgeType === 'haystack' || rs.edgeType === 'straight' ){\n box.push( edge );\n }\n\n }\n\n return box;\n};\n\n\n/**\n * Returns the shape of the given node. If the height or width of the given node\n * is set to auto, the node is considered to be a compound.\n *\n * @param node a node\n * @return {String} shape of the node\n */\nBRp.getNodeShape = function( node ){\n var r = this;\n var style = node._private.style;\n var shape = style['shape'].value;\n\n if( node.isParent() ){\n if( shape === 'rectangle' || shape === 'roundrectangle' ){\n return shape;\n } else {\n return 'rectangle';\n }\n }\n\n if( shape === 'polygon' ){\n var points = style['shape-polygon-points'].value;\n\n return r.nodeShapes.makePolygon( points ).name;\n }\n\n return shape;\n};\n\nBRp.updateCachedZSortedEles = function(){\n this.getCachedZSortedEles( true );\n};\n\nBRp.getCachedZSortedEles = function( forceRecalc ){\n var lastNodes = this.lastZOrderCachedNodes;\n var lastEdges = this.lastZOrderCachedEdges;\n var nodes = this.getCachedNodes();\n var edges = this.getCachedEdges();\n var eles = [];\n\n if( forceRecalc || !lastNodes || !lastEdges || lastNodes !== nodes || lastEdges !== edges ){\n //console.time('cachezorder')\n\n for( var i = 0; i < nodes.length; i++ ){\n var n = nodes[i];\n\n if( n.animated() || (n.visible() && !n.transparent()) ){\n eles.push( n );\n }\n }\n\n for( var i = 0; i < edges.length; i++ ){\n var e = edges[i];\n\n if( e.animated() || (e.visible() && !e.transparent()) ){\n eles.push( e );\n }\n }\n\n eles.sort( zIndexSort );\n this.cachedZSortedEles = eles;\n //console.log('make cache')\n\n //console.timeEnd('cachezorder')\n } else {\n eles = this.cachedZSortedEles;\n //console.log('read cache')\n }\n\n this.lastZOrderCachedNodes = nodes;\n this.lastZOrderCachedEdges = edges;\n\n return eles;\n};\n\nfunction pushBezierPts(edge, pts){\n var qbezierAt = function( p1, p2, p3, t ){ return math.qbezierAt(p1, p2, p3, t); };\n var _p = edge._private;\n var bpts = _p.rstyle.bezierPts;\n\n bpts.push({\n x: qbezierAt( pts[0], pts[2], pts[4], 0.05 ),\n y: qbezierAt( pts[1], pts[3], pts[5], 0.05 )\n });\n\n bpts.push({\n x: qbezierAt( pts[0], pts[2], pts[4], 0.25 ),\n y: qbezierAt( pts[1], pts[3], pts[5], 0.25 )\n });\n\n bpts.push({\n x: qbezierAt( pts[0], pts[2], pts[4], 0.4 ),\n y: qbezierAt( pts[1], pts[3], pts[5], 0.4 )\n });\n\n bpts.push({\n x: qbezierAt( pts[0], pts[2], pts[4], 0.5 ),\n y: qbezierAt( pts[1], pts[3], pts[5], 0.5 )\n });\n\n bpts.push({\n x: qbezierAt( pts[0], pts[2], pts[4], 0.6 ),\n y: qbezierAt( pts[1], pts[3], pts[5], 0.6 )\n });\n\n bpts.push({\n x: qbezierAt( pts[0], pts[2], pts[4], 0.75 ),\n y: qbezierAt( pts[1], pts[3], pts[5], 0.75 )\n });\n\n bpts.push({\n x: qbezierAt( pts[0], pts[2], pts[4], 0.95 ),\n y: qbezierAt( pts[1], pts[3], pts[5], 0.95 )\n });\n}\n\nBRp.projectLines = function( edge ){\n var _p = edge._private;\n var rs = _p.rscratch;\n var et = rs.edgeType;\n\n if( et === 'multibezier' || et === 'bezier' || et === 'self' || et === 'compound' ){\n var bpts = _p.rstyle.bezierPts = []; // jshint ignore:line\n\n for( var i = 0; i + 5 < rs.allpts.length; i += 4 ){\n pushBezierPts( edge, rs.allpts.slice(i, i+6) );\n }\n } else if( et === 'segments' ){\n var lpts = _p.rstyle.linePts = [];\n\n for( var i = 0; i + 1 < rs.allpts.length; i += 2 ){\n lpts.push({\n x: rs.allpts[i],\n y: rs.allpts[i+1]\n });\n }\n } else if( et === 'haystack' ){\n var hpts = rs.haystackPts;\n\n _p.rstyle.haystackPts = [\n { x: hpts[0], y: hpts[1] },\n { x: hpts[2], y: hpts[3] }\n ];\n }\n};\n\nBRp.projectBezier = BRp.projectLines;\n\nBRp.recalculateNodeLabelProjection = function( node ){\n var content = node._private.style['label'].strValue;\n if( !content || content.match(/^\\s+$/) ){ return; }\n\n var textX, textY;\n var nodeWidth = node.outerWidth();\n var nodeHeight = node.outerHeight();\n var nodePos = node._private.position;\n var textHalign = node._private.style['text-halign'].strValue;\n var textValign = node._private.style['text-valign'].strValue;\n var rs = node._private.rscratch;\n var rstyle = node._private.rstyle;\n\n switch( textHalign ){\n case 'left':\n textX = nodePos.x - nodeWidth / 2;\n break;\n\n case 'right':\n textX = nodePos.x + nodeWidth / 2;\n break;\n\n default: // e.g. center\n textX = nodePos.x;\n }\n\n switch( textValign ){\n case 'top':\n textY = nodePos.y - nodeHeight / 2;\n break;\n\n case 'bottom':\n textY = nodePos.y + nodeHeight / 2;\n break;\n\n default: // e.g. middle\n textY = nodePos.y;\n }\n\n rs.labelX = textX;\n rs.labelY = textY;\n rstyle.labelX = textX;\n rstyle.labelY = textY;\n\n this.applyLabelDimensions( node );\n};\n\nBRp.recalculateEdgeLabelProjection = function( edge ){\n var content = edge._private.style['label'].strValue;\n if( !content || content.match(/^\\s+$/) ){ return; }\n\n var textX, textY;\n var _p = edge._private;\n var rs = _p.rscratch;\n //var style = _p.style;\n var rstyle = _p.rstyle;\n\n textX = rs.midX;\n textY = rs.midY;\n\n // add center point to style so bounding box calculations can use it\n rs.labelX = textX;\n rs.labelY = textY;\n rstyle.labelX = textX;\n rstyle.labelY = textY;\n\n this.applyLabelDimensions( edge );\n};\n\nBRp.applyLabelDimensions = function( ele ){\n var rs = ele._private.rscratch;\n var rstyle = ele._private.rstyle;\n\n var text = this.getLabelText( ele );\n var labelDims = this.calculateLabelDimensions( ele, text );\n\n rstyle.labelWidth = labelDims.width;\n rs.labelWidth = labelDims.width;\n\n rstyle.labelHeight = labelDims.height;\n rs.labelHeight = labelDims.height;\n};\n\nBRp.getLabelText = function( ele ){\n var style = ele._private.style;\n var text = ele._private.style['label'].strValue;\n var textTransform = style['text-transform'].value;\n var rscratch = ele._private.rscratch;\n\n if (textTransform == 'none') {\n } else if (textTransform == 'uppercase') {\n text = text.toUpperCase();\n } else if (textTransform == 'lowercase') {\n text = text.toLowerCase();\n }\n\n if( style['text-wrap'].value === 'wrap' ){\n //console.log('wrap');\n\n // save recalc if the label is the same as before\n if( rscratch.labelWrapKey === rscratch.labelKey ){\n // console.log('wrap cache hit');\n return rscratch.labelWrapCachedText;\n }\n // console.log('wrap cache miss');\n\n var lines = text.split('\\n');\n var maxW = style['text-max-width'].pfValue;\n var wrappedLines = [];\n\n for( var l = 0; l < lines.length; l++ ){\n var line = lines[l];\n var lineDims = this.calculateLabelDimensions( ele, line, 'line=' + line );\n var lineW = lineDims.width;\n\n if( lineW > maxW ){ // line is too long\n var words = line.split(/\\s+/); // NB: assume collapsed whitespace into single space\n var subline = '';\n\n for( var w = 0; w < words.length; w++ ){\n var word = words[w];\n var testLine = subline.length === 0 ? word : subline + ' ' + word;\n var testDims = this.calculateLabelDimensions( ele, testLine, 'testLine=' + testLine );\n var testW = testDims.width;\n\n if( testW <= maxW ){ // word fits on current line\n subline += word + ' ';\n } else { // word starts new line\n wrappedLines.push( subline );\n subline = word + ' ';\n }\n }\n\n // if there's remaining text, put it in a wrapped line\n if( !subline.match(/^\\s+$/) ){\n wrappedLines.push( subline );\n }\n } else { // line is already short enough\n wrappedLines.push( line );\n }\n } // for\n\n rscratch.labelWrapCachedLines = wrappedLines;\n rscratch.labelWrapCachedText = text = wrappedLines.join('\\n');\n rscratch.labelWrapKey = rscratch.labelKey;\n\n // console.log(text)\n } // if wrap\n\n return text;\n};\n\nBRp.calculateLabelDimensions = function( ele, text, extraKey ){\n var r = this;\n var style = ele._private.style;\n var fStyle = style['font-style'].strValue;\n var size = style['font-size'].pfValue + 'px';\n var family = style['font-family'].strValue;\n // var variant = style['font-variant'].strValue;\n var weight = style['font-weight'].strValue;\n\n var cacheKey = ele._private.labelKey;\n\n if( extraKey ){\n cacheKey += '$@$' + extraKey;\n }\n\n var cache = r.labelDimCache || (r.labelDimCache = {});\n\n if( cache[cacheKey] ){\n return cache[cacheKey];\n }\n\n var div = this.labelCalcDiv;\n\n if( !div ){\n div = this.labelCalcDiv = document.createElement('div');\n document.body.appendChild( div );\n }\n\n var ds = div.style;\n\n // from ele style\n ds.fontFamily = family;\n ds.fontStyle = fStyle;\n ds.fontSize = size;\n // ds.fontVariant = variant;\n ds.fontWeight = weight;\n\n // forced style\n ds.position = 'absolute';\n ds.left = '-9999px';\n ds.top = '-9999px';\n ds.zIndex = '-1';\n ds.visibility = 'hidden';\n ds.pointerEvents = 'none';\n ds.padding = '0';\n ds.lineHeight = '1';\n\n if( style['text-wrap'].value === 'wrap' ){\n ds.whiteSpace = 'pre'; // so newlines are taken into account\n } else {\n ds.whiteSpace = 'normal';\n }\n\n // put label content in div\n div.textContent = text;\n\n cache[cacheKey] = {\n width: div.clientWidth,\n height: div.clientHeight\n };\n\n return cache[cacheKey];\n};\n\nBRp.recalculateRenderedStyle = function( eles ){\n var edges = [];\n var nodes = [];\n var handledEdge = {};\n\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n var _p = ele._private;\n var style = _p.style;\n var rs = _p.rscratch;\n var rstyle = _p.rstyle;\n var id = _p.data.id;\n var bbStyleSame = rs.boundingBoxKey != null && _p.boundingBoxKey === rs.boundingBoxKey;\n var labelStyleSame = rs.labelKey != null && _p.labelKey === rs.labelKey;\n var styleSame = bbStyleSame && labelStyleSame;\n\n if( _p.group === 'nodes' ){\n var pos = _p.position;\n var posSame = rstyle.nodeX != null && rstyle.nodeY != null && pos.x === rstyle.nodeX && pos.y === rstyle.nodeY;\n var wSame = rstyle.nodeW != null && rstyle.nodeW === style['width'].pfValue;\n var hSame = rstyle.nodeH != null && rstyle.nodeH === style['height'].pfValue;\n\n if( !posSame || !styleSame || !wSame || !hSame ){\n nodes.push( ele );\n }\n\n rstyle.nodeX = pos.x;\n rstyle.nodeY = pos.y;\n rstyle.nodeW = style['width'].pfValue;\n rstyle.nodeH = style['height'].pfValue;\n } else { // edges\n\n var srcPos = _p.source._private.position;\n var tgtPos = _p.target._private.position;\n var srcSame = rstyle.srcX != null && rstyle.srcY != null && srcPos.x === rstyle.srcX && srcPos.y === rstyle.srcY;\n var tgtSame = rstyle.tgtX != null && rstyle.tgtY != null && tgtPos.x === rstyle.tgtX && tgtPos.y === rstyle.tgtY;\n var positionsSame = srcSame && tgtSame;\n\n if( !positionsSame || !styleSame ){\n if( rs.edgeType === 'bezier' || rs.edgeType === 'straight' || rs.edgeType === 'self' || rs.edgeType === 'compound' ){\n if( !handledEdge[ id ] ){\n edges.push( ele );\n handledEdge[ id ] = true;\n\n var parallelEdges = ele.parallelEdges();\n for( var i = 0; i < parallelEdges.length; i++ ){\n var pEdge = parallelEdges[i];\n var pId = pEdge._private.data.id;\n\n if( !handledEdge[ pId ] ){\n edges.push( pEdge );\n handledEdge[ pId ] = true;\n }\n\n }\n }\n } else {\n edges.push( ele );\n }\n } // if positions diff\n\n // update rstyle positions\n rstyle.srcX = srcPos.x;\n rstyle.srcY = srcPos.y;\n rstyle.tgtX = tgtPos.x;\n rstyle.tgtY = tgtPos.y;\n\n } // if edges\n\n rs.boundingBoxKey = _p.boundingBoxKey;\n rs.labelKey = _p.labelKey;\n }\n\n this.recalculateEdgeProjections( edges );\n this.recalculateLabelProjections( nodes, edges );\n};\n\nBRp.recalculateLabelProjections = function( nodes, edges ){\n for( var i = 0; i < nodes.length; i++ ){\n this.recalculateNodeLabelProjection( nodes[i] );\n }\n\n for( var i = 0; i < edges.length; i++ ){\n this.recalculateEdgeLabelProjection( edges[i] );\n }\n};\n\nBRp.recalculateEdgeProjections = function( edges ){\n this.findEdgeControlPoints( edges );\n};\n\n\n// Find edge control points\nBRp.findEdgeControlPoints = function(edges) {\n if( !edges || edges.length === 0 ){ return; }\n\n var r = this;\n var cy = r.cy;\n var hasCompounds = cy.hasCompoundNodes();\n var hashTable = {};\n var pairIds = [];\n var haystackEdges = [];\n var autorotateEdges = [];\n\n // create a table of edge (src, tgt) => list of edges between them\n var pairId;\n for (var i = 0; i < edges.length; i++){\n var edge = edges[i];\n var _p = edge._private;\n var data = _p.data;\n var style = _p.style;\n var curveStyle = style['curve-style'].value;\n var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments';\n\n // ignore edges who are not to be displayed\n // they shouldn't take up space\n if( style.display.value === 'none' ){\n continue;\n }\n\n if( style['edge-text-rotation'].strValue === 'autorotate' ){\n autorotateEdges.push( edge );\n }\n\n if( curveStyle === 'haystack' ){\n haystackEdges.push( edge );\n continue;\n }\n\n var srcId = data.source;\n var tgtId = data.target;\n\n pairId = srcId > tgtId ?\n tgtId + '$-$' + srcId :\n srcId + '$-$' + tgtId ;\n\n if( edgeIsUnbundled ){\n pairId = 'unbundled' + '$-$' + data.id;\n }\n\n if( hashTable[pairId] == null ){\n hashTable[pairId] = [];\n pairIds.push( pairId );\n }\n\n hashTable[pairId].push( edge );\n\n if( edgeIsUnbundled ){\n hashTable[pairId].hasUnbundled = true;\n }\n }\n\n var src, tgt, src_p, tgt_p, srcPos, tgtPos, srcW, srcH, tgtW, tgtH, srcShape, tgtShape;\n var vectorNormInverse;\n var badBezier;\n\n // for each pair (src, tgt), create the ctrl pts\n // Nested for loop is OK; total number of iterations for both loops = edgeCount\n for (var p = 0; p < pairIds.length; p++) {\n pairId = pairIds[p];\n var pairEdges = hashTable[pairId];\n\n // for each pair id, the edges should be sorted by index\n pairEdges.sort(function(edge1, edge2){\n return edge1._private.index - edge2._private.index;\n });\n\n src = pairEdges[0]._private.source;\n tgt = pairEdges[0]._private.target;\n\n src_p = src._private;\n tgt_p = tgt._private;\n\n // make sure src/tgt distinction is consistent\n // (src/tgt in this case are just for ctrlpts and don't actually have to be true src/tgt)\n if( src_p.data.id > tgt_p.data.id ){\n var temp = src;\n src = tgt;\n tgt = temp;\n }\n\n srcPos = src_p.position;\n tgtPos = tgt_p.position;\n\n srcW = src.outerWidth();\n srcH = src.outerHeight();\n\n tgtW = tgt.outerWidth();\n tgtH = tgt.outerHeight();\n\n srcShape = r.nodeShapes[ this.getNodeShape(src) ];\n tgtShape = r.nodeShapes[ this.getNodeShape(tgt) ];\n\n badBezier = false;\n\n\n if( (pairEdges.length > 1 && src !== tgt) || pairEdges.hasUnbundled ){\n\n // pt outside src shape to calc distance/displacement from src to tgt\n var srcOutside = srcShape.intersectLine(\n srcPos.x,\n srcPos.y,\n srcW,\n srcH,\n tgtPos.x,\n tgtPos.y,\n 0\n );\n\n // pt outside tgt shape to calc distance/displacement from src to tgt\n var tgtOutside = tgtShape.intersectLine(\n tgtPos.x,\n tgtPos.y,\n tgtW,\n tgtH,\n srcPos.x,\n srcPos.y,\n 0\n );\n\n var midptSrcPts = {\n x1: srcOutside[0],\n x2: tgtOutside[0],\n y1: srcOutside[1],\n y2: tgtOutside[1]\n };\n\n var dy = ( tgtOutside[1] - srcOutside[1] );\n var dx = ( tgtOutside[0] - srcOutside[0] );\n var l = Math.sqrt( dx*dx + dy*dy );\n\n var vector = {\n x: dx,\n y: dy\n };\n\n var vectorNorm = {\n x: vector.x/l,\n y: vector.y/l\n };\n vectorNormInverse = {\n x: -vectorNorm.y,\n y: vectorNorm.x\n };\n\n\n // if src intersection is inside tgt or tgt intersection is inside src, then no ctrl pts to draw\n if(\n tgtShape.checkPoint( srcOutside[0], srcOutside[1], 0, tgtW, tgtH, tgtPos.x, tgtPos.y ) ||\n srcShape.checkPoint( tgtOutside[0], tgtOutside[1], 0, srcW, srcH, srcPos.x, srcPos.y )\n ){\n vectorNormInverse = {};\n badBezier = true;\n }\n\n }\n\n var edge;\n var edge_p;\n var rs;\n\n for (var i = 0; i < pairEdges.length; i++) {\n edge = pairEdges[i];\n edge_p = edge._private;\n rs = edge_p.rscratch;\n\n var edgeIndex1 = rs.lastEdgeIndex;\n var edgeIndex2 = i;\n\n var numEdges1 = rs.lastNumEdges;\n var numEdges2 = pairEdges.length;\n\n var eStyle = edge_p.style;\n var style = eStyle;\n var curveStyle = eStyle['curve-style'].value;\n var ctrlptDists = eStyle['control-point-distances'];\n var ctrlptWs = eStyle['control-point-weights'];\n var bezierN = ctrlptDists && ctrlptWs ? Math.min( ctrlptDists.value.length, ctrlptWs.value.length ) : 1;\n var stepSize = eStyle['control-point-step-size'].pfValue;\n var ctrlptDist = ctrlptDists !== undefined ? ctrlptDists.pfValue[0] : undefined;\n var ctrlptWeight = ctrlptWs.value[0];\n var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments';\n\n var swappedDirection = edge_p.source !== src;\n\n if( swappedDirection && edgeIsUnbundled ){\n ctrlptDist *= -1;\n }\n\n var srcX1 = rs.lastSrcCtlPtX;\n var srcX2 = srcPos.x;\n var srcY1 = rs.lastSrcCtlPtY;\n var srcY2 = srcPos.y;\n var srcW1 = rs.lastSrcCtlPtW;\n var srcW2 = src.outerWidth();\n var srcH1 = rs.lastSrcCtlPtH;\n var srcH2 = src.outerHeight();\n\n var tgtX1 = rs.lastTgtCtlPtX;\n var tgtX2 = tgtPos.x;\n var tgtY1 = rs.lastTgtCtlPtY;\n var tgtY2 = tgtPos.y;\n var tgtW1 = rs.lastTgtCtlPtW;\n var tgtW2 = tgt.outerWidth();\n var tgtH1 = rs.lastTgtCtlPtH;\n var tgtH2 = tgt.outerHeight();\n\n var width1 = rs.lastW;\n var width2 = eStyle['control-point-step-size'].pfValue;\n\n if( badBezier ){\n rs.badBezier = true;\n } else {\n rs.badBezier = false;\n }\n\n if( srcX1 === srcX2 && srcY1 === srcY2 && srcW1 === srcW2 && srcH1 === srcH2\n && tgtX1 === tgtX2 && tgtY1 === tgtY2 && tgtW1 === tgtW2 && tgtH1 === tgtH2\n && width1 === width2\n && ((edgeIndex1 === edgeIndex2 && numEdges1 === numEdges2) || edgeIsUnbundled) ){\n // console.log('edge ctrl pt cache HIT')\n continue; // then the control points haven't changed and we can skip calculating them\n } else {\n rs.lastSrcCtlPtX = srcX2;\n rs.lastSrcCtlPtY = srcY2;\n rs.lastSrcCtlPtW = srcW2;\n rs.lastSrcCtlPtH = srcH2;\n rs.lastTgtCtlPtX = tgtX2;\n rs.lastTgtCtlPtY = tgtY2;\n rs.lastTgtCtlPtW = tgtW2;\n rs.lastTgtCtlPtH = tgtH2;\n rs.lastEdgeIndex = edgeIndex2;\n rs.lastNumEdges = numEdges2;\n rs.lastWidth = width2;\n // console.log('edge ctrl pt cache MISS')\n }\n\n if( src === tgt ){\n // Self-edge\n\n rs.edgeType = 'self';\n\n var j = i;\n var loopDist = stepSize;\n\n if( edgeIsUnbundled ){\n j = 0;\n loopDist = ctrlptDist;\n }\n\n rs.ctrlpts = [\n srcPos.x,\n srcPos.y - (1 + Math.pow(srcH, 1.12) / 100) * loopDist * (j / 3 + 1),\n\n srcPos.x - (1 + Math.pow(srcW, 1.12) / 100) * loopDist * (j / 3 + 1),\n srcPos.y\n ];\n\n } else if(\n hasCompounds &&\n ( src.isParent() || src.isChild() || tgt.isParent() || tgt.isChild() ) &&\n ( src.parents().anySame(tgt) || tgt.parents().anySame(src) )\n ){\n // Compound edge\n\n rs.edgeType = 'compound';\n\n // because the line approximation doesn't apply for compound beziers\n // (loop/self edges are already elided b/c of cheap src==tgt check)\n rs.badBezier = false;\n\n var j = i;\n var loopDist = stepSize;\n\n if( edgeIsUnbundled ){\n j = 0;\n loopDist = ctrlptDist;\n }\n\n var loopW = 50;\n\n var loopaPos = {\n x: srcPos.x - srcW/2,\n y: srcPos.y - srcH/2\n };\n\n var loopbPos = {\n x: tgtPos.x - tgtW/2,\n y: tgtPos.y - tgtH/2\n };\n\n var loopPos = {\n x: Math.min( loopaPos.x, loopbPos.x ),\n y: Math.min( loopaPos.y, loopbPos.y )\n };\n\n // avoids cases with impossible beziers\n var minCompoundStretch = 0.5;\n var compoundStretchA = Math.max( minCompoundStretch, Math.log(srcW * 0.01) );\n var compoundStretchB = Math.max( minCompoundStretch, Math.log(tgtW * 0.01) );\n\n rs.ctrlpts = [\n loopPos.x,\n loopPos.y - (1 + Math.pow(loopW, 1.12) / 100) * loopDist * (j / 3 + 1) * compoundStretchA,\n\n loopPos.x - (1 + Math.pow(loopW, 1.12) / 100) * loopDist * (j / 3 + 1) * compoundStretchB,\n loopPos.y\n ];\n\n } else if( curveStyle === 'segments' ){\n // Segments (multiple straight lines)\n\n rs.edgeType = 'segments';\n rs.segpts = [];\n\n var segmentWs = eStyle['segment-weights'].pfValue;\n var segmentDs = eStyle['segment-distances'].pfValue;\n var segmentsN = Math.min( segmentWs.length, segmentDs.length );\n\n for( var s = 0; s < segmentsN; s++ ){\n var w = segmentWs[s];\n var d = segmentDs[s];\n\n // d = swappedDirection ? -d : d;\n //\n // d = Math.abs(d);\n\n // var w1 = !swappedDirection ? (1 - w) : w;\n // var w2 = !swappedDirection ? w : (1 - w);\n\n var w1 = (1 - w);\n var w2 = w;\n\n var adjustedMidpt = {\n x: midptSrcPts.x1 * w1 + midptSrcPts.x2 * w2,\n y: midptSrcPts.y1 * w1 + midptSrcPts.y2 * w2\n };\n\n rs.segpts.push(\n adjustedMidpt.x + vectorNormInverse.x * d,\n adjustedMidpt.y + vectorNormInverse.y * d\n );\n }\n\n // Straight edge\n } else if (\n pairEdges.length % 2 === 1\n && i === Math.floor(pairEdges.length / 2)\n && !edgeIsUnbundled\n ){\n\n rs.edgeType = 'straight';\n\n } else {\n // (Multi)bezier\n\n var multi = edgeIsUnbundled;\n\n rs.edgeType = multi ? 'multibezier' : 'bezier';\n rs.ctrlpts = [];\n\n for( var b = 0; b < bezierN; b++ ){\n var normctrlptDist = (0.5 - pairEdges.length / 2 + i) * stepSize;\n var manctrlptDist;\n var sign = math.signum( normctrlptDist );\n\n if( multi ){\n ctrlptDist = ctrlptDists ? ctrlptDists.pfValue[b] : stepSize; // fall back on step size\n ctrlptWeight = ctrlptWs.value[b];\n }\n\n if( edgeIsUnbundled ){ // multi or single unbundled\n manctrlptDist = ctrlptDist;\n } else {\n manctrlptDist = ctrlptDist !== undefined ? sign * ctrlptDist : undefined;\n }\n\n var distanceFromMidpoint = manctrlptDist !== undefined ? manctrlptDist : normctrlptDist;\n\n var w1 = !swappedDirection || edgeIsUnbundled ? (1 - ctrlptWeight) : ctrlptWeight;\n var w2 = !swappedDirection || edgeIsUnbundled ? ctrlptWeight : (1 - ctrlptWeight);\n\n var adjustedMidpt = {\n x: midptSrcPts.x1 * w1 + midptSrcPts.x2 * w2,\n y: midptSrcPts.y1 * w1 + midptSrcPts.y2 * w2\n };\n\n rs.ctrlpts.push(\n adjustedMidpt.x + vectorNormInverse.x * distanceFromMidpoint,\n adjustedMidpt.y + vectorNormInverse.y * distanceFromMidpoint\n );\n }\n\n }\n\n // find endpts for edge\n this.findEndpoints( edge );\n\n var badStart = !is.number( rs.startX ) || !is.number( rs.startY );\n var badAStart = !is.number( rs.arrowStartX ) || !is.number( rs.arrowStartY );\n var badEnd = !is.number( rs.endX ) || !is.number( rs.endY );\n var badAEnd = !is.number( rs.arrowEndX ) || !is.number( rs.arrowEndY );\n\n var minCpADistFactor = 3;\n var arrowW = this.getArrowWidth( eStyle['width'].pfValue ) * this.arrowShapeHeight;\n var minCpADist = minCpADistFactor * arrowW;\n\n if( rs.edgeType === 'bezier' ){\n var startACpDist = math.distance( { x: rs.ctrlpts[0], y: rs.ctrlpts[1] }, { x: rs.startX, y: rs.startY } );\n var closeStartACp = startACpDist < minCpADist;\n var endACpDist = math.distance( { x: rs.ctrlpts[0], y: rs.ctrlpts[1] }, { x: rs.endX, y: rs.endY } );\n var closeEndACp = endACpDist < minCpADist;\n\n var overlapping = false;\n\n if( badStart || badAStart || closeStartACp ){\n overlapping = true;\n\n // project control point along line from src centre to outside the src shape\n // (otherwise intersection will yield nothing)\n var cpD = { // delta\n x: rs.ctrlpts[0] - srcPos.x,\n y: rs.ctrlpts[1] - srcPos.y\n };\n var cpL = Math.sqrt( cpD.x*cpD.x + cpD.y*cpD.y ); // length of line\n var cpM = { // normalised delta\n x: cpD.x / cpL,\n y: cpD.y / cpL\n };\n var radius = Math.max(srcW, srcH);\n var cpProj = { // *2 radius guarantees outside shape\n x: rs.ctrlpts[0] + cpM.x * 2 * radius,\n y: rs.ctrlpts[1] + cpM.y * 2 * radius\n };\n\n var srcCtrlPtIntn = srcShape.intersectLine(\n srcPos.x,\n srcPos.y,\n srcW,\n srcH,\n cpProj.x,\n cpProj.y,\n 0\n );\n\n if( closeStartACp ){\n rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - startACpDist);\n rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - startACpDist);\n } else {\n rs.ctrlpts[0] = srcCtrlPtIntn[0] + cpM.x * minCpADist;\n rs.ctrlpts[1] = srcCtrlPtIntn[1] + cpM.y * minCpADist;\n }\n }\n\n if( badEnd || badAEnd || closeEndACp ){\n overlapping = true;\n\n // project control point along line from tgt centre to outside the tgt shape\n // (otherwise intersection will yield nothing)\n var cpD = { // delta\n x: rs.ctrlpts[0] - tgtPos.x,\n y: rs.ctrlpts[1] - tgtPos.y\n };\n var cpL = Math.sqrt( cpD.x*cpD.x + cpD.y*cpD.y ); // length of line\n var cpM = { // normalised delta\n x: cpD.x / cpL,\n y: cpD.y / cpL\n };\n var radius = Math.max(srcW, srcH);\n var cpProj = { // *2 radius guarantees outside shape\n x: rs.ctrlpts[0] + cpM.x * 2 * radius,\n y: rs.ctrlpts[1] + cpM.y * 2 * radius\n };\n\n var tgtCtrlPtIntn = tgtShape.intersectLine(\n tgtPos.x,\n tgtPos.y,\n tgtW,\n tgtH,\n cpProj.x,\n cpProj.y,\n 0\n );\n\n if( closeEndACp ){\n rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - endACpDist);\n rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - endACpDist);\n } else {\n rs.ctrlpts[0] = tgtCtrlPtIntn[0] + cpM.x * minCpADist;\n rs.ctrlpts[1] = tgtCtrlPtIntn[1] + cpM.y * minCpADist;\n }\n\n }\n\n if( overlapping ){\n // recalc endpts\n this.findEndpoints( edge );\n }\n\n }\n\n if( rs.edgeType === 'multibezier' || rs.edgeType === 'bezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' ){\n rs.allpts = [];\n\n rs.allpts.push( rs.startX, rs.startY );\n\n for( var b = 0; b+1 < rs.ctrlpts.length; b += 2 ){\n // ctrl pt itself\n rs.allpts.push( rs.ctrlpts[b], rs.ctrlpts[b+1] );\n\n // the midpt between ctrlpts as intermediate destination pts\n if( b + 3 < rs.ctrlpts.length ){\n rs.allpts.push( (rs.ctrlpts[b] + rs.ctrlpts[b+2])/2, (rs.ctrlpts[b+1] + rs.ctrlpts[b+3])/2 );\n }\n }\n\n rs.allpts.push( rs.endX, rs.endY );\n\n var m, mt;\n if( rs.edgeType === 'bezier' ){\n rs.midX = math.qbezierAt( rs.arrowStartX, rs.ctrlpts[0], rs.arrowEndX, 0.5 );\n rs.midY = math.qbezierAt( rs.arrowStartY, rs.ctrlpts[1], rs.arrowEndY, 0.5 );\n } else if( rs.ctrlpts.length/2 % 2 === 0 ){\n m = rs.allpts.length/2 - 1;\n\n rs.midX = rs.allpts[m];\n rs.midY = rs.allpts[m+1];\n } else {\n m = rs.allpts.length/2 - 3;\n mt = 0.5;\n\n rs.midX = math.qbezierAt( rs.allpts[m], rs.allpts[m+2], rs.allpts[m+4], mt );\n rs.midY = math.qbezierAt( rs.allpts[m+1], rs.allpts[m+3], rs.allpts[m+5], mt );\n }\n\n } else if( rs.edgeType === 'straight' ){\n // need to calc these after endpts\n rs.allpts = [ rs.startX, rs.startY, rs.endX, rs.endY ];\n\n // default midpt for labels etc\n rs.midX = ( rs.arrowStartX + rs.arrowEndX )/2;\n rs.midY = ( rs.arrowStartY + rs.arrowEndY )/2;\n\n } else if( rs.edgeType === 'segments' ){\n rs.allpts = [];\n rs.allpts.push( rs.startX, rs.startY );\n rs.allpts.push.apply( rs.allpts, rs.segpts );\n rs.allpts.push( rs.endX, rs.endY );\n\n if( rs.segpts.length % 4 === 0 ){\n var i2 = rs.segpts.length / 2;\n var i1 = i2 - 2;\n\n rs.midX = ( rs.segpts[i1] + rs.segpts[i2] ) / 2;\n rs.midY = ( rs.segpts[i1+1] + rs.segpts[i2+1] ) / 2;\n } else {\n var i1 = rs.segpts.length / 2 - 1;\n\n rs.midX = rs.segpts[i1];\n rs.midY = rs.segpts[i1+1];\n }\n\n\n }\n\n this.projectLines( edge );\n this.calculateArrowAngles( edge );\n this.recalculateEdgeLabelProjection( edge );\n\n }\n }\n\n for( var i = 0; i < haystackEdges.length; i++ ){\n var edge = haystackEdges[i];\n var _p = edge._private;\n var style = _p.style;\n var rscratch = _p.rscratch;\n var rs = rscratch;\n\n if( !rscratch.haystack ){\n var angle = Math.random() * 2 * Math.PI;\n\n rscratch.source = {\n x: Math.cos(angle),\n y: Math.sin(angle)\n };\n\n var angle = Math.random() * 2 * Math.PI;\n\n rscratch.target = {\n x: Math.cos(angle),\n y: Math.sin(angle)\n };\n\n }\n\n var src = _p.source;\n var tgt = _p.target;\n var srcPos = src._private.position;\n var tgtPos = tgt._private.position;\n var srcW = src.width();\n var tgtW = tgt.width();\n var srcH = src.height();\n var tgtH = tgt.height();\n var radius = style['haystack-radius'].value;\n var halfRadius = radius/2; // b/c have to half width/height\n\n rs.haystackPts = rs.allpts = [\n rs.source.x * srcW * halfRadius + srcPos.x,\n rs.source.y * srcH * halfRadius + srcPos.y,\n rs.target.x * tgtW * halfRadius + tgtPos.x,\n rs.target.y * tgtH * halfRadius + tgtPos.y\n ];\n\n rs.midX = (rs.allpts[0] + rs.allpts[2])/2;\n rs.midY = (rs.allpts[1] + rs.allpts[3])/2;\n\n // always override as haystack in case set to different type previously\n rscratch.edgeType = 'haystack';\n rscratch.haystack = true;\n\n this.projectLines( edge );\n this.calculateArrowAngles( edge );\n this.recalculateEdgeLabelProjection( edge );\n }\n\n for( var i = 0 ; i < autorotateEdges.length; i++ ){\n var edge = autorotateEdges[i];\n var rs = edge._private.rscratch;\n\n rs.labelAngle = Math.atan( rs.midDispY / rs.midDispX );\n }\n\n return hashTable;\n};\n\nvar getAngleFromDisp = function( dispX, dispY ){\n return Math.atan2( dispY, dispX ) - Math.PI/2;\n};\n\nBRp.calculateArrowAngles = function( edge ){\n var rs = edge._private.rscratch;\n var isHaystack = rs.edgeType === 'haystack';\n var isMultibezier = rs.edgeType === 'multibezier';\n var isSegments = rs.edgeType === 'segments';\n var isCompound = rs.edgeType === 'compound';\n var isSelf = rs.edgeType === 'self';\n\n // Displacement gives direction for arrowhead orientation\n var dispX, dispY;\n var startX, startY, endX, endY;\n\n var srcPos = edge.source().position();\n var tgtPos = edge.target().position();\n\n if( isHaystack ){\n startX = rs.haystackPts[0];\n startY = rs.haystackPts[1];\n endX = rs.haystackPts[2];\n endY = rs.haystackPts[3];\n } else {\n startX = rs.arrowStartX;\n startY = rs.arrowStartY;\n endX = rs.arrowEndX;\n endY = rs.arrowEndY;\n }\n\n // source\n //\n\n dispX = srcPos.x - startX;\n dispY = srcPos.y - startY;\n\n rs.srcArrowAngle = getAngleFromDisp( dispX, dispY );\n\n // mid target\n //\n\n var midX = rs.midX;\n var midY = rs.midY;\n\n if( isHaystack ){\n midX = ( startX + endX )/2;\n midY = ( startY + endY )/2;\n }\n\n dispX = endX - startX;\n dispY = endY - startY;\n\n if( isSelf ){\n dispX = -1;\n dispY = 1;\n } else if( isSegments ){\n var pts = rs.allpts;\n\n if( pts.length / 2 % 2 === 0 ){\n var i2 = pts.length / 2;\n var i1 = i2 - 2;\n\n dispX = ( pts[i2] - pts[i1] );\n dispY = ( pts[i2+1] - pts[i1+1] );\n } else {\n var i2 = pts.length / 2 - 1;\n var i1 = i2 - 2;\n var i3 = i2 + 2;\n\n dispX = ( pts[i2] - pts[i1] );\n dispY = ( pts[i2+1] - pts[i1+1] );\n }\n } else if( isMultibezier || isCompound ){\n var pts = rs.allpts;\n var cpts = rs.ctrlpts;\n var bp0x, bp0y;\n var bp1x, bp1y;\n\n if( cpts.length / 2 % 2 === 0 ){\n var p0 = pts.length / 2 - 1; // startpt\n var ic = p0 + 2;\n var p1 = ic + 2;\n\n bp0x = math.qbezierAt( pts[p0], pts[ic], pts[p1], 0.0 );\n bp0y = math.qbezierAt( pts[p0+1], pts[ic+1], pts[p1+1], 0.0 );\n\n bp1x = math.qbezierAt( pts[p0], pts[ic], pts[p1], 0.0001 );\n bp1y = math.qbezierAt( pts[p0+1], pts[ic+1], pts[p1+1], 0.0001 );\n } else {\n var ic = pts.length / 2 - 1; // ctrpt\n var p0 = ic - 2; // startpt\n var p1 = ic + 2; // endpt\n\n bp0x = math.qbezierAt( pts[p0], pts[ic], pts[p1], 0.4999 );\n bp0y = math.qbezierAt( pts[p0+1], pts[ic+1], pts[p1+1], 0.4999 );\n\n bp1x = math.qbezierAt( pts[p0], pts[ic], pts[p1], 0.5 );\n bp1y = math.qbezierAt( pts[p0+1], pts[ic+1], pts[p1+1], 0.5 );\n }\n\n dispX = ( bp1x - bp0x );\n dispY = ( bp1y - bp0y );\n }\n\n rs.midtgtArrowAngle = getAngleFromDisp( dispX, dispY );\n\n rs.midDispX = dispX;\n rs.midDispY = dispY;\n\n // mid source\n //\n\n dispX *= -1;\n dispY *= -1;\n\n if( isSegments ){\n var pts = rs.allpts;\n\n if( pts.length / 2 % 2 === 0 ){\n // already ok\n } else {\n var i2 = pts.length / 2 - 1;\n var i3 = i2 + 2;\n\n dispX = -( pts[i3] - pts[i2] );\n dispY = -( pts[i3+1] - pts[i2+1] );\n }\n }\n\n rs.midsrcArrowAngle = getAngleFromDisp( dispX, dispY );\n\n // target\n //\n\n dispX = tgtPos.x - endX;\n dispY = tgtPos.y - endY;\n\n rs.tgtArrowAngle = getAngleFromDisp( dispX, dispY );\n};\n\n\nBRp.findEndpoints = function( edge ){\n var r = this;\n var intersect;\n\n var source = edge.source()[0];\n var target = edge.target()[0];\n\n var src_p = source._private;\n var tgt_p = target._private;\n\n var srcPos = src_p.position;\n var tgtPos = tgt_p.position;\n\n var tgtArShape = edge._private.style['target-arrow-shape'].value;\n var srcArShape = edge._private.style['source-arrow-shape'].value;\n\n var rs = edge._private.rscratch;\n\n var et = rs.edgeType;\n var bezier = et === 'bezier' || et === 'multibezier' || et === 'self' || et === 'compound';\n var multi = et !== 'bezier';\n var lines = et === 'straight' || et === 'segments';\n var segments = et === 'segments';\n\n var p1, p2;\n\n if( bezier ){\n var cpStart = [ rs.ctrlpts[0], rs.ctrlpts[1] ];\n var cpEnd = multi ? [ rs.ctrlpts[rs.ctrlpts.length - 2], rs.ctrlpts[rs.ctrlpts.length - 1] ] : cpStart;\n\n p1 = cpEnd;\n p2 = cpStart;\n } else if( lines ){\n var srcArrowFromPt = !segments ? [ tgtPos.x, tgtPos.y ] : rs.segpts.slice( 0, 2 );\n var tgtArrowFromPt = !segments ? [ srcPos.x, srcPos.y ] : rs.segpts.slice( rs.segpts.length - 2 );\n\n p1 = tgtArrowFromPt;\n p2 = srcArrowFromPt;\n }\n\n intersect = r.nodeShapes[this.getNodeShape(target)].intersectLine(\n tgtPos.x,\n tgtPos.y,\n target.outerWidth(),\n target.outerHeight(),\n p1[0],\n p1[1],\n 0\n );\n\n var arrowEnd = math.shortenIntersection(intersect, p1,\n r.arrowShapes[tgtArShape].spacing(edge));\n var edgeEnd = math.shortenIntersection(intersect, p1,\n r.arrowShapes[tgtArShape].gap(edge));\n\n rs.endX = edgeEnd[0];\n rs.endY = edgeEnd[1];\n\n rs.arrowEndX = arrowEnd[0];\n rs.arrowEndY = arrowEnd[1];\n\n intersect = r.nodeShapes[this.getNodeShape(source)].intersectLine(\n srcPos.x,\n srcPos.y,\n source.outerWidth(),\n source.outerHeight(),\n p2[0],\n p2[1],\n 0\n );\n\n var arrowStart = math.shortenIntersection(\n intersect, p2,\n r.arrowShapes[srcArShape].spacing(edge)\n );\n var edgeStart = math.shortenIntersection(\n intersect, p2,\n r.arrowShapes[srcArShape].gap(edge)\n );\n\n rs.startX = edgeStart[0];\n rs.startY = edgeStart[1];\n\n rs.arrowStartX = arrowStart[0];\n rs.arrowStartY = arrowStart[1];\n\n if( lines ){\n if( !is.number(rs.startX) || !is.number(rs.startY) || !is.number(rs.endX) || !is.number(rs.endY) ){\n rs.badLine = true;\n } else {\n rs.badLine = false;\n }\n }\n};\n\nBRp.getArrowWidth = BRp.getArrowHeight = function(edgeWidth) {\n var cache = this.arrowWidthCache = this.arrowWidthCache || {};\n\n var cachedVal = cache[edgeWidth];\n if( cachedVal ){\n return cachedVal;\n }\n\n cachedVal = Math.max(Math.pow(edgeWidth * 13.37, 0.9), 29);\n cache[edgeWidth] = cachedVal;\n\n return cachedVal;\n};\n\nmodule.exports = BRp;\n","'use strict';\n\nvar BRp = {};\n\nBRp.getCachedImage = function(url, onLoad) {\n var r = this;\n var imageCache = r.imageCache = r.imageCache || {};\n\n if( imageCache[url] && imageCache[url].image ){\n return imageCache[url].image;\n }\n\n var cache = imageCache[url] = imageCache[url] || {};\n\n var image = cache.image = new Image();\n image.addEventListener('load', onLoad);\n image.src = url;\n\n return image;\n};\n\nmodule.exports = BRp;\n","'use strict';\n\nvar is = require('../../../is');\nvar util = require('../../../util');\n\nvar BaseRenderer = function(){};\nvar BR = BaseRenderer;\nvar BRp = BR.prototype;\n\nBRp.clientFunctions = [ 'redrawHint', 'render', 'renderTo', 'matchCanvasSize', 'nodeShapeImpl', 'arrowShapeImpl' ];\n\nBRp.init = function( options ){\n var r = this;\n\n r.options = options;\n\n r.cy = options.cy;\n\n r.container = options.cy.container();\n\n r.selection = [undefined, undefined, undefined, undefined, 0]; // Coordinates for selection box, plus enabled flag\n\n //--Pointer-related data\n r.hoverData = {down: null, last: null,\n downTime: null, triggerMode: null,\n dragging: false,\n initialPan: [null, null], capture: false};\n\n r.dragData = {possibleDragElements: []};\n\n r.touchData = {\n start: null, capture: false,\n\n // These 3 fields related to tap, taphold events\n startPosition: [null, null, null, null, null, null],\n singleTouchStartTime: null,\n singleTouchMoved: true,\n\n now: [null, null, null, null, null, null],\n earlier: [null, null, null, null, null, null]\n };\n\n r.redraws = 0;\n r.showFps = options.showFps;\n\n r.hideEdgesOnViewport = options.hideEdgesOnViewport;\n r.hideLabelsOnViewport = options.hideLabelsOnViewport;\n r.textureOnViewport = options.textureOnViewport;\n r.wheelSensitivity = options.wheelSensitivity;\n r.motionBlurEnabled = options.motionBlur; // on by default\n r.forcedPixelRatio = options.pixelRatio;\n r.motionBlur = true; // for initial kick off\n r.motionBlurOpacity = options.motionBlurOpacity;\n r.motionBlurTransparency = 1 - r.motionBlurOpacity;\n r.motionBlurPxRatio = 1;\n r.mbPxRBlurry = 1; //0.8;\n r.minMbLowQualFrames = 4;\n r.fullQualityMb = false;\n r.clearedForMotionBlur = [];\n r.desktopTapThreshold = options.desktopTapThreshold;\n r.desktopTapThreshold2 = options.desktopTapThreshold * options.desktopTapThreshold;\n r.touchTapThreshold = options.touchTapThreshold;\n r.touchTapThreshold2 = options.touchTapThreshold * options.touchTapThreshold;\n r.tapholdDuration = 500;\n\n r.bindings = [];\n\n r.registerNodeShapes();\n r.registerArrowShapes();\n r.load();\n};\n\nBRp.notify = function(params) {\n var types;\n var r = this;\n\n if( is.array( params.type ) ){\n types = params.type;\n\n } else {\n types = [ params.type ];\n }\n\n for( var i = 0; i < types.length; i++ ){\n var type = types[i];\n\n switch( type ){\n case 'destroy':\n r.destroy();\n return;\n\n case 'add':\n case 'remove':\n case 'load':\n r.updateElementsCache();\n break;\n\n case 'viewport':\n r.redrawHint('select', true);\n break;\n\n case 'style':\n r.updateCachedZSortedEles();\n break;\n }\n\n if( type === 'load' || type === 'resize' ){\n r.invalidateContainerClientCoordsCache();\n r.matchCanvasSize(r.container);\n }\n } // for\n\n r.redrawHint('eles', true);\n r.redrawHint('drag', true);\n\n this.startRenderLoop();\n\n this.redraw();\n};\n\nBRp.destroy = function(){\n this.destroyed = true;\n\n this.cy.stopAnimationLoop();\n\n for( var i = 0; i < this.bindings.length; i++ ){\n var binding = this.bindings[i];\n var b = binding;\n\n b.target.removeEventListener(b.event, b.handler, b.useCapture);\n }\n\n if( this.removeObserver ){\n this.removeObserver.disconnect();\n }\n\n if( this.labelCalcDiv ){\n try{\n document.body.removeChild(this.labelCalcDiv);\n } catch(e){\n // ie10 issue #1014\n }\n }\n};\n\n[\n require('./arrow-shapes'),\n require('./cached-eles'),\n require('./coord-ele-math'),\n require('./images'),\n require('./load-listeners'),\n require('./node-shapes'),\n require('./redraw')\n].forEach(function( props ){\n util.extend( BRp, props );\n});\n\nmodule.exports = BR;\n","'use strict';\n\nvar is = require('../../../is');\nvar util = require('../../../util');\nvar Event = require('../../../event');\nvar Collection = require('../../../collection');\n\nvar BRp = {};\n\nBRp.registerBinding = function(target, event, handler, useCapture){\n this.bindings.push({\n target: target,\n event: event,\n handler: handler,\n useCapture: useCapture\n });\n\n target.addEventListener(event, handler, useCapture);\n};\n\nBRp.nodeIsDraggable = function(node) {\n if (node._private.style['opacity'].value !== 0\n && node._private.style['visibility'].value == 'visible'\n && node._private.style['display'].value == 'element'\n && !node.locked()\n && node.grabbable() ) {\n\n return true;\n }\n\n return false;\n};\n\nBRp.load = function() {\n var r = this;\n\n var triggerEvents = function( target, names, e, props ){\n if( target == null ){\n target = r.cy;\n }\n\n for( var i = 0; i < names.length; i++ ){\n var name = names[i];\n\n var event = Event( e, util.extend({ type: name }, props) );\n target.trigger( event );\n }\n };\n\n var isMultSelKeyDown = function( e ){\n return e.shiftKey || e.metaKey || e.ctrlKey; // maybe e.altKey\n };\n\n var getDragListIds = function(opts){\n var listHasId;\n\n if( opts.addToList && r.cy.hasCompoundNodes() ){ // only needed for compound graphs\n if( !opts.addToList.hasId ){ // build ids lookup if doesn't already exist\n opts.addToList.hasId = {};\n\n for( var i = 0; i < opts.addToList.length; i++ ){\n var ele = opts.addToList[i];\n\n opts.addToList.hasId[ ele.id() ] = true;\n }\n }\n\n listHasId = opts.addToList.hasId;\n }\n\n return listHasId || {};\n };\n\n // helper function to determine which child nodes and inner edges\n // of a compound node to be dragged as well as the grabbed and selected nodes\n var addDescendantsToDrag = function(node, opts){\n if( !node._private.cy.hasCompoundNodes() ){\n return;\n }\n\n if( opts.inDragLayer == null && opts.addToList == null ){ return; } // nothing to do\n\n var listHasId = getDragListIds( opts );\n\n var innerNodes = node.descendants();\n\n for( var i = 0; i < innerNodes.size(); i++ ){\n var iNode = innerNodes[i];\n var _p = iNode._private;\n\n if( opts.inDragLayer ){\n _p.rscratch.inDragLayer = true;\n }\n\n if( opts.addToList && !listHasId[ iNode.id() ] ){\n opts.addToList.push( iNode );\n listHasId[ iNode.id() ] = true;\n\n _p.grabbed = true;\n }\n\n var edges = _p.edges;\n for( var j = 0; opts.inDragLayer && j < edges.length; j++ ){\n edges[j]._private.rscratch.inDragLayer = true;\n }\n }\n };\n\n // adds the given nodes, and its edges to the drag layer\n var addNodeToDrag = function(node, opts){\n\n var _p = node._private;\n var listHasId = getDragListIds( opts );\n\n if( opts.inDragLayer ){\n _p.rscratch.inDragLayer = true;\n }\n\n if( opts.addToList && !listHasId[ node.id() ] ){\n opts.addToList.push( node );\n listHasId[ node.id() ] = true;\n\n _p.grabbed = true;\n }\n\n var edges = _p.edges;\n for( var i = 0; opts.inDragLayer && i < edges.length; i++ ){\n edges[i]._private.rscratch.inDragLayer = true;\n }\n\n addDescendantsToDrag( node, opts ); // always add to drag\n\n // also add nodes and edges related to the topmost ancestor\n updateAncestorsInDragLayer( node, {\n inDragLayer: opts.inDragLayer\n } );\n };\n\n var freeDraggedElements = function( draggedElements ){\n if( !draggedElements ){ return; }\n\n for (var i=0; i < draggedElements.length; i++) {\n\n var dEi_p = draggedElements[i]._private;\n\n if(dEi_p.group === 'nodes') {\n dEi_p.rscratch.inDragLayer = false;\n dEi_p.grabbed = false;\n\n var sEdges = dEi_p.edges;\n for( var j = 0; j < sEdges.length; j++ ){ sEdges[j]._private.rscratch.inDragLayer = false; }\n\n // for compound nodes, also remove related nodes and edges from the drag layer\n updateAncestorsInDragLayer(draggedElements[i], { inDragLayer: false });\n\n } else if( dEi_p.group === 'edges' ){\n dEi_p.rscratch.inDragLayer = false;\n }\n\n }\n };\n\n // helper function to determine which ancestor nodes and edges should go\n // to the drag layer (or should be removed from drag layer).\n var updateAncestorsInDragLayer = function(node, opts) {\n\n if( opts.inDragLayer == null && opts.addToList == null ){ return; } // nothing to do\n\n // find top-level parent\n var parent = node;\n\n if( !node._private.cy.hasCompoundNodes() ){\n return;\n }\n\n while( parent.parent().nonempty() ){\n parent = parent.parent()[0];\n }\n\n // no parent node: no nodes to add to the drag layer\n if( parent == node ){\n return;\n }\n\n var nodes = parent.descendants()\n .merge( parent )\n .unmerge( node )\n .unmerge( node.descendants() )\n ;\n\n var edges = nodes.connectedEdges();\n\n var listHasId = getDragListIds( opts );\n\n for( var i = 0; i < nodes.size(); i++ ){\n if( opts.inDragLayer !== undefined ){\n nodes[i]._private.rscratch.inDragLayer = opts.inDragLayer;\n }\n\n if( opts.addToList && !listHasId[ nodes[i].id() ] ){\n opts.addToList.push( nodes[i] );\n listHasId[ nodes[i].id() ] = true;\n\n nodes[i]._private.grabbed = true;\n }\n }\n\n for( var j = 0; opts.inDragLayer !== undefined && j < edges.length; j++ ) {\n edges[j]._private.rscratch.inDragLayer = opts.inDragLayer;\n }\n };\n\n if( typeof MutationObserver !== 'undefined' ){\n r.removeObserver = new MutationObserver(function( mutns ){\n for( var i = 0; i < mutns.length; i++ ){\n var mutn = mutns[i];\n var rNodes = mutn.removedNodes;\n\n if( rNodes ){ for( var j = 0; j < rNodes.length; j++ ){\n var rNode = rNodes[j];\n\n if( rNode === r.container ){\n r.destroy();\n break;\n }\n } }\n }\n });\n\n if( r.container.parentNode ){\n r.removeObserver.observe( r.container.parentNode, { childList: true } );\n }\n } else {\n r.registerBinding(r.container, 'DOMNodeRemoved', function(e){\n r.destroy();\n });\n }\n\n\n\n // auto resize\n r.registerBinding(window, 'resize', util.debounce( function(e) {\n r.invalidateContainerClientCoordsCache();\n\n r.matchCanvasSize(r.container);\n r.redrawHint('eles', true);\n r.redraw();\n }, 100 ) );\n\n var invalCtnrBBOnScroll = function(domEle){\n r.registerBinding(domEle, 'scroll', function(e){\n r.invalidateContainerClientCoordsCache();\n } );\n };\n\n var bbCtnr = r.cy.container();\n\n for( ;; ){\n\n invalCtnrBBOnScroll( bbCtnr );\n\n if( bbCtnr.parentNode ){\n bbCtnr = bbCtnr.parentNode;\n } else {\n break;\n }\n\n }\n\n // stop right click menu from appearing on cy\n r.registerBinding(r.container, 'contextmenu', function(e){\n e.preventDefault();\n });\n\n var inBoxSelection = function(){\n return r.selection[4] !== 0;\n };\n\n // Primary key\n r.registerBinding(r.container, 'mousedown', function(e) {\n e.preventDefault();\n r.hoverData.capture = true;\n r.hoverData.which = e.which;\n\n var cy = r.cy;\n var pos = r.projectIntoViewport(e.clientX, e.clientY);\n var select = r.selection;\n var near = r.findNearestElement(pos[0], pos[1], true, false);\n var draggedElements = r.dragData.possibleDragElements;\n\n r.hoverData.mdownPos = pos;\n\n var checkForTaphold = function(){\n r.hoverData.tapholdCancelled = false;\n\n clearTimeout( r.hoverData.tapholdTimeout );\n\n r.hoverData.tapholdTimeout = setTimeout(function(){\n\n if( r.hoverData.tapholdCancelled ){\n return;\n } else {\n var ele = r.hoverData.down;\n\n if( ele ){\n ele.trigger( Event(e, {\n type: 'taphold',\n cyPosition: { x: pos[0], y: pos[1] }\n }) );\n } else {\n cy.trigger( Event(e, {\n type: 'taphold',\n cyPosition: { x: pos[0], y: pos[1] }\n }) );\n }\n }\n\n }, r.tapholdDuration);\n };\n\n // Right click button\n if( e.which == 3 ){\n\n r.hoverData.cxtStarted = true;\n\n var cxtEvt = Event(e, {\n type: 'cxttapstart',\n cyPosition: { x: pos[0], y: pos[1] }\n });\n\n if( near ){\n near.activate();\n near.trigger( cxtEvt );\n\n r.hoverData.down = near;\n } else {\n cy.trigger( cxtEvt );\n }\n\n r.hoverData.downTime = (new Date()).getTime();\n r.hoverData.cxtDragged = false;\n\n // Primary button\n } else if (e.which == 1) {\n\n if( near ){\n near.activate();\n }\n\n // Element dragging\n {\n // If something is under the cursor and it is draggable, prepare to grab it\n if (near != null) {\n\n if( r.nodeIsDraggable(near) ){\n\n var grabEvent = Event(e, {\n type: 'grab',\n cyPosition: { x: pos[0], y: pos[1] }\n });\n\n if ( near.isNode() && !near.selected() ){\n\n draggedElements = r.dragData.possibleDragElements = [];\n addNodeToDrag( near, { addToList: draggedElements } );\n\n near.trigger(grabEvent);\n\n } else if ( near.isNode() && near.selected() ){\n draggedElements = r.dragData.possibleDragElements = [ ];\n\n var selectedNodes = cy.$(function(){ return this.isNode() && this.selected(); });\n\n for( var i = 0; i < selectedNodes.length; i++ ){\n\n // Only add this selected node to drag if it is draggable, eg. has nonzero opacity\n if( r.nodeIsDraggable( selectedNodes[i] ) ){\n addNodeToDrag( selectedNodes[i], { addToList: draggedElements } );\n }\n }\n\n near.trigger( grabEvent );\n }\n\n r.redrawHint('eles', true);\n r.redrawHint('drag', true);\n\n }\n\n }\n\n r.hoverData.down = near;\n r.hoverData.downTime = (new Date()).getTime();\n }\n\n triggerEvents( near, ['mousedown', 'tapstart', 'vmousedown'], e, {\n cyPosition: { x: pos[0], y: pos[1] }\n } );\n\n if ( near == null ) {\n select[4] = 1;\n\n r.data.bgActivePosistion = {\n x: pos[0],\n y: pos[1]\n };\n\n r.redrawHint('select', true);\n\n r.redraw();\n } else if( near.isEdge() ){\n select[4] = 1; // for future pan\n }\n\n checkForTaphold();\n\n }\n\n // Initialize selection box coordinates\n select[0] = select[2] = pos[0];\n select[1] = select[3] = pos[1];\n\n }, false);\n\n r.registerBinding(window, 'mousemove', function(e) {\n var preventDefault = false;\n var capture = r.hoverData.capture;\n\n // save cycles if mouse events aren't to be captured\n if ( !capture ){\n var containerPageCoords = r.findContainerClientCoords();\n\n if (e.clientX > containerPageCoords[0] && e.clientX < containerPageCoords[0] + r.canvasWidth\n && e.clientY > containerPageCoords[1] && e.clientY < containerPageCoords[1] + r.canvasHeight\n ) {\n // inside container bounds so OK\n } else {\n return;\n }\n\n var cyContainer = r.container;\n var target = e.target;\n var tParent = target.parentNode;\n var containerIsTarget = false;\n\n while( tParent ){\n if( tParent === cyContainer ){\n containerIsTarget = true;\n break;\n }\n\n tParent = tParent.parentNode;\n }\n\n if( !containerIsTarget ){ return; } // if target is outisde cy container, then this event is not for us\n }\n\n var cy = r.cy;\n var zoom = cy.zoom();\n var pos = r.projectIntoViewport(e.clientX, e.clientY);\n var select = r.selection;\n\n var near = null;\n if( !r.hoverData.draggingEles ){\n near = r.findNearestElement(pos[0], pos[1], true, false);\n }\n var last = r.hoverData.last;\n var down = r.hoverData.down;\n\n var disp = [pos[0] - select[2], pos[1] - select[3]];\n\n var draggedElements = r.dragData.possibleDragElements;\n\n var dx = select[2] - select[0];\n var dx2 = dx * dx;\n var dy = select[3] - select[1];\n var dy2 = dy * dy;\n var dist2 = dx2 + dy2;\n var rdist2 = dist2 * zoom * zoom;\n\n var multSelKeyDown = isMultSelKeyDown( e );\n\n r.hoverData.tapholdCancelled = true;\n\n var updateDragDelta = function(){\n var dragDelta = r.hoverData.dragDelta = r.hoverData.dragDelta || [];\n\n if( dragDelta.length === 0 ){\n dragDelta.push( disp[0] );\n dragDelta.push( disp[1] );\n } else {\n dragDelta[0] += disp[0];\n dragDelta[1] += disp[1];\n }\n };\n\n\n preventDefault = true;\n\n triggerEvents( near, ['mousemove', 'vmousemove', 'tapdrag'], e, {\n cyPosition: { x: pos[0], y: pos[1] }\n } );\n\n // trigger context drag if rmouse down\n if( r.hoverData.which === 3 ){\n var cxtEvt = Event(e, {\n type: 'cxtdrag',\n cyPosition: { x: pos[0], y: pos[1] }\n });\n\n if( down ){\n down.trigger( cxtEvt );\n } else {\n cy.trigger( cxtEvt );\n }\n\n r.hoverData.cxtDragged = true;\n\n if( !r.hoverData.cxtOver || near !== r.hoverData.cxtOver ){\n\n if( r.hoverData.cxtOver ){\n r.hoverData.cxtOver.trigger( Event(e, {\n type: 'cxtdragout',\n cyPosition: { x: pos[0], y: pos[1] }\n }) );\n }\n\n r.hoverData.cxtOver = near;\n\n if( near ){\n near.trigger( Event(e, {\n type: 'cxtdragover',\n cyPosition: { x: pos[0], y: pos[1] }\n }) );\n }\n\n }\n\n // Check if we are drag panning the entire graph\n } else if (r.hoverData.dragging) {\n preventDefault = true;\n\n if( cy.panningEnabled() && cy.userPanningEnabled() ){\n var deltaP;\n\n if( r.hoverData.justStartedPan ){\n var mdPos = r.hoverData.mdownPos;\n\n deltaP = {\n x: ( pos[0] - mdPos[0] ) * zoom,\n y: ( pos[1] - mdPos[1] ) * zoom\n };\n\n r.hoverData.justStartedPan = false;\n\n } else {\n deltaP = {\n x: disp[0] * zoom,\n y: disp[1] * zoom\n };\n\n }\n\n cy.panBy( deltaP );\n\n r.hoverData.dragged = true;\n }\n\n // Needs reproject due to pan changing viewport\n pos = r.projectIntoViewport(e.clientX, e.clientY);\n\n // Checks primary button down & out of time & mouse not moved much\n } else if(\n select[4] == 1 && (down == null || down.isEdge())\n ){\n\n if( !r.hoverData.dragging && cy.boxSelectionEnabled() && ( multSelKeyDown || !cy.panningEnabled() || !cy.userPanningEnabled() ) ){\n r.data.bgActivePosistion = undefined;\n r.hoverData.selecting = true;\n\n r.redrawHint('select', true);\n r.redraw();\n\n } else if( !r.hoverData.selecting && cy.panningEnabled() && cy.userPanningEnabled() ){\n r.hoverData.dragging = true;\n r.hoverData.justStartedPan = true;\n select[4] = 0;\n\n r.data.bgActivePosistion = {\n x: pos[0],\n y: pos[1]\n };\n\n r.redrawHint('select', true);\n r.redraw();\n }\n\n if( down && down.isEdge() && down.active() ){ down.unactivate(); }\n\n } else {\n if( down && down.isEdge() && down.active() ){ down.unactivate(); }\n\n if (near != last) {\n\n if (last) {\n triggerEvents( last, ['mouseout', 'tapdragout'], e, {\n cyPosition: { x: pos[0], y: pos[1] }\n } );\n }\n\n if (near) {\n triggerEvents( near, ['mouseover', 'tapdragover'], e, {\n cyPosition: { x: pos[0], y: pos[1] }\n } );\n }\n\n r.hoverData.last = near;\n }\n\n if( down && down.isNode() && r.nodeIsDraggable(down) ){\n\n if( rdist2 >= r.desktopTapThreshold2 ){ // then drag\n\n var justStartedDrag = !r.dragData.didDrag;\n\n if( justStartedDrag ) {\n r.redrawHint('eles', true);\n }\n\n r.dragData.didDrag = true; // indicate that we actually did drag the node\n\n var toTrigger = [];\n\n for( var i = 0; i < draggedElements.length; i++ ){\n var dEle = draggedElements[i];\n\n // now, add the elements to the drag layer if not done already\n if( !r.hoverData.draggingEles ){\n addNodeToDrag( dEle, { inDragLayer: true } );\n }\n\n // Locked nodes not draggable, as well as non-visible nodes\n if( dEle.isNode() && r.nodeIsDraggable(dEle) && dEle.grabbed() ){\n var dPos = dEle._private.position;\n\n toTrigger.push( dEle );\n\n if( is.number(disp[0]) && is.number(disp[1]) ){\n var updatePos = !dEle.isParent();\n\n if( updatePos ){\n dPos.x += disp[0];\n dPos.y += disp[1];\n }\n\n if( justStartedDrag ){\n var dragDelta = r.hoverData.dragDelta;\n\n if( updatePos && is.number(dragDelta[0]) && is.number(dragDelta[1]) ){\n dPos.x += dragDelta[0];\n dPos.y += dragDelta[1];\n }\n }\n }\n\n }\n }\n\n r.hoverData.draggingEles = true;\n\n var tcol = (Collection(cy, toTrigger));\n\n tcol.updateCompoundBounds();\n tcol.trigger('position drag');\n\n r.redrawHint('drag', true);\n r.redraw();\n\n } else { // otherwise save drag delta for when we actually start dragging so the relative grab pos is constant\n updateDragDelta();\n }\n }\n\n // prevent the dragging from triggering text selection on the page\n preventDefault = true;\n }\n\n select[2] = pos[0]; select[3] = pos[1];\n\n if( preventDefault ){\n if(e.stopPropagation) e.stopPropagation();\n if(e.preventDefault) e.preventDefault();\n return false;\n }\n }, false);\n\n r.registerBinding(window, 'mouseup', function(e) {\n var capture = r.hoverData.capture;\n if (!capture) { return; }\n r.hoverData.capture = false;\n\n var cy = r.cy; var pos = r.projectIntoViewport(e.clientX, e.clientY); var select = r.selection;\n var near = r.findNearestElement(pos[0], pos[1], true, false);\n var draggedElements = r.dragData.possibleDragElements; var down = r.hoverData.down;\n var multSelKeyDown = isMultSelKeyDown( e );\n\n if( r.data.bgActivePosistion ){\n r.redrawHint('select', true);\n r.redraw();\n }\n\n r.hoverData.tapholdCancelled = true;\n\n r.data.bgActivePosistion = undefined; // not active bg now\n\n if( down ){\n down.unactivate();\n }\n\n if( r.hoverData.which === 3 ){\n var cxtEvt = Event(e, {\n type: 'cxttapend',\n cyPosition: { x: pos[0], y: pos[1] }\n });\n\n if( down ){\n down.trigger( cxtEvt );\n } else {\n cy.trigger( cxtEvt );\n }\n\n if( !r.hoverData.cxtDragged ){\n var cxtTap = Event(e, {\n type: 'cxttap',\n cyPosition: { x: pos[0], y: pos[1] }\n });\n\n if( down ){\n down.trigger( cxtTap );\n } else {\n cy.trigger( cxtTap );\n }\n }\n\n r.hoverData.cxtDragged = false;\n r.hoverData.which = null;\n\n } else if( r.hoverData.which === 1 ) {\n\n // Deselect all elements if nothing is currently under the mouse cursor and we aren't dragging something\n if ( (down == null) // not mousedown on node\n && !r.dragData.didDrag // didn't move the node around\n && !r.hoverData.selecting // not box selection\n && !r.hoverData.dragged // didn't pan\n && !isMultSelKeyDown( e )\n ) {\n\n cy.$(function(){\n return this.selected();\n }).unselect();\n\n if (draggedElements.length > 0) {\n r.redrawHint('eles', true);\n }\n\n r.dragData.possibleDragElements = draggedElements = [];\n }\n\n triggerEvents( near, ['mouseup', 'tapend', 'vmouseup'], e, {\n cyPosition: { x: pos[0], y: pos[1] }\n } );\n\n if(\n !r.dragData.didDrag // didn't move a node around\n && !r.hoverData.dragged // didn't pan\n ){\n triggerEvents( near, ['click', 'tap', 'vclick'], e, {\n cyPosition: { x: pos[0], y: pos[1] }\n } );\n }\n\n // Single selection\n if( near == down && !r.dragData.didDrag && !r.hoverData.selecting ){\n if( near != null && near._private.selectable ){\n\n if( r.hoverData.dragging ){\n // if panning, don't change selection state\n } else if( cy.selectionType() === 'additive' || multSelKeyDown ){\n if( near.selected() ){\n near.unselect();\n } else {\n near.select();\n }\n } else {\n if( !multSelKeyDown ){\n cy.$(':selected').unmerge( near ).unselect();\n near.select();\n }\n }\n\n r.redrawHint('eles', true);\n }\n }\n\n if ( r.hoverData.selecting ) {\n var newlySelected = [];\n var box = r.getAllInBox( select[0], select[1], select[2], select[3] );\n\n r.redrawHint('select', true);\n\n if( box.length > 0 ) {\n r.redrawHint('eles', true);\n }\n\n for( var i = 0; i < box.length; i++ ){\n if( box[i]._private.selectable ){\n newlySelected.push( box[i] );\n }\n }\n\n var newlySelCol = Collection( cy, newlySelected );\n\n if( cy.selectionType() === 'additive' ){\n newlySelCol.select();\n } else {\n if( !multSelKeyDown ){\n cy.$(':selected').unmerge( newlySelCol ).unselect();\n }\n\n newlySelCol.select();\n }\n\n // always need redraw in case eles unselectable\n r.redraw();\n\n }\n\n // Cancel drag pan\n if( r.hoverData.dragging ){\n r.hoverData.dragging = false;\n\n r.redrawHint('select', true);\n r.redrawHint('eles', true);\n\n r.redraw();\n }\n\n if (!select[4]) {\n\n\n r.redrawHint('drag', true);\n r.redrawHint('eles', true);\n\n freeDraggedElements( draggedElements );\n\n if( down ){ down.trigger('free'); }\n }\n\n } // else not right mouse\n\n select[4] = 0; r.hoverData.down = null;\n\n r.hoverData.cxtStarted = false;\n r.hoverData.draggingEles = false;\n r.hoverData.selecting = false;\n r.dragData.didDrag = false;\n r.hoverData.dragged = false;\n r.hoverData.dragDelta = [];\n\n }, false);\n\n var wheelHandler = function(e) {\n\n\n if( r.scrollingPage ){ return; } // while scrolling, ignore wheel-to-zoom\n\n var cy = r.cy;\n var pos = r.projectIntoViewport(e.clientX, e.clientY);\n var rpos = [pos[0] * cy.zoom() + cy.pan().x,\n pos[1] * cy.zoom() + cy.pan().y];\n\n if( r.hoverData.draggingEles || r.hoverData.dragging || r.hoverData.cxtStarted || inBoxSelection() ){ // if pan dragging or cxt dragging, wheel movements make no zoom\n e.preventDefault();\n return;\n }\n\n if( cy.panningEnabled() && cy.userPanningEnabled() && cy.zoomingEnabled() && cy.userZoomingEnabled() ){\n e.preventDefault();\n\n r.data.wheelZooming = true;\n clearTimeout( r.data.wheelTimeout );\n r.data.wheelTimeout = setTimeout(function(){\n r.data.wheelZooming = false;\n\n r.redrawHint('eles', true);\n r.redraw();\n }, 150);\n\n var diff = e.deltaY / -250 || e.wheelDeltaY / 1000 || e.wheelDelta / 1000;\n diff = diff * r.wheelSensitivity;\n\n var needsWheelFix = e.deltaMode === 1;\n if( needsWheelFix ){ // fixes slow wheel events on ff/linux and ff/windows\n diff *= 33;\n }\n\n cy.zoom({\n level: cy.zoom() * Math.pow(10, diff),\n renderedPosition: { x: rpos[0], y: rpos[1] }\n });\n }\n\n };\n\n // Functions to help with whether mouse wheel should trigger zooming\n // --\n r.registerBinding(r.container, 'wheel', wheelHandler, true);\n\n // disable nonstandard wheel events\n // r.registerBinding(r.container, 'mousewheel', wheelHandler, true);\n // r.registerBinding(r.container, 'DOMMouseScroll', wheelHandler, true);\n // r.registerBinding(r.container, 'MozMousePixelScroll', wheelHandler, true); // older firefox\n\n r.registerBinding(window, 'scroll', function(e){\n r.scrollingPage = true;\n\n clearTimeout( r.scrollingPageTimeout );\n r.scrollingPageTimeout = setTimeout(function(){\n r.scrollingPage = false;\n }, 250);\n }, true);\n\n // Functions to help with handling mouseout/mouseover on the Cytoscape container\n // Handle mouseout on Cytoscape container\n r.registerBinding(r.container, 'mouseout', function(e) {\n var pos = r.projectIntoViewport(e.clientX, e.clientY);\n\n r.cy.trigger(Event(e, {\n type: 'mouseout',\n cyPosition: { x: pos[0], y: pos[1] }\n }));\n }, false);\n\n r.registerBinding(r.container, 'mouseover', function(e) {\n var pos = r.projectIntoViewport(e.clientX, e.clientY);\n\n r.cy.trigger(Event(e, {\n type: 'mouseover',\n cyPosition: { x: pos[0], y: pos[1] }\n }));\n }, false);\n\n var f1x1, f1y1, f2x1, f2y1; // starting points for pinch-to-zoom\n var distance1, distance1Sq; // initial distance between finger 1 and finger 2 for pinch-to-zoom\n var center1, modelCenter1; // center point on start pinch to zoom\n var offsetLeft, offsetTop;\n var containerWidth, containerHeight;\n var twoFingersStartInside;\n\n var distance = function(x1, y1, x2, y2){\n return Math.sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) );\n };\n\n var distanceSq = function(x1, y1, x2, y2){\n return (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);\n };\n\n var touchstartHandler;\n r.registerBinding(r.container, 'touchstart', touchstartHandler = function(e) {\n r.touchData.capture = true;\n r.data.bgActivePosistion = undefined;\n\n var cy = r.cy;\n var nodes = r.getCachedNodes();\n var edges = r.getCachedEdges();\n var now = r.touchData.now;\n var earlier = r.touchData.earlier;\n\n if (e.touches[0]) { var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY); now[0] = pos[0]; now[1] = pos[1]; }\n if (e.touches[1]) { var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY); now[2] = pos[0]; now[3] = pos[1]; }\n if (e.touches[2]) { var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY); now[4] = pos[0]; now[5] = pos[1]; }\n\n\n // record starting points for pinch-to-zoom\n if( e.touches[1] ){\n\n // anything in the set of dragged eles should be released\n var release = function( eles ){\n for( var i = 0; i < eles.length; i++ ){\n eles[i]._private.grabbed = false;\n eles[i]._private.rscratch.inDragLayer = false;\n if( eles[i].active() ){ eles[i].unactivate(); }\n }\n };\n release(nodes);\n release(edges);\n\n var offsets = r.findContainerClientCoords();\n offsetLeft = offsets[0];\n offsetTop = offsets[1];\n containerWidth = offsets[2];\n containerHeight = offsets[3];\n\n f1x1 = e.touches[0].clientX - offsetLeft;\n f1y1 = e.touches[0].clientY - offsetTop;\n\n f2x1 = e.touches[1].clientX - offsetLeft;\n f2y1 = e.touches[1].clientY - offsetTop;\n\n twoFingersStartInside =\n 0 <= f1x1 && f1x1 <= containerWidth\n && 0 <= f2x1 && f2x1 <= containerWidth\n && 0 <= f1y1 && f1y1 <= containerHeight\n && 0 <= f2y1 && f2y1 <= containerHeight\n ;\n\n var pan = cy.pan();\n var zoom = cy.zoom();\n\n distance1 = distance( f1x1, f1y1, f2x1, f2y1 );\n distance1Sq = distanceSq( f1x1, f1y1, f2x1, f2y1 );\n center1 = [ (f1x1 + f2x1)/2, (f1y1 + f2y1)/2 ];\n modelCenter1 = [\n (center1[0] - pan.x) / zoom,\n (center1[1] - pan.y) / zoom\n ];\n\n // consider context tap\n var cxtDistThreshold = 200;\n var cxtDistThresholdSq = cxtDistThreshold * cxtDistThreshold;\n if( distance1Sq < cxtDistThresholdSq && !e.touches[2] ){\n\n var near1 = r.findNearestElement(now[0], now[1], true, true);\n var near2 = r.findNearestElement(now[2], now[3], true, true);\n\n if( near1 && near1.isNode() ){\n near1.activate().trigger( Event(e, {\n type: 'cxttapstart',\n cyPosition: { x: now[0], y: now[1] }\n }) );\n r.touchData.start = near1;\n\n } else if( near2 && near2.isNode() ){\n near2.activate().trigger( Event(e, {\n type: 'cxttapstart',\n cyPosition: { x: now[0], y: now[1] }\n }) );\n r.touchData.start = near2;\n\n } else {\n cy.trigger( Event(e, {\n type: 'cxttapstart',\n cyPosition: { x: now[0], y: now[1] }\n }) );\n r.touchData.start = null;\n }\n\n if( r.touchData.start ){ r.touchData.start._private.grabbed = false; }\n r.touchData.cxt = true;\n r.touchData.cxtDragged = false;\n r.data.bgActivePosistion = undefined;\n\n r.redraw();\n return;\n\n }\n\n }\n\n if (e.touches[2]) {\n\n } else if (e.touches[1]) {\n\n } else if (e.touches[0]) {\n var near = r.findNearestElement(now[0], now[1], true, true);\n\n if (near != null) {\n near.activate();\n\n r.touchData.start = near;\n\n if( near.isNode() && r.nodeIsDraggable(near) ){\n\n var draggedEles = r.dragData.touchDragEles = [];\n\n r.redrawHint('eles', true);\n r.redrawHint('drag', true);\n\n if( near.selected() ){\n // reset drag elements, since near will be added again\n\n var selectedNodes = cy.$(function(){\n return this.isNode() && this.selected();\n });\n\n for( var k = 0; k < selectedNodes.length; k++ ){\n var selectedNode = selectedNodes[k];\n\n if( r.nodeIsDraggable(selectedNode) ){\n addNodeToDrag( selectedNode, { addToList: draggedEles } );\n }\n }\n } else {\n addNodeToDrag( near, { addToList: draggedEles } );\n }\n\n near.trigger( Event(e, {\n type: 'grab',\n cyPosition: { x: now[0], y: now[1] }\n }) );\n }\n }\n\n triggerEvents( near, ['touchstart', 'tapstart', 'vmousedown'], e, {\n cyPosition: { x: now[0], y: now[1] }\n } );\n\n if (near == null) {\n r.data.bgActivePosistion = {\n x: pos[0],\n y: pos[1]\n };\n\n r.redrawHint('select', true);\n r.redraw();\n }\n\n\n // Tap, taphold\n // -----\n\n for (var i=0; i= factorThresholdSq || distance2Sq >= distThresholdSq ){\n r.touchData.cxt = false;\n if( r.touchData.start ){ r.touchData.start.unactivate(); r.touchData.start = null; }\n r.data.bgActivePosistion = undefined;\n r.redrawHint('select', true);\n\n var cxtEvt = Event(e, {\n type: 'cxttapend',\n cyPosition: { x: now[0], y: now[1] }\n });\n if( r.touchData.start ){\n r.touchData.start.trigger( cxtEvt );\n } else {\n cy.trigger( cxtEvt );\n }\n }\n\n }\n\n // context swipe\n if( capture && r.touchData.cxt ){\n var cxtEvt = Event(e, {\n type: 'cxtdrag',\n cyPosition: { x: now[0], y: now[1] }\n });\n r.data.bgActivePosistion = undefined;\n r.redrawHint('select', true);\n\n if( r.touchData.start ){\n r.touchData.start.trigger( cxtEvt );\n } else {\n cy.trigger( cxtEvt );\n }\n\n if( r.touchData.start ){ r.touchData.start._private.grabbed = false; }\n r.touchData.cxtDragged = true;\n\n var near = r.findNearestElement(now[0], now[1], true, true);\n\n if( !r.touchData.cxtOver || near !== r.touchData.cxtOver ){\n\n if( r.touchData.cxtOver ){\n r.touchData.cxtOver.trigger( Event(e, {\n type: 'cxtdragout',\n cyPosition: { x: now[0], y: now[1] }\n }) );\n }\n\n r.touchData.cxtOver = near;\n\n if( near ){\n near.trigger( Event(e, {\n type: 'cxtdragover',\n cyPosition: { x: now[0], y: now[1] }\n }) );\n\n }\n\n }\n\n // box selection\n } else if( capture && e.touches[2] && cy.boxSelectionEnabled() ){\n e.preventDefault();\n\n r.data.bgActivePosistion = undefined;\n\n this.lastThreeTouch = +new Date();\n r.touchData.selecting = true;\n\n r.redrawHint('select', true);\n\n if( !select || select.length === 0 || select[0] === undefined ){\n select[0] = (now[0] + now[2] + now[4])/3;\n select[1] = (now[1] + now[3] + now[5])/3;\n select[2] = (now[0] + now[2] + now[4])/3 + 1;\n select[3] = (now[1] + now[3] + now[5])/3 + 1;\n } else {\n select[2] = (now[0] + now[2] + now[4])/3;\n select[3] = (now[1] + now[3] + now[5])/3;\n }\n\n select[4] = 1;\n r.touchData.selecting = true;\n\n r.redraw();\n\n // pinch to zoom\n } else if ( capture && e.touches[1] && cy.zoomingEnabled() && cy.panningEnabled() && cy.userZoomingEnabled() && cy.userPanningEnabled() ) { // two fingers => pinch to zoom\n e.preventDefault();\n\n r.data.bgActivePosistion = undefined;\n r.redrawHint('select', true);\n\n var draggedEles = r.dragData.touchDragEles;\n if( draggedEles ){\n r.redrawHint('drag', true);\n\n for( var i = 0; i < draggedEles.length; i++ ){\n draggedEles[i]._private.grabbed = false;\n draggedEles[i]._private.rscratch.inDragLayer = false;\n }\n }\n\n // (x2, y2) for fingers 1 and 2\n var f1x2 = e.touches[0].clientX - offsetLeft, f1y2 = e.touches[0].clientY - offsetTop;\n var f2x2 = e.touches[1].clientX - offsetLeft, f2y2 = e.touches[1].clientY - offsetTop;\n\n\n var distance2 = distance( f1x2, f1y2, f2x2, f2y2 );\n // var distance2Sq = distanceSq( f1x2, f1y2, f2x2, f2y2 );\n // var factor = Math.sqrt( distance2Sq ) / Math.sqrt( distance1Sq );\n var factor = distance2 / distance1;\n\n if( factor != 1 && twoFingersStartInside){\n // delta finger1\n var df1x = f1x2 - f1x1;\n var df1y = f1y2 - f1y1;\n\n // delta finger 2\n var df2x = f2x2 - f2x1;\n var df2y = f2y2 - f2y1;\n\n // translation is the normalised vector of the two fingers movement\n // i.e. so pinching cancels out and moving together pans\n var tx = (df1x + df2x)/2;\n var ty = (df1y + df2y)/2;\n\n // adjust factor by the speed multiplier\n // var speed = 1.5;\n // if( factor > 1 ){\n // factor = (factor - 1) * speed + 1;\n // } else {\n // factor = 1 - (1 - factor) * speed;\n // }\n\n // now calculate the zoom\n var zoom1 = cy.zoom();\n var zoom2 = zoom1 * factor;\n var pan1 = cy.pan();\n\n // the model center point converted to the current rendered pos\n var ctrx = modelCenter1[0] * zoom1 + pan1.x;\n var ctry = modelCenter1[1] * zoom1 + pan1.y;\n\n var pan2 = {\n x: -zoom2/zoom1 * (ctrx - pan1.x - tx) + ctrx,\n y: -zoom2/zoom1 * (ctry - pan1.y - ty) + ctry\n };\n\n // remove dragged eles\n if( r.touchData.start ){\n var draggedEles = r.dragData.touchDragEles;\n\n if( draggedEles ){ for( var i = 0; i < draggedEles.length; i++ ){\n var dEi_p = draggedEles[i]._private;\n\n dEi_p.grabbed = false;\n dEi_p.rscratch.inDragLayer = false;\n } }\n\n var start_p = r.touchData.start._private;\n start_p.active = false;\n start_p.grabbed = false;\n start_p.rscratch.inDragLayer = false;\n\n r.redrawHint('drag', true);\n\n r.touchData.start\n .trigger('free')\n .trigger('unactivate')\n ;\n }\n\n cy.viewport({\n zoom: zoom2,\n pan: pan2,\n cancelOnFailedZoom: true\n });\n\n distance1 = distance2;\n f1x1 = f1x2;\n f1y1 = f1y2;\n f2x1 = f2x2;\n f2y1 = f2y2;\n\n r.pinching = true;\n }\n\n // Re-project\n if (e.touches[0]) { var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY); now[0] = pos[0]; now[1] = pos[1]; }\n if (e.touches[1]) { var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY); now[2] = pos[0]; now[3] = pos[1]; }\n if (e.touches[2]) { var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY); now[4] = pos[0]; now[5] = pos[1]; }\n\n } else if (e.touches[0]) {\n var start = r.touchData.start;\n var last = r.touchData.last;\n var near = near || r.findNearestElement(now[0], now[1], true, true);\n\n if( start != null ){\n e.preventDefault();\n }\n\n // dragging nodes\n if( start != null && start._private.group == 'nodes' && r.nodeIsDraggable(start) ){\n\n if( rdist2 >= r.touchTapThreshold2 ){ // then dragging can happen\n var draggedEles = r.dragData.touchDragEles;\n var justStartedDrag = !r.dragData.didDrag;\n\n for( var k = 0; k < draggedEles.length; k++ ){\n var draggedEle = draggedEles[k];\n\n if( justStartedDrag ){\n addNodeToDrag( draggedEle, { inDragLayer: true } );\n }\n\n if( r.nodeIsDraggable(draggedEle) && draggedEle.isNode() && draggedEle.grabbed() ){\n r.dragData.didDrag = true;\n var dPos = draggedEle._private.position;\n var updatePos = !draggedEle.isParent();\n\n if( updatePos && is.number(disp[0]) && is.number(disp[1]) ){\n dPos.x += disp[0];\n dPos.y += disp[1];\n }\n\n if( justStartedDrag ){\n r.redrawHint('eles', true);\n\n var dragDelta = r.touchData.dragDelta;\n\n if( updatePos && is.number(dragDelta[0]) && is.number(dragDelta[1]) ){\n dPos.x += dragDelta[0];\n dPos.y += dragDelta[1];\n }\n\n }\n }\n }\n\n var tcol = Collection(cy, draggedEles);\n\n tcol.updateCompoundBounds();\n tcol.trigger('position drag');\n\n r.hoverData.draggingEles = true;\n\n r.redrawHint('drag', true);\n\n if(\n r.touchData.startPosition[0] == earlier[0]\n && r.touchData.startPosition[1] == earlier[1]\n ){\n\n r.redrawHint('eles', true);\n }\n\n r.redraw();\n } else { // otherise keep track of drag delta for later\n var dragDelta = r.touchData.dragDelta = r.touchData.dragDelta || [];\n\n if( dragDelta.length === 0 ){\n dragDelta.push( disp[0] );\n dragDelta.push( disp[1] );\n } else {\n dragDelta[0] += disp[0];\n dragDelta[1] += disp[1];\n }\n }\n }\n\n // touchmove\n {\n triggerEvents( (start || near), ['touchmove', 'tapdrag', 'vmousemove'], e, {\n cyPosition: { x: now[0], y: now[1] }\n } );\n\n if (near != last) {\n if (last) { last.trigger(Event(e, { type: 'tapdragout', cyPosition: { x: now[0], y: now[1] } })); }\n if (near) { near.trigger(Event(e, { type: 'tapdragover', cyPosition: { x: now[0], y: now[1] } })); }\n }\n\n r.touchData.last = near;\n }\n\n // check to cancel taphold\n for (var i=0;i r.touchTapThreshold2 ){\n\n r.touchData.singleTouchMoved = true;\n }\n }\n\n // panning\n if(\n capture\n && ( start == null || start.isEdge() )\n && cy.panningEnabled() && cy.userPanningEnabled()\n ){\n\n e.preventDefault();\n\n if( r.swipePanning ){\n cy.panBy({\n x: disp[0] * zoom,\n y: disp[1] * zoom\n });\n\n } else if( rdist2 >= r.touchTapThreshold2 ){\n r.swipePanning = true;\n\n cy.panBy({\n x: dx * zoom,\n y: dy * zoom\n });\n\n if( start ){\n start.unactivate();\n\n if( !r.data.bgActivePosistion ){\n r.data.bgActivePosistion = {\n x: now[0],\n y: now[1]\n };\n }\n\n r.redrawHint('select', true);\n\n r.touchData.start = null;\n }\n }\n\n // Re-project\n var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);\n now[0] = pos[0]; now[1] = pos[1];\n }\n }\n\n for (var j=0; j 0 ) {\n r.redrawHint('eles', true);\n } else {\n r.redraw();\n }\n }\n\n var updateStartStyle = false;\n\n if( start != null ){\n start._private.active = false;\n updateStartStyle = true;\n start.unactivate();\n }\n\n if (e.touches[2]) {\n r.data.bgActivePosistion = undefined;\n r.redrawHint('select', true);\n } else if (e.touches[1]) {\n\n } else if (e.touches[0]) {\n\n // Last touch released\n } else if (!e.touches[0]) {\n\n r.data.bgActivePosistion = undefined;\n r.redrawHint('select', true);\n\n var draggedEles = r.dragData.touchDragEles;\n\n if (start != null ) {\n\n var startWasGrabbed = start._private.grabbed;\n\n freeDraggedElements( draggedEles );\n\n r.redrawHint('drag', true);\n r.redrawHint('eles', true);\n\n if( startWasGrabbed ){\n start.trigger('free');\n }\n\n triggerEvents( start, ['touchend', 'tapend', 'vmouseup'], e, {\n cyPosition: { x: now[0], y: now[1] }\n } );\n\n start.unactivate();\n\n r.touchData.start = null;\n\n } else {\n var near = r.findNearestElement(now[0], now[1], true, true);\n\n triggerEvents( near, ['touchend', 'tapend', 'vmouseup'], e, {\n cyPosition: { x: now[0], y: now[1] }\n } );\n\n }\n\n var dx = r.touchData.startPosition[0] - now[0];\n var dx2 = dx * dx;\n var dy = r.touchData.startPosition[1] - now[1];\n var dy2 = dy * dy;\n var dist2 = dx2 + dy2;\n var rdist2 = dist2 * zoom * zoom;\n\n // Prepare to select the currently touched node, only if it hasn't been dragged past a certain distance\n if (start != null\n && !r.dragData.didDrag // didn't drag nodes around\n && start._private.selectable\n && rdist2 < r.touchTapThreshold2\n && !r.pinching // pinch to zoom should not affect selection\n ) {\n\n if( cy.selectionType() === 'single' ){\n cy.$(':selected').unmerge( start ).unselect();\n start.select();\n } else {\n if( start.selected() ){\n start.unselect();\n } else {\n start.select();\n }\n }\n\n updateStartStyle = true;\n\n\n r.redrawHint('eles', true);\n }\n\n // Tap event, roughly same as mouse click event for touch\n if( !r.touchData.singleTouchMoved ){\n triggerEvents( start, ['tap', 'vclick'], e, {\n cyPosition: { x: now[0], y: now[1] }\n } );\n }\n\n r.touchData.singleTouchMoved = true;\n }\n\n for( var j = 0; j < now.length; j++ ){ earlier[j] = now[j]; }\n\n r.dragData.didDrag = false; // reset for next mousedown\n\n if( e.touches.length === 0 ){\n r.touchData.dragDelta = [];\n }\n\n if( updateStartStyle && start ){\n start.updateStyle(false);\n }\n\n if( e.touches.length < 2 ){\n r.pinching = false;\n r.redrawHint('eles', true);\n r.redraw();\n }\n\n //r.redraw();\n\n }, false);\n\n // fallback compatibility layer for ms pointer events\n if( typeof TouchEvent === 'undefined' ){\n\n var pointers = [];\n\n var makeTouch = function( e ){\n return {\n clientX: e.clientX,\n clientY: e.clientY,\n force: 1,\n identifier: e.pointerId,\n pageX: e.pageX,\n pageY: e.pageY,\n radiusX: e.width/2,\n radiusY: e.height/2,\n screenX: e.screenX,\n screenY: e.screenY,\n target: e.target\n };\n };\n\n var makePointer = function( e ){\n return {\n event: e,\n touch: makeTouch(e)\n };\n };\n\n var addPointer = function( e ){\n pointers.push( makePointer(e) );\n };\n\n var removePointer = function( e ){\n for( var i = 0; i < pointers.length; i++ ){\n var p = pointers[i];\n\n if( p.event.pointerId === e.pointerId ){\n pointers.splice( i, 1 );\n return;\n }\n }\n };\n\n var updatePointer = function( e ){\n var p = pointers.filter(function( p ){\n return p.event.pointerId === e.pointerId;\n })[0];\n\n p.event = e;\n p.touch = makeTouch(e);\n };\n\n var addTouchesToEvent = function( e ){\n e.touches = pointers.map(function( p ){\n return p.touch;\n });\n };\n\n var pointerIsMouse = function( e ){\n return e.pointerType === 'mouse' || e.pointerType === 4;\n };\n\n r.registerBinding(r.container, 'pointerdown', function(e){\n if( pointerIsMouse(e) ){ return; } // mouse already handled\n\n e.preventDefault();\n\n addPointer( e );\n\n addTouchesToEvent( e );\n touchstartHandler( e );\n });\n\n r.registerBinding(r.container, 'pointerup', function(e){\n if( pointerIsMouse(e) ){ return; } // mouse already handled\n\n removePointer( e );\n\n addTouchesToEvent( e );\n touchendHandler( e );\n });\n\n r.registerBinding(r.container, 'pointercancel', function(e){\n if( pointerIsMouse(e) ){ return; } // mouse already handled\n\n removePointer( e );\n\n addTouchesToEvent( e );\n touchcancelHandler( e );\n });\n\n r.registerBinding(r.container, 'pointermove', function(e){\n if( pointerIsMouse(e) ){ return; } // mouse already handled\n\n e.preventDefault();\n\n updatePointer( e );\n\n addTouchesToEvent( e );\n touchmoveHandler( e );\n });\n\n }\n};\n\nmodule.exports = BRp;\n","'use strict';\n\nvar math = require('../../../math');\n\nvar BRp = {};\n\nBRp.registerNodeShapes = function(){\n var nodeShapes = this.nodeShapes = {};\n var renderer = this;\n\n nodeShapes['ellipse'] = {\n name: 'ellipse',\n\n draw: function( context, centerX, centerY, width, height ){\n renderer.nodeShapeImpl( this.name )( context, centerX, centerY, width, height );\n },\n\n intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){\n return math.intersectLineEllipse(\n x, y,\n nodeX,\n nodeY,\n width / 2 + padding,\n height / 2 + padding)\n ;\n },\n\n checkPoint: function( x, y, padding, width, height, centerX, centerY ){\n x -= centerX;\n y -= centerY;\n\n x /= (width / 2 + padding);\n y /= (height / 2 + padding);\n\n return x*x + y*y <= 1;\n }\n };\n\n function generatePolygon( name, points ){\n return ( nodeShapes[name] = {\n name: name,\n\n points: points,\n\n draw: function( context, centerX, centerY, width, height ){\n renderer.nodeShapeImpl('polygon')( context, centerX, centerY, width, height, this.points );\n },\n\n intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){\n return math.polygonIntersectLine(\n x, y,\n this.points,\n nodeX,\n nodeY,\n width / 2, height / 2,\n padding)\n ;\n },\n\n checkPoint: function( x, y, padding, width, height, centerX, centerY ){\n return math.pointInsidePolygon(x, y, nodeShapes[name].points,\n centerX, centerY, width, height, [0, -1], padding)\n ;\n }\n } );\n }\n\n generatePolygon( 'triangle', math.generateUnitNgonPointsFitToSquare(3, 0) );\n\n generatePolygon( 'square', math.generateUnitNgonPointsFitToSquare(4, 0) );\n nodeShapes['rectangle'] = nodeShapes['square'];\n\n nodeShapes['roundrectangle'] = {\n name: 'roundrectangle',\n\n points: math.generateUnitNgonPointsFitToSquare(4, 0),\n\n draw: function( context, centerX, centerY, width, height ){\n renderer.nodeShapeImpl( this.name )( context, centerX, centerY, width, height );\n },\n\n intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){\n return math.roundRectangleIntersectLine(\n x, y,\n nodeX,\n nodeY,\n width, height,\n padding)\n ;\n },\n\n // Looks like the width passed into this function is actually the total width / 2\n checkPoint: function(\n x, y, padding, width, height, centerX, centerY ){\n\n var cornerRadius = math.getRoundRectangleRadius(width, height);\n\n // Check hBox\n if (math.pointInsidePolygon(x, y, this.points,\n centerX, centerY, width, height - 2 * cornerRadius, [0, -1], padding) ){\n return true;\n }\n\n // Check vBox\n if (math.pointInsidePolygon(x, y, this.points,\n centerX, centerY, width - 2 * cornerRadius, height, [0, -1], padding) ){\n return true;\n }\n\n var checkInEllipse = function( x, y, centerX, centerY, width, height, padding ){\n x -= centerX;\n y -= centerY;\n\n x /= (width / 2 + padding);\n y /= (height / 2 + padding);\n\n return (x*x + y*y <= 1);\n };\n\n\n // Check top left quarter circle\n if (checkInEllipse(x, y,\n centerX - width / 2 + cornerRadius,\n centerY - height / 2 + cornerRadius,\n cornerRadius * 2, cornerRadius * 2, padding) ){\n\n return true;\n }\n\n // Check top right quarter circle\n if (checkInEllipse(x, y,\n centerX + width / 2 - cornerRadius,\n centerY - height / 2 + cornerRadius,\n cornerRadius * 2, cornerRadius * 2, padding) ){\n\n return true;\n }\n\n // Check bottom right quarter circle\n if (checkInEllipse(x, y,\n centerX + width / 2 - cornerRadius,\n centerY + height / 2 - cornerRadius,\n cornerRadius * 2, cornerRadius * 2, padding) ){\n\n return true;\n }\n\n // Check bottom left quarter circle\n if (checkInEllipse(x, y,\n centerX - width / 2 + cornerRadius,\n centerY + height / 2 - cornerRadius,\n cornerRadius * 2, cornerRadius * 2, padding) ){\n\n return true;\n }\n\n return false;\n }\n };\n\n generatePolygon( 'diamond', [\n 0, 1,\n 1, 0,\n 0, -1,\n -1, 0\n ] );\n\n generatePolygon( 'pentagon', math.generateUnitNgonPointsFitToSquare(5, 0) );\n\n generatePolygon( 'hexagon', math.generateUnitNgonPointsFitToSquare(6, 0) );\n\n generatePolygon( 'heptagon', math.generateUnitNgonPointsFitToSquare(7, 0) );\n\n generatePolygon( 'octagon', math.generateUnitNgonPointsFitToSquare(8, 0) );\n\n var star5Points = new Array(20);\n {\n var outerPoints = math.generateUnitNgonPoints(5, 0);\n var innerPoints = math.generateUnitNgonPoints(5, Math.PI / 5);\n\n // Outer radius is 1; inner radius of star is smaller\n var innerRadius = 0.5 * (3 - Math.sqrt(5));\n innerRadius *= 1.57;\n\n for (var i=0;i redrawLimit ? minRedrawLimit : redrawLimit;\n redrawLimit = redrawLimit < maxRedrawLimit ? redrawLimit : maxRedrawLimit;\n\n if( r.lastDrawTime === undefined ){ r.lastDrawTime = 0; }\n\n var nowTime = Date.now();\n var timeElapsed = nowTime - r.lastDrawTime;\n var callAfterLimit = timeElapsed >= redrawLimit;\n\n if( !forcedContext ){\n if( !callAfterLimit ){\n r.skipFrame = true;\n return;\n }\n }\n\n r.requestedFrame = true;\n r.renderOptions = options;\n};\n\nBRp.startRenderLoop = function(){\n var r = this;\n\n if( r.renderLoopStarted ){\n return;\n } else {\n r.renderLoopStarted = true;\n }\n\n var renderFn = function(){\n if( r.destroyed ){ return; }\n\n if( r.requestedFrame && !r.skipFrame ){\n var startTime = util.performanceNow();\n\n r.render( r.renderOptions );\n\n var endTime = r.lastRedrawTime = util.performanceNow();\n\n if( r.averageRedrawTime === undefined ){\n r.averageRedrawTime = endTime - startTime;\n }\n\n if( r.redrawCount === undefined ){\n r.redrawCount = 0;\n }\n\n r.redrawCount++;\n\n if( r.redrawTotalTime === undefined ){\n r.redrawTotalTime = 0;\n }\n\n var duration = endTime - startTime;\n\n r.redrawTotalTime += duration;\n r.lastRedrawTime = duration;\n\n // use a weighted average with a bias from the previous average so we don't spike so easily\n r.averageRedrawTime = r.averageRedrawTime/2 + duration/2;\n\n r.requestedFrame = false;\n }\n\n r.skipFrame = false;\n\n util.requestAnimationFrame( renderFn );\n };\n\n util.requestAnimationFrame( renderFn );\n\n};\n\nmodule.exports = BRp;\n","'use strict';\n\nvar CRp = {};\n\nvar impl;\n\nCRp.arrowShapeImpl = function( name ){\n return ( impl || (impl = {\n 'polygon': function( context, points ){\n for( var i = 0; i < points.length; i++ ){\n var pt = points[i];\n\n context.lineTo( pt.x, pt.y );\n }\n },\n\n 'triangle-backcurve': function( context, points, controlPoint ){\n var firstPt;\n\n for( var i = 0; i < points.length; i++ ){\n var pt = points[i];\n\n if( i === 0 ){\n firstPt = pt;\n }\n\n context.lineTo( pt.x, pt.y );\n }\n\n context.quadraticCurveTo( controlPoint.x, controlPoint.y, firstPt.x, firstPt.y );\n },\n\n 'triangle-tee': function( context, trianglePoints, teePoints ){\n var triPts = trianglePoints;\n for( var i = 0; i < triPts.length; i++ ){\n var pt = triPts[i];\n\n context.lineTo( pt.x, pt.y );\n }\n\n var teePts = teePoints;\n var firstTeePt = teePoints[0];\n context.moveTo( firstTeePt.x, firstTeePt.y );\n\n for( var i = 0; i < teePts.length; i++ ){\n var pt = teePts[i];\n\n context.lineTo( pt.x, pt.y );\n }\n },\n\n 'circle': function( context, rx, ry, r ){\n context.arc(rx, ry, r, 0, Math.PI * 2, false);\n }\n }) )[ name ];\n};\n\nmodule.exports = CRp;\n","'use strict';\n\nvar CRp = {};\n\nCRp.drawEdge = function(context, edge, drawOverlayInstead) {\n var rs = edge._private.rscratch;\n var usePaths = this.usePaths();\n\n // if bezier ctrl pts can not be calculated, then die\n if( rs.badBezier || rs.badLine || isNaN( rs.allpts[0] ) ){ // iNaN in case edge is impossible and browser bugs (e.g. safari)\n return;\n }\n\n var style = edge._private.style;\n\n // Edge line width\n if (style['width'].pfValue <= 0) {\n return;\n }\n\n var overlayPadding = style['overlay-padding'].pfValue;\n var overlayOpacity = style['overlay-opacity'].value;\n var overlayColor = style['overlay-color'].value;\n\n // Edge color & opacity\n if( drawOverlayInstead ){\n\n if( overlayOpacity === 0 ){ // exit early if no overlay\n return;\n }\n\n this.strokeStyle(context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity);\n context.lineCap = 'round';\n\n if( rs.edgeType == 'self' && !usePaths ){\n context.lineCap = 'butt';\n }\n\n } else {\n var lineColor = style['line-color'].value;\n\n this.strokeStyle(context, lineColor[0], lineColor[1], lineColor[2], style.opacity.value);\n\n context.lineCap = 'butt';\n }\n\n var edgeWidth = style['width'].pfValue + (drawOverlayInstead ? 2 * overlayPadding : 0);\n var lineStyle = drawOverlayInstead ? 'solid' : style['line-style'].value;\n context.lineWidth = edgeWidth;\n\n var shadowBlur = style['shadow-blur'].pfValue;\n var shadowOpacity = style['shadow-opacity'].value;\n var shadowColor = style['shadow-color'].value;\n var shadowOffsetX = style['shadow-offset-x'].pfValue;\n var shadowOffsetY = style['shadow-offset-y'].pfValue;\n\n this.shadowStyle(context, shadowColor, drawOverlayInstead ? 0 : shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY);\n\n this.drawEdgePath(\n edge,\n context,\n rs.allpts,\n lineStyle,\n edgeWidth\n );\n\n this.drawArrowheads(context, edge, drawOverlayInstead);\n\n this.shadowStyle(context, 'transparent', 0); // reset for next guy\n\n};\n\n\nCRp.drawEdgePath = function(edge, context, pts, type, width) {\n var rs = edge._private.rscratch;\n var canvasCxt = context;\n var path;\n var pathCacheHit = false;\n var usePaths = this.usePaths();\n\n if( usePaths ){\n var pathCacheKey = pts.join('$');\n var keyMatches = rs.pathCacheKey && rs.pathCacheKey === pathCacheKey;\n\n if( keyMatches ){\n path = context = rs.pathCache;\n pathCacheHit = true;\n } else {\n path = context = new Path2D();\n rs.pathCacheKey = pathCacheKey;\n rs.pathCache = path;\n }\n }\n\n if( canvasCxt.setLineDash ){ // for very outofdate browsers\n switch( type ){\n case 'dotted':\n canvasCxt.setLineDash([ 1, 1 ]);\n break;\n\n case 'dashed':\n canvasCxt.setLineDash([ 6, 3 ]);\n break;\n\n case 'solid':\n canvasCxt.setLineDash([ ]);\n break;\n }\n }\n\n if( !pathCacheHit ){\n if( context.beginPath ){ context.beginPath(); }\n context.moveTo( pts[0], pts[1] );\n\n switch( rs.edgeType ){\n case 'bezier':\n case 'self':\n case 'compound':\n case 'multibezier':\n if( !rs.badBezier ){\n for( var i = 2; i + 3 < pts.length; i += 4 ){\n context.quadraticCurveTo( pts[i], pts[i+1], pts[i+2], pts[i+3] );\n }\n }\n break;\n\n case 'straight':\n case 'segments':\n case 'haystack':\n if( !rs.badLine ){\n for( var i = 2; i + 1 < pts.length; i += 2 ){\n context.lineTo( pts[i], pts[i+1] );\n }\n }\n break;\n }\n }\n\n context = canvasCxt;\n if( usePaths ){\n context.stroke( path );\n } else {\n context.stroke();\n }\n\n // reset any line dashes\n if( context.setLineDash ){ // for very outofdate browsers\n context.setLineDash([ ]);\n }\n\n};\n\nCRp.drawArrowheads = function(context, edge, drawOverlayInstead) {\n if( drawOverlayInstead ){ return; } // don't do anything for overlays\n\n var rs = edge._private.rscratch;\n var isHaystack = rs.edgeType === 'haystack';\n\n if( !isHaystack ){\n this.drawArrowhead( context, edge, 'source', rs.arrowStartX, rs.arrowStartY, rs.srcArrowAngle );\n }\n\n this.drawArrowhead( context, edge, 'mid-target', rs.midX, rs.midY, rs.midtgtArrowAngle );\n\n this.drawArrowhead( context, edge, 'mid-source', rs.midX, rs.midY, rs.midsrcArrowAngle );\n\n if( !isHaystack ){\n this.drawArrowhead( context, edge, 'target', rs.arrowEndX, rs.arrowEndY, rs.tgtArrowAngle );\n }\n};\n\nCRp.drawArrowhead = function( context, edge, prefix, x, y, angle ){\n if( isNaN(x) || x == null || isNaN(y) || y == null || isNaN(angle) || angle == null ){ return; }\n\n var self = this;\n var style = edge._private.style;\n var arrowShape = style[prefix + '-arrow-shape'].value;\n\n if( arrowShape === 'none' ){\n return;\n }\n\n var gco = context.globalCompositeOperation;\n\n var arrowClearFill = style[prefix + '-arrow-fill'].value === 'hollow' ? 'both' : 'filled';\n var arrowFill = style[prefix + '-arrow-fill'].value;\n\n if( arrowShape === 'half-triangle-overshot' ){\n arrowFill = 'hollow';\n arrowClearFill = 'hollow';\n }\n\n if( style.opacity.value !== 1 || arrowFill === 'hollow' ){ // then extra clear is needed\n context.globalCompositeOperation = 'destination-out';\n\n self.fillStyle(context, 255, 255, 255, 1);\n self.strokeStyle(context, 255, 255, 255, 1);\n\n self.drawArrowShape( edge, prefix, context,\n arrowClearFill, style['width'].pfValue, style[prefix + '-arrow-shape'].value,\n x, y, angle\n );\n\n context.globalCompositeOperation = gco;\n } // otherwise, the opaque arrow clears it for free :)\n\n var color = style[prefix + '-arrow-color'].value;\n self.fillStyle(context, color[0], color[1], color[2], style.opacity.value);\n self.strokeStyle(context, color[0], color[1], color[2], style.opacity.value);\n\n self.drawArrowShape( edge, prefix, context,\n arrowFill, style['width'].pfValue, style[prefix + '-arrow-shape'].value,\n x, y, angle\n );\n};\n\nCRp.drawArrowShape = function(edge, arrowType, context, fill, edgeWidth, shape, x, y, angle) {\n var r = this;\n var usePaths = this.usePaths();\n var rs = edge._private.rscratch;\n var pathCacheHit = false;\n var path;\n var canvasContext = context;\n var translation = { x: x, y: y };\n var size = this.getArrowWidth( edgeWidth );\n var shapeImpl = r.arrowShapes[shape];\n\n if( usePaths ){\n var pathCacheKey = size + '$' + shape + '$' + angle + '$' + x + '$' + y;\n rs.arrowPathCacheKey = rs.arrowPathCacheKey || {};\n rs.arrowPathCache = rs.arrowPathCache || {};\n\n var alreadyCached = rs.arrowPathCacheKey[arrowType] === pathCacheKey;\n if( alreadyCached ){\n path = context = rs.arrowPathCache[arrowType];\n pathCacheHit = true;\n } else {\n path = context = new Path2D();\n rs.arrowPathCacheKey[arrowType] = pathCacheKey;\n rs.arrowPathCache[arrowType] = path;\n }\n }\n\n if( context.beginPath ){ context.beginPath(); }\n\n if( !pathCacheHit ){\n shapeImpl.draw(context, size, angle, translation);\n }\n\n if( !shapeImpl.leavePathOpen && context.closePath ){\n context.closePath();\n }\n\n context = canvasContext;\n\n if( fill === 'filled' || fill === 'both' ){\n if( usePaths ){\n context.fill( path );\n } else {\n context.fill();\n }\n }\n\n if( fill === 'hollow' || fill === 'both' ){\n context.lineWidth = ( shapeImpl.matchEdgeWidth ? edgeWidth : 1 );\n context.lineJoin = 'miter';\n\n if( usePaths ){\n context.stroke( path );\n } else {\n context.stroke();\n }\n\n }\n};\n\nmodule.exports = CRp;\n","'use strict';\n\nvar CRp = {};\n\nCRp.safeDrawImage = function( context, img, ix, iy, iw, ih, x, y, w, h ){\n var r = this;\n\n try {\n context.drawImage( img, ix, iy, iw, ih, x, y, w, h );\n } catch(e){\n r.data.canvasNeedsRedraw[r.NODE] = true;\n r.data.canvasNeedsRedraw[r.DRAG] = true;\n\n r.drawingImage = true;\n\n r.redraw();\n }\n};\n\nCRp.drawInscribedImage = function(context, img, node) {\n var r = this;\n var nodeX = node._private.position.x;\n var nodeY = node._private.position.y;\n var style = node._private.style;\n var fit = style['background-fit'].value;\n var xPos = style['background-position-x'];\n var yPos = style['background-position-y'];\n var repeat = style['background-repeat'].value;\n var nodeW = node.width();\n var nodeH = node.height();\n var rs = node._private.rscratch;\n var clip = style['background-clip'].value;\n var shouldClip = clip === 'node';\n var imgOpacity = style['background-image-opacity'].value;\n\n var imgW = img.width || img.cachedW;\n var imgH = img.height || img.cachedH;\n\n // workaround for broken browsers like ie\n if( null == imgW || null == imgH ){\n document.body.appendChild( img );\n\n imgW = img.cachedW = img.width || img.offsetWidth;\n imgH = img.cachedH = img.height || img.offsetHeight;\n\n document.body.removeChild( img );\n }\n\n var w = imgW;\n var h = imgH;\n\n var bgW = style['background-width'];\n if( bgW.value !== 'auto' ){\n if( bgW.units === '%' ){\n w = bgW.value/100 * nodeW;\n } else {\n w = bgW.pfValue;\n }\n }\n\n var bgH = style['background-height'];\n if( bgH.value !== 'auto' ){\n if( bgH.units === '%' ){\n h = bgH.value/100 * nodeH;\n } else {\n h = bgH.pfValue;\n }\n }\n\n if( w === 0 || h === 0 ){\n return; // no point in drawing empty image (and chrome is broken in this case)\n }\n\n if( fit === 'contain' ){\n var scale = Math.min( nodeW/w, nodeH/h );\n\n w *= scale;\n h *= scale;\n\n } else if( fit === 'cover' ){\n var scale = Math.max( nodeW/w, nodeH/h );\n\n w *= scale;\n h *= scale;\n }\n\n var x = (nodeX - nodeW/2); // left\n if( xPos.units === '%' ){\n x += (nodeW - w) * xPos.value/100;\n } else {\n x += xPos.pfValue;\n }\n\n var y = (nodeY - nodeH/2); // top\n if( yPos.units === '%' ){\n y += (nodeH - h) * yPos.value/100;\n } else {\n y += yPos.pfValue;\n }\n\n if( rs.pathCache ){\n x -= nodeX;\n y -= nodeY;\n\n nodeX = 0;\n nodeY = 0;\n }\n\n var gAlpha = context.globalAlpha;\n\n context.globalAlpha = imgOpacity;\n\n if( repeat === 'no-repeat' ){\n\n if( shouldClip ){\n context.save();\n\n if( rs.pathCache ){\n context.clip( rs.pathCache );\n } else {\n r.nodeShapes[r.getNodeShape(node)].draw(\n context,\n nodeX, nodeY,\n nodeW, nodeH);\n\n context.clip();\n }\n }\n\n r.safeDrawImage( context, img, 0, 0, imgW, imgH, x, y, w, h );\n\n if( shouldClip ){\n context.restore();\n }\n } else {\n var pattern = context.createPattern( img, repeat );\n context.fillStyle = pattern;\n\n r.nodeShapes[r.getNodeShape(node)].draw(\n context,\n nodeX, nodeY,\n nodeW, nodeH);\n\n context.translate(x, y);\n context.fill();\n context.translate(-x, -y);\n }\n\n context.globalAlpha = gAlpha;\n\n};\n\nmodule.exports = CRp;\n","'use strict';\n\nvar is = require('../../../is');\n\nvar CRp = {};\n\n// Draw edge text\nCRp.drawEdgeText = function(context, edge) {\n var text = edge._private.style['label'].strValue;\n\n if( !text || text.match(/^\\s+$/) ){\n return;\n }\n\n if( this.hideEdgesOnViewport && (this.dragData.didDrag || this.pinching || this.hoverData.dragging || this.data.wheel || this.swipePanning) ){ return; } // save cycles on pinching\n\n var computedSize = edge._private.style['font-size'].pfValue * edge.cy().zoom();\n var minSize = edge._private.style['min-zoomed-font-size'].pfValue;\n\n if( computedSize < minSize ){\n return;\n }\n\n // Calculate text draw position\n\n context.textAlign = 'center';\n context.textBaseline = 'middle';\n\n var rs = edge._private.rscratch;\n if( !is.number( rs.labelX ) || !is.number( rs.labelY ) ){ return; } // no pos => label can't be rendered\n\n var style = edge._private.style;\n var autorotate = style['edge-text-rotation'].strValue === 'autorotate';\n var theta;\n\n if( autorotate ){\n theta = rs.labelAngle;\n\n context.translate(rs.labelX, rs.labelY);\n context.rotate(theta);\n\n this.drawText(context, edge, 0, 0);\n\n context.rotate(-theta);\n context.translate(-rs.labelX, -rs.labelY);\n } else {\n this.drawText(context, edge, rs.labelX, rs.labelY);\n }\n\n};\n\n// Draw node text\nCRp.drawNodeText = function(context, node) {\n var text = node._private.style['label'].strValue;\n\n if ( !text || text.match(/^\\s+$/) ) {\n return;\n }\n\n var computedSize = node._private.style['font-size'].pfValue * node.cy().zoom();\n var minSize = node._private.style['min-zoomed-font-size'].pfValue;\n\n if( computedSize < minSize ){\n return;\n }\n\n // this.recalculateNodeLabelProjection( node );\n\n var textHalign = node._private.style['text-halign'].strValue;\n var textValign = node._private.style['text-valign'].strValue;\n var rs = node._private.rscratch;\n if( !is.number( rs.labelX ) || !is.number( rs.labelY ) ){ return; } // no pos => label can't be rendered\n\n switch( textHalign ){\n case 'left':\n context.textAlign = 'right';\n break;\n\n case 'right':\n context.textAlign = 'left';\n break;\n\n default: // e.g. center\n context.textAlign = 'center';\n }\n\n switch( textValign ){\n case 'top':\n context.textBaseline = 'bottom';\n break;\n\n case 'bottom':\n context.textBaseline = 'top';\n break;\n\n default: // e.g. center\n context.textBaseline = 'middle';\n }\n\n this.drawText(context, node, rs.labelX, rs.labelY);\n};\n\nCRp.getFontCache = function(context){\n var cache;\n\n this.fontCaches = this.fontCaches || [];\n\n for( var i = 0; i < this.fontCaches.length; i++ ){\n cache = this.fontCaches[i];\n\n if( cache.context === context ){\n return cache;\n }\n }\n\n cache = {\n context: context\n };\n this.fontCaches.push(cache);\n\n return cache;\n};\n\n// set up canvas context with font\n// returns transformed text string\nCRp.setupTextStyle = function( context, element ){\n // Font style\n var parentOpacity = element.effectiveOpacity();\n var style = element._private.style;\n var labelStyle = style['font-style'].strValue;\n var labelSize = style['font-size'].pfValue + 'px';\n var labelFamily = style['font-family'].strValue;\n var labelWeight = style['font-weight'].strValue;\n var opacity = style['text-opacity'].value * style['opacity'].value * parentOpacity;\n var outlineOpacity = style['text-outline-opacity'].value * opacity;\n var color = style['color'].value;\n var outlineColor = style['text-outline-color'].value;\n var shadowBlur = style['text-shadow-blur'].pfValue;\n var shadowOpacity = style['text-shadow-opacity'].value;\n var shadowColor = style['text-shadow-color'].value;\n var shadowOffsetX = style['text-shadow-offset-x'].pfValue;\n var shadowOffsetY = style['text-shadow-offset-y'].pfValue;\n\n var fontCacheKey = element._private.fontKey;\n var cache = this.getFontCache(context);\n\n if( cache.key !== fontCacheKey ){\n context.font = labelStyle + ' ' + labelWeight + ' ' + labelSize + ' ' + labelFamily;\n\n cache.key = fontCacheKey;\n }\n\n var text = this.getLabelText( element );\n\n // Calculate text draw position based on text alignment\n\n // so text outlines aren't jagged\n context.lineJoin = 'round';\n\n this.fillStyle(context, color[0], color[1], color[2], opacity);\n\n this.strokeStyle(context, outlineColor[0], outlineColor[1], outlineColor[2], outlineOpacity);\n\n this.shadowStyle(context, shadowColor, shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY);\n\n return text;\n};\n\nfunction roundRect(ctx, x, y, width, height, radius) {\n var radius = radius || 5;\n ctx.beginPath();\n ctx.moveTo(x + radius, y);\n ctx.lineTo(x + width - radius, y);\n ctx.quadraticCurveTo(x + width, y, x + width, y + radius);\n ctx.lineTo(x + width, y + height - radius);\n ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);\n ctx.lineTo(x + radius, y + height);\n ctx.quadraticCurveTo(x, y + height, x, y + height - radius);\n ctx.lineTo(x, y + radius);\n ctx.quadraticCurveTo(x, y, x + radius, y);\n ctx.closePath();\n ctx.fill();\n}\n\n// Draw text\nCRp.drawText = function(context, element, textX, textY) {\n var _p = element._private;\n var style = _p.style;\n var rstyle = _p.rstyle;\n var rscratch = _p.rscratch;\n var parentOpacity = element.effectiveOpacity();\n if( parentOpacity === 0 || style['text-opacity'].value === 0){ return; }\n\n var text = this.setupTextStyle( context, element );\n var halign = style['text-halign'].value;\n var valign = style['text-valign'].value;\n\n if( element.isEdge() ){\n halign = 'center';\n valign = 'center';\n }\n\n if( element.isNode() ){\n var pLeft = style['padding-left'].pfValue;\n var pRight = style['padding-right'].pfValue;\n var pTop = style['padding-top'].pfValue;\n var pBottom = style['padding-bottom'].pfValue;\n\n textX += pLeft/2;\n textX -= pRight/2;\n\n textY += pTop/2;\n textY -= pBottom/2;\n }\n\n if ( text != null && !isNaN(textX) && !isNaN(textY)) {\n var backgroundOpacity = style['text-background-opacity'].value;\n var borderOpacity = style['text-border-opacity'].value;\n var textBorderWidth = style['text-border-width'].pfValue;\n\n if( backgroundOpacity > 0 || (textBorderWidth > 0 && borderOpacity > 0) ){\n var margin = 4 + textBorderWidth/2;\n\n if (element.isNode()) {\n //Move textX, textY to include the background margins\n if (valign === 'top') {\n textY -= margin;\n } else if (valign === 'bottom') {\n textY += margin;\n }\n if (halign === 'left') {\n textX -= margin;\n } else if (halign === 'right') {\n textX += margin;\n }\n }\n\n var bgWidth = rstyle.labelWidth;\n var bgHeight = rstyle.labelHeight;\n var bgX = textX;\n\n if (halign) {\n if (halign == 'center') {\n bgX = bgX - bgWidth / 2;\n } else if (halign == 'left') {\n bgX = bgX- bgWidth;\n }\n }\n\n var bgY = textY;\n\n if (element.isNode()) {\n if (valign == 'top') {\n bgY = bgY - bgHeight;\n } else if (valign == 'center') {\n bgY = bgY- bgHeight / 2;\n }\n } else {\n bgY = bgY - bgHeight / 2;\n }\n\n if (style['edge-text-rotation'].strValue === 'autorotate') {\n textY = 0;\n bgWidth += 4;\n bgX = textX - bgWidth / 2;\n bgY = textY - bgHeight / 2;\n } else {\n // Adjust with border width & margin\n bgX -= margin;\n bgY -= margin;\n bgHeight += margin*2;\n bgWidth += margin*2;\n }\n\n if( backgroundOpacity > 0 ){\n var textFill = context.fillStyle;\n var textBackgroundColor = style['text-background-color'].value;\n\n context.fillStyle = 'rgba(' + textBackgroundColor[0] + ',' + textBackgroundColor[1] + ',' + textBackgroundColor[2] + ',' + backgroundOpacity * parentOpacity + ')';\n var styleShape = style['text-background-shape'].strValue;\n if (styleShape == 'roundrectangle') {\n roundRect(context, bgX, bgY, bgWidth, bgHeight, 2);\n } else {\n context.fillRect(bgX,bgY,bgWidth,bgHeight);\n }\n context.fillStyle = textFill;\n }\n\n if( textBorderWidth > 0 && borderOpacity > 0 ){\n var textStroke = context.strokeStyle;\n var textLineWidth = context.lineWidth;\n var textBorderColor = style['text-border-color'].value;\n var textBorderStyle = style['text-border-style'].value;\n\n context.strokeStyle = 'rgba(' + textBorderColor[0] + ',' + textBorderColor[1] + ',' + textBorderColor[2] + ',' + borderOpacity * parentOpacity + ')';\n context.lineWidth = textBorderWidth;\n\n if( context.setLineDash ){ // for very outofdate browsers\n switch( textBorderStyle ){\n case 'dotted':\n context.setLineDash([ 1, 1 ]);\n break;\n case 'dashed':\n context.setLineDash([ 4, 2 ]);\n break;\n case 'double':\n context.lineWidth = textBorderWidth/4; // 50% reserved for white between the two borders\n context.setLineDash([ ]);\n break;\n case 'solid':\n context.setLineDash([ ]);\n break;\n }\n }\n\n context.strokeRect(bgX,bgY,bgWidth,bgHeight);\n\n if( textBorderStyle === 'double' ){\n var whiteWidth = textBorderWidth/2;\n\n context.strokeRect(bgX+whiteWidth,bgY+whiteWidth,bgWidth-whiteWidth*2,bgHeight-whiteWidth*2);\n }\n\n if( context.setLineDash ){ // for very outofdate browsers\n context.setLineDash([ ]);\n }\n context.lineWidth = textLineWidth;\n context.strokeStyle = textStroke;\n }\n\n }\n\n var lineWidth = 2 * style['text-outline-width'].pfValue; // *2 b/c the stroke is drawn centred on the middle\n\n if( lineWidth > 0 ){\n context.lineWidth = lineWidth;\n }\n\n if( style['text-wrap'].value === 'wrap' ){\n var lines = rscratch.labelWrapCachedLines;\n var lineHeight = rstyle.labelHeight / lines.length;\n\n switch( valign ){\n case 'top':\n textY -= (lines.length - 1) * lineHeight;\n break;\n\n case 'bottom':\n // nothing required\n break;\n\n default:\n case 'center':\n textY -= (lines.length - 1) * lineHeight / 2;\n }\n\n for( var l = 0; l < lines.length; l++ ){\n if( lineWidth > 0 ){\n context.strokeText( lines[l], textX, textY );\n }\n\n context.fillText( lines[l], textX, textY );\n\n textY += lineHeight;\n }\n\n } else {\n if( lineWidth > 0 ){\n context.strokeText( text, textX, textY );\n }\n\n context.fillText( text, textX, textY );\n }\n\n\n this.shadowStyle(context, 'transparent', 0); // reset for next guy\n }\n};\n\n\nmodule.exports = CRp;\n","'use strict';\n\nvar is = require('../../../is');\n\nvar CRp = {};\n\n// Draw node\nCRp.drawNode = function(context, node, drawOverlayInstead) {\n\n var r = this;\n var nodeWidth, nodeHeight;\n var style = node._private.style;\n var rs = node._private.rscratch;\n var _p = node._private;\n var pos = _p.position;\n\n if( !is.number(pos.x) || !is.number(pos.y) ){\n return; // can't draw node with undefined position\n }\n\n var usePaths = this.usePaths();\n var canvasContext = context;\n var path;\n var pathCacheHit = false;\n\n var overlayPadding = style['overlay-padding'].pfValue;\n var overlayOpacity = style['overlay-opacity'].value;\n var overlayColor = style['overlay-color'].value;\n\n if( drawOverlayInstead && overlayOpacity === 0 ){ // exit early if drawing overlay but none to draw\n return;\n }\n\n var parentOpacity = node.effectiveOpacity();\n if( parentOpacity === 0 ){ return; }\n\n nodeWidth = node.width() + style['padding-left'].pfValue + style['padding-right'].pfValue;\n nodeHeight = node.height() + style['padding-top'].pfValue + style['padding-bottom'].pfValue;\n\n context.lineWidth = style['border-width'].pfValue;\n\n if( drawOverlayInstead === undefined || !drawOverlayInstead ){\n\n var url = style['background-image'].value[2] ||\n style['background-image'].value[1];\n var image;\n\n if (url !== undefined) {\n\n // get image, and if not loaded then ask to redraw when later loaded\n image = this.getCachedImage(url, function(){\n r.data.canvasNeedsRedraw[r.NODE] = true;\n r.data.canvasNeedsRedraw[r.DRAG] = true;\n\n r.drawingImage = true;\n\n r.redraw();\n });\n\n var prevBging = _p.backgrounding;\n _p.backgrounding = !image.complete;\n\n if( prevBging !== _p.backgrounding ){ // update style b/c :backgrounding state changed\n node.updateStyle( false );\n }\n }\n\n // Node color & opacity\n\n var bgColor = style['background-color'].value;\n var borderColor = style['border-color'].value;\n var borderStyle = style['border-style'].value;\n\n this.fillStyle(context, bgColor[0], bgColor[1], bgColor[2], style['background-opacity'].value * parentOpacity);\n\n this.strokeStyle(context, borderColor[0], borderColor[1], borderColor[2], style['border-opacity'].value * parentOpacity);\n\n var shadowBlur = style['shadow-blur'].pfValue;\n var shadowOpacity = style['shadow-opacity'].value;\n var shadowColor = style['shadow-color'].value;\n var shadowOffsetX = style['shadow-offset-x'].pfValue;\n var shadowOffsetY = style['shadow-offset-y'].pfValue;\n\n this.shadowStyle(context, shadowColor, shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY);\n\n context.lineJoin = 'miter'; // so borders are square with the node shape\n\n if( context.setLineDash ){ // for very outofdate browsers\n switch( borderStyle ){\n case 'dotted':\n context.setLineDash([ 1, 1 ]);\n break;\n\n case 'dashed':\n context.setLineDash([ 4, 2 ]);\n break;\n\n case 'solid':\n case 'double':\n context.setLineDash([ ]);\n break;\n }\n }\n\n\n var styleShape = style['shape'].strValue;\n\n if( usePaths ){\n var pathCacheKey = styleShape + '$' + nodeWidth +'$' + nodeHeight;\n\n context.translate( pos.x, pos.y );\n\n if( rs.pathCacheKey === pathCacheKey ){\n path = context = rs.pathCache;\n pathCacheHit = true;\n } else {\n path = context = new Path2D();\n rs.pathCacheKey = pathCacheKey;\n rs.pathCache = path;\n }\n }\n\n if( !pathCacheHit ){\n\n var npos = pos;\n\n if( usePaths ){\n npos = {\n x: 0,\n y: 0\n };\n }\n\n r.nodeShapes[this.getNodeShape(node)].draw(\n context,\n npos.x,\n npos.y,\n nodeWidth,\n nodeHeight);\n }\n\n context = canvasContext;\n\n if( usePaths ){\n context.fill( path );\n } else {\n context.fill();\n }\n\n this.shadowStyle(context, 'transparent', 0); // reset for next guy\n\n if (url !== undefined) {\n if( image.complete ){\n this.drawInscribedImage(context, image, node);\n }\n }\n\n var darkness = style['background-blacken'].value;\n var borderWidth = style['border-width'].pfValue;\n\n if( this.hasPie(node) ){\n this.drawPie( context, node, parentOpacity );\n\n // redraw path for blacken and border\n if( darkness !== 0 || borderWidth !== 0 ){\n\n if( !usePaths ){\n r.nodeShapes[this.getNodeShape(node)].draw(\n context,\n pos.x,\n pos.y,\n nodeWidth,\n nodeHeight);\n }\n }\n }\n\n if( darkness > 0 ){\n this.fillStyle(context, 0, 0, 0, darkness);\n\n if( usePaths ){\n context.fill( path );\n } else {\n context.fill();\n }\n\n } else if( darkness < 0 ){\n this.fillStyle(context, 255, 255, 255, -darkness);\n\n if( usePaths ){\n context.fill( path );\n } else {\n context.fill();\n }\n }\n\n // Border width, draw border\n if (borderWidth > 0) {\n\n if( usePaths ){\n context.stroke( path );\n } else {\n context.stroke();\n }\n\n if( borderStyle === 'double' ){\n context.lineWidth = style['border-width'].pfValue/3;\n\n var gco = context.globalCompositeOperation;\n context.globalCompositeOperation = 'destination-out';\n\n if( usePaths ){\n context.stroke( path );\n } else {\n context.stroke();\n }\n\n context.globalCompositeOperation = gco;\n }\n\n }\n\n if( usePaths ){\n context.translate( -pos.x, -pos.y );\n }\n\n // reset in case we changed the border style\n if( context.setLineDash ){ // for very outofdate browsers\n context.setLineDash([ ]);\n }\n\n // draw the overlay\n } else {\n\n if( overlayOpacity > 0 ){\n this.fillStyle(context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity);\n\n r.nodeShapes['roundrectangle'].draw(\n context,\n node._private.position.x,\n node._private.position.y,\n nodeWidth + overlayPadding * 2,\n nodeHeight + overlayPadding * 2\n );\n\n context.fill();\n }\n }\n\n};\n\n// does the node have at least one pie piece?\nCRp.hasPie = function(node){\n node = node[0]; // ensure ele ref\n\n return node._private.hasPie;\n};\n\nCRp.drawPie = function( context, node, nodeOpacity ){\n node = node[0]; // ensure ele ref\n\n var _p = node._private;\n var cyStyle = node.cy().style();\n var style = _p.style;\n var pieSize = style['pie-size'];\n var nodeW = node.width();\n var nodeH = node.height();\n var x = _p.position.x;\n var y = _p.position.y;\n var radius = Math.min( nodeW, nodeH ) / 2; // must fit in node\n var lastPercent = 0; // what % to continue drawing pie slices from on [0, 1]\n var usePaths = this.usePaths();\n\n if( usePaths ){\n x = 0;\n y = 0;\n }\n\n if( pieSize.units === '%' ){\n radius = radius * pieSize.value / 100;\n } else if( pieSize.pfValue !== undefined ){\n radius = pieSize.pfValue / 2;\n }\n\n for( var i = 1; i <= cyStyle.pieBackgroundN; i++ ){ // 1..N\n var size = style['pie-' + i + '-background-size'].value;\n var color = style['pie-' + i + '-background-color'].value;\n var opacity = style['pie-' + i + '-background-opacity'].value * nodeOpacity;\n var percent = size / 100; // map integer range [0, 100] to [0, 1]\n\n // percent can't push beyond 1\n if( percent + lastPercent > 1 ){\n percent = 1 - lastPercent;\n }\n\n var angleStart = 1.5 * Math.PI + 2 * Math.PI * lastPercent; // start at 12 o'clock and go clockwise\n var angleDelta = 2 * Math.PI * percent;\n var angleEnd = angleStart + angleDelta;\n\n // ignore if\n // - zero size\n // - we're already beyond the full circle\n // - adding the current slice would go beyond the full circle\n if( size === 0 || lastPercent >= 1 || lastPercent + percent > 1 ){\n continue;\n }\n\n context.beginPath();\n context.moveTo(x, y);\n context.arc( x, y, radius, angleStart, angleEnd );\n context.closePath();\n\n this.fillStyle(context, color[0], color[1], color[2], opacity);\n\n context.fill();\n\n lastPercent += percent;\n }\n\n};\n\n\nmodule.exports = CRp;\n","'use strict';\n\nvar CRp = {};\n\nvar util = require('../../../util');\nvar math = require('../../../math');\n\nvar motionBlurDelay = 100;\n\n// var isFirefox = typeof InstallTrigger !== 'undefined';\n\nCRp.getPixelRatio = function(){\n var context = this.data.contexts[0];\n\n if( this.forcedPixelRatio != null ){\n return this.forcedPixelRatio;\n }\n\n var backingStore = context.backingStorePixelRatio ||\n context.webkitBackingStorePixelRatio ||\n context.mozBackingStorePixelRatio ||\n context.msBackingStorePixelRatio ||\n context.oBackingStorePixelRatio ||\n context.backingStorePixelRatio || 1;\n\n return (window.devicePixelRatio || 1) / backingStore;\n};\n\nCRp.paintCache = function(context){\n var caches = this.paintCaches = this.paintCaches || [];\n var needToCreateCache = true;\n var cache;\n\n for(var i = 0; i < caches.length; i++ ){\n cache = caches[i];\n\n if( cache.context === context ){\n needToCreateCache = false;\n break;\n }\n }\n\n if( needToCreateCache ){\n cache = {\n context: context\n };\n caches.push( cache );\n }\n\n return cache;\n};\n\nCRp.fillStyle = function(context, r, g, b, a){\n context.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';\n\n // turn off for now, seems context does its own caching\n\n // var cache = this.paintCache(context);\n\n // var fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';\n\n // if( cache.fillStyle !== fillStyle ){\n // context.fillStyle = cache.fillStyle = fillStyle;\n // }\n};\n\nCRp.strokeStyle = function(context, r, g, b, a){\n context.strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';\n\n // turn off for now, seems context does its own caching\n\n // var cache = this.paintCache(context);\n\n // var strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';\n\n // if( cache.strokeStyle !== strokeStyle ){\n // context.strokeStyle = cache.strokeStyle = strokeStyle;\n // }\n};\n\nCRp.shadowStyle = function(context, color, opacity, blur, offsetX, offsetY){\n var zoom = this.cy.zoom();\n\n var cache = this.paintCache(context);\n\n // don't make expensive changes to the shadow style if it's not used\n if( cache.shadowOpacity === 0 && opacity === 0 ){\n return;\n }\n\n cache.shadowOpacity = opacity;\n\n if (opacity > 0) {\n context.shadowBlur = blur * zoom;\n context.shadowColor = \"rgba(\" + color[0] + \",\" + color[1] + \",\" + color[2] + \",\" + opacity + \")\";\n context.shadowOffsetX = offsetX * zoom;\n context.shadowOffsetY = offsetY * zoom;\n } else {\n context.shadowBlur = 0;\n context.shadowColor = \"transparent\";\n }\n};\n\n// Resize canvas\nCRp.matchCanvasSize = function(container) {\n var r = this;\n var data = r.data;\n var width = container.clientWidth;\n var height = container.clientHeight;\n var pixelRatio = r.getPixelRatio();\n var mbPxRatio = r.motionBlurPxRatio;\n\n if(\n container === r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_NODE] ||\n container === r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_DRAG]\n ){\n pixelRatio = mbPxRatio;\n }\n\n var canvasWidth = width * pixelRatio;\n var canvasHeight = height * pixelRatio;\n var canvas;\n\n if( canvasWidth === r.canvasWidth && canvasHeight === r.canvasHeight ){\n return; // save cycles if same\n }\n\n r.fontCaches = null; // resizing resets the style\n\n var canvasContainer = data.canvasContainer;\n canvasContainer.style.width = width + 'px';\n canvasContainer.style.height = height + 'px';\n\n for (var i = 0; i < r.CANVAS_LAYERS; i++) {\n\n canvas = data.canvases[i];\n\n if (canvas.width !== canvasWidth || canvas.height !== canvasHeight) {\n\n canvas.width = canvasWidth;\n canvas.height = canvasHeight;\n\n canvas.style.width = width + 'px';\n canvas.style.height = height + 'px';\n }\n }\n\n for (var i = 0; i < r.BUFFER_COUNT; i++) {\n\n canvas = data.bufferCanvases[i];\n\n if (canvas.width !== canvasWidth || canvas.height !== canvasHeight) {\n\n canvas.width = canvasWidth;\n canvas.height = canvasHeight;\n\n canvas.style.width = width + 'px';\n canvas.style.height = height + 'px';\n }\n }\n\n r.textureMult = 1;\n if( pixelRatio <= 1 ){\n canvas = data.bufferCanvases[ r.TEXTURE_BUFFER ];\n\n r.textureMult = 2;\n canvas.width = canvasWidth * r.textureMult;\n canvas.height = canvasHeight * r.textureMult;\n }\n\n r.canvasWidth = canvasWidth;\n r.canvasHeight = canvasHeight;\n\n};\n\nCRp.renderTo = function( cxt, zoom, pan, pxRatio ){\n this.render({\n forcedContext: cxt,\n forcedZoom: zoom,\n forcedPan: pan,\n drawAllLayers: true,\n forcedPxRatio: pxRatio\n });\n};\n\nCRp.render = function( options ) {\n options = options || util.staticEmptyObject();\n\n var forcedContext = options.forcedContext;\n var drawAllLayers = options.drawAllLayers;\n var drawOnlyNodeLayer = options.drawOnlyNodeLayer;\n var forcedZoom = options.forcedZoom;\n var forcedPan = options.forcedPan;\n var r = this;\n var pixelRatio = options.forcedPxRatio === undefined ? this.getPixelRatio() : options.forcedPxRatio;\n var cy = r.cy; var data = r.data;\n var needDraw = data.canvasNeedsRedraw;\n var textureDraw = r.textureOnViewport && !forcedContext && (r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming);\n var motionBlur = options.motionBlur !== undefined ? options.motionBlur : r.motionBlur;\n var mbPxRatio = r.motionBlurPxRatio;\n var hasCompoundNodes = cy.hasCompoundNodes();\n var inNodeDragGesture = r.hoverData.draggingEles;\n var inBoxSelection = r.hoverData.selecting || r.touchData.selecting ? true : false;\n motionBlur = motionBlur && !forcedContext && r.motionBlurEnabled && !inBoxSelection;\n var motionBlurFadeEffect = motionBlur;\n\n if( !forcedContext ){\n if( r.prevPxRatio !== pixelRatio ){\n r.invalidateContainerClientCoordsCache();\n r.matchCanvasSize( r.container );\n\n r.redrawHint('eles', true);\n r.redrawHint('drag', true);\n }\n\n r.prevPxRatio = pixelRatio;\n }\n\n if( !forcedContext && r.motionBlurTimeout ){\n clearTimeout( r.motionBlurTimeout );\n }\n\n if( motionBlur ){\n if( r.mbFrames == null ){\n r.mbFrames = 0;\n }\n\n if( !r.drawingImage ){ // image loading frames don't count towards motion blur blurry frames\n r.mbFrames++;\n }\n\n if( r.mbFrames < 3 ){ // need several frames before even high quality motionblur\n motionBlurFadeEffect = false;\n }\n\n // go to lower quality blurry frames when several m/b frames have been rendered (avoids flashing)\n if( r.mbFrames > r.minMbLowQualFrames ){\n //r.fullQualityMb = false;\n r.motionBlurPxRatio = r.mbPxRBlurry;\n }\n }\n\n if( r.clearingMotionBlur ){\n r.motionBlurPxRatio = 1;\n }\n\n // b/c drawToContext() may be async w.r.t. redraw(), keep track of last texture frame\n // because a rogue async texture frame would clear needDraw\n if( r.textureDrawLastFrame && !textureDraw ){\n needDraw[r.NODE] = true;\n needDraw[r.SELECT_BOX] = true;\n }\n\n var edges = r.getCachedEdges();\n var coreStyle = cy.style()._private.coreStyle;\n\n var zoom = cy.zoom();\n var effectiveZoom = forcedZoom !== undefined ? forcedZoom : zoom;\n var pan = cy.pan();\n var effectivePan = {\n x: pan.x,\n y: pan.y\n };\n\n var vp = {\n zoom: zoom,\n pan: {\n x: pan.x,\n y: pan.y\n }\n };\n var prevVp = r.prevViewport;\n var viewportIsDiff = prevVp === undefined || vp.zoom !== prevVp.zoom || vp.pan.x !== prevVp.pan.x || vp.pan.y !== prevVp.pan.y;\n\n // we want the low quality motionblur only when the viewport is being manipulated etc (where it's not noticed)\n if( !viewportIsDiff && !(inNodeDragGesture && !hasCompoundNodes) ){\n r.motionBlurPxRatio = 1;\n }\n\n if( forcedPan ){\n effectivePan = forcedPan;\n }\n\n // apply pixel ratio\n\n effectiveZoom *= pixelRatio;\n effectivePan.x *= pixelRatio;\n effectivePan.y *= pixelRatio;\n\n var eles = {\n drag: {\n nodes: [],\n edges: [],\n eles: []\n },\n nondrag: {\n nodes: [],\n edges: [],\n eles: []\n }\n };\n\n function mbclear( context, x, y, w, h ){\n var gco = context.globalCompositeOperation;\n\n context.globalCompositeOperation = 'destination-out';\n r.fillStyle( context, 255, 255, 255, r.motionBlurTransparency );\n context.fillRect(x, y, w, h);\n\n context.globalCompositeOperation = gco;\n }\n\n function setContextTransform(context, clear){\n var ePan, eZoom, w, h;\n\n if( !r.clearingMotionBlur && (context === data.bufferContexts[r.MOTIONBLUR_BUFFER_NODE] || context === data.bufferContexts[r.MOTIONBLUR_BUFFER_DRAG]) ){\n ePan = {\n x: pan.x * mbPxRatio,\n y: pan.y * mbPxRatio\n };\n\n eZoom = zoom * mbPxRatio;\n\n w = r.canvasWidth * mbPxRatio;\n h = r.canvasHeight * mbPxRatio;\n } else {\n ePan = effectivePan;\n eZoom = effectiveZoom;\n\n w = r.canvasWidth;\n h = r.canvasHeight;\n }\n\n context.setTransform(1, 0, 0, 1, 0, 0);\n\n if( clear === 'motionBlur' ){\n mbclear(context, 0, 0, w, h);\n } else if( !forcedContext && (clear === undefined || clear) ){\n context.clearRect(0, 0, w, h);\n }\n\n if( !drawAllLayers ){\n context.translate( ePan.x, ePan.y );\n context.scale( eZoom, eZoom );\n }\n if( forcedPan ){\n context.translate( forcedPan.x, forcedPan.y );\n }\n if( forcedZoom ){\n context.scale( forcedZoom, forcedZoom );\n }\n }\n\n if( !textureDraw ){\n r.textureDrawLastFrame = false;\n }\n\n if( textureDraw ){\n r.textureDrawLastFrame = true;\n\n var bb;\n\n if( !r.textureCache ){\n r.textureCache = {};\n\n bb = r.textureCache.bb = cy.elements().boundingBox();\n\n r.textureCache.texture = r.data.bufferCanvases[ r.TEXTURE_BUFFER ];\n\n var cxt = r.data.bufferContexts[ r.TEXTURE_BUFFER ];\n\n cxt.setTransform(1, 0, 0, 1, 0, 0);\n cxt.clearRect(0, 0, r.canvasWidth * r.textureMult, r.canvasHeight * r.textureMult);\n\n r.render({\n forcedContext: cxt,\n drawOnlyNodeLayer: true,\n forcedPxRatio: pixelRatio * r.textureMult\n });\n\n var vp = r.textureCache.viewport = {\n zoom: cy.zoom(),\n pan: cy.pan(),\n width: r.canvasWidth,\n height: r.canvasHeight\n };\n\n vp.mpan = {\n x: (0 - vp.pan.x)/vp.zoom,\n y: (0 - vp.pan.y)/vp.zoom\n };\n }\n\n needDraw[r.DRAG] = false;\n needDraw[r.NODE] = false;\n\n var context = data.contexts[r.NODE];\n\n var texture = r.textureCache.texture;\n var vp = r.textureCache.viewport;\n bb = r.textureCache.bb;\n\n context.setTransform(1, 0, 0, 1, 0, 0);\n\n if( motionBlur ){\n mbclear(context, 0, 0, vp.width, vp.height);\n } else {\n context.clearRect(0, 0, vp.width, vp.height);\n }\n\n var outsideBgColor = coreStyle['outside-texture-bg-color'].value;\n var outsideBgOpacity = coreStyle['outside-texture-bg-opacity'].value;\n r.fillStyle( context, outsideBgColor[0], outsideBgColor[1], outsideBgColor[2], outsideBgOpacity );\n context.fillRect( 0, 0, vp.width, vp.height );\n\n var zoom = cy.zoom();\n\n setContextTransform( context, false );\n\n context.clearRect( vp.mpan.x, vp.mpan.y, vp.width/vp.zoom/pixelRatio, vp.height/vp.zoom/pixelRatio );\n context.drawImage( texture, vp.mpan.x, vp.mpan.y, vp.width/vp.zoom/pixelRatio, vp.height/vp.zoom/pixelRatio );\n\n } else if( r.textureOnViewport && !forcedContext ){ // clear the cache since we don't need it\n r.textureCache = null;\n }\n\n var vpManip = (r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming || r.hoverData.draggingEles);\n var hideEdges = r.hideEdgesOnViewport && vpManip;\n var hideLabels = r.hideLabelsOnViewport && vpManip;\n\n if (needDraw[r.DRAG] || needDraw[r.NODE] || drawAllLayers || drawOnlyNodeLayer) {\n if( hideEdges ){\n } else {\n r.findEdgeControlPoints(edges);\n }\n\n var zEles = r.getCachedZSortedEles();\n var extent = cy.extent();\n\n for (var i = 0; i < zEles.length; i++) {\n var ele = zEles[i];\n var list;\n var bb = forcedContext ? null : ele.boundingBox();\n var insideExtent = forcedContext ? true : math.boundingBoxesIntersect( extent, bb );\n\n if( !insideExtent ){ continue; } // no need to render\n\n if ( ele._private.rscratch.inDragLayer ) {\n list = eles.drag;\n } else {\n list = eles.nondrag;\n }\n\n list.eles.push( ele );\n }\n\n }\n\n\n function drawElements( list, context ){\n var eles = list.eles;\n\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n\n if( ele.isNode() ){\n r.drawNode(context, ele);\n\n if( !hideLabels ){\n r.drawNodeText(context, ele);\n }\n\n r.drawNode(context, ele, true);\n } else if( !hideEdges ) {\n r.drawEdge(context, ele);\n\n if( !hideLabels ){\n r.drawEdgeText(context, ele);\n }\n\n r.drawEdge(context, ele, true);\n }\n\n\n }\n\n }\n\n var needMbClear = [];\n\n needMbClear[r.NODE] = !needDraw[r.NODE] && motionBlur && !r.clearedForMotionBlur[r.NODE] || r.clearingMotionBlur;\n if( needMbClear[r.NODE] ){ r.clearedForMotionBlur[r.NODE] = true; }\n\n needMbClear[r.DRAG] = !needDraw[r.DRAG] && motionBlur && !r.clearedForMotionBlur[r.DRAG] || r.clearingMotionBlur;\n if( needMbClear[r.DRAG] ){ r.clearedForMotionBlur[r.DRAG] = true; }\n\n if( needDraw[r.NODE] || drawAllLayers || drawOnlyNodeLayer || needMbClear[r.NODE] ){\n var useBuffer = motionBlur && !needMbClear[r.NODE] && mbPxRatio !== 1;\n var context = forcedContext || ( useBuffer ? r.data.bufferContexts[ r.MOTIONBLUR_BUFFER_NODE ] : data.contexts[r.NODE] );\n var clear = motionBlur && !useBuffer ? 'motionBlur' : undefined;\n\n setContextTransform( context, clear );\n drawElements(eles.nondrag, context);\n\n if( !drawAllLayers && !motionBlur ){\n needDraw[r.NODE] = false;\n }\n }\n\n if ( !drawOnlyNodeLayer && (needDraw[r.DRAG] || drawAllLayers || needMbClear[r.DRAG]) ) {\n var useBuffer = motionBlur && !needMbClear[r.DRAG] && mbPxRatio !== 1;\n var context = forcedContext || ( useBuffer ? r.data.bufferContexts[ r.MOTIONBLUR_BUFFER_DRAG ] : data.contexts[r.DRAG] );\n\n setContextTransform( context, motionBlur && !useBuffer ? 'motionBlur' : undefined );\n drawElements(eles.drag, context);\n\n if( !drawAllLayers && !motionBlur ){\n needDraw[r.DRAG] = false;\n }\n }\n\n if( r.showFps || (!drawOnlyNodeLayer && (needDraw[r.SELECT_BOX] && !drawAllLayers)) ) {\n var context = forcedContext || data.contexts[r.SELECT_BOX];\n\n setContextTransform( context );\n\n if( r.selection[4] == 1 && ( r.hoverData.selecting || r.touchData.selecting ) ){\n var zoom = r.cy.zoom();\n var borderWidth = coreStyle['selection-box-border-width'].value / zoom;\n\n context.lineWidth = borderWidth;\n context.fillStyle = \"rgba(\"\n + coreStyle['selection-box-color'].value[0] + \",\"\n + coreStyle['selection-box-color'].value[1] + \",\"\n + coreStyle['selection-box-color'].value[2] + \",\"\n + coreStyle['selection-box-opacity'].value + \")\";\n\n context.fillRect(\n r.selection[0],\n r.selection[1],\n r.selection[2] - r.selection[0],\n r.selection[3] - r.selection[1]);\n\n if (borderWidth > 0) {\n context.strokeStyle = \"rgba(\"\n + coreStyle['selection-box-border-color'].value[0] + \",\"\n + coreStyle['selection-box-border-color'].value[1] + \",\"\n + coreStyle['selection-box-border-color'].value[2] + \",\"\n + coreStyle['selection-box-opacity'].value + \")\";\n\n context.strokeRect(\n r.selection[0],\n r.selection[1],\n r.selection[2] - r.selection[0],\n r.selection[3] - r.selection[1]);\n }\n }\n\n if( data.bgActivePosistion && !r.hoverData.selecting ){\n var zoom = r.cy.zoom();\n var pos = data.bgActivePosistion;\n\n context.fillStyle = \"rgba(\"\n + coreStyle['active-bg-color'].value[0] + \",\"\n + coreStyle['active-bg-color'].value[1] + \",\"\n + coreStyle['active-bg-color'].value[2] + \",\"\n + coreStyle['active-bg-opacity'].value + \")\";\n\n context.beginPath();\n context.arc(pos.x, pos.y, coreStyle['active-bg-size'].pfValue / zoom, 0, 2 * Math.PI);\n context.fill();\n }\n\n var timeToRender = r.lastRedrawTime;\n if( r.showFps && timeToRender ){\n timeToRender = Math.round( timeToRender );\n var fps = Math.round(1000/timeToRender);\n\n context.setTransform(1, 0, 0, 1, 0, 0);\n\n context.fillStyle = 'rgba(255, 0, 0, 0.75)';\n context.strokeStyle = 'rgba(255, 0, 0, 0.75)';\n context.lineWidth = 1;\n context.fillText( '1 frame = ' + timeToRender + ' ms = ' + fps + ' fps', 0, 20);\n\n var maxFps = 60;\n context.strokeRect(0, 30, 250, 20);\n context.fillRect(0, 30, 250 * Math.min(fps/maxFps, 1), 20);\n }\n\n if( !drawAllLayers ){\n needDraw[r.SELECT_BOX] = false;\n }\n }\n\n // motionblur: blit rendered blurry frames\n if( motionBlur && mbPxRatio !== 1 ){\n var cxtNode = data.contexts[r.NODE];\n var txtNode = r.data.bufferCanvases[ r.MOTIONBLUR_BUFFER_NODE ];\n\n var cxtDrag = data.contexts[r.DRAG];\n var txtDrag = r.data.bufferCanvases[ r.MOTIONBLUR_BUFFER_DRAG ];\n\n var drawMotionBlur = function( cxt, txt, needClear ){\n cxt.setTransform(1, 0, 0, 1, 0, 0);\n\n if( needClear || !motionBlurFadeEffect ){\n cxt.clearRect( 0, 0, r.canvasWidth, r.canvasHeight );\n } else {\n mbclear( cxt, 0, 0, r.canvasWidth, r.canvasHeight );\n }\n\n var pxr = mbPxRatio;\n\n cxt.drawImage(\n txt, // img\n 0, 0, // sx, sy\n r.canvasWidth * pxr, r.canvasHeight * pxr, // sw, sh\n 0, 0, // x, y\n r.canvasWidth, r.canvasHeight // w, h\n );\n };\n\n if( needDraw[r.NODE] || needMbClear[r.NODE] ){\n drawMotionBlur( cxtNode, txtNode, needMbClear[r.NODE] );\n needDraw[r.NODE] = false;\n }\n\n if( needDraw[r.DRAG] || needMbClear[r.DRAG] ){\n drawMotionBlur( cxtDrag, txtDrag, needMbClear[r.DRAG] );\n needDraw[r.DRAG] = false;\n }\n }\n\n r.prevViewport = vp;\n\n if( r.clearingMotionBlur ){\n r.clearingMotionBlur = false;\n r.motionBlurCleared = true;\n r.motionBlur = true;\n }\n\n if( motionBlur ){\n r.motionBlurTimeout = setTimeout(function(){\n r.motionBlurTimeout = null;\n\n r.clearedForMotionBlur[r.NODE] = false;\n r.clearedForMotionBlur[r.DRAG] = false;\n r.motionBlur = false;\n r.clearingMotionBlur = !textureDraw;\n r.mbFrames = 0;\n\n needDraw[r.NODE] = true;\n needDraw[r.DRAG] = true;\n\n r.redraw();\n }, motionBlurDelay);\n }\n\n r.drawingImage = false;\n\n\n if( !forcedContext && !r.initrender ){\n r.initrender = true;\n cy.trigger('initrender');\n }\n\n if( !forcedContext ){\n cy.triggerOnRender();\n }\n\n};\n\nmodule.exports = CRp;\n","'use strict';\n\n var math = require('../../../math');\n\n var CRp = {};\n\n // @O Polygon drawing\n CRp.drawPolygonPath = function(\n context, x, y, width, height, points) {\n\n var halfW = width / 2;\n var halfH = height / 2;\n\n if( context.beginPath ){ context.beginPath(); }\n\n context.moveTo( x + halfW * points[0], y + halfH * points[1] );\n\n for (var i = 1; i < points.length / 2; i++) {\n context.lineTo( x + halfW * points[i * 2], y + halfH * points[i * 2 + 1] );\n }\n\n context.closePath();\n };\n\n // Round rectangle drawing\n CRp.drawRoundRectanglePath = function(\n context, x, y, width, height, radius) {\n\n var halfWidth = width / 2;\n var halfHeight = height / 2;\n var cornerRadius = math.getRoundRectangleRadius(width, height);\n\n if( context.beginPath ){ context.beginPath(); }\n\n // Start at top middle\n context.moveTo(x, y - halfHeight);\n // Arc from middle top to right side\n context.arcTo(x + halfWidth, y - halfHeight, x + halfWidth, y, cornerRadius);\n // Arc from right side to bottom\n context.arcTo(x + halfWidth, y + halfHeight, x, y + halfHeight, cornerRadius);\n // Arc from bottom to left side\n context.arcTo(x - halfWidth, y + halfHeight, x - halfWidth, y, cornerRadius);\n // Arc from left side to topBorder\n context.arcTo(x - halfWidth, y - halfHeight, x, y - halfHeight, cornerRadius);\n // Join line\n context.lineTo(x, y - halfHeight);\n\n\n context.closePath();\n };\n\n var sin0 = Math.sin(0);\n var cos0 = Math.cos(0);\n\n var sin = {};\n var cos = {};\n\n var ellipseStepSize = Math.PI / 40;\n\n for (var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize ) {\n sin[i] = Math.sin(i);\n cos[i] = Math.cos(i);\n }\n\n CRp.drawEllipsePath = function(context, centerX, centerY, width, height){\n if( context.beginPath ){ context.beginPath(); }\n\n if( context.ellipse ){\n context.ellipse( centerX, centerY, width/2, height/2, 0, 0, 2*Math.PI );\n } else {\n var xPos, yPos;\n var rw = width/2;\n var rh = height/2;\n for (var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize ) {\n xPos = centerX - (rw * sin[i]) * sin0 + (rw * cos[i]) * cos0;\n yPos = centerY + (rh * cos[i]) * sin0 + (rh * sin[i]) * cos0;\n\n if (i === 0) {\n context.moveTo(xPos, yPos);\n } else {\n context.lineTo(xPos, yPos);\n }\n }\n }\n\n context.closePath();\n };\n\nmodule.exports = CRp;\n","'use strict';\n\nvar is = require('../../../is');\n\nvar CRp = {};\n\nCRp.createBuffer = function(w, h) {\n var buffer = document.createElement('canvas');\n buffer.width = w;\n buffer.height = h;\n\n return [buffer, buffer.getContext('2d')];\n};\n\nCRp.bufferCanvasImage = function( options ){\n var cy = this.cy;\n var bb = cy.elements().boundingBox();\n var width = options.full ? Math.ceil(bb.w) : this.container.clientWidth;\n var height = options.full ? Math.ceil(bb.h) : this.container.clientHeight;\n var scale = 1;\n\n if( options.scale !== undefined ){\n width *= options.scale;\n height *= options.scale;\n\n scale = options.scale;\n } else if( is.number(options.maxWidth) || is.number(options.maxHeight) ){\n var maxScaleW = Infinity;\n var maxScaleH = Infinity;\n\n if( is.number(options.maxWidth) ){\n maxScaleW = scale * options.maxWidth / width;\n }\n\n if( is.number(options.maxHeight) ){\n maxScaleH = scale * options.maxHeight / height;\n }\n\n scale = Math.min( maxScaleW, maxScaleH );\n\n width *= scale;\n height *= scale;\n }\n\n var buffCanvas = document.createElement('canvas');\n\n buffCanvas.width = width;\n buffCanvas.height = height;\n\n buffCanvas.style.width = width + 'px';\n buffCanvas.style.height = height + 'px';\n\n var buffCxt = buffCanvas.getContext('2d');\n\n // Rasterize the layers, but only if container has nonzero size\n if (width > 0 && height > 0) {\n\n buffCxt.clearRect( 0, 0, width, height );\n\n if( options.bg ){\n buffCxt.fillStyle = options.bg;\n buffCxt.rect( 0, 0, width, height );\n buffCxt.fill();\n }\n\n buffCxt.globalCompositeOperation = 'source-over';\n\n if( options.full ){ // draw the full bounds of the graph\n this.render({\n forcedContext: buffCxt,\n drawAllLayers: true,\n forcedZoom: scale,\n forcedPan: { x: -bb.x1*scale, y: -bb.y1*scale },\n forcedPxRatio: 1\n });\n } else { // draw the current view\n var cyPan = cy.pan();\n var pan = {\n x: cyPan.x * scale,\n y: cyPan.y * scale\n };\n var zoom = cy.zoom() * scale;\n\n this.render({\n forcedContext: buffCxt,\n drawAllLayers: true,\n forcedZoom: zoom,\n forcedPan: pan,\n forcedPxRatio: 1\n });\n }\n }\n\n return buffCanvas;\n};\n\nCRp.png = function( options ){\n return this.bufferCanvasImage( options ).toDataURL('image/png');\n};\n\nCRp.jpg = function( options ){\n return this.bufferCanvasImage( options ).toDataURL('image/jpeg');\n};\n\nmodule.exports = CRp;\n","/*\nThe canvas renderer was written by Yue Dong.\n\nModifications tracked on Github.\n*/\n\n'use strict';\n\nvar util = require('../../../util');\nvar is = require('../../../is');\n\nvar CR = CanvasRenderer;\nvar CRp = CanvasRenderer.prototype;\n\nCRp.CANVAS_LAYERS = 3;\n//\nCRp.SELECT_BOX = 0;\nCRp.DRAG = 1;\nCRp.NODE = 2;\n\nCRp.BUFFER_COUNT = 3;\n//\nCRp.TEXTURE_BUFFER = 0;\nCRp.MOTIONBLUR_BUFFER_NODE = 1;\nCRp.MOTIONBLUR_BUFFER_DRAG = 2;\n\nfunction CanvasRenderer(options) {\n var r = this;\n\n r.data = {\n canvases: new Array(CRp.CANVAS_LAYERS),\n contexts: new Array(CRp.CANVAS_LAYERS),\n canvasNeedsRedraw: new Array(CRp.CANVAS_LAYERS),\n\n bufferCanvases: new Array(CRp.BUFFER_COUNT),\n bufferContexts: new Array(CRp.CANVAS_LAYERS)\n };\n\n r.data.canvasContainer = document.createElement('div');\n var containerStyle = r.data.canvasContainer.style;\n r.data.canvasContainer.setAttribute('style', '-webkit-tap-highlight-color: rgba(0,0,0,0);');\n containerStyle.position = 'relative';\n containerStyle.zIndex = '0';\n containerStyle.overflow = 'hidden';\n\n var container = options.cy.container();\n container.appendChild( r.data.canvasContainer );\n container.setAttribute('style', ( container.getAttribute('style') || '' ) + '-webkit-tap-highlight-color: rgba(0,0,0,0);');\n\n for (var i = 0; i < CRp.CANVAS_LAYERS; i++) {\n var canvas = r.data.canvases[i] = document.createElement('canvas');\n r.data.contexts[i] = canvas.getContext('2d');\n canvas.setAttribute( 'style', '-webkit-user-select: none; -moz-user-select: -moz-none; user-select: none; -webkit-tap-highlight-color: rgba(0,0,0,0); outline-style: none;' + ( is.ms() ? ' -ms-touch-action: none; touch-action: none; ' : '' ) );\n canvas.style.position = 'absolute';\n canvas.setAttribute('data-id', 'layer' + i);\n canvas.style.zIndex = String(CRp.CANVAS_LAYERS - i);\n r.data.canvasContainer.appendChild(canvas);\n\n r.data.canvasNeedsRedraw[i] = false;\n }\n r.data.topCanvas = r.data.canvases[0];\n\n r.data.canvases[CRp.NODE].setAttribute('data-id', 'layer' + CRp.NODE + '-node');\n r.data.canvases[CRp.SELECT_BOX].setAttribute('data-id', 'layer' + CRp.SELECT_BOX + '-selectbox');\n r.data.canvases[CRp.DRAG].setAttribute('data-id', 'layer' + CRp.DRAG + '-drag');\n\n for (var i = 0; i < CRp.BUFFER_COUNT; i++) {\n r.data.bufferCanvases[i] = document.createElement('canvas');\n r.data.bufferContexts[i] = r.data.bufferCanvases[i].getContext('2d');\n r.data.bufferCanvases[i].style.position = 'absolute';\n r.data.bufferCanvases[i].setAttribute('data-id', 'buffer' + i);\n r.data.bufferCanvases[i].style.zIndex = String(-i - 1);\n r.data.bufferCanvases[i].style.visibility = 'hidden';\n //r.data.canvasContainer.appendChild(r.data.bufferCanvases[i]);\n }\n\n r.pathsEnabled = true;\n}\n\nCRp.redrawHint = function( group, bool ){\n var r = this;\n\n switch( group ){\n case 'eles':\n r.data.canvasNeedsRedraw[ CRp.NODE ] = bool;\n break;\n case 'drag':\n r.data.canvasNeedsRedraw[ CRp.DRAG ] = bool;\n break;\n case 'select':\n r.data.canvasNeedsRedraw[ CRp.SELECT_BOX ] = bool;\n break;\n }\n};\n\n// whether to use Path2D caching for drawing\nvar pathsImpld = typeof Path2D !== 'undefined';\n\nCRp.path2dEnabled = function( on ){\n if( on === undefined ){\n return this.pathsEnabled;\n }\n\n this.pathsEnabled = on ? true : false;\n};\n\nCRp.usePaths = function(){\n return pathsImpld && this.pathsEnabled;\n};\n\n[\n require('./arrow-shapes'),\n require('./drawing-edges'),\n require('./drawing-images'),\n require('./drawing-label-text'),\n require('./drawing-nodes'),\n require('./drawing-redraw'),\n require('./drawing-shapes'),\n require('./export-image'),\n require('./node-shapes')\n].forEach(function( props ){\n util.extend( CRp, props );\n});\n\nmodule.exports = CR;\n","'use strict';\n\nvar CRp = {};\n\nvar impl;\n\nCRp.nodeShapeImpl = function( name ){\n var self = this;\n\n return ( impl || (impl = {\n 'ellipse': function( context, centerX, centerY, width, height ){\n self.drawEllipsePath( context, centerX, centerY, width, height );\n },\n\n 'polygon': function( context, centerX, centerY, width, height, points ){\n self.drawPolygonPath( context, centerX, centerY, width, height, points );\n },\n\n 'roundrectangle': function( context, centerX, centerY, width, height ){\n self.drawRoundRectanglePath( context, centerX, centerY, width, height, 10 );\n }\n }) )[ name ];\n};\n\nmodule.exports = CRp;\n","'use strict';\n\nmodule.exports = [\n { name: 'null', impl: require('./null') },\n { name: 'base', impl: require('./base') },\n { name: 'canvas', impl: require('./canvas') }\n];\n","'use strict';\n\nfunction NullRenderer(options){\n this.options = options;\n this.notifications = 0; // for testing\n}\n\nvar noop = function(){};\n\nNullRenderer.prototype = {\n recalculateRenderedStyle: noop,\n notify: function(){ this.notifications++; },\n init: noop\n};\n\nmodule.exports = NullRenderer;\n","/*! Weaver licensed under MIT (https://tldrlegal.com/license/mit-license), copyright Max Franz */\n\n'use strict';\n\nvar is = require('./is');\nvar util = require('./util');\nvar Thread = require('./thread');\nvar Promise = require('./promise');\nvar define = require('./define');\n\nvar Fabric = function( N ){\n if( !(this instanceof Fabric) ){\n return new Fabric( N );\n }\n\n this._private = {\n pass: []\n };\n\n var defN = 4;\n\n if( is.number(N) ){\n // then use the specified number of threads\n } if( typeof navigator !== 'undefined' && navigator.hardwareConcurrency != null ){\n N = navigator.hardwareConcurrency;\n } else {\n try{\n N = require('os').cpus().length;\n } catch( err ){\n N = defN;\n }\n } // TODO could use an estimation here but would the additional expense be worth it?\n\n for( var i = 0; i < N; i++ ){\n this[i] = new Thread();\n }\n\n this.length = N;\n};\n\nvar fabfn = Fabric.prototype; // short alias\n\nutil.extend(fabfn, {\n\n instanceString: function(){ return 'fabric'; },\n\n // require fn in all threads\n require: function( fn, as ){\n for( var i = 0; i < this.length; i++ ){\n var thread = this[i];\n\n thread.require( fn, as );\n }\n\n return this;\n },\n\n // get a random thread\n random: function(){\n var i = Math.round( (this.length - 1) * Math.random() );\n var thread = this[i];\n\n return thread;\n },\n\n // run on random thread\n run: function( fn ){\n var pass = this._private.pass.shift();\n\n return this.random().pass( pass ).run( fn );\n },\n\n // sends a random thread a message\n message: function( m ){\n return this.random().message( m );\n },\n\n // send all threads a message\n broadcast: function( m ){\n for( var i = 0; i < this.length; i++ ){\n var thread = this[i];\n\n thread.message( m );\n }\n\n return this; // chaining\n },\n\n // stop all threads\n stop: function(){\n for( var i = 0; i < this.length; i++ ){\n var thread = this[i];\n\n thread.stop();\n }\n\n return this; // chaining\n },\n\n // pass data to be used with .spread() etc.\n pass: function( data ){\n var pass = this._private.pass;\n\n if( is.array(data) ){\n pass.push( data );\n } else {\n throw 'Only arrays may be used with fabric.pass()';\n }\n\n return this; // chaining\n },\n\n spreadSize: function(){\n var subsize = Math.ceil( this._private.pass[0].length / this.length );\n\n subsize = Math.max( 1, subsize ); // don't pass less than one ele to each thread\n\n return subsize;\n },\n\n // split the data into slices to spread the data equally among threads\n spread: function( fn ){\n var self = this;\n var _p = self._private;\n var subsize = self.spreadSize(); // number of pass eles to handle in each thread\n var pass = _p.pass.shift().concat([]); // keep a copy\n var runPs = [];\n\n for( var i = 0; i < this.length; i++ ){\n var thread = this[i];\n var slice = pass.splice( 0, subsize );\n\n var runP = thread.pass( slice ).run( fn );\n\n runPs.push( runP );\n\n var doneEarly = pass.length === 0;\n if( doneEarly ){ break; }\n }\n\n return Promise.all( runPs ).then(function( thens ){\n var postpass = [];\n var p = 0;\n\n // fill postpass with the total result joined from all threads\n for( var i = 0; i < thens.length; i++ ){\n var then = thens[i]; // array result from thread i\n\n for( var j = 0; j < then.length; j++ ){\n var t = then[j]; // array element\n\n postpass[ p++ ] = t;\n }\n }\n\n return postpass;\n });\n },\n\n // parallel version of array.map()\n map: function( fn ){\n var self = this;\n\n self.require( fn, '_$_$_fabmap' );\n\n return self.spread(function( split ){\n var mapped = [];\n var origResolve = resolve; // jshint ignore:line\n\n resolve = function( val ){ // jshint ignore:line\n mapped.push( val );\n };\n\n for( var i = 0; i < split.length; i++ ){\n var oldLen = mapped.length;\n var ret = _$_$_fabmap( split[i] ); // jshint ignore:line\n var nothingInsdByResolve = oldLen === mapped.length;\n\n if( nothingInsdByResolve ){\n mapped.push( ret );\n }\n }\n\n resolve = origResolve; // jshint ignore:line\n\n return mapped;\n });\n\n },\n\n // parallel version of array.filter()\n filter: function( fn ){\n var _p = this._private;\n var pass = _p.pass[0];\n\n return this.map( fn ).then(function( include ){\n var ret = [];\n\n for( var i = 0; i < pass.length; i++ ){\n var datum = pass[i];\n var incDatum = include[i];\n\n if( incDatum ){\n ret.push( datum );\n }\n }\n\n return ret;\n });\n },\n\n // sorts the passed array using a divide and conquer strategy\n sort: function( cmp ){\n var self = this;\n var P = this._private.pass[0].length;\n var subsize = this.spreadSize();\n\n cmp = cmp || function( a, b ){ // default comparison function\n if( a < b ){\n return -1;\n } else if( a > b ){\n return 1;\n }\n\n return 0;\n };\n\n self.require( cmp, '_$_$_cmp' );\n\n return self.spread(function( split ){ // sort each split normally\n var sortedSplit = split.sort( _$_$_cmp ); // jshint ignore:line\n resolve( sortedSplit ); // jshint ignore:line\n\n }).then(function( joined ){\n // do all the merging in the main thread to minimise data transfer\n\n // TODO could do merging in separate threads but would incur add'l cost of data transfer\n // for each level of the merge\n\n var merge = function( i, j, max ){\n // don't overflow array\n j = Math.min( j, P );\n max = Math.min( max, P );\n\n // left and right sides of merge\n var l = i;\n var r = j;\n\n var sorted = [];\n\n for( var k = l; k < max; k++ ){\n\n var eleI = joined[i];\n var eleJ = joined[j];\n\n if( i < r && ( j >= max || cmp(eleI, eleJ) <= 0 ) ){\n sorted.push( eleI );\n i++;\n } else {\n sorted.push( eleJ );\n j++;\n }\n\n }\n\n // in the array proper, put the sorted values\n for( var k = 0; k < sorted.length; k++ ){ // kth sorted item\n var index = l + k;\n\n joined[ index ] = sorted[k];\n }\n };\n\n for( var splitL = subsize; splitL < P; splitL *= 2 ){ // merge until array is \"split\" as 1\n\n for( var i = 0; i < P; i += 2*splitL ){\n merge( i, i + splitL, i + 2*splitL );\n }\n\n }\n\n return joined;\n });\n }\n\n\n});\n\nvar defineRandomPasser = function( opts ){\n opts = opts || {};\n\n return function( fn, arg1 ){\n var pass = this._private.pass.shift();\n\n return this.random().pass( pass )[ opts.threadFn ]( fn, arg1 );\n };\n};\n\nutil.extend(fabfn, {\n randomMap: defineRandomPasser({ threadFn: 'map' }),\n\n reduce: defineRandomPasser({ threadFn: 'reduce' }),\n\n reduceRight: defineRandomPasser({ threadFn: 'reduceRight' })\n});\n\n// aliases\nvar fn = fabfn;\nfn.promise = fn.run;\nfn.terminate = fn.halt = fn.stop;\nfn.include = fn.require;\n\n// pull in event apis\nutil.extend(fabfn, {\n on: define.on(),\n one: define.on({ unbindSelfOnTrigger: true }),\n off: define.off(),\n trigger: define.trigger()\n});\n\ndefine.eventAliasesOn( fabfn );\n\nmodule.exports = Fabric;\n","/*!\nPorted by Xueqiao Xu ;\n\nPSF LICENSE AGREEMENT FOR PYTHON 2.7.2\n\n1. This LICENSE AGREEMENT is between the Python Software Foundation (“PSF”), and the Individual or Organization (“Licensee”) accessing and otherwise using Python 2.7.2 software in source or binary form and its associated documentation.\n2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 2.7.2 alone or in any derivative version, provided, however, that PSF’s License Agreement and PSF’s notice of copyright, i.e., “Copyright © 2001-2012 Python Software Foundation; All Rights Reserved” are retained in Python 2.7.2 alone or in any derivative version prepared by Licensee.\n3. In the event Licensee prepares a derivative work that is based on or incorporates Python 2.7.2 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 2.7.2.\n4. PSF is making Python 2.7.2 available to Licensee on an “AS IS” basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.7.2 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.\n5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.7.2 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.7.2, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.\n6. This License Agreement will automatically terminate upon a material breach of its terms and conditions.\n7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party.\n8. By copying, installing or otherwise using Python 2.7.2, Licensee agrees to be bound by the terms and conditions of this License Agreement.\n*/\n\n'use strict';\n/* jshint ignore:start */\n\n// Generated by CoffeeScript 1.8.0\n(function() {\n var Heap, defaultCmp, floor, heapify, heappop, heappush, heappushpop, heapreplace, insort, min, nlargest, nsmallest, updateItem, _siftdown, _siftup;\n\n floor = Math.floor, min = Math.min;\n\n\n /*\n Default comparison function to be used\n */\n\n defaultCmp = function(x, y) {\n if (x < y) {\n return -1;\n }\n if (x > y) {\n return 1;\n }\n return 0;\n };\n\n\n /*\n Insert item x in list a, and keep it sorted assuming a is sorted.\n\n If x is already in a, insert it to the right of the rightmost x.\n\n Optional args lo (default 0) and hi (default a.length) bound the slice\n of a to be searched.\n */\n\n insort = function(a, x, lo, hi, cmp) {\n var mid;\n if (lo == null) {\n lo = 0;\n }\n if (cmp == null) {\n cmp = defaultCmp;\n }\n if (lo < 0) {\n throw new Error('lo must be non-negative');\n }\n if (hi == null) {\n hi = a.length;\n }\n while (lo < hi) {\n mid = floor((lo + hi) / 2);\n if (cmp(x, a[mid]) < 0) {\n hi = mid;\n } else {\n lo = mid + 1;\n }\n }\n return ([].splice.apply(a, [lo, lo - lo].concat(x)), x);\n };\n\n\n /*\n Push item onto heap, maintaining the heap invariant.\n */\n\n heappush = function(array, item, cmp) {\n if (cmp == null) {\n cmp = defaultCmp;\n }\n array.push(item);\n return _siftdown(array, 0, array.length - 1, cmp);\n };\n\n\n /*\n Pop the smallest item off the heap, maintaining the heap invariant.\n */\n\n heappop = function(array, cmp) {\n var lastelt, returnitem;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n lastelt = array.pop();\n if (array.length) {\n returnitem = array[0];\n array[0] = lastelt;\n _siftup(array, 0, cmp);\n } else {\n returnitem = lastelt;\n }\n return returnitem;\n };\n\n\n /*\n Pop and return the current smallest value, and add the new item.\n\n This is more efficient than heappop() followed by heappush(), and can be\n more appropriate when using a fixed size heap. Note that the value\n returned may be larger than item! That constrains reasonable use of\n this routine unless written as part of a conditional replacement:\n if item > array[0]\n item = heapreplace(array, item)\n */\n\n heapreplace = function(array, item, cmp) {\n var returnitem;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n returnitem = array[0];\n array[0] = item;\n _siftup(array, 0, cmp);\n return returnitem;\n };\n\n\n /*\n Fast version of a heappush followed by a heappop.\n */\n\n heappushpop = function(array, item, cmp) {\n var _ref;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n if (array.length && cmp(array[0], item) < 0) {\n _ref = [array[0], item], item = _ref[0], array[0] = _ref[1];\n _siftup(array, 0, cmp);\n }\n return item;\n };\n\n\n /*\n Transform list into a heap, in-place, in O(array.length) time.\n */\n\n heapify = function(array, cmp) {\n var i, _i, _j, _len, _ref, _ref1, _results, _results1;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n _ref1 = (function() {\n _results1 = [];\n for (var _j = 0, _ref = floor(array.length / 2); 0 <= _ref ? _j < _ref : _j > _ref; 0 <= _ref ? _j++ : _j--){ _results1.push(_j); }\n return _results1;\n }).apply(this).reverse();\n _results = [];\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n i = _ref1[_i];\n _results.push(_siftup(array, i, cmp));\n }\n return _results;\n };\n\n\n /*\n Update the position of the given item in the heap.\n This function should be called every time the item is being modified.\n */\n\n updateItem = function(array, item, cmp) {\n var pos;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n pos = array.indexOf(item);\n if (pos === -1) {\n return;\n }\n _siftdown(array, 0, pos, cmp);\n return _siftup(array, pos, cmp);\n };\n\n\n /*\n Find the n largest elements in a dataset.\n */\n\n nlargest = function(array, n, cmp) {\n var elem, result, _i, _len, _ref;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n result = array.slice(0, n);\n if (!result.length) {\n return result;\n }\n heapify(result, cmp);\n _ref = array.slice(n);\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n elem = _ref[_i];\n heappushpop(result, elem, cmp);\n }\n return result.sort(cmp).reverse();\n };\n\n\n /*\n Find the n smallest elements in a dataset.\n */\n\n nsmallest = function(array, n, cmp) {\n var elem, i, los, result, _i, _j, _len, _ref, _ref1, _results;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n if (n * 10 <= array.length) {\n result = array.slice(0, n).sort(cmp);\n if (!result.length) {\n return result;\n }\n los = result[result.length - 1];\n _ref = array.slice(n);\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n elem = _ref[_i];\n if (cmp(elem, los) < 0) {\n insort(result, elem, 0, null, cmp);\n result.pop();\n los = result[result.length - 1];\n }\n }\n return result;\n }\n heapify(array, cmp);\n _results = [];\n for (i = _j = 0, _ref1 = min(n, array.length); 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) {\n _results.push(heappop(array, cmp));\n }\n return _results;\n };\n\n _siftdown = function(array, startpos, pos, cmp) {\n var newitem, parent, parentpos;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n newitem = array[pos];\n while (pos > startpos) {\n parentpos = (pos - 1) >> 1;\n parent = array[parentpos];\n if (cmp(newitem, parent) < 0) {\n array[pos] = parent;\n pos = parentpos;\n continue;\n }\n break;\n }\n return array[pos] = newitem;\n };\n\n _siftup = function(array, pos, cmp) {\n var childpos, endpos, newitem, rightpos, startpos;\n if (cmp == null) {\n cmp = defaultCmp;\n }\n endpos = array.length;\n startpos = pos;\n newitem = array[pos];\n childpos = 2 * pos + 1;\n while (childpos < endpos) {\n rightpos = childpos + 1;\n if (rightpos < endpos && !(cmp(array[childpos], array[rightpos]) < 0)) {\n childpos = rightpos;\n }\n array[pos] = array[childpos];\n pos = childpos;\n childpos = 2 * pos + 1;\n }\n array[pos] = newitem;\n return _siftdown(array, startpos, pos, cmp);\n };\n\n Heap = (function() {\n Heap.push = heappush;\n\n Heap.pop = heappop;\n\n Heap.replace = heapreplace;\n\n Heap.pushpop = heappushpop;\n\n Heap.heapify = heapify;\n\n Heap.updateItem = updateItem;\n\n Heap.nlargest = nlargest;\n\n Heap.nsmallest = nsmallest;\n\n function Heap(cmp) {\n this.cmp = cmp != null ? cmp : defaultCmp;\n this.nodes = [];\n }\n\n Heap.prototype.push = function(x) {\n return heappush(this.nodes, x, this.cmp);\n };\n\n Heap.prototype.pop = function() {\n return heappop(this.nodes, this.cmp);\n };\n\n Heap.prototype.peek = function() {\n return this.nodes[0];\n };\n\n Heap.prototype.contains = function(x) {\n return this.nodes.indexOf(x) !== -1;\n };\n\n Heap.prototype.replace = function(x) {\n return heapreplace(this.nodes, x, this.cmp);\n };\n\n Heap.prototype.pushpop = function(x) {\n return heappushpop(this.nodes, x, this.cmp);\n };\n\n Heap.prototype.heapify = function() {\n return heapify(this.nodes, this.cmp);\n };\n\n Heap.prototype.updateItem = function(x) {\n return updateItem(this.nodes, x, this.cmp);\n };\n\n Heap.prototype.clear = function() {\n return this.nodes = [];\n };\n\n Heap.prototype.empty = function() {\n return this.nodes.length === 0;\n };\n\n Heap.prototype.size = function() {\n return this.nodes.length;\n };\n\n Heap.prototype.clone = function() {\n var heap;\n heap = new Heap();\n heap.nodes = this.nodes.slice(0);\n return heap;\n };\n\n Heap.prototype.toArray = function() {\n return this.nodes.slice(0);\n };\n\n Heap.prototype.insert = Heap.prototype.push;\n\n Heap.prototype.top = Heap.prototype.peek;\n\n Heap.prototype.front = Heap.prototype.peek;\n\n Heap.prototype.has = Heap.prototype.contains;\n\n Heap.prototype.copy = Heap.prototype.clone;\n\n return Heap;\n\n })();\n\n (function(root, factory) {\n if (typeof define === 'function' && define.amd) {\n return define([], factory);\n } else if (typeof exports === 'object') {\n return module.exports = factory();\n } else {\n return root.Heap = factory();\n }\n })(this, function() {\n return Heap;\n });\n\n}).call(this);\n\n/* jshint ignore:end */\n","'use strict';\n\nvar window = require('./window');\nvar is = require('./is');\nvar Core = require('./core');\nvar extension = require('./extension');\nvar registerJquery = require('./jquery-plugin');\nvar Stylesheet = require('./stylesheet');\nvar Thread = require('./thread');\nvar Fabric = require('./fabric');\n\nvar cytoscape = function( options ){ // jshint ignore:line\n // if no options specified, use default\n if( options === undefined ){\n options = {};\n }\n\n // create instance\n if( is.plainObject( options ) ){\n return new Core( options );\n }\n\n // allow for registration of extensions\n else if( is.string( options ) ) {\n return extension.apply(extension, arguments);\n }\n};\n\n// replaced by build system\ncytoscape.version = '{{VERSION}}';\n\n// try to register w/ jquery\nif( window && window.jQuery ){\n registerJquery( window.jQuery, cytoscape );\n}\n\n// expose register api\ncytoscape.registerJquery = function( jQuery ){\n registerJquery( jQuery, cytoscape );\n};\n\n// expose public apis (mostly for extensions)\ncytoscape.stylesheet = cytoscape.Stylesheet = Stylesheet;\ncytoscape.thread = cytoscape.Thread = Thread;\ncytoscape.fabric = cytoscape.Fabric = Fabric;\n\nmodule.exports = cytoscape;\n","'use strict';\n\nvar window = require('./window');\nvar navigator = window ? window.navigator : null;\n\nvar typeofstr = typeof '';\nvar typeofobj = typeof {};\nvar typeoffn = typeof function(){};\nvar typeofhtmlele = typeof HTMLElement;\n\nvar instanceStr = function( obj ){\n return obj && obj.instanceString && is.fn( obj.instanceString ) ? obj.instanceString() : null;\n};\n\nvar is = {\n defined: function(obj){\n return obj != null; // not undefined or null\n },\n\n string: function(obj){\n return obj != null && typeof obj == typeofstr;\n },\n\n fn: function(obj){\n return obj != null && typeof obj === typeoffn;\n },\n\n array: function(obj){\n return Array.isArray ? Array.isArray(obj) : obj != null && obj instanceof Array;\n },\n\n plainObject: function(obj){\n return obj != null && typeof obj === typeofobj && !is.array(obj) && obj.constructor === Object;\n },\n\n object: function(obj){\n return obj != null && typeof obj === typeofobj;\n },\n\n number: function(obj){\n return obj != null && typeof obj === typeof 1 && !isNaN(obj);\n },\n\n integer: function( obj ){\n return is.number(obj) && Math.floor(obj) === obj;\n },\n\n bool: function(obj){\n return obj != null && typeof obj === typeof true;\n },\n\n htmlElement: function(obj){\n if( 'undefined' === typeofhtmlele ){\n return undefined;\n } else {\n return null != obj && obj instanceof HTMLElement;\n }\n },\n\n elementOrCollection: function(obj){\n return is.element(obj) || is.collection(obj);\n },\n\n element: function(obj){\n return instanceStr(obj) === 'collection' && obj._private.single;\n },\n\n collection: function(obj){\n return instanceStr(obj) === 'collection' && !obj._private.single;\n },\n\n core: function(obj){\n return instanceStr(obj) === 'core';\n },\n\n style: function(obj){\n return instanceStr(obj) === 'style';\n },\n\n stylesheet: function(obj){\n return instanceStr(obj) === 'stylesheet';\n },\n\n event: function(obj){\n return instanceStr(obj) === 'event';\n },\n\n thread: function(obj){\n return instanceStr(obj) === 'thread';\n },\n\n fabric: function(obj){\n return instanceStr(obj) === 'fabric';\n },\n\n emptyString: function(obj){\n if( !obj ){ // null is empty\n return true;\n } else if( is.string(obj) ){\n if( obj === '' || obj.match(/^\\s+$/) ){\n return true; // empty string is empty\n }\n }\n\n return false; // otherwise, we don't know what we've got\n },\n\n nonemptyString: function(obj){\n if( obj && is.string(obj) && obj !== '' && !obj.match(/^\\s+$/) ){\n return true;\n }\n\n return false;\n },\n\n domElement: function(obj){\n if( typeof HTMLElement === 'undefined' ){\n return false; // we're not in a browser so it doesn't matter\n } else {\n return obj instanceof HTMLElement;\n }\n },\n\n boundingBox: function(obj){\n return is.plainObject(obj) &&\n is.number(obj.x1) && is.number(obj.x2) &&\n is.number(obj.y1) && is.number(obj.y2)\n ;\n },\n\n promise: function(obj){\n return is.object(obj) && is.fn(obj.then);\n },\n\n touch: function(){\n return window && ( ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch );\n },\n\n gecko: function(){\n return typeof InstallTrigger !== 'undefined' || ('MozAppearance' in document.documentElement.style);\n },\n\n webkit: function(){\n return typeof webkitURL !== 'undefined' || ('WebkitAppearance' in document.documentElement.style);\n },\n\n chromium: function(){\n return typeof chrome !== 'undefined';\n },\n\n khtml: function(){\n return navigator && navigator.vendor.match(/kde/i); // probably a better way to detect this...\n },\n\n khtmlEtc: function(){\n return is.khtml() || is.webkit() || is.chromium();\n },\n\n ms: function(){\n return navigator && navigator.userAgent.match(/msie|trident|edge/i); // probably a better way to detect this...\n },\n\n windows: function(){\n return navigator && navigator.appVersion.match(/Win/i);\n },\n\n mac: function(){\n return navigator && navigator.appVersion.match(/Mac/i);\n },\n\n linux: function(){\n return navigator && navigator.appVersion.match(/Linux/i);\n },\n\n unix: function(){\n return navigator && navigator.appVersion.match(/X11/i);\n }\n};\n\nmodule.exports = is;\n","'use strict';\n\nvar is = require('./is');\n\nvar cyReg = function( $ele ){\n var d = $ele[0]._cyreg = $ele[0]._cyreg || {};\n\n return d;\n};\n\nvar registerJquery = function( $, cytoscape ){\n if( !$ ){ return; } // no jquery => don't need this\n\n if( $.fn.cytoscape ){ return; } // already registered\n\n // allow calls on a jQuery selector by proxying calls to $.cytoscape\n // e.g. $(\"#foo\").cytoscape(options) => $.cytoscape(options) on #foo\n $.fn.cytoscape = function(opts){\n var $this = $(this);\n\n // get object\n if( opts === 'get' ){\n return cyReg( $this ).cy;\n }\n\n // bind to ready\n else if( is.fn(opts) ){\n\n var ready = opts;\n var cy = cyReg( $this ).cy;\n\n if( cy && cy.isReady() ){ // already ready so just trigger now\n cy.trigger('ready', [], ready);\n\n } else { // not yet ready, so add to readies list\n var data = cyReg( $this );\n var readies = data.readies = data.readies || [];\n\n readies.push( ready );\n }\n\n }\n\n // proxy to create instance\n else if( is.plainObject(opts) ){\n return $this.each(function(){\n var options = $.extend({}, opts, {\n container: $(this)[0]\n });\n\n cytoscape(options);\n });\n }\n };\n\n // allow access to the global cytoscape object under jquery for legacy reasons\n $.cytoscape = cytoscape;\n\n // use short alias (cy) if not already defined\n if( $.fn.cy == null && $.cy == null ){\n $.fn.cy = $.fn.cytoscape;\n $.cy = $.cytoscape;\n }\n};\n\nmodule.exports = registerJquery;\n","'use strict';\n\nvar math = {};\n\nmath.signum = function(x){\n if( x > 0 ){\n return 1;\n } else if( x < 0 ){\n return -1;\n } else {\n return 0;\n }\n};\n\nmath.distance = function( p1, p2 ){\n return Math.sqrt( math.sqDistance(p1, p2) );\n};\n\nmath.sqDistance = function( p1, p2 ){\n var dx = p2.x - p1.x;\n var dy = p2.y - p1.y;\n\n return dx*dx + dy*dy;\n};\n\n// from http://en.wikipedia.org/wiki/Bézier_curve#Quadratic_curves\nmath.qbezierAt = function(p0, p1, p2, t){\n return (1 - t)*(1 - t)*p0 + 2*(1 - t)*t*p1 + t*t*p2;\n};\n\nmath.qbezierPtAt = function(p0, p1, p2, t){\n return {\n x: math.qbezierAt( p0.x, p1.x, p2.x, t ),\n y: math.qbezierAt( p0.y, p1.y, p2.y, t )\n };\n};\n\n// makes a full bb (x1, y1, x2, y2, w, h) from implicit params\nmath.makeBoundingBox = function( bb ){\n if( bb.x1 != null && bb.y1 != null ){\n if( bb.x2 != null && bb.y2 != null && bb.x2 >= bb.x1 && bb.y2 >= bb.y1 ){\n return {\n x1: bb.x1,\n y1: bb.y1,\n x2: bb.x2,\n y2: bb.y2,\n w: bb.x2 - bb.x1,\n h: bb.y2 - bb.y1\n };\n } else if( bb.w != null && bb.h != null && bb.w >= 0 && bb.h >= 0 ){\n return {\n x1: bb.x1,\n y1: bb.y1,\n x2: bb.x1 + bb.w,\n y2: bb.y1 + bb.h,\n w: bb.w,\n h: bb.h\n };\n }\n }\n};\n\nmath.boundingBoxesIntersect = function( bb1, bb2 ){\n // case: one bb to right of other\n if( bb1.x1 > bb2.x2 ){ return false; }\n if( bb2.x1 > bb1.x2 ){ return false; }\n\n // case: one bb to left of other\n if( bb1.x2 < bb2.x1 ){ return false; }\n if( bb2.x2 < bb1.x1 ){ return false; }\n\n // case: one bb above other\n if( bb1.y2 < bb2.y1 ){ return false; }\n if( bb2.y2 < bb1.y1 ){ return false; }\n\n // case: one bb below other\n if( bb1.y1 > bb2.y2 ){ return false; }\n if( bb2.y1 > bb1.y2 ){ return false; }\n\n // otherwise, must have some overlap\n return true;\n};\n\nmath.inBoundingBox = function( bb, x, y ){\n return bb.x1 <= x && x <= bb.x2 && bb.y1 <= y && y <= bb.y2;\n};\n\nmath.pointInBoundingBox = function( bb, pt ){\n return this.inBoundingBox( bb, pt.x, pt.y );\n};\n\nmath.roundRectangleIntersectLine = function(\n x, y, nodeX, nodeY, width, height, padding) {\n\n var cornerRadius = this.getRoundRectangleRadius(width, height);\n\n var halfWidth = width / 2;\n var halfHeight = height / 2;\n\n // Check intersections with straight line segments\n var straightLineIntersections;\n\n // Top segment, left to right\n {\n var topStartX = nodeX - halfWidth + cornerRadius - padding;\n var topStartY = nodeY - halfHeight - padding;\n var topEndX = nodeX + halfWidth - cornerRadius + padding;\n var topEndY = topStartY;\n\n straightLineIntersections = this.finiteLinesIntersect(\n x, y, nodeX, nodeY, topStartX, topStartY, topEndX, topEndY, false);\n\n if (straightLineIntersections.length > 0) {\n return straightLineIntersections;\n }\n }\n\n // Right segment, top to bottom\n {\n var rightStartX = nodeX + halfWidth + padding;\n var rightStartY = nodeY - halfHeight + cornerRadius - padding;\n var rightEndX = rightStartX;\n var rightEndY = nodeY + halfHeight - cornerRadius + padding;\n\n straightLineIntersections = this.finiteLinesIntersect(\n x, y, nodeX, nodeY, rightStartX, rightStartY, rightEndX, rightEndY, false);\n\n if (straightLineIntersections.length > 0) {\n return straightLineIntersections;\n }\n }\n\n // Bottom segment, left to right\n {\n var bottomStartX = nodeX - halfWidth + cornerRadius - padding;\n var bottomStartY = nodeY + halfHeight + padding;\n var bottomEndX = nodeX + halfWidth - cornerRadius + padding;\n var bottomEndY = bottomStartY;\n\n straightLineIntersections = this.finiteLinesIntersect(\n x, y, nodeX, nodeY, bottomStartX, bottomStartY, bottomEndX, bottomEndY, false);\n\n if (straightLineIntersections.length > 0) {\n return straightLineIntersections;\n }\n }\n\n // Left segment, top to bottom\n {\n var leftStartX = nodeX - halfWidth - padding;\n var leftStartY = nodeY - halfHeight + cornerRadius - padding;\n var leftEndX = leftStartX;\n var leftEndY = nodeY + halfHeight - cornerRadius + padding;\n\n straightLineIntersections = this.finiteLinesIntersect(\n x, y, nodeX, nodeY, leftStartX, leftStartY, leftEndX, leftEndY, false);\n\n if (straightLineIntersections.length > 0) {\n return straightLineIntersections;\n }\n }\n\n // Check intersections with arc segments\n var arcIntersections;\n\n // Top Left\n {\n var topLeftCenterX = nodeX - halfWidth + cornerRadius;\n var topLeftCenterY = nodeY - halfHeight + cornerRadius;\n arcIntersections = this.intersectLineCircle(\n x, y, nodeX, nodeY,\n topLeftCenterX, topLeftCenterY, cornerRadius + padding);\n\n // Ensure the intersection is on the desired quarter of the circle\n if (arcIntersections.length > 0\n && arcIntersections[0] <= topLeftCenterX\n && arcIntersections[1] <= topLeftCenterY) {\n return [arcIntersections[0], arcIntersections[1]];\n }\n }\n\n // Top Right\n {\n var topRightCenterX = nodeX + halfWidth - cornerRadius;\n var topRightCenterY = nodeY - halfHeight + cornerRadius;\n arcIntersections = this.intersectLineCircle(\n x, y, nodeX, nodeY,\n topRightCenterX, topRightCenterY, cornerRadius + padding);\n\n // Ensure the intersection is on the desired quarter of the circle\n if (arcIntersections.length > 0\n && arcIntersections[0] >= topRightCenterX\n && arcIntersections[1] <= topRightCenterY) {\n return [arcIntersections[0], arcIntersections[1]];\n }\n }\n\n // Bottom Right\n {\n var bottomRightCenterX = nodeX + halfWidth - cornerRadius;\n var bottomRightCenterY = nodeY + halfHeight - cornerRadius;\n arcIntersections = this.intersectLineCircle(\n x, y, nodeX, nodeY,\n bottomRightCenterX, bottomRightCenterY, cornerRadius + padding);\n\n // Ensure the intersection is on the desired quarter of the circle\n if (arcIntersections.length > 0\n && arcIntersections[0] >= bottomRightCenterX\n && arcIntersections[1] >= bottomRightCenterY) {\n return [arcIntersections[0], arcIntersections[1]];\n }\n }\n\n // Bottom Left\n {\n var bottomLeftCenterX = nodeX - halfWidth + cornerRadius;\n var bottomLeftCenterY = nodeY + halfHeight - cornerRadius;\n arcIntersections = this.intersectLineCircle(\n x, y, nodeX, nodeY,\n bottomLeftCenterX, bottomLeftCenterY, cornerRadius + padding);\n\n // Ensure the intersection is on the desired quarter of the circle\n if (arcIntersections.length > 0\n && arcIntersections[0] <= bottomLeftCenterX\n && arcIntersections[1] >= bottomLeftCenterY) {\n return [arcIntersections[0], arcIntersections[1]];\n }\n }\n\n return []; // if nothing\n};\n\nmath.inLineVicinity = function(x, y, lx1, ly1, lx2, ly2, tolerance){\n var t = tolerance;\n\n var x1 = Math.min(lx1, lx2);\n var x2 = Math.max(lx1, lx2);\n var y1 = Math.min(ly1, ly2);\n var y2 = Math.max(ly1, ly2);\n\n return x1 - t <= x && x <= x2 + t\n && y1 - t <= y && y <= y2 + t;\n};\n\nmath.inBezierVicinity = function(\n x, y, x1, y1, x2, y2, x3, y3, tolerance) {\n\n var bb = {\n x1: Math.min( x1, x3, x2 ) - tolerance,\n x2: Math.max( x1, x3, x2 ) + tolerance,\n y1: Math.min( y1, y3, y2 ) - tolerance,\n y2: Math.max( y1, y3, y2 ) + tolerance\n };\n\n // if outside the rough bounding box for the bezier, then it can't be a hit\n if( x < bb.x1 || x > bb.x2 || y < bb.y1 || y > bb.y2 ){\n // console.log('bezier out of rough bb')\n return false;\n } else {\n // console.log('do more expensive check');\n return true;\n }\n\n};\n\nmath.solveCubic = function(a, b, c, d, result) {\n\n // Solves a cubic function, returns root in form [r1, i1, r2, i2, r3, i3], where\n // r is the real component, i is the imaginary component\n\n // An implementation of the Cardano method from the year 1545\n // http://en.wikipedia.org/wiki/Cubic_function#The_nature_of_the_roots\n\n b /= a;\n c /= a;\n d /= a;\n\n var discriminant, q, r, dum1, s, t, term1, r13;\n\n q = (3.0 * c - (b * b)) / 9.0;\n r = -(27.0 * d) + b * (9.0 * c - 2.0 * (b * b));\n r /= 54.0;\n\n discriminant = q * q * q + r * r;\n result[1] = 0;\n term1 = (b / 3.0);\n\n if (discriminant > 0) {\n s = r + Math.sqrt(discriminant);\n s = ((s < 0) ? -Math.pow(-s, (1.0 / 3.0)) : Math.pow(s, (1.0 / 3.0)));\n t = r - Math.sqrt(discriminant);\n t = ((t < 0) ? -Math.pow(-t, (1.0 / 3.0)) : Math.pow(t, (1.0 / 3.0)));\n result[0] = -term1 + s + t;\n term1 += (s + t) / 2.0;\n result[4] = result[2] = -term1;\n term1 = Math.sqrt(3.0) * (-t + s) / 2;\n result[3] = term1;\n result[5] = -term1;\n return;\n }\n\n result[5] = result[3] = 0;\n\n if (discriminant === 0) {\n r13 = ((r < 0) ? -Math.pow(-r, (1.0 / 3.0)) : Math.pow(r, (1.0 / 3.0)));\n result[0] = -term1 + 2.0 * r13;\n result[4] = result[2] = -(r13 + term1);\n return;\n }\n\n q = -q;\n dum1 = q * q * q;\n dum1 = Math.acos(r / Math.sqrt(dum1));\n r13 = 2.0 * Math.sqrt(q);\n result[0] = -term1 + r13 * Math.cos(dum1 / 3.0);\n result[2] = -term1 + r13 * Math.cos((dum1 + 2.0 * Math.PI) / 3.0);\n result[4] = -term1 + r13 * Math.cos((dum1 + 4.0 * Math.PI) / 3.0);\n\n return;\n};\n\nmath.sqDistanceToQuadraticBezier = function(\n x, y, x1, y1, x2, y2, x3, y3) {\n\n // Find minimum distance by using the minimum of the distance\n // function between the given point and the curve\n\n // This gives the coefficients of the resulting cubic equation\n // whose roots tell us where a possible minimum is\n // (Coefficients are divided by 4)\n\n var a = 1.0 * x1*x1 - 4*x1*x2 + 2*x1*x3 + 4*x2*x2 - 4*x2*x3 + x3*x3\n + y1*y1 - 4*y1*y2 + 2*y1*y3 + 4*y2*y2 - 4*y2*y3 + y3*y3;\n\n var b = 1.0 * 9*x1*x2 - 3*x1*x1 - 3*x1*x3 - 6*x2*x2 + 3*x2*x3\n + 9*y1*y2 - 3*y1*y1 - 3*y1*y3 - 6*y2*y2 + 3*y2*y3;\n\n var c = 1.0 * 3*x1*x1 - 6*x1*x2 + x1*x3 - x1*x + 2*x2*x2 + 2*x2*x - x3*x\n + 3*y1*y1 - 6*y1*y2 + y1*y3 - y1*y + 2*y2*y2 + 2*y2*y - y3*y;\n\n var d = 1.0 * x1*x2 - x1*x1 + x1*x - x2*x\n + y1*y2 - y1*y1 + y1*y - y2*y;\n\n // debug(\"coefficients: \" + a / a + \", \" + b / a + \", \" + c / a + \", \" + d / a);\n\n var roots = [];\n\n // Use the cubic solving algorithm\n this.solveCubic(a, b, c, d, roots);\n\n var zeroThreshold = 0.0000001;\n\n var params = [];\n\n for (var index = 0; index < 6; index += 2) {\n if (Math.abs(roots[index + 1]) < zeroThreshold\n && roots[index] >= 0\n && roots[index] <= 1.0) {\n params.push(roots[index]);\n }\n }\n\n params.push(1.0);\n params.push(0.0);\n\n var minDistanceSquared = -1;\n var closestParam;\n\n var curX, curY, distSquared;\n for (var i = 0; i < params.length; i++) {\n curX = Math.pow(1.0 - params[i], 2.0) * x1\n + 2.0 * (1 - params[i]) * params[i] * x2\n + params[i] * params[i] * x3;\n\n curY = Math.pow(1 - params[i], 2.0) * y1\n + 2 * (1.0 - params[i]) * params[i] * y2\n + params[i] * params[i] * y3;\n\n distSquared = Math.pow(curX - x, 2) + Math.pow(curY - y, 2);\n // debug('distance for param ' + params[i] + \": \" + Math.sqrt(distSquared));\n if (minDistanceSquared >= 0) {\n if (distSquared < minDistanceSquared) {\n minDistanceSquared = distSquared;\n closestParam = params[i];\n }\n } else {\n minDistanceSquared = distSquared;\n closestParam = params[i];\n }\n }\n\n return minDistanceSquared;\n};\n\nmath.sqDistanceToFiniteLine = function(x, y, x1, y1, x2, y2) {\n var offset = [x - x1, y - y1];\n var line = [x2 - x1, y2 - y1];\n\n var lineSq = line[0] * line[0] + line[1] * line[1];\n var hypSq = offset[0] * offset[0] + offset[1] * offset[1];\n\n var dotProduct = offset[0] * line[0] + offset[1] * line[1];\n var adjSq = dotProduct * dotProduct / lineSq;\n\n if (dotProduct < 0) {\n return hypSq;\n }\n\n if (adjSq > lineSq) {\n return (x - x2) * (x - x2) + (y - y2) * (y - y2);\n }\n\n return hypSq - adjSq;\n};\n\nmath.pointInsidePolygonPoints = function(x, y, points){\n var x1, y1, x2, y2;\n var y3;\n\n // Intersect with vertical line through (x, y)\n var up = 0;\n var down = 0;\n for (var i = 0; i < points.length / 2; i++) {\n\n x1 = points[i * 2];\n y1 = points[i * 2 + 1];\n\n if (i + 1 < points.length / 2) {\n x2 = points[(i + 1) * 2];\n y2 = points[(i + 1) * 2 + 1];\n } else {\n x2 = points[(i + 1 - points.length / 2) * 2];\n y2 = points[(i + 1 - points.length / 2) * 2 + 1];\n }\n\n if (x1 == x && x2 == x) {\n\n } else if ((x1 >= x && x >= x2)\n || (x1 <= x && x <= x2)) {\n\n y3 = (x - x1) / (x2 - x1) * (y2 - y1) + y1;\n\n if (y3 > y) {\n up++;\n }\n\n if (y3 < y) {\n down++;\n }\n\n } else {\n continue;\n }\n\n }\n\n if (up % 2 === 0) {\n return false;\n } else {\n return true;\n }\n};\n\nmath.pointInsidePolygon = function(\n x, y, basePoints, centerX, centerY, width, height, direction, padding) {\n\n //var direction = arguments[6];\n var transformedPoints = new Array(basePoints.length);\n\n // Gives negative angle\n var angle;\n\n if( direction[0] != null ){\n angle = Math.atan(direction[1] / direction[0]);\n\n if (direction[0] < 0) {\n angle = angle + Math.PI / 2;\n } else {\n angle = -angle - Math.PI / 2;\n }\n } else {\n angle = direction;\n }\n\n var cos = Math.cos(-angle);\n var sin = Math.sin(-angle);\n\n // console.log(\"base: \" + basePoints);\n for (var i = 0; i < transformedPoints.length / 2; i++) {\n transformedPoints[i * 2] =\n width / 2 * (basePoints[i * 2] * cos\n - basePoints[i * 2 + 1] * sin);\n\n transformedPoints[i * 2 + 1] =\n height / 2 * (basePoints[i * 2 + 1] * cos\n + basePoints[i * 2] * sin);\n\n transformedPoints[i * 2] += centerX;\n transformedPoints[i * 2 + 1] += centerY;\n }\n\n var points;\n\n if (padding > 0) {\n var expandedLineSet = this.expandPolygon(\n transformedPoints,\n -padding);\n\n points = this.joinLines(expandedLineSet);\n } else {\n points = transformedPoints;\n }\n\n return math.pointInsidePolygonPoints( x, y, points );\n};\n\nmath.joinLines = function(lineSet) {\n\n var vertices = new Array(lineSet.length / 2);\n\n var currentLineStartX, currentLineStartY, currentLineEndX, currentLineEndY;\n var nextLineStartX, nextLineStartY, nextLineEndX, nextLineEndY;\n\n for (var i = 0; i < lineSet.length / 4; i++) {\n currentLineStartX = lineSet[i * 4];\n currentLineStartY = lineSet[i * 4 + 1];\n currentLineEndX = lineSet[i * 4 + 2];\n currentLineEndY = lineSet[i * 4 + 3];\n\n if (i < lineSet.length / 4 - 1) {\n nextLineStartX = lineSet[(i + 1) * 4];\n nextLineStartY = lineSet[(i + 1) * 4 + 1];\n nextLineEndX = lineSet[(i + 1) * 4 + 2];\n nextLineEndY = lineSet[(i + 1) * 4 + 3];\n } else {\n nextLineStartX = lineSet[0];\n nextLineStartY = lineSet[1];\n nextLineEndX = lineSet[2];\n nextLineEndY = lineSet[3];\n }\n\n var intersection = this.finiteLinesIntersect(\n currentLineStartX, currentLineStartY,\n currentLineEndX, currentLineEndY,\n nextLineStartX, nextLineStartY,\n nextLineEndX, nextLineEndY,\n true);\n\n vertices[i * 2] = intersection[0];\n vertices[i * 2 + 1] = intersection[1];\n }\n\n return vertices;\n};\n\nmath.expandPolygon = function(points, pad) {\n\n var expandedLineSet = new Array(points.length * 2);\n\n var currentPointX, currentPointY, nextPointX, nextPointY;\n\n for (var i = 0; i < points.length / 2; i++) {\n currentPointX = points[i * 2];\n currentPointY = points[i * 2 + 1];\n\n if (i < points.length / 2 - 1) {\n nextPointX = points[(i + 1) * 2];\n nextPointY = points[(i + 1) * 2 + 1];\n } else {\n nextPointX = points[0];\n nextPointY = points[1];\n }\n\n // Current line: [currentPointX, currentPointY] to [nextPointX, nextPointY]\n\n // Assume CCW polygon winding\n\n var offsetX = (nextPointY - currentPointY);\n var offsetY = -(nextPointX - currentPointX);\n\n // Normalize\n var offsetLength = Math.sqrt(offsetX * offsetX + offsetY * offsetY);\n var normalizedOffsetX = offsetX / offsetLength;\n var normalizedOffsetY = offsetY / offsetLength;\n\n expandedLineSet[i * 4] = currentPointX + normalizedOffsetX * pad;\n expandedLineSet[i * 4 + 1] = currentPointY + normalizedOffsetY * pad;\n expandedLineSet[i * 4 + 2] = nextPointX + normalizedOffsetX * pad;\n expandedLineSet[i * 4 + 3] = nextPointY + normalizedOffsetY * pad;\n }\n\n return expandedLineSet;\n};\n\nmath.intersectLineEllipse = function(\n x, y, centerX, centerY, ellipseWradius, ellipseHradius) {\n\n var dispX = centerX - x;\n var dispY = centerY - y;\n\n dispX /= ellipseWradius;\n dispY /= ellipseHradius;\n\n var len = Math.sqrt(dispX * dispX + dispY * dispY);\n\n var newLength = len - 1;\n\n if (newLength < 0) {\n return [];\n }\n\n var lenProportion = newLength / len;\n\n return [(centerX - x) * lenProportion + x, (centerY - y) * lenProportion + y];\n};\n\n// Returns intersections of increasing distance from line's start point\nmath.intersectLineCircle = function(\n x1, y1, x2, y2, centerX, centerY, radius) {\n\n // Calculate d, direction vector of line\n var d = [x2 - x1, y2 - y1]; // Direction vector of line\n var c = [centerX, centerY]; // Center of circle\n var f = [x1 - centerX, y1 - centerY];\n\n var a = d[0] * d[0] + d[1] * d[1];\n var b = 2 * (f[0] * d[0] + f[1] * d[1]);\n var c = (f[0] * f[0] + f[1] * f[1]) - radius * radius ;\n\n var discriminant = b*b-4*a*c;\n\n if (discriminant < 0) {\n return [];\n }\n\n var t1 = (-b + Math.sqrt(discriminant)) / (2 * a);\n var t2 = (-b - Math.sqrt(discriminant)) / (2 * a);\n\n var tMin = Math.min(t1, t2);\n var tMax = Math.max(t1, t2);\n var inRangeParams = [];\n\n if (tMin >= 0 && tMin <= 1) {\n inRangeParams.push(tMin);\n }\n\n if (tMax >= 0 && tMax <= 1) {\n inRangeParams.push(tMax);\n }\n\n if (inRangeParams.length === 0) {\n return [];\n }\n\n var nearIntersectionX = inRangeParams[0] * d[0] + x1;\n var nearIntersectionY = inRangeParams[0] * d[1] + y1;\n\n if (inRangeParams.length > 1) {\n\n if (inRangeParams[0] == inRangeParams[1]) {\n return [nearIntersectionX, nearIntersectionY];\n } else {\n\n var farIntersectionX = inRangeParams[1] * d[0] + x1;\n var farIntersectionY = inRangeParams[1] * d[1] + y1;\n\n return [nearIntersectionX, nearIntersectionY, farIntersectionX, farIntersectionY];\n }\n\n } else {\n return [nearIntersectionX, nearIntersectionY];\n }\n\n};\n\nmath.findCircleNearPoint = function(centerX, centerY,\n radius, farX, farY) {\n\n var displacementX = farX - centerX;\n var displacementY = farY - centerY;\n var distance = Math.sqrt(displacementX * displacementX\n + displacementY * displacementY);\n\n var unitDisplacementX = displacementX / distance;\n var unitDisplacementY = displacementY / distance;\n\n return [centerX + unitDisplacementX * radius,\n centerY + unitDisplacementY * radius];\n};\n\nmath.findMaxSqDistanceToOrigin = function(points) {\n var maxSqDistance = 0.000001;\n var sqDistance;\n\n for (var i = 0; i < points.length / 2; i++) {\n\n sqDistance = points[i * 2] * points[i * 2]\n + points[i * 2 + 1] * points[i * 2 + 1];\n\n if (sqDistance > maxSqDistance) {\n maxSqDistance = sqDistance;\n }\n }\n\n return maxSqDistance;\n};\n\nmath.finiteLinesIntersect = function(\n x1, y1, x2, y2, x3, y3, x4, y4, infiniteLines) {\n\n var ua_t = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);\n var ub_t = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3);\n var u_b = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);\n\n if (u_b !== 0) {\n var ua = ua_t / u_b;\n var ub = ub_t / u_b;\n\n if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {\n return [x1 + ua * (x2 - x1), y1 + ua * (y2 - y1)];\n\n } else {\n if (!infiniteLines) {\n return [];\n } else {\n return [x1 + ua * (x2 - x1), y1 + ua * (y2 - y1)];\n }\n }\n } else {\n if (ua_t === 0 || ub_t === 0) {\n\n // Parallel, coincident lines. Check if overlap\n\n // Check endpoint of second line\n if ([x1, x2, x4].sort()[1] === x4) {\n return [x4, y4];\n }\n\n // Check start point of second line\n if ([x1, x2, x3].sort()[1] === x3) {\n return [x3, y3];\n }\n\n // Endpoint of first line\n if ([x3, x4, x2].sort()[1] === x2) {\n return [x2, y2];\n }\n\n return [];\n } else {\n\n // Parallel, non-coincident\n return [];\n }\n }\n};\n\nmath.polygonIntersectLine = function(\n x, y, basePoints, centerX, centerY, width, height, padding) {\n\n var intersections = [];\n var intersection;\n\n var transformedPoints = new Array(basePoints.length);\n\n for (var i = 0; i < transformedPoints.length / 2; i++) {\n transformedPoints[i * 2] = basePoints[i * 2] * width + centerX;\n transformedPoints[i * 2 + 1] = basePoints[i * 2 + 1] * height + centerY;\n }\n\n var points;\n\n if (padding > 0) {\n var expandedLineSet = math.expandPolygon(\n transformedPoints,\n -padding);\n\n points = math.joinLines(expandedLineSet);\n } else {\n points = transformedPoints;\n }\n // var points = transformedPoints;\n\n var currentX, currentY, nextX, nextY;\n\n for (var i = 0; i < points.length / 2; i++) {\n\n currentX = points[i * 2];\n currentY = points[i * 2 + 1];\n\n if (i < points.length / 2 - 1) {\n nextX = points[(i + 1) * 2];\n nextY = points[(i + 1) * 2 + 1];\n } else {\n nextX = points[0];\n nextY = points[1];\n }\n\n intersection = this.finiteLinesIntersect(\n x, y, centerX, centerY,\n currentX, currentY,\n nextX, nextY);\n\n if (intersection.length !== 0) {\n intersections.push(intersection[0], intersection[1]);\n }\n }\n\n return intersections;\n};\n\nmath.shortenIntersection = function(\n intersection, offset, amount) {\n\n var disp = [intersection[0] - offset[0], intersection[1] - offset[1]];\n\n var length = Math.sqrt(disp[0] * disp[0] + disp[1] * disp[1]);\n\n var lenRatio = (length - amount) / length;\n\n if (lenRatio < 0) {\n lenRatio = 0.00001;\n }\n\n return [offset[0] + lenRatio * disp[0], offset[1] + lenRatio * disp[1]];\n};\n\nmath.generateUnitNgonPointsFitToSquare = function(sides, rotationRadians) {\n var points = math.generateUnitNgonPoints(sides, rotationRadians);\n points = math.fitPolygonToSquare(points);\n\n return points;\n};\n\nmath.fitPolygonToSquare = function(points){\n var x, y;\n var sides = points.length/2;\n var minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n\n for (var i = 0; i < sides; i++) {\n x = points[2 * i];\n y = points[2 * i + 1];\n\n minX = Math.min( minX, x );\n maxX = Math.max( maxX, x );\n minY = Math.min( minY, y );\n maxY = Math.max( maxY, y );\n }\n\n // stretch factors\n var sx = 2 / (maxX - minX);\n var sy = 2 / (maxY - minY);\n\n for (var i = 0; i < sides; i++){\n x = points[2 * i] = points[2 * i] * sx;\n y = points[2 * i + 1] = points[2 * i + 1] * sy;\n\n minX = Math.min( minX, x );\n maxX = Math.max( maxX, x );\n minY = Math.min( minY, y );\n maxY = Math.max( maxY, y );\n }\n\n if( minY < -1 ){\n for (var i = 0; i < sides; i++){\n y = points[2 * i + 1] = points[2 * i + 1] + (-1 -minY);\n }\n }\n\n return points;\n};\n\nmath.generateUnitNgonPoints = function(sides, rotationRadians) {\n\n var increment = 1.0 / sides * 2 * Math.PI;\n var startAngle = sides % 2 === 0 ?\n Math.PI / 2.0 + increment / 2.0 : Math.PI / 2.0;\n // console.log(nodeShapes['square']);\n startAngle += rotationRadians;\n\n var points = new Array(sides * 2);\n\n var currentAngle, x, y;\n for (var i = 0; i < sides; i++) {\n currentAngle = i * increment + startAngle;\n\n x = points[2 * i] = Math.cos(currentAngle);// * (1 + i/2);\n y = points[2 * i + 1] = Math.sin(-currentAngle);// * (1 + i/2);\n }\n\n return points;\n};\n\nmath.getRoundRectangleRadius = function(width, height) {\n\n // Set the default radius, unless half of width or height is smaller than default\n return Math.min(width / 4, height / 4, 8);\n};\n\nmodule.exports = math;\n","/*!\nEmbeddable Minimum Strictly-Compliant Promises/A+ 1.1.1 Thenable\nCopyright (c) 2013-2014 Ralf S. Engelschall (http://engelschall.com)\nLicensed under The MIT License (http://opensource.org/licenses/MIT)\n*/\n\n'use strict';\n\n/* promise states [Promises/A+ 2.1] */\nvar STATE_PENDING = 0; /* [Promises/A+ 2.1.1] */\nvar STATE_FULFILLED = 1; /* [Promises/A+ 2.1.2] */\nvar STATE_REJECTED = 2; /* [Promises/A+ 2.1.3] */\n\n/* promise object constructor */\nvar api = function (executor) {\n /* optionally support non-constructor/plain-function call */\n if (!(this instanceof api))\n return new api(executor);\n\n /* initialize object */\n this.id = \"Thenable/1.0.7\";\n this.state = STATE_PENDING; /* initial state */\n this.fulfillValue = undefined; /* initial value */ /* [Promises/A+ 1.3, 2.1.2.2] */\n this.rejectReason = undefined; /* initial reason */ /* [Promises/A+ 1.5, 2.1.3.2] */\n this.onFulfilled = []; /* initial handlers */\n this.onRejected = []; /* initial handlers */\n\n /* provide optional information-hiding proxy */\n this.proxy = {\n then: this.then.bind(this)\n };\n\n /* support optional executor function */\n if (typeof executor === \"function\")\n executor.call(this, this.fulfill.bind(this), this.reject.bind(this));\n};\n\n/* promise API methods */\napi.prototype = {\n /* promise resolving methods */\n fulfill: function (value) { return deliver(this, STATE_FULFILLED, \"fulfillValue\", value); },\n reject: function (value) { return deliver(this, STATE_REJECTED, \"rejectReason\", value); },\n\n /* \"The then Method\" [Promises/A+ 1.1, 1.2, 2.2] */\n then: function (onFulfilled, onRejected) {\n var curr = this;\n var next = new api(); /* [Promises/A+ 2.2.7] */\n curr.onFulfilled.push(\n resolver(onFulfilled, next, \"fulfill\")); /* [Promises/A+ 2.2.2/2.2.6] */\n curr.onRejected.push(\n resolver(onRejected, next, \"reject\" )); /* [Promises/A+ 2.2.3/2.2.6] */\n execute(curr);\n return next.proxy; /* [Promises/A+ 2.2.7, 3.3] */\n }\n};\n\n/* deliver an action */\nvar deliver = function (curr, state, name, value) {\n if (curr.state === STATE_PENDING) {\n curr.state = state; /* [Promises/A+ 2.1.2.1, 2.1.3.1] */\n curr[name] = value; /* [Promises/A+ 2.1.2.2, 2.1.3.2] */\n execute(curr);\n }\n return curr;\n};\n\n/* execute all handlers */\nvar execute = function (curr) {\n if (curr.state === STATE_FULFILLED)\n execute_handlers(curr, \"onFulfilled\", curr.fulfillValue);\n else if (curr.state === STATE_REJECTED)\n execute_handlers(curr, \"onRejected\", curr.rejectReason);\n};\n\n/* execute particular set of handlers */\nvar execute_handlers = function (curr, name, value) {\n /* global setImmediate: true */\n /* global setTimeout: true */\n\n /* short-circuit processing */\n if (curr[name].length === 0)\n return;\n\n /* iterate over all handlers, exactly once */\n var handlers = curr[name];\n curr[name] = []; /* [Promises/A+ 2.2.2.3, 2.2.3.3] */\n var func = function () {\n for (var i = 0; i < handlers.length; i++)\n handlers[i](value); /* [Promises/A+ 2.2.5] */\n };\n\n /* execute procedure asynchronously */ /* [Promises/A+ 2.2.4, 3.1] */\n if (typeof setImmediate === \"function\")\n setImmediate(func);\n else\n setTimeout(func, 0);\n};\n\n/* generate a resolver function */\nvar resolver = function (cb, next, method) {\n return function (value) {\n if (typeof cb !== \"function\") /* [Promises/A+ 2.2.1, 2.2.7.3, 2.2.7.4] */\n next[method].call(next, value); /* [Promises/A+ 2.2.7.3, 2.2.7.4] */\n else {\n var result;\n try { result = cb(value); } /* [Promises/A+ 2.2.2.1, 2.2.3.1, 2.2.5, 3.2] */\n catch (e) {\n next.reject(e); /* [Promises/A+ 2.2.7.2] */\n return;\n }\n resolve(next, result); /* [Promises/A+ 2.2.7.1] */\n }\n };\n};\n\n/* \"Promise Resolution Procedure\" */ /* [Promises/A+ 2.3] */\nvar resolve = function (promise, x) {\n /* sanity check arguments */ /* [Promises/A+ 2.3.1] */\n if (promise === x || promise.proxy === x) {\n promise.reject(new TypeError(\"cannot resolve promise with itself\"));\n return;\n }\n\n /* surgically check for a \"then\" method\n (mainly to just call the \"getter\" of \"then\" only once) */\n var then;\n if ((typeof x === \"object\" && x !== null) || typeof x === \"function\") {\n try { then = x.then; } /* [Promises/A+ 2.3.3.1, 3.5] */\n catch (e) {\n promise.reject(e); /* [Promises/A+ 2.3.3.2] */\n return;\n }\n }\n\n /* handle own Thenables [Promises/A+ 2.3.2]\n and similar \"thenables\" [Promises/A+ 2.3.3] */\n if (typeof then === \"function\") {\n var resolved = false;\n try {\n /* call retrieved \"then\" method */ /* [Promises/A+ 2.3.3.3] */\n then.call(x,\n /* resolvePromise */ /* [Promises/A+ 2.3.3.3.1] */\n function (y) {\n if (resolved) return; resolved = true; /* [Promises/A+ 2.3.3.3.3] */\n if (y === x) /* [Promises/A+ 3.6] */\n promise.reject(new TypeError(\"circular thenable chain\"));\n else\n resolve(promise, y);\n },\n\n /* rejectPromise */ /* [Promises/A+ 2.3.3.3.2] */\n function (r) {\n if (resolved) return; resolved = true; /* [Promises/A+ 2.3.3.3.3] */\n promise.reject(r);\n }\n );\n }\n catch (e) {\n if (!resolved) /* [Promises/A+ 2.3.3.3.3] */\n promise.reject(e); /* [Promises/A+ 2.3.3.3.4] */\n }\n return;\n }\n\n /* handle other values */\n promise.fulfill(x); /* [Promises/A+ 2.3.4, 2.3.3.4] */\n};\n\n// use native promises where possible\nvar Promise = typeof Promise === 'undefined' ? api : Promise;\n\n// so we always have Promise.all()\nPromise.all = Promise.all || function( ps ){\n return new Promise(function( resolveAll, rejectAll ){\n var vals = new Array( ps.length );\n var doneCount = 0;\n\n var fulfill = function( i, val ){\n vals[i] = val;\n doneCount++;\n\n if( doneCount === ps.length ){\n resolveAll( vals );\n }\n };\n\n for( var i = 0; i < ps.length; i++ ){\n (function( i ){\n var p = ps[i];\n var isPromise = p.then != null;\n\n if( isPromise ){\n p.then(function( val ){\n fulfill( i, val );\n }, function( err ){\n rejectAll( err );\n });\n } else {\n var val = p;\n fulfill( i, val );\n }\n })( i );\n }\n\n });\n};\n\nmodule.exports = Promise;\n","'use strict';\n\nvar is = require('./is');\nvar util = require('./util');\n\nvar Selector = function( onlyThisGroup, selector ){\n\n if( !(this instanceof Selector) ){\n return new Selector(onlyThisGroup, selector);\n }\n\n if( selector === undefined && onlyThisGroup !== undefined ){\n selector = onlyThisGroup;\n onlyThisGroup = undefined;\n }\n\n var self = this;\n\n self._private = {\n selectorText: null,\n invalid: true\n };\n\n if( !selector || ( is.string(selector) && selector.match(/^\\s*$/) ) ){\n\n if( onlyThisGroup == null ){\n // ignore\n self.length = 0;\n } else {\n self[0] = newQuery();\n self[0].group = onlyThisGroup;\n self.length = 1;\n }\n\n } else if( is.elementOrCollection( selector ) ){\n var collection = selector.collection();\n\n self[0] = newQuery();\n self[0].collection = collection;\n self.length = 1;\n\n } else if( is.fn( selector ) ) {\n self[0] = newQuery();\n self[0].filter = selector;\n self.length = 1;\n\n } else if( is.string( selector ) ){\n\n // the current subject in the query\n var currentSubject = null;\n\n // storage for parsed queries\n var newQuery = function(){\n return {\n classes: [],\n colonSelectors: [],\n data: [],\n group: null,\n ids: [],\n meta: [],\n\n // fake selectors\n collection: null, // a collection to match against\n filter: null, // filter function\n\n // these are defined in the upward direction rather than down (e.g. child)\n // because we need to go up in Selector.filter()\n parent: null, // parent query obj\n ancestor: null, // ancestor query obj\n subject: null, // defines subject in compound query (subject query obj; points to self if subject)\n\n // use these only when subject has been defined\n child: null,\n descendant: null\n };\n };\n\n // tokens in the query language\n var tokens = {\n metaChar: '[\\\\!\\\\\"\\\\#\\\\$\\\\%\\\\&\\\\\\'\\\\(\\\\)\\\\*\\\\+\\\\,\\\\.\\\\/\\\\:\\\\;\\\\<\\\\=\\\\>\\\\?\\\\@\\\\[\\\\]\\\\^\\\\`\\\\{\\\\|\\\\}\\\\~]', // chars we need to escape in var names, etc\n comparatorOp: '=|\\\\!=|>|>=|<|<=|\\\\$=|\\\\^=|\\\\*=', // binary comparison op (used in data selectors)\n boolOp: '\\\\?|\\\\!|\\\\^', // boolean (unary) operators (used in data selectors)\n string: '\"(?:\\\\\\\\\"|[^\"])+\"' + '|' + \"'(?:\\\\\\\\'|[^'])+'\", // string literals (used in data selectors) -- doublequotes | singlequotes\n number: util.regex.number, // number literal (used in data selectors) --- e.g. 0.1234, 1234, 12e123\n meta: 'degree|indegree|outdegree', // allowed metadata fields (i.e. allowed functions to use from Collection)\n separator: '\\\\s*,\\\\s*', // queries are separated by commas, e.g. edge[foo = 'bar'], node.someClass\n descendant: '\\\\s+',\n child: '\\\\s+>\\\\s+',\n subject: '\\\\$'\n };\n tokens.variable = '(?:[\\\\w-]|(?:\\\\\\\\'+ tokens.metaChar +'))+'; // a variable name\n tokens.value = tokens.string + '|' + tokens.number; // a value literal, either a string or number\n tokens.className = tokens.variable; // a class name (follows variable conventions)\n tokens.id = tokens.variable; // an element id (follows variable conventions)\n\n // when a token like a variable has escaped meta characters, we need to clean the backslashes out\n // so that values get compared properly in Selector.filter()\n var cleanMetaChars = function(str){\n return str.replace(new RegExp('\\\\\\\\(' + tokens.metaChar + ')', 'g'), function(match, $1, offset, original){\n return $1;\n });\n };\n\n // add @ variants to comparatorOp\n var ops = tokens.comparatorOp.split('|');\n for( var i = 0; i < ops.length; i++ ){\n var op = ops[i];\n tokens.comparatorOp += '|@' + op;\n }\n\n // add ! variants to comparatorOp\n var ops = tokens.comparatorOp.split('|');\n for( var i = 0; i < ops.length; i++ ){\n var op = ops[i];\n\n if( op.indexOf('!') >= 0 ){ continue; } // skip ops that explicitly contain !\n if( op === '=' ){ continue; } // skip = b/c != is explicitly defined\n\n tokens.comparatorOp += '|\\\\!' + op;\n }\n\n // NOTE: add new expression syntax here to have it recognised by the parser;\n // - a query contains all adjacent (i.e. no separator in between) expressions;\n // - the current query is stored in self[i] --- you can use the reference to `this` in the populate function;\n // - you need to check the query objects in Selector.filter() for it actually filter properly, but that's pretty straight forward\n // - when you add something here, also add to Selector.toString()\n var exprs = [\n {\n name: 'group',\n query: true,\n regex: '(node|edge|\\\\*)',\n populate: function( group ){\n this.group = group == \"*\" ? group : group + 's';\n }\n },\n\n {\n name: 'state',\n query: true,\n // NB: if one colon selector is a substring of another from its start, place the longer one first\n // e.g. :foobar|:foo\n regex: '(:selected|:unselected|:locked|:unlocked|:visible|:hidden|:transparent|:grabbed|:free|:removed|:inside|:grabbable|:ungrabbable|:animated|:unanimated|:selectable|:unselectable|:orphan|:nonorphan|:parent|:child|:loop|:simple|:active|:inactive|:touch|:backgrounding|:nonbackgrounding)',\n populate: function( state ){\n this.colonSelectors.push( state );\n }\n },\n\n {\n name: 'id',\n query: true,\n regex: '\\\\#('+ tokens.id +')',\n populate: function( id ){\n this.ids.push( cleanMetaChars(id) );\n }\n },\n\n {\n name: 'className',\n query: true,\n regex: '\\\\.('+ tokens.className +')',\n populate: function( className ){\n this.classes.push( cleanMetaChars(className) );\n }\n },\n\n {\n name: 'dataExists',\n query: true,\n regex: '\\\\[\\\\s*('+ tokens.variable +')\\\\s*\\\\]',\n populate: function( variable ){\n this.data.push({\n field: cleanMetaChars(variable)\n });\n }\n },\n\n {\n name: 'dataCompare',\n query: true,\n regex: '\\\\[\\\\s*('+ tokens.variable +')\\\\s*('+ tokens.comparatorOp +')\\\\s*('+ tokens.value +')\\\\s*\\\\]',\n populate: function( variable, comparatorOp, value ){\n var valueIsString = new RegExp('^' + tokens.string + '$').exec(value) != null;\n\n if( valueIsString ){\n value = value.substring(1, value.length - 1);\n } else {\n value = parseFloat(value);\n }\n\n this.data.push({\n field: cleanMetaChars(variable),\n operator: comparatorOp,\n value: value\n });\n }\n },\n\n {\n name: 'dataBool',\n query: true,\n regex: '\\\\[\\\\s*('+ tokens.boolOp +')\\\\s*('+ tokens.variable +')\\\\s*\\\\]',\n populate: function( boolOp, variable ){\n this.data.push({\n field: cleanMetaChars(variable),\n operator: boolOp\n });\n }\n },\n\n {\n name: 'metaCompare',\n query: true,\n regex: '\\\\[\\\\[\\\\s*('+ tokens.meta +')\\\\s*('+ tokens.comparatorOp +')\\\\s*('+ tokens.number +')\\\\s*\\\\]\\\\]',\n populate: function( meta, comparatorOp, number ){\n this.meta.push({\n field: cleanMetaChars(meta),\n operator: comparatorOp,\n value: parseFloat(number)\n });\n }\n },\n\n {\n name: 'nextQuery',\n separator: true,\n regex: tokens.separator,\n populate: function(){\n // go on to next query\n self[++i] = newQuery();\n currentSubject = null;\n }\n },\n\n {\n name: 'child',\n separator: true,\n regex: tokens.child,\n populate: function(){\n // this query is the parent of the following query\n var childQuery = newQuery();\n childQuery.parent = this;\n childQuery.subject = currentSubject;\n\n // we're now populating the child query with expressions that follow\n self[i] = childQuery;\n }\n },\n\n {\n name: 'descendant',\n separator: true,\n regex: tokens.descendant,\n populate: function(){\n // this query is the ancestor of the following query\n var descendantQuery = newQuery();\n descendantQuery.ancestor = this;\n descendantQuery.subject = currentSubject;\n\n // we're now populating the descendant query with expressions that follow\n self[i] = descendantQuery;\n }\n },\n\n {\n name: 'subject',\n modifier: true,\n regex: tokens.subject,\n populate: function(){\n if( currentSubject != null && this.subject != this ){\n util.error('Redefinition of subject in selector `' + selector + '`');\n return false;\n }\n\n currentSubject = this;\n this.subject = this;\n }\n\n }\n ];\n\n self._private.selectorText = selector;\n var remaining = selector;\n var i = 0;\n\n // of all the expressions, find the first match in the remaining text\n var consumeExpr = function( expectation ){\n var expr;\n var match;\n var name;\n\n for( var j = 0; j < exprs.length; j++ ){\n var e = exprs[j];\n var n = e.name;\n\n // ignore this expression if it doesn't meet the expectation function\n if( is.fn( expectation ) && !expectation(n, e) ){ continue; }\n\n var m = remaining.match(new RegExp( '^' + e.regex ));\n\n if( m != null ){\n match = m;\n expr = e;\n name = n;\n\n var consumed = m[0];\n remaining = remaining.substring( consumed.length );\n\n break; // we've consumed one expr, so we can return now\n }\n }\n\n return {\n expr: expr,\n match: match,\n name: name\n };\n };\n\n // consume all leading whitespace\n var consumeWhitespace = function(){\n var match = remaining.match(/^\\s+/);\n\n if( match ){\n var consumed = match[0];\n remaining = remaining.substring( consumed.length );\n }\n };\n\n self[0] = newQuery(); // get started\n\n consumeWhitespace(); // get rid of leading whitespace\n for(;;){\n var check = consumeExpr();\n\n if( check.expr == null ){\n util.error('The selector `'+ selector +'`is invalid');\n return;\n } else {\n var args = [];\n for(var j = 1; j < check.match.length; j++){\n args.push( check.match[j] );\n }\n\n // let the token populate the selector object (i.e. in self[i])\n var ret = check.expr.populate.apply( self[i], args );\n\n if( ret === false ){ return; } // exit if population failed\n }\n\n // we're done when there's nothing left to parse\n if( remaining.match(/^\\s*$/) ){\n break;\n }\n }\n\n self.length = i + 1;\n\n // adjust references for subject\n for(var j = 0; j < self.length; j++){\n var query = self[j];\n\n if( query.subject != null ){\n // go up the tree until we reach the subject\n for(;;){\n if( query.subject == query ){ break; } // done if subject is self\n\n if( query.parent != null ){ // swap parent/child reference\n var parent = query.parent;\n var child = query;\n\n child.parent = null;\n parent.child = child;\n\n query = parent; // go up the tree\n } else if( query.ancestor != null ){ // swap ancestor/descendant\n var ancestor = query.ancestor;\n var descendant = query;\n\n descendant.ancestor = null;\n ancestor.descendant = descendant;\n\n query = ancestor; // go up the tree\n } else {\n util.error('When adjusting references for the selector `'+ query +'`, neither parent nor ancestor was found');\n break;\n }\n } // for\n\n self[j] = query.subject; // subject should be the root query\n } // if\n } // for\n\n // make sure for each query that the subject group matches the implicit group if any\n if( onlyThisGroup != null ){\n for(var j = 0; j < self.length; j++){\n if( self[j].group != null && self[j].group != onlyThisGroup ){\n util.error('Group `'+ self[j].group +'` conflicts with implicit group `'+ onlyThisGroup +'` in selector `'+ selector +'`');\n return;\n }\n\n self[j].group = onlyThisGroup; // set to implicit group\n }\n }\n\n } else {\n util.error('A selector must be created from a string; found ' + selector);\n return;\n }\n\n self._private.invalid = false;\n\n};\n\nvar selfn = Selector.prototype;\n\nselfn.size = function(){\n return this.length;\n};\n\nselfn.eq = function(i){\n return this[i];\n};\n\nvar queryMatches = function(query, element){\n // check group\n if( query.group != null && query.group != '*' && query.group != element._private.group ){\n return false;\n }\n\n var cy = element.cy();\n\n // check colon selectors\n var allColonSelectorsMatch = true;\n for(var k = 0; k < query.colonSelectors.length; k++){\n var sel = query.colonSelectors[k];\n\n switch(sel){\n case ':selected':\n allColonSelectorsMatch = element.selected();\n break;\n case ':unselected':\n allColonSelectorsMatch = !element.selected();\n break;\n case ':selectable':\n allColonSelectorsMatch = element.selectable();\n break;\n case ':unselectable':\n allColonSelectorsMatch = !element.selectable();\n break;\n case ':locked':\n allColonSelectorsMatch = element.locked();\n break;\n case ':unlocked':\n allColonSelectorsMatch = !element.locked();\n break;\n case ':visible':\n allColonSelectorsMatch = element.visible();\n break;\n case ':hidden':\n allColonSelectorsMatch = !element.visible();\n break;\n case ':transparent':\n allColonSelectorsMatch = element.transparent();\n break;\n case ':grabbed':\n allColonSelectorsMatch = element.grabbed();\n break;\n case ':free':\n allColonSelectorsMatch = !element.grabbed();\n break;\n case ':removed':\n allColonSelectorsMatch = element.removed();\n break;\n case ':inside':\n allColonSelectorsMatch = !element.removed();\n break;\n case ':grabbable':\n allColonSelectorsMatch = element.grabbable();\n break;\n case ':ungrabbable':\n allColonSelectorsMatch = !element.grabbable();\n break;\n case ':animated':\n allColonSelectorsMatch = element.animated();\n break;\n case ':unanimated':\n allColonSelectorsMatch = !element.animated();\n break;\n case ':parent':\n allColonSelectorsMatch = element.isNode() && element.children().nonempty();\n break;\n case ':child':\n case ':nonorphan':\n allColonSelectorsMatch = element.isNode() && element.parent().nonempty();\n break;\n case ':orphan':\n allColonSelectorsMatch = element.isNode() && element.parent().empty();\n break;\n case ':loop':\n allColonSelectorsMatch = element.isEdge() && element.data('source') === element.data('target');\n break;\n case ':simple':\n allColonSelectorsMatch = element.isEdge() && element.data('source') !== element.data('target');\n break;\n case ':active':\n allColonSelectorsMatch = element.active();\n break;\n case ':inactive':\n allColonSelectorsMatch = !element.active();\n break;\n case ':touch':\n allColonSelectorsMatch = is.touch();\n break;\n case ':backgrounding':\n allColonSelectorsMatch = element.backgrounding();\n break;\n case ':nonbackgrounding':\n allColonSelectorsMatch = !element.backgrounding();\n break;\n }\n\n if( !allColonSelectorsMatch ) break;\n }\n if( !allColonSelectorsMatch ) return false;\n\n // check id\n var allIdsMatch = true;\n for(var k = 0; k < query.ids.length; k++){\n var id = query.ids[k];\n var actualId = element._private.data.id;\n\n allIdsMatch = allIdsMatch && (id == actualId);\n\n if( !allIdsMatch ) break;\n }\n if( !allIdsMatch ) return false;\n\n // check classes\n var allClassesMatch = true;\n for(var k = 0; k < query.classes.length; k++){\n var cls = query.classes[k];\n\n allClassesMatch = allClassesMatch && element.hasClass(cls);\n\n if( !allClassesMatch ) break;\n }\n if( !allClassesMatch ) return false;\n\n // generic checking for data/metadata\n var operandsMatch = function(params){\n var allDataMatches = true;\n for(var k = 0; k < query[params.name].length; k++){\n var data = query[params.name][k];\n var operator = data.operator;\n var value = data.value;\n var field = data.field;\n var matches;\n\n if( operator != null && value != null ){\n\n var fieldVal = params.fieldValue(field);\n var fieldStr = !is.string(fieldVal) && !is.number(fieldVal) ? '' : '' + fieldVal;\n var valStr = '' + value;\n\n var caseInsensitive = false;\n if( operator.indexOf('@') >= 0 ){\n fieldStr = fieldStr.toLowerCase();\n valStr = valStr.toLowerCase();\n\n operator = operator.replace('@', '');\n caseInsensitive = true;\n }\n\n var notExpr = false;\n var handledNotExpr = false;\n if( operator.indexOf('!') >= 0 ){\n operator = operator.replace('!', '');\n notExpr = true;\n }\n\n // if we're doing a case insensitive comparison, then we're using a STRING comparison\n // even if we're comparing numbers\n if( caseInsensitive ){\n value = valStr.toLowerCase();\n fieldVal = fieldStr.toLowerCase();\n }\n\n switch(operator){\n case '*=':\n matches = fieldStr.search(valStr) >= 0;\n break;\n case '$=':\n matches = new RegExp(valStr + '$').exec(fieldStr) != null;\n break;\n case '^=':\n matches = new RegExp('^' + valStr).exec(fieldStr) != null;\n break;\n case '=':\n matches = fieldVal === value;\n break;\n case '!=':\n matches = fieldVal !== value;\n break;\n case '>':\n matches = !notExpr ? fieldVal > value : fieldVal <= value;\n handledNotExpr = true;\n break;\n case '>=':\n matches = !notExpr ? fieldVal >= value : fieldVal < value;\n handledNotExpr = true;\n break;\n case '<':\n matches = !notExpr ? fieldVal < value : fieldVal >= value;\n handledNotExpr = true;\n break;\n case '<=':\n matches = !notExpr ? fieldVal <= value : fieldVal > value;\n handledNotExpr = true;\n break;\n default:\n matches = false;\n break;\n\n }\n } else if( operator != null ){\n switch(operator){\n case '?':\n matches = params.fieldTruthy(field);\n break;\n case '!':\n matches = !params.fieldTruthy(field);\n break;\n case '^':\n matches = params.fieldUndefined(field);\n break;\n }\n } else {\n matches = !params.fieldUndefined(field);\n }\n\n if( notExpr && !handledNotExpr ){\n matches = !matches;\n handledNotExpr = true;\n }\n\n if( !matches ){\n allDataMatches = false;\n break;\n }\n } // for\n\n return allDataMatches;\n }; // operandsMatch\n\n // check data matches\n var allDataMatches = operandsMatch({\n name: 'data',\n fieldValue: function(field){\n return element._private.data[field];\n },\n fieldRef: function(field){\n return 'element._private.data.' + field;\n },\n fieldUndefined: function(field){\n return element._private.data[field] === undefined;\n },\n fieldTruthy: function(field){\n if( element._private.data[field] ){\n return true;\n }\n return false;\n }\n });\n\n if( !allDataMatches ){\n return false;\n }\n\n // check metadata matches\n var allMetaMatches = operandsMatch({\n name: 'meta',\n fieldValue: function(field){\n return element[field]();\n },\n fieldRef: function(field){\n return 'element.' + field + '()';\n },\n fieldUndefined: function(field){\n return element[field]() == null;\n },\n fieldTruthy: function(field){\n if( element[field]() ){\n return true;\n }\n return false;\n }\n });\n\n if( !allMetaMatches ){\n return false;\n }\n\n // check collection\n if( query.collection != null ){\n var matchesAny = query.collection._private.ids[ element.id() ] != null;\n\n if( !matchesAny ){\n return false;\n }\n }\n\n // check filter function\n if( query.filter != null && element.collection().filter( query.filter ).size() === 0 ){\n return false;\n }\n\n\n // check parent/child relations\n var confirmRelations = function( query, elements ){\n if( query != null ){\n var matches = false;\n\n if( !cy.hasCompoundNodes() ){\n return false;\n }\n\n elements = elements(); // make elements functional so we save cycles if query == null\n\n // query must match for at least one element (may be recursive)\n for(var i = 0; i < elements.length; i++){\n if( queryMatches( query, elements[i] ) ){\n matches = true;\n break;\n }\n }\n\n return matches;\n } else {\n return true;\n }\n };\n\n if (! confirmRelations(query.parent, function(){\n return element.parent();\n }) ){ return false; }\n\n if (! confirmRelations(query.ancestor, function(){\n return element.parents();\n }) ){ return false; }\n\n if (! confirmRelations(query.child, function(){\n return element.children();\n }) ){ return false; }\n\n if (! confirmRelations(query.descendant, function(){\n return element.descendants();\n }) ){ return false; }\n\n // we've reached the end, so we've matched everything for this query\n return true;\n}; // queryMatches\n\n// filter an existing collection\nselfn.filter = function(collection){\n var self = this;\n var cy = collection.cy();\n\n // don't bother trying if it's invalid\n if( self._private.invalid ){\n return cy.collection();\n }\n\n var selectorFunction = function(i, element){\n for(var j = 0; j < self.length; j++){\n var query = self[j];\n\n if( queryMatches(query, element) ){\n return true;\n }\n }\n\n return false;\n };\n\n if( self._private.selectorText == null ){\n selectorFunction = function(){ return true; };\n }\n\n var filteredCollection = collection.filter( selectorFunction );\n\n return filteredCollection;\n}; // filter\n\n// does selector match a single element?\nselfn.matches = function(ele){\n var self = this;\n\n // don't bother trying if it's invalid\n if( self._private.invalid ){\n return false;\n }\n\n for(var j = 0; j < self.length; j++){\n var query = self[j];\n\n if( queryMatches(query, ele) ){\n return true;\n }\n }\n\n return false;\n}; // filter\n\n// ith query to string\nselfn.toString = selfn.selector = function(){\n\n var str = '';\n\n var clean = function(obj, isValue){\n if( is.string(obj) ){\n return isValue ? '\"' + obj + '\"' : obj;\n }\n return '';\n };\n\n var queryToString = function(query){\n var str = '';\n\n if( query.subject === query ){\n str += '$';\n }\n\n var group = clean(query.group);\n str += group.substring(0, group.length - 1);\n\n for(var j = 0; j < query.data.length; j++){\n var data = query.data[j];\n\n if( data.value ){\n str += '[' + data.field + clean(data.operator) + clean(data.value, true) + ']';\n } else {\n str += '[' + clean(data.operator) + data.field + ']';\n }\n }\n\n for(var j = 0; j < query.meta.length; j++){\n var meta = query.meta[j];\n str += '[[' + meta.field + clean(meta.operator) + clean(meta.value, true) + ']]';\n }\n\n for(var j = 0; j < query.colonSelectors.length; j++){\n var sel = query.colonSelectors[i];\n str += sel;\n }\n\n for(var j = 0; j < query.ids.length; j++){\n var sel = '#' + query.ids[i];\n str += sel;\n }\n\n for(var j = 0; j < query.classes.length; j++){\n var sel = '.' + query.classes[j];\n str += sel;\n }\n\n if( query.parent != null ){\n str = queryToString( query.parent ) + ' > ' + str;\n }\n\n if( query.ancestor != null ){\n str = queryToString( query.ancestor ) + ' ' + str;\n }\n\n if( query.child != null ){\n str += ' > ' + queryToString( query.child );\n }\n\n if( query.descendant != null ){\n str += ' ' + queryToString( query.descendant );\n }\n\n return str;\n };\n\n for(var i = 0; i < this.length; i++){\n var query = this[i];\n\n str += queryToString( query );\n\n if( this.length > 1 && i < this.length - 1 ){\n str += ', ';\n }\n }\n\n return str;\n};\n\nmodule.exports = Selector;\n","'use strict';\n\nvar util = require('../util');\nvar is = require('../is');\n\nvar styfn = {};\n\n// (potentially expensive calculation)\n// apply the style to the element based on\n// - its bypass\n// - what selectors match it\nstyfn.apply = function( eles ){\n var self = this;\n\n if( self._private.newStyle ){ // clear style caches\n this._private.contextStyles = {};\n this._private.propDiffs = {};\n }\n\n for( var ie = 0; ie < eles.length; ie++ ){\n var ele = eles[ie];\n var cxtMeta = self.getContextMeta( ele );\n var cxtStyle = self.getContextStyle( cxtMeta );\n var app = self.applyContextStyle( cxtMeta, cxtStyle, ele );\n\n self.updateTransitions( ele, app.diffProps );\n self.updateStyleHints( ele );\n\n } // for elements\n\n self._private.newStyle = false;\n};\n\nstyfn.getPropertiesDiff = function( oldCxtKey, newCxtKey ){\n var self = this;\n var cache = self._private.propDiffs = self._private.propDiffs || {};\n var dualCxtKey = oldCxtKey + '-' + newCxtKey;\n var cachedVal = cache[dualCxtKey];\n\n if( cachedVal ){\n return cachedVal;\n }\n\n var diffProps = [];\n var addedProp = {};\n\n for( var i = 0; i < self.length; i++ ){\n var cxt = self[i];\n var oldHasCxt = oldCxtKey[i] === 't';\n var newHasCxt = newCxtKey[i] === 't';\n var cxtHasDiffed = oldHasCxt !== newHasCxt;\n var cxtHasMappedProps = cxt.mappedProperties.length > 0;\n\n if( cxtHasDiffed || cxtHasMappedProps ){\n var props;\n\n if( cxtHasDiffed && cxtHasMappedProps ){\n props = cxt.properties; // suffices b/c mappedProperties is a subset of properties\n } else if( cxtHasDiffed ){\n props = cxt.properties; // need to check them all\n } else if( cxtHasMappedProps ){\n props = cxt.mappedProperties; // only need to check mapped\n }\n\n for( var j = 0; j < props.length; j++ ){\n var prop = props[j];\n var name = prop.name;\n\n // if a later context overrides this property, then the fact that this context has switched/diffed doesn't matter\n // (semi expensive check since it makes this function O(n^2) on context length, but worth it since overall result\n // is cached)\n var laterCxtOverrides = false;\n for( var k = i + 1; k < self.length; k++ ){\n var laterCxt = self[k];\n var hasLaterCxt = newCxtKey[k] === 't';\n\n if( !hasLaterCxt ){ continue; } // can't override unless the context is active\n\n laterCxtOverrides = laterCxt.properties[ prop.name ] != null;\n\n if( laterCxtOverrides ){ break; } // exit early as long as one later context overrides\n }\n\n if( !addedProp[name] && !laterCxtOverrides ){\n addedProp[name] = true;\n diffProps.push( name );\n }\n } // for props\n } // if\n\n } // for contexts\n\n cache[ dualCxtKey ] = diffProps;\n return diffProps;\n};\n\nstyfn.getContextMeta = function( ele ){\n var self = this;\n var cxtKey = '';\n var diffProps;\n var prevKey = ele._private.styleCxtKey || '';\n\n if( self._private.newStyle ){\n prevKey = ''; // since we need to apply all style if a fresh stylesheet\n }\n\n // get the cxt key\n for( var i = 0; i < self.length; i++ ){\n var context = self[i];\n var contextSelectorMatches = context.selector && context.selector.matches( ele ); // NB: context.selector may be null for 'core'\n\n if( contextSelectorMatches ){\n cxtKey += 't';\n } else {\n cxtKey += 'f';\n }\n } // for context\n\n diffProps = self.getPropertiesDiff( prevKey, cxtKey );\n\n ele._private.styleCxtKey = cxtKey;\n\n return {\n key: cxtKey,\n diffPropNames: diffProps\n };\n};\n\n// gets a computed ele style object based on matched contexts\nstyfn.getContextStyle = function( cxtMeta ){\n var cxtKey = cxtMeta.key;\n var self = this;\n var cxtStyles = this._private.contextStyles = this._private.contextStyles || {};\n\n // if already computed style, returned cached copy\n if( cxtStyles[cxtKey] ){ return cxtStyles[cxtKey]; }\n\n var style = {\n _private: {\n key: cxtKey\n }\n };\n\n for( var i = 0; i < self.length; i++ ){\n var cxt = self[i];\n var hasCxt = cxtKey[i] === 't';\n\n if( !hasCxt ){ continue; }\n\n for( var j = 0; j < cxt.properties.length; j++ ){\n var prop = cxt.properties[j];\n var styProp = style[ prop.name ] = prop;\n\n styProp.context = cxt;\n }\n }\n\n cxtStyles[cxtKey] = style;\n return style;\n};\n\nstyfn.applyContextStyle = function( cxtMeta, cxtStyle, ele ){\n var self = this;\n var diffProps = cxtMeta.diffPropNames;\n var retDiffProps = {};\n\n for( var i = 0; i < diffProps.length; i++ ){\n var diffPropName = diffProps[i];\n var cxtProp = cxtStyle[ diffPropName ];\n var eleProp = ele._private.style[ diffPropName ];\n\n // save cycles when the context prop doesn't need to be applied\n if( !cxtProp || eleProp === cxtProp ){ continue; }\n\n var retDiffProp = retDiffProps[ diffPropName ] = {\n prev: eleProp\n };\n\n self.applyParsedProperty( ele, cxtProp );\n\n retDiffProp.next = ele._private.style[ diffPropName ];\n\n if( retDiffProp.next && retDiffProp.next.bypass ){\n retDiffProp.next = retDiffProp.next.bypassed;\n }\n }\n\n return {\n diffProps: retDiffProps\n };\n};\n\nstyfn.updateStyleHints = function(ele){\n var _p = ele._private;\n var self = this;\n var style = _p.style;\n\n if( ele.removed() ){ return; }\n\n // set whether has pie or not; for greater efficiency\n var hasPie = false;\n if( _p.group === 'nodes' && self._private.hasPie ){\n for( var i = 1; i <= self.pieBackgroundN; i++ ){ // 1..N\n var size = _p.style['pie-' + i + '-background-size'].value;\n\n if( size > 0 ){\n hasPie = true;\n break;\n }\n }\n }\n\n _p.hasPie = hasPie;\n\n var transform = style['text-transform'].strValue;\n var content = style['label'].strValue;\n var fStyle = style['font-style'].strValue;\n var size = style['font-size'].pfValue + 'px';\n var family = style['font-family'].strValue;\n // var variant = style['font-variant'].strValue;\n var weight = style['font-weight'].strValue;\n var valign = style['text-valign'].strValue;\n var halign = style['text-valign'].strValue;\n var oWidth = style['text-outline-width'].pfValue;\n var wrap = style['text-wrap'].strValue;\n var wrapW = style['text-max-width'].pfValue;\n _p.labelKey = fStyle +'$'+ size +'$'+ family +'$'+ weight +'$'+ content +'$'+ transform +'$'+ valign +'$'+ halign +'$'+ oWidth + '$' + wrap + '$' + wrapW;\n _p.fontKey = fStyle +'$'+ weight +'$'+ size +'$'+ family;\n\n var width = style['width'].pfValue;\n var height = style['height'].pfValue;\n var borderW = style['border-width'].pfValue;\n _p.boundingBoxKey = width +'$'+ height +'$'+ borderW;\n\n if( ele._private.group === 'edges' ){\n var cpss = style['control-point-step-size'].pfValue;\n var cpd = style['control-point-distances'] ? style['control-point-distances'].pfValue.join('_') : undefined;\n var cpw = style['control-point-weights'].value.join('_');\n var curve = style['curve-style'].strValue;\n var sd = style['segment-distances'] ? style['segment-distances'].pfValue.join('_') : undefined;\n var sw = style['segment-weights'].value.join('_');\n\n _p.boundingBoxKey += '$'+ cpss +'$'+ cpd +'$'+ cpw +'$'+ sd +'$'+ sw +'$'+ curve;\n }\n\n _p.styleKey = Date.now();\n};\n\n// apply a property to the style (for internal use)\n// returns whether application was successful\n//\n// now, this function flattens the property, and here's how:\n//\n// for parsedProp:{ bypass: true, deleteBypass: true }\n// no property is generated, instead the bypass property in the\n// element's style is replaced by what's pointed to by the `bypassed`\n// field in the bypass property (i.e. restoring the property the\n// bypass was overriding)\n//\n// for parsedProp:{ mapped: truthy }\n// the generated flattenedProp:{ mapping: prop }\n//\n// for parsedProp:{ bypass: true }\n// the generated flattenedProp:{ bypassed: parsedProp }\nstyfn.applyParsedProperty = function( ele, parsedProp ){\n var self = this;\n var prop = parsedProp;\n var style = ele._private.style;\n var fieldVal, flatProp;\n var types = self.types;\n var type = self.properties[ prop.name ].type;\n var propIsBypass = prop.bypass;\n var origProp = style[ prop.name ];\n var origPropIsBypass = origProp && origProp.bypass;\n var _p = ele._private;\n\n // can't apply auto to width or height unless it's a parent node\n if( (parsedProp.name === 'height' || parsedProp.name === 'width') && ele.isNode() ){\n if( parsedProp.value === 'auto' && !ele.isParent() ){\n return false;\n } else if( parsedProp.value !== 'auto' && ele.isParent() ){\n prop = parsedProp = this.parse( parsedProp.name, 'auto', propIsBypass );\n }\n }\n\n // check if we need to delete the current bypass\n if( propIsBypass && prop.deleteBypass ){ // then this property is just here to indicate we need to delete\n var currentProp = style[ prop.name ];\n\n // can only delete if the current prop is a bypass and it points to the property it was overriding\n if( !currentProp ){\n return true; // property is already not defined\n } else if( currentProp.bypass && currentProp.bypassed ){ // then replace the bypass property with the original\n\n // because the bypassed property was already applied (and therefore parsed), we can just replace it (no reapplying necessary)\n style[ prop.name ] = currentProp.bypassed;\n return true;\n\n } else {\n return false; // we're unsuccessful deleting the bypass\n }\n }\n\n var printMappingErr = function(){\n util.error('Do not assign mappings to elements without corresponding data (e.g. ele `'+ ele.id() +'` for property `'+ prop.name +'` with data field `'+ prop.field +'`); try a `['+ prop.field +']` selector to limit scope to elements with `'+ prop.field +'` defined');\n };\n\n // put the property in the style objects\n switch( prop.mapped ){ // flatten the property if mapped\n case types.mapData:\n case types.mapLayoutData:\n case types.mapScratch:\n\n var isLayout = prop.mapped === types.mapLayoutData;\n var isScratch = prop.mapped === types.mapScratch;\n\n // flatten the field (e.g. data.foo.bar)\n var fields = prop.field.split(\".\");\n var fieldVal;\n\n if( isScratch || isLayout ){\n fieldVal = _p.scratch;\n } else {\n fieldVal = _p.data;\n }\n\n for( var i = 0; i < fields.length && fieldVal; i++ ){\n var field = fields[i];\n fieldVal = fieldVal[ field ];\n }\n\n var percent;\n if( !is.number(fieldVal) ){ // then keep the mapping but assume 0% for now\n percent = 0;\n } else {\n percent = (fieldVal - prop.fieldMin) / (prop.fieldMax - prop.fieldMin);\n }\n\n // make sure to bound percent value\n if( percent < 0 ){\n percent = 0;\n } else if( percent > 1 ){\n percent = 1;\n }\n\n if( type.color ){\n var r1 = prop.valueMin[0];\n var r2 = prop.valueMax[0];\n var g1 = prop.valueMin[1];\n var g2 = prop.valueMax[1];\n var b1 = prop.valueMin[2];\n var b2 = prop.valueMax[2];\n var a1 = prop.valueMin[3] == null ? 1 : prop.valueMin[3];\n var a2 = prop.valueMax[3] == null ? 1 : prop.valueMax[3];\n\n var clr = [\n Math.round( r1 + (r2 - r1)*percent ),\n Math.round( g1 + (g2 - g1)*percent ),\n Math.round( b1 + (b2 - b1)*percent ),\n Math.round( a1 + (a2 - a1)*percent )\n ];\n\n flatProp = { // colours are simple, so just create the flat property instead of expensive string parsing\n bypass: prop.bypass, // we're a bypass if the mapping property is a bypass\n name: prop.name,\n value: clr,\n strValue: 'rgb(' + clr[0] + ', ' + clr[1] + ', ' + clr[2] + ')'\n };\n\n } else if( type.number ){\n var calcValue = prop.valueMin + (prop.valueMax - prop.valueMin) * percent;\n flatProp = this.parse( prop.name, calcValue, prop.bypass, true );\n\n } else {\n return false; // can only map to colours and numbers\n }\n\n if( !flatProp ){ // if we can't flatten the property, then use the origProp so we still keep the mapping itself\n flatProp = this.parse( prop.name, origProp.strValue, prop.bypass, true );\n }\n\n if( !flatProp ){ printMappingErr(); }\n flatProp.mapping = prop; // keep a reference to the mapping\n prop = flatProp; // the flattened (mapped) property is the one we want\n\n break;\n\n // direct mapping\n case types.data:\n case types.layoutData:\n case types.scratch:\n var isLayout = prop.mapped === types.layoutData;\n var isScratch = prop.mapped === types.scratch;\n\n // flatten the field (e.g. data.foo.bar)\n var fields = prop.field.split(\".\");\n var fieldVal;\n\n if( isScratch || isLayout ){\n fieldVal = _p.scratch;\n } else {\n fieldVal = _p.data;\n }\n\n if( fieldVal ){ for( var i = 0; i < fields.length; i++ ){\n var field = fields[i];\n fieldVal = fieldVal[ field ];\n } }\n\n flatProp = this.parse( prop.name, fieldVal, prop.bypass, true );\n\n if( !flatProp ){ // if we can't flatten the property, then use the origProp so we still keep the mapping itself\n var flatPropVal = origProp ? origProp.strValue : '';\n\n flatProp = this.parse( prop.name, flatPropVal, prop.bypass, true );\n }\n\n if( !flatProp ){ printMappingErr(); }\n flatProp.mapping = prop; // keep a reference to the mapping\n prop = flatProp; // the flattened (mapped) property is the one we want\n\n break;\n\n case types.fn:\n var fn = prop.value;\n var fnRetVal = fn( ele );\n\n flatProp = this.parse( prop.name, fnRetVal, prop.bypass, true );\n flatProp.mapping = prop; // keep a reference to the mapping\n prop = flatProp; // the flattened (mapped) property is the one we want\n\n break;\n\n case undefined:\n break; // just set the property\n\n default:\n return false; // not a valid mapping\n }\n\n // if the property is a bypass property, then link the resultant property to the original one\n if( propIsBypass ){\n if( origPropIsBypass ){ // then this bypass overrides the existing one\n prop.bypassed = origProp.bypassed; // steal bypassed prop from old bypass\n } else { // then link the orig prop to the new bypass\n prop.bypassed = origProp;\n }\n\n style[ prop.name ] = prop; // and set\n\n } else { // prop is not bypass\n if( origPropIsBypass ){ // then keep the orig prop (since it's a bypass) and link to the new prop\n origProp.bypassed = prop;\n } else { // then just replace the old prop with the new one\n style[ prop.name ] = prop;\n }\n }\n\n return true;\n};\n\n// updates the visual style for all elements (useful for manual style modification after init)\nstyfn.update = function(){\n var cy = this._private.cy;\n var eles = cy.elements();\n\n eles.updateStyle();\n};\n\n// just update the functional properties (i.e. mappings) in the elements'\n// styles (less expensive than recalculation)\nstyfn.updateMappers = function( eles ){\n var self = this;\n\n for( var i = 0; i < eles.length; i++ ){ // for each ele\n var ele = eles[i];\n var style = ele._private.style;\n\n for( var j = 0; j < self.properties.length; j++ ){ // for each prop\n var prop = self.properties[j];\n var propInStyle = style[ prop.name ];\n\n if( propInStyle && propInStyle.mapping ){\n var mapping = propInStyle.mapping;\n this.applyParsedProperty( ele, mapping ); // reapply the mapping property\n }\n }\n\n this.updateStyleHints( ele );\n }\n};\n\n// diffProps : { name => { prev, next } }\nstyfn.updateTransitions = function( ele, diffProps, isBypass ){\n var self = this;\n var _p = ele._private;\n var style = _p.style;\n var props = style['transition-property'].value;\n var duration = style['transition-duration'].pfValue;\n var delay = style['transition-delay'].pfValue;\n var css = {};\n\n if( props.length > 0 && duration > 0 ){\n\n // build up the style to animate towards\n var anyPrev = false;\n for( var i = 0; i < props.length; i++ ){\n var prop = props[i];\n var styProp = style[ prop ];\n var diffProp = diffProps[ prop ];\n\n if( !diffProp ){ continue; }\n\n var prevProp = diffProp.prev;\n var fromProp = prevProp;\n var toProp = diffProp.next != null ? diffProp.next : styProp;\n var diff = false;\n var initVal;\n var initDt = 0.000001; // delta time % value for initVal (allows animating out of init zero opacity)\n\n if( !fromProp ){ continue; }\n\n // consider px values\n if( is.number( fromProp.pfValue ) && is.number( toProp.pfValue ) ){\n diff = toProp.pfValue - fromProp.pfValue; // nonzero is truthy\n initVal = fromProp.pfValue + initDt * diff;\n\n // consider numerical values\n } else if( is.number( fromProp.value ) && is.number( toProp.value ) ){\n diff = toProp.value - fromProp.value; // nonzero is truthy\n initVal = fromProp.value + initDt * diff;\n\n // consider colour values\n } else if( is.array( fromProp.value ) && is.array( toProp.value ) ){\n diff = fromProp.value[0] !== toProp.value[0]\n || fromProp.value[1] !== toProp.value[1]\n || fromProp.value[2] !== toProp.value[2]\n ;\n\n initVal = fromProp.strValue;\n }\n\n // the previous value is good for an animation only if it's different\n if( diff ){\n css[ prop ] = toProp.strValue; // to val\n this.applyBypass( ele, prop, initVal ); // from val\n anyPrev = true;\n }\n\n } // end if props allow ani\n\n // can't transition if there's nothing previous to transition from\n if( !anyPrev ){ return; }\n\n _p.transitioning = true;\n\n ele.stop();\n\n if( delay > 0 ){\n ele.delay( delay );\n }\n\n ele.animate({\n css: css\n }, {\n duration: duration,\n easing: style['transition-timing-function'].value,\n queue: false,\n complete: function(){\n if( !isBypass ){\n self.removeBypasses( ele, props );\n }\n\n _p.transitioning = false;\n }\n });\n\n } else if( _p.transitioning ){\n ele.stop();\n\n this.removeBypasses( ele, props );\n\n _p.transitioning = false;\n }\n};\n\nmodule.exports = styfn;\n","'use strict';\n\nvar is = require('../is');\nvar util = require('../util');\n\nvar styfn = {};\n\n// bypasses are applied to an existing style on an element, and just tacked on temporarily\n// returns true iff application was successful for at least 1 specified property\nstyfn.applyBypass = function( eles, name, value, updateTransitions ){\n var self = this;\n var props = [];\n var isBypass = true;\n\n // put all the properties (can specify one or many) in an array after parsing them\n if( name === \"*\" || name === \"**\" ){ // apply to all property names\n\n if( value !== undefined ){\n for( var i = 0; i < self.properties.length; i++ ){\n var prop = self.properties[i];\n var name = prop.name;\n\n var parsedProp = this.parse(name, value, true);\n\n if( parsedProp ){\n props.push( parsedProp );\n }\n }\n }\n\n } else if( is.string(name) ){ // then parse the single property\n var parsedProp = this.parse(name, value, true);\n\n if( parsedProp ){\n props.push( parsedProp );\n }\n } else if( is.plainObject(name) ){ // then parse each property\n var specifiedProps = name;\n updateTransitions = value;\n\n for( var i = 0; i < self.properties.length; i++ ){\n var prop = self.properties[i];\n var name = prop.name;\n var value = specifiedProps[ name ];\n\n if( value === undefined ){ // try camel case name too\n value = specifiedProps[ util.dash2camel(name) ];\n }\n\n if( value !== undefined ){\n var parsedProp = this.parse(name, value, true);\n\n if( parsedProp ){\n props.push( parsedProp );\n }\n }\n }\n } else { // can't do anything without well defined properties\n return false;\n }\n\n // we've failed if there are no valid properties\n if( props.length === 0 ){ return false; }\n\n // now, apply the bypass properties on the elements\n var ret = false; // return true if at least one succesful bypass applied\n for( var i = 0; i < eles.length; i++ ){ // for each ele\n var ele = eles[i];\n var style = ele._private.style;\n var diffProps = {};\n var diffProp;\n\n for( var j = 0; j < props.length; j++ ){ // for each prop\n var prop = props[j];\n\n if( updateTransitions ){\n var prevProp = style[ prop.name ];\n diffProp = diffProps[ prop.name ] = { prev: prevProp };\n }\n\n ret = this.applyParsedProperty( ele, prop ) || ret;\n\n if( updateTransitions ){\n diffProp.next = style[ prop.name ];\n }\n\n } // for props\n\n if( ret ){\n this.updateStyleHints( ele );\n }\n\n if( updateTransitions ){\n this.updateTransitions( ele, diffProps, isBypass );\n }\n } // for eles\n\n return ret;\n};\n\n// only useful in specific cases like animation\nstyfn.overrideBypass = function( eles, name, value ){\n name = util.camel2dash(name);\n\n for( var i = 0; i < eles.length; i++ ){\n var ele = eles[i];\n var prop = ele._private.style[ name ];\n var type = this.properties[ name ].type;\n var isColor = type.color;\n var isMulti = type.mutiple;\n\n if( !prop.bypass ){ // need a bypass if one doesn't exist\n this.applyBypass( ele, name, value );\n continue;\n }\n\n prop.value = value;\n\n if( prop.pfValue != null ){\n prop.pfValue = value;\n }\n\n if( isColor ){\n prop.strValue = 'rgb(' + value.join(',') + ')';\n } else if( isMulti ){\n prop.strValue = value.join(' ');\n } else {\n prop.strValue = '' + value;\n }\n }\n};\n\nstyfn.removeAllBypasses = function( eles, updateTransitions ){\n return this.removeBypasses( eles, this.propertyNames, updateTransitions );\n};\n\nstyfn.removeBypasses = function( eles, props, updateTransitions ){\n var isBypass = true;\n\n for( var j = 0; j < eles.length; j++ ){\n var ele = eles[j];\n var diffProps = {};\n var style = ele._private.style;\n\n for( var i = 0; i < props.length; i++ ){\n var name = props[i];\n var prop = this.properties[ name ];\n var value = ''; // empty => remove bypass\n var parsedProp = this.parse(name, value, true);\n var prevProp = style[ prop.name ];\n var diffProp = diffProps[ prop.name ] = { prev: prevProp };\n\n this.applyParsedProperty(ele, parsedProp);\n\n diffProp.next = style[ prop.name ];\n } // for props\n\n this.updateStyleHints( ele );\n\n if( updateTransitions ){\n this.updateTransitions( ele, diffProps, isBypass );\n }\n } // for eles\n};\n\nmodule.exports = styfn;\n","'use strict';\n\nvar window = require('../window');\n\nvar styfn = {};\n\n// gets what an em size corresponds to in pixels relative to a dom element\nstyfn.getEmSizeInPixels = function(){\n var px = this.containerCss('font-size');\n\n if( px != null ){\n return parseFloat( px );\n } else {\n return 1; // for headless\n }\n};\n\n// gets css property from the core container\nstyfn.containerCss = function( propName ){\n var cy = this._private.cy;\n var domElement = cy.container();\n\n if( window && domElement && window.getComputedStyle ){\n return window.getComputedStyle(domElement).getPropertyValue( propName );\n }\n};\n\nmodule.exports = styfn;\n","'use strict';\n\nvar util = require('../util');\nvar is = require('../is');\n\nvar styfn = {};\n\n// gets the rendered style for an element\nstyfn.getRenderedStyle = function( ele ){\n return this.getRawStyle( ele, true );\n};\n\n// gets the raw style for an element\nstyfn.getRawStyle = function( ele, isRenderedVal ){\n var self = this;\n var ele = ele[0]; // insure it's an element\n\n if( ele ){\n var rstyle = {};\n\n for( var i = 0; i < self.properties.length; i++ ){\n var prop = self.properties[i];\n var val = self.getStylePropertyValue( ele, prop.name, isRenderedVal );\n\n if( val ){\n rstyle[ prop.name ] = val;\n rstyle[ util.dash2camel(prop.name) ] = val;\n }\n }\n\n return rstyle;\n }\n};\n\nstyfn.getStylePropertyValue = function( ele, propName, isRenderedVal ){\n var self = this;\n var ele = ele[0]; // insure it's an element\n\n if( ele ){\n var style = ele._private.style;\n var prop = self.properties[ propName ];\n var type = prop.type;\n var styleProp = style[ prop.name ];\n var zoom = ele.cy().zoom();\n\n if( styleProp ){\n var units = styleProp.units ? type.implicitUnits || 'px' : null;\n var val = units ? [].concat( styleProp.pfValue ).map(function( pfValue ){\n return ( pfValue * (isRenderedVal ? zoom : 1) ) + units;\n }).join(' ') : styleProp.strValue;\n\n return val;\n }\n }\n};\n\n// gets the value style for an element (useful for things like animations)\nstyfn.getValueStyle = function( ele ){\n var self = this;\n var rstyle = {};\n var style;\n var isEle = is.element(ele);\n\n if( isEle ){\n style = ele._private.style;\n } else {\n style = ele; // just passed the style itself\n }\n\n if( style ){\n for( var i = 0; i < self.properties.length; i++ ){\n var prop = self.properties[i];\n var styleProp = style[ prop.name ] || style[ util.dash2camel(prop.name) ];\n\n if( styleProp !== undefined ){ // then make a prop of it\n if( is.plainObject( styleProp ) ){\n styleProp = this.parse( prop.name, styleProp.strValue );\n } else {\n styleProp = this.parse( prop.name, styleProp );\n }\n }\n\n if( styleProp ){\n rstyle[ prop.name ] = styleProp;\n rstyle[ util.dash2camel(prop.name) ] = styleProp;\n }\n }\n }\n\n return rstyle;\n};\n\nstyfn.getPropsList = function( propsObj ){\n var self = this;\n var rstyle = [];\n var style = propsObj;\n var props = self.properties;\n\n if( style ){\n for( var name in style ){\n var val = style[name];\n var prop = props[name] || props[ util.camel2dash(name) ];\n var styleProp = this.parse( prop.name, val );\n\n rstyle.push( styleProp );\n }\n }\n\n return rstyle;\n};\n\nmodule.exports = styfn;\n","'use strict';\n\nvar is = require('../is');\nvar util = require('../util');\nvar Selector = require('../selector');\n\nvar Style = function( cy ){\n\n if( !(this instanceof Style) ){\n return new Style(cy);\n }\n\n if( !is.core(cy) ){\n util.error('A style must have a core reference');\n return;\n }\n\n this._private = {\n cy: cy,\n coreStyle: {},\n newStyle: true\n };\n\n this.length = 0;\n\n this.addDefaultStylesheet();\n};\n\nvar styfn = Style.prototype;\n\nstyfn.instanceString = function(){\n return 'style';\n};\n\n// remove all contexts\nstyfn.clear = function(){\n for( var i = 0; i < this.length; i++ ){\n this[i] = undefined;\n }\n this.length = 0;\n this._private.newStyle = true;\n\n return this; // chaining\n};\n\nstyfn.resetToDefault = function(){\n this.clear();\n this.addDefaultStylesheet();\n\n return this;\n};\n\n// builds a style object for the 'core' selector\nstyfn.core = function(){\n return this._private.coreStyle;\n};\n\n// create a new context from the specified selector string and switch to that context\nstyfn.selector = function( selectorStr ){\n // 'core' is a special case and does not need a selector\n var selector = selectorStr === 'core' ? null : new Selector( selectorStr );\n\n var i = this.length++; // new context means new index\n this[i] = {\n selector: selector,\n properties: [],\n mappedProperties: [],\n index: i\n };\n\n return this; // chaining\n};\n\n// add one or many css rules to the current context\nstyfn.css = function(){\n var self = this;\n var args = arguments;\n\n switch( args.length ){\n case 1:\n var map = args[0];\n\n for( var i = 0; i < self.properties.length; i++ ){\n var prop = self.properties[i];\n var mapVal = map[ prop.name ];\n\n if( mapVal === undefined ){\n mapVal = map[ util.dash2camel(prop.name) ];\n }\n\n if( mapVal !== undefined ){\n this.cssRule( prop.name, mapVal );\n }\n }\n\n break;\n\n case 2:\n this.cssRule( args[0], args[1] );\n break;\n\n default:\n break; // do nothing if args are invalid\n }\n\n return this; // chaining\n};\nstyfn.style = styfn.css;\n\n// add a single css rule to the current context\nstyfn.cssRule = function( name, value ){\n // name-value pair\n var property = this.parse( name, value );\n\n // add property to current context if valid\n if( property ){\n var i = this.length - 1;\n this[i].properties.push( property );\n this[i].properties[ property.name ] = property; // allow access by name as well\n\n if( property.name.match(/pie-(\\d+)-background-size/) && property.value ){\n this._private.hasPie = true;\n }\n\n if( property.mapped ){\n this[i].mappedProperties.push( property );\n }\n\n // add to core style if necessary\n var currentSelectorIsCore = !this[i].selector;\n if( currentSelectorIsCore ){\n this._private.coreStyle[ property.name ] = property;\n }\n }\n\n return this; // chaining\n};\n\n// static function\nStyle.fromJson = function( cy, json ){\n var style = new Style( cy );\n\n style.fromJson( json );\n\n return style;\n};\n\nStyle.fromString = function( cy, string ){\n return new Style( cy ).fromString( string );\n};\n\n[\n require('./apply'),\n require('./bypass'),\n require('./container'),\n require('./get-for-ele'),\n require('./json'),\n require('./string-sheet'),\n require('./properties'),\n require('./parse')\n].forEach(function( props ){\n util.extend( styfn, props );\n});\n\n\nStyle.types = styfn.types;\nStyle.properties = styfn.properties;\n\nmodule.exports = Style;\n","'use strict';\n\nvar styfn = {};\n\nstyfn.applyFromJson = function( json ){\n var style = this;\n\n for( var i = 0; i < json.length; i++ ){\n var context = json[i];\n var selector = context.selector;\n var props = context.style || context.css;\n\n style.selector( selector ); // apply selector\n\n for( var name in props ){\n var value = props[name];\n\n style.css( name, value ); // apply property\n }\n }\n\n return style;\n};\n\n// accessible cy.style() function\nstyfn.fromJson = function( json ){\n var style = this;\n\n style.resetToDefault();\n style.applyFromJson( json );\n\n return style;\n};\n\n// get json from cy.style() api\nstyfn.json = function(){\n var json = [];\n\n for( var i = this.defaultLength; i < this.length; i++ ){\n var cxt = this[i];\n var selector = cxt.selector;\n var props = cxt.properties;\n var css = {};\n\n for( var j = 0; j < props.length; j++ ){\n var prop = props[j];\n css[ prop.name ] = prop.strValue;\n }\n\n json.push({\n selector: !selector ? 'core' : selector.toString(),\n style: css\n });\n }\n\n return json;\n};\n\nmodule.exports = styfn;\n","'use strict';\n\nvar util = require('../util');\nvar is = require('../is');\n\nvar styfn = {};\n\n// a caching layer for property parsing\nstyfn.parse = function( name, value, propIsBypass, propIsFlat ){\n var argHash = [ name, value, propIsBypass, propIsFlat ].join('$');\n var propCache = this.propCache = this.propCache || {};\n var ret;\n var impl = parseImpl.bind( this );\n\n if( !(ret = propCache[argHash]) ){\n ret = propCache[argHash] = impl( name, value, propIsBypass, propIsFlat );\n }\n\n // always need a copy since props are mutated later in their lifecycles\n ret = util.copy( ret );\n\n if( ret ){\n ret.value = util.copy( ret.value ); // because it could be an array, e.g. colour\n }\n\n return ret;\n};\n\n// parse a property; return null on invalid; return parsed property otherwise\n// fields :\n// - name : the name of the property\n// - value : the parsed, native-typed value of the property\n// - strValue : a string value that represents the property value in valid css\n// - bypass : true iff the property is a bypass property\nvar parseImpl = function( name, value, propIsBypass, propIsFlat ){\n var self = this;\n\n name = util.camel2dash( name ); // make sure the property name is in dash form (e.g. 'property-name' not 'propertyName')\n\n var property = self.properties[ name ];\n var passedValue = value;\n var types = self.types;\n\n if( !property ){ return null; } // return null on property of unknown name\n if( value === undefined || value === null ){ return null; } // can't assign null\n\n // the property may be an alias\n if( property.alias ){\n property = property.pointsTo;\n name = property.name;\n }\n\n var valueIsString = is.string(value);\n if( valueIsString ){ // trim the value to make parsing easier\n value = value.trim();\n }\n\n var type = property.type;\n if( !type ){ return null; } // no type, no luck\n\n // check if bypass is null or empty string (i.e. indication to delete bypass property)\n if( propIsBypass && (value === '' || value === null) ){\n return {\n name: name,\n value: value,\n bypass: true,\n deleteBypass: true\n };\n }\n\n // check if value is a function used as a mapper\n if( is.fn(value) ){\n return {\n name: name,\n value: value,\n strValue: 'fn',\n mapped: types.fn,\n bypass: propIsBypass\n };\n }\n\n // check if value is mapped\n var data, mapData, layoutData, mapLayoutData, scratch, mapScratch;\n if( !valueIsString || propIsFlat ){\n // then don't bother to do the expensive regex checks\n\n } else if(\n ( data = new RegExp( types.data.regex ).exec( value ) ) ||\n ( layoutData = new RegExp( types.layoutData.regex ).exec( value ) ) ||\n ( scratch = new RegExp( types.scratch.regex ).exec( value ) )\n ){\n if( propIsBypass ){ return false; } // mappers not allowed in bypass\n\n var mapped;\n if( data ){\n mapped = types.data;\n } else if( layoutData ){\n mapped = types.layoutData;\n } else {\n mapped = types.scratch;\n }\n\n data = data || layoutData || scratch;\n\n return {\n name: name,\n value: data,\n strValue: '' + value,\n mapped: mapped,\n field: data[1],\n bypass: propIsBypass\n };\n\n } else if(\n ( mapData = new RegExp( types.mapData.regex ).exec( value ) ) ||\n ( mapLayoutData = new RegExp( types.mapLayoutData.regex ).exec( value ) ) ||\n ( mapScratch = new RegExp( types.mapScratch.regex ).exec( value ) )\n ){\n if( propIsBypass ){ return false; } // mappers not allowed in bypass\n if( type.multiple ){ return false; } // impossible to map to num\n\n var mapped;\n if( mapData ){\n mapped = types.mapData;\n } else if( mapLayoutData ){\n mapped = types.mapLayoutData;\n } else {\n mapped = types.mapScratch;\n }\n\n mapData = mapData || mapLayoutData || mapScratch;\n\n // we can map only if the type is a colour or a number\n if( !(type.color || type.number) ){ return false; }\n\n var valueMin = this.parse( name, mapData[4] ); // parse to validate\n if( !valueMin || valueMin.mapped ){ return false; } // can't be invalid or mapped\n\n var valueMax = this.parse( name, mapData[5] ); // parse to validate\n if( !valueMax || valueMax.mapped ){ return false; } // can't be invalid or mapped\n\n // check if valueMin and valueMax are the same\n if( valueMin.value === valueMax.value ){\n return false; // can't make much of a mapper without a range\n\n } else if( type.color ){\n var c1 = valueMin.value;\n var c2 = valueMax.value;\n\n var same = c1[0] === c2[0] // red\n && c1[1] === c2[1] // green\n && c1[2] === c2[2] // blue\n && ( // optional alpha\n c1[3] === c2[3] // same alpha outright\n || (\n (c1[3] == null || c1[3] === 1) // full opacity for colour 1?\n &&\n (c2[3] == null || c2[3] === 1) // full opacity for colour 2?\n )\n )\n ;\n\n if( same ){ return false; } // can't make a mapper without a range\n }\n\n return {\n name: name,\n value: mapData,\n strValue: '' + value,\n mapped: mapped,\n field: mapData[1],\n fieldMin: parseFloat( mapData[2] ), // min & max are numeric\n fieldMax: parseFloat( mapData[3] ),\n valueMin: valueMin.value,\n valueMax: valueMax.value,\n bypass: propIsBypass\n };\n }\n\n if( type.multiple && propIsFlat !== 'multiple' ){\n var vals;\n\n if( valueIsString ){\n vals = value.split(/\\s+/);\n } else if( is.array(value) ){\n vals = value;\n } else {\n vals = [ value ];\n }\n\n if( type.evenMultiple && vals.length % 2 !== 0 ){ return null; }\n\n var valArr = vals.map(function( v ){\n var p = self.parse( name, v, propIsBypass, 'multiple' );\n\n if( p.pfValue != null ){\n return p.pfValue;\n } else {\n return p.value;\n }\n });\n\n return {\n name: name,\n value: valArr,\n pfValue: valArr,\n strValue: valArr.join(' '),\n bypass: propIsBypass,\n units: type.number && !type.unitless ? type.implicitUnits || 'px' : undefined\n };\n }\n\n // several types also allow enums\n var checkEnums = function(){\n for( var i = 0; i < type.enums.length; i++ ){\n var en = type.enums[i];\n\n if( en === value ){\n return {\n name: name,\n value: value,\n strValue: '' + value,\n bypass: propIsBypass\n };\n }\n }\n\n return null;\n };\n\n // check the type and return the appropriate object\n if( type.number ){\n var units;\n var implicitUnits = 'px'; // not set => px\n\n if( type.units ){ // use specified units if set\n units = type.units;\n }\n\n if( type.implicitUnits ){\n implicitUnits = type.implicitUnits;\n }\n\n if( !type.unitless ){\n if( valueIsString ){\n var unitsRegex = 'px|em' + (type.allowPercent ? '|\\\\%' : '');\n if( units ){ unitsRegex = units; } // only allow explicit units if so set\n var match = value.match( '^(' + util.regex.number + ')(' + unitsRegex + ')?' + '$' );\n\n if( match ){\n value = match[1];\n units = match[2] || implicitUnits;\n }\n\n } else if( !units || type.implicitUnits ) {\n units = implicitUnits; // implicitly px if unspecified\n }\n }\n\n value = parseFloat( value );\n\n // if not a number and enums not allowed, then the value is invalid\n if( isNaN(value) && type.enums === undefined ){\n return null;\n }\n\n // check if this number type also accepts special keywords in place of numbers\n // (i.e. `left`, `auto`, etc)\n if( isNaN(value) && type.enums !== undefined ){\n value = passedValue;\n\n return checkEnums();\n }\n\n // check if value must be an integer\n if( type.integer && !is.integer(value) ){\n return null;\n }\n\n // check value is within range\n if( (type.min !== undefined && value < type.min)\n || (type.max !== undefined && value > type.max)\n ){\n return null;\n }\n\n var ret = {\n name: name,\n value: value,\n strValue: '' + value + (units ? units : ''),\n units: units,\n bypass: propIsBypass\n };\n\n // normalise value in pixels\n if( type.unitless || (units !== 'px' && units !== 'em') ){\n ret.pfValue = value;\n } else {\n ret.pfValue = ( units === 'px' || !units ? (value) : (this.getEmSizeInPixels() * value) );\n }\n\n // normalise value in ms\n if( units === 'ms' || units === 's' ){\n ret.pfValue = units === 'ms' ? value : 1000 * value;\n }\n\n // normalise value in rad\n if( units === 'deg' || units === 'rad' ){\n ret.pfValue = units === 'rad' ? value : value * Math.PI/180;\n }\n\n return ret;\n\n } else if( type.propList ) {\n\n var props = [];\n var propsStr = '' + value;\n\n if( propsStr === 'none' ){\n // leave empty\n\n } else { // go over each prop\n\n var propsSplit = propsStr.split(',');\n for( var i = 0; i < propsSplit.length; i++ ){\n var propName = propsSplit[i].trim();\n\n if( self.properties[propName] ){\n props.push( propName );\n }\n }\n\n if( props.length === 0 ){ return null; }\n }\n\n return {\n name: name,\n value: props,\n strValue: props.length === 0 ? 'none' : props.join(', '),\n bypass: propIsBypass\n };\n\n } else if( type.color ){\n var tuple = util.color2tuple( value );\n\n if( !tuple ){ return null; }\n\n return {\n name: name,\n value: tuple,\n strValue: '' + value,\n bypass: propIsBypass,\n roundValue: true\n };\n\n } else if( type.regex || type.regexes ){\n\n // first check enums\n if( type.enums ){\n var enumProp = checkEnums();\n\n if( enumProp ){ return enumProp; }\n }\n\n var regexes = type.regexes ? type.regexes : [ type.regex ];\n\n for( var i = 0; i < regexes.length; i++ ){\n var regex = new RegExp( regexes[i] ); // make a regex from the type string\n var m = regex.exec( value );\n\n if( m ){ // regex matches\n return {\n name: name,\n value: m,\n strValue: '' + value,\n bypass: propIsBypass\n };\n\n }\n }\n\n return null; // didn't match any\n\n } else if( type.string ){\n // just return\n return {\n name: name,\n value: value,\n strValue: '' + value,\n bypass: propIsBypass\n };\n\n } else if( type.enums ){ // check enums last because it's a combo type in others\n return checkEnums();\n\n } else {\n return null; // not a type we can handle\n }\n\n};\n\nmodule.exports = styfn;\n","'use strict';\n\nvar util = require('../util');\n\nvar styfn = {};\n\n(function(){\n var number = util.regex.number;\n var rgba = util.regex.rgbaNoBackRefs;\n var hsla = util.regex.hslaNoBackRefs;\n var hex3 = util.regex.hex3;\n var hex6 = util.regex.hex6;\n var data = function( prefix ){ return '^' + prefix + '\\\\s*\\\\(\\\\s*([\\\\w\\\\.]+)\\\\s*\\\\)$'; };\n var mapData = function( prefix ){\n var mapArg = number + '|\\\\w+|' + rgba + '|' + hsla + '|' + hex3 + '|' + hex6;\n return '^' + prefix + '\\\\s*\\\\(([\\\\w\\\\.]+)\\\\s*\\\\,\\\\s*(' + number + ')\\\\s*\\\\,\\\\s*(' + number + ')\\\\s*,\\\\s*(' + mapArg + ')\\\\s*\\\\,\\\\s*(' + mapArg + ')\\\\)$';\n };\n\n // each visual style property has a type and needs to be validated according to it\n styfn.types = {\n time: { number: true, min: 0, units: 's|ms', implicitUnits: 'ms' },\n percent: { number: true, min: 0, max: 100, units: '%', implicitUnits: '%' },\n zeroOneNumber: { number: true, min: 0, max: 1, unitless: true },\n nOneOneNumber: { number: true, min: -1, max: 1, unitless: true },\n nonNegativeInt: { number: true, min: 0, integer: true, unitless: true },\n position: { enums: ['parent', 'origin'] },\n nodeSize: { number: true, min: 0, enums: ['auto', 'label'] },\n number: { number: true, unitless: true },\n numbers: { number: true, unitless: true, multiple: true },\n size: { number: true, min: 0 },\n bidirectionalSize: { number: true }, // allows negative\n bidirectionalSizes: { number: true, multiple: true }, // allows negative\n bgSize: { number: true, min: 0, allowPercent: true },\n bgWH: { number: true, min: 0, allowPercent: true, enums: ['auto'] },\n bgPos: { number: true, allowPercent: true },\n bgRepeat: { enums: ['repeat', 'repeat-x', 'repeat-y', 'no-repeat'] },\n bgFit: { enums: ['none', 'contain', 'cover'] },\n bgClip: { enums: ['none', 'node'] },\n color: { color: true },\n bool: { enums: ['yes', 'no'] },\n lineStyle: { enums: ['solid', 'dotted', 'dashed'] },\n borderStyle: { enums: ['solid', 'dotted', 'dashed', 'double'] },\n curveStyle: { enums: ['bezier', 'unbundled-bezier', 'haystack', 'segments'] },\n fontFamily: { regex: '^([\\\\w- \\\\\"]+(?:\\\\s*,\\\\s*[\\\\w- \\\\\"]+)*)$' },\n fontVariant: { enums: ['small-caps', 'normal'] },\n fontStyle: { enums: ['italic', 'normal', 'oblique'] },\n fontWeight: { enums: ['normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '800', '900', 100, 200, 300, 400, 500, 600, 700, 800, 900] },\n textDecoration: { enums: ['none', 'underline', 'overline', 'line-through'] },\n textTransform: { enums: ['none', 'uppercase', 'lowercase'] },\n textWrap: { enums: ['none', 'wrap'] },\n textBackgroundShape: { enums: ['rectangle', 'roundrectangle']},\n nodeShape: { enums: ['rectangle', 'roundrectangle', 'ellipse', 'triangle', 'square', 'pentagon', 'hexagon', 'heptagon', 'octagon', 'star', 'diamond', 'vee', 'rhomboid', 'polygon'] },\n compoundIncludeLabels: { enums: ['include', 'exclude'] },\n arrowShape: { enums: ['tee', 'triangle', 'triangle-tee', 'triangle-backcurve', 'half-triangle-overshot', 'vee', 'square', 'circle', 'diamond', 'none'] },\n arrowFill: { enums: ['filled', 'hollow'] },\n display: { enums: ['element', 'none'] },\n visibility: { enums: ['hidden', 'visible'] },\n valign: { enums: ['top', 'center', 'bottom'] },\n halign: { enums: ['left', 'center', 'right'] },\n text: { string: true },\n data: { mapping: true, regex: data('data') },\n layoutData: { mapping: true, regex: data('layoutData') },\n scratch: { mapping: true, regex: data('scratch') },\n mapData: { mapping: true, regex: mapData('mapData') },\n mapLayoutData: { mapping: true, regex: mapData('mapLayoutData') },\n mapScratch: { mapping: true, regex: mapData('mapScratch') },\n fn: { mapping: true, fn: true },\n url: { regex: '^url\\\\s*\\\\(\\\\s*([^\\\\s]+)\\\\s*\\\\s*\\\\)|none|(.+)$' },\n propList: { propList: true },\n angle: { number: true, units: 'deg|rad', implicitUnits: 'rad' },\n textRotation: { enums: ['none', 'autorotate'] },\n polygonPointList: { number: true, multiple: true, evenMultiple: true, min: -1, max: 1, unitless: true },\n easing: {\n regexes: [\n '^(spring)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*,\\\\s*(' + number + ')\\\\s*\\\\)$',\n '^(cubic-bezier)\\\\s*\\\\(\\\\s*(' + number + ')\\\\s*,\\\\s*(' + number + ')\\\\s*,\\\\s*(' + number + ')\\\\s*,\\\\s*(' + number + ')\\\\s*\\\\)$'\n ],\n enums: [\n 'linear',\n 'ease', 'ease-in', 'ease-out', 'ease-in-out',\n 'ease-in-sine', 'ease-out-sine', 'ease-in-out-sine',\n 'ease-in-quad', 'ease-out-quad', 'ease-in-out-quad',\n 'ease-in-cubic', 'ease-out-cubic', 'ease-in-out-cubic',\n 'ease-in-quart', 'ease-out-quart', 'ease-in-out-quart',\n 'ease-in-quint', 'ease-out-quint', 'ease-in-out-quint',\n 'ease-in-expo', 'ease-out-expo', 'ease-in-out-expo',\n 'ease-in-circ', 'ease-out-circ', 'ease-in-out-circ'\n ]\n }\n };\n\n // define visual style properties\n var t = styfn.types;\n var props = styfn.properties = [\n // labels\n { name: 'text-valign', type: t.valign },\n { name: 'text-halign', type: t.halign },\n { name: 'color', type: t.color },\n { name: 'label', type: t.text },\n { name: 'text-outline-color', type: t.color },\n { name: 'text-outline-width', type: t.size },\n { name: 'text-outline-opacity', type: t.zeroOneNumber },\n { name: 'text-opacity', type: t.zeroOneNumber },\n { name: 'text-background-color', type: t.color },\n { name: 'text-background-opacity', type: t.zeroOneNumber },\n { name: 'text-border-opacity', type: t.zeroOneNumber },\n { name: 'text-border-color', type: t.color },\n { name: 'text-border-width', type: t.size },\n { name: 'text-border-style', type: t.borderStyle },\n { name: 'text-background-shape', type: t.textBackgroundShape},\n // { name: 'text-decoration', type: t.textDecoration }, // not supported in canvas\n { name: 'text-transform', type: t.textTransform },\n { name: 'text-wrap', type: t.textWrap },\n { name: 'text-max-width', type: t.size },\n { name: 'text-events', type: t.bool },\n\n // { name: 'text-rotation', type: t.angle }, // TODO disabled b/c rotation breaks bounding boxes\n { name: 'font-family', type: t.fontFamily },\n { name: 'font-style', type: t.fontStyle },\n // { name: 'font-variant', type: t.fontVariant }, // not useful\n { name: 'font-weight', type: t.fontWeight },\n { name: 'font-size', type: t.size },\n { name: 'min-zoomed-font-size', type: t.size },\n { name: 'edge-text-rotation', type: t.textRotation },\n\n // behaviour\n { name: 'events', type: t.bool },\n\n // visibility\n { name: 'display', type: t.display },\n { name: 'visibility', type: t.visibility },\n { name: 'opacity', type: t.zeroOneNumber },\n { name: 'z-index', type: t.nonNegativeInt },\n\n // overlays\n { name: 'overlay-padding', type: t.size },\n { name: 'overlay-color', type: t.color },\n { name: 'overlay-opacity', type: t.zeroOneNumber },\n\n // shadows\n { name: 'shadow-blur', type: t.size },\n { name: 'shadow-color', type: t.color },\n { name: 'shadow-opacity', type: t.zeroOneNumber },\n { name: 'shadow-offset-x', type: t.bidirectionalSize },\n { name: 'shadow-offset-y', type: t.bidirectionalSize },\n\n // label shadows\n { name: 'text-shadow-blur', type: t.size },\n { name: 'text-shadow-color', type: t.color },\n { name: 'text-shadow-opacity', type: t.zeroOneNumber },\n { name: 'text-shadow-offset-x', type: t.bidirectionalSize },\n { name: 'text-shadow-offset-y', type: t.bidirectionalSize },\n\n // transition anis\n { name: 'transition-property', type: t.propList },\n { name: 'transition-duration', type: t.time },\n { name: 'transition-delay', type: t.time },\n { name: 'transition-timing-function', type: t.easing },\n\n // node body\n { name: 'height', type: t.nodeSize },\n { name: 'width', type: t.nodeSize },\n { name: 'shape', type: t.nodeShape },\n { name: 'shape-polygon-points', type: t.polygonPointList },\n { name: 'background-color', type: t.color },\n { name: 'background-opacity', type: t.zeroOneNumber },\n { name: 'background-blacken', type: t.nOneOneNumber },\n { name: 'padding-left', type: t.size },\n { name: 'padding-right', type: t.size },\n { name: 'padding-top', type: t.size },\n { name: 'padding-bottom', type: t.size },\n\n // node border\n { name: 'border-color', type: t.color },\n { name: 'border-opacity', type: t.zeroOneNumber },\n { name: 'border-width', type: t.size },\n { name: 'border-style', type: t.borderStyle },\n\n // node background images\n { name: 'background-image', type: t.url },\n { name: 'background-image-opacity', type: t.zeroOneNumber },\n { name: 'background-position-x', type: t.bgPos },\n { name: 'background-position-y', type: t.bgPos },\n { name: 'background-repeat', type: t.bgRepeat },\n { name: 'background-fit', type: t.bgFit },\n { name: 'background-clip', type: t.bgClip },\n { name: 'background-width', type: t.bgWH },\n { name: 'background-height', type: t.bgWH },\n\n // compound props\n { name: 'position', type: t.position },\n { name: 'compound-sizing-wrt-labels', type: t.compoundIncludeLabels },\n\n // edge line\n { name: 'line-style', type: t.lineStyle },\n { name: 'line-color', type: t.color },\n { name: 'curve-style', type: t.curveStyle },\n { name: 'haystack-radius', type: t.zeroOneNumber },\n { name: 'control-point-step-size', type: t.size },\n { name: 'control-point-distances', type: t.bidirectionalSizes },\n { name: 'control-point-weights', type: t.numbers },\n { name: 'segment-distances', type: t.bidirectionalSizes },\n { name: 'segment-weights', type: t.numbers },\n\n // these are just for the core\n { name: 'selection-box-color', type: t.color },\n { name: 'selection-box-opacity', type: t.zeroOneNumber },\n { name: 'selection-box-border-color', type: t.color },\n { name: 'selection-box-border-width', type: t.size },\n { name: 'active-bg-color', type: t.color },\n { name: 'active-bg-opacity', type: t.zeroOneNumber },\n { name: 'active-bg-size', type: t.size },\n { name: 'outside-texture-bg-color', type: t.color },\n { name: 'outside-texture-bg-opacity', type: t.zeroOneNumber }\n ];\n\n // define aliases\n var aliases = styfn.aliases = [\n { name: 'content', pointsTo: 'label' },\n { name: 'control-point-distance', pointsTo: 'control-point-distances' },\n { name: 'control-point-weight', pointsTo: 'control-point-weights' }\n ];\n\n // pie backgrounds for nodes\n styfn.pieBackgroundN = 16; // because the pie properties are numbered, give access to a constant N (for renderer use)\n props.push({ name: 'pie-size', type: t.bgSize });\n for( var i = 1; i <= styfn.pieBackgroundN; i++ ){\n props.push({ name: 'pie-'+i+'-background-color', type: t.color });\n props.push({ name: 'pie-'+i+'-background-size', type: t.percent });\n props.push({ name: 'pie-'+i+'-background-opacity', type: t.zeroOneNumber });\n }\n\n // edge arrows\n var arrowPrefixes = styfn.arrowPrefixes = ['source', 'mid-source', 'target', 'mid-target'];\n [\n { name: 'arrow-shape', type: t.arrowShape },\n { name: 'arrow-color', type: t.color },\n { name: 'arrow-fill', type: t.arrowFill }\n ].forEach(function( prop ){\n arrowPrefixes.forEach(function( prefix ){\n var name = prefix + '-' + prop.name;\n var type = prop.type;\n\n props.push({ name: name, type: type });\n });\n }, {});\n\n // list of property names\n styfn.propertyNames = props.map(function(p){ return p.name; });\n\n // allow access of properties by name ( e.g. style.properties.height )\n for( var i = 0; i < props.length; i++ ){\n var prop = props[i];\n\n props[ prop.name ] = prop; // allow lookup by name\n }\n\n // map aliases\n for( var i = 0; i < aliases.length; i++ ){\n var alias = aliases[i];\n var pointsToProp = props[ alias.pointsTo ];\n var aliasProp = {\n name: alias.name,\n alias: true,\n pointsTo: pointsToProp\n };\n\n // add alias prop for parsing\n props.push( aliasProp );\n\n props[ alias.name ] = aliasProp; // allow lookup by name\n }\n})();\n\n// adds the default stylesheet to the current style\nstyfn.addDefaultStylesheet = function(){\n // fill the style with the default stylesheet\n this\n .selector('node, edge') // common properties\n .css( util.extend( {\n 'events': 'yes',\n 'text-events': 'no',\n 'text-valign': 'top',\n 'text-halign': 'center',\n 'color': '#000',\n 'text-outline-color': '#000',\n 'text-outline-width': 0,\n 'text-outline-opacity': 1,\n 'text-opacity': 1,\n 'text-decoration': 'none',\n 'text-transform': 'none',\n 'text-wrap': 'none',\n 'text-max-width': 9999,\n 'text-background-color': '#000',\n 'text-background-opacity': 0,\n 'text-border-opacity': 0,\n 'text-border-width': 0,\n 'text-border-style': 'solid',\n 'text-border-color':'#000',\n 'text-background-shape':'rectangle',\n 'font-family': 'Helvetica Neue, Helvetica, sans-serif',\n 'font-style': 'normal',\n // 'font-variant': fontVariant,\n 'font-weight': 'normal',\n 'font-size': 16,\n 'min-zoomed-font-size': 0,\n 'edge-text-rotation': 'none',\n 'visibility': 'visible',\n 'display': 'element',\n 'opacity': 1,\n 'z-index': 0,\n 'label': '',\n 'overlay-opacity': 0,\n 'overlay-color': '#000',\n 'overlay-padding': 10,\n 'shadow-opacity': 0,\n 'shadow-color': '#000',\n 'shadow-blur': 10,\n 'shadow-offset-x': 0,\n 'shadow-offset-y': 0,\n 'text-shadow-opacity': 0,\n 'text-shadow-color': '#000',\n 'text-shadow-blur': 5,\n 'text-shadow-offset-x': 0,\n 'text-shadow-offset-y': 0,\n 'transition-property': 'none',\n 'transition-duration': 0,\n 'transition-delay': 0,\n 'transition-timing-function': 'linear',\n\n // node props\n 'background-blacken': 0,\n 'background-color': '#888',\n 'background-opacity': 1,\n 'background-image': 'none',\n 'background-image-opacity': 1,\n 'background-position-x': '50%',\n 'background-position-y': '50%',\n 'background-repeat': 'no-repeat',\n 'background-fit': 'none',\n 'background-clip': 'node',\n 'background-width': 'auto',\n 'background-height': 'auto',\n 'border-color': '#000',\n 'border-opacity': 1,\n 'border-width': 0,\n 'border-style': 'solid',\n 'height': 30,\n 'width': 30,\n 'shape': 'ellipse',\n 'shape-polygon-points': '-1, -1, 1, -1, 1, 1, -1, 1',\n\n // compound props\n 'padding-top': 0,\n 'padding-bottom': 0,\n 'padding-left': 0,\n 'padding-right': 0,\n 'position': 'origin',\n 'compound-sizing-wrt-labels': 'include'\n }, {\n // node pie bg\n 'pie-size': '100%'\n }, [\n { name: 'pie-{{i}}-background-color', value: 'black' },\n { name: 'pie-{{i}}-background-size', value: '0%' },\n { name: 'pie-{{i}}-background-opacity', value: 1 }\n ].reduce(function( css, prop ){\n for( var i = 1; i <= styfn.pieBackgroundN; i++ ){\n var name = prop.name.replace('{{i}}', i);\n var val = prop.value;\n\n css[ name ] = val;\n }\n\n return css;\n }, {}), {\n // edge props\n 'line-style': 'solid',\n 'line-color': '#ddd',\n 'control-point-step-size': 40,\n 'control-point-weights': 0.5,\n 'segment-weights': 0.5,\n 'segment-distances': 20,\n 'curve-style': 'bezier',\n 'haystack-radius': 0.8\n }, [\n { name: 'arrow-shape', value: 'none' },\n { name: 'arrow-color', value: '#ddd' },\n { name: 'arrow-fill', value: 'filled' }\n ].reduce(function( css, prop ){\n styfn.arrowPrefixes.forEach(function( prefix ){\n var name = prefix + '-' + prop.name;\n var val = prop.value;\n\n css[ name ] = val;\n });\n\n return css;\n }, {}) ) )\n .selector('$node > node') // compound (parent) node properties\n .css({\n 'width': 'auto',\n 'height': 'auto',\n 'shape': 'rectangle',\n 'padding-top': 10,\n 'padding-right': 10,\n 'padding-left': 10,\n 'padding-bottom': 10\n })\n .selector('edge') // just edge properties\n .css({\n 'width': 1\n })\n .selector(':active')\n .css({\n 'overlay-color': 'black',\n 'overlay-padding': 10,\n 'overlay-opacity': 0.25\n })\n .selector('core') // just core properties\n .css({\n 'selection-box-color': '#ddd',\n 'selection-box-opacity': 0.65,\n 'selection-box-border-color': '#aaa',\n 'selection-box-border-width': 1,\n 'active-bg-color': 'black',\n 'active-bg-opacity': 0.15,\n 'active-bg-size': 30,\n 'outside-texture-bg-color': '#000',\n 'outside-texture-bg-opacity': 0.125\n })\n ;\n\n this.defaultLength = this.length;\n};\n\nmodule.exports = styfn;\n","'use strict';\n\nvar util = require('../util');\nvar Selector = require('../selector');\n\nvar styfn = {};\n\nstyfn.applyFromString = function( string ){\n var self = this;\n var style = this;\n var remaining = '' + string;\n var selAndBlockStr;\n var blockRem;\n var propAndValStr;\n\n // remove comments from the style string\n remaining = remaining.replace(/[/][*](\\s|.)+?[*][/]/g, '');\n\n function removeSelAndBlockFromRemaining(){\n // remove the parsed selector and block from the remaining text to parse\n if( remaining.length > selAndBlockStr.length ){\n remaining = remaining.substr( selAndBlockStr.length );\n } else {\n remaining = '';\n }\n }\n\n function removePropAndValFromRem(){\n // remove the parsed property and value from the remaining block text to parse\n if( blockRem.length > propAndValStr.length ){\n blockRem = blockRem.substr( propAndValStr.length );\n } else {\n blockRem = '';\n }\n }\n\n while(true){\n var nothingLeftToParse = remaining.match(/^\\s*$/);\n if( nothingLeftToParse ){ break; }\n\n var selAndBlock = remaining.match(/^\\s*((?:.|\\s)+?)\\s*\\{((?:.|\\s)+?)\\}/);\n\n if( !selAndBlock ){\n util.error('Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: ' + remaining);\n break;\n }\n\n selAndBlockStr = selAndBlock[0];\n\n // parse the selector\n var selectorStr = selAndBlock[1];\n if( selectorStr !== 'core' ){\n var selector = new Selector( selectorStr );\n if( selector._private.invalid ){\n util.error('Skipping parsing of block: Invalid selector found in string stylesheet: ' + selectorStr);\n\n // skip this selector and block\n removeSelAndBlockFromRemaining();\n continue;\n }\n }\n\n // parse the block of properties and values\n var blockStr = selAndBlock[2];\n var invalidBlock = false;\n blockRem = blockStr;\n var props = [];\n\n while(true){\n var nothingLeftToParse = blockRem.match(/^\\s*$/);\n if( nothingLeftToParse ){ break; }\n\n var propAndVal = blockRem.match(/^\\s*(.+?)\\s*:\\s*(.+?)\\s*;/);\n\n if( !propAndVal ){\n util.error('Skipping parsing of block: Invalid formatting of style property and value definitions found in:' + blockStr);\n invalidBlock = true;\n break;\n }\n\n propAndValStr = propAndVal[0];\n var propStr = propAndVal[1];\n var valStr = propAndVal[2];\n\n var prop = self.properties[ propStr ];\n if( !prop ){\n util.error('Skipping property: Invalid property name in: ' + propAndValStr);\n\n // skip this property in the block\n removePropAndValFromRem();\n continue;\n }\n\n var parsedProp = style.parse( propStr, valStr );\n\n if( !parsedProp ){\n util.error('Skipping property: Invalid property definition in: ' + propAndValStr);\n\n // skip this property in the block\n removePropAndValFromRem();\n continue;\n }\n\n props.push({\n name: propStr,\n val: valStr\n });\n removePropAndValFromRem();\n }\n\n if( invalidBlock ){\n removeSelAndBlockFromRemaining();\n break;\n }\n\n // put the parsed block in the style\n style.selector( selectorStr );\n for( var i = 0; i < props.length; i++ ){\n var prop = props[i];\n style.css( prop.name, prop.val );\n }\n\n removeSelAndBlockFromRemaining();\n }\n\n return style;\n};\n\nstyfn.fromString = function( string ){\n var style = this;\n\n style.resetToDefault();\n style.applyFromString( string );\n\n return style;\n};\n\nmodule.exports = styfn;\n","'use strict';\n\nvar is = require('./is');\nvar util = require('./util');\nvar Style = require('./style');\n\n// a dummy stylesheet object that doesn't need a reference to the core\n// (useful for init)\nvar Stylesheet = function(){\n if( !(this instanceof Stylesheet) ){\n return new Stylesheet();\n }\n\n this.length = 0;\n};\n\nvar sheetfn = Stylesheet.prototype;\n\nsheetfn.instanceString = function(){\n return 'stylesheet';\n};\n\n// just store the selector to be parsed later\nsheetfn.selector = function( selector ){\n var i = this.length++;\n\n this[i] = {\n selector: selector,\n properties: []\n };\n\n return this; // chaining\n};\n\n// just store the property to be parsed later\nsheetfn.css = function( name, value ){\n var i = this.length - 1;\n\n if( is.string(name) ){\n this[i].properties.push({\n name: name,\n value: value\n });\n } else if( is.plainObject(name) ){\n var map = name;\n\n for( var j = 0; j < Style.properties.length; j++ ){\n var prop = Style.properties[j];\n var mapVal = map[ prop.name ];\n\n if( mapVal === undefined ){ // also try camel case name\n mapVal = map[ util.dash2camel(prop.name) ];\n }\n\n if( mapVal !== undefined ){\n var name = prop.name;\n var value = mapVal;\n\n this[i].properties.push({\n name: name,\n value: value\n });\n }\n }\n }\n\n return this; // chaining\n};\n\nsheetfn.style = sheetfn.css;\n\n// generate a real style object from the dummy stylesheet\nsheetfn.generateStyle = function( cy ){\n var style = new Style(cy);\n\n for( var i = 0; i < this.length; i++ ){\n var context = this[i];\n var selector = context.selector;\n var props = context.properties;\n\n style.selector(selector); // apply selector\n\n for( var j = 0; j < props.length; j++ ){\n var prop = props[j];\n\n style.css( prop.name, prop.value ); // apply property\n }\n }\n\n return style;\n};\n\nmodule.exports = Stylesheet;\n","/*! Weaver licensed under MIT (https://tldrlegal.com/license/mit-license), copyright Max Franz */\n\n// cross-env thread/worker\n// NB : uses (heavyweight) processes on nodejs so best not to create too many threads\n\n'use strict';\n\nvar window = require('./window');\nvar util = require('./util');\nvar Promise = require('./promise');\nvar Event = require('./event');\nvar define = require('./define');\nvar is = require('./is');\n\nvar Thread = function( opts ){\n if( !(this instanceof Thread) ){\n return new Thread( opts );\n }\n\n var _p = this._private = {\n requires: [],\n files: [],\n queue: null,\n pass: [],\n disabled: false\n };\n\n if( is.plainObject(opts) ){\n if( opts.disabled != null ){\n _p.disabled = !!opts.disabled;\n }\n }\n\n};\n\nvar thdfn = Thread.prototype; // short alias\n\nvar stringifyFieldVal = function( val ){\n var valStr = is.fn( val ) ? val.toString() : \"JSON.parse('\" + JSON.stringify(val) + \"')\";\n\n return valStr;\n};\n\n// allows for requires with prototypes and subobjs etc\nvar fnAsRequire = function( fn ){\n var req;\n var fnName;\n\n if( is.object(fn) && fn.fn ){ // manual fn\n req = fnAs( fn.fn, fn.name );\n fnName = fn.name;\n fn = fn.fn;\n } else if( is.fn(fn) ){ // auto fn\n req = fn.toString();\n fnName = fn.name;\n } else if( is.string(fn) ){ // stringified fn\n req = fn;\n } else if( is.object(fn) ){ // plain object\n if( fn.proto ){\n req = '';\n } else {\n req = fn.name + ' = {};';\n }\n\n fnName = fn.name;\n fn = fn.obj;\n }\n\n req += '\\n';\n\n var protoreq = function( val, subname ){\n if( val.prototype ){\n var protoNonempty = false;\n for( var prop in val.prototype ){ protoNonempty = true; break; } // jshint ignore:line\n\n if( protoNonempty ){\n req += fnAsRequire( {\n name: subname,\n obj: val,\n proto: true\n }, val );\n }\n }\n };\n\n // pull in prototype\n if( fn.prototype && fnName != null ){\n\n for( var name in fn.prototype ){\n var protoStr = '';\n\n var val = fn.prototype[ name ];\n var valStr = stringifyFieldVal( val );\n var subname = fnName + '.prototype.' + name;\n\n protoStr += subname + ' = ' + valStr + ';\\n';\n\n if( protoStr ){\n req += protoStr;\n }\n\n protoreq( val, subname ); // subobject with prototype\n }\n\n }\n\n // pull in properties for obj/fns\n if( !is.string(fn) ){ for( var name in fn ){\n var propsStr = '';\n\n if( fn.hasOwnProperty(name) ){\n var val = fn[ name ];\n var valStr = stringifyFieldVal( val );\n var subname = fnName + '[\"' + name + '\"]';\n\n propsStr += subname + ' = ' + valStr + ';\\n';\n }\n\n if( propsStr ){\n req += propsStr;\n }\n\n protoreq( val, subname ); // subobject with prototype\n } }\n\n return req;\n};\n\nvar isPathStr = function( str ){\n return is.string(str) && str.match(/\\.js$/);\n};\n\nutil.extend(thdfn, {\n\n instanceString: function(){ return 'thread'; },\n\n require: function( fn, as ){\n var requires = this._private.requires;\n\n if( isPathStr(fn) ){\n this._private.files.push( fn );\n\n return this;\n }\n\n if( as ){\n if( is.fn(fn) ){\n fn = { name: as, fn: fn };\n } else {\n fn = { name: as, obj: fn };\n }\n } else {\n if( is.fn(fn) ){\n if( !fn.name ){\n throw 'The function name could not be automatically determined. Use thread.require( someFunction, \"someFunction\" )';\n }\n\n fn = { name: fn.name, fn: fn };\n }\n }\n\n requires.push( fn );\n\n return this; // chaining\n },\n\n pass: function( data ){\n this._private.pass.push( data );\n\n return this; // chaining\n },\n\n run: function( fn, pass ){ // fn used like main()\n var self = this;\n var _p = this._private;\n pass = pass || _p.pass.shift();\n\n if( _p.stopped ){\n throw 'Attempted to run a stopped thread! Start a new thread or do not stop the existing thread and reuse it.';\n }\n\n if( _p.running ){\n return ( _p.queue = _p.queue.then(function(){ // inductive step\n return self.run( fn, pass );\n }) );\n }\n\n var useWW = window != null && !_p.disabled;\n var useNode = !window && typeof module !== 'undefined' && !_p.disabled;\n\n self.trigger('run');\n\n var runP = new Promise(function( resolve, reject ){\n\n _p.running = true;\n\n var threadTechAlreadyExists = _p.ran;\n\n var fnImplStr = is.string( fn ) ? fn : fn.toString();\n\n // worker code to exec\n var fnStr = '\\n' + ( _p.requires.map(function( r ){\n return fnAsRequire( r );\n }) ).concat( _p.files.map(function( f ){\n if( useWW ){\n var wwifyFile = function( file ){\n if( file.match(/^\\.\\//) || file.match(/^\\.\\./) ){\n return window.location.origin + window.location.pathname + file;\n } else if( file.match(/^\\//) ){\n return window.location.origin + '/' + file;\n }\n return file;\n };\n\n return 'importScripts(\"' + wwifyFile(f) + '\");';\n } else if( useNode ) {\n return 'eval( require(\"fs\").readFileSync(\"' + f + '\", { encoding: \"utf8\" }) );';\n } else {\n throw 'External file `' + f + '` can not be required without any threading technology.';\n }\n }) ).concat([\n '( function(){',\n 'var ret = (' + fnImplStr + ')(' + JSON.stringify(pass) + ');',\n 'if( ret !== undefined ){ resolve(ret); }', // assume if ran fn returns defined value (incl. null), that we want to resolve to it\n '} )()\\n'\n ]).join('\\n');\n\n // because we've now consumed the requires, empty the list so we don't dupe on next run()\n _p.requires = [];\n _p.files = [];\n\n if( useWW ){\n var fnBlob, fnUrl;\n\n // add normalised thread api functions\n if( !threadTechAlreadyExists ){\n var fnPre = fnStr + '';\n\n fnStr = [\n 'function _ref_(o){ return eval(o); };',\n 'function broadcast(m){ return message(m); };', // alias\n 'function message(m){ postMessage(m); };',\n 'function listen(fn){',\n ' self.addEventListener(\"message\", function(m){ ',\n ' if( typeof m === \"object\" && (m.data.$$eval || m.data === \"$$start\") ){',\n ' } else { ',\n ' fn( m.data );',\n ' }',\n ' });',\n '};',\n 'self.addEventListener(\"message\", function(m){ if( m.data.$$eval ){ eval( m.data.$$eval ); } });',\n 'function resolve(v){ postMessage({ $$resolve: v }); };',\n 'function reject(v){ postMessage({ $$reject: v }); };'\n ].join('\\n');\n\n fnStr += fnPre;\n\n fnBlob = new Blob([ fnStr ], {\n type: 'application/javascript'\n });\n fnUrl = window.URL.createObjectURL( fnBlob );\n }\n // create webworker and let it exec the serialised code\n var ww = _p.webworker = _p.webworker || new Worker( fnUrl );\n\n if( threadTechAlreadyExists ){ // then just exec new run() code\n ww.postMessage({\n $$eval: fnStr\n });\n }\n\n // worker messages => events\n var cb;\n ww.addEventListener('message', cb = function( m ){\n var isObject = is.object(m) && is.object( m.data );\n\n if( isObject && ('$$resolve' in m.data) ){\n ww.removeEventListener('message', cb); // done listening b/c resolve()\n\n resolve( m.data.$$resolve );\n } else if( isObject && ('$$reject' in m.data) ){\n ww.removeEventListener('message', cb); // done listening b/c reject()\n\n reject( m.data.$$reject );\n } else {\n self.trigger( new Event(m, { type: 'message', message: m.data }) );\n }\n }, false);\n\n if( !threadTechAlreadyExists ){\n ww.postMessage('$$start'); // start up the worker\n }\n\n } else if( useNode ){\n // create a new process\n\n if( !_p.child ){\n _p.child = ( require('child_process').fork( require('path').join(__dirname, 'thread-node-fork') ) );\n }\n\n var child = _p.child;\n\n // child process messages => events\n var cb;\n child.on('message', cb = function( m ){\n if( is.object(m) && ('$$resolve' in m) ){\n child.removeListener('message', cb); // done listening b/c resolve()\n\n resolve( m.$$resolve );\n } else if( is.object(m) && ('$$reject' in m) ){\n child.removeListener('message', cb); // done listening b/c reject()\n\n reject( m.$$reject );\n } else {\n self.trigger( new Event({}, { type: 'message', message: m }) );\n }\n });\n\n // ask the child process to eval the worker code\n child.send({\n $$eval: fnStr\n });\n\n } else { // use a fallback mechanism using a timeout\n\n var promiseResolve = resolve;\n var promiseReject = reject;\n\n var timer = _p.timer = _p.timer || {\n\n listeners: [],\n\n exec: function(){\n // as a string so it can't be mangled by minifiers and processors\n fnStr = [\n 'function _ref_(o){ return eval(o); };',\n 'function broadcast(m){ return message(m); };',\n 'function message(m){ self.trigger( new Event({}, { type: \"message\", message: m }) ); };',\n 'function listen(fn){ timer.listeners.push( fn ); };',\n 'function resolve(v){ promiseResolve(v); };',\n 'function reject(v){ promiseReject(v); };'\n ].join('\\n') + fnStr;\n\n // the .run() code\n eval( fnStr ); // jshint ignore:line\n },\n\n message: function( m ){\n var ls = timer.listeners;\n\n for( var i = 0; i < ls.length; i++ ){\n var fn = ls[i];\n\n fn( m );\n }\n }\n\n };\n\n timer.exec();\n }\n\n }).then(function( v ){\n _p.running = false;\n _p.ran = true;\n\n self.trigger('ran');\n\n return v;\n });\n\n if( _p.queue == null ){\n _p.queue = runP; // i.e. first step of inductive promise chain (for queue)\n }\n\n return runP;\n },\n\n // send the thread a message\n message: function( m ){\n var _p = this._private;\n\n if( _p.webworker ){\n _p.webworker.postMessage( m );\n }\n\n if( _p.child ){\n _p.child.send( m );\n }\n\n if( _p.timer ){\n _p.timer.message( m );\n }\n\n return this; // chaining\n },\n\n stop: function(){\n var _p = this._private;\n\n if( _p.webworker ){\n _p.webworker.terminate();\n }\n\n if( _p.child ){\n _p.child.kill();\n }\n\n if( _p.timer ){\n // nothing we can do if we've run a timeout\n }\n\n _p.stopped = true;\n\n return this.trigger('stop'); // chaining\n },\n\n stopped: function(){\n return this._private.stopped;\n }\n\n});\n\n// turns a stringified function into a (re)named function\nvar fnAs = function( fn, name ){\n var fnStr = fn.toString();\n fnStr = fnStr.replace(/function\\s*?\\S*?\\s*?\\(/, 'function ' + name + '(');\n\n return fnStr;\n};\n\nvar defineFnal = function( opts ){\n opts = opts || {};\n\n return function fnalImpl( fn, arg1 ){\n var fnStr = fnAs( fn, '_$_$_' + opts.name );\n\n this.require( fnStr );\n\n return this.run( [\n 'function( data ){',\n ' var origResolve = resolve;',\n ' var res = [];',\n ' ',\n ' resolve = function( val ){',\n ' res.push( val );',\n ' };',\n ' ',\n ' var ret = data.' + opts.name + '( _$_$_' + opts.name + ( arguments.length > 1 ? ', ' + JSON.stringify(arg1) : '' ) + ' );',\n ' ',\n ' resolve = origResolve;',\n ' resolve( res.length > 0 ? res : ret );',\n '}'\n ].join('\\n') );\n };\n};\n\nutil.extend(thdfn, {\n reduce: defineFnal({ name: 'reduce' }),\n\n reduceRight: defineFnal({ name: 'reduceRight' }),\n\n map: defineFnal({ name: 'map' })\n});\n\n// aliases\nvar fn = thdfn;\nfn.promise = fn.run;\nfn.terminate = fn.halt = fn.stop;\nfn.include = fn.require;\n\n// pull in event apis\nutil.extend(thdfn, {\n on: define.on(),\n one: define.on({ unbindSelfOnTrigger: true }),\n off: define.off(),\n trigger: define.trigger()\n});\n\ndefine.eventAliasesOn( thdfn );\n\nmodule.exports = Thread;\n","'use strict';\n\nvar is = require('../is');\n\nmodule.exports = {\n // get [r, g, b] from #abc or #aabbcc\n hex2tuple: function( hex ){\n if( !(hex.length === 4 || hex.length === 7) || hex[0] !== \"#\" ){ return; }\n\n var shortHex = hex.length === 4;\n var r, g, b;\n var base = 16;\n\n if( shortHex ){\n r = parseInt( hex[1] + hex[1], base );\n g = parseInt( hex[2] + hex[2], base );\n b = parseInt( hex[3] + hex[3], base );\n } else {\n r = parseInt( hex[1] + hex[2], base );\n g = parseInt( hex[3] + hex[4], base );\n b = parseInt( hex[5] + hex[6], base );\n }\n\n return [r, g, b];\n },\n\n // get [r, g, b, a] from hsl(0, 0, 0) or hsla(0, 0, 0, 0)\n hsl2tuple: function( hsl ){\n var ret;\n var h, s, l, a, r, g, b;\n function hue2rgb(p, q, t){\n if(t < 0) t += 1;\n if(t > 1) t -= 1;\n if(t < 1/6) return p + (q - p) * 6 * t;\n if(t < 1/2) return q;\n if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;\n return p;\n }\n\n var m = new RegExp(\"^\" + this.regex.hsla + \"$\").exec(hsl);\n if( m ){\n\n // get hue\n h = parseInt( m[1] );\n if( h < 0 ){\n h = ( 360 - (-1*h % 360) ) % 360;\n } else if( h > 360 ){\n h = h % 360;\n }\n h /= 360; // normalise on [0, 1]\n\n s = parseFloat( m[2] );\n if( s < 0 || s > 100 ){ return; } // saturation is [0, 100]\n s = s/100; // normalise on [0, 1]\n\n l = parseFloat( m[3] );\n if( l < 0 || l > 100 ){ return; } // lightness is [0, 100]\n l = l/100; // normalise on [0, 1]\n\n a = m[4];\n if( a !== undefined ){\n a = parseFloat( a );\n\n if( a < 0 || a > 1 ){ return; } // alpha is [0, 1]\n }\n\n // now, convert to rgb\n // code from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript\n if( s === 0 ){\n r = g = b = Math.round(l * 255); // achromatic\n } else {\n var q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n var p = 2 * l - q;\n r = Math.round( 255 * hue2rgb(p, q, h + 1/3) );\n g = Math.round( 255 * hue2rgb(p, q, h) );\n b = Math.round( 255 * hue2rgb(p, q, h - 1/3) );\n }\n\n ret = [r, g, b, a];\n }\n\n return ret;\n },\n\n // get [r, g, b, a] from rgb(0, 0, 0) or rgba(0, 0, 0, 0)\n rgb2tuple: function( rgb ){\n var ret;\n\n var m = new RegExp(\"^\" + this.regex.rgba + \"$\").exec(rgb);\n if( m ){\n ret = [];\n\n var isPct = [];\n for( var i = 1; i <= 3; i++ ){\n var channel = m[i];\n\n if( channel[ channel.length - 1 ] === \"%\" ){\n isPct[i] = true;\n }\n channel = parseFloat( channel );\n\n if( isPct[i] ){\n channel = channel/100 * 255; // normalise to [0, 255]\n }\n\n if( channel < 0 || channel > 255 ){ return; } // invalid channel value\n\n ret.push( Math.floor(channel) );\n }\n\n var atLeastOneIsPct = isPct[1] || isPct[2] || isPct[3];\n var allArePct = isPct[1] && isPct[2] && isPct[3];\n if( atLeastOneIsPct && !allArePct ){ return; } // must all be percent values if one is\n\n var alpha = m[4];\n if( alpha !== undefined ){\n alpha = parseFloat( alpha );\n\n if( alpha < 0 || alpha > 1 ){ return; } // invalid alpha value\n\n ret.push( alpha );\n }\n }\n\n return ret;\n },\n\n colorname2tuple: function( color ){\n return this.colors[ color.toLowerCase() ];\n },\n\n color2tuple: function( color ){\n return ( is.array(color) ? color : null )\n || this.colorname2tuple(color)\n || this.hex2tuple(color)\n || this.rgb2tuple(color)\n || this.hsl2tuple(color);\n },\n\n colors: {\n // special colour names\n transparent: [0, 0, 0, 0], // NB alpha === 0\n\n // regular colours\n aliceblue: [240, 248, 255],\n antiquewhite: [250, 235, 215],\n aqua: [0, 255, 255],\n aquamarine: [127, 255, 212],\n azure: [240, 255, 255],\n beige: [245, 245, 220],\n bisque: [255, 228, 196],\n black: [0, 0, 0],\n blanchedalmond: [255, 235, 205],\n blue: [0, 0, 255],\n blueviolet: [138, 43, 226],\n brown: [165, 42, 42],\n burlywood: [222, 184, 135],\n cadetblue: [95, 158, 160],\n chartreuse: [127, 255, 0],\n chocolate: [210, 105, 30],\n coral: [255, 127, 80],\n cornflowerblue: [100, 149, 237],\n cornsilk: [255, 248, 220],\n crimson: [220, 20, 60],\n cyan: [0, 255, 255],\n darkblue: [0, 0, 139],\n darkcyan: [0, 139, 139],\n darkgoldenrod: [184, 134, 11],\n darkgray: [169, 169, 169],\n darkgreen: [0, 100, 0],\n darkgrey: [169, 169, 169],\n darkkhaki: [189, 183, 107],\n darkmagenta: [139, 0, 139],\n darkolivegreen: [85, 107, 47],\n darkorange: [255, 140, 0],\n darkorchid: [153, 50, 204],\n darkred: [139, 0, 0],\n darksalmon: [233, 150, 122],\n darkseagreen: [143, 188, 143],\n darkslateblue: [72, 61, 139],\n darkslategray: [47, 79, 79],\n darkslategrey: [47, 79, 79],\n darkturquoise: [0, 206, 209],\n darkviolet: [148, 0, 211],\n deeppink: [255, 20, 147],\n deepskyblue: [0, 191, 255],\n dimgray: [105, 105, 105],\n dimgrey: [105, 105, 105],\n dodgerblue: [30, 144, 255],\n firebrick: [178, 34, 34],\n floralwhite: [255, 250, 240],\n forestgreen: [34, 139, 34],\n fuchsia: [255, 0, 255],\n gainsboro: [220, 220, 220],\n ghostwhite: [248, 248, 255],\n gold: [255, 215, 0],\n goldenrod: [218, 165, 32],\n gray: [128, 128, 128],\n grey: [128, 128, 128],\n green: [0, 128, 0],\n greenyellow: [173, 255, 47],\n honeydew: [240, 255, 240],\n hotpink: [255, 105, 180],\n indianred: [205, 92, 92],\n indigo: [75, 0, 130],\n ivory: [255, 255, 240],\n khaki: [240, 230, 140],\n lavender: [230, 230, 250],\n lavenderblush: [255, 240, 245],\n lawngreen: [124, 252, 0],\n lemonchiffon: [255, 250, 205],\n lightblue: [173, 216, 230],\n lightcoral: [240, 128, 128],\n lightcyan: [224, 255, 255],\n lightgoldenrodyellow: [250, 250, 210],\n lightgray: [211, 211, 211],\n lightgreen: [144, 238, 144],\n lightgrey: [211, 211, 211],\n lightpink: [255, 182, 193],\n lightsalmon: [255, 160, 122],\n lightseagreen: [32, 178, 170],\n lightskyblue: [135, 206, 250],\n lightslategray: [119, 136, 153],\n lightslategrey: [119, 136, 153],\n lightsteelblue: [176, 196, 222],\n lightyellow: [255, 255, 224],\n lime: [0, 255, 0],\n limegreen: [50, 205, 50],\n linen: [250, 240, 230],\n magenta: [255, 0, 255],\n maroon: [128, 0, 0],\n mediumaquamarine: [102, 205, 170],\n mediumblue: [0, 0, 205],\n mediumorchid: [186, 85, 211],\n mediumpurple: [147, 112, 219],\n mediumseagreen: [60, 179, 113],\n mediumslateblue: [123, 104, 238],\n mediumspringgreen: [0, 250, 154],\n mediumturquoise: [72, 209, 204],\n mediumvioletred: [199, 21, 133],\n midnightblue: [25, 25, 112],\n mintcream: [245, 255, 250],\n mistyrose: [255, 228, 225],\n moccasin: [255, 228, 181],\n navajowhite: [255, 222, 173],\n navy: [0, 0, 128],\n oldlace: [253, 245, 230],\n olive: [128, 128, 0],\n olivedrab: [107, 142, 35],\n orange: [255, 165, 0],\n orangered: [255, 69, 0],\n orchid: [218, 112, 214],\n palegoldenrod: [238, 232, 170],\n palegreen: [152, 251, 152],\n paleturquoise: [175, 238, 238],\n palevioletred: [219, 112, 147],\n papayawhip: [255, 239, 213],\n peachpuff: [255, 218, 185],\n peru: [205, 133, 63],\n pink: [255, 192, 203],\n plum: [221, 160, 221],\n powderblue: [176, 224, 230],\n purple: [128, 0, 128],\n red: [255, 0, 0],\n rosybrown: [188, 143, 143],\n royalblue: [65, 105, 225],\n saddlebrown: [139, 69, 19],\n salmon: [250, 128, 114],\n sandybrown: [244, 164, 96],\n seagreen: [46, 139, 87],\n seashell: [255, 245, 238],\n sienna: [160, 82, 45],\n silver: [192, 192, 192],\n skyblue: [135, 206, 235],\n slateblue: [106, 90, 205],\n slategray: [112, 128, 144],\n slategrey: [112, 128, 144],\n snow: [255, 250, 250],\n springgreen: [0, 255, 127],\n steelblue: [70, 130, 180],\n tan: [210, 180, 140],\n teal: [0, 128, 128],\n thistle: [216, 191, 216],\n tomato: [255, 99, 71],\n turquoise: [64, 224, 208],\n violet: [238, 130, 238],\n wheat: [245, 222, 179],\n white: [255, 255, 255],\n whitesmoke: [245, 245, 245],\n yellow: [255, 255, 0],\n yellowgreen: [154, 205, 50]\n }\n};\n","'use strict';\n\nvar is = require('../is');\nvar math = require('../math');\n\nvar util = {\n\n falsify: function(){ return false; },\n\n zeroify: function(){ return 0; },\n\n noop: function(){},\n\n /* jshint ignore:start */\n error: function( msg ){\n if( console.error ){\n console.error.apply( console, arguments );\n\n if( console.trace ){ console.trace(); }\n } else {\n console.log.apply( console, arguments );\n\n if( console.trace ){ console.trace(); }\n }\n },\n /* jshint ignore:end */\n\n clone: function( obj ){\n return this.extend( {}, obj );\n },\n\n // gets a shallow copy of the argument\n copy: function( obj ){\n if( obj == null ){\n return obj;\n } if( is.array(obj) ){\n return obj.slice();\n } else if( is.plainObject(obj) ){\n return this.clone( obj );\n } else {\n return obj;\n }\n }\n\n};\n\nutil.makeBoundingBox = math.makeBoundingBox.bind( math );\n\nutil._staticEmptyObject = {};\n\nutil.staticEmptyObject = function(){\n return util._staticEmptyObject;\n};\n\nutil.extend = Object.assign != null ? Object.assign : function( tgt ){\n var args = arguments;\n\n for( var i = 1; i < args.length; i++ ){\n var obj = args[i];\n\n for( var k in obj ){\n tgt[k] = obj[k];\n }\n }\n\n return tgt;\n};\n\n[\n require('./colors'),\n require('./maps'),\n { memoize: require('./memoize') },\n require('./regex'),\n require('./strings'),\n require('./timing')\n].forEach(function( req ){\n util.extend( util, req );\n});\n\nmodule.exports = util;\n","'use strict';\n\nvar is = require('../is');\n\nmodule.exports = {\n // has anything been set in the map\n mapEmpty: function( map ){\n var empty = true;\n\n if( map != null ){\n for(var i in map){ // jshint ignore:line\n empty = false;\n break;\n }\n }\n\n return empty;\n },\n\n // pushes to the array at the end of a map (map may not be built)\n pushMap: function( options ){\n var array = this.getMap(options);\n\n if( array == null ){ // if empty, put initial array\n this.setMap( this.extend({}, options, {\n value: [ options.value ]\n }) );\n } else {\n array.push( options.value );\n }\n },\n\n // sets the value in a map (map may not be built)\n setMap: function( options ){\n var obj = options.map;\n var key;\n var keys = options.keys;\n var l = keys.length;\n\n for(var i = 0; i < l; i++){\n var key = keys[i];\n\n if( is.plainObject( key ) ){\n this.error('Tried to set map with object key');\n }\n\n if( i < keys.length - 1 ){\n\n // extend the map if necessary\n if( obj[key] == null ){\n obj[key] = {};\n }\n\n obj = obj[key];\n } else {\n // set the value\n obj[key] = options.value;\n }\n }\n },\n\n // gets the value in a map even if it's not built in places\n getMap: function( options ){\n var obj = options.map;\n var keys = options.keys;\n var l = keys.length;\n\n for(var i = 0; i < l; i++){\n var key = keys[i];\n\n if( is.plainObject( key ) ){\n this.error('Tried to get map with object key');\n }\n\n obj = obj[key];\n\n if( obj == null ){\n return obj;\n }\n }\n\n return obj;\n },\n\n // deletes the entry in the map\n deleteMap: function( options ){\n var obj = options.map;\n var keys = options.keys;\n var l = keys.length;\n var keepChildren = options.keepChildren;\n\n for(var i = 0; i < l; i++){\n var key = keys[i];\n\n if( is.plainObject( key ) ){\n this.error('Tried to delete map with object key');\n }\n\n var lastKey = i === options.keys.length - 1;\n if( lastKey ){\n\n if( keepChildren ){ // then only delete child fields not in keepChildren\n for( var child in obj ){\n if( !keepChildren[child] ){\n obj[child] = undefined;\n }\n }\n } else {\n obj[key] = undefined;\n }\n\n } else {\n obj = obj[key];\n }\n }\n }\n};\n","'use strict';\n\nmodule.exports = function memoize( fn, keyFn ){\n var self = this;\n var cache = {};\n\n if( !keyFn ){\n keyFn = function(){\n if( arguments.length === 1 ){\n return arguments[0];\n }\n\n var args = [];\n\n for( var i = 0; i < arguments.length; i++ ){\n args.push( arguments[i] );\n }\n\n return args.join('$');\n };\n }\n\n return function memoizedFn(){\n var args = arguments;\n var ret;\n var k = keyFn.apply( self, args );\n\n if( !(ret = cache[k]) ){\n ret = cache[k] = fn.apply( self, args );\n }\n\n return ret;\n };\n};\n","'use strict';\n\nvar number = \"(?:[-+]?(?:(?:\\\\d+|\\\\d*\\\\.\\\\d+)(?:[Ee][+-]?\\\\d+)?))\";\n\nvar rgba = \"rgb[a]?\\\\((\"+ number +\"[%]?)\\\\s*,\\\\s*(\"+ number +\"[%]?)\\\\s*,\\\\s*(\"+ number +\"[%]?)(?:\\\\s*,\\\\s*(\"+ number +\"))?\\\\)\";\nvar rgbaNoBackRefs = \"rgb[a]?\\\\((?:\"+ number +\"[%]?)\\\\s*,\\\\s*(?:\"+ number +\"[%]?)\\\\s*,\\\\s*(?:\"+ number +\"[%]?)(?:\\\\s*,\\\\s*(?:\"+ number +\"))?\\\\)\";\n\nvar hsla = \"hsl[a]?\\\\((\"+ number +\")\\\\s*,\\\\s*(\"+ number +\"[%])\\\\s*,\\\\s*(\"+ number +\"[%])(?:\\\\s*,\\\\s*(\"+ number +\"))?\\\\)\";\nvar hslaNoBackRefs = \"hsl[a]?\\\\((?:\"+ number +\")\\\\s*,\\\\s*(?:\"+ number +\"[%])\\\\s*,\\\\s*(?:\"+ number +\"[%])(?:\\\\s*,\\\\s*(?:\"+ number +\"))?\\\\)\";\n\nvar hex3 = \"\\\\#[0-9a-fA-F]{3}\";\nvar hex6 = \"\\\\#[0-9a-fA-F]{6}\";\n\nmodule.exports = {\n regex: {\n number: number,\n rgba: rgba,\n rgbaNoBackRefs: rgbaNoBackRefs,\n hsla: hsla,\n hslaNoBackRefs: hslaNoBackRefs,\n hex3: hex3,\n hex6: hex6\n }\n};\n","'use strict';\n\nvar memoize = require('./memoize');\nvar is = require('../is');\n\nmodule.exports = {\n\n camel2dash: memoize( function( str ){\n return str.replace(/([A-Z])/g, function( v ){\n return '-' + v.toLowerCase();\n });\n } ),\n\n dash2camel: memoize( function( str ){\n return str.replace(/(-\\w)/g, function( v ){\n return v[1].toUpperCase();\n });\n } ),\n\n capitalize: function(str){\n if( is.emptyString(str) ){\n return str;\n }\n\n return str.charAt(0).toUpperCase() + str.substring(1);\n }\n\n};\n","'use strict';\n\nvar window = require('../window');\nvar is = require('../is');\nvar performance = window ? window.performance : null;\n\nvar util = {};\n\nvar raf = !window ? null : ( window.requestAnimationFrame || window.mozRequestAnimationFrame ||\n window.webkitRequestAnimationFrame || window.msRequestAnimationFrame );\n\nraf = raf || function( fn ){\n if( fn ){\n setTimeout(function(){\n fn( pnow() );\n }, 1000/60);\n }\n};\n\nutil.requestAnimationFrame = function(fn){\n raf( fn );\n};\n\nvar pnow = performance && performance.now ? function(){ return performance.now(); } : function(){ return Date.now(); };\n\nutil.performanceNow = pnow;\n\n// ported lodash throttle function\nutil.throttle = function(func, wait, options) {\n var leading = true,\n trailing = true;\n\n if (options === false) {\n leading = false;\n } else if (is.plainObject(options)) {\n leading = 'leading' in options ? options.leading : leading;\n trailing = 'trailing' in options ? options.trailing : trailing;\n }\n options = options || {};\n options.leading = leading;\n options.maxWait = wait;\n options.trailing = trailing;\n\n return util.debounce(func, wait, options);\n};\n\nutil.now = function(){\n return Date.now();\n};\n\nutil.debounce = function(func, wait, options) { // ported lodash debounce function\n var util = this;\n var args,\n maxTimeoutId,\n result,\n stamp,\n thisArg,\n timeoutId,\n trailingCall,\n lastCalled = 0,\n maxWait = false,\n trailing = true;\n\n if (!is.fn(func)) {\n return;\n }\n wait = Math.max(0, wait) || 0;\n if (options === true) {\n var leading = true;\n trailing = false;\n } else if (is.plainObject(options)) {\n leading = options.leading;\n maxWait = 'maxWait' in options && (Math.max(wait, options.maxWait) || 0);\n trailing = 'trailing' in options ? options.trailing : trailing;\n }\n var delayed = function() {\n var remaining = wait - (util.now() - stamp);\n if (remaining <= 0) {\n if (maxTimeoutId) {\n clearTimeout(maxTimeoutId);\n }\n var isCalled = trailingCall;\n maxTimeoutId = timeoutId = trailingCall = undefined;\n if (isCalled) {\n lastCalled = util.now();\n result = func.apply(thisArg, args);\n if (!timeoutId && !maxTimeoutId) {\n args = thisArg = null;\n }\n }\n } else {\n timeoutId = setTimeout(delayed, remaining);\n }\n };\n\n var maxDelayed = function() {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n maxTimeoutId = timeoutId = trailingCall = undefined;\n if (trailing || (maxWait !== wait)) {\n lastCalled = util.now();\n result = func.apply(thisArg, args);\n if (!timeoutId && !maxTimeoutId) {\n args = thisArg = null;\n }\n }\n };\n\n return function() {\n args = arguments;\n stamp = util.now();\n thisArg = this;\n trailingCall = trailing && (timeoutId || !leading);\n\n if (maxWait === false) {\n var leadingCall = leading && !timeoutId;\n } else {\n if (!maxTimeoutId && !leading) {\n lastCalled = stamp;\n }\n var remaining = maxWait - (stamp - lastCalled),\n isCalled = remaining <= 0;\n\n if (isCalled) {\n if (maxTimeoutId) {\n maxTimeoutId = clearTimeout(maxTimeoutId);\n }\n lastCalled = stamp;\n result = func.apply(thisArg, args);\n }\n else if (!maxTimeoutId) {\n maxTimeoutId = setTimeout(maxDelayed, remaining);\n }\n }\n if (isCalled && timeoutId) {\n timeoutId = clearTimeout(timeoutId);\n }\n else if (!timeoutId && wait !== maxWait) {\n timeoutId = setTimeout(delayed, wait);\n }\n if (leadingCall) {\n isCalled = true;\n result = func.apply(thisArg, args);\n }\n if (isCalled && !timeoutId && !maxTimeoutId) {\n args = thisArg = null;\n }\n return result;\n };\n};\n\nmodule.exports = util;\n","module.exports = ( typeof window === 'undefined' ? null : window );\n"]}