(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-hierarchy'), require('d3-transition'), require('d3-ease'), require('d3-selection'), require('d3-zoom'), require('d3-array')) : typeof define === 'function' && define.amd ? define(['exports', 'd3-hierarchy', 'd3-transition', 'd3-ease', 'd3-selection', 'd3-zoom', 'd3-array'], factory) : (factory((global.mapexplorerCore = global.mapexplorerCore || {}),global.d3,global.d3,global.d3,global.d3,global.d3,global.d3)); }(this, (function (exports,d3Hierarchy,d3Transition,d3Ease,d3Selection,d3Zoom,d3Array) { 'use strict'; /* Copyright 2017 Stratumn SAS. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ function makeLink(source, target) { var margin = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; var finalTarget = target || source; var targetX = finalTarget.x; var targetY = finalTarget.y - margin; return "M" + source.y + "," + source.x + "\n C" + (source.y + targetY) / 2 + "," + source.x + " " + (source.y + targetY) / 2 + ",\n " + targetX + " " + targetY + "," + targetX; } function finalLink(d, margin) { return makeLink(d.source, d.target, margin); } function translate(x, y) { return "translate(" + y + ", " + x + ")"; } /* Copyright 2017 Stratumn SAS. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ function parseChainscript(chainscript) { return d3Hierarchy.stratify().id(function (d) { return d.meta.linkHash; }).parentId(function (d) { return d.link.meta.prevLinkHash; })(chainscript); } var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var asyncGenerator = function () { function AwaitValue(value) { this.value = value; } function AsyncGenerator(gen) { var front, back; function send(key, arg) { return new Promise(function (resolve, reject) { var request = { key: key, arg: arg, resolve: resolve, reject: reject, next: null }; if (back) { back = back.next = request; } else { front = back = request; resume(key, arg); } }); } function resume(key, arg) { try { var result = gen[key](arg); var value = result.value; if (value instanceof AwaitValue) { Promise.resolve(value.value).then(function (arg) { resume("next", arg); }, function (arg) { resume("throw", arg); }); } else { settle(result.done ? "return" : "normal", result.value); } } catch (err) { settle("throw", err); } } function settle(type, value) { switch (type) { case "return": front.resolve({ value: value, done: true }); break; case "throw": front.reject(value); break; default: front.resolve({ value: value, done: false }); break; } front = front.next; if (front) { resume(front.key, front.arg); } else { back = null; } } this._invoke = send; if (typeof gen.return !== "function") { this.return = undefined; } } if (typeof Symbol === "function" && Symbol.asyncIterator) { AsyncGenerator.prototype[Symbol.asyncIterator] = function () { return this; }; } AsyncGenerator.prototype.next = function (arg) { return this._invoke("next", arg); }; AsyncGenerator.prototype.throw = function (arg) { return this._invoke("throw", arg); }; AsyncGenerator.prototype.return = function (arg) { return this._invoke("return", arg); }; return { wrap: function (fn) { return function () { return new AsyncGenerator(fn.apply(this, arguments)); }; }, await: function (value) { return new AwaitValue(value); } }; }(); var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; /* Copyright 2017 Stratumn SAS. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var margin = { top: 20, right: 120, bottom: 20, left: 120 }; var height = 800 - margin.top - margin.bottom; var ChainTree = function () { function ChainTree(element) { var _this = this; classCallCheck(this, ChainTree); this.tree = d3Hierarchy.tree(); this.svg = d3Selection.select(element).append('svg'); this.innerG = this.svg.append('g'); this.zoomed = function () { return _this.innerG.attr('transform', d3Selection.event.transform); }; } createClass(ChainTree, [{ key: 'display', value: function display(chainscript, options) { if (chainscript && chainscript.length) { var root = parseChainscript(chainscript); this._update(root, options); } else { this._update(null, options); } } }, { key: '_update', value: function _update(root, options) { var self = this; var polygon = options.polygonSize; var nodes = root ? root.descendants() : []; var links = root ? root.links() : []; var maxDepth = d3Array.max(nodes, function (x) { return x.depth; }) || 0; var computedWidth = Math.max(maxDepth * (polygon.width + options.getArrowLength()), 500); var treeTransition = d3Transition.transition().duration(options.duration).ease(d3Ease.easeLinear); var branchesCount = nodes.reduce(function (pre, cur) { return pre + (cur.children ? Math.max(cur.children.length - 1, 0) : 0); }, 1); var computedHeight = branchesCount * polygon.height * options.verticalSpacing; this.tree.size([computedHeight, computedWidth]); this.svg.attr('width', options.zoomable ? 1200 : computedWidth + margin.right + margin.left + options.getArrowLength()).attr('height', (options.zoomable ? height : computedHeight) + margin.top + margin.bottom); // Compute the new tree layout. if (root) { root.x0 = computedHeight / 2; root.y0 = 0; this.tree(root); root.each(function (node) { node.y += options.getArrowLength(); }); } if (options.zoomable) { this.svg.call(d3Zoom.zoom().on('zoom', this.zoomed)); } else { this.svg.on('.zoom', null); } this.innerG.attr('transform', function () { return translate(margin.top, margin.left); }); // Update the links... var link = this.innerG.selectAll('path.link').data(links, function key(d) { return d ? d.target.id : this.id; }); link.enter().insert('text').attr('dx', polygon.width + 20).attr('dy', '-0.3em').append('textPath').attr('class', 'textpath').attr('xlink:href', function (d) { return '#link-' + d.target.id; }).text(options.getLinkText); // Enter any new links at the parent's previous position. link.enter().insert('path', 'g').attr('class', 'link').attr('id', function (d) { return 'link-' + d.target.id; }); var linkUpdate = this.innerG.selectAll('path.link:not(.init)').transition(treeTransition); // Transition links to their new position. linkUpdate.attr('d', function (d) { return finalLink(d, 15); }); link.exit().remove(); // Update the nodes... var node = this.innerG.selectAll('g.node').data(nodes, function key(d) { return d ? d.id : this.id; }); // Enter any new nodes at the parent's previous position. var nodeEnter = node.enter().append('g').attr('class', function (d) { return ['node'].concat(d.data.link.meta.tags).join(' '); }).attr('id', function (d) { return d.id; }).attr('transform', function (d) { var origin = d.parent && d.parent.x0 ? d.parent : root; return translate(origin.x0, origin.y0); }).on('click', function onClick(d) { d3Selection.selectAll('g.node').classed('selected', false); d3Selection.select(this).classed('selected', true); options.onclick(d, function () { self.innerG.selectAll('g.node.selected').classed('selected', false); }, this); }); nodeEnter.append('polygon').attr('points', '0,' + polygon.height / 4 + ' ' + polygon.width / 2 + ',' + polygon.height / 2 + ' ' + (polygon.width + ',' + polygon.height / 4 + ' ' + polygon.width + ',' + -polygon.height / 4 + ' ') + (polygon.width / 2 + ',' + -polygon.height / 2 + ' 0,' + -polygon.height / 4)); nodeEnter.append('rect').attr('y', -(options.getBoxSize().height / 2)).attr('width', polygon.width).attr('height', options.getBoxSize().height).style('fill-opacity', 1e-6); nodeEnter.append('text').attr('dx', 12).attr('dy', 4).attr('text-anchor', 'begin').text(options.getSegmentText).style('fill-opacity', 1e-6); // Transition nodes to their new position. var nodeUpdate = this.svg.selectAll('g.node').transition(treeTransition); nodeUpdate.attr('transform', function (d) { return translate(d.x, d.y); }); nodeUpdate.select('text').style('fill-opacity', 1); nodeUpdate.select('rect').style('fill-opacity', 1); // Transition exiting nodes to the parent's new position. var nodeExit = node.exit(); // .transition(treeTransition); nodeExit.select('text').style('fill-opacity', 1e-6); nodeExit.attr('transform', function () { return translate(0, 0); }).remove(); this._drawInit(root); } }, { key: '_drawInit', value: function _drawInit(root) { this.innerG.append('path').attr('class', 'link init').attr('id', 'init-link').attr('d', makeLink({ x: root.x, y: root.y0 }, root, 15)); this.innerG.append('text').attr('dx', 20).attr('dy', '-0.3em').append('textPath').attr('class', 'textpath').attr('xlink:href', '#init-link').text('init'); } }]); return ChainTree; }(); /* Copyright 2017 Stratumn SAS. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ function compactHash (hash) { return "" + hash.slice(0, 3) + hash.slice(hash.length - 3); } var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {} function interopDefault(ex) { return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex; } function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var index = createCommonjsModule(function (module, exports) { (function (root, factory) { if (typeof define === 'function' && define.amd) { define(factory); } else if (typeof exports === 'object') { module.exports = factory(); } else { root.deepmerge = factory(); } }(commonjsGlobal, function () { return function deepmerge(target, src) { var array = Array.isArray(src); var dst = array && [] || {}; if (array) { target = target || []; dst = dst.concat(target); src.forEach(function(e, i) { if (typeof dst[i] === 'undefined') { dst[i] = e; } else if (typeof e === 'object') { dst[i] = deepmerge(target[i], e); } else { if (target.indexOf(e) === -1) { dst.push(e); } } }); } else { if (target && typeof target === 'object') { Object.keys(target).forEach(function (key) { dst[key] = target[key]; }) } Object.keys(src).forEach(function (key) { if (typeof src[key] !== 'object' || !src[key]) { dst[key] = src[key]; } else { if (!target[key]) { dst[key] = src[key]; } else { dst[key] = deepmerge(target[key], src[key]); } } }); } return dst; } })); }); var merge = interopDefault(index); var global$1 = typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {} // shim for using process in browser // based off https://github.com/defunctzombie/node-process/blob/master/browser.js function defaultSetTimout() { throw new Error('setTimeout has not been defined'); } function defaultClearTimeout () { throw new Error('clearTimeout has not been defined'); } var cachedSetTimeout = defaultSetTimout; var cachedClearTimeout = defaultClearTimeout; if (typeof global$1.setTimeout === 'function') { cachedSetTimeout = setTimeout; } if (typeof global$1.clearTimeout === 'function') { cachedClearTimeout = clearTimeout; } function runTimeout(fun) { if (cachedSetTimeout === setTimeout) { //normal enviroments in sane situations return setTimeout(fun, 0); } // if setTimeout wasn't available but was latter defined if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { cachedSetTimeout = setTimeout; return setTimeout(fun, 0); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedSetTimeout(fun, 0); } catch(e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedSetTimeout.call(null, fun, 0); } catch(e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error return cachedSetTimeout.call(this, fun, 0); } } } function runClearTimeout(marker) { if (cachedClearTimeout === clearTimeout) { //normal enviroments in sane situations return clearTimeout(marker); } // if clearTimeout wasn't available but was latter defined if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { cachedClearTimeout = clearTimeout; return clearTimeout(marker); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedClearTimeout(marker); } catch (e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedClearTimeout.call(null, marker); } catch (e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. // Some versions of I.E. have different rules for clearTimeout vs setTimeout return cachedClearTimeout.call(this, marker); } } } var queue = []; var draining = false; var currentQueue; var queueIndex = -1; function cleanUpNextTick() { if (!draining || !currentQueue) { return; } draining = false; if (currentQueue.length) { queue = currentQueue.concat(queue); } else { queueIndex = -1; } if (queue.length) { drainQueue(); } } function drainQueue() { if (draining) { return; } var timeout = runTimeout(cleanUpNextTick); draining = true; var len = queue.length; while(len) { currentQueue = queue; queue = []; while (++queueIndex < len) { if (currentQueue) { currentQueue[queueIndex].run(); } } queueIndex = -1; len = queue.length; } currentQueue = null; draining = false; runClearTimeout(timeout); } function nextTick(fun) { var args = new Array(arguments.length - 1); if (arguments.length > 1) { for (var i = 1; i < arguments.length; i++) { args[i - 1] = arguments[i]; } } queue.push(new Item(fun, args)); if (queue.length === 1 && !draining) { runTimeout(drainQueue); } } // v8 likes predictible objects function Item(fun, array) { this.fun = fun; this.array = array; } Item.prototype.run = function () { this.fun.apply(null, this.array); }; var title = 'browser'; var platform = 'browser'; var browser = true; var env = {}; var argv = []; var version = ''; // empty string to avoid regexp issues var versions = {}; var release = {}; var config$1 = {}; function noop() {} var on = noop; var addListener = noop; var once = noop; var off = noop; var removeListener = noop; var removeAllListeners = noop; var emit = noop; function binding(name) { throw new Error('process.binding is not supported'); } function cwd () { return '/' } function chdir (dir) { throw new Error('process.chdir is not supported'); }; function umask() { return 0; } // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js var performance = global$1.performance || {} var performanceNow = performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function(){ return (new Date()).getTime() } // generate timestamp or delta // see http://nodejs.org/api/process.html#process_process_hrtime function hrtime(previousTimestamp){ var clocktime = performanceNow.call(performance)*1e-3 var seconds = Math.floor(clocktime) var nanoseconds = Math.floor((clocktime%1)*1e9) if (previousTimestamp) { seconds = seconds - previousTimestamp[0] nanoseconds = nanoseconds - previousTimestamp[1] if (nanoseconds<0) { seconds-- nanoseconds += 1e9 } } return [seconds,nanoseconds] } var startTime = new Date(); function uptime() { var currentTime = new Date(); var dif = currentTime - startTime; return dif / 1000; } var process = { nextTick: nextTick, title: title, browser: browser, env: env, argv: argv, version: version, versions: versions, on: on, addListener: addListener, once: once, off: off, removeListener: removeListener, removeAllListeners: removeAllListeners, emit: emit, binding: binding, cwd: cwd, chdir: chdir, umask: umask, hrtime: hrtime, platform: platform, release: release, config: config$1, uptime: uptime }; var setImmediate$1 = createCommonjsModule(function (module) { (function (global, undefined) { "use strict"; if (global.setImmediate) { return; } var nextHandle = 1; // Spec says greater than zero var tasksByHandle = {}; var currentlyRunningATask = false; var doc = global.document; var registerImmediate; function setImmediate(callback) { // Callback can either be a function or a string if (typeof callback !== "function") { callback = new Function("" + callback); } // Copy function arguments var args = new Array(arguments.length - 1); for (var i = 0; i < args.length; i++) { args[i] = arguments[i + 1]; } // Store and register the task var task = { callback: callback, args: args }; tasksByHandle[nextHandle] = task; registerImmediate(nextHandle); return nextHandle++; } function clearImmediate(handle) { delete tasksByHandle[handle]; } function run(task) { var callback = task.callback; var args = task.args; switch (args.length) { case 0: callback(); break; case 1: callback(args[0]); break; case 2: callback(args[0], args[1]); break; case 3: callback(args[0], args[1], args[2]); break; default: callback.apply(undefined, args); break; } } function runIfPresent(handle) { // From the spec: "Wait until any invocations of this algorithm started before this one have completed." // So if we're currently running a task, we'll need to delay this invocation. if (currentlyRunningATask) { // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a // "too much recursion" error. setTimeout(runIfPresent, 0, handle); } else { var task = tasksByHandle[handle]; if (task) { currentlyRunningATask = true; try { run(task); } finally { clearImmediate(handle); currentlyRunningATask = false; } } } } function installNextTickImplementation() { registerImmediate = function(handle) { nextTick(function () { runIfPresent(handle); }); }; } function canUsePostMessage() { // The test against `importScripts` prevents this implementation from being installed inside a web worker, // where `global.postMessage` means something completely different and can't be used for this purpose. if (global.postMessage && !global.importScripts) { var postMessageIsAsynchronous = true; var oldOnMessage = global.onmessage; global.onmessage = function() { postMessageIsAsynchronous = false; }; global.postMessage("", "*"); global.onmessage = oldOnMessage; return postMessageIsAsynchronous; } } function installPostMessageImplementation() { // Installs an event handler on `global` for the `message` event: see // * https://developer.mozilla.org/en/DOM/window.postMessage // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages var messagePrefix = "setImmediate$" + Math.random() + "$"; var onGlobalMessage = function(event) { if (event.source === global && typeof event.data === "string" && event.data.indexOf(messagePrefix) === 0) { runIfPresent(+event.data.slice(messagePrefix.length)); } }; if (global.addEventListener) { global.addEventListener("message", onGlobalMessage, false); } else { global.attachEvent("onmessage", onGlobalMessage); } registerImmediate = function(handle) { global.postMessage(messagePrefix + handle, "*"); }; } function installMessageChannelImplementation() { var channel = new MessageChannel(); channel.port1.onmessage = function(event) { var handle = event.data; runIfPresent(handle); }; registerImmediate = function(handle) { channel.port2.postMessage(handle); }; } function installReadyStateChangeImplementation() { var html = doc.documentElement; registerImmediate = function(handle) { // Create a