suitepro/plugins/additionals/assets/javascripts/d3plus-hierarchy.full.js

56878 lines
1.7 MiB
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
d3plus-hierarchy v0.9.0
Nested, hierarchical, and cluster charts built on D3
Copyright (c) 2020 D3plus - https://d3plus.org
@license MIT
*/
(function (factory) {
typeof define === 'function' && define.amd ? define(factory) :
factory();
}((function () { 'use strict';
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var check = function (it) {
return it && it.Math == Math && it;
};
// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
var global_1 =
// eslint-disable-next-line no-undef
check(typeof globalThis == 'object' && globalThis) ||
check(typeof window == 'object' && window) ||
check(typeof self == 'object' && self) ||
check(typeof commonjsGlobal == 'object' && commonjsGlobal) ||
// eslint-disable-next-line no-new-func
Function('return this')();
var fails = function (exec) {
try {
return !!exec();
} catch (error) {
return true;
}
};
// Thank's IE8 for his funny defineProperty
var descriptors = !fails(function () {
return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] != 7;
});
var nativePropertyIsEnumerable = {}.propertyIsEnumerable;
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
// Nashorn ~ JDK8 bug
var NASHORN_BUG = getOwnPropertyDescriptor && !nativePropertyIsEnumerable.call({ 1: 2 }, 1);
// `Object.prototype.propertyIsEnumerable` method implementation
// https://tc39.github.io/ecma262/#sec-object.prototype.propertyisenumerable
var f = NASHORN_BUG ? function propertyIsEnumerable(V) {
var descriptor = getOwnPropertyDescriptor(this, V);
return !!descriptor && descriptor.enumerable;
} : nativePropertyIsEnumerable;
var objectPropertyIsEnumerable = {
f: f
};
var createPropertyDescriptor = function (bitmap, value) {
return {
enumerable: !(bitmap & 1),
configurable: !(bitmap & 2),
writable: !(bitmap & 4),
value: value
};
};
var toString = {}.toString;
var classofRaw = function (it) {
return toString.call(it).slice(8, -1);
};
var split = ''.split;
// fallback for non-array-like ES3 and non-enumerable old V8 strings
var indexedObject = fails(function () {
// throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
// eslint-disable-next-line no-prototype-builtins
return !Object('z').propertyIsEnumerable(0);
}) ? function (it) {
return classofRaw(it) == 'String' ? split.call(it, '') : Object(it);
} : Object;
// `RequireObjectCoercible` abstract operation
// https://tc39.github.io/ecma262/#sec-requireobjectcoercible
var requireObjectCoercible = function (it) {
if (it == undefined) throw TypeError("Can't call method on " + it);
return it;
};
// toObject with fallback for non-array-like ES3 strings
var toIndexedObject = function (it) {
return indexedObject(requireObjectCoercible(it));
};
var isObject = function (it) {
return typeof it === 'object' ? it !== null : typeof it === 'function';
};
// `ToPrimitive` abstract operation
// https://tc39.github.io/ecma262/#sec-toprimitive
// instead of the ES6 spec version, we didn't implement @@toPrimitive case
// and the second argument - flag - preferred type is a string
var toPrimitive = function (input, PREFERRED_STRING) {
if (!isObject(input)) return input;
var fn, val;
if (PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val;
if (typeof (fn = input.valueOf) == 'function' && !isObject(val = fn.call(input))) return val;
if (!PREFERRED_STRING && typeof (fn = input.toString) == 'function' && !isObject(val = fn.call(input))) return val;
throw TypeError("Can't convert object to primitive value");
};
var hasOwnProperty = {}.hasOwnProperty;
var has = function (it, key) {
return hasOwnProperty.call(it, key);
};
var document$1 = global_1.document;
// typeof document.createElement is 'object' in old IE
var EXISTS = isObject(document$1) && isObject(document$1.createElement);
var documentCreateElement = function (it) {
return EXISTS ? document$1.createElement(it) : {};
};
// Thank's IE8 for his funny defineProperty
var ie8DomDefine = !descriptors && !fails(function () {
return Object.defineProperty(documentCreateElement('div'), 'a', {
get: function () { return 7; }
}).a != 7;
});
var nativeGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
// `Object.getOwnPropertyDescriptor` method
// https://tc39.github.io/ecma262/#sec-object.getownpropertydescriptor
var f$1 = descriptors ? nativeGetOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) {
O = toIndexedObject(O);
P = toPrimitive(P, true);
if (ie8DomDefine) try {
return nativeGetOwnPropertyDescriptor(O, P);
} catch (error) { /* empty */ }
if (has(O, P)) return createPropertyDescriptor(!objectPropertyIsEnumerable.f.call(O, P), O[P]);
};
var objectGetOwnPropertyDescriptor = {
f: f$1
};
var anObject = function (it) {
if (!isObject(it)) {
throw TypeError(String(it) + ' is not an object');
} return it;
};
var nativeDefineProperty = Object.defineProperty;
// `Object.defineProperty` method
// https://tc39.github.io/ecma262/#sec-object.defineproperty
var f$2 = descriptors ? nativeDefineProperty : function defineProperty(O, P, Attributes) {
anObject(O);
P = toPrimitive(P, true);
anObject(Attributes);
if (ie8DomDefine) try {
return nativeDefineProperty(O, P, Attributes);
} catch (error) { /* empty */ }
if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported');
if ('value' in Attributes) O[P] = Attributes.value;
return O;
};
var objectDefineProperty = {
f: f$2
};
var createNonEnumerableProperty = descriptors ? function (object, key, value) {
return objectDefineProperty.f(object, key, createPropertyDescriptor(1, value));
} : function (object, key, value) {
object[key] = value;
return object;
};
var setGlobal = function (key, value) {
try {
createNonEnumerableProperty(global_1, key, value);
} catch (error) {
global_1[key] = value;
} return value;
};
var SHARED = '__core-js_shared__';
var store = global_1[SHARED] || setGlobal(SHARED, {});
var sharedStore = store;
var functionToString = Function.toString;
// this helper broken in `3.4.1-3.4.4`, so we can't use `shared` helper
if (typeof sharedStore.inspectSource != 'function') {
sharedStore.inspectSource = function (it) {
return functionToString.call(it);
};
}
var inspectSource = sharedStore.inspectSource;
var WeakMap = global_1.WeakMap;
var nativeWeakMap = typeof WeakMap === 'function' && /native code/.test(inspectSource(WeakMap));
var shared = createCommonjsModule(function (module) {
(module.exports = function (key, value) {
return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {});
})('versions', []).push({
version: '3.6.5',
mode: 'global',
copyright: '© 2020 Denis Pushkarev (zloirock.ru)'
});
});
var id = 0;
var postfix = Math.random();
var uid = function (key) {
return 'Symbol(' + String(key === undefined ? '' : key) + ')_' + (++id + postfix).toString(36);
};
var keys = shared('keys');
var sharedKey = function (key) {
return keys[key] || (keys[key] = uid(key));
};
var hiddenKeys = {};
var WeakMap$1 = global_1.WeakMap;
var set, get, has$1;
var enforce = function (it) {
return has$1(it) ? get(it) : set(it, {});
};
var getterFor = function (TYPE) {
return function (it) {
var state;
if (!isObject(it) || (state = get(it)).type !== TYPE) {
throw TypeError('Incompatible receiver, ' + TYPE + ' required');
} return state;
};
};
if (nativeWeakMap) {
var store$1 = new WeakMap$1();
var wmget = store$1.get;
var wmhas = store$1.has;
var wmset = store$1.set;
set = function (it, metadata) {
wmset.call(store$1, it, metadata);
return metadata;
};
get = function (it) {
return wmget.call(store$1, it) || {};
};
has$1 = function (it) {
return wmhas.call(store$1, it);
};
} else {
var STATE = sharedKey('state');
hiddenKeys[STATE] = true;
set = function (it, metadata) {
createNonEnumerableProperty(it, STATE, metadata);
return metadata;
};
get = function (it) {
return has(it, STATE) ? it[STATE] : {};
};
has$1 = function (it) {
return has(it, STATE);
};
}
var internalState = {
set: set,
get: get,
has: has$1,
enforce: enforce,
getterFor: getterFor
};
var redefine = createCommonjsModule(function (module) {
var getInternalState = internalState.get;
var enforceInternalState = internalState.enforce;
var TEMPLATE = String(String).split('String');
(module.exports = function (O, key, value, options) {
var unsafe = options ? !!options.unsafe : false;
var simple = options ? !!options.enumerable : false;
var noTargetGet = options ? !!options.noTargetGet : false;
if (typeof value == 'function') {
if (typeof key == 'string' && !has(value, 'name')) createNonEnumerableProperty(value, 'name', key);
enforceInternalState(value).source = TEMPLATE.join(typeof key == 'string' ? key : '');
}
if (O === global_1) {
if (simple) O[key] = value;
else setGlobal(key, value);
return;
} else if (!unsafe) {
delete O[key];
} else if (!noTargetGet && O[key]) {
simple = true;
}
if (simple) O[key] = value;
else createNonEnumerableProperty(O, key, value);
// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
})(Function.prototype, 'toString', function toString() {
return typeof this == 'function' && getInternalState(this).source || inspectSource(this);
});
});
var path = global_1;
var aFunction = function (variable) {
return typeof variable == 'function' ? variable : undefined;
};
var getBuiltIn = function (namespace, method) {
return arguments.length < 2 ? aFunction(path[namespace]) || aFunction(global_1[namespace])
: path[namespace] && path[namespace][method] || global_1[namespace] && global_1[namespace][method];
};
var ceil = Math.ceil;
var floor = Math.floor;
// `ToInteger` abstract operation
// https://tc39.github.io/ecma262/#sec-tointeger
var toInteger = function (argument) {
return isNaN(argument = +argument) ? 0 : (argument > 0 ? floor : ceil)(argument);
};
var min = Math.min;
// `ToLength` abstract operation
// https://tc39.github.io/ecma262/#sec-tolength
var toLength = function (argument) {
return argument > 0 ? min(toInteger(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
};
var max = Math.max;
var min$1 = Math.min;
// Helper for a popular repeating case of the spec:
// Let integer be ? ToInteger(index).
// If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
var toAbsoluteIndex = function (index, length) {
var integer = toInteger(index);
return integer < 0 ? max(integer + length, 0) : min$1(integer, length);
};
// `Array.prototype.{ indexOf, includes }` methods implementation
var createMethod = function (IS_INCLUDES) {
return function ($this, el, fromIndex) {
var O = toIndexedObject($this);
var length = toLength(O.length);
var index = toAbsoluteIndex(fromIndex, length);
var value;
// Array#includes uses SameValueZero equality algorithm
// eslint-disable-next-line no-self-compare
if (IS_INCLUDES && el != el) while (length > index) {
value = O[index++];
// eslint-disable-next-line no-self-compare
if (value != value) return true;
// Array#indexOf ignores holes, Array#includes - not
} else for (;length > index; index++) {
if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
} return !IS_INCLUDES && -1;
};
};
var arrayIncludes = {
// `Array.prototype.includes` method
// https://tc39.github.io/ecma262/#sec-array.prototype.includes
includes: createMethod(true),
// `Array.prototype.indexOf` method
// https://tc39.github.io/ecma262/#sec-array.prototype.indexof
indexOf: createMethod(false)
};
var indexOf = arrayIncludes.indexOf;
var objectKeysInternal = function (object, names) {
var O = toIndexedObject(object);
var i = 0;
var result = [];
var key;
for (key in O) !has(hiddenKeys, key) && has(O, key) && result.push(key);
// Don't enum bug & hidden keys
while (names.length > i) if (has(O, key = names[i++])) {
~indexOf(result, key) || result.push(key);
}
return result;
};
// IE8- don't enum bug keys
var enumBugKeys = [
'constructor',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'toLocaleString',
'toString',
'valueOf'
];
var hiddenKeys$1 = enumBugKeys.concat('length', 'prototype');
// `Object.getOwnPropertyNames` method
// https://tc39.github.io/ecma262/#sec-object.getownpropertynames
var f$3 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
return objectKeysInternal(O, hiddenKeys$1);
};
var objectGetOwnPropertyNames = {
f: f$3
};
var f$4 = Object.getOwnPropertySymbols;
var objectGetOwnPropertySymbols = {
f: f$4
};
// all object keys, includes non-enumerable and symbols
var ownKeys = getBuiltIn('Reflect', 'ownKeys') || function ownKeys(it) {
var keys = objectGetOwnPropertyNames.f(anObject(it));
var getOwnPropertySymbols = objectGetOwnPropertySymbols.f;
return getOwnPropertySymbols ? keys.concat(getOwnPropertySymbols(it)) : keys;
};
var copyConstructorProperties = function (target, source) {
var keys = ownKeys(source);
var defineProperty = objectDefineProperty.f;
var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (!has(target, key)) defineProperty(target, key, getOwnPropertyDescriptor(source, key));
}
};
var replacement = /#|\.prototype\./;
var isForced = function (feature, detection) {
var value = data[normalize(feature)];
return value == POLYFILL ? true
: value == NATIVE ? false
: typeof detection == 'function' ? fails(detection)
: !!detection;
};
var normalize = isForced.normalize = function (string) {
return String(string).replace(replacement, '.').toLowerCase();
};
var data = isForced.data = {};
var NATIVE = isForced.NATIVE = 'N';
var POLYFILL = isForced.POLYFILL = 'P';
var isForced_1 = isForced;
var getOwnPropertyDescriptor$1 = objectGetOwnPropertyDescriptor.f;
/*
options.target - name of the target object
options.global - target is the global object
options.stat - export as static methods of target
options.proto - export as prototype methods of target
options.real - real prototype method for the `pure` version
options.forced - export even if the native feature is available
options.bind - bind methods to the target, required for the `pure` version
options.wrap - wrap constructors to preventing global pollution, required for the `pure` version
options.unsafe - use the simple assignment of property instead of delete + defineProperty
options.sham - add a flag to not completely full polyfills
options.enumerable - export as enumerable property
options.noTargetGet - prevent calling a getter on target
*/
var _export = function (options, source) {
var TARGET = options.target;
var GLOBAL = options.global;
var STATIC = options.stat;
var FORCED, target, key, targetProperty, sourceProperty, descriptor;
if (GLOBAL) {
target = global_1;
} else if (STATIC) {
target = global_1[TARGET] || setGlobal(TARGET, {});
} else {
target = (global_1[TARGET] || {}).prototype;
}
if (target) for (key in source) {
sourceProperty = source[key];
if (options.noTargetGet) {
descriptor = getOwnPropertyDescriptor$1(target, key);
targetProperty = descriptor && descriptor.value;
} else targetProperty = target[key];
FORCED = isForced_1(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced);
// contained in target
if (!FORCED && targetProperty !== undefined) {
if (typeof sourceProperty === typeof targetProperty) continue;
copyConstructorProperties(sourceProperty, targetProperty);
}
// add a flag to not completely full polyfills
if (options.sham || (targetProperty && targetProperty.sham)) {
createNonEnumerableProperty(sourceProperty, 'sham', true);
}
// extend global
redefine(target, key, sourceProperty, options);
}
};
var aFunction$1 = function (it) {
if (typeof it != 'function') {
throw TypeError(String(it) + ' is not a function');
} return it;
};
// optional / simple context binding
var functionBindContext = function (fn, that, length) {
aFunction$1(fn);
if (that === undefined) return fn;
switch (length) {
case 0: return function () {
return fn.call(that);
};
case 1: return function (a) {
return fn.call(that, a);
};
case 2: return function (a, b) {
return fn.call(that, a, b);
};
case 3: return function (a, b, c) {
return fn.call(that, a, b, c);
};
}
return function (/* ...args */) {
return fn.apply(that, arguments);
};
};
// `ToObject` abstract operation
// https://tc39.github.io/ecma262/#sec-toobject
var toObject = function (argument) {
return Object(requireObjectCoercible(argument));
};
// `IsArray` abstract operation
// https://tc39.github.io/ecma262/#sec-isarray
var isArray = Array.isArray || function isArray(arg) {
return classofRaw(arg) == 'Array';
};
var nativeSymbol = !!Object.getOwnPropertySymbols && !fails(function () {
// Chrome 38 Symbol has incorrect toString conversion
// eslint-disable-next-line no-undef
return !String(Symbol());
});
var useSymbolAsUid = nativeSymbol
// eslint-disable-next-line no-undef
&& !Symbol.sham
// eslint-disable-next-line no-undef
&& typeof Symbol.iterator == 'symbol';
var WellKnownSymbolsStore = shared('wks');
var Symbol$1 = global_1.Symbol;
var createWellKnownSymbol = useSymbolAsUid ? Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || uid;
var wellKnownSymbol = function (name) {
if (!has(WellKnownSymbolsStore, name)) {
if (nativeSymbol && has(Symbol$1, name)) WellKnownSymbolsStore[name] = Symbol$1[name];
else WellKnownSymbolsStore[name] = createWellKnownSymbol('Symbol.' + name);
} return WellKnownSymbolsStore[name];
};
var SPECIES = wellKnownSymbol('species');
// `ArraySpeciesCreate` abstract operation
// https://tc39.github.io/ecma262/#sec-arrayspeciescreate
var arraySpeciesCreate = function (originalArray, length) {
var C;
if (isArray(originalArray)) {
C = originalArray.constructor;
// cross-realm fallback
if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;
else if (isObject(C)) {
C = C[SPECIES];
if (C === null) C = undefined;
}
} return new (C === undefined ? Array : C)(length === 0 ? 0 : length);
};
var push = [].push;
// `Array.prototype.{ forEach, map, filter, some, every, find, findIndex }` methods implementation
var createMethod$1 = function (TYPE) {
var IS_MAP = TYPE == 1;
var IS_FILTER = TYPE == 2;
var IS_SOME = TYPE == 3;
var IS_EVERY = TYPE == 4;
var IS_FIND_INDEX = TYPE == 6;
var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;
return function ($this, callbackfn, that, specificCreate) {
var O = toObject($this);
var self = indexedObject(O);
var boundFunction = functionBindContext(callbackfn, that, 3);
var length = toLength(self.length);
var index = 0;
var create = specificCreate || arraySpeciesCreate;
var target = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined;
var value, result;
for (;length > index; index++) if (NO_HOLES || index in self) {
value = self[index];
result = boundFunction(value, index, O);
if (TYPE) {
if (IS_MAP) target[index] = result; // map
else if (result) switch (TYPE) {
case 3: return true; // some
case 5: return value; // find
case 6: return index; // findIndex
case 2: push.call(target, value); // filter
} else if (IS_EVERY) return false; // every
}
}
return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : target;
};
};
var arrayIteration = {
// `Array.prototype.forEach` method
// https://tc39.github.io/ecma262/#sec-array.prototype.foreach
forEach: createMethod$1(0),
// `Array.prototype.map` method
// https://tc39.github.io/ecma262/#sec-array.prototype.map
map: createMethod$1(1),
// `Array.prototype.filter` method
// https://tc39.github.io/ecma262/#sec-array.prototype.filter
filter: createMethod$1(2),
// `Array.prototype.some` method
// https://tc39.github.io/ecma262/#sec-array.prototype.some
some: createMethod$1(3),
// `Array.prototype.every` method
// https://tc39.github.io/ecma262/#sec-array.prototype.every
every: createMethod$1(4),
// `Array.prototype.find` method
// https://tc39.github.io/ecma262/#sec-array.prototype.find
find: createMethod$1(5),
// `Array.prototype.findIndex` method
// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex
findIndex: createMethod$1(6)
};
// `Object.keys` method
// https://tc39.github.io/ecma262/#sec-object.keys
var objectKeys = Object.keys || function keys(O) {
return objectKeysInternal(O, enumBugKeys);
};
// `Object.defineProperties` method
// https://tc39.github.io/ecma262/#sec-object.defineproperties
var objectDefineProperties = descriptors ? Object.defineProperties : function defineProperties(O, Properties) {
anObject(O);
var keys = objectKeys(Properties);
var length = keys.length;
var index = 0;
var key;
while (length > index) objectDefineProperty.f(O, key = keys[index++], Properties[key]);
return O;
};
var html = getBuiltIn('document', 'documentElement');
var GT = '>';
var LT = '<';
var PROTOTYPE = 'prototype';
var SCRIPT = 'script';
var IE_PROTO = sharedKey('IE_PROTO');
var EmptyConstructor = function () { /* empty */ };
var scriptTag = function (content) {
return LT + SCRIPT + GT + content + LT + '/' + SCRIPT + GT;
};
// Create object with fake `null` prototype: use ActiveX Object with cleared prototype
var NullProtoObjectViaActiveX = function (activeXDocument) {
activeXDocument.write(scriptTag(''));
activeXDocument.close();
var temp = activeXDocument.parentWindow.Object;
activeXDocument = null; // avoid memory leak
return temp;
};
// Create object with fake `null` prototype: use iframe Object with cleared prototype
var NullProtoObjectViaIFrame = function () {
// Thrash, waste and sodomy: IE GC bug
var iframe = documentCreateElement('iframe');
var JS = 'java' + SCRIPT + ':';
var iframeDocument;
iframe.style.display = 'none';
html.appendChild(iframe);
// https://github.com/zloirock/core-js/issues/475
iframe.src = String(JS);
iframeDocument = iframe.contentWindow.document;
iframeDocument.open();
iframeDocument.write(scriptTag('document.F=Object'));
iframeDocument.close();
return iframeDocument.F;
};
// Check for document.domain and active x support
// No need to use active x approach when document.domain is not set
// see https://github.com/es-shims/es5-shim/issues/150
// variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346
// avoid IE GC bug
var activeXDocument;
var NullProtoObject = function () {
try {
/* global ActiveXObject */
activeXDocument = document.domain && new ActiveXObject('htmlfile');
} catch (error) { /* ignore */ }
NullProtoObject = activeXDocument ? NullProtoObjectViaActiveX(activeXDocument) : NullProtoObjectViaIFrame();
var length = enumBugKeys.length;
while (length--) delete NullProtoObject[PROTOTYPE][enumBugKeys[length]];
return NullProtoObject();
};
hiddenKeys[IE_PROTO] = true;
// `Object.create` method
// https://tc39.github.io/ecma262/#sec-object.create
var objectCreate = Object.create || function create(O, Properties) {
var result;
if (O !== null) {
EmptyConstructor[PROTOTYPE] = anObject(O);
result = new EmptyConstructor();
EmptyConstructor[PROTOTYPE] = null;
// add "__proto__" for Object.getPrototypeOf polyfill
result[IE_PROTO] = O;
} else result = NullProtoObject();
return Properties === undefined ? result : objectDefineProperties(result, Properties);
};
var UNSCOPABLES = wellKnownSymbol('unscopables');
var ArrayPrototype = Array.prototype;
// Array.prototype[@@unscopables]
// https://tc39.github.io/ecma262/#sec-array.prototype-@@unscopables
if (ArrayPrototype[UNSCOPABLES] == undefined) {
objectDefineProperty.f(ArrayPrototype, UNSCOPABLES, {
configurable: true,
value: objectCreate(null)
});
}
// add a key to Array.prototype[@@unscopables]
var addToUnscopables = function (key) {
ArrayPrototype[UNSCOPABLES][key] = true;
};
var defineProperty = Object.defineProperty;
var cache = {};
var thrower = function (it) { throw it; };
var arrayMethodUsesToLength = function (METHOD_NAME, options) {
if (has(cache, METHOD_NAME)) return cache[METHOD_NAME];
if (!options) options = {};
var method = [][METHOD_NAME];
var ACCESSORS = has(options, 'ACCESSORS') ? options.ACCESSORS : false;
var argument0 = has(options, 0) ? options[0] : thrower;
var argument1 = has(options, 1) ? options[1] : undefined;
return cache[METHOD_NAME] = !!method && !fails(function () {
if (ACCESSORS && !descriptors) return true;
var O = { length: -1 };
if (ACCESSORS) defineProperty(O, 1, { enumerable: true, get: thrower });
else O[1] = 1;
method.call(O, argument0, argument1);
});
};
var $find = arrayIteration.find;
var FIND = 'find';
var SKIPS_HOLES = true;
var USES_TO_LENGTH = arrayMethodUsesToLength(FIND);
// Shouldn't skip holes
if (FIND in []) Array(1)[FIND](function () { SKIPS_HOLES = false; });
// `Array.prototype.find` method
// https://tc39.github.io/ecma262/#sec-array.prototype.find
_export({ target: 'Array', proto: true, forced: SKIPS_HOLES || !USES_TO_LENGTH }, {
find: function find(callbackfn /* , that = undefined */) {
return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
}
});
// https://tc39.github.io/ecma262/#sec-array.prototype-@@unscopables
addToUnscopables(FIND);
var $includes = arrayIncludes.includes;
var USES_TO_LENGTH$1 = arrayMethodUsesToLength('indexOf', { ACCESSORS: true, 1: 0 });
// `Array.prototype.includes` method
// https://tc39.github.io/ecma262/#sec-array.prototype.includes
_export({ target: 'Array', proto: true, forced: !USES_TO_LENGTH$1 }, {
includes: function includes(el /* , fromIndex = 0 */) {
return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
}
});
// https://tc39.github.io/ecma262/#sec-array.prototype-@@unscopables
addToUnscopables('includes');
var nativeAssign = Object.assign;
var defineProperty$1 = Object.defineProperty;
// `Object.assign` method
// https://tc39.github.io/ecma262/#sec-object.assign
var objectAssign = !nativeAssign || fails(function () {
// should have correct order of operations (Edge bug)
if (descriptors && nativeAssign({ b: 1 }, nativeAssign(defineProperty$1({}, 'a', {
enumerable: true,
get: function () {
defineProperty$1(this, 'b', {
value: 3,
enumerable: false
});
}
}), { b: 2 })).b !== 1) return true;
// should work with symbols and should have deterministic property order (V8 bug)
var A = {};
var B = {};
// eslint-disable-next-line no-undef
var symbol = Symbol();
var alphabet = 'abcdefghijklmnopqrst';
A[symbol] = 7;
alphabet.split('').forEach(function (chr) { B[chr] = chr; });
return nativeAssign({}, A)[symbol] != 7 || objectKeys(nativeAssign({}, B)).join('') != alphabet;
}) ? function assign(target, source) { // eslint-disable-line no-unused-vars
var T = toObject(target);
var argumentsLength = arguments.length;
var index = 1;
var getOwnPropertySymbols = objectGetOwnPropertySymbols.f;
var propertyIsEnumerable = objectPropertyIsEnumerable.f;
while (argumentsLength > index) {
var S = indexedObject(arguments[index++]);
var keys = getOwnPropertySymbols ? objectKeys(S).concat(getOwnPropertySymbols(S)) : objectKeys(S);
var length = keys.length;
var j = 0;
var key;
while (length > j) {
key = keys[j++];
if (!descriptors || propertyIsEnumerable.call(S, key)) T[key] = S[key];
}
} return T;
} : nativeAssign;
// `Object.assign` method
// https://tc39.github.io/ecma262/#sec-object.assign
_export({ target: 'Object', stat: true, forced: Object.assign !== objectAssign }, {
assign: objectAssign
});
var MATCH = wellKnownSymbol('match');
// `IsRegExp` abstract operation
// https://tc39.github.io/ecma262/#sec-isregexp
var isRegexp = function (it) {
var isRegExp;
return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : classofRaw(it) == 'RegExp');
};
var notARegexp = function (it) {
if (isRegexp(it)) {
throw TypeError("The method doesn't accept regular expressions");
} return it;
};
var MATCH$1 = wellKnownSymbol('match');
var correctIsRegexpLogic = function (METHOD_NAME) {
var regexp = /./;
try {
'/./'[METHOD_NAME](regexp);
} catch (e) {
try {
regexp[MATCH$1] = false;
return '/./'[METHOD_NAME](regexp);
} catch (f) { /* empty */ }
} return false;
};
// `String.prototype.includes` method
// https://tc39.github.io/ecma262/#sec-string.prototype.includes
_export({ target: 'String', proto: true, forced: !correctIsRegexpLogic('includes') }, {
includes: function includes(searchString /* , position = 0 */) {
return !!~String(requireObjectCoercible(this))
.indexOf(notARegexp(searchString), arguments.length > 1 ? arguments[1] : undefined);
}
});
var getOwnPropertyDescriptor$2 = objectGetOwnPropertyDescriptor.f;
var nativeStartsWith = ''.startsWith;
var min$2 = Math.min;
var CORRECT_IS_REGEXP_LOGIC = correctIsRegexpLogic('startsWith');
// https://github.com/zloirock/core-js/pull/702
var MDN_POLYFILL_BUG = !CORRECT_IS_REGEXP_LOGIC && !!function () {
var descriptor = getOwnPropertyDescriptor$2(String.prototype, 'startsWith');
return descriptor && !descriptor.writable;
}();
// `String.prototype.startsWith` method
// https://tc39.github.io/ecma262/#sec-string.prototype.startswith
_export({ target: 'String', proto: true, forced: !MDN_POLYFILL_BUG && !CORRECT_IS_REGEXP_LOGIC }, {
startsWith: function startsWith(searchString /* , position = 0 */) {
var that = String(requireObjectCoercible(this));
notARegexp(searchString);
var index = toLength(min$2(arguments.length > 1 ? arguments[1] : undefined, that.length));
var search = String(searchString);
return nativeStartsWith
? nativeStartsWith.call(that, search, index)
: that.slice(index, index + search.length) === search;
}
});
if (typeof window !== "undefined") {
(function () {
try {
if (typeof SVGElement === 'undefined' || Boolean(SVGElement.prototype.innerHTML)) {
return;
}
} catch (e) {
return;
}
function serializeNode (node) {
switch (node.nodeType) {
case 1:
return serializeElementNode(node);
case 3:
return serializeTextNode(node);
case 8:
return serializeCommentNode(node);
}
}
function serializeTextNode (node) {
return node.textContent.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
function serializeCommentNode (node) {
return '<!--' + node.nodeValue + '-->'
}
function serializeElementNode (node) {
var output = '';
output += '<' + node.tagName;
if (node.hasAttributes()) {
[].forEach.call(node.attributes, function(attrNode) {
output += ' ' + attrNode.name + '="' + attrNode.value + '"';
});
}
output += '>';
if (node.hasChildNodes()) {
[].forEach.call(node.childNodes, function(childNode) {
output += serializeNode(childNode);
});
}
output += '</' + node.tagName + '>';
return output;
}
Object.defineProperty(SVGElement.prototype, 'innerHTML', {
get: function () {
var output = '';
[].forEach.call(this.childNodes, function(childNode) {
output += serializeNode(childNode);
});
return output;
},
set: function (markup) {
while (this.firstChild) {
this.removeChild(this.firstChild);
}
try {
var dXML = new DOMParser();
dXML.async = false;
var sXML = '<svg xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\'>' + markup + '</svg>';
var svgDocElement = dXML.parseFromString(sXML, 'text/xml').documentElement;
[].forEach.call(svgDocElement.childNodes, function(childNode) {
this.appendChild(this.ownerDocument.importNode(childNode, true));
}.bind(this));
} catch (e) {
throw new Error('Error parsing markup string');
}
}
});
Object.defineProperty(SVGElement.prototype, 'innerSVG', {
get: function () {
return this.innerHTML;
},
set: function (markup) {
this.innerHTML = markup;
}
});
})();
}
})));
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define('d3plus-hierarchy', ['exports'], factory) :
(global = global || self, factory(global.d3plus = {}));
}(this, (function (exports) {
function _typeof(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof = function (obj) {
return typeof obj;
};
} else {
_typeof = function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof(obj);
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
if (enumerableOnly) symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
});
keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
if (i % 2) {
ownKeys(Object(source), true).forEach(function (key) {
_defineProperty(target, key, source[key]);
});
} else if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
ownKeys(Object(source)).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
}
return target;
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf(subClass, superClass);
}
function _getPrototypeOf(o) {
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf(o);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
function _isNativeReflectConstruct() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _possibleConstructorReturn(self, call) {
if (call && (typeof call === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized(self);
}
function _createSuper(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct();
return function _createSuperInternal() {
var Super = _getPrototypeOf(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn(this, result);
};
}
function _superPropBase(object, property) {
while (!Object.prototype.hasOwnProperty.call(object, property)) {
object = _getPrototypeOf(object);
if (object === null) break;
}
return object;
}
function _get(target, property, receiver) {
if (typeof Reflect !== "undefined" && Reflect.get) {
_get = Reflect.get;
} else {
_get = function _get(target, property, receiver) {
var base = _superPropBase(target, property);
if (!base) return;
var desc = Object.getOwnPropertyDescriptor(base, property);
if (desc.get) {
return desc.get.call(receiver);
}
return desc.value;
};
}
return _get(target, property, receiver || target);
}
function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
}
function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}
function _iterableToArray(iter) {
if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _createForOfIteratorHelper(o, allowArrayLike) {
var it;
if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
if (it) o = it;
var i = 0;
var F = function () {};
return {
s: F,
n: function () {
if (i >= o.length) return {
done: true
};
return {
done: false,
value: o[i++]
};
},
e: function (e) {
throw e;
},
f: F
};
}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var normalCompletion = true,
didErr = false,
err;
return {
s: function () {
it = o[Symbol.iterator]();
},
n: function () {
var step = it.next();
normalCompletion = step.done;
return step;
},
e: function (e) {
didErr = true;
err = e;
},
f: function () {
try {
if (!normalCompletion && it.return != null) it.return();
} finally {
if (didErr) throw err;
}
}
};
}
function ascending (a, b) {
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}
function bisector (compare) {
if (compare.length === 1) compare = ascendingComparator(compare);
return {
left: function left(a, x, lo, hi) {
if (lo == null) lo = 0;
if (hi == null) hi = a.length;
while (lo < hi) {
var mid = lo + hi >>> 1;
if (compare(a[mid], x) < 0) lo = mid + 1;else hi = mid;
}
return lo;
},
right: function right(a, x, lo, hi) {
if (lo == null) lo = 0;
if (hi == null) hi = a.length;
while (lo < hi) {
var mid = lo + hi >>> 1;
if (compare(a[mid], x) > 0) hi = mid;else lo = mid + 1;
}
return lo;
}
};
}
function ascendingComparator(f) {
return function (d, x) {
return ascending(f(d), x);
};
}
var ascendingBisect = bisector(ascending);
var bisectRight = ascendingBisect.right;
function number (x) {
return x === null ? NaN : +x;
}
function variance (values, valueof) {
var n = values.length,
m = 0,
i = -1,
mean = 0,
value,
delta,
sum = 0;
if (valueof == null) {
while (++i < n) {
if (!isNaN(value = number(values[i]))) {
delta = value - mean;
mean += delta / ++m;
sum += delta * (value - mean);
}
}
} else {
while (++i < n) {
if (!isNaN(value = number(valueof(values[i], i, values)))) {
delta = value - mean;
mean += delta / ++m;
sum += delta * (value - mean);
}
}
}
if (m > 1) return sum / (m - 1);
}
function deviation (array, f) {
var v = variance(array, f);
return v ? Math.sqrt(v) : v;
}
function extent (values, valueof) {
var n = values.length,
i = -1,
value,
min,
max;
if (valueof == null) {
while (++i < n) {
// Find the first comparable value.
if ((value = values[i]) != null && value >= value) {
min = max = value;
while (++i < n) {
// Compare the remaining values.
if ((value = values[i]) != null) {
if (min > value) min = value;
if (max < value) max = value;
}
}
}
}
} else {
while (++i < n) {
// Find the first comparable value.
if ((value = valueof(values[i], i, values)) != null && value >= value) {
min = max = value;
while (++i < n) {
// Compare the remaining values.
if ((value = valueof(values[i], i, values)) != null) {
if (min > value) min = value;
if (max < value) max = value;
}
}
}
}
}
return [min, max];
}
function range (start, stop, step) {
start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
var i = -1,
n = Math.max(0, Math.ceil((stop - start) / step)) | 0,
range = new Array(n);
while (++i < n) {
range[i] = start + i * step;
}
return range;
}
var e10 = Math.sqrt(50),
e5 = Math.sqrt(10),
e2 = Math.sqrt(2);
function d3Ticks (start, stop, count) {
var reverse,
i = -1,
n,
ticks,
step;
stop = +stop, start = +start, count = +count;
if (start === stop && count > 0) return [start];
if (reverse = stop < start) n = start, start = stop, stop = n;
if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return [];
if (step > 0) {
start = Math.ceil(start / step);
stop = Math.floor(stop / step);
ticks = new Array(n = Math.ceil(stop - start + 1));
while (++i < n) {
ticks[i] = (start + i) * step;
}
} else {
start = Math.floor(start * step);
stop = Math.ceil(stop * step);
ticks = new Array(n = Math.ceil(start - stop + 1));
while (++i < n) {
ticks[i] = (start - i) / step;
}
}
if (reverse) ticks.reverse();
return ticks;
}
function tickIncrement(start, stop, count) {
var step = (stop - start) / Math.max(0, count),
power = Math.floor(Math.log(step) / Math.LN10),
error = step / Math.pow(10, power);
return power >= 0 ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power) : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1);
}
function tickStep(start, stop, count) {
var step0 = Math.abs(stop - start) / Math.max(0, count),
step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)),
error = step0 / step1;
if (error >= e10) step1 *= 10;else if (error >= e5) step1 *= 5;else if (error >= e2) step1 *= 2;
return stop < start ? -step1 : step1;
}
function quantile (values, p, valueof) {
if (valueof == null) valueof = number;
if (!(n = values.length)) return;
if ((p = +p) <= 0 || n < 2) return +valueof(values[0], 0, values);
if (p >= 1) return +valueof(values[n - 1], n - 1, values);
var n,
i = (n - 1) * p,
i0 = Math.floor(i),
value0 = +valueof(values[i0], i0, values),
value1 = +valueof(values[i0 + 1], i0 + 1, values);
return value0 + (value1 - value0) * (i - i0);
}
function max (values, valueof) {
var n = values.length,
i = -1,
value,
max;
if (valueof == null) {
while (++i < n) {
// Find the first comparable value.
if ((value = values[i]) != null && value >= value) {
max = value;
while (++i < n) {
// Compare the remaining values.
if ((value = values[i]) != null && value > max) {
max = value;
}
}
}
}
} else {
while (++i < n) {
// Find the first comparable value.
if ((value = valueof(values[i], i, values)) != null && value >= value) {
max = value;
while (++i < n) {
// Compare the remaining values.
if ((value = valueof(values[i], i, values)) != null && value > max) {
max = value;
}
}
}
}
}
return max;
}
function arrayMerge (arrays) {
var n = arrays.length,
m,
i = -1,
j = 0,
merged,
array;
while (++i < n) {
j += arrays[i].length;
}
merged = new Array(j);
while (--n >= 0) {
array = arrays[n];
m = array.length;
while (--m >= 0) {
merged[--j] = array[m];
}
}
return merged;
}
function min (values, valueof) {
var n = values.length,
i = -1,
value,
min;
if (valueof == null) {
while (++i < n) {
// Find the first comparable value.
if ((value = values[i]) != null && value >= value) {
min = value;
while (++i < n) {
// Compare the remaining values.
if ((value = values[i]) != null && min > value) {
min = value;
}
}
}
}
} else {
while (++i < n) {
// Find the first comparable value.
if ((value = valueof(values[i], i, values)) != null && value >= value) {
min = value;
while (++i < n) {
// Compare the remaining values.
if ((value = valueof(values[i], i, values)) != null && min > value) {
min = value;
}
}
}
}
}
return min;
}
function sum (values, valueof) {
var n = values.length,
i = -1,
value,
sum = 0;
if (valueof == null) {
while (++i < n) {
if (value = +values[i]) sum += value; // Note: zero and null are equivalent.
}
} else {
while (++i < n) {
if (value = +valueof(values[i], i, values)) sum += value;
}
}
return sum;
}
var pi = Math.PI,
tau = 2 * pi,
epsilon = 1e-6,
tauEpsilon = tau - epsilon;
function Path() {
this._x0 = this._y0 = // start of current subpath
this._x1 = this._y1 = null; // end of current subpath
this._ = "";
}
function path() {
return new Path();
}
Path.prototype = path.prototype = {
constructor: Path,
moveTo: function moveTo(x, y) {
this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y);
},
closePath: function closePath() {
if (this._x1 !== null) {
this._x1 = this._x0, this._y1 = this._y0;
this._ += "Z";
}
},
lineTo: function lineTo(x, y) {
this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y);
},
quadraticCurveTo: function quadraticCurveTo(x1, y1, x, y) {
this._ += "Q" + +x1 + "," + +y1 + "," + (this._x1 = +x) + "," + (this._y1 = +y);
},
bezierCurveTo: function bezierCurveTo(x1, y1, x2, y2, x, y) {
this._ += "C" + +x1 + "," + +y1 + "," + +x2 + "," + +y2 + "," + (this._x1 = +x) + "," + (this._y1 = +y);
},
arcTo: function arcTo(x1, y1, x2, y2, r) {
x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r;
var x0 = this._x1,
y0 = this._y1,
x21 = x2 - x1,
y21 = y2 - y1,
x01 = x0 - x1,
y01 = y0 - y1,
l01_2 = x01 * x01 + y01 * y01; // Is the radius negative? Error.
if (r < 0) throw new Error("negative radius: " + r); // Is this path empty? Move to (x1,y1).
if (this._x1 === null) {
this._ += "M" + (this._x1 = x1) + "," + (this._y1 = y1);
} // Or, is (x1,y1) coincident with (x0,y0)? Do nothing.
else if (!(l01_2 > epsilon)) ; // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear?
// Equivalently, is (x1,y1) coincident with (x2,y2)?
// Or, is the radius zero? Line to (x1,y1).
else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon) || !r) {
this._ += "L" + (this._x1 = x1) + "," + (this._y1 = y1);
} // Otherwise, draw an arc!
else {
var x20 = x2 - x0,
y20 = y2 - y0,
l21_2 = x21 * x21 + y21 * y21,
l20_2 = x20 * x20 + y20 * y20,
l21 = Math.sqrt(l21_2),
l01 = Math.sqrt(l01_2),
l = r * Math.tan((pi - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2),
t01 = l / l01,
t21 = l / l21; // If the start tangent is not coincident with (x0,y0), line to.
if (Math.abs(t01 - 1) > epsilon) {
this._ += "L" + (x1 + t01 * x01) + "," + (y1 + t01 * y01);
}
this._ += "A" + r + "," + r + ",0,0," + +(y01 * x20 > x01 * y20) + "," + (this._x1 = x1 + t21 * x21) + "," + (this._y1 = y1 + t21 * y21);
}
},
arc: function arc(x, y, r, a0, a1, ccw) {
x = +x, y = +y, r = +r;
var dx = r * Math.cos(a0),
dy = r * Math.sin(a0),
x0 = x + dx,
y0 = y + dy,
cw = 1 ^ ccw,
da = ccw ? a0 - a1 : a1 - a0; // Is the radius negative? Error.
if (r < 0) throw new Error("negative radius: " + r); // Is this path empty? Move to (x0,y0).
if (this._x1 === null) {
this._ += "M" + x0 + "," + y0;
} // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0).
else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) {
this._ += "L" + x0 + "," + y0;
} // Is this arc empty? Were done.
if (!r) return; // Does the angle go the wrong way? Flip the direction.
if (da < 0) da = da % tau + tau; // Is this a complete circle? Draw two arcs to complete the circle.
if (da > tauEpsilon) {
this._ += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + (this._x1 = x0) + "," + (this._y1 = y0);
} // Is this arc non-empty? Draw an arc!
else if (da > epsilon) {
this._ += "A" + r + "," + r + ",0," + +(da >= pi) + "," + cw + "," + (this._x1 = x + r * Math.cos(a1)) + "," + (this._y1 = y + r * Math.sin(a1));
}
},
rect: function rect(x, y, w, h) {
this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y) + "h" + +w + "v" + +h + "h" + -w + "Z";
},
toString: function toString() {
return this._;
}
};
function constant (x) {
return function constant() {
return x;
};
}
var abs = Math.abs;
var atan2 = Math.atan2;
var cos = Math.cos;
var max$1 = Math.max;
var min$1 = Math.min;
var sin = Math.sin;
var sqrt = Math.sqrt;
var epsilon$1 = 1e-12;
var pi$1 = Math.PI;
var halfPi = pi$1 / 2;
var tau$1 = 2 * pi$1;
function acos(x) {
return x > 1 ? 0 : x < -1 ? pi$1 : Math.acos(x);
}
function asin(x) {
return x >= 1 ? halfPi : x <= -1 ? -halfPi : Math.asin(x);
}
function arcInnerRadius(d) {
return d.innerRadius;
}
function arcOuterRadius(d) {
return d.outerRadius;
}
function arcStartAngle(d) {
return d.startAngle;
}
function arcEndAngle(d) {
return d.endAngle;
}
function arcPadAngle(d) {
return d && d.padAngle; // Note: optional!
}
function intersect(x0, y0, x1, y1, x2, y2, x3, y3) {
var x10 = x1 - x0,
y10 = y1 - y0,
x32 = x3 - x2,
y32 = y3 - y2,
t = y32 * x10 - x32 * y10;
if (t * t < epsilon$1) return;
t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / t;
return [x0 + t * x10, y0 + t * y10];
} // Compute perpendicular offset line of length rc.
// http://mathworld.wolfram.com/Circle-LineIntersection.html
function cornerTangents(x0, y0, x1, y1, r1, rc, cw) {
var x01 = x0 - x1,
y01 = y0 - y1,
lo = (cw ? rc : -rc) / sqrt(x01 * x01 + y01 * y01),
ox = lo * y01,
oy = -lo * x01,
x11 = x0 + ox,
y11 = y0 + oy,
x10 = x1 + ox,
y10 = y1 + oy,
x00 = (x11 + x10) / 2,
y00 = (y11 + y10) / 2,
dx = x10 - x11,
dy = y10 - y11,
d2 = dx * dx + dy * dy,
r = r1 - rc,
D = x11 * y10 - x10 * y11,
d = (dy < 0 ? -1 : 1) * sqrt(max$1(0, r * r * d2 - D * D)),
cx0 = (D * dy - dx * d) / d2,
cy0 = (-D * dx - dy * d) / d2,
cx1 = (D * dy + dx * d) / d2,
cy1 = (-D * dx + dy * d) / d2,
dx0 = cx0 - x00,
dy0 = cy0 - y00,
dx1 = cx1 - x00,
dy1 = cy1 - y00; // Pick the closer of the two intersection points.
// TODO Is there a faster way to determine which intersection to use?
if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;
return {
cx: cx0,
cy: cy0,
x01: -ox,
y01: -oy,
x11: cx0 * (r1 / r - 1),
y11: cy0 * (r1 / r - 1)
};
}
function arc () {
var innerRadius = arcInnerRadius,
outerRadius = arcOuterRadius,
cornerRadius = constant(0),
padRadius = null,
startAngle = arcStartAngle,
endAngle = arcEndAngle,
padAngle = arcPadAngle,
context = null;
function arc() {
var buffer,
r,
r0 = +innerRadius.apply(this, arguments),
r1 = +outerRadius.apply(this, arguments),
a0 = startAngle.apply(this, arguments) - halfPi,
a1 = endAngle.apply(this, arguments) - halfPi,
da = abs(a1 - a0),
cw = a1 > a0;
if (!context) context = buffer = path(); // Ensure that the outer radius is always larger than the inner radius.
if (r1 < r0) r = r1, r1 = r0, r0 = r; // Is it a point?
if (!(r1 > epsilon$1)) context.moveTo(0, 0); // Or is it a circle or annulus?
else if (da > tau$1 - epsilon$1) {
context.moveTo(r1 * cos(a0), r1 * sin(a0));
context.arc(0, 0, r1, a0, a1, !cw);
if (r0 > epsilon$1) {
context.moveTo(r0 * cos(a1), r0 * sin(a1));
context.arc(0, 0, r0, a1, a0, cw);
}
} // Or is it a circular or annular sector?
else {
var a01 = a0,
a11 = a1,
a00 = a0,
a10 = a1,
da0 = da,
da1 = da,
ap = padAngle.apply(this, arguments) / 2,
rp = ap > epsilon$1 && (padRadius ? +padRadius.apply(this, arguments) : sqrt(r0 * r0 + r1 * r1)),
rc = min$1(abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)),
rc0 = rc,
rc1 = rc,
t0,
t1; // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0.
if (rp > epsilon$1) {
var p0 = asin(rp / r0 * sin(ap)),
p1 = asin(rp / r1 * sin(ap));
if ((da0 -= p0 * 2) > epsilon$1) p0 *= cw ? 1 : -1, a00 += p0, a10 -= p0;else da0 = 0, a00 = a10 = (a0 + a1) / 2;
if ((da1 -= p1 * 2) > epsilon$1) p1 *= cw ? 1 : -1, a01 += p1, a11 -= p1;else da1 = 0, a01 = a11 = (a0 + a1) / 2;
}
var x01 = r1 * cos(a01),
y01 = r1 * sin(a01),
x10 = r0 * cos(a10),
y10 = r0 * sin(a10); // Apply rounded corners?
if (rc > epsilon$1) {
var x11 = r1 * cos(a11),
y11 = r1 * sin(a11),
x00 = r0 * cos(a00),
y00 = r0 * sin(a00),
oc; // Restrict the corner radius according to the sector angle.
if (da < pi$1 && (oc = intersect(x01, y01, x00, y00, x11, y11, x10, y10))) {
var ax = x01 - oc[0],
ay = y01 - oc[1],
bx = x11 - oc[0],
by = y11 - oc[1],
kc = 1 / sin(acos((ax * bx + ay * by) / (sqrt(ax * ax + ay * ay) * sqrt(bx * bx + by * by))) / 2),
lc = sqrt(oc[0] * oc[0] + oc[1] * oc[1]);
rc0 = min$1(rc, (r0 - lc) / (kc - 1));
rc1 = min$1(rc, (r1 - lc) / (kc + 1));
}
} // Is the sector collapsed to a line?
if (!(da1 > epsilon$1)) context.moveTo(x01, y01); // Does the sectors outer ring have rounded corners?
else if (rc1 > epsilon$1) {
t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw);
t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw);
context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01); // Have the corners merged?
if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, atan2(t0.y01, t0.x01), atan2(t1.y01, t1.x01), !cw); // Otherwise, draw the two corners and the ring.
else {
context.arc(t0.cx, t0.cy, rc1, atan2(t0.y01, t0.x01), atan2(t0.y11, t0.x11), !cw);
context.arc(0, 0, r1, atan2(t0.cy + t0.y11, t0.cx + t0.x11), atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw);
context.arc(t1.cx, t1.cy, rc1, atan2(t1.y11, t1.x11), atan2(t1.y01, t1.x01), !cw);
}
} // Or is the outer ring just a circular arc?
else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw); // Is there no inner ring, and its a circular sector?
// Or perhaps its an annular sector collapsed due to padding?
if (!(r0 > epsilon$1) || !(da0 > epsilon$1)) context.lineTo(x10, y10); // Does the sectors inner ring (or point) have rounded corners?
else if (rc0 > epsilon$1) {
t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw);
t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw);
context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01); // Have the corners merged?
if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, atan2(t0.y01, t0.x01), atan2(t1.y01, t1.x01), !cw); // Otherwise, draw the two corners and the ring.
else {
context.arc(t0.cx, t0.cy, rc0, atan2(t0.y01, t0.x01), atan2(t0.y11, t0.x11), !cw);
context.arc(0, 0, r0, atan2(t0.cy + t0.y11, t0.cx + t0.x11), atan2(t1.cy + t1.y11, t1.cx + t1.x11), cw);
context.arc(t1.cx, t1.cy, rc0, atan2(t1.y11, t1.x11), atan2(t1.y01, t1.x01), !cw);
}
} // Or is the inner ring just a circular arc?
else context.arc(0, 0, r0, a10, a00, cw);
}
context.closePath();
if (buffer) return context = null, buffer + "" || null;
}
arc.centroid = function () {
var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2,
a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi$1 / 2;
return [cos(a) * r, sin(a) * r];
};
arc.innerRadius = function (_) {
return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant(+_), arc) : innerRadius;
};
arc.outerRadius = function (_) {
return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant(+_), arc) : outerRadius;
};
arc.cornerRadius = function (_) {
return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant(+_), arc) : cornerRadius;
};
arc.padRadius = function (_) {
return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant(+_), arc) : padRadius;
};
arc.startAngle = function (_) {
return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), arc) : startAngle;
};
arc.endAngle = function (_) {
return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), arc) : endAngle;
};
arc.padAngle = function (_) {
return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant(+_), arc) : padAngle;
};
arc.context = function (_) {
return arguments.length ? (context = _ == null ? null : _, arc) : context;
};
return arc;
}
function Linear(context) {
this._context = context;
}
Linear.prototype = {
areaStart: function areaStart() {
this._line = 0;
},
areaEnd: function areaEnd() {
this._line = NaN;
},
lineStart: function lineStart() {
this._point = 0;
},
lineEnd: function lineEnd() {
if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();
this._line = 1 - this._line;
},
point: function point(x, y) {
x = +x, y = +y;
switch (this._point) {
case 0:
this._point = 1;
this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y);
break;
case 1:
this._point = 2;
// proceed
default:
this._context.lineTo(x, y);
break;
}
}
};
function curveLinear (context) {
return new Linear(context);
}
function x(p) {
return p[0];
}
function y(p) {
return p[1];
}
function line () {
var x$1 = x,
y$1 = y,
defined = constant(true),
context = null,
curve = curveLinear,
output = null;
function line(data) {
var i,
n = data.length,
d,
defined0 = false,
buffer;
if (context == null) output = curve(buffer = path());
for (i = 0; i <= n; ++i) {
if (!(i < n && defined(d = data[i], i, data)) === defined0) {
if (defined0 = !defined0) output.lineStart();else output.lineEnd();
}
if (defined0) output.point(+x$1(d, i, data), +y$1(d, i, data));
}
if (buffer) return output = null, buffer + "" || null;
}
line.x = function (_) {
return arguments.length ? (x$1 = typeof _ === "function" ? _ : constant(+_), line) : x$1;
};
line.y = function (_) {
return arguments.length ? (y$1 = typeof _ === "function" ? _ : constant(+_), line) : y$1;
};
line.defined = function (_) {
return arguments.length ? (defined = typeof _ === "function" ? _ : constant(!!_), line) : defined;
};
line.curve = function (_) {
return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve;
};
line.context = function (_) {
return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context;
};
return line;
}
function area () {
var x0 = x,
x1 = null,
y0 = constant(0),
y1 = y,
defined = constant(true),
context = null,
curve = curveLinear,
output = null;
function area(data) {
var i,
j,
k,
n = data.length,
d,
defined0 = false,
buffer,
x0z = new Array(n),
y0z = new Array(n);
if (context == null) output = curve(buffer = path());
for (i = 0; i <= n; ++i) {
if (!(i < n && defined(d = data[i], i, data)) === defined0) {
if (defined0 = !defined0) {
j = i;
output.areaStart();
output.lineStart();
} else {
output.lineEnd();
output.lineStart();
for (k = i - 1; k >= j; --k) {
output.point(x0z[k], y0z[k]);
}
output.lineEnd();
output.areaEnd();
}
}
if (defined0) {
x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data);
output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]);
}
}
if (buffer) return output = null, buffer + "" || null;
}
function arealine() {
return line().defined(defined).curve(curve).context(context);
}
area.x = function (_) {
return arguments.length ? (x0 = typeof _ === "function" ? _ : constant(+_), x1 = null, area) : x0;
};
area.x0 = function (_) {
return arguments.length ? (x0 = typeof _ === "function" ? _ : constant(+_), area) : x0;
};
area.x1 = function (_) {
return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant(+_), area) : x1;
};
area.y = function (_) {
return arguments.length ? (y0 = typeof _ === "function" ? _ : constant(+_), y1 = null, area) : y0;
};
area.y0 = function (_) {
return arguments.length ? (y0 = typeof _ === "function" ? _ : constant(+_), area) : y0;
};
area.y1 = function (_) {
return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant(+_), area) : y1;
};
area.lineX0 = area.lineY0 = function () {
return arealine().x(x0).y(y0);
};
area.lineY1 = function () {
return arealine().x(x0).y(y1);
};
area.lineX1 = function () {
return arealine().x(x1).y(y0);
};
area.defined = function (_) {
return arguments.length ? (defined = typeof _ === "function" ? _ : constant(!!_), area) : defined;
};
area.curve = function (_) {
return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve;
};
area.context = function (_) {
return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context;
};
return area;
}
function descending (a, b) {
return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
}
function identity (d) {
return d;
}
function pie () {
var value = identity,
sortValues = descending,
sort = null,
startAngle = constant(0),
endAngle = constant(tau$1),
padAngle = constant(0);
function pie(data) {
var i,
n = data.length,
j,
k,
sum = 0,
index = new Array(n),
arcs = new Array(n),
a0 = +startAngle.apply(this, arguments),
da = Math.min(tau$1, Math.max(-tau$1, endAngle.apply(this, arguments) - a0)),
a1,
p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)),
pa = p * (da < 0 ? -1 : 1),
v;
for (i = 0; i < n; ++i) {
if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) {
sum += v;
}
} // Optionally sort the arcs by previously-computed values or by data.
if (sortValues != null) index.sort(function (i, j) {
return sortValues(arcs[i], arcs[j]);
});else if (sort != null) index.sort(function (i, j) {
return sort(data[i], data[j]);
}); // Compute the arcs! They are stored in the original data's order.
for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) {
j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = {
data: data[j],
index: i,
value: v,
startAngle: a0,
endAngle: a1,
padAngle: p
};
}
return arcs;
}
pie.value = function (_) {
return arguments.length ? (value = typeof _ === "function" ? _ : constant(+_), pie) : value;
};
pie.sortValues = function (_) {
return arguments.length ? (sortValues = _, sort = null, pie) : sortValues;
};
pie.sort = function (_) {
return arguments.length ? (sort = _, sortValues = null, pie) : sort;
};
pie.startAngle = function (_) {
return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), pie) : startAngle;
};
pie.endAngle = function (_) {
return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), pie) : endAngle;
};
pie.padAngle = function (_) {
return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant(+_), pie) : padAngle;
};
return pie;
}
var curveRadialLinear = curveRadial(curveLinear);
function Radial(curve) {
this._curve = curve;
}
Radial.prototype = {
areaStart: function areaStart() {
this._curve.areaStart();
},
areaEnd: function areaEnd() {
this._curve.areaEnd();
},
lineStart: function lineStart() {
this._curve.lineStart();
},
lineEnd: function lineEnd() {
this._curve.lineEnd();
},
point: function point(a, r) {
this._curve.point(r * Math.sin(a), r * -Math.cos(a));
}
};
function curveRadial(curve) {
function radial(context) {
return new Radial(curve(context));
}
radial._curve = curve;
return radial;
}
function lineRadial(l) {
var c = l.curve;
l.angle = l.x, delete l.x;
l.radius = l.y, delete l.y;
l.curve = function (_) {
return arguments.length ? c(curveRadial(_)) : c()._curve;
};
return l;
}
function lineRadial$1 () {
return lineRadial(line().curve(curveRadialLinear));
}
function areaRadial () {
var a = area().curve(curveRadialLinear),
c = a.curve,
x0 = a.lineX0,
x1 = a.lineX1,
y0 = a.lineY0,
y1 = a.lineY1;
a.angle = a.x, delete a.x;
a.startAngle = a.x0, delete a.x0;
a.endAngle = a.x1, delete a.x1;
a.radius = a.y, delete a.y;
a.innerRadius = a.y0, delete a.y0;
a.outerRadius = a.y1, delete a.y1;
a.lineStartAngle = function () {
return lineRadial(x0());
}, delete a.lineX0;
a.lineEndAngle = function () {
return lineRadial(x1());
}, delete a.lineX1;
a.lineInnerRadius = function () {
return lineRadial(y0());
}, delete a.lineY0;
a.lineOuterRadius = function () {
return lineRadial(y1());
}, delete a.lineY1;
a.curve = function (_) {
return arguments.length ? c(curveRadial(_)) : c()._curve;
};
return a;
}
function pointRadial (x, y) {
return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)];
}
var slice = Array.prototype.slice;
function linkSource(d) {
return d.source;
}
function linkTarget(d) {
return d.target;
}
function link(curve) {
var source = linkSource,
target = linkTarget,
x$1 = x,
y$1 = y,
context = null;
function link() {
var buffer,
argv = slice.call(arguments),
s = source.apply(this, argv),
t = target.apply(this, argv);
if (!context) context = buffer = path();
curve(context, +x$1.apply(this, (argv[0] = s, argv)), +y$1.apply(this, argv), +x$1.apply(this, (argv[0] = t, argv)), +y$1.apply(this, argv));
if (buffer) return context = null, buffer + "" || null;
}
link.source = function (_) {
return arguments.length ? (source = _, link) : source;
};
link.target = function (_) {
return arguments.length ? (target = _, link) : target;
};
link.x = function (_) {
return arguments.length ? (x$1 = typeof _ === "function" ? _ : constant(+_), link) : x$1;
};
link.y = function (_) {
return arguments.length ? (y$1 = typeof _ === "function" ? _ : constant(+_), link) : y$1;
};
link.context = function (_) {
return arguments.length ? (context = _ == null ? null : _, link) : context;
};
return link;
}
function curveHorizontal(context, x0, y0, x1, y1) {
context.moveTo(x0, y0);
context.bezierCurveTo(x0 = (x0 + x1) / 2, y0, x0, y1, x1, y1);
}
function curveVertical(context, x0, y0, x1, y1) {
context.moveTo(x0, y0);
context.bezierCurveTo(x0, y0 = (y0 + y1) / 2, x1, y0, x1, y1);
}
function curveRadial$1(context, x0, y0, x1, y1) {
var p0 = pointRadial(x0, y0),
p1 = pointRadial(x0, y0 = (y0 + y1) / 2),
p2 = pointRadial(x1, y0),
p3 = pointRadial(x1, y1);
context.moveTo(p0[0], p0[1]);
context.bezierCurveTo(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]);
}
function linkHorizontal() {
return link(curveHorizontal);
}
function linkVertical() {
return link(curveVertical);
}
function linkRadial() {
var l = link(curveRadial$1);
l.angle = l.x, delete l.x;
l.radius = l.y, delete l.y;
return l;
}
var circle = {
draw: function draw(context, size) {
var r = Math.sqrt(size / pi$1);
context.moveTo(r, 0);
context.arc(0, 0, r, 0, tau$1);
}
};
var cross = {
draw: function draw(context, size) {
var r = Math.sqrt(size / 5) / 2;
context.moveTo(-3 * r, -r);
context.lineTo(-r, -r);
context.lineTo(-r, -3 * r);
context.lineTo(r, -3 * r);
context.lineTo(r, -r);
context.lineTo(3 * r, -r);
context.lineTo(3 * r, r);
context.lineTo(r, r);
context.lineTo(r, 3 * r);
context.lineTo(-r, 3 * r);
context.lineTo(-r, r);
context.lineTo(-3 * r, r);
context.closePath();
}
};
var tan30 = Math.sqrt(1 / 3),
tan30_2 = tan30 * 2;
var diamond = {
draw: function draw(context, size) {
var y = Math.sqrt(size / tan30_2),
x = y * tan30;
context.moveTo(0, -y);
context.lineTo(x, 0);
context.lineTo(0, y);
context.lineTo(-x, 0);
context.closePath();
}
};
var ka = 0.89081309152928522810,
kr = Math.sin(pi$1 / 10) / Math.sin(7 * pi$1 / 10),
kx = Math.sin(tau$1 / 10) * kr,
ky = -Math.cos(tau$1 / 10) * kr;
var star = {
draw: function draw(context, size) {
var r = Math.sqrt(size * ka),
x = kx * r,
y = ky * r;
context.moveTo(0, -r);
context.lineTo(x, y);
for (var i = 1; i < 5; ++i) {
var a = tau$1 * i / 5,
c = Math.cos(a),
s = Math.sin(a);
context.lineTo(s * r, -c * r);
context.lineTo(c * x - s * y, s * x + c * y);
}
context.closePath();
}
};
var square = {
draw: function draw(context, size) {
var w = Math.sqrt(size),
x = -w / 2;
context.rect(x, x, w, w);
}
};
var sqrt3 = Math.sqrt(3);
var triangle = {
draw: function draw(context, size) {
var y = -Math.sqrt(size / (sqrt3 * 3));
context.moveTo(0, y * 2);
context.lineTo(-sqrt3 * y, -y);
context.lineTo(sqrt3 * y, -y);
context.closePath();
}
};
var c = -0.5,
s = Math.sqrt(3) / 2,
k = 1 / Math.sqrt(12),
a = (k / 2 + 1) * 3;
var wye = {
draw: function draw(context, size) {
var r = Math.sqrt(size / a),
x0 = r / 2,
y0 = r * k,
x1 = x0,
y1 = r * k + r,
x2 = -x1,
y2 = y1;
context.moveTo(x0, y0);
context.lineTo(x1, y1);
context.lineTo(x2, y2);
context.lineTo(c * x0 - s * y0, s * x0 + c * y0);
context.lineTo(c * x1 - s * y1, s * x1 + c * y1);
context.lineTo(c * x2 - s * y2, s * x2 + c * y2);
context.lineTo(c * x0 + s * y0, c * y0 - s * x0);
context.lineTo(c * x1 + s * y1, c * y1 - s * x1);
context.lineTo(c * x2 + s * y2, c * y2 - s * x2);
context.closePath();
}
};
var symbols = [circle, cross, diamond, square, star, triangle, wye];
function symbol () {
var type = constant(circle),
size = constant(64),
context = null;
function symbol() {
var buffer;
if (!context) context = buffer = path();
type.apply(this, arguments).draw(context, +size.apply(this, arguments));
if (buffer) return context = null, buffer + "" || null;
}
symbol.type = function (_) {
return arguments.length ? (type = typeof _ === "function" ? _ : constant(_), symbol) : type;
};
symbol.size = function (_) {
return arguments.length ? (size = typeof _ === "function" ? _ : constant(+_), symbol) : size;
};
symbol.context = function (_) {
return arguments.length ? (context = _ == null ? null : _, symbol) : context;
};
return symbol;
}
function noop () {}
function _point(that, x, y) {
that._context.bezierCurveTo((2 * that._x0 + that._x1) / 3, (2 * that._y0 + that._y1) / 3, (that._x0 + 2 * that._x1) / 3, (that._y0 + 2 * that._y1) / 3, (that._x0 + 4 * that._x1 + x) / 6, (that._y0 + 4 * that._y1 + y) / 6);
}
function Basis(context) {
this._context = context;
}
Basis.prototype = {
areaStart: function areaStart() {
this._line = 0;
},
areaEnd: function areaEnd() {
this._line = NaN;
},
lineStart: function lineStart() {
this._x0 = this._x1 = this._y0 = this._y1 = NaN;
this._point = 0;
},
lineEnd: function lineEnd() {
switch (this._point) {
case 3:
_point(this, this._x1, this._y1);
// proceed
case 2:
this._context.lineTo(this._x1, this._y1);
break;
}
if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();
this._line = 1 - this._line;
},
point: function point(x, y) {
x = +x, y = +y;
switch (this._point) {
case 0:
this._point = 1;
this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y);
break;
case 1:
this._point = 2;
break;
case 2:
this._point = 3;
this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6);
// proceed
default:
_point(this, x, y);
break;
}
this._x0 = this._x1, this._x1 = x;
this._y0 = this._y1, this._y1 = y;
}
};
function basis (context) {
return new Basis(context);
}
function BasisClosed(context) {
this._context = context;
}
BasisClosed.prototype = {
areaStart: noop,
areaEnd: noop,
lineStart: function lineStart() {
this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN;
this._point = 0;
},
lineEnd: function lineEnd() {
switch (this._point) {
case 1:
{
this._context.moveTo(this._x2, this._y2);
this._context.closePath();
break;
}
case 2:
{
this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3);
this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3);
this._context.closePath();
break;
}
case 3:
{
this.point(this._x2, this._y2);
this.point(this._x3, this._y3);
this.point(this._x4, this._y4);
break;
}
}
},
point: function point(x, y) {
x = +x, y = +y;
switch (this._point) {
case 0:
this._point = 1;
this._x2 = x, this._y2 = y;
break;
case 1:
this._point = 2;
this._x3 = x, this._y3 = y;
break;
case 2:
this._point = 3;
this._x4 = x, this._y4 = y;
this._context.moveTo((this._x0 + 4 * this._x1 + x) / 6, (this._y0 + 4 * this._y1 + y) / 6);
break;
default:
_point(this, x, y);
break;
}
this._x0 = this._x1, this._x1 = x;
this._y0 = this._y1, this._y1 = y;
}
};
function basisClosed (context) {
return new BasisClosed(context);
}
function BasisOpen(context) {
this._context = context;
}
BasisOpen.prototype = {
areaStart: function areaStart() {
this._line = 0;
},
areaEnd: function areaEnd() {
this._line = NaN;
},
lineStart: function lineStart() {
this._x0 = this._x1 = this._y0 = this._y1 = NaN;
this._point = 0;
},
lineEnd: function lineEnd() {
if (this._line || this._line !== 0 && this._point === 3) this._context.closePath();
this._line = 1 - this._line;
},
point: function point(x, y) {
x = +x, y = +y;
switch (this._point) {
case 0:
this._point = 1;
break;
case 1:
this._point = 2;
break;
case 2:
this._point = 3;
var x0 = (this._x0 + 4 * this._x1 + x) / 6,
y0 = (this._y0 + 4 * this._y1 + y) / 6;
this._line ? this._context.lineTo(x0, y0) : this._context.moveTo(x0, y0);
break;
case 3:
this._point = 4;
// proceed
default:
_point(this, x, y);
break;
}
this._x0 = this._x1, this._x1 = x;
this._y0 = this._y1, this._y1 = y;
}
};
function basisOpen (context) {
return new BasisOpen(context);
}
function Bundle(context, beta) {
this._basis = new Basis(context);
this._beta = beta;
}
Bundle.prototype = {
lineStart: function lineStart() {
this._x = [];
this._y = [];
this._basis.lineStart();
},
lineEnd: function lineEnd() {
var x = this._x,
y = this._y,
j = x.length - 1;
if (j > 0) {
var x0 = x[0],
y0 = y[0],
dx = x[j] - x0,
dy = y[j] - y0,
i = -1,
t;
while (++i <= j) {
t = i / j;
this._basis.point(this._beta * x[i] + (1 - this._beta) * (x0 + t * dx), this._beta * y[i] + (1 - this._beta) * (y0 + t * dy));
}
}
this._x = this._y = null;
this._basis.lineEnd();
},
point: function point(x, y) {
this._x.push(+x);
this._y.push(+y);
}
};
var bundle = (function custom(beta) {
function bundle(context) {
return beta === 1 ? new Basis(context) : new Bundle(context, beta);
}
bundle.beta = function (beta) {
return custom(+beta);
};
return bundle;
})(0.85);
function _point$1(that, x, y) {
that._context.bezierCurveTo(that._x1 + that._k * (that._x2 - that._x0), that._y1 + that._k * (that._y2 - that._y0), that._x2 + that._k * (that._x1 - x), that._y2 + that._k * (that._y1 - y), that._x2, that._y2);
}
function Cardinal(context, tension) {
this._context = context;
this._k = (1 - tension) / 6;
}
Cardinal.prototype = {
areaStart: function areaStart() {
this._line = 0;
},
areaEnd: function areaEnd() {
this._line = NaN;
},
lineStart: function lineStart() {
this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN;
this._point = 0;
},
lineEnd: function lineEnd() {
switch (this._point) {
case 2:
this._context.lineTo(this._x2, this._y2);
break;
case 3:
_point$1(this, this._x1, this._y1);
break;
}
if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();
this._line = 1 - this._line;
},
point: function point(x, y) {
x = +x, y = +y;
switch (this._point) {
case 0:
this._point = 1;
this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y);
break;
case 1:
this._point = 2;
this._x1 = x, this._y1 = y;
break;
case 2:
this._point = 3;
// proceed
default:
_point$1(this, x, y);
break;
}
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
}
};
var cardinal = (function custom(tension) {
function cardinal(context) {
return new Cardinal(context, tension);
}
cardinal.tension = function (tension) {
return custom(+tension);
};
return cardinal;
})(0);
function CardinalClosed(context, tension) {
this._context = context;
this._k = (1 - tension) / 6;
}
CardinalClosed.prototype = {
areaStart: noop,
areaEnd: noop,
lineStart: function lineStart() {
this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
this._point = 0;
},
lineEnd: function lineEnd() {
switch (this._point) {
case 1:
{
this._context.moveTo(this._x3, this._y3);
this._context.closePath();
break;
}
case 2:
{
this._context.lineTo(this._x3, this._y3);
this._context.closePath();
break;
}
case 3:
{
this.point(this._x3, this._y3);
this.point(this._x4, this._y4);
this.point(this._x5, this._y5);
break;
}
}
},
point: function point(x, y) {
x = +x, y = +y;
switch (this._point) {
case 0:
this._point = 1;
this._x3 = x, this._y3 = y;
break;
case 1:
this._point = 2;
this._context.moveTo(this._x4 = x, this._y4 = y);
break;
case 2:
this._point = 3;
this._x5 = x, this._y5 = y;
break;
default:
_point$1(this, x, y);
break;
}
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
}
};
var cardinalClosed = (function custom(tension) {
function cardinal(context) {
return new CardinalClosed(context, tension);
}
cardinal.tension = function (tension) {
return custom(+tension);
};
return cardinal;
})(0);
function CardinalOpen(context, tension) {
this._context = context;
this._k = (1 - tension) / 6;
}
CardinalOpen.prototype = {
areaStart: function areaStart() {
this._line = 0;
},
areaEnd: function areaEnd() {
this._line = NaN;
},
lineStart: function lineStart() {
this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN;
this._point = 0;
},
lineEnd: function lineEnd() {
if (this._line || this._line !== 0 && this._point === 3) this._context.closePath();
this._line = 1 - this._line;
},
point: function point(x, y) {
x = +x, y = +y;
switch (this._point) {
case 0:
this._point = 1;
break;
case 1:
this._point = 2;
break;
case 2:
this._point = 3;
this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2);
break;
case 3:
this._point = 4;
// proceed
default:
_point$1(this, x, y);
break;
}
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
}
};
var cardinalOpen = (function custom(tension) {
function cardinal(context) {
return new CardinalOpen(context, tension);
}
cardinal.tension = function (tension) {
return custom(+tension);
};
return cardinal;
})(0);
function _point$2(that, x, y) {
var x1 = that._x1,
y1 = that._y1,
x2 = that._x2,
y2 = that._y2;
if (that._l01_a > epsilon$1) {
var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a,
n = 3 * that._l01_a * (that._l01_a + that._l12_a);
x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n;
y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n;
}
if (that._l23_a > epsilon$1) {
var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a,
m = 3 * that._l23_a * (that._l23_a + that._l12_a);
x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m;
y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m;
}
that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2);
}
function CatmullRom(context, alpha) {
this._context = context;
this._alpha = alpha;
}
CatmullRom.prototype = {
areaStart: function areaStart() {
this._line = 0;
},
areaEnd: function areaEnd() {
this._line = NaN;
},
lineStart: function lineStart() {
this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN;
this._l01_a = this._l12_a = this._l23_a = this._l01_2a = this._l12_2a = this._l23_2a = this._point = 0;
},
lineEnd: function lineEnd() {
switch (this._point) {
case 2:
this._context.lineTo(this._x2, this._y2);
break;
case 3:
this.point(this._x2, this._y2);
break;
}
if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();
this._line = 1 - this._line;
},
point: function point(x, y) {
x = +x, y = +y;
if (this._point) {
var x23 = this._x2 - x,
y23 = this._y2 - y;
this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
}
switch (this._point) {
case 0:
this._point = 1;
this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y);
break;
case 1:
this._point = 2;
break;
case 2:
this._point = 3;
// proceed
default:
_point$2(this, x, y);
break;
}
this._l01_a = this._l12_a, this._l12_a = this._l23_a;
this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
}
};
var catmullRom = (function custom(alpha) {
function catmullRom(context) {
return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0);
}
catmullRom.alpha = function (alpha) {
return custom(+alpha);
};
return catmullRom;
})(0.5);
function CatmullRomClosed(context, alpha) {
this._context = context;
this._alpha = alpha;
}
CatmullRomClosed.prototype = {
areaStart: noop,
areaEnd: noop,
lineStart: function lineStart() {
this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
this._l01_a = this._l12_a = this._l23_a = this._l01_2a = this._l12_2a = this._l23_2a = this._point = 0;
},
lineEnd: function lineEnd() {
switch (this._point) {
case 1:
{
this._context.moveTo(this._x3, this._y3);
this._context.closePath();
break;
}
case 2:
{
this._context.lineTo(this._x3, this._y3);
this._context.closePath();
break;
}
case 3:
{
this.point(this._x3, this._y3);
this.point(this._x4, this._y4);
this.point(this._x5, this._y5);
break;
}
}
},
point: function point(x, y) {
x = +x, y = +y;
if (this._point) {
var x23 = this._x2 - x,
y23 = this._y2 - y;
this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
}
switch (this._point) {
case 0:
this._point = 1;
this._x3 = x, this._y3 = y;
break;
case 1:
this._point = 2;
this._context.moveTo(this._x4 = x, this._y4 = y);
break;
case 2:
this._point = 3;
this._x5 = x, this._y5 = y;
break;
default:
_point$2(this, x, y);
break;
}
this._l01_a = this._l12_a, this._l12_a = this._l23_a;
this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
}
};
var catmullRomClosed = (function custom(alpha) {
function catmullRom(context) {
return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0);
}
catmullRom.alpha = function (alpha) {
return custom(+alpha);
};
return catmullRom;
})(0.5);
function CatmullRomOpen(context, alpha) {
this._context = context;
this._alpha = alpha;
}
CatmullRomOpen.prototype = {
areaStart: function areaStart() {
this._line = 0;
},
areaEnd: function areaEnd() {
this._line = NaN;
},
lineStart: function lineStart() {
this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN;
this._l01_a = this._l12_a = this._l23_a = this._l01_2a = this._l12_2a = this._l23_2a = this._point = 0;
},
lineEnd: function lineEnd() {
if (this._line || this._line !== 0 && this._point === 3) this._context.closePath();
this._line = 1 - this._line;
},
point: function point(x, y) {
x = +x, y = +y;
if (this._point) {
var x23 = this._x2 - x,
y23 = this._y2 - y;
this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
}
switch (this._point) {
case 0:
this._point = 1;
break;
case 1:
this._point = 2;
break;
case 2:
this._point = 3;
this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2);
break;
case 3:
this._point = 4;
// proceed
default:
_point$2(this, x, y);
break;
}
this._l01_a = this._l12_a, this._l12_a = this._l23_a;
this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
}
};
var catmullRomOpen = (function custom(alpha) {
function catmullRom(context) {
return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0);
}
catmullRom.alpha = function (alpha) {
return custom(+alpha);
};
return catmullRom;
})(0.5);
function LinearClosed(context) {
this._context = context;
}
LinearClosed.prototype = {
areaStart: noop,
areaEnd: noop,
lineStart: function lineStart() {
this._point = 0;
},
lineEnd: function lineEnd() {
if (this._point) this._context.closePath();
},
point: function point(x, y) {
x = +x, y = +y;
if (this._point) this._context.lineTo(x, y);else this._point = 1, this._context.moveTo(x, y);
}
};
function linearClosed (context) {
return new LinearClosed(context);
}
function sign(x) {
return x < 0 ? -1 : 1;
} // Calculate the slopes of the tangents (Hermite-type interpolation) based on
// the following paper: Steffen, M. 1990. A Simple Method for Monotonic
// Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO.
// NOV(II), P. 443, 1990.
function slope3(that, x2, y2) {
var h0 = that._x1 - that._x0,
h1 = x2 - that._x1,
s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0),
s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0),
p = (s0 * h1 + s1 * h0) / (h0 + h1);
return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0;
} // Calculate a one-sided slope.
function slope2(that, t) {
var h = that._x1 - that._x0;
return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t;
} // According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations
// "you can express cubic Hermite interpolation in terms of cubic Bézier curves
// with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1".
function _point$3(that, t0, t1) {
var x0 = that._x0,
y0 = that._y0,
x1 = that._x1,
y1 = that._y1,
dx = (x1 - x0) / 3;
that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1);
}
function MonotoneX(context) {
this._context = context;
}
MonotoneX.prototype = {
areaStart: function areaStart() {
this._line = 0;
},
areaEnd: function areaEnd() {
this._line = NaN;
},
lineStart: function lineStart() {
this._x0 = this._x1 = this._y0 = this._y1 = this._t0 = NaN;
this._point = 0;
},
lineEnd: function lineEnd() {
switch (this._point) {
case 2:
this._context.lineTo(this._x1, this._y1);
break;
case 3:
_point$3(this, this._t0, slope2(this, this._t0));
break;
}
if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();
this._line = 1 - this._line;
},
point: function point(x, y) {
var t1 = NaN;
x = +x, y = +y;
if (x === this._x1 && y === this._y1) return; // Ignore coincident points.
switch (this._point) {
case 0:
this._point = 1;
this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y);
break;
case 1:
this._point = 2;
break;
case 2:
this._point = 3;
_point$3(this, slope2(this, t1 = slope3(this, x, y)), t1);
break;
default:
_point$3(this, this._t0, t1 = slope3(this, x, y));
break;
}
this._x0 = this._x1, this._x1 = x;
this._y0 = this._y1, this._y1 = y;
this._t0 = t1;
}
};
function MonotoneY(context) {
this._context = new ReflectContext(context);
}
(MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function (x, y) {
MonotoneX.prototype.point.call(this, y, x);
};
function ReflectContext(context) {
this._context = context;
}
ReflectContext.prototype = {
moveTo: function moveTo(x, y) {
this._context.moveTo(y, x);
},
closePath: function closePath() {
this._context.closePath();
},
lineTo: function lineTo(x, y) {
this._context.lineTo(y, x);
},
bezierCurveTo: function bezierCurveTo(x1, y1, x2, y2, x, y) {
this._context.bezierCurveTo(y1, x1, y2, x2, y, x);
}
};
function monotoneX(context) {
return new MonotoneX(context);
}
function monotoneY(context) {
return new MonotoneY(context);
}
function Natural(context) {
this._context = context;
}
Natural.prototype = {
areaStart: function areaStart() {
this._line = 0;
},
areaEnd: function areaEnd() {
this._line = NaN;
},
lineStart: function lineStart() {
this._x = [];
this._y = [];
},
lineEnd: function lineEnd() {
var x = this._x,
y = this._y,
n = x.length;
if (n) {
this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]);
if (n === 2) {
this._context.lineTo(x[1], y[1]);
} else {
var px = controlPoints(x),
py = controlPoints(y);
for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) {
this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]);
}
}
}
if (this._line || this._line !== 0 && n === 1) this._context.closePath();
this._line = 1 - this._line;
this._x = this._y = null;
},
point: function point(x, y) {
this._x.push(+x);
this._y.push(+y);
}
}; // See https://www.particleincell.com/2012/bezier-splines/ for derivation.
function controlPoints(x) {
var i,
n = x.length - 1,
m,
a = new Array(n),
b = new Array(n),
r = new Array(n);
a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1];
for (i = 1; i < n - 1; ++i) {
a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1];
}
a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n];
for (i = 1; i < n; ++i) {
m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1];
}
a[n - 1] = r[n - 1] / b[n - 1];
for (i = n - 2; i >= 0; --i) {
a[i] = (r[i] - a[i + 1]) / b[i];
}
b[n - 1] = (x[n] + a[n - 1]) / 2;
for (i = 0; i < n - 1; ++i) {
b[i] = 2 * x[i + 1] - a[i + 1];
}
return [a, b];
}
function natural (context) {
return new Natural(context);
}
function Step(context, t) {
this._context = context;
this._t = t;
}
Step.prototype = {
areaStart: function areaStart() {
this._line = 0;
},
areaEnd: function areaEnd() {
this._line = NaN;
},
lineStart: function lineStart() {
this._x = this._y = NaN;
this._point = 0;
},
lineEnd: function lineEnd() {
if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);
if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();
if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line;
},
point: function point(x, y) {
x = +x, y = +y;
switch (this._point) {
case 0:
this._point = 1;
this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y);
break;
case 1:
this._point = 2;
// proceed
default:
{
if (this._t <= 0) {
this._context.lineTo(this._x, y);
this._context.lineTo(x, y);
} else {
var x1 = this._x * (1 - this._t) + x * this._t;
this._context.lineTo(x1, this._y);
this._context.lineTo(x1, y);
}
break;
}
}
this._x = x, this._y = y;
}
};
function step (context) {
return new Step(context, 0.5);
}
function stepBefore(context) {
return new Step(context, 0);
}
function stepAfter(context) {
return new Step(context, 1);
}
function none (series, order) {
if (!((n = series.length) > 1)) return;
for (var i = 1, j, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) {
s0 = s1, s1 = series[order[i]];
for (j = 0; j < m; ++j) {
s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1];
}
}
}
function none$1 (series) {
var n = series.length,
o = new Array(n);
while (--n >= 0) {
o[n] = n;
}
return o;
}
function stackValue(d, key) {
return d[key];
}
function stack () {
var keys = constant([]),
order = none$1,
offset = none,
value = stackValue;
function stack(data) {
var kz = keys.apply(this, arguments),
i,
m = data.length,
n = kz.length,
sz = new Array(n),
oz;
for (i = 0; i < n; ++i) {
for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) {
si[j] = sij = [0, +value(data[j], ki, j, data)];
sij.data = data[j];
}
si.key = ki;
}
for (i = 0, oz = order(sz); i < n; ++i) {
sz[oz[i]].index = i;
}
offset(sz, oz);
return sz;
}
stack.keys = function (_) {
return arguments.length ? (keys = typeof _ === "function" ? _ : constant(slice.call(_)), stack) : keys;
};
stack.value = function (_) {
return arguments.length ? (value = typeof _ === "function" ? _ : constant(+_), stack) : value;
};
stack.order = function (_) {
return arguments.length ? (order = _ == null ? none$1 : typeof _ === "function" ? _ : constant(slice.call(_)), stack) : order;
};
stack.offset = function (_) {
return arguments.length ? (offset = _ == null ? none : _, stack) : offset;
};
return stack;
}
function expand (series, order) {
if (!((n = series.length) > 0)) return;
for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) {
for (y = i = 0; i < n; ++i) {
y += series[i][j][1] || 0;
}
if (y) for (i = 0; i < n; ++i) {
series[i][j][1] /= y;
}
}
none(series, order);
}
function diverging (series, order) {
if (!((n = series.length) > 0)) return;
for (var i, j = 0, d, dy, yp, yn, n, m = series[order[0]].length; j < m; ++j) {
for (yp = yn = 0, i = 0; i < n; ++i) {
if ((dy = (d = series[order[i]][j])[1] - d[0]) >= 0) {
d[0] = yp, d[1] = yp += dy;
} else if (dy < 0) {
d[1] = yn, d[0] = yn += dy;
} else {
d[0] = yp;
}
}
}
}
function silhouette (series, order) {
if (!((n = series.length) > 0)) return;
for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) {
for (var i = 0, y = 0; i < n; ++i) {
y += series[i][j][1] || 0;
}
s0[j][1] += s0[j][0] = -y / 2;
}
none(series, order);
}
function wiggle (series, order) {
if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return;
for (var y = 0, j = 1, s0, m, n; j < m; ++j) {
for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) {
var si = series[order[i]],
sij0 = si[j][1] || 0,
sij1 = si[j - 1][1] || 0,
s3 = (sij0 - sij1) / 2;
for (var k = 0; k < i; ++k) {
var sk = series[order[k]],
skj0 = sk[j][1] || 0,
skj1 = sk[j - 1][1] || 0;
s3 += skj0 - skj1;
}
s1 += sij0, s2 += s3 * sij0;
}
s0[j - 1][1] += s0[j - 1][0] = y;
if (s1) y -= s2 / s1;
}
s0[j - 1][1] += s0[j - 1][0] = y;
none(series, order);
}
function appearance (series) {
var peaks = series.map(peak);
return none$1(series).sort(function (a, b) {
return peaks[a] - peaks[b];
});
}
function peak(series) {
var i = -1,
j = 0,
n = series.length,
vi,
vj = -Infinity;
while (++i < n) {
if ((vi = +series[i][1]) > vj) vj = vi, j = i;
}
return j;
}
function ascending$1 (series) {
var sums = series.map(sum$1);
return none$1(series).sort(function (a, b) {
return sums[a] - sums[b];
});
}
function sum$1(series) {
var s = 0,
i = -1,
n = series.length,
v;
while (++i < n) {
if (v = +series[i][1]) s += v;
}
return s;
}
function descending$1 (series) {
return ascending$1(series).reverse();
}
function insideOut (series) {
var n = series.length,
i,
j,
sums = series.map(sum$1),
order = appearance(series),
top = 0,
bottom = 0,
tops = [],
bottoms = [];
for (i = 0; i < n; ++i) {
j = order[i];
if (top < bottom) {
top += sums[j];
tops.push(j);
} else {
bottom += sums[j];
bottoms.push(j);
}
}
return bottoms.reverse().concat(tops);
}
function reverse (series) {
return none$1(series).reverse();
}
var paths = /*#__PURE__*/Object.freeze({
__proto__: null,
arc: arc,
area: area,
line: line,
pie: pie,
areaRadial: areaRadial,
radialArea: areaRadial,
lineRadial: lineRadial$1,
radialLine: lineRadial$1,
pointRadial: pointRadial,
linkHorizontal: linkHorizontal,
linkVertical: linkVertical,
linkRadial: linkRadial,
symbol: symbol,
symbols: symbols,
symbolCircle: circle,
symbolCross: cross,
symbolDiamond: diamond,
symbolSquare: square,
symbolStar: star,
symbolTriangle: triangle,
symbolWye: wye,
curveBasisClosed: basisClosed,
curveBasisOpen: basisOpen,
curveBasis: basis,
curveBundle: bundle,
curveCardinalClosed: cardinalClosed,
curveCardinalOpen: cardinalOpen,
curveCardinal: cardinal,
curveCatmullRomClosed: catmullRomClosed,
curveCatmullRomOpen: catmullRomOpen,
curveCatmullRom: catmullRom,
curveLinearClosed: linearClosed,
curveLinear: curveLinear,
curveMonotoneX: monotoneX,
curveMonotoneY: monotoneY,
curveNatural: natural,
curveStep: step,
curveStepAfter: stepAfter,
curveStepBefore: stepBefore,
stack: stack,
stackOffsetExpand: expand,
stackOffsetDiverging: diverging,
stackOffsetNone: none,
stackOffsetSilhouette: silhouette,
stackOffsetWiggle: wiggle,
stackOrderAppearance: appearance,
stackOrderAscending: ascending$1,
stackOrderDescending: descending$1,
stackOrderInsideOut: insideOut,
stackOrderNone: none$1,
stackOrderReverse: reverse
});
/**
@function accessor
@desc Wraps an object key in a simple accessor function.
@param {String} key The key to be returned from each Object passed to the function.
@param {*} [def] A default value to be returned if the key is not present.
@example <caption>this</caption>
accessor("id");
@example <caption>returns this</caption>
function(d) {
return d["id"];
}
*/
function accessor (key, def) {
if (def === void 0) return function (d) {
return d[key];
};
return function (d) {
return d[key] === void 0 ? def : d[key];
};
}
function _typeof$1(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$1 = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$1 = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$1(obj);
}
/**
@function isObject
@desc Detects if a variable is a javascript Object.
@param {*} item
*/
function isObject (item) {
return item && _typeof$1(item) === "object" && (typeof window === "undefined" || item !== window && item !== window.document && !(item instanceof Element)) && !Array.isArray(item) ? true : false;
}
/**
@function validObject
@desc Determines if the object passed is the document or window.
@param {Object} obj
@private
*/
function validObject(obj) {
if (typeof window === "undefined") return true;else return obj !== window && obj !== document;
}
/**
@function assign
@desc A deeply recursive version of `Object.assign`.
@param {...Object} objects
@example <caption>this</caption>
assign({id: "foo", deep: {group: "A"}}, {id: "bar", deep: {value: 20}}));
@example <caption>returns this</caption>
{id: "bar", deep: {group: "A", value: 20}}
*/
function assign() {
var _arguments = arguments;
var target = arguments.length <= 0 ? undefined : arguments[0];
var _loop = function _loop(i) {
var source = i < 0 || _arguments.length <= i ? undefined : _arguments[i];
Object.keys(source).forEach(function (prop) {
var value = source[prop];
if (isObject(value) && validObject(value)) {
if (target.hasOwnProperty(prop) && isObject(target[prop])) target[prop] = assign({}, target[prop], value);else target[prop] = assign({}, value);
} else if (Array.isArray(value)) target[prop] = value.slice();else target[prop] = value;
});
};
for (var i = 1; i < arguments.length; i++) {
_loop(i);
}
return target;
}
/**
@function attrize
@desc Applies each key/value in an object as an attr.
@param {D3selection} elem The D3 element to apply the styles to.
@param {Object} attrs An object of key/value attr pairs.
*/
function attrize (e) {
var a = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
for (var k in a) {
if ({}.hasOwnProperty.call(a, k)) e.attr(k, a[k]);
}
}
var aa = {
language: "Afar",
location: null,
id: 4096,
tag: "aa",
version: "Release 10"
};
var af = {
language: "Afrikaans",
location: null,
id: 54,
tag: "af",
version: "Release 7"
};
var agq = {
language: "Aghem",
location: null,
id: 4096,
tag: "agq",
version: "Release 10"
};
var ak = {
language: "Akan",
location: null,
id: 4096,
tag: "ak",
version: "Release 10"
};
var sq = {
language: "Albanian",
location: null,
id: 28,
tag: "sq",
version: "Release 7"
};
var gsw = {
language: "Alsatian",
location: null,
id: 132,
tag: "gsw",
version: "Release 7"
};
var am = {
language: "Amharic",
location: null,
id: 94,
tag: "am",
version: "Release 7"
};
var ar = {
language: "Arabic",
location: null,
id: 1,
tag: "ar",
version: "Release 7"
};
var hy = {
language: "Armenian",
location: null,
id: 43,
tag: "hy",
version: "Release 7"
};
var as = {
language: "Assamese",
location: null,
id: 77,
tag: "as",
version: "Release 7"
};
var ast = {
language: "Asturian",
location: null,
id: 4096,
tag: "ast",
version: "Release 10"
};
var asa = {
language: "Asu",
location: null,
id: 4096,
tag: "asa",
version: "Release 10"
};
var az = {
language: "Azerbaijani (Latin)",
location: null,
id: 44,
tag: "az",
version: "Release 7"
};
var ksf = {
language: "Bafia",
location: null,
id: 4096,
tag: "ksf",
version: "Release 10"
};
var bm = {
language: "Bamanankan",
location: null,
id: 4096,
tag: "bm",
version: "Release 10"
};
var bn = {
language: "Bangla",
location: null,
id: 69,
tag: "bn",
version: "Release 7"
};
var bas = {
language: "Basaa",
location: null,
id: 4096,
tag: "bas",
version: "Release 10"
};
var ba = {
language: "Bashkir",
location: null,
id: 109,
tag: "ba",
version: "Release 7"
};
var eu = {
language: "Basque",
location: null,
id: 45,
tag: "eu",
version: "Release 7"
};
var be = {
language: "Belarusian",
location: null,
id: 35,
tag: "be",
version: "Release 7"
};
var bem = {
language: "Bemba",
location: null,
id: 4096,
tag: "bem",
version: "Release 10"
};
var bez = {
language: "Bena",
location: null,
id: 4096,
tag: "bez",
version: "Release 10"
};
var byn = {
language: "Blin",
location: null,
id: 4096,
tag: "byn",
version: "Release 10"
};
var brx = {
language: "Bodo",
location: null,
id: 4096,
tag: "brx",
version: "Release 10"
};
var bs = {
language: "Bosnian (Latin)",
location: null,
id: 30746,
tag: "bs",
version: "Release 7"
};
var br = {
language: "Breton",
location: null,
id: 126,
tag: "br",
version: "Release 7"
};
var bg = {
language: "Bulgarian",
location: null,
id: 2,
tag: "bg",
version: "Release 7"
};
var my = {
language: "Burmese",
location: null,
id: 85,
tag: "my",
version: "Release 8.1"
};
var ca = {
language: "Catalan",
location: null,
id: 3,
tag: "ca",
version: "Release 7"
};
var ceb = {
language: "Cebuano",
location: null,
id: 4096,
tag: "ceb",
version: "Release 10.5"
};
var ku = {
language: "Central Kurdish",
location: null,
id: 146,
tag: "ku",
version: "Release 8"
};
var ccp = {
language: "Chakma",
location: null,
id: 4096,
tag: "ccp",
version: "Release 10.5"
};
var chr = {
language: "Cherokee",
location: null,
id: 92,
tag: "chr",
version: "Release 8"
};
var cgg = {
language: "Chiga",
location: null,
id: 4096,
tag: "cgg",
version: "Release 10"
};
var zh = {
language: "Chinese (Simplified)",
location: null,
id: 30724,
tag: "zh",
version: "Windows 7"
};
var swc = {
language: "Congo Swahili",
location: null,
id: 4096,
tag: "swc",
version: "Release 10"
};
var kw = {
language: "Cornish",
location: null,
id: 4096,
tag: "kw",
version: "Release 10"
};
var co = {
language: "Corsican",
location: null,
id: 131,
tag: "co",
version: "Release 7"
};
var cs = {
language: "Czech",
location: null,
id: 5,
tag: "cs",
version: "Release 7"
};
var da = {
language: "Danish",
location: null,
id: 6,
tag: "da",
version: "Release 7"
};
var prs = {
language: "Dari",
location: null,
id: 140,
tag: "prs",
version: "Release 7"
};
var dv = {
language: "Divehi",
location: null,
id: 101,
tag: "dv",
version: "Release 7"
};
var dua = {
language: "Duala",
location: null,
id: 4096,
tag: "dua",
version: "Release 10"
};
var nl = {
language: "Dutch",
location: null,
id: 19,
tag: "nl",
version: "Release 7"
};
var dz = {
language: "Dzongkha",
location: null,
id: 4096,
tag: "dz",
version: "Release 10"
};
var ebu = {
language: "Embu",
location: null,
id: 4096,
tag: "ebu",
version: "Release 10"
};
var en = {
language: "English",
location: null,
id: 9,
tag: "en",
version: "Release 7"
};
var eo = {
language: "Esperanto",
location: null,
id: 4096,
tag: "eo",
version: "Release 10"
};
var et = {
language: "Estonian",
location: null,
id: 37,
tag: "et",
version: "Release 7"
};
var ee = {
language: "Ewe",
location: null,
id: 4096,
tag: "ee",
version: "Release 10"
};
var ewo = {
language: "Ewondo",
location: null,
id: 4096,
tag: "ewo",
version: "Release 10"
};
var fo = {
language: "Faroese",
location: null,
id: 56,
tag: "fo",
version: "Release 7"
};
var fil = {
language: "Filipino",
location: null,
id: 100,
tag: "fil",
version: "Release 7"
};
var fi = {
language: "Finnish",
location: null,
id: 11,
tag: "fi",
version: "Release 7"
};
var fr = {
language: "French",
location: null,
id: 12,
tag: "fr",
version: "Release 7"
};
var fy = {
language: "Frisian",
location: null,
id: 98,
tag: "fy",
version: "Release 7"
};
var fur = {
language: "Friulian",
location: null,
id: 4096,
tag: "fur",
version: "Release 10"
};
var ff = {
language: "Fulah",
location: null,
id: 103,
tag: "ff",
version: "Release 8"
};
var gl = {
language: "Galician",
location: null,
id: 86,
tag: "gl",
version: "Release 7"
};
var lg = {
language: "Ganda",
location: null,
id: 4096,
tag: "lg",
version: "Release 10"
};
var ka$1 = {
language: "Georgian",
location: null,
id: 55,
tag: "ka",
version: "Release 7"
};
var de = {
language: "German",
location: null,
id: 7,
tag: "de",
version: "Release 7"
};
var el = {
language: "Greek",
location: null,
id: 8,
tag: "el",
version: "Release 7"
};
var kl = {
language: "Greenlandic",
location: null,
id: 111,
tag: "kl",
version: "Release 7"
};
var gn = {
language: "Guarani",
location: null,
id: 116,
tag: "gn",
version: "Release 8.1"
};
var gu = {
language: "Gujarati",
location: null,
id: 71,
tag: "gu",
version: "Release 7"
};
var guz = {
language: "Gusii",
location: null,
id: 4096,
tag: "guz",
version: "Release 10"
};
var ha = {
language: "Hausa (Latin)",
location: null,
id: 104,
tag: "ha",
version: "Release 7"
};
var haw = {
language: "Hawaiian",
location: null,
id: 117,
tag: "haw",
version: "Release 8"
};
var he = {
language: "Hebrew",
location: null,
id: 13,
tag: "he",
version: "Release 7"
};
var hi = {
language: "Hindi",
location: null,
id: 57,
tag: "hi",
version: "Release 7"
};
var hu = {
language: "Hungarian",
location: null,
id: 14,
tag: "hu",
version: "Release 7"
};
var is = {
language: "Icelandic",
location: null,
id: 15,
tag: "is",
version: "Release 7"
};
var ig = {
language: "Igbo",
location: null,
id: 112,
tag: "ig",
version: "Release 7"
};
var id = {
language: "Indonesian",
location: null,
id: 33,
tag: "id",
version: "Release 7"
};
var ia = {
language: "Interlingua",
location: null,
id: 4096,
tag: "ia",
version: "Release 10"
};
var iu = {
language: "Inuktitut (Latin)",
location: null,
id: 93,
tag: "iu",
version: "Release 7"
};
var ga = {
language: "Irish",
location: null,
id: 60,
tag: "ga",
version: "Windows 7"
};
var it = {
language: "Italian",
location: null,
id: 16,
tag: "it",
version: "Release 7"
};
var ja = {
language: "Japanese",
location: null,
id: 17,
tag: "ja",
version: "Release 7"
};
var jv = {
language: "Javanese",
location: null,
id: 4096,
tag: "jv",
version: "Release 8.1"
};
var dyo = {
language: "Jola-Fonyi",
location: null,
id: 4096,
tag: "dyo",
version: "Release 10"
};
var kea = {
language: "Kabuverdianu",
location: null,
id: 4096,
tag: "kea",
version: "Release 10"
};
var kab = {
language: "Kabyle",
location: null,
id: 4096,
tag: "kab",
version: "Release 10"
};
var kkj = {
language: "Kako",
location: null,
id: 4096,
tag: "kkj",
version: "Release 10"
};
var kln = {
language: "Kalenjin",
location: null,
id: 4096,
tag: "kln",
version: "Release 10"
};
var kam = {
language: "Kamba",
location: null,
id: 4096,
tag: "kam",
version: "Release 10"
};
var kn = {
language: "Kannada",
location: null,
id: 75,
tag: "kn",
version: "Release 7"
};
var ks = {
language: "Kashmiri",
location: null,
id: 96,
tag: "ks",
version: "Release 10"
};
var kk = {
language: "Kazakh",
location: null,
id: 63,
tag: "kk",
version: "Release 7"
};
var km = {
language: "Khmer",
location: null,
id: 83,
tag: "km",
version: "Release 7"
};
var quc = {
language: "K'iche",
location: null,
id: 134,
tag: "quc",
version: "Release 10"
};
var ki = {
language: "Kikuyu",
location: null,
id: 4096,
tag: "ki",
version: "Release 10"
};
var rw = {
language: "Kinyarwanda",
location: null,
id: 135,
tag: "rw",
version: "Release 7"
};
var sw = {
language: "Kiswahili",
location: null,
id: 65,
tag: "sw",
version: "Release 7"
};
var kok = {
language: "Konkani",
location: null,
id: 87,
tag: "kok",
version: "Release 7"
};
var ko = {
language: "Korean",
location: null,
id: 18,
tag: "ko",
version: "Release 7"
};
var khq = {
language: "Koyra Chiini",
location: null,
id: 4096,
tag: "khq",
version: "Release 10"
};
var ses = {
language: "Koyraboro Senni",
location: null,
id: 4096,
tag: "ses",
version: "Release 10"
};
var nmg = {
language: "Kwasio",
location: null,
id: 4096,
tag: "nmg",
version: "Release 10"
};
var ky$1 = {
language: "Kyrgyz",
location: null,
id: 64,
tag: "ky",
version: "Release 7"
};
var lkt = {
language: "Lakota",
location: null,
id: 4096,
tag: "lkt",
version: "Release 10"
};
var lag = {
language: "Langi",
location: null,
id: 4096,
tag: "lag",
version: "Release 10"
};
var lo = {
language: "Lao",
location: null,
id: 84,
tag: "lo",
version: "Release 7"
};
var lv = {
language: "Latvian",
location: null,
id: 38,
tag: "lv",
version: "Release 7"
};
var ln = {
language: "Lingala",
location: null,
id: 4096,
tag: "ln",
version: "Release 10"
};
var lt = {
language: "Lithuanian",
location: null,
id: 39,
tag: "lt",
version: "Release 7"
};
var nds = {
language: "Low German",
location: null,
id: 4096,
tag: "nds",
version: "Release 10.2"
};
var dsb = {
language: "Lower Sorbian",
location: null,
id: 31790,
tag: "dsb",
version: "Windows 7"
};
var lu = {
language: "Luba-Katanga",
location: null,
id: 4096,
tag: "lu",
version: "Release 10"
};
var luo = {
language: "Luo",
location: null,
id: 4096,
tag: "luo",
version: "Release 10"
};
var lb = {
language: "Luxembourgish",
location: null,
id: 110,
tag: "lb",
version: "Release 7"
};
var luy = {
language: "Luyia",
location: null,
id: 4096,
tag: "luy",
version: "Release 10"
};
var mk = {
language: "Macedonian",
location: null,
id: 47,
tag: "mk",
version: "Release 7"
};
var jmc = {
language: "Machame",
location: null,
id: 4096,
tag: "jmc",
version: "Release 10"
};
var mgh = {
language: "Makhuwa-Meetto",
location: null,
id: 4096,
tag: "mgh",
version: "Release 10"
};
var kde = {
language: "Makonde",
location: null,
id: 4096,
tag: "kde",
version: "Release 10"
};
var mg = {
language: "Malagasy",
location: null,
id: 4096,
tag: "mg",
version: "Release 8.1"
};
var ms = {
language: "Malay",
location: null,
id: 62,
tag: "ms",
version: "Release 7"
};
var ml = {
language: "Malayalam",
location: null,
id: 76,
tag: "ml",
version: "Release 7"
};
var mt = {
language: "Maltese",
location: null,
id: 58,
tag: "mt",
version: "Release 7"
};
var gv = {
language: "Manx",
location: null,
id: 4096,
tag: "gv",
version: "Release 10"
};
var mi = {
language: "Maori",
location: null,
id: 129,
tag: "mi",
version: "Release 7"
};
var arn = {
language: "Mapudungun",
location: null,
id: 122,
tag: "arn",
version: "Release 7"
};
var mr = {
language: "Marathi",
location: null,
id: 78,
tag: "mr",
version: "Release 7"
};
var mas = {
language: "Masai",
location: null,
id: 4096,
tag: "mas",
version: "Release 10"
};
var mer = {
language: "Meru",
location: null,
id: 4096,
tag: "mer",
version: "Release 10"
};
var mgo = {
language: "Meta'",
location: null,
id: 4096,
tag: "mgo",
version: "Release 10"
};
var moh = {
language: "Mohawk",
location: null,
id: 124,
tag: "moh",
version: "Release 7"
};
var mn = {
language: "Mongolian (Cyrillic)",
location: null,
id: 80,
tag: "mn",
version: "Release 7"
};
var mfe = {
language: "Morisyen",
location: null,
id: 4096,
tag: "mfe",
version: "Release 10"
};
var mua = {
language: "Mundang",
location: null,
id: 4096,
tag: "mua",
version: "Release 10"
};
var nqo = {
language: "N'ko",
location: null,
id: 4096,
tag: "nqo",
version: "Release 8.1"
};
var naq = {
language: "Nama",
location: null,
id: 4096,
tag: "naq",
version: "Release 10"
};
var ne = {
language: "Nepali",
location: null,
id: 97,
tag: "ne",
version: "Release 7"
};
var nnh = {
language: "Ngiemboon",
location: null,
id: 4096,
tag: "nnh",
version: "Release 10"
};
var jgo = {
language: "Ngomba",
location: null,
id: 4096,
tag: "jgo",
version: "Release 10"
};
var nd = {
language: "North Ndebele",
location: null,
id: 4096,
tag: "nd",
version: "Release 10"
};
var no = {
language: "Norwegian (Bokmal)",
location: null,
id: 20,
tag: "no",
version: "Release 7"
};
var nb = {
language: "Norwegian (Bokmal)",
location: null,
id: 31764,
tag: "nb",
version: "Release 7"
};
var nn = {
language: "Norwegian (Nynorsk)",
location: null,
id: 30740,
tag: "nn",
version: "Release 7"
};
var nus = {
language: "Nuer",
location: null,
id: 4096,
tag: "nus",
version: "Release 10"
};
var nyn = {
language: "Nyankole",
location: null,
id: 4096,
tag: "nyn",
version: "Release 10"
};
var oc = {
language: "Occitan",
location: null,
id: 130,
tag: "oc",
version: "Release 7"
};
var or = {
language: "Odia",
location: null,
id: 72,
tag: "or",
version: "Release 7"
};
var om = {
language: "Oromo",
location: null,
id: 114,
tag: "om",
version: "Release 8.1"
};
var os = {
language: "Ossetian",
location: null,
id: 4096,
tag: "os",
version: "Release 10"
};
var ps = {
language: "Pashto",
location: null,
id: 99,
tag: "ps",
version: "Release 7"
};
var fa = {
language: "Persian",
location: null,
id: 41,
tag: "fa",
version: "Release 7"
};
var pl = {
language: "Polish",
location: null,
id: 21,
tag: "pl",
version: "Release 7"
};
var pt = {
language: "Portuguese",
location: null,
id: 22,
tag: "pt",
version: "Release 7"
};
var pa = {
language: "Punjabi",
location: null,
id: 70,
tag: "pa",
version: "Release 7"
};
var quz = {
language: "Quechua",
location: null,
id: 107,
tag: "quz",
version: "Release 7"
};
var ksh = {
language: "Ripuarian",
location: null,
id: 4096,
tag: "ksh",
version: "Release 10"
};
var ro = {
language: "Romanian",
location: null,
id: 24,
tag: "ro",
version: "Release 7"
};
var rm = {
language: "Romansh",
location: null,
id: 23,
tag: "rm",
version: "Release 7"
};
var rof = {
language: "Rombo",
location: null,
id: 4096,
tag: "rof",
version: "Release 10"
};
var rn = {
language: "Rundi",
location: null,
id: 4096,
tag: "rn",
version: "Release 10"
};
var ru = {
language: "Russian",
location: null,
id: 25,
tag: "ru",
version: "Release 7"
};
var rwk = {
language: "Rwa",
location: null,
id: 4096,
tag: "rwk",
version: "Release 10"
};
var ssy = {
language: "Saho",
location: null,
id: 4096,
tag: "ssy",
version: "Release 10"
};
var sah = {
language: "Sakha",
location: null,
id: 133,
tag: "sah",
version: "Release 7"
};
var saq = {
language: "Samburu",
location: null,
id: 4096,
tag: "saq",
version: "Release 10"
};
var smn = {
language: "Sami (Inari)",
location: null,
id: 28731,
tag: "smn",
version: "Windows 7"
};
var smj = {
language: "Sami (Lule)",
location: null,
id: 31803,
tag: "smj",
version: "Windows 7"
};
var se = {
language: "Sami (Northern)",
location: null,
id: 59,
tag: "se",
version: "Release 7"
};
var sms = {
language: "Sami (Skolt)",
location: null,
id: 29755,
tag: "sms",
version: "Windows 7"
};
var sma = {
language: "Sami (Southern)",
location: null,
id: 30779,
tag: "sma",
version: "Windows 7"
};
var sg = {
language: "Sango",
location: null,
id: 4096,
tag: "sg",
version: "Release 10"
};
var sbp = {
language: "Sangu",
location: null,
id: 4096,
tag: "sbp",
version: "Release 10"
};
var sa = {
language: "Sanskrit",
location: null,
id: 79,
tag: "sa",
version: "Release 7"
};
var gd = {
language: "Scottish Gaelic",
location: null,
id: 145,
tag: "gd",
version: "Windows 7"
};
var seh = {
language: "Sena",
location: null,
id: 4096,
tag: "seh",
version: "Release 10"
};
var sr = {
language: "Serbian (Latin)",
location: null,
id: 31770,
tag: "sr",
version: "Release 7"
};
var nso = {
language: "Sesotho sa Leboa",
location: null,
id: 108,
tag: "nso",
version: "Release 7"
};
var tn = {
language: "Setswana",
location: null,
id: 50,
tag: "tn",
version: "Release 7"
};
var ksb = {
language: "Shambala",
location: null,
id: 4096,
tag: "ksb",
version: "Release 10"
};
var sn = {
language: "Shona",
location: null,
id: 4096,
tag: "sn",
version: "Release 8.1"
};
var sd = {
language: "Sindhi",
location: null,
id: 89,
tag: "sd",
version: "Release 8"
};
var si = {
language: "Sinhala",
location: null,
id: 91,
tag: "si",
version: "Release 7"
};
var sk = {
language: "Slovak",
location: null,
id: 27,
tag: "sk",
version: "Release 7"
};
var sl = {
language: "Slovenian",
location: null,
id: 36,
tag: "sl",
version: "Release 7"
};
var xog = {
language: "Soga",
location: null,
id: 4096,
tag: "xog",
version: "Release 10"
};
var so = {
language: "Somali",
location: null,
id: 119,
tag: "so",
version: "Release 8.1"
};
var st = {
language: "Sotho",
location: null,
id: 48,
tag: "st",
version: "Release 8.1"
};
var nr = {
language: "South Ndebele",
location: null,
id: 4096,
tag: "nr",
version: "Release 10"
};
var es = {
language: "Spanish",
location: null,
id: 10,
tag: "es",
version: "Release 7"
};
var zgh = {
language: "Standard Moroccan Tamazight",
location: null,
id: 4096,
tag: "zgh",
version: "Release 8.1"
};
var ss = {
language: "Swati",
location: null,
id: 4096,
tag: "ss",
version: "Release 10"
};
var sv = {
language: "Swedish",
location: null,
id: 29,
tag: "sv",
version: "Release 7"
};
var syr = {
language: "Syriac",
location: null,
id: 90,
tag: "syr",
version: "Release 7"
};
var shi = {
language: "Tachelhit",
location: null,
id: 4096,
tag: "shi",
version: "Release 10"
};
var dav = {
language: "Taita",
location: null,
id: 4096,
tag: "dav",
version: "Release 10"
};
var tg = {
language: "Tajik (Cyrillic)",
location: null,
id: 40,
tag: "tg",
version: "Release 7"
};
var tzm = {
language: "Tamazight (Latin)",
location: null,
id: 95,
tag: "tzm",
version: "Release 7"
};
var ta = {
language: "Tamil",
location: null,
id: 73,
tag: "ta",
version: "Release 7"
};
var twq = {
language: "Tasawaq",
location: null,
id: 4096,
tag: "twq",
version: "Release 10"
};
var tt = {
language: "Tatar",
location: null,
id: 68,
tag: "tt",
version: "Release 7"
};
var te = {
language: "Telugu",
location: null,
id: 74,
tag: "te",
version: "Release 7"
};
var teo = {
language: "Teso",
location: null,
id: 4096,
tag: "teo",
version: "Release 10"
};
var th = {
language: "Thai",
location: null,
id: 30,
tag: "th",
version: "Release 7"
};
var bo = {
language: "Tibetan",
location: null,
id: 81,
tag: "bo",
version: "Release 7"
};
var tig = {
language: "Tigre",
location: null,
id: 4096,
tag: "tig",
version: "Release 10"
};
var ti = {
language: "Tigrinya",
location: null,
id: 115,
tag: "ti",
version: "Release 8"
};
var to = {
language: "Tongan",
location: null,
id: 4096,
tag: "to",
version: "Release 10"
};
var ts = {
language: "Tsonga",
location: null,
id: 49,
tag: "ts",
version: "Release 8.1"
};
var tr = {
language: "Turkish",
location: null,
id: 31,
tag: "tr",
version: "Release 7"
};
var tk = {
language: "Turkmen",
location: null,
id: 66,
tag: "tk",
version: "Release 7"
};
var uk = {
language: "Ukrainian",
location: null,
id: 34,
tag: "uk",
version: "Release 7"
};
var hsb = {
language: "Upper Sorbian",
location: null,
id: 46,
tag: "hsb",
version: "Release 7"
};
var ur = {
language: "Urdu",
location: null,
id: 32,
tag: "ur",
version: "Release 7"
};
var ug = {
language: "Uyghur",
location: null,
id: 128,
tag: "ug",
version: "Release 7"
};
var uz = {
language: "Uzbek (Latin)",
location: null,
id: 67,
tag: "uz",
version: "Release 7"
};
var vai = {
language: "Vai",
location: null,
id: 4096,
tag: "vai",
version: "Release 10"
};
var ve = {
language: "Venda",
location: null,
id: 51,
tag: "ve",
version: "Release 10"
};
var vi = {
language: "Vietnamese",
location: null,
id: 42,
tag: "vi",
version: "Release 7"
};
var vo = {
language: "Volapük",
location: null,
id: 4096,
tag: "vo",
version: "Release 10"
};
var vun = {
language: "Vunjo",
location: null,
id: 4096,
tag: "vun",
version: "Release 10"
};
var wae = {
language: "Walser",
location: null,
id: 4096,
tag: "wae",
version: "Release 10"
};
var cy = {
language: "Welsh",
location: null,
id: 82,
tag: "cy",
version: "Release 7"
};
var wal = {
language: "Wolaytta",
location: null,
id: 4096,
tag: "wal",
version: "Release 10"
};
var wo = {
language: "Wolof",
location: null,
id: 136,
tag: "wo",
version: "Release 7"
};
var xh = {
language: "Xhosa",
location: null,
id: 52,
tag: "xh",
version: "Release 7"
};
var yav = {
language: "Yangben",
location: null,
id: 4096,
tag: "yav",
version: "Release 10"
};
var ii = {
language: "Yi",
location: null,
id: 120,
tag: "ii",
version: "Release 7"
};
var yo = {
language: "Yoruba",
location: null,
id: 106,
tag: "yo",
version: "Release 7"
};
var dje = {
language: "Zarma",
location: null,
id: 4096,
tag: "dje",
version: "Release 10"
};
var zu = {
language: "Zulu",
location: null,
id: 53,
tag: "zu",
version: "Release 7"
};
var lcid = {
aa: aa,
"aa-dj": {
language: "Afar",
location: "Djibouti",
id: 4096,
tag: "aa-DJ",
version: "Release 10"
},
"aa-er": {
language: "Afar",
location: "Eritrea",
id: 4096,
tag: "aa-ER",
version: "Release 10"
},
"aa-et": {
language: "Afar",
location: "Ethiopia",
id: 4096,
tag: "aa-ET",
version: "Release 10"
},
af: af,
"af-na": {
language: "Afrikaans",
location: "Namibia",
id: 4096,
tag: "af-NA",
version: "Release 10"
},
"af-za": {
language: "Afrikaans",
location: "South Africa",
id: 1078,
tag: "af-ZA",
version: "Release B"
},
agq: agq,
"agq-cm": {
language: "Aghem",
location: "Cameroon",
id: 4096,
tag: "agq-CM",
version: "Release 10"
},
ak: ak,
"ak-gh": {
language: "Akan",
location: "Ghana",
id: 4096,
tag: "ak-GH",
version: "Release 10"
},
sq: sq,
"sq-al": {
language: "Albanian",
location: "Albania",
id: 1052,
tag: "sq-AL",
version: "Release B"
},
"sq-mk": {
language: "Albanian",
location: "North Macedonia",
id: 4096,
tag: "sq-MK",
version: "Release 10"
},
gsw: gsw,
"gsw-fr": {
language: "Alsatian",
location: "France",
id: 1156,
tag: "gsw-FR",
version: "Release V"
},
"gsw-li": {
language: "Alsatian",
location: "Liechtenstein",
id: 4096,
tag: "gsw-LI",
version: "Release 10"
},
"gsw-ch": {
language: "Alsatian",
location: "Switzerland",
id: 4096,
tag: "gsw-CH",
version: "Release 10"
},
am: am,
"am-et": {
language: "Amharic",
location: "Ethiopia",
id: 1118,
tag: "am-ET",
version: "Release V"
},
ar: ar,
"ar-dz": {
language: "Arabic",
location: "Algeria",
id: 5121,
tag: "ar-DZ",
version: "Release B"
},
"ar-bh": {
language: "Arabic",
location: "Bahrain",
id: 15361,
tag: "ar-BH",
version: "Release B"
},
"ar-td": {
language: "Arabic",
location: "Chad",
id: 4096,
tag: "ar-TD",
version: "Release 10"
},
"ar-km": {
language: "Arabic",
location: "Comoros",
id: 4096,
tag: "ar-KM",
version: "Release 10"
},
"ar-dj": {
language: "Arabic",
location: "Djibouti",
id: 4096,
tag: "ar-DJ",
version: "Release 10"
},
"ar-eg": {
language: "Arabic",
location: "Egypt",
id: 3073,
tag: "ar-EG",
version: "Release B"
},
"ar-er": {
language: "Arabic",
location: "Eritrea",
id: 4096,
tag: "ar-ER",
version: "Release 10"
},
"ar-iq": {
language: "Arabic",
location: "Iraq",
id: 2049,
tag: "ar-IQ",
version: "Release B"
},
"ar-il": {
language: "Arabic",
location: "Israel",
id: 4096,
tag: "ar-IL",
version: "Release 10"
},
"ar-jo": {
language: "Arabic",
location: "Jordan",
id: 11265,
tag: "ar-JO",
version: "Release B"
},
"ar-kw": {
language: "Arabic",
location: "Kuwait",
id: 13313,
tag: "ar-KW",
version: "Release B"
},
"ar-lb": {
language: "Arabic",
location: "Lebanon",
id: 12289,
tag: "ar-LB",
version: "Release B"
},
"ar-ly": {
language: "Arabic",
location: "Libya",
id: 4097,
tag: "ar-LY",
version: "Release B"
},
"ar-mr": {
language: "Arabic",
location: "Mauritania",
id: 4096,
tag: "ar-MR",
version: "Release 10"
},
"ar-ma": {
language: "Arabic",
location: "Morocco",
id: 6145,
tag: "ar-MA",
version: "Release B"
},
"ar-om": {
language: "Arabic",
location: "Oman",
id: 8193,
tag: "ar-OM",
version: "Release B"
},
"ar-ps": {
language: "Arabic",
location: "Palestinian Authority",
id: 4096,
tag: "ar-PS",
version: "Release 10"
},
"ar-qa": {
language: "Arabic",
location: "Qatar",
id: 16385,
tag: "ar-QA",
version: "Release B"
},
"ar-sa": {
language: "Arabic",
location: "Saudi Arabia",
id: 1025,
tag: "ar-SA",
version: "Release B"
},
"ar-so": {
language: "Arabic",
location: "Somalia",
id: 4096,
tag: "ar-SO",
version: "Release 10"
},
"ar-ss": {
language: "Arabic",
location: "South Sudan",
id: 4096,
tag: "ar-SS",
version: "Release 10"
},
"ar-sd": {
language: "Arabic",
location: "Sudan",
id: 4096,
tag: "ar-SD",
version: "Release 10"
},
"ar-sy": {
language: "Arabic",
location: "Syria",
id: 10241,
tag: "ar-SY",
version: "Release B"
},
"ar-tn": {
language: "Arabic",
location: "Tunisia",
id: 7169,
tag: "ar-TN",
version: "Release B"
},
"ar-ae": {
language: "Arabic",
location: "U.A.E.",
id: 14337,
tag: "ar-AE",
version: "Release B"
},
"ar-001": {
language: "Arabic",
location: "World",
id: 4096,
tag: "ar-001",
version: "Release 10"
},
"ar-ye": {
language: "Arabic",
location: "Yemen",
id: 9217,
tag: "ar-YE",
version: "Release B"
},
hy: hy,
"hy-am": {
language: "Armenian",
location: "Armenia",
id: 1067,
tag: "hy-AM",
version: "Release C"
},
as: as,
"as-in": {
language: "Assamese",
location: "India",
id: 1101,
tag: "as-IN",
version: "Release V"
},
ast: ast,
"ast-es": {
language: "Asturian",
location: "Spain",
id: 4096,
tag: "ast-ES",
version: "Release 10"
},
asa: asa,
"asa-tz": {
language: "Asu",
location: "Tanzania",
id: 4096,
tag: "asa-TZ",
version: "Release 10"
},
"az-cyrl": {
language: "Azerbaijani (Cyrillic)",
location: null,
id: 29740,
tag: "az-Cyrl",
version: "Windows 7"
},
"az-cyrl-az": {
language: "Azerbaijani (Cyrillic)",
location: "Azerbaijan",
id: 2092,
tag: "az-Cyrl-AZ",
version: "Release C"
},
az: az,
"az-latn": {
language: "Azerbaijani (Latin)",
location: null,
id: 30764,
tag: "az-Latn",
version: "Windows 7"
},
"az-latn-az": {
language: "Azerbaijani (Latin)",
location: "Azerbaijan",
id: 1068,
tag: "az-Latn-AZ",
version: "Release C"
},
ksf: ksf,
"ksf-cm": {
language: "Bafia",
location: "Cameroon",
id: 4096,
tag: "ksf-CM",
version: "Release 10"
},
bm: bm,
"bm-latn-ml": {
language: "Bamanankan (Latin)",
location: "Mali",
id: 4096,
tag: "bm-Latn-ML",
version: "Release 10"
},
bn: bn,
"bn-bd": {
language: "Bangla",
location: "Bangladesh",
id: 2117,
tag: "bn-BD",
version: "Release V"
},
"bn-in": {
language: "Bangla",
location: "India",
id: 1093,
tag: "bn-IN",
version: "Release E1"
},
bas: bas,
"bas-cm": {
language: "Basaa",
location: "Cameroon",
id: 4096,
tag: "bas-CM",
version: "Release 10"
},
ba: ba,
"ba-ru": {
language: "Bashkir",
location: "Russia",
id: 1133,
tag: "ba-RU",
version: "Release V"
},
eu: eu,
"eu-es": {
language: "Basque",
location: "Spain",
id: 1069,
tag: "eu-ES",
version: "Release B"
},
be: be,
"be-by": {
language: "Belarusian",
location: "Belarus",
id: 1059,
tag: "be-BY",
version: "Release B"
},
bem: bem,
"bem-zm": {
language: "Bemba",
location: "Zambia",
id: 4096,
tag: "bem-ZM",
version: "Release 10"
},
bez: bez,
"bez-tz": {
language: "Bena",
location: "Tanzania",
id: 4096,
tag: "bez-TZ",
version: "Release 10"
},
byn: byn,
"byn-er": {
language: "Blin",
location: "Eritrea",
id: 4096,
tag: "byn-ER",
version: "Release 10"
},
brx: brx,
"brx-in": {
language: "Bodo",
location: "India",
id: 4096,
tag: "brx-IN",
version: "Release 10"
},
"bs-cyrl": {
language: "Bosnian (Cyrillic)",
location: null,
id: 25626,
tag: "bs-Cyrl",
version: "Windows 7"
},
"bs-cyrl-ba": {
language: "Bosnian (Cyrillic)",
location: "Bosnia and Herzegovina",
id: 8218,
tag: "bs-Cyrl-BA",
version: "Release E1"
},
"bs-latn": {
language: "Bosnian (Latin)",
location: null,
id: 26650,
tag: "bs-Latn",
version: "Windows 7"
},
bs: bs,
"bs-latn-ba": {
language: "Bosnian (Latin)",
location: "Bosnia and Herzegovina",
id: 5146,
tag: "bs-Latn-BA",
version: "Release E1"
},
br: br,
"br-fr": {
language: "Breton",
location: "France",
id: 1150,
tag: "br-FR",
version: "Release V"
},
bg: bg,
"bg-bg": {
language: "Bulgarian",
location: "Bulgaria",
id: 1026,
tag: "bg-BG",
version: "Release B"
},
my: my,
"my-mm": {
language: "Burmese",
location: "Myanmar",
id: 1109,
tag: "my-MM",
version: "Release 8.1"
},
ca: ca,
"ca-ad": {
language: "Catalan",
location: "Andorra",
id: 4096,
tag: "ca-AD",
version: "Release 10"
},
"ca-fr": {
language: "Catalan",
location: "France",
id: 4096,
tag: "ca-FR",
version: "Release 10"
},
"ca-it": {
language: "Catalan",
location: "Italy",
id: 4096,
tag: "ca-IT",
version: "Release 10"
},
"ca-es": {
language: "Catalan",
location: "Spain",
id: 1027,
tag: "ca-ES",
version: "Release B"
},
ceb: ceb,
"ceb-latn": {
language: "Cebuan (Latin)",
location: null,
id: 4096,
tag: "ceb-Latn",
version: "Release 10.5"
},
"ceb-latn-ph": {
language: "Cebuan (Latin)",
location: "Philippines",
id: 4096,
tag: "ceb-Latn-PH",
version: "Release 10.5"
},
"tzm-latn-": {
language: "Central Atlas Tamazight (Latin)",
location: "Morocco",
id: 4096,
tag: "tzm-Latn-",
version: "Release 10"
},
ku: ku,
"ku-arab": {
language: "Central Kurdish",
location: null,
id: 31890,
tag: "ku-Arab",
version: "Release 8"
},
"ku-arab-iq": {
language: "Central Kurdish",
location: "Iraq",
id: 1170,
tag: "ku-Arab-IQ",
version: "Release 8"
},
ccp: ccp,
"ccp-cakm": {
language: "Chakma",
location: "Chakma",
id: 4096,
tag: "ccp-Cakm",
version: "Release 10.5"
},
"ccp-cakm-": {
language: "Chakma",
location: "India",
id: 4096,
tag: "ccp-Cakm-",
version: "Release 10.5"
},
"cd-ru": {
language: "Chechen",
location: "Russia",
id: 4096,
tag: "cd-RU",
version: "Release 10.1"
},
chr: chr,
"chr-cher": {
language: "Cherokee",
location: null,
id: 31836,
tag: "chr-Cher",
version: "Release 8"
},
"chr-cher-us": {
language: "Cherokee",
location: "United States",
id: 1116,
tag: "chr-Cher-US",
version: "Release 8"
},
cgg: cgg,
"cgg-ug": {
language: "Chiga",
location: "Uganda",
id: 4096,
tag: "cgg-UG",
version: "Release 10"
},
"zh-hans": {
language: "Chinese (Simplified)",
location: null,
id: 4,
tag: "zh-Hans",
version: "Release A"
},
zh: zh,
"zh-cn": {
language: "Chinese (Simplified)",
location: "People's Republic of China",
id: 2052,
tag: "zh-CN",
version: "Release A"
},
"zh-sg": {
language: "Chinese (Simplified)",
location: "Singapore",
id: 4100,
tag: "zh-SG",
version: "Release A"
},
"zh-hant": {
language: "Chinese (Traditional)",
location: null,
id: 31748,
tag: "zh-Hant",
version: "Release A"
},
"zh-hk": {
language: "Chinese (Traditional)",
location: "Hong Kong S.A.R.",
id: 3076,
tag: "zh-HK",
version: "Release A"
},
"zh-mo": {
language: "Chinese (Traditional)",
location: "Macao S.A.R.",
id: 5124,
tag: "zh-MO",
version: "Release D"
},
"zh-tw": {
language: "Chinese (Traditional)",
location: "Taiwan",
id: 1028,
tag: "zh-TW",
version: "Release A"
},
"cu-ru": {
language: "Church Slavic",
location: "Russia",
id: 4096,
tag: "cu-RU",
version: "Release 10.1"
},
swc: swc,
"swc-cd": {
language: "Congo Swahili",
location: "Congo DRC",
id: 4096,
tag: "swc-CD",
version: "Release 10"
},
kw: kw,
"kw-gb": {
language: "Cornish",
location: "United Kingdom",
id: 4096,
tag: "kw-GB",
version: "Release 10"
},
co: co,
"co-fr": {
language: "Corsican",
location: "France",
id: 1155,
tag: "co-FR",
version: "Release V"
},
"hr,": {
language: "Croatian",
location: null,
id: 26,
tag: "hr,",
version: "Release 7"
},
"hr-hr": {
language: "Croatian",
location: "Croatia",
id: 1050,
tag: "hr-HR",
version: "Release A"
},
"hr-ba": {
language: "Croatian (Latin)",
location: "Bosnia and Herzegovina",
id: 4122,
tag: "hr-BA",
version: "Release E1"
},
cs: cs,
"cs-cz": {
language: "Czech",
location: "Czech Republic",
id: 1029,
tag: "cs-CZ",
version: "Release A"
},
da: da,
"da-dk": {
language: "Danish",
location: "Denmark",
id: 1030,
tag: "da-DK",
version: "Release A"
},
"da-gl": {
language: "Danish",
location: "Greenland",
id: 4096,
tag: "da-GL",
version: "Release 10"
},
prs: prs,
"prs-af": {
language: "Dari",
location: "Afghanistan",
id: 1164,
tag: "prs-AF",
version: "Release V"
},
dv: dv,
"dv-mv": {
language: "Divehi",
location: "Maldives",
id: 1125,
tag: "dv-MV",
version: "Release D"
},
dua: dua,
"dua-cm": {
language: "Duala",
location: "Cameroon",
id: 4096,
tag: "dua-CM",
version: "Release 10"
},
nl: nl,
"nl-aw": {
language: "Dutch",
location: "Aruba",
id: 4096,
tag: "nl-AW",
version: "Release 10"
},
"nl-be": {
language: "Dutch",
location: "Belgium",
id: 2067,
tag: "nl-BE",
version: "Release A"
},
"nl-bq": {
language: "Dutch",
location: "Bonaire, Sint Eustatius and Saba",
id: 4096,
tag: "nl-BQ",
version: "Release 10"
},
"nl-cw": {
language: "Dutch",
location: "Curaçao",
id: 4096,
tag: "nl-CW",
version: "Release 10"
},
"nl-nl": {
language: "Dutch",
location: "Netherlands",
id: 1043,
tag: "nl-NL",
version: "Release A"
},
"nl-sx": {
language: "Dutch",
location: "Sint Maarten",
id: 4096,
tag: "nl-SX",
version: "Release 10"
},
"nl-sr": {
language: "Dutch",
location: "Suriname",
id: 4096,
tag: "nl-SR",
version: "Release 10"
},
dz: dz,
"dz-bt": {
language: "Dzongkha",
location: "Bhutan",
id: 3153,
tag: "dz-BT",
version: "Release 10"
},
ebu: ebu,
"ebu-ke": {
language: "Embu",
location: "Kenya",
id: 4096,
tag: "ebu-KE",
version: "Release 10"
},
en: en,
"en-as": {
language: "English",
location: "American Samoa",
id: 4096,
tag: "en-AS",
version: "Release 10"
},
"en-ai": {
language: "English",
location: "Anguilla",
id: 4096,
tag: "en-AI",
version: "Release 10"
},
"en-ag": {
language: "English",
location: "Antigua and Barbuda",
id: 4096,
tag: "en-AG",
version: "Release 10"
},
"en-au": {
language: "English",
location: "Australia",
id: 3081,
tag: "en-AU",
version: "Release A"
},
"en-at": {
language: "English",
location: "Austria",
id: 4096,
tag: "en-AT",
version: "Release 10.1"
},
"en-bs": {
language: "English",
location: "Bahamas",
id: 4096,
tag: "en-BS",
version: "Release 10"
},
"en-bb": {
language: "English",
location: "Barbados",
id: 4096,
tag: "en-BB",
version: "Release 10"
},
"en-be": {
language: "English",
location: "Belgium",
id: 4096,
tag: "en-BE",
version: "Release 10"
},
"en-bz": {
language: "English",
location: "Belize",
id: 10249,
tag: "en-BZ",
version: "Release B"
},
"en-bm": {
language: "English",
location: "Bermuda",
id: 4096,
tag: "en-BM",
version: "Release 10"
},
"en-bw": {
language: "English",
location: "Botswana",
id: 4096,
tag: "en-BW",
version: "Release 10"
},
"en-io": {
language: "English",
location: "British Indian Ocean Territory",
id: 4096,
tag: "en-IO",
version: "Release 10"
},
"en-vg": {
language: "English",
location: "British Virgin Islands",
id: 4096,
tag: "en-VG",
version: "Release 10"
},
"en-bi": {
language: "English",
location: "Burundi",
id: 4096,
tag: "en-BI",
version: "Release 10.1"
},
"en-cm": {
language: "English",
location: "Cameroon",
id: 4096,
tag: "en-CM",
version: "Release 10"
},
"en-ca": {
language: "English",
location: "Canada",
id: 4105,
tag: "en-CA",
version: "Release A"
},
"en-029": {
language: "English",
location: "Caribbean",
id: 9225,
tag: "en-029",
version: "Release B"
},
"en-ky": {
language: "English",
location: "Cayman Islands",
id: 4096,
tag: "en-KY",
version: "Release 10"
},
"en-cx": {
language: "English",
location: "Christmas Island",
id: 4096,
tag: "en-CX",
version: "Release 10"
},
"en-cc": {
language: "English",
location: "Cocos [Keeling] Islands",
id: 4096,
tag: "en-CC",
version: "Release 10"
},
"en-ck": {
language: "English",
location: "Cook Islands",
id: 4096,
tag: "en-CK",
version: "Release 10"
},
"en-cy": {
language: "English",
location: "Cyprus",
id: 4096,
tag: "en-CY",
version: "Release 10.1"
},
"en-dk": {
language: "English",
location: "Denmark",
id: 4096,
tag: "en-DK",
version: "Release 10.1"
},
"en-dm": {
language: "English",
location: "Dominica",
id: 4096,
tag: "en-DM",
version: "Release 10"
},
"en-er": {
language: "English",
location: "Eritrea",
id: 4096,
tag: "en-ER",
version: "Release 10"
},
"en-150": {
language: "English",
location: "Europe",
id: 4096,
tag: "en-150",
version: "Release 10"
},
"en-fk": {
language: "English",
location: "Falkland Islands",
id: 4096,
tag: "en-FK",
version: "Release 10"
},
"en-fi": {
language: "English",
location: "Finland",
id: 4096,
tag: "en-FI",
version: "Release 10.1"
},
"en-fj": {
language: "English",
location: "Fiji",
id: 4096,
tag: "en-FJ",
version: "Release 10"
},
"en-gm": {
language: "English",
location: "Gambia",
id: 4096,
tag: "en-GM",
version: "Release 10"
},
"en-de": {
language: "English",
location: "Germany",
id: 4096,
tag: "en-DE",
version: "Release 10.1"
},
"en-gh": {
language: "English",
location: "Ghana",
id: 4096,
tag: "en-GH",
version: "Release 10"
},
"en-gi": {
language: "English",
location: "Gibraltar",
id: 4096,
tag: "en-GI",
version: "Release 10"
},
"en-gd": {
language: "English",
location: "Grenada",
id: 4096,
tag: "en-GD",
version: "Release 10"
},
"en-gu": {
language: "English",
location: "Guam",
id: 4096,
tag: "en-GU",
version: "Release 10"
},
"en-gg": {
language: "English",
location: "Guernsey",
id: 4096,
tag: "en-GG",
version: "Release 10"
},
"en-gy": {
language: "English",
location: "Guyana",
id: 4096,
tag: "en-GY",
version: "Release 10"
},
"en-hk": {
language: "English",
location: "Hong Kong",
id: 15369,
tag: "en-HK",
version: "Release 8.1"
},
"en-in": {
language: "English",
location: "India",
id: 16393,
tag: "en-IN",
version: "Release V"
},
"en-ie": {
language: "English",
location: "Ireland",
id: 6153,
tag: "en-IE",
version: "Release A"
},
"en-im": {
language: "English",
location: "Isle of Man",
id: 4096,
tag: "en-IM",
version: "Release 10"
},
"en-il": {
language: "English",
location: "Israel",
id: 4096,
tag: "en-IL",
version: "Release 10.1"
},
"en-jm": {
language: "English",
location: "Jamaica",
id: 8201,
tag: "en-JM",
version: "Release B"
},
"en-je": {
language: "English",
location: "Jersey",
id: 4096,
tag: "en-JE",
version: "Release 10"
},
"en-ke": {
language: "English",
location: "Kenya",
id: 4096,
tag: "en-KE",
version: "Release 10"
},
"en-ki": {
language: "English",
location: "Kiribati",
id: 4096,
tag: "en-KI",
version: "Release 10"
},
"en-ls": {
language: "English",
location: "Lesotho",
id: 4096,
tag: "en-LS",
version: "Release 10"
},
"en-lr": {
language: "English",
location: "Liberia",
id: 4096,
tag: "en-LR",
version: "Release 10"
},
"en-mo": {
language: "English",
location: "Macao SAR",
id: 4096,
tag: "en-MO",
version: "Release 10"
},
"en-mg": {
language: "English",
location: "Madagascar",
id: 4096,
tag: "en-MG",
version: "Release 10"
},
"en-mw": {
language: "English",
location: "Malawi",
id: 4096,
tag: "en-MW",
version: "Release 10"
},
"en-my": {
language: "English",
location: "Malaysia",
id: 17417,
tag: "en-MY",
version: "Release V"
},
"en-mt": {
language: "English",
location: "Malta",
id: 4096,
tag: "en-MT",
version: "Release 10"
},
"en-mh": {
language: "English",
location: "Marshall Islands",
id: 4096,
tag: "en-MH",
version: "Release 10"
},
"en-mu": {
language: "English",
location: "Mauritius",
id: 4096,
tag: "en-MU",
version: "Release 10"
},
"en-fm": {
language: "English",
location: "Micronesia",
id: 4096,
tag: "en-FM",
version: "Release 10"
},
"en-ms": {
language: "English",
location: "Montserrat",
id: 4096,
tag: "en-MS",
version: "Release 10"
},
"en-na": {
language: "English",
location: "Namibia",
id: 4096,
tag: "en-NA",
version: "Release 10"
},
"en-nr": {
language: "English",
location: "Nauru",
id: 4096,
tag: "en-NR",
version: "Release 10"
},
"en-nl": {
language: "English",
location: "Netherlands",
id: 4096,
tag: "en-NL",
version: "Release 10.1"
},
"en-nz": {
language: "English",
location: "New Zealand",
id: 5129,
tag: "en-NZ",
version: "Release A"
},
"en-ng": {
language: "English",
location: "Nigeria",
id: 4096,
tag: "en-NG",
version: "Release 10"
},
"en-nu": {
language: "English",
location: "Niue",
id: 4096,
tag: "en-NU",
version: "Release 10"
},
"en-nf": {
language: "English",
location: "Norfolk Island",
id: 4096,
tag: "en-NF",
version: "Release 10"
},
"en-mp": {
language: "English",
location: "Northern Mariana Islands",
id: 4096,
tag: "en-MP",
version: "Release 10"
},
"en-pk": {
language: "English",
location: "Pakistan",
id: 4096,
tag: "en-PK",
version: "Release 10"
},
"en-pw": {
language: "English",
location: "Palau",
id: 4096,
tag: "en-PW",
version: "Release 10"
},
"en-pg": {
language: "English",
location: "Papua New Guinea",
id: 4096,
tag: "en-PG",
version: "Release 10"
},
"en-pn": {
language: "English",
location: "Pitcairn Islands",
id: 4096,
tag: "en-PN",
version: "Release 10"
},
"en-pr": {
language: "English",
location: "Puerto Rico",
id: 4096,
tag: "en-PR",
version: "Release 10"
},
"en-ph": {
language: "English",
location: "Republic of the Philippines",
id: 13321,
tag: "en-PH",
version: "Release C"
},
"en-rw": {
language: "English",
location: "Rwanda",
id: 4096,
tag: "en-RW",
version: "Release 10"
},
"en-kn": {
language: "English",
location: "Saint Kitts and Nevis",
id: 4096,
tag: "en-KN",
version: "Release 10"
},
"en-lc": {
language: "English",
location: "Saint Lucia",
id: 4096,
tag: "en-LC",
version: "Release 10"
},
"en-vc": {
language: "English",
location: "Saint Vincent and the Grenadines",
id: 4096,
tag: "en-VC",
version: "Release 10"
},
"en-ws": {
language: "English",
location: "Samoa",
id: 4096,
tag: "en-WS",
version: "Release 10"
},
"en-sc": {
language: "English",
location: "Seychelles",
id: 4096,
tag: "en-SC",
version: "Release 10"
},
"en-sl": {
language: "English",
location: "Sierra Leone",
id: 4096,
tag: "en-SL",
version: "Release 10"
},
"en-sg": {
language: "English",
location: "Singapore",
id: 18441,
tag: "en-SG",
version: "Release V"
},
"en-sx": {
language: "English",
location: "Sint Maarten",
id: 4096,
tag: "en-SX",
version: "Release 10"
},
"en-si": {
language: "English",
location: "Slovenia",
id: 4096,
tag: "en-SI",
version: "Release 10.1"
},
"en-sb": {
language: "English",
location: "Solomon Islands",
id: 4096,
tag: "en-SB",
version: "Release 10"
},
"en-za": {
language: "English",
location: "South Africa",
id: 7177,
tag: "en-ZA",
version: "Release B"
},
"en-ss": {
language: "English",
location: "South Sudan",
id: 4096,
tag: "en-SS",
version: "Release 10"
},
"en-sh": {
language: "English",
location: "St Helena, Ascension, Tristan da Cunha",
id: 4096,
tag: "en-SH",
version: "Release 10"
},
"en-sd": {
language: "English",
location: "Sudan",
id: 4096,
tag: "en-SD",
version: "Release 10"
},
"en-sz": {
language: "English",
location: "Swaziland",
id: 4096,
tag: "en-SZ",
version: "Release 10"
},
"en-se": {
language: "English",
location: "Sweden",
id: 4096,
tag: "en-SE",
version: "Release 10.1"
},
"en-ch": {
language: "English",
location: "Switzerland",
id: 4096,
tag: "en-CH",
version: "Release 10.1"
},
"en-tz": {
language: "English",
location: "Tanzania",
id: 4096,
tag: "en-TZ",
version: "Release 10"
},
"en-tk": {
language: "English",
location: "Tokelau",
id: 4096,
tag: "en-TK",
version: "Release 10"
},
"en-to": {
language: "English",
location: "Tonga",
id: 4096,
tag: "en-TO",
version: "Release 10"
},
"en-tt": {
language: "English",
location: "Trinidad and Tobago",
id: 11273,
tag: "en-TT",
version: "Release B"
},
"en-tc": {
language: "English",
location: "Turks and Caicos Islands",
id: 4096,
tag: "en-TC",
version: "Release 10"
},
"en-tv": {
language: "English",
location: "Tuvalu",
id: 4096,
tag: "en-TV",
version: "Release 10"
},
"en-ug": {
language: "English",
location: "Uganda",
id: 4096,
tag: "en-UG",
version: "Release 10"
},
"en-ae": {
language: "English",
location: "United Arab Emirates",
id: 19465,
tag: "en-AE",
version: "Release 10.5"
},
"en-gb": {
language: "English",
location: "United Kingdom",
id: 2057,
tag: "en-GB",
version: "Release A"
},
"en-us": {
language: "English",
location: "United States",
id: 1033,
tag: "en-US",
version: "Release A"
},
"en-um": {
language: "English",
location: "US Minor Outlying Islands",
id: 4096,
tag: "en-UM",
version: "Release 10"
},
"en-vi": {
language: "English",
location: "US Virgin Islands",
id: 4096,
tag: "en-VI",
version: "Release 10"
},
"en-vu": {
language: "English",
location: "Vanuatu",
id: 4096,
tag: "en-VU",
version: "Release 10"
},
"en-001": {
language: "English",
location: "World",
id: 4096,
tag: "en-001",
version: "Release 10"
},
"en-zm": {
language: "English",
location: "Zambia",
id: 4096,
tag: "en-ZM",
version: "Release 10"
},
"en-zw": {
language: "English",
location: "Zimbabwe",
id: 12297,
tag: "en-ZW",
version: "Release C"
},
eo: eo,
"eo-001": {
language: "Esperanto",
location: "World",
id: 4096,
tag: "eo-001",
version: "Release 10"
},
et: et,
"et-ee": {
language: "Estonian",
location: "Estonia",
id: 1061,
tag: "et-EE",
version: "Release B"
},
ee: ee,
"ee-gh": {
language: "Ewe",
location: "Ghana",
id: 4096,
tag: "ee-GH",
version: "Release 10"
},
"ee-tg": {
language: "Ewe",
location: "Togo",
id: 4096,
tag: "ee-TG",
version: "Release 10"
},
ewo: ewo,
"ewo-cm": {
language: "Ewondo",
location: "Cameroon",
id: 4096,
tag: "ewo-CM",
version: "Release 10"
},
fo: fo,
"fo-dk": {
language: "Faroese",
location: "Denmark",
id: 4096,
tag: "fo-DK",
version: "Release 10.1"
},
"fo-fo": {
language: "Faroese",
location: "Faroe Islands",
id: 1080,
tag: "fo-FO",
version: "Release B"
},
fil: fil,
"fil-ph": {
language: "Filipino",
location: "Philippines",
id: 1124,
tag: "fil-PH",
version: "Release E2"
},
fi: fi,
"fi-fi": {
language: "Finnish",
location: "Finland",
id: 1035,
tag: "fi-FI",
version: "Release A"
},
fr: fr,
"fr-dz": {
language: "French",
location: "Algeria",
id: 4096,
tag: "fr-DZ",
version: "Release 10"
},
"fr-be": {
language: "French",
location: "Belgium",
id: 2060,
tag: "fr-BE",
version: "Release A"
},
"fr-bj": {
language: "French",
location: "Benin",
id: 4096,
tag: "fr-BJ",
version: "Release 10"
},
"fr-bf": {
language: "French",
location: "Burkina Faso",
id: 4096,
tag: "fr-BF",
version: "Release 10"
},
"fr-bi": {
language: "French",
location: "Burundi",
id: 4096,
tag: "fr-BI",
version: "Release 10"
},
"fr-cm": {
language: "French",
location: "Cameroon",
id: 11276,
tag: "fr-CM",
version: "Release 8.1"
},
"fr-ca": {
language: "French",
location: "Canada",
id: 3084,
tag: "fr-CA",
version: "Release A"
},
"fr-cf": {
language: "French",
location: "Central African Republic",
id: 4096,
tag: "fr-CF",
version: "Release10"
},
"fr-td": {
language: "French",
location: "Chad",
id: 4096,
tag: "fr-TD",
version: "Release 10"
},
"fr-km": {
language: "French",
location: "Comoros",
id: 4096,
tag: "fr-KM",
version: "Release 10"
},
"fr-cg": {
language: "French",
location: "Congo",
id: 4096,
tag: "fr-CG",
version: "Release 10"
},
"fr-cd": {
language: "French",
location: "Congo, DRC",
id: 9228,
tag: "fr-CD",
version: "Release 8.1"
},
"fr-ci": {
language: "French",
location: "Côte d'Ivoire",
id: 12300,
tag: "fr-CI",
version: "Release 8.1"
},
"fr-dj": {
language: "French",
location: "Djibouti",
id: 4096,
tag: "fr-DJ",
version: "Release 10"
},
"fr-gq": {
language: "French",
location: "Equatorial Guinea",
id: 4096,
tag: "fr-GQ",
version: "Release 10"
},
"fr-fr": {
language: "French",
location: "France",
id: 1036,
tag: "fr-FR",
version: "Release A"
},
"fr-gf": {
language: "French",
location: "French Guiana",
id: 4096,
tag: "fr-GF",
version: "Release 10"
},
"fr-pf": {
language: "French",
location: "French Polynesia",
id: 4096,
tag: "fr-PF",
version: "Release 10"
},
"fr-ga": {
language: "French",
location: "Gabon",
id: 4096,
tag: "fr-GA",
version: "Release 10"
},
"fr-gp": {
language: "French",
location: "Guadeloupe",
id: 4096,
tag: "fr-GP",
version: "Release 10"
},
"fr-gn": {
language: "French",
location: "Guinea",
id: 4096,
tag: "fr-GN",
version: "Release 10"
},
"fr-ht": {
language: "French",
location: "Haiti",
id: 15372,
tag: "fr-HT",
version: "Release 8.1"
},
"fr-lu": {
language: "French",
location: "Luxembourg",
id: 5132,
tag: "fr-LU",
version: "Release A"
},
"fr-mg": {
language: "French",
location: "Madagascar",
id: 4096,
tag: "fr-MG",
version: "Release 10"
},
"fr-ml": {
language: "French",
location: "Mali",
id: 13324,
tag: "fr-ML",
version: "Release 8.1"
},
"fr-mq": {
language: "French",
location: "Martinique",
id: 4096,
tag: "fr-MQ",
version: "Release 10"
},
"fr-mr": {
language: "French",
location: "Mauritania",
id: 4096,
tag: "fr-MR",
version: "Release 10"
},
"fr-mu": {
language: "French",
location: "Mauritius",
id: 4096,
tag: "fr-MU",
version: "Release 10"
},
"fr-yt": {
language: "French",
location: "Mayotte",
id: 4096,
tag: "fr-YT",
version: "Release 10"
},
"fr-ma": {
language: "French",
location: "Morocco",
id: 14348,
tag: "fr-MA",
version: "Release 8.1"
},
"fr-nc": {
language: "French",
location: "New Caledonia",
id: 4096,
tag: "fr-NC",
version: "Release 10"
},
"fr-ne": {
language: "French",
location: "Niger",
id: 4096,
tag: "fr-NE",
version: "Release 10"
},
"fr-mc": {
language: "French",
location: "Principality of Monaco",
id: 6156,
tag: "fr-MC",
version: "Release A"
},
"fr-re": {
language: "French",
location: "Reunion",
id: 8204,
tag: "fr-RE",
version: "Release 8.1"
},
"fr-rw": {
language: "French",
location: "Rwanda",
id: 4096,
tag: "fr-RW",
version: "Release 10"
},
"fr-bl": {
language: "French",
location: "Saint Barthélemy",
id: 4096,
tag: "fr-BL",
version: "Release 10"
},
"fr-mf": {
language: "French",
location: "Saint Martin",
id: 4096,
tag: "fr-MF",
version: "Release 10"
},
"fr-pm": {
language: "French",
location: "Saint Pierre and Miquelon",
id: 4096,
tag: "fr-PM",
version: "Release 10"
},
"fr-sn": {
language: "French",
location: "Senegal",
id: 10252,
tag: "fr-SN",
version: "Release 8.1"
},
"fr-sc": {
language: "French",
location: "Seychelles",
id: 4096,
tag: "fr-SC",
version: "Release 10"
},
"fr-ch": {
language: "French",
location: "Switzerland",
id: 4108,
tag: "fr-CH",
version: "Release A"
},
"fr-sy": {
language: "French",
location: "Syria",
id: 4096,
tag: "fr-SY",
version: "Release 10"
},
"fr-tg": {
language: "French",
location: "Togo",
id: 4096,
tag: "fr-TG",
version: "Release 10"
},
"fr-tn": {
language: "French",
location: "Tunisia",
id: 4096,
tag: "fr-TN",
version: "Release 10"
},
"fr-vu": {
language: "French",
location: "Vanuatu",
id: 4096,
tag: "fr-VU",
version: "Release 10"
},
"fr-wf": {
language: "French",
location: "Wallis and Futuna",
id: 4096,
tag: "fr-WF",
version: "Release 10"
},
fy: fy,
"fy-nl": {
language: "Frisian",
location: "Netherlands",
id: 1122,
tag: "fy-NL",
version: "Release E2"
},
fur: fur,
"fur-it": {
language: "Friulian",
location: "Italy",
id: 4096,
tag: "fur-IT",
version: "Release 10"
},
ff: ff,
"ff-latn": {
language: "Fulah (Latin)",
location: null,
id: 31847,
tag: "ff-Latn",
version: "Release 8"
},
"ff-latn-bf": {
language: "Fulah (Latin)",
location: "Burkina Faso",
id: 4096,
tag: "ff-Latn-BF",
version: "Release 10.4"
},
"ff-cm": {
language: "Fulah",
location: "Cameroon",
id: 4096,
tag: "ff-CM",
version: "Release 10"
},
"ff-latn-cm": {
language: "Fulah (Latin)",
location: "Cameroon",
id: 4096,
tag: "ff-Latn-CM",
version: "Release 10.4"
},
"ff-latn-gm": {
language: "Fulah (Latin)",
location: "Gambia",
id: 4096,
tag: "ff-Latn-GM",
version: "Release 10.4"
},
"ff-latn-gh": {
language: "Fulah (Latin)",
location: "Ghana",
id: 4096,
tag: "ff-Latn-GH",
version: "Release 10.4"
},
"ff-gn": {
language: "Fulah",
location: "Guinea",
id: 4096,
tag: "ff-GN",
version: "Release 10"
},
"ff-latn-gn": {
language: "Fulah (Latin)",
location: "Guinea",
id: 4096,
tag: "ff-Latn-GN",
version: "Release 10.4"
},
"ff-latn-gw": {
language: "Fulah (Latin)",
location: "Guinea-Bissau",
id: 4096,
tag: "ff-Latn-GW",
version: "Release 10.4"
},
"ff-latn-lr": {
language: "Fulah (Latin)",
location: "Liberia",
id: 4096,
tag: "ff-Latn-LR",
version: "Release 10.4"
},
"ff-mr": {
language: "Fulah",
location: "Mauritania",
id: 4096,
tag: "ff-MR",
version: "Release 10"
},
"ff-latn-mr": {
language: "Fulah (Latin)",
location: "Mauritania",
id: 4096,
tag: "ff-Latn-MR",
version: "Release 10.4"
},
"ff-latn-ne": {
language: "Fulah (Latin)",
location: "Niger",
id: 4096,
tag: "ff-Latn-NE",
version: "Release 10.4"
},
"ff-ng": {
language: "Fulah",
location: "Nigeria",
id: 4096,
tag: "ff-NG",
version: "Release 10"
},
"ff-latn-ng": {
language: "Fulah (Latin)",
location: "Nigeria",
id: 4096,
tag: "ff-Latn-NG",
version: "Release 10.4"
},
"ff-latn-sn": {
language: "Fulah",
location: "Senegal",
id: 2151,
tag: "ff-Latn-SN",
version: "Release 8"
},
"ff-latn-sl": {
language: "Fulah (Latin)",
location: "Sierra Leone",
id: 4096,
tag: "ff-Latn-SL",
version: "Release 10.4"
},
gl: gl,
"gl-es": {
language: "Galician",
location: "Spain",
id: 1110,
tag: "gl-ES",
version: "Release D"
},
lg: lg,
"lg-ug": {
language: "Ganda",
location: "Uganda",
id: 4096,
tag: "lg-UG",
version: "Release 10"
},
ka: ka$1,
"ka-ge": {
language: "Georgian",
location: "Georgia",
id: 1079,
tag: "ka-GE",
version: "Release C"
},
de: de,
"de-at": {
language: "German",
location: "Austria",
id: 3079,
tag: "de-AT",
version: "Release A"
},
"de-be": {
language: "German",
location: "Belgium",
id: 4096,
tag: "de-BE",
version: "Release 10"
},
"de-de": {
language: "German",
location: "Germany",
id: 1031,
tag: "de-DE",
version: "Release A"
},
"de-it": {
language: "German",
location: "Italy",
id: 4096,
tag: "de-IT",
version: "Release 10.2"
},
"de-li": {
language: "German",
location: "Liechtenstein",
id: 5127,
tag: "de-LI",
version: "Release B"
},
"de-lu": {
language: "German",
location: "Luxembourg",
id: 4103,
tag: "de-LU",
version: "Release B"
},
"de-ch": {
language: "German",
location: "Switzerland",
id: 2055,
tag: "de-CH",
version: "Release A"
},
el: el,
"el-cy": {
language: "Greek",
location: "Cyprus",
id: 4096,
tag: "el-CY",
version: "Release 10"
},
"el-gr": {
language: "Greek",
location: "Greece",
id: 1032,
tag: "el-GR",
version: "Release A"
},
kl: kl,
"kl-gl": {
language: "Greenlandic",
location: "Greenland",
id: 1135,
tag: "kl-GL",
version: "Release V"
},
gn: gn,
"gn-py": {
language: "Guarani",
location: "Paraguay",
id: 1140,
tag: "gn-PY",
version: "Release 8.1"
},
gu: gu,
"gu-in": {
language: "Gujarati",
location: "India",
id: 1095,
tag: "gu-IN",
version: "Release D"
},
guz: guz,
"guz-ke": {
language: "Gusii",
location: "Kenya",
id: 4096,
tag: "guz-KE",
version: "Release 10"
},
ha: ha,
"ha-latn": {
language: "Hausa (Latin)",
location: null,
id: 31848,
tag: "ha-Latn",
version: "Windows 7"
},
"ha-latn-gh": {
language: "Hausa (Latin)",
location: "Ghana",
id: 4096,
tag: "ha-Latn-GH",
version: "Release 10"
},
"ha-latn-ne": {
language: "Hausa (Latin)",
location: "Niger",
id: 4096,
tag: "ha-Latn-NE",
version: "Release 10"
},
"ha-latn-ng": {
language: "Hausa (Latin)",
location: "Nigeria",
id: 1128,
tag: "ha-Latn-NG",
version: "Release V"
},
haw: haw,
"haw-us": {
language: "Hawaiian",
location: "United States",
id: 1141,
tag: "haw-US",
version: "Release 8"
},
he: he,
"he-il": {
language: "Hebrew",
location: "Israel",
id: 1037,
tag: "he-IL",
version: "Release B"
},
hi: hi,
"hi-in": {
language: "Hindi",
location: "India",
id: 1081,
tag: "hi-IN",
version: "Release C"
},
hu: hu,
"hu-hu": {
language: "Hungarian",
location: "Hungary",
id: 1038,
tag: "hu-HU",
version: "Release A"
},
is: is,
"is-is": {
language: "Icelandic",
location: "Iceland",
id: 1039,
tag: "is-IS",
version: "Release A"
},
ig: ig,
"ig-ng": {
language: "Igbo",
location: "Nigeria",
id: 1136,
tag: "ig-NG",
version: "Release V"
},
id: id,
"id-id": {
language: "Indonesian",
location: "Indonesia",
id: 1057,
tag: "id-ID",
version: "Release B"
},
ia: ia,
"ia-fr": {
language: "Interlingua",
location: "France",
id: 4096,
tag: "ia-FR",
version: "Release 10"
},
"ia-001": {
language: "Interlingua",
location: "World",
id: 4096,
tag: "ia-001",
version: "Release 10"
},
iu: iu,
"iu-latn": {
language: "Inuktitut (Latin)",
location: null,
id: 31837,
tag: "iu-Latn",
version: "Windows 7"
},
"iu-latn-ca": {
language: "Inuktitut (Latin)",
location: "Canada",
id: 2141,
tag: "iu-Latn-CA",
version: "Release E2"
},
"iu-cans": {
language: "Inuktitut (Syllabics)",
location: null,
id: 30813,
tag: "iu-Cans",
version: "Windows 7"
},
"iu-cans-ca": {
language: "Inuktitut (Syllabics)",
location: "Canada",
id: 1117,
tag: "iu-Cans-CA",
version: "Release V"
},
ga: ga,
"ga-ie": {
language: "Irish",
location: "Ireland",
id: 2108,
tag: "ga-IE",
version: "Release E2"
},
it: it,
"it-it": {
language: "Italian",
location: "Italy",
id: 1040,
tag: "it-IT",
version: "Release A"
},
"it-sm": {
language: "Italian",
location: "San Marino",
id: 4096,
tag: "it-SM",
version: "Release 10"
},
"it-ch": {
language: "Italian",
location: "Switzerland",
id: 2064,
tag: "it-CH",
version: "Release A"
},
"it-va": {
language: "Italian",
location: "Vatican City",
id: 4096,
tag: "it-VA",
version: "Release 10.3"
},
ja: ja,
"ja-jp": {
language: "Japanese",
location: "Japan",
id: 1041,
tag: "ja-JP",
version: "Release A"
},
jv: jv,
"jv-latn": {
language: "Javanese",
location: "Latin",
id: 4096,
tag: "jv-Latn",
version: "Release 8.1"
},
"jv-latn-id": {
language: "Javanese",
location: "Latin, Indonesia",
id: 4096,
tag: "jv-Latn-ID",
version: "Release 8.1"
},
dyo: dyo,
"dyo-sn": {
language: "Jola-Fonyi",
location: "Senegal",
id: 4096,
tag: "dyo-SN",
version: "Release 10"
},
kea: kea,
"kea-cv": {
language: "Kabuverdianu",
location: "Cabo Verde",
id: 4096,
tag: "kea-CV",
version: "Release 10"
},
kab: kab,
"kab-dz": {
language: "Kabyle",
location: "Algeria",
id: 4096,
tag: "kab-DZ",
version: "Release 10"
},
kkj: kkj,
"kkj-cm": {
language: "Kako",
location: "Cameroon",
id: 4096,
tag: "kkj-CM",
version: "Release 10"
},
kln: kln,
"kln-ke": {
language: "Kalenjin",
location: "Kenya",
id: 4096,
tag: "kln-KE",
version: "Release 10"
},
kam: kam,
"kam-ke": {
language: "Kamba",
location: "Kenya",
id: 4096,
tag: "kam-KE",
version: "Release 10"
},
kn: kn,
"kn-in": {
language: "Kannada",
location: "India",
id: 1099,
tag: "kn-IN",
version: "Release D"
},
ks: ks,
"ks-arab": {
language: "Kashmiri",
location: "Perso-Arabic",
id: 1120,
tag: "ks-Arab",
version: "Release 10"
},
"ks-arab-in": {
language: "Kashmiri",
location: "Perso-Arabic",
id: 4096,
tag: "ks-Arab-IN",
version: "Release 10"
},
kk: kk,
"kk-kz": {
language: "Kazakh",
location: "Kazakhstan",
id: 1087,
tag: "kk-KZ",
version: "Release C"
},
km: km,
"km-kh": {
language: "Khmer",
location: "Cambodia",
id: 1107,
tag: "km-KH",
version: "Release V"
},
quc: quc,
"quc-latn-gt": {
language: "K'iche",
location: "Guatemala",
id: 1158,
tag: "quc-Latn-GT",
version: "Release 10"
},
ki: ki,
"ki-ke": {
language: "Kikuyu",
location: "Kenya",
id: 4096,
tag: "ki-KE",
version: "Release 10"
},
rw: rw,
"rw-rw": {
language: "Kinyarwanda",
location: "Rwanda",
id: 1159,
tag: "rw-RW",
version: "Release V"
},
sw: sw,
"sw-ke": {
language: "Kiswahili",
location: "Kenya",
id: 1089,
tag: "sw-KE",
version: "Release C"
},
"sw-tz": {
language: "Kiswahili",
location: "Tanzania",
id: 4096,
tag: "sw-TZ",
version: "Release 10"
},
"sw-ug": {
language: "Kiswahili",
location: "Uganda",
id: 4096,
tag: "sw-UG",
version: "Release 10"
},
kok: kok,
"kok-in": {
language: "Konkani",
location: "India",
id: 1111,
tag: "kok-IN",
version: "Release C"
},
ko: ko,
"ko-kr": {
language: "Korean",
location: "Korea",
id: 1042,
tag: "ko-KR",
version: "Release A"
},
"ko-kp": {
language: "Korean",
location: "North Korea",
id: 4096,
tag: "ko-KP",
version: "Release 10.1"
},
khq: khq,
"khq-ml": {
language: "Koyra Chiini",
location: "Mali",
id: 4096,
tag: "khq-ML",
version: "Release 10"
},
ses: ses,
"ses-ml": {
language: "Koyraboro Senni",
location: "Mali",
id: 4096,
tag: "ses-ML",
version: "Release 10"
},
nmg: nmg,
"nmg-cm": {
language: "Kwasio",
location: "Cameroon",
id: 4096,
tag: "nmg-CM",
version: "Release 10"
},
ky: ky$1,
"ky-kg": {
language: "Kyrgyz",
location: "Kyrgyzstan",
id: 1088,
tag: "ky-KG",
version: "Release D"
},
"ku-arab-ir": {
language: "Kurdish",
location: "Perso-Arabic, Iran",
id: 4096,
tag: "ku-Arab-IR",
version: "Release 10.1"
},
lkt: lkt,
"lkt-us": {
language: "Lakota",
location: "United States",
id: 4096,
tag: "lkt-US",
version: "Release 10"
},
lag: lag,
"lag-tz": {
language: "Langi",
location: "Tanzania",
id: 4096,
tag: "lag-TZ",
version: "Release 10"
},
lo: lo,
"lo-la": {
language: "Lao",
location: "Lao P.D.R.",
id: 1108,
tag: "lo-LA",
version: "Release V"
},
lv: lv,
"lv-lv": {
language: "Latvian",
location: "Latvia",
id: 1062,
tag: "lv-LV",
version: "Release B"
},
ln: ln,
"ln-ao": {
language: "Lingala",
location: "Angola",
id: 4096,
tag: "ln-AO",
version: "Release 10"
},
"ln-cf": {
language: "Lingala",
location: "Central African Republic",
id: 4096,
tag: "ln-CF",
version: "Release 10"
},
"ln-cg": {
language: "Lingala",
location: "Congo",
id: 4096,
tag: "ln-CG",
version: "Release 10"
},
"ln-cd": {
language: "Lingala",
location: "Congo DRC",
id: 4096,
tag: "ln-CD",
version: "Release 10"
},
lt: lt,
"lt-lt": {
language: "Lithuanian",
location: "Lithuania",
id: 1063,
tag: "lt-LT",
version: "Release B"
},
nds: nds,
"nds-de": {
language: "Low German",
location: "Germany",
id: 4096,
tag: "nds-DE",
version: "Release 10.2"
},
"nds-nl": {
language: "Low German",
location: "Netherlands",
id: 4096,
tag: "nds-NL",
version: "Release 10.2"
},
dsb: dsb,
"dsb-de": {
language: "Lower Sorbian",
location: "Germany",
id: 2094,
tag: "dsb-DE",
version: "Release V"
},
lu: lu,
"lu-cd": {
language: "Luba-Katanga",
location: "Congo DRC",
id: 4096,
tag: "lu-CD",
version: "Release 10"
},
luo: luo,
"luo-ke": {
language: "Luo",
location: "Kenya",
id: 4096,
tag: "luo-KE",
version: "Release 10"
},
lb: lb,
"lb-lu": {
language: "Luxembourgish",
location: "Luxembourg",
id: 1134,
tag: "lb-LU",
version: "Release E2"
},
luy: luy,
"luy-ke": {
language: "Luyia",
location: "Kenya",
id: 4096,
tag: "luy-KE",
version: "Release 10"
},
mk: mk,
"mk-mk": {
language: "Macedonian",
location: "North Macedonia",
id: 1071,
tag: "mk-MK",
version: "Release C"
},
jmc: jmc,
"jmc-tz": {
language: "Machame",
location: "Tanzania",
id: 4096,
tag: "jmc-TZ",
version: "Release 10"
},
mgh: mgh,
"mgh-mz": {
language: "Makhuwa-Meetto",
location: "Mozambique",
id: 4096,
tag: "mgh-MZ",
version: "Release 10"
},
kde: kde,
"kde-tz": {
language: "Makonde",
location: "Tanzania",
id: 4096,
tag: "kde-TZ",
version: "Release 10"
},
mg: mg,
"mg-mg": {
language: "Malagasy",
location: "Madagascar",
id: 4096,
tag: "mg-MG",
version: "Release 8.1"
},
ms: ms,
"ms-bn": {
language: "Malay",
location: "Brunei Darussalam",
id: 2110,
tag: "ms-BN",
version: "Release C"
},
"ms-my": {
language: "Malay",
location: "Malaysia",
id: 1086,
tag: "ms-MY",
version: "Release C"
},
ml: ml,
"ml-in": {
language: "Malayalam",
location: "India",
id: 1100,
tag: "ml-IN",
version: "Release E1"
},
mt: mt,
"mt-mt": {
language: "Maltese",
location: "Malta",
id: 1082,
tag: "mt-MT",
version: "Release E1"
},
gv: gv,
"gv-im": {
language: "Manx",
location: "Isle of Man",
id: 4096,
tag: "gv-IM",
version: "Release 10"
},
mi: mi,
"mi-nz": {
language: "Maori",
location: "New Zealand",
id: 1153,
tag: "mi-NZ",
version: "Release E1"
},
arn: arn,
"arn-cl": {
language: "Mapudungun",
location: "Chile",
id: 1146,
tag: "arn-CL",
version: "Release E2"
},
mr: mr,
"mr-in": {
language: "Marathi",
location: "India",
id: 1102,
tag: "mr-IN",
version: "Release C"
},
mas: mas,
"mas-ke": {
language: "Masai",
location: "Kenya",
id: 4096,
tag: "mas-KE",
version: "Release 10"
},
"mas-tz": {
language: "Masai",
location: "Tanzania",
id: 4096,
tag: "mas-TZ",
version: "Release 10"
},
"mzn-ir": {
language: "Mazanderani",
location: "Iran",
id: 4096,
tag: "mzn-IR",
version: "Release 10.1"
},
mer: mer,
"mer-ke": {
language: "Meru",
location: "Kenya",
id: 4096,
tag: "mer-KE",
version: "Release 10"
},
mgo: mgo,
"mgo-cm": {
language: "Meta'",
location: "Cameroon",
id: 4096,
tag: "mgo-CM",
version: "Release 10"
},
moh: moh,
"moh-ca": {
language: "Mohawk",
location: "Canada",
id: 1148,
tag: "moh-CA",
version: "Release E2"
},
mn: mn,
"mn-cyrl": {
language: "Mongolian (Cyrillic)",
location: null,
id: 30800,
tag: "mn-Cyrl",
version: "Windows 7"
},
"mn-mn": {
language: "Mongolian (Cyrillic)",
location: "Mongolia",
id: 1104,
tag: "mn-MN",
version: "Release D"
},
"mn-mong": {
language: "Mongolian (Traditional Mongolian)",
location: null,
id: 31824,
tag: "mn-Mong",
version: "Windows 7"
},
"mn-mong-cn": {
language: "Mongolian (Traditional Mongolian)",
location: "People's Republic of China",
id: 2128,
tag: "mn-Mong-CN",
version: "Windows V"
},
"mn-mong-mn": {
language: "Mongolian (Traditional Mongolian)",
location: "Mongolia",
id: 3152,
tag: "mn-Mong-MN",
version: "Windows 7"
},
mfe: mfe,
"mfe-mu": {
language: "Morisyen",
location: "Mauritius",
id: 4096,
tag: "mfe-MU",
version: "Release 10"
},
mua: mua,
"mua-cm": {
language: "Mundang",
location: "Cameroon",
id: 4096,
tag: "mua-CM",
version: "Release 10"
},
nqo: nqo,
"nqo-gn": {
language: "N'ko",
location: "Guinea",
id: 4096,
tag: "nqo-GN",
version: "Release 8.1"
},
naq: naq,
"naq-na": {
language: "Nama",
location: "Namibia",
id: 4096,
tag: "naq-NA",
version: "Release 10"
},
ne: ne,
"ne-in": {
language: "Nepali",
location: "India",
id: 2145,
tag: "ne-IN",
version: "Release 8.1"
},
"ne-np": {
language: "Nepali",
location: "Nepal",
id: 1121,
tag: "ne-NP",
version: "Release E2"
},
nnh: nnh,
"nnh-cm": {
language: "Ngiemboon",
location: "Cameroon",
id: 4096,
tag: "nnh-CM",
version: "Release 10"
},
jgo: jgo,
"jgo-cm": {
language: "Ngomba",
location: "Cameroon",
id: 4096,
tag: "jgo-CM",
version: "Release 10"
},
"lrc-iq": {
language: "Northern Luri",
location: "Iraq",
id: 4096,
tag: "lrc-IQ",
version: "Release 10.1"
},
"lrc-ir": {
language: "Northern Luri",
location: "Iran",
id: 4096,
tag: "lrc-IR",
version: "Release 10.1"
},
nd: nd,
"nd-zw": {
language: "North Ndebele",
location: "Zimbabwe",
id: 4096,
tag: "nd-ZW",
version: "Release 10"
},
no: no,
nb: nb,
"nb-no": {
language: "Norwegian (Bokmal)",
location: "Norway",
id: 1044,
tag: "nb-NO",
version: "Release A"
},
nn: nn,
"nn-no": {
language: "Norwegian (Nynorsk)",
location: "Norway",
id: 2068,
tag: "nn-NO",
version: "Release A"
},
"nb-sj": {
language: "Norwegian Bokmål",
location: "Svalbard and Jan Mayen",
id: 4096,
tag: "nb-SJ",
version: "Release 10"
},
nus: nus,
"nus-sd": {
language: "Nuer",
location: "Sudan",
id: 4096,
tag: "nus-SD",
version: "Release 10"
},
"nus-ss": {
language: "Nuer",
location: "South Sudan",
id: 4096,
tag: "nus-SS",
version: "Release 10.1"
},
nyn: nyn,
"nyn-ug": {
language: "Nyankole",
location: "Uganda",
id: 4096,
tag: "nyn-UG",
version: "Release 10"
},
oc: oc,
"oc-fr": {
language: "Occitan",
location: "France",
id: 1154,
tag: "oc-FR",
version: "Release V"
},
or: or,
"or-in": {
language: "Odia",
location: "India",
id: 1096,
tag: "or-IN",
version: "Release V"
},
om: om,
"om-et": {
language: "Oromo",
location: "Ethiopia",
id: 1138,
tag: "om-ET",
version: "Release 8.1"
},
"om-ke": {
language: "Oromo",
location: "Kenya",
id: 4096,
tag: "om-KE",
version: "Release 10"
},
os: os,
"os-ge": {
language: "Ossetian",
location: "Cyrillic, Georgia",
id: 4096,
tag: "os-GE",
version: "Release 10"
},
"os-ru": {
language: "Ossetian",
location: "Cyrillic, Russia",
id: 4096,
tag: "os-RU",
version: "Release 10"
},
ps: ps,
"ps-af": {
language: "Pashto",
location: "Afghanistan",
id: 1123,
tag: "ps-AF",
version: "Release E2"
},
"ps-pk": {
language: "Pashto",
location: "Pakistan",
id: 4096,
tag: "ps-PK",
version: "Release 10.5"
},
fa: fa,
"fa-af": {
language: "Persian",
location: "Afghanistan",
id: 4096,
tag: "fa-AF",
version: "Release 10"
},
"fa-ir": {
language: "Persian",
location: "Iran",
id: 1065,
tag: "fa-IR",
version: "Release B"
},
pl: pl,
"pl-pl": {
language: "Polish",
location: "Poland",
id: 1045,
tag: "pl-PL",
version: "Release A"
},
pt: pt,
"pt-ao": {
language: "Portuguese",
location: "Angola",
id: 4096,
tag: "pt-AO",
version: "Release 8.1"
},
"pt-br": {
language: "Portuguese",
location: "Brazil",
id: 1046,
tag: "pt-BR",
version: "Release A"
},
"pt-cv": {
language: "Portuguese",
location: "Cabo Verde",
id: 4096,
tag: "pt-CV",
version: "Release 10"
},
"pt-gq": {
language: "Portuguese",
location: "Equatorial Guinea",
id: 4096,
tag: "pt-GQ",
version: "Release 10.2"
},
"pt-gw": {
language: "Portuguese",
location: "Guinea-Bissau",
id: 4096,
tag: "pt-GW",
version: "Release 10"
},
"pt-lu": {
language: "Portuguese",
location: "Luxembourg",
id: 4096,
tag: "pt-LU",
version: "Release 10.2"
},
"pt-mo": {
language: "Portuguese",
location: "Macao SAR",
id: 4096,
tag: "pt-MO",
version: "Release 10"
},
"pt-mz": {
language: "Portuguese",
location: "Mozambique",
id: 4096,
tag: "pt-MZ",
version: "Release 10"
},
"pt-pt": {
language: "Portuguese",
location: "Portugal",
id: 2070,
tag: "pt-PT",
version: "Release A"
},
"pt-st": {
language: "Portuguese",
location: "São Tomé and Príncipe",
id: 4096,
tag: "pt-ST",
version: "Release 10"
},
"pt-ch": {
language: "Portuguese",
location: "Switzerland",
id: 4096,
tag: "pt-CH",
version: "Release 10.2"
},
"pt-tl": {
language: "Portuguese",
location: "Timor-Leste",
id: 4096,
tag: "pt-TL",
version: "Release 10"
},
"prg-001": {
language: "Prussian",
location: null,
id: 4096,
tag: "prg-001",
version: "Release 10.1"
},
"qps-ploca": {
language: "Pseudo Language",
location: "Pseudo locale for east Asian/complex script localization testing",
id: 1534,
tag: "qps-ploca",
version: "Release 7"
},
"qps-ploc": {
language: "Pseudo Language",
location: "Pseudo locale used for localization testing",
id: 1281,
tag: "qps-ploc",
version: "Release 7"
},
"qps-plocm": {
language: "Pseudo Language",
location: "Pseudo locale used for localization testing of mirrored locales",
id: 2559,
tag: "qps-plocm",
version: "Release 7"
},
pa: pa,
"pa-arab": {
language: "Punjabi",
location: null,
id: 31814,
tag: "pa-Arab",
version: "Release 8"
},
"pa-in": {
language: "Punjabi",
location: "India",
id: 1094,
tag: "pa-IN",
version: "Release D"
},
"pa-arab-pk": {
language: "Punjabi",
location: "Islamic Republic of Pakistan",
id: 2118,
tag: "pa-Arab-PK",
version: "Release 8"
},
quz: quz,
"quz-bo": {
language: "Quechua",
location: "Bolivia",
id: 1131,
tag: "quz-BO",
version: "Release E1"
},
"quz-ec": {
language: "Quechua",
location: "Ecuador",
id: 2155,
tag: "quz-EC",
version: "Release E1"
},
"quz-pe": {
language: "Quechua",
location: "Peru",
id: 3179,
tag: "quz-PE",
version: "Release E1"
},
ksh: ksh,
"ksh-de": {
language: "Ripuarian",
location: "Germany",
id: 4096,
tag: "ksh-DE",
version: "Release 10"
},
ro: ro,
"ro-md": {
language: "Romanian",
location: "Moldova",
id: 2072,
tag: "ro-MD",
version: "Release 8.1"
},
"ro-ro": {
language: "Romanian",
location: "Romania",
id: 1048,
tag: "ro-RO",
version: "Release A"
},
rm: rm,
"rm-ch": {
language: "Romansh",
location: "Switzerland",
id: 1047,
tag: "rm-CH",
version: "Release E2"
},
rof: rof,
"rof-tz": {
language: "Rombo",
location: "Tanzania",
id: 4096,
tag: "rof-TZ",
version: "Release 10"
},
rn: rn,
"rn-bi": {
language: "Rundi",
location: "Burundi",
id: 4096,
tag: "rn-BI",
version: "Release 10"
},
ru: ru,
"ru-by": {
language: "Russian",
location: "Belarus",
id: 4096,
tag: "ru-BY",
version: "Release 10"
},
"ru-kz": {
language: "Russian",
location: "Kazakhstan",
id: 4096,
tag: "ru-KZ",
version: "Release 10"
},
"ru-kg": {
language: "Russian",
location: "Kyrgyzstan",
id: 4096,
tag: "ru-KG",
version: "Release 10"
},
"ru-md": {
language: "Russian",
location: "Moldova",
id: 2073,
tag: "ru-MD",
version: "Release 10"
},
"ru-ru": {
language: "Russian",
location: "Russia",
id: 1049,
tag: "ru-RU",
version: "Release A"
},
"ru-ua": {
language: "Russian",
location: "Ukraine",
id: 4096,
tag: "ru-UA",
version: "Release 10"
},
rwk: rwk,
"rwk-tz": {
language: "Rwa",
location: "Tanzania",
id: 4096,
tag: "rwk-TZ",
version: "Release 10"
},
ssy: ssy,
"ssy-er": {
language: "Saho",
location: "Eritrea",
id: 4096,
tag: "ssy-ER",
version: "Release 10"
},
sah: sah,
"sah-ru": {
language: "Sakha",
location: "Russia",
id: 1157,
tag: "sah-RU",
version: "Release V"
},
saq: saq,
"saq-ke": {
language: "Samburu",
location: "Kenya",
id: 4096,
tag: "saq-KE",
version: "Release 10"
},
smn: smn,
"smn-fi": {
language: "Sami (Inari)",
location: "Finland",
id: 9275,
tag: "smn-FI",
version: "Release E1"
},
smj: smj,
"smj-no": {
language: "Sami (Lule)",
location: "Norway",
id: 4155,
tag: "smj-NO",
version: "Release E1"
},
"smj-se": {
language: "Sami (Lule)",
location: "Sweden",
id: 5179,
tag: "smj-SE",
version: "Release E1"
},
se: se,
"se-fi": {
language: "Sami (Northern)",
location: "Finland",
id: 3131,
tag: "se-FI",
version: "Release E1"
},
"se-no": {
language: "Sami (Northern)",
location: "Norway",
id: 1083,
tag: "se-NO",
version: "Release E1"
},
"se-se": {
language: "Sami (Northern)",
location: "Sweden",
id: 2107,
tag: "se-SE",
version: "Release E1"
},
sms: sms,
"sms-fi": {
language: "Sami (Skolt)",
location: "Finland",
id: 8251,
tag: "sms-FI",
version: "Release E1"
},
sma: sma,
"sma-no": {
language: "Sami (Southern)",
location: "Norway",
id: 6203,
tag: "sma-NO",
version: "Release E1"
},
"sma-se": {
language: "Sami (Southern)",
location: "Sweden",
id: 7227,
tag: "sma-SE",
version: "Release E1"
},
sg: sg,
"sg-cf": {
language: "Sango",
location: "Central African Republic",
id: 4096,
tag: "sg-CF",
version: "Release 10"
},
sbp: sbp,
"sbp-tz": {
language: "Sangu",
location: "Tanzania",
id: 4096,
tag: "sbp-TZ",
version: "Release 10"
},
sa: sa,
"sa-in": {
language: "Sanskrit",
location: "India",
id: 1103,
tag: "sa-IN",
version: "Release C"
},
gd: gd,
"gd-gb": {
language: "Scottish Gaelic",
location: "United Kingdom",
id: 1169,
tag: "gd-GB",
version: "Release 7"
},
seh: seh,
"seh-mz": {
language: "Sena",
location: "Mozambique",
id: 4096,
tag: "seh-MZ",
version: "Release 10"
},
"sr-cyrl": {
language: "Serbian (Cyrillic)",
location: null,
id: 27674,
tag: "sr-Cyrl",
version: "Windows 7"
},
"sr-cyrl-ba": {
language: "Serbian (Cyrillic)",
location: "Bosnia and Herzegovina",
id: 7194,
tag: "sr-Cyrl-BA",
version: "Release E1"
},
"sr-cyrl-me": {
language: "Serbian (Cyrillic)",
location: "Montenegro",
id: 12314,
tag: "sr-Cyrl-ME",
version: "Release 7"
},
"sr-cyrl-rs": {
language: "Serbian (Cyrillic)",
location: "Serbia",
id: 10266,
tag: "sr-Cyrl-RS",
version: "Release 7"
},
"sr-cyrl-cs": {
language: "Serbian (Cyrillic)",
location: "Serbia and Montenegro (Former)",
id: 3098,
tag: "sr-Cyrl-CS",
version: "Release B"
},
"sr-latn": {
language: "Serbian (Latin)",
location: null,
id: 28698,
tag: "sr-Latn",
version: "Windows 7"
},
sr: sr,
"sr-latn-ba": {
language: "Serbian (Latin)",
location: "Bosnia and Herzegovina",
id: 6170,
tag: "sr-Latn-BA",
version: "Release E1"
},
"sr-latn-me": {
language: "Serbian (Latin)",
location: "Montenegro",
id: 11290,
tag: "sr-Latn-ME",
version: "Release 7"
},
"sr-latn-rs": {
language: "Serbian (Latin)",
location: "Serbia",
id: 9242,
tag: "sr-Latn-RS",
version: "Release 7"
},
"sr-latn-cs": {
language: "Serbian (Latin)",
location: "Serbia and Montenegro (Former)",
id: 2074,
tag: "sr-Latn-CS",
version: "Release B"
},
nso: nso,
"nso-za": {
language: "Sesotho sa Leboa",
location: "South Africa",
id: 1132,
tag: "nso-ZA",
version: "Release E1"
},
tn: tn,
"tn-bw": {
language: "Setswana",
location: "Botswana",
id: 2098,
tag: "tn-BW",
version: "Release 8"
},
"tn-za": {
language: "Setswana",
location: "South Africa",
id: 1074,
tag: "tn-ZA",
version: "Release E1"
},
ksb: ksb,
"ksb-tz": {
language: "Shambala",
location: "Tanzania",
id: 4096,
tag: "ksb-TZ",
version: "Release 10"
},
sn: sn,
"sn-latn": {
language: "Shona",
location: "Latin",
id: 4096,
tag: "sn-Latn",
version: "Release 8.1"
},
"sn-latn-zw": {
language: "Shona",
location: "Zimbabwe",
id: 4096,
tag: "sn-Latn-ZW",
version: "Release 8.1"
},
sd: sd,
"sd-arab": {
language: "Sindhi",
location: null,
id: 31833,
tag: "sd-Arab",
version: "Release 8"
},
"sd-arab-pk": {
language: "Sindhi",
location: "Islamic Republic of Pakistan",
id: 2137,
tag: "sd-Arab-PK",
version: "Release 8"
},
si: si,
"si-lk": {
language: "Sinhala",
location: "Sri Lanka",
id: 1115,
tag: "si-LK",
version: "Release V"
},
sk: sk,
"sk-sk": {
language: "Slovak",
location: "Slovakia",
id: 1051,
tag: "sk-SK",
version: "Release A"
},
sl: sl,
"sl-si": {
language: "Slovenian",
location: "Slovenia",
id: 1060,
tag: "sl-SI",
version: "Release A"
},
xog: xog,
"xog-ug": {
language: "Soga",
location: "Uganda",
id: 4096,
tag: "xog-UG",
version: "Release 10"
},
so: so,
"so-dj": {
language: "Somali",
location: "Djibouti",
id: 4096,
tag: "so-DJ",
version: "Release 10"
},
"so-et": {
language: "Somali",
location: "Ethiopia",
id: 4096,
tag: "so-ET",
version: "Release 10"
},
"so-ke": {
language: "Somali",
location: "Kenya",
id: 4096,
tag: "so-KE",
version: "Release 10"
},
"so-so": {
language: "Somali",
location: "Somalia",
id: 1143,
tag: "so-SO",
version: "Release 8.1"
},
st: st,
"st-za": {
language: "Sotho",
location: "South Africa",
id: 1072,
tag: "st-ZA",
version: "Release 8.1"
},
nr: nr,
"nr-za": {
language: "South Ndebele",
location: "South Africa",
id: 4096,
tag: "nr-ZA",
version: "Release 10"
},
"st-ls": {
language: "Southern Sotho",
location: "Lesotho",
id: 4096,
tag: "st-LS",
version: "Release 10"
},
es: es,
"es-ar": {
language: "Spanish",
location: "Argentina",
id: 11274,
tag: "es-AR",
version: "Release B"
},
"es-bz": {
language: "Spanish",
location: "Belize",
id: 4096,
tag: "es-BZ",
version: "Release 10.3"
},
"es-ve": {
language: "Spanish",
location: "Bolivarian Republic of Venezuela",
id: 8202,
tag: "es-VE",
version: "Release B"
},
"es-bo": {
language: "Spanish",
location: "Bolivia",
id: 16394,
tag: "es-BO",
version: "Release B"
},
"es-br": {
language: "Spanish",
location: "Brazil",
id: 4096,
tag: "es-BR",
version: "Release 10.2"
},
"es-cl": {
language: "Spanish",
location: "Chile",
id: 13322,
tag: "es-CL",
version: "Release B"
},
"es-co": {
language: "Spanish",
location: "Colombia",
id: 9226,
tag: "es-CO",
version: "Release B"
},
"es-cr": {
language: "Spanish",
location: "Costa Rica",
id: 5130,
tag: "es-CR",
version: "Release B"
},
"es-cu": {
language: "Spanish",
location: "Cuba",
id: 23562,
tag: "es-CU",
version: "Release 10"
},
"es-do": {
language: "Spanish",
location: "Dominican Republic",
id: 7178,
tag: "es-DO",
version: "Release B"
},
"es-ec": {
language: "Spanish",
location: "Ecuador",
id: 12298,
tag: "es-EC",
version: "Release B"
},
"es-sv": {
language: "Spanish",
location: "El Salvador",
id: 17418,
tag: "es-SV",
version: "Release B"
},
"es-gq": {
language: "Spanish",
location: "Equatorial Guinea",
id: 4096,
tag: "es-GQ",
version: "Release 10"
},
"es-gt": {
language: "Spanish",
location: "Guatemala",
id: 4106,
tag: "es-GT",
version: "Release B"
},
"es-hn": {
language: "Spanish",
location: "Honduras",
id: 18442,
tag: "es-HN",
version: "Release B"
},
"es-419": {
language: "Spanish",
location: "Latin America",
id: 22538,
tag: "es-419",
version: "Release 8.1"
},
"es-mx": {
language: "Spanish",
location: "Mexico",
id: 2058,
tag: "es-MX",
version: "Release A"
},
"es-ni": {
language: "Spanish",
location: "Nicaragua",
id: 19466,
tag: "es-NI",
version: "Release B"
},
"es-pa": {
language: "Spanish",
location: "Panama",
id: 6154,
tag: "es-PA",
version: "Release B"
},
"es-py": {
language: "Spanish",
location: "Paraguay",
id: 15370,
tag: "es-PY",
version: "Release B"
},
"es-pe": {
language: "Spanish",
location: "Peru",
id: 10250,
tag: "es-PE",
version: "Release B"
},
"es-ph": {
language: "Spanish",
location: "Philippines",
id: 4096,
tag: "es-PH",
version: "Release 10"
},
"es-pr": {
language: "Spanish",
location: "Puerto Rico",
id: 20490,
tag: "es-PR",
version: "Release B"
},
"es-es_tradnl": {
language: "Spanish",
location: "Spain",
id: 1034,
tag: "es-ES_tradnl",
version: "Release A"
},
"es-es": {
language: "Spanish",
location: "Spain",
id: 3082,
tag: "es-ES",
version: "Release A"
},
"es-us": {
language: "Spanish",
location: "UnitedStates",
id: 21514,
tag: "es-US",
version: "Release V"
},
"es-uy": {
language: "Spanish",
location: "Uruguay",
id: 14346,
tag: "es-UY",
version: "Release B"
},
zgh: zgh,
"zgh-tfng-ma": {
language: "Standard Moroccan Tamazight",
location: "Morocco",
id: 4096,
tag: "zgh-Tfng-MA",
version: "Release 8.1"
},
"zgh-tfng": {
language: "Standard Moroccan Tamazight",
location: "Tifinagh",
id: 4096,
tag: "zgh-Tfng",
version: "Release 8.1"
},
ss: ss,
"ss-za": {
language: "Swati",
location: "South Africa",
id: 4096,
tag: "ss-ZA",
version: "Release 10"
},
"ss-sz": {
language: "Swati",
location: "Swaziland",
id: 4096,
tag: "ss-SZ",
version: "Release 10"
},
sv: sv,
"sv-ax": {
language: "Swedish",
location: "Åland Islands",
id: 4096,
tag: "sv-AX",
version: "Release 10"
},
"sv-fi": {
language: "Swedish",
location: "Finland",
id: 2077,
tag: "sv-FI",
version: "Release B"
},
"sv-se": {
language: "Swedish",
location: "Sweden",
id: 1053,
tag: "sv-SE",
version: "Release A"
},
syr: syr,
"syr-sy": {
language: "Syriac",
location: "Syria",
id: 1114,
tag: "syr-SY",
version: "Release D"
},
shi: shi,
"shi-tfng": {
language: "Tachelhit",
location: "Tifinagh",
id: 4096,
tag: "shi-Tfng",
version: "Release 10"
},
"shi-tfng-ma": {
language: "Tachelhit",
location: "Tifinagh, Morocco",
id: 4096,
tag: "shi-Tfng-MA",
version: "Release 10"
},
"shi-latn": {
language: "Tachelhit (Latin)",
location: null,
id: 4096,
tag: "shi-Latn",
version: "Release 10"
},
"shi-latn-ma": {
language: "Tachelhit (Latin)",
location: "Morocco",
id: 4096,
tag: "shi-Latn-MA",
version: "Release 10"
},
dav: dav,
"dav-ke": {
language: "Taita",
location: "Kenya",
id: 4096,
tag: "dav-KE",
version: "Release 10"
},
tg: tg,
"tg-cyrl": {
language: "Tajik (Cyrillic)",
location: null,
id: 31784,
tag: "tg-Cyrl",
version: "Windows 7"
},
"tg-cyrl-tj": {
language: "Tajik (Cyrillic)",
location: "Tajikistan",
id: 1064,
tag: "tg-Cyrl-TJ",
version: "Release V"
},
tzm: tzm,
"tzm-latn": {
language: "Tamazight (Latin)",
location: null,
id: 31839,
tag: "tzm-Latn",
version: "Windows 7"
},
"tzm-latn-dz": {
language: "Tamazight (Latin)",
location: "Algeria",
id: 2143,
tag: "tzm-Latn-DZ",
version: "Release V"
},
ta: ta,
"ta-in": {
language: "Tamil",
location: "India",
id: 1097,
tag: "ta-IN",
version: "Release C"
},
"ta-my": {
language: "Tamil",
location: "Malaysia",
id: 4096,
tag: "ta-MY",
version: "Release 10"
},
"ta-sg": {
language: "Tamil",
location: "Singapore",
id: 4096,
tag: "ta-SG",
version: "Release 10"
},
"ta-lk": {
language: "Tamil",
location: "Sri Lanka",
id: 2121,
tag: "ta-LK",
version: "Release 8"
},
twq: twq,
"twq-ne": {
language: "Tasawaq",
location: "Niger",
id: 4096,
tag: "twq-NE",
version: "Release 10"
},
tt: tt,
"tt-ru": {
language: "Tatar",
location: "Russia",
id: 1092,
tag: "tt-RU",
version: "Release D"
},
te: te,
"te-in": {
language: "Telugu",
location: "India",
id: 1098,
tag: "te-IN",
version: "Release D"
},
teo: teo,
"teo-ke": {
language: "Teso",
location: "Kenya",
id: 4096,
tag: "teo-KE",
version: "Release 10"
},
"teo-ug": {
language: "Teso",
location: "Uganda",
id: 4096,
tag: "teo-UG",
version: "Release 10"
},
th: th,
"th-th": {
language: "Thai",
location: "Thailand",
id: 1054,
tag: "th-TH",
version: "Release B"
},
bo: bo,
"bo-in": {
language: "Tibetan",
location: "India",
id: 4096,
tag: "bo-IN",
version: "Release 10"
},
"bo-cn": {
language: "Tibetan",
location: "People's Republic of China",
id: 1105,
tag: "bo-CN",
version: "Release V"
},
tig: tig,
"tig-er": {
language: "Tigre",
location: "Eritrea",
id: 4096,
tag: "tig-ER",
version: "Release 10"
},
ti: ti,
"ti-er": {
language: "Tigrinya",
location: "Eritrea",
id: 2163,
tag: "ti-ER",
version: "Release 8"
},
"ti-et": {
language: "Tigrinya",
location: "Ethiopia",
id: 1139,
tag: "ti-ET",
version: "Release 8"
},
to: to,
"to-to": {
language: "Tongan",
location: "Tonga",
id: 4096,
tag: "to-TO",
version: "Release 10"
},
ts: ts,
"ts-za": {
language: "Tsonga",
location: "South Africa",
id: 1073,
tag: "ts-ZA",
version: "Release 8.1"
},
tr: tr,
"tr-cy": {
language: "Turkish",
location: "Cyprus",
id: 4096,
tag: "tr-CY",
version: "Release 10"
},
"tr-tr": {
language: "Turkish",
location: "Turkey",
id: 1055,
tag: "tr-TR",
version: "Release A"
},
tk: tk,
"tk-tm": {
language: "Turkmen",
location: "Turkmenistan",
id: 1090,
tag: "tk-TM",
version: "Release V"
},
uk: uk,
"uk-ua": {
language: "Ukrainian",
location: "Ukraine",
id: 1058,
tag: "uk-UA",
version: "Release B"
},
hsb: hsb,
"hsb-de": {
language: "Upper Sorbian",
location: "Germany",
id: 1070,
tag: "hsb-DE",
version: "Release V"
},
ur: ur,
"ur-in": {
language: "Urdu",
location: "India",
id: 2080,
tag: "ur-IN",
version: "Release 8.1"
},
"ur-pk": {
language: "Urdu",
location: "Islamic Republic of Pakistan",
id: 1056,
tag: "ur-PK",
version: "Release C"
},
ug: ug,
"ug-cn": {
language: "Uyghur",
location: "People's Republic of China",
id: 1152,
tag: "ug-CN",
version: "Release V"
},
"uz-arab": {
language: "Uzbek",
location: "Perso-Arabic",
id: 4096,
tag: "uz-Arab",
version: "Release 10"
},
"uz-arab-af": {
language: "Uzbek",
location: "Perso-Arabic, Afghanistan",
id: 4096,
tag: "uz-Arab-AF",
version: "Release 10"
},
"uz-cyrl": {
language: "Uzbek (Cyrillic)",
location: null,
id: 30787,
tag: "uz-Cyrl",
version: "Windows 7"
},
"uz-cyrl-uz": {
language: "Uzbek (Cyrillic)",
location: "Uzbekistan",
id: 2115,
tag: "uz-Cyrl-UZ",
version: "Release C"
},
uz: uz,
"uz-latn": {
language: "Uzbek (Latin)",
location: null,
id: 31811,
tag: "uz-Latn",
version: "Windows7"
},
"uz-latn-uz": {
language: "Uzbek (Latin)",
location: "Uzbekistan",
id: 1091,
tag: "uz-Latn-UZ",
version: "Release C"
},
vai: vai,
"vai-vaii": {
language: "Vai",
location: null,
id: 4096,
tag: "vai-Vaii",
version: "Release 10"
},
"vai-vaii-lr": {
language: "Vai",
location: "Liberia",
id: 4096,
tag: "vai-Vaii-LR",
version: "Release 10"
},
"vai-latn-lr": {
language: "Vai (Latin)",
location: "Liberia",
id: 4096,
tag: "vai-Latn-LR",
version: "Release 10"
},
"vai-latn": {
language: "Vai (Latin)",
location: null,
id: 4096,
tag: "vai-Latn",
version: "Release 10"
},
"ca-es-": {
language: "Valencian",
location: "Spain",
id: 2051,
tag: "ca-ES-",
version: "Release 8"
},
ve: ve,
"ve-za": {
language: "Venda",
location: "South Africa",
id: 1075,
tag: "ve-ZA",
version: "Release 10"
},
vi: vi,
"vi-vn": {
language: "Vietnamese",
location: "Vietnam",
id: 1066,
tag: "vi-VN",
version: "Release B"
},
vo: vo,
"vo-001": {
language: "Volapük",
location: "World",
id: 4096,
tag: "vo-001",
version: "Release 10"
},
vun: vun,
"vun-tz": {
language: "Vunjo",
location: "Tanzania",
id: 4096,
tag: "vun-TZ",
version: "Release 10"
},
wae: wae,
"wae-ch": {
language: "Walser",
location: "Switzerland",
id: 4096,
tag: "wae-CH",
version: "Release 10"
},
cy: cy,
"cy-gb": {
language: "Welsh",
location: "United Kingdom",
id: 1106,
tag: "cy-GB",
version: "ReleaseE1"
},
wal: wal,
"wal-et": {
language: "Wolaytta",
location: "Ethiopia",
id: 4096,
tag: "wal-ET",
version: "Release 10"
},
wo: wo,
"wo-sn": {
language: "Wolof",
location: "Senegal",
id: 1160,
tag: "wo-SN",
version: "Release V"
},
xh: xh,
"xh-za": {
language: "Xhosa",
location: "South Africa",
id: 1076,
tag: "xh-ZA",
version: "Release E1"
},
yav: yav,
"yav-cm": {
language: "Yangben",
location: "Cameroon",
id: 4096,
tag: "yav-CM",
version: "Release 10"
},
ii: ii,
"ii-cn": {
language: "Yi",
location: "People's Republic of China",
id: 1144,
tag: "ii-CN",
version: "Release V"
},
yo: yo,
"yo-bj": {
language: "Yoruba",
location: "Benin",
id: 4096,
tag: "yo-BJ",
version: "Release 10"
},
"yo-ng": {
language: "Yoruba",
location: "Nigeria",
id: 1130,
tag: "yo-NG",
version: "Release V"
},
dje: dje,
"dje-ne": {
language: "Zarma",
location: "Niger",
id: 4096,
tag: "dje-NE",
version: "Release 10"
},
zu: zu,
"zu-za": {
language: "Zulu",
location: "South Africa",
id: 1077,
tag: "zu-ZA",
version: "Release E1"
}
};
var Abkhazian = {
name: "Abkhazian",
names: [
"Abkhazian"
],
"iso639-2": "abk",
"iso639-1": "ab"
};
var Achinese = {
name: "Achinese",
names: [
"Achinese"
],
"iso639-2": "ace",
"iso639-1": null
};
var Acoli = {
name: "Acoli",
names: [
"Acoli"
],
"iso639-2": "ach",
"iso639-1": null
};
var Adangme = {
name: "Adangme",
names: [
"Adangme"
],
"iso639-2": "ada",
"iso639-1": null
};
var Adygei = {
name: "Adygei",
names: [
"Adyghe",
"Adygei"
],
"iso639-2": "ady",
"iso639-1": null
};
var Adyghe = {
name: "Adyghe",
names: [
"Adyghe",
"Adygei"
],
"iso639-2": "ady",
"iso639-1": null
};
var Afar = {
name: "Afar",
names: [
"Afar"
],
"iso639-2": "aar",
"iso639-1": "aa"
};
var Afrihili = {
name: "Afrihili",
names: [
"Afrihili"
],
"iso639-2": "afh",
"iso639-1": null
};
var Afrikaans = {
name: "Afrikaans",
names: [
"Afrikaans"
],
"iso639-2": "afr",
"iso639-1": "af"
};
var Ainu = {
name: "Ainu",
names: [
"Ainu"
],
"iso639-2": "ain",
"iso639-1": null
};
var Akan = {
name: "Akan",
names: [
"Akan"
],
"iso639-2": "aka",
"iso639-1": "ak"
};
var Akkadian = {
name: "Akkadian",
names: [
"Akkadian"
],
"iso639-2": "akk",
"iso639-1": null
};
var Albanian = {
name: "Albanian",
names: [
"Albanian"
],
"iso639-2": "alb/sqi",
"iso639-1": "sq"
};
var Alemannic = {
name: "Alemannic",
names: [
"Swiss German",
"Alemannic",
"Alsatian"
],
"iso639-2": "gsw",
"iso639-1": null
};
var Aleut = {
name: "Aleut",
names: [
"Aleut"
],
"iso639-2": "ale",
"iso639-1": null
};
var Alsatian = {
name: "Alsatian",
names: [
"Swiss German",
"Alemannic",
"Alsatian"
],
"iso639-2": "gsw",
"iso639-1": null
};
var Amharic = {
name: "Amharic",
names: [
"Amharic"
],
"iso639-2": "amh",
"iso639-1": "am"
};
var Angika = {
name: "Angika",
names: [
"Angika"
],
"iso639-2": "anp",
"iso639-1": null
};
var Arabic = {
name: "Arabic",
names: [
"Arabic"
],
"iso639-2": "ara",
"iso639-1": "ar"
};
var Aragonese = {
name: "Aragonese",
names: [
"Aragonese"
],
"iso639-2": "arg",
"iso639-1": "an"
};
var Arapaho = {
name: "Arapaho",
names: [
"Arapaho"
],
"iso639-2": "arp",
"iso639-1": null
};
var Arawak = {
name: "Arawak",
names: [
"Arawak"
],
"iso639-2": "arw",
"iso639-1": null
};
var Armenian = {
name: "Armenian",
names: [
"Armenian"
],
"iso639-2": "arm/hye",
"iso639-1": "hy"
};
var Aromanian = {
name: "Aromanian",
names: [
"Aromanian",
"Arumanian",
"Macedo-Romanian"
],
"iso639-2": "rup",
"iso639-1": null
};
var Arumanian = {
name: "Arumanian",
names: [
"Aromanian",
"Arumanian",
"Macedo-Romanian"
],
"iso639-2": "rup",
"iso639-1": null
};
var Assamese = {
name: "Assamese",
names: [
"Assamese"
],
"iso639-2": "asm",
"iso639-1": "as"
};
var Asturian = {
name: "Asturian",
names: [
"Asturian",
"Bable",
"Leonese",
"Asturleonese"
],
"iso639-2": "ast",
"iso639-1": null
};
var Asturleonese = {
name: "Asturleonese",
names: [
"Asturian",
"Bable",
"Leonese",
"Asturleonese"
],
"iso639-2": "ast",
"iso639-1": null
};
var Avaric = {
name: "Avaric",
names: [
"Avaric"
],
"iso639-2": "ava",
"iso639-1": "av"
};
var Avestan = {
name: "Avestan",
names: [
"Avestan"
],
"iso639-2": "ave",
"iso639-1": "ae"
};
var Awadhi = {
name: "Awadhi",
names: [
"Awadhi"
],
"iso639-2": "awa",
"iso639-1": null
};
var Aymara = {
name: "Aymara",
names: [
"Aymara"
],
"iso639-2": "aym",
"iso639-1": "ay"
};
var Azerbaijani = {
name: "Azerbaijani",
names: [
"Azerbaijani"
],
"iso639-2": "aze",
"iso639-1": "az"
};
var Bable = {
name: "Bable",
names: [
"Asturian",
"Bable",
"Leonese",
"Asturleonese"
],
"iso639-2": "ast",
"iso639-1": null
};
var Balinese = {
name: "Balinese",
names: [
"Balinese"
],
"iso639-2": "ban",
"iso639-1": null
};
var Baluchi = {
name: "Baluchi",
names: [
"Baluchi"
],
"iso639-2": "bal",
"iso639-1": null
};
var Bambara = {
name: "Bambara",
names: [
"Bambara"
],
"iso639-2": "bam",
"iso639-1": "bm"
};
var Basa = {
name: "Basa",
names: [
"Basa"
],
"iso639-2": "bas",
"iso639-1": null
};
var Bashkir = {
name: "Bashkir",
names: [
"Bashkir"
],
"iso639-2": "bak",
"iso639-1": "ba"
};
var Basque = {
name: "Basque",
names: [
"Basque"
],
"iso639-2": "baq/eus",
"iso639-1": "eu"
};
var Bedawiyet = {
name: "Bedawiyet",
names: [
"Beja",
"Bedawiyet"
],
"iso639-2": "bej",
"iso639-1": null
};
var Beja = {
name: "Beja",
names: [
"Beja",
"Bedawiyet"
],
"iso639-2": "bej",
"iso639-1": null
};
var Belarusian = {
name: "Belarusian",
names: [
"Belarusian"
],
"iso639-2": "bel",
"iso639-1": "be"
};
var Bemba = {
name: "Bemba",
names: [
"Bemba"
],
"iso639-2": "bem",
"iso639-1": null
};
var Bengali = {
name: "Bengali",
names: [
"Bengali"
],
"iso639-2": "ben",
"iso639-1": "bn"
};
var Bhojpuri = {
name: "Bhojpuri",
names: [
"Bhojpuri"
],
"iso639-2": "bho",
"iso639-1": null
};
var Bikol = {
name: "Bikol",
names: [
"Bikol"
],
"iso639-2": "bik",
"iso639-1": null
};
var Bilin = {
name: "Bilin",
names: [
"Blin",
"Bilin"
],
"iso639-2": "byn",
"iso639-1": null
};
var Bini = {
name: "Bini",
names: [
"Bini",
"Edo"
],
"iso639-2": "bin",
"iso639-1": null
};
var Bislama = {
name: "Bislama",
names: [
"Bislama"
],
"iso639-2": "bis",
"iso639-1": "bi"
};
var Blin = {
name: "Blin",
names: [
"Blin",
"Bilin"
],
"iso639-2": "byn",
"iso639-1": null
};
var Bliss = {
name: "Bliss",
names: [
"Blissymbols",
"Blissymbolics",
"Bliss"
],
"iso639-2": "zbl",
"iso639-1": null
};
var Blissymbolics = {
name: "Blissymbolics",
names: [
"Blissymbols",
"Blissymbolics",
"Bliss"
],
"iso639-2": "zbl",
"iso639-1": null
};
var Blissymbols = {
name: "Blissymbols",
names: [
"Blissymbols",
"Blissymbolics",
"Bliss"
],
"iso639-2": "zbl",
"iso639-1": null
};
var Bosnian = {
name: "Bosnian",
names: [
"Bosnian"
],
"iso639-2": "bos",
"iso639-1": "bs"
};
var Braj = {
name: "Braj",
names: [
"Braj"
],
"iso639-2": "bra",
"iso639-1": null
};
var Breton = {
name: "Breton",
names: [
"Breton"
],
"iso639-2": "bre",
"iso639-1": "br"
};
var Buginese = {
name: "Buginese",
names: [
"Buginese"
],
"iso639-2": "bug",
"iso639-1": null
};
var Bulgarian = {
name: "Bulgarian",
names: [
"Bulgarian"
],
"iso639-2": "bul",
"iso639-1": "bg"
};
var Buriat = {
name: "Buriat",
names: [
"Buriat"
],
"iso639-2": "bua",
"iso639-1": null
};
var Burmese = {
name: "Burmese",
names: [
"Burmese"
],
"iso639-2": "bur/mya",
"iso639-1": "my"
};
var Caddo = {
name: "Caddo",
names: [
"Caddo"
],
"iso639-2": "cad",
"iso639-1": null
};
var Castilian = {
name: "Castilian",
names: [
"Spanish",
"Castilian"
],
"iso639-2": "spa",
"iso639-1": "es"
};
var Catalan = {
name: "Catalan",
names: [
"Catalan",
"Valencian"
],
"iso639-2": "cat",
"iso639-1": "ca"
};
var Cebuano = {
name: "Cebuano",
names: [
"Cebuano"
],
"iso639-2": "ceb",
"iso639-1": null
};
var Chagatai = {
name: "Chagatai",
names: [
"Chagatai"
],
"iso639-2": "chg",
"iso639-1": null
};
var Chamorro = {
name: "Chamorro",
names: [
"Chamorro"
],
"iso639-2": "cha",
"iso639-1": "ch"
};
var Chechen = {
name: "Chechen",
names: [
"Chechen"
],
"iso639-2": "che",
"iso639-1": "ce"
};
var Cherokee = {
name: "Cherokee",
names: [
"Cherokee"
],
"iso639-2": "chr",
"iso639-1": null
};
var Chewa = {
name: "Chewa",
names: [
"Chichewa",
"Chewa",
"Nyanja"
],
"iso639-2": "nya",
"iso639-1": "ny"
};
var Cheyenne = {
name: "Cheyenne",
names: [
"Cheyenne"
],
"iso639-2": "chy",
"iso639-1": null
};
var Chibcha = {
name: "Chibcha",
names: [
"Chibcha"
],
"iso639-2": "chb",
"iso639-1": null
};
var Chichewa = {
name: "Chichewa",
names: [
"Chichewa",
"Chewa",
"Nyanja"
],
"iso639-2": "nya",
"iso639-1": "ny"
};
var Chinese = {
name: "Chinese",
names: [
"Chinese"
],
"iso639-2": "chi/zho",
"iso639-1": "zh"
};
var Chipewyan = {
name: "Chipewyan",
names: [
"Chipewyan",
"Dene Suline"
],
"iso639-2": "chp",
"iso639-1": null
};
var Choctaw = {
name: "Choctaw",
names: [
"Choctaw"
],
"iso639-2": "cho",
"iso639-1": null
};
var Chuang = {
name: "Chuang",
names: [
"Zhuang",
"Chuang"
],
"iso639-2": "zha",
"iso639-1": "za"
};
var Chuukese = {
name: "Chuukese",
names: [
"Chuukese"
],
"iso639-2": "chk",
"iso639-1": null
};
var Chuvash = {
name: "Chuvash",
names: [
"Chuvash"
],
"iso639-2": "chv",
"iso639-1": "cv"
};
var Coptic = {
name: "Coptic",
names: [
"Coptic"
],
"iso639-2": "cop",
"iso639-1": null
};
var Cornish = {
name: "Cornish",
names: [
"Cornish"
],
"iso639-2": "cor",
"iso639-1": "kw"
};
var Corsican = {
name: "Corsican",
names: [
"Corsican"
],
"iso639-2": "cos",
"iso639-1": "co"
};
var Cree = {
name: "Cree",
names: [
"Cree"
],
"iso639-2": "cre",
"iso639-1": "cr"
};
var Creek = {
name: "Creek",
names: [
"Creek"
],
"iso639-2": "mus",
"iso639-1": null
};
var Croatian = {
name: "Croatian",
names: [
"Croatian"
],
"iso639-2": "hrv",
"iso639-1": "hr"
};
var Czech = {
name: "Czech",
names: [
"Czech"
],
"iso639-2": "cze/ces",
"iso639-1": "cs"
};
var Dakota = {
name: "Dakota",
names: [
"Dakota"
],
"iso639-2": "dak",
"iso639-1": null
};
var Danish = {
name: "Danish",
names: [
"Danish"
],
"iso639-2": "dan",
"iso639-1": "da"
};
var Dargwa = {
name: "Dargwa",
names: [
"Dargwa"
],
"iso639-2": "dar",
"iso639-1": null
};
var Delaware = {
name: "Delaware",
names: [
"Delaware"
],
"iso639-2": "del",
"iso639-1": null
};
var Dhivehi = {
name: "Dhivehi",
names: [
"Divehi",
"Dhivehi",
"Maldivian"
],
"iso639-2": "div",
"iso639-1": "dv"
};
var Dimili = {
name: "Dimili",
names: [
"Zaza",
"Dimili",
"Dimli",
"Kirdki",
"Kirmanjki",
"Zazaki"
],
"iso639-2": "zza",
"iso639-1": null
};
var Dimli = {
name: "Dimli",
names: [
"Zaza",
"Dimili",
"Dimli",
"Kirdki",
"Kirmanjki",
"Zazaki"
],
"iso639-2": "zza",
"iso639-1": null
};
var Dinka = {
name: "Dinka",
names: [
"Dinka"
],
"iso639-2": "din",
"iso639-1": null
};
var Divehi = {
name: "Divehi",
names: [
"Divehi",
"Dhivehi",
"Maldivian"
],
"iso639-2": "div",
"iso639-1": "dv"
};
var Dogri = {
name: "Dogri",
names: [
"Dogri"
],
"iso639-2": "doi",
"iso639-1": null
};
var Dogrib = {
name: "Dogrib",
names: [
"Dogrib"
],
"iso639-2": "dgr",
"iso639-1": null
};
var Duala = {
name: "Duala",
names: [
"Duala"
],
"iso639-2": "dua",
"iso639-1": null
};
var Dutch = {
name: "Dutch",
names: [
"Dutch",
"Flemish"
],
"iso639-2": "dut/nld",
"iso639-1": "nl"
};
var Dyula = {
name: "Dyula",
names: [
"Dyula"
],
"iso639-2": "dyu",
"iso639-1": null
};
var Dzongkha = {
name: "Dzongkha",
names: [
"Dzongkha"
],
"iso639-2": "dzo",
"iso639-1": "dz"
};
var Edo = {
name: "Edo",
names: [
"Bini",
"Edo"
],
"iso639-2": "bin",
"iso639-1": null
};
var Efik = {
name: "Efik",
names: [
"Efik"
],
"iso639-2": "efi",
"iso639-1": null
};
var Ekajuk = {
name: "Ekajuk",
names: [
"Ekajuk"
],
"iso639-2": "eka",
"iso639-1": null
};
var Elamite = {
name: "Elamite",
names: [
"Elamite"
],
"iso639-2": "elx",
"iso639-1": null
};
var English = {
name: "English",
names: [
"English"
],
"iso639-2": "eng",
"iso639-1": "en"
};
var Erzya = {
name: "Erzya",
names: [
"Erzya"
],
"iso639-2": "myv",
"iso639-1": null
};
var Esperanto = {
name: "Esperanto",
names: [
"Esperanto"
],
"iso639-2": "epo",
"iso639-1": "eo"
};
var Estonian = {
name: "Estonian",
names: [
"Estonian"
],
"iso639-2": "est",
"iso639-1": "et"
};
var Ewe = {
name: "Ewe",
names: [
"Ewe"
],
"iso639-2": "ewe",
"iso639-1": "ee"
};
var Ewondo = {
name: "Ewondo",
names: [
"Ewondo"
],
"iso639-2": "ewo",
"iso639-1": null
};
var Fang = {
name: "Fang",
names: [
"Fang"
],
"iso639-2": "fan",
"iso639-1": null
};
var Fanti = {
name: "Fanti",
names: [
"Fanti"
],
"iso639-2": "fat",
"iso639-1": null
};
var Faroese = {
name: "Faroese",
names: [
"Faroese"
],
"iso639-2": "fao",
"iso639-1": "fo"
};
var Fijian = {
name: "Fijian",
names: [
"Fijian"
],
"iso639-2": "fij",
"iso639-1": "fj"
};
var Filipino = {
name: "Filipino",
names: [
"Filipino",
"Pilipino"
],
"iso639-2": "fil",
"iso639-1": null
};
var Finnish = {
name: "Finnish",
names: [
"Finnish"
],
"iso639-2": "fin",
"iso639-1": "fi"
};
var Flemish = {
name: "Flemish",
names: [
"Dutch",
"Flemish"
],
"iso639-2": "dut/nld",
"iso639-1": "nl"
};
var Fon = {
name: "Fon",
names: [
"Fon"
],
"iso639-2": "fon",
"iso639-1": null
};
var French = {
name: "French",
names: [
"French"
],
"iso639-2": "fre/fra",
"iso639-1": "fr"
};
var Friulian = {
name: "Friulian",
names: [
"Friulian"
],
"iso639-2": "fur",
"iso639-1": null
};
var Fulah = {
name: "Fulah",
names: [
"Fulah"
],
"iso639-2": "ful",
"iso639-1": "ff"
};
var Ga = {
name: "Ga",
names: [
"Ga"
],
"iso639-2": "gaa",
"iso639-1": null
};
var Gaelic = {
name: "Gaelic",
names: [
"Gaelic",
"Scottish Gaelic"
],
"iso639-2": "gla",
"iso639-1": "gd"
};
var Galician = {
name: "Galician",
names: [
"Galician"
],
"iso639-2": "glg",
"iso639-1": "gl"
};
var Ganda = {
name: "Ganda",
names: [
"Ganda"
],
"iso639-2": "lug",
"iso639-1": "lg"
};
var Gayo = {
name: "Gayo",
names: [
"Gayo"
],
"iso639-2": "gay",
"iso639-1": null
};
var Gbaya = {
name: "Gbaya",
names: [
"Gbaya"
],
"iso639-2": "gba",
"iso639-1": null
};
var Geez = {
name: "Geez",
names: [
"Geez"
],
"iso639-2": "gez",
"iso639-1": null
};
var Georgian = {
name: "Georgian",
names: [
"Georgian"
],
"iso639-2": "geo/kat",
"iso639-1": "ka"
};
var German = {
name: "German",
names: [
"German"
],
"iso639-2": "ger/deu",
"iso639-1": "de"
};
var Gikuyu = {
name: "Gikuyu",
names: [
"Kikuyu",
"Gikuyu"
],
"iso639-2": "kik",
"iso639-1": "ki"
};
var Gilbertese = {
name: "Gilbertese",
names: [
"Gilbertese"
],
"iso639-2": "gil",
"iso639-1": null
};
var Gondi = {
name: "Gondi",
names: [
"Gondi"
],
"iso639-2": "gon",
"iso639-1": null
};
var Gorontalo = {
name: "Gorontalo",
names: [
"Gorontalo"
],
"iso639-2": "gor",
"iso639-1": null
};
var Gothic = {
name: "Gothic",
names: [
"Gothic"
],
"iso639-2": "got",
"iso639-1": null
};
var Grebo = {
name: "Grebo",
names: [
"Grebo"
],
"iso639-2": "grb",
"iso639-1": null
};
var Greenlandic = {
name: "Greenlandic",
names: [
"Kalaallisut",
"Greenlandic"
],
"iso639-2": "kal",
"iso639-1": "kl"
};
var Guarani = {
name: "Guarani",
names: [
"Guarani"
],
"iso639-2": "grn",
"iso639-1": "gn"
};
var Gujarati = {
name: "Gujarati",
names: [
"Gujarati"
],
"iso639-2": "guj",
"iso639-1": "gu"
};
var Haida = {
name: "Haida",
names: [
"Haida"
],
"iso639-2": "hai",
"iso639-1": null
};
var Haitian = {
name: "Haitian",
names: [
"Haitian",
"Haitian Creole"
],
"iso639-2": "hat",
"iso639-1": "ht"
};
var Hausa = {
name: "Hausa",
names: [
"Hausa"
],
"iso639-2": "hau",
"iso639-1": "ha"
};
var Hawaiian = {
name: "Hawaiian",
names: [
"Hawaiian"
],
"iso639-2": "haw",
"iso639-1": null
};
var Hebrew = {
name: "Hebrew",
names: [
"Hebrew"
],
"iso639-2": "heb",
"iso639-1": "he"
};
var Herero = {
name: "Herero",
names: [
"Herero"
],
"iso639-2": "her",
"iso639-1": "hz"
};
var Hiligaynon = {
name: "Hiligaynon",
names: [
"Hiligaynon"
],
"iso639-2": "hil",
"iso639-1": null
};
var Hindi = {
name: "Hindi",
names: [
"Hindi"
],
"iso639-2": "hin",
"iso639-1": "hi"
};
var Hittite = {
name: "Hittite",
names: [
"Hittite"
],
"iso639-2": "hit",
"iso639-1": null
};
var Hmong = {
name: "Hmong",
names: [
"Hmong",
"Mong"
],
"iso639-2": "hmn",
"iso639-1": null
};
var Hungarian = {
name: "Hungarian",
names: [
"Hungarian"
],
"iso639-2": "hun",
"iso639-1": "hu"
};
var Hupa = {
name: "Hupa",
names: [
"Hupa"
],
"iso639-2": "hup",
"iso639-1": null
};
var Iban = {
name: "Iban",
names: [
"Iban"
],
"iso639-2": "iba",
"iso639-1": null
};
var Icelandic = {
name: "Icelandic",
names: [
"Icelandic"
],
"iso639-2": "ice/isl",
"iso639-1": "is"
};
var Ido = {
name: "Ido",
names: [
"Ido"
],
"iso639-2": "ido",
"iso639-1": "io"
};
var Igbo = {
name: "Igbo",
names: [
"Igbo"
],
"iso639-2": "ibo",
"iso639-1": "ig"
};
var Iloko = {
name: "Iloko",
names: [
"Iloko"
],
"iso639-2": "ilo",
"iso639-1": null
};
var Indonesian = {
name: "Indonesian",
names: [
"Indonesian"
],
"iso639-2": "ind",
"iso639-1": "id"
};
var Ingush = {
name: "Ingush",
names: [
"Ingush"
],
"iso639-2": "inh",
"iso639-1": null
};
var Interlingue = {
name: "Interlingue",
names: [
"Interlingue",
"Occidental"
],
"iso639-2": "ile",
"iso639-1": "ie"
};
var Inuktitut = {
name: "Inuktitut",
names: [
"Inuktitut"
],
"iso639-2": "iku",
"iso639-1": "iu"
};
var Inupiaq = {
name: "Inupiaq",
names: [
"Inupiaq"
],
"iso639-2": "ipk",
"iso639-1": "ik"
};
var Irish = {
name: "Irish",
names: [
"Irish"
],
"iso639-2": "gle",
"iso639-1": "ga"
};
var Italian = {
name: "Italian",
names: [
"Italian"
],
"iso639-2": "ita",
"iso639-1": "it"
};
var Japanese = {
name: "Japanese",
names: [
"Japanese"
],
"iso639-2": "jpn",
"iso639-1": "ja"
};
var Javanese = {
name: "Javanese",
names: [
"Javanese"
],
"iso639-2": "jav",
"iso639-1": "jv"
};
var Jingpho = {
name: "Jingpho",
names: [
"Kachin",
"Jingpho"
],
"iso639-2": "kac",
"iso639-1": null
};
var Kabardian = {
name: "Kabardian",
names: [
"Kabardian"
],
"iso639-2": "kbd",
"iso639-1": null
};
var Kabyle = {
name: "Kabyle",
names: [
"Kabyle"
],
"iso639-2": "kab",
"iso639-1": null
};
var Kachin = {
name: "Kachin",
names: [
"Kachin",
"Jingpho"
],
"iso639-2": "kac",
"iso639-1": null
};
var Kalaallisut = {
name: "Kalaallisut",
names: [
"Kalaallisut",
"Greenlandic"
],
"iso639-2": "kal",
"iso639-1": "kl"
};
var Kalmyk = {
name: "Kalmyk",
names: [
"Kalmyk",
"Oirat"
],
"iso639-2": "xal",
"iso639-1": null
};
var Kamba = {
name: "Kamba",
names: [
"Kamba"
],
"iso639-2": "kam",
"iso639-1": null
};
var Kannada = {
name: "Kannada",
names: [
"Kannada"
],
"iso639-2": "kan",
"iso639-1": "kn"
};
var Kanuri = {
name: "Kanuri",
names: [
"Kanuri"
],
"iso639-2": "kau",
"iso639-1": "kr"
};
var Kapampangan = {
name: "Kapampangan",
names: [
"Pampanga",
"Kapampangan"
],
"iso639-2": "pam",
"iso639-1": null
};
var Karelian = {
name: "Karelian",
names: [
"Karelian"
],
"iso639-2": "krl",
"iso639-1": null
};
var Kashmiri = {
name: "Kashmiri",
names: [
"Kashmiri"
],
"iso639-2": "kas",
"iso639-1": "ks"
};
var Kashubian = {
name: "Kashubian",
names: [
"Kashubian"
],
"iso639-2": "csb",
"iso639-1": null
};
var Kawi = {
name: "Kawi",
names: [
"Kawi"
],
"iso639-2": "kaw",
"iso639-1": null
};
var Kazakh = {
name: "Kazakh",
names: [
"Kazakh"
],
"iso639-2": "kaz",
"iso639-1": "kk"
};
var Khasi = {
name: "Khasi",
names: [
"Khasi"
],
"iso639-2": "kha",
"iso639-1": null
};
var Khotanese = {
name: "Khotanese",
names: [
"Khotanese",
"Sakan"
],
"iso639-2": "kho",
"iso639-1": null
};
var Kikuyu = {
name: "Kikuyu",
names: [
"Kikuyu",
"Gikuyu"
],
"iso639-2": "kik",
"iso639-1": "ki"
};
var Kimbundu = {
name: "Kimbundu",
names: [
"Kimbundu"
],
"iso639-2": "kmb",
"iso639-1": null
};
var Kinyarwanda = {
name: "Kinyarwanda",
names: [
"Kinyarwanda"
],
"iso639-2": "kin",
"iso639-1": "rw"
};
var Kirdki = {
name: "Kirdki",
names: [
"Zaza",
"Dimili",
"Dimli",
"Kirdki",
"Kirmanjki",
"Zazaki"
],
"iso639-2": "zza",
"iso639-1": null
};
var Kirghiz = {
name: "Kirghiz",
names: [
"Kirghiz",
"Kyrgyz"
],
"iso639-2": "kir",
"iso639-1": "ky"
};
var Kirmanjki = {
name: "Kirmanjki",
names: [
"Zaza",
"Dimili",
"Dimli",
"Kirdki",
"Kirmanjki",
"Zazaki"
],
"iso639-2": "zza",
"iso639-1": null
};
var Klingon = {
name: "Klingon",
names: [
"Klingon",
"tlhIngan-Hol"
],
"iso639-2": "tlh",
"iso639-1": null
};
var Komi = {
name: "Komi",
names: [
"Komi"
],
"iso639-2": "kom",
"iso639-1": "kv"
};
var Kongo = {
name: "Kongo",
names: [
"Kongo"
],
"iso639-2": "kon",
"iso639-1": "kg"
};
var Konkani = {
name: "Konkani",
names: [
"Konkani"
],
"iso639-2": "kok",
"iso639-1": null
};
var Korean = {
name: "Korean",
names: [
"Korean"
],
"iso639-2": "kor",
"iso639-1": "ko"
};
var Kosraean = {
name: "Kosraean",
names: [
"Kosraean"
],
"iso639-2": "kos",
"iso639-1": null
};
var Kpelle = {
name: "Kpelle",
names: [
"Kpelle"
],
"iso639-2": "kpe",
"iso639-1": null
};
var Kuanyama = {
name: "Kuanyama",
names: [
"Kuanyama",
"Kwanyama"
],
"iso639-2": "kua",
"iso639-1": "kj"
};
var Kumyk = {
name: "Kumyk",
names: [
"Kumyk"
],
"iso639-2": "kum",
"iso639-1": null
};
var Kurdish = {
name: "Kurdish",
names: [
"Kurdish"
],
"iso639-2": "kur",
"iso639-1": "ku"
};
var Kurukh = {
name: "Kurukh",
names: [
"Kurukh"
],
"iso639-2": "kru",
"iso639-1": null
};
var Kutenai = {
name: "Kutenai",
names: [
"Kutenai"
],
"iso639-2": "kut",
"iso639-1": null
};
var Kwanyama = {
name: "Kwanyama",
names: [
"Kuanyama",
"Kwanyama"
],
"iso639-2": "kua",
"iso639-1": "kj"
};
var Kyrgyz = {
name: "Kyrgyz",
names: [
"Kirghiz",
"Kyrgyz"
],
"iso639-2": "kir",
"iso639-1": "ky"
};
var Ladino = {
name: "Ladino",
names: [
"Ladino"
],
"iso639-2": "lad",
"iso639-1": null
};
var Lahnda = {
name: "Lahnda",
names: [
"Lahnda"
],
"iso639-2": "lah",
"iso639-1": null
};
var Lamba = {
name: "Lamba",
names: [
"Lamba"
],
"iso639-2": "lam",
"iso639-1": null
};
var Lao = {
name: "Lao",
names: [
"Lao"
],
"iso639-2": "lao",
"iso639-1": "lo"
};
var Latin = {
name: "Latin",
names: [
"Latin"
],
"iso639-2": "lat",
"iso639-1": "la"
};
var Latvian = {
name: "Latvian",
names: [
"Latvian"
],
"iso639-2": "lav",
"iso639-1": "lv"
};
var Leonese = {
name: "Leonese",
names: [
"Asturian",
"Bable",
"Leonese",
"Asturleonese"
],
"iso639-2": "ast",
"iso639-1": null
};
var Letzeburgesch = {
name: "Letzeburgesch",
names: [
"Luxembourgish",
"Letzeburgesch"
],
"iso639-2": "ltz",
"iso639-1": "lb"
};
var Lezghian = {
name: "Lezghian",
names: [
"Lezghian"
],
"iso639-2": "lez",
"iso639-1": null
};
var Limburgan = {
name: "Limburgan",
names: [
"Limburgan",
"Limburger",
"Limburgish"
],
"iso639-2": "lim",
"iso639-1": "li"
};
var Limburger = {
name: "Limburger",
names: [
"Limburgan",
"Limburger",
"Limburgish"
],
"iso639-2": "lim",
"iso639-1": "li"
};
var Limburgish = {
name: "Limburgish",
names: [
"Limburgan",
"Limburger",
"Limburgish"
],
"iso639-2": "lim",
"iso639-1": "li"
};
var Lingala = {
name: "Lingala",
names: [
"Lingala"
],
"iso639-2": "lin",
"iso639-1": "ln"
};
var Lithuanian = {
name: "Lithuanian",
names: [
"Lithuanian"
],
"iso639-2": "lit",
"iso639-1": "lt"
};
var Lojban = {
name: "Lojban",
names: [
"Lojban"
],
"iso639-2": "jbo",
"iso639-1": null
};
var Lozi = {
name: "Lozi",
names: [
"Lozi"
],
"iso639-2": "loz",
"iso639-1": null
};
var Luiseno = {
name: "Luiseno",
names: [
"Luiseno"
],
"iso639-2": "lui",
"iso639-1": null
};
var Lunda = {
name: "Lunda",
names: [
"Lunda"
],
"iso639-2": "lun",
"iso639-1": null
};
var Lushai = {
name: "Lushai",
names: [
"Lushai"
],
"iso639-2": "lus",
"iso639-1": null
};
var Luxembourgish = {
name: "Luxembourgish",
names: [
"Luxembourgish",
"Letzeburgesch"
],
"iso639-2": "ltz",
"iso639-1": "lb"
};
var Macedonian = {
name: "Macedonian",
names: [
"Macedonian"
],
"iso639-2": "mac/mkd",
"iso639-1": "mk"
};
var Madurese = {
name: "Madurese",
names: [
"Madurese"
],
"iso639-2": "mad",
"iso639-1": null
};
var Magahi = {
name: "Magahi",
names: [
"Magahi"
],
"iso639-2": "mag",
"iso639-1": null
};
var Maithili = {
name: "Maithili",
names: [
"Maithili"
],
"iso639-2": "mai",
"iso639-1": null
};
var Makasar = {
name: "Makasar",
names: [
"Makasar"
],
"iso639-2": "mak",
"iso639-1": null
};
var Malagasy = {
name: "Malagasy",
names: [
"Malagasy"
],
"iso639-2": "mlg",
"iso639-1": "mg"
};
var Malay = {
name: "Malay",
names: [
"Malay"
],
"iso639-2": "may/msa",
"iso639-1": "ms"
};
var Malayalam = {
name: "Malayalam",
names: [
"Malayalam"
],
"iso639-2": "mal",
"iso639-1": "ml"
};
var Maldivian = {
name: "Maldivian",
names: [
"Divehi",
"Dhivehi",
"Maldivian"
],
"iso639-2": "div",
"iso639-1": "dv"
};
var Maltese = {
name: "Maltese",
names: [
"Maltese"
],
"iso639-2": "mlt",
"iso639-1": "mt"
};
var Manchu = {
name: "Manchu",
names: [
"Manchu"
],
"iso639-2": "mnc",
"iso639-1": null
};
var Mandar = {
name: "Mandar",
names: [
"Mandar"
],
"iso639-2": "mdr",
"iso639-1": null
};
var Mandingo = {
name: "Mandingo",
names: [
"Mandingo"
],
"iso639-2": "man",
"iso639-1": null
};
var Manipuri = {
name: "Manipuri",
names: [
"Manipuri"
],
"iso639-2": "mni",
"iso639-1": null
};
var Manx = {
name: "Manx",
names: [
"Manx"
],
"iso639-2": "glv",
"iso639-1": "gv"
};
var Maori = {
name: "Maori",
names: [
"Maori"
],
"iso639-2": "mao/mri",
"iso639-1": "mi"
};
var Mapuche = {
name: "Mapuche",
names: [
"Mapudungun",
"Mapuche"
],
"iso639-2": "arn",
"iso639-1": null
};
var Mapudungun = {
name: "Mapudungun",
names: [
"Mapudungun",
"Mapuche"
],
"iso639-2": "arn",
"iso639-1": null
};
var Marathi = {
name: "Marathi",
names: [
"Marathi"
],
"iso639-2": "mar",
"iso639-1": "mr"
};
var Mari = {
name: "Mari",
names: [
"Mari"
],
"iso639-2": "chm",
"iso639-1": null
};
var Marshallese = {
name: "Marshallese",
names: [
"Marshallese"
],
"iso639-2": "mah",
"iso639-1": "mh"
};
var Marwari = {
name: "Marwari",
names: [
"Marwari"
],
"iso639-2": "mwr",
"iso639-1": null
};
var Masai = {
name: "Masai",
names: [
"Masai"
],
"iso639-2": "mas",
"iso639-1": null
};
var Mende = {
name: "Mende",
names: [
"Mende"
],
"iso639-2": "men",
"iso639-1": null
};
var Micmac = {
name: "Micmac",
names: [
"Mi'kmaq",
"Micmac"
],
"iso639-2": "mic",
"iso639-1": null
};
var Minangkabau = {
name: "Minangkabau",
names: [
"Minangkabau"
],
"iso639-2": "min",
"iso639-1": null
};
var Mirandese = {
name: "Mirandese",
names: [
"Mirandese"
],
"iso639-2": "mwl",
"iso639-1": null
};
var Mohawk = {
name: "Mohawk",
names: [
"Mohawk"
],
"iso639-2": "moh",
"iso639-1": null
};
var Moksha = {
name: "Moksha",
names: [
"Moksha"
],
"iso639-2": "mdf",
"iso639-1": null
};
var Moldavian = {
name: "Moldavian",
names: [
"Romanian",
"Moldavian",
"Moldovan"
],
"iso639-2": "rum/ron",
"iso639-1": "ro"
};
var Moldovan = {
name: "Moldovan",
names: [
"Romanian",
"Moldavian",
"Moldovan"
],
"iso639-2": "rum/ron",
"iso639-1": "ro"
};
var Mong = {
name: "Mong",
names: [
"Hmong",
"Mong"
],
"iso639-2": "hmn",
"iso639-1": null
};
var Mongo = {
name: "Mongo",
names: [
"Mongo"
],
"iso639-2": "lol",
"iso639-1": null
};
var Mongolian = {
name: "Mongolian",
names: [
"Mongolian"
],
"iso639-2": "mon",
"iso639-1": "mn"
};
var Montenegrin = {
name: "Montenegrin",
names: [
"Montenegrin"
],
"iso639-2": "cnr",
"iso639-1": null
};
var Mossi = {
name: "Mossi",
names: [
"Mossi"
],
"iso639-2": "mos",
"iso639-1": null
};
var Nauru = {
name: "Nauru",
names: [
"Nauru"
],
"iso639-2": "nau",
"iso639-1": "na"
};
var Navaho = {
name: "Navaho",
names: [
"Navajo",
"Navaho"
],
"iso639-2": "nav",
"iso639-1": "nv"
};
var Navajo = {
name: "Navajo",
names: [
"Navajo",
"Navaho"
],
"iso639-2": "nav",
"iso639-1": "nv"
};
var Ndonga = {
name: "Ndonga",
names: [
"Ndonga"
],
"iso639-2": "ndo",
"iso639-1": "ng"
};
var Neapolitan = {
name: "Neapolitan",
names: [
"Neapolitan"
],
"iso639-2": "nap",
"iso639-1": null
};
var Nepali = {
name: "Nepali",
names: [
"Nepali"
],
"iso639-2": "nep",
"iso639-1": "ne"
};
var Newari = {
name: "Newari",
names: [
"Nepal Bhasa",
"Newari"
],
"iso639-2": "new",
"iso639-1": null
};
var Nias = {
name: "Nias",
names: [
"Nias"
],
"iso639-2": "nia",
"iso639-1": null
};
var Niuean = {
name: "Niuean",
names: [
"Niuean"
],
"iso639-2": "niu",
"iso639-1": null
};
var Nogai = {
name: "Nogai",
names: [
"Nogai"
],
"iso639-2": "nog",
"iso639-1": null
};
var Norwegian = {
name: "Norwegian",
names: [
"Norwegian"
],
"iso639-2": "nor",
"iso639-1": "no"
};
var Nuosu = {
name: "Nuosu",
names: [
"Sichuan Yi",
"Nuosu"
],
"iso639-2": "iii",
"iso639-1": "ii"
};
var Nyamwezi = {
name: "Nyamwezi",
names: [
"Nyamwezi"
],
"iso639-2": "nym",
"iso639-1": null
};
var Nyanja = {
name: "Nyanja",
names: [
"Chichewa",
"Chewa",
"Nyanja"
],
"iso639-2": "nya",
"iso639-1": "ny"
};
var Nyankole = {
name: "Nyankole",
names: [
"Nyankole"
],
"iso639-2": "nyn",
"iso639-1": null
};
var Nyoro = {
name: "Nyoro",
names: [
"Nyoro"
],
"iso639-2": "nyo",
"iso639-1": null
};
var Nzima = {
name: "Nzima",
names: [
"Nzima"
],
"iso639-2": "nzi",
"iso639-1": null
};
var Occidental = {
name: "Occidental",
names: [
"Interlingue",
"Occidental"
],
"iso639-2": "ile",
"iso639-1": "ie"
};
var Oirat = {
name: "Oirat",
names: [
"Kalmyk",
"Oirat"
],
"iso639-2": "xal",
"iso639-1": null
};
var Ojibwa = {
name: "Ojibwa",
names: [
"Ojibwa"
],
"iso639-2": "oji",
"iso639-1": "oj"
};
var Oriya = {
name: "Oriya",
names: [
"Oriya"
],
"iso639-2": "ori",
"iso639-1": "or"
};
var Oromo = {
name: "Oromo",
names: [
"Oromo"
],
"iso639-2": "orm",
"iso639-1": "om"
};
var Osage = {
name: "Osage",
names: [
"Osage"
],
"iso639-2": "osa",
"iso639-1": null
};
var Ossetian = {
name: "Ossetian",
names: [
"Ossetian",
"Ossetic"
],
"iso639-2": "oss",
"iso639-1": "os"
};
var Ossetic = {
name: "Ossetic",
names: [
"Ossetian",
"Ossetic"
],
"iso639-2": "oss",
"iso639-1": "os"
};
var Pahlavi = {
name: "Pahlavi",
names: [
"Pahlavi"
],
"iso639-2": "pal",
"iso639-1": null
};
var Palauan = {
name: "Palauan",
names: [
"Palauan"
],
"iso639-2": "pau",
"iso639-1": null
};
var Pali = {
name: "Pali",
names: [
"Pali"
],
"iso639-2": "pli",
"iso639-1": "pi"
};
var Pampanga = {
name: "Pampanga",
names: [
"Pampanga",
"Kapampangan"
],
"iso639-2": "pam",
"iso639-1": null
};
var Pangasinan = {
name: "Pangasinan",
names: [
"Pangasinan"
],
"iso639-2": "pag",
"iso639-1": null
};
var Panjabi = {
name: "Panjabi",
names: [
"Panjabi",
"Punjabi"
],
"iso639-2": "pan",
"iso639-1": "pa"
};
var Papiamento = {
name: "Papiamento",
names: [
"Papiamento"
],
"iso639-2": "pap",
"iso639-1": null
};
var Pashto = {
name: "Pashto",
names: [
"Pushto",
"Pashto"
],
"iso639-2": "pus",
"iso639-1": "ps"
};
var Pedi = {
name: "Pedi",
names: [
"Pedi",
"Sepedi",
"Northern Sotho"
],
"iso639-2": "nso",
"iso639-1": null
};
var Persian = {
name: "Persian",
names: [
"Persian"
],
"iso639-2": "per/fas",
"iso639-1": "fa"
};
var Phoenician = {
name: "Phoenician",
names: [
"Phoenician"
],
"iso639-2": "phn",
"iso639-1": null
};
var Pilipino = {
name: "Pilipino",
names: [
"Filipino",
"Pilipino"
],
"iso639-2": "fil",
"iso639-1": null
};
var Pohnpeian = {
name: "Pohnpeian",
names: [
"Pohnpeian"
],
"iso639-2": "pon",
"iso639-1": null
};
var Polish = {
name: "Polish",
names: [
"Polish"
],
"iso639-2": "pol",
"iso639-1": "pl"
};
var Portuguese = {
name: "Portuguese",
names: [
"Portuguese"
],
"iso639-2": "por",
"iso639-1": "pt"
};
var Punjabi = {
name: "Punjabi",
names: [
"Panjabi",
"Punjabi"
],
"iso639-2": "pan",
"iso639-1": "pa"
};
var Pushto = {
name: "Pushto",
names: [
"Pushto",
"Pashto"
],
"iso639-2": "pus",
"iso639-1": "ps"
};
var Quechua = {
name: "Quechua",
names: [
"Quechua"
],
"iso639-2": "que",
"iso639-1": "qu"
};
var Rajasthani = {
name: "Rajasthani",
names: [
"Rajasthani"
],
"iso639-2": "raj",
"iso639-1": null
};
var Rapanui = {
name: "Rapanui",
names: [
"Rapanui"
],
"iso639-2": "rap",
"iso639-1": null
};
var Rarotongan = {
name: "Rarotongan",
names: [
"Rarotongan",
"Cook Islands Maori"
],
"iso639-2": "rar",
"iso639-1": null
};
var Romanian = {
name: "Romanian",
names: [
"Romanian",
"Moldavian",
"Moldovan"
],
"iso639-2": "rum/ron",
"iso639-1": "ro"
};
var Romansh = {
name: "Romansh",
names: [
"Romansh"
],
"iso639-2": "roh",
"iso639-1": "rm"
};
var Romany = {
name: "Romany",
names: [
"Romany"
],
"iso639-2": "rom",
"iso639-1": null
};
var Rundi = {
name: "Rundi",
names: [
"Rundi"
],
"iso639-2": "run",
"iso639-1": "rn"
};
var Russian = {
name: "Russian",
names: [
"Russian"
],
"iso639-2": "rus",
"iso639-1": "ru"
};
var Sakan = {
name: "Sakan",
names: [
"Khotanese",
"Sakan"
],
"iso639-2": "kho",
"iso639-1": null
};
var Samoan = {
name: "Samoan",
names: [
"Samoan"
],
"iso639-2": "smo",
"iso639-1": "sm"
};
var Sandawe = {
name: "Sandawe",
names: [
"Sandawe"
],
"iso639-2": "sad",
"iso639-1": null
};
var Sango = {
name: "Sango",
names: [
"Sango"
],
"iso639-2": "sag",
"iso639-1": "sg"
};
var Sanskrit = {
name: "Sanskrit",
names: [
"Sanskrit"
],
"iso639-2": "san",
"iso639-1": "sa"
};
var Santali = {
name: "Santali",
names: [
"Santali"
],
"iso639-2": "sat",
"iso639-1": null
};
var Sardinian = {
name: "Sardinian",
names: [
"Sardinian"
],
"iso639-2": "srd",
"iso639-1": "sc"
};
var Sasak = {
name: "Sasak",
names: [
"Sasak"
],
"iso639-2": "sas",
"iso639-1": null
};
var Scots = {
name: "Scots",
names: [
"Scots"
],
"iso639-2": "sco",
"iso639-1": null
};
var Selkup = {
name: "Selkup",
names: [
"Selkup"
],
"iso639-2": "sel",
"iso639-1": null
};
var Sepedi = {
name: "Sepedi",
names: [
"Pedi",
"Sepedi",
"Northern Sotho"
],
"iso639-2": "nso",
"iso639-1": null
};
var Serbian = {
name: "Serbian",
names: [
"Serbian"
],
"iso639-2": "srp",
"iso639-1": "sr"
};
var Serer = {
name: "Serer",
names: [
"Serer"
],
"iso639-2": "srr",
"iso639-1": null
};
var Shan = {
name: "Shan",
names: [
"Shan"
],
"iso639-2": "shn",
"iso639-1": null
};
var Shona = {
name: "Shona",
names: [
"Shona"
],
"iso639-2": "sna",
"iso639-1": "sn"
};
var Sicilian = {
name: "Sicilian",
names: [
"Sicilian"
],
"iso639-2": "scn",
"iso639-1": null
};
var Sidamo = {
name: "Sidamo",
names: [
"Sidamo"
],
"iso639-2": "sid",
"iso639-1": null
};
var Siksika = {
name: "Siksika",
names: [
"Siksika"
],
"iso639-2": "bla",
"iso639-1": null
};
var Sindhi = {
name: "Sindhi",
names: [
"Sindhi"
],
"iso639-2": "snd",
"iso639-1": "sd"
};
var Sinhala = {
name: "Sinhala",
names: [
"Sinhala",
"Sinhalese"
],
"iso639-2": "sin",
"iso639-1": "si"
};
var Sinhalese = {
name: "Sinhalese",
names: [
"Sinhala",
"Sinhalese"
],
"iso639-2": "sin",
"iso639-1": "si"
};
var Slovak = {
name: "Slovak",
names: [
"Slovak"
],
"iso639-2": "slo/slk",
"iso639-1": "sk"
};
var Slovenian = {
name: "Slovenian",
names: [
"Slovenian"
],
"iso639-2": "slv",
"iso639-1": "sl"
};
var Sogdian = {
name: "Sogdian",
names: [
"Sogdian"
],
"iso639-2": "sog",
"iso639-1": null
};
var Somali = {
name: "Somali",
names: [
"Somali"
],
"iso639-2": "som",
"iso639-1": "so"
};
var Soninke = {
name: "Soninke",
names: [
"Soninke"
],
"iso639-2": "snk",
"iso639-1": null
};
var Spanish = {
name: "Spanish",
names: [
"Spanish",
"Castilian"
],
"iso639-2": "spa",
"iso639-1": "es"
};
var Sukuma = {
name: "Sukuma",
names: [
"Sukuma"
],
"iso639-2": "suk",
"iso639-1": null
};
var Sumerian = {
name: "Sumerian",
names: [
"Sumerian"
],
"iso639-2": "sux",
"iso639-1": null
};
var Sundanese = {
name: "Sundanese",
names: [
"Sundanese"
],
"iso639-2": "sun",
"iso639-1": "su"
};
var Susu = {
name: "Susu",
names: [
"Susu"
],
"iso639-2": "sus",
"iso639-1": null
};
var Swahili = {
name: "Swahili",
names: [
"Swahili"
],
"iso639-2": "swa",
"iso639-1": "sw"
};
var Swati = {
name: "Swati",
names: [
"Swati"
],
"iso639-2": "ssw",
"iso639-1": "ss"
};
var Swedish = {
name: "Swedish",
names: [
"Swedish"
],
"iso639-2": "swe",
"iso639-1": "sv"
};
var Syriac = {
name: "Syriac",
names: [
"Syriac"
],
"iso639-2": "syr",
"iso639-1": null
};
var Tagalog = {
name: "Tagalog",
names: [
"Tagalog"
],
"iso639-2": "tgl",
"iso639-1": "tl"
};
var Tahitian = {
name: "Tahitian",
names: [
"Tahitian"
],
"iso639-2": "tah",
"iso639-1": "ty"
};
var Tajik = {
name: "Tajik",
names: [
"Tajik"
],
"iso639-2": "tgk",
"iso639-1": "tg"
};
var Tamashek = {
name: "Tamashek",
names: [
"Tamashek"
],
"iso639-2": "tmh",
"iso639-1": null
};
var Tamil = {
name: "Tamil",
names: [
"Tamil"
],
"iso639-2": "tam",
"iso639-1": "ta"
};
var Tatar = {
name: "Tatar",
names: [
"Tatar"
],
"iso639-2": "tat",
"iso639-1": "tt"
};
var Telugu = {
name: "Telugu",
names: [
"Telugu"
],
"iso639-2": "tel",
"iso639-1": "te"
};
var Tereno = {
name: "Tereno",
names: [
"Tereno"
],
"iso639-2": "ter",
"iso639-1": null
};
var Tetum = {
name: "Tetum",
names: [
"Tetum"
],
"iso639-2": "tet",
"iso639-1": null
};
var Thai = {
name: "Thai",
names: [
"Thai"
],
"iso639-2": "tha",
"iso639-1": "th"
};
var Tibetan = {
name: "Tibetan",
names: [
"Tibetan"
],
"iso639-2": "tib/bod",
"iso639-1": "bo"
};
var Tigre = {
name: "Tigre",
names: [
"Tigre"
],
"iso639-2": "tig",
"iso639-1": null
};
var Tigrinya = {
name: "Tigrinya",
names: [
"Tigrinya"
],
"iso639-2": "tir",
"iso639-1": "ti"
};
var Timne = {
name: "Timne",
names: [
"Timne"
],
"iso639-2": "tem",
"iso639-1": null
};
var Tiv = {
name: "Tiv",
names: [
"Tiv"
],
"iso639-2": "tiv",
"iso639-1": null
};
var Tlingit = {
name: "Tlingit",
names: [
"Tlingit"
],
"iso639-2": "tli",
"iso639-1": null
};
var Tokelau = {
name: "Tokelau",
names: [
"Tokelau"
],
"iso639-2": "tkl",
"iso639-1": null
};
var Tsimshian = {
name: "Tsimshian",
names: [
"Tsimshian"
],
"iso639-2": "tsi",
"iso639-1": null
};
var Tsonga = {
name: "Tsonga",
names: [
"Tsonga"
],
"iso639-2": "tso",
"iso639-1": "ts"
};
var Tswana = {
name: "Tswana",
names: [
"Tswana"
],
"iso639-2": "tsn",
"iso639-1": "tn"
};
var Tumbuka = {
name: "Tumbuka",
names: [
"Tumbuka"
],
"iso639-2": "tum",
"iso639-1": null
};
var Turkish = {
name: "Turkish",
names: [
"Turkish"
],
"iso639-2": "tur",
"iso639-1": "tr"
};
var Turkmen = {
name: "Turkmen",
names: [
"Turkmen"
],
"iso639-2": "tuk",
"iso639-1": "tk"
};
var Tuvalu = {
name: "Tuvalu",
names: [
"Tuvalu"
],
"iso639-2": "tvl",
"iso639-1": null
};
var Tuvinian = {
name: "Tuvinian",
names: [
"Tuvinian"
],
"iso639-2": "tyv",
"iso639-1": null
};
var Twi = {
name: "Twi",
names: [
"Twi"
],
"iso639-2": "twi",
"iso639-1": "tw"
};
var Udmurt = {
name: "Udmurt",
names: [
"Udmurt"
],
"iso639-2": "udm",
"iso639-1": null
};
var Ugaritic = {
name: "Ugaritic",
names: [
"Ugaritic"
],
"iso639-2": "uga",
"iso639-1": null
};
var Uighur = {
name: "Uighur",
names: [
"Uighur",
"Uyghur"
],
"iso639-2": "uig",
"iso639-1": "ug"
};
var Ukrainian = {
name: "Ukrainian",
names: [
"Ukrainian"
],
"iso639-2": "ukr",
"iso639-1": "uk"
};
var Umbundu = {
name: "Umbundu",
names: [
"Umbundu"
],
"iso639-2": "umb",
"iso639-1": null
};
var Undetermined = {
name: "Undetermined",
names: [
"Undetermined"
],
"iso639-2": "und",
"iso639-1": null
};
var Urdu = {
name: "Urdu",
names: [
"Urdu"
],
"iso639-2": "urd",
"iso639-1": "ur"
};
var Uyghur = {
name: "Uyghur",
names: [
"Uighur",
"Uyghur"
],
"iso639-2": "uig",
"iso639-1": "ug"
};
var Uzbek = {
name: "Uzbek",
names: [
"Uzbek"
],
"iso639-2": "uzb",
"iso639-1": "uz"
};
var Vai = {
name: "Vai",
names: [
"Vai"
],
"iso639-2": "vai",
"iso639-1": null
};
var Valencian = {
name: "Valencian",
names: [
"Catalan",
"Valencian"
],
"iso639-2": "cat",
"iso639-1": "ca"
};
var Venda = {
name: "Venda",
names: [
"Venda"
],
"iso639-2": "ven",
"iso639-1": "ve"
};
var Vietnamese = {
name: "Vietnamese",
names: [
"Vietnamese"
],
"iso639-2": "vie",
"iso639-1": "vi"
};
var Votic = {
name: "Votic",
names: [
"Votic"
],
"iso639-2": "vot",
"iso639-1": null
};
var Walloon = {
name: "Walloon",
names: [
"Walloon"
],
"iso639-2": "wln",
"iso639-1": "wa"
};
var Waray = {
name: "Waray",
names: [
"Waray"
],
"iso639-2": "war",
"iso639-1": null
};
var Washo = {
name: "Washo",
names: [
"Washo"
],
"iso639-2": "was",
"iso639-1": null
};
var Welsh = {
name: "Welsh",
names: [
"Welsh"
],
"iso639-2": "wel/cym",
"iso639-1": "cy"
};
var Wolaitta = {
name: "Wolaitta",
names: [
"Wolaitta",
"Wolaytta"
],
"iso639-2": "wal",
"iso639-1": null
};
var Wolaytta = {
name: "Wolaytta",
names: [
"Wolaitta",
"Wolaytta"
],
"iso639-2": "wal",
"iso639-1": null
};
var Wolof = {
name: "Wolof",
names: [
"Wolof"
],
"iso639-2": "wol",
"iso639-1": "wo"
};
var Xhosa = {
name: "Xhosa",
names: [
"Xhosa"
],
"iso639-2": "xho",
"iso639-1": "xh"
};
var Yakut = {
name: "Yakut",
names: [
"Yakut"
],
"iso639-2": "sah",
"iso639-1": null
};
var Yao = {
name: "Yao",
names: [
"Yao"
],
"iso639-2": "yao",
"iso639-1": null
};
var Yapese = {
name: "Yapese",
names: [
"Yapese"
],
"iso639-2": "yap",
"iso639-1": null
};
var Yiddish = {
name: "Yiddish",
names: [
"Yiddish"
],
"iso639-2": "yid",
"iso639-1": "yi"
};
var Yoruba = {
name: "Yoruba",
names: [
"Yoruba"
],
"iso639-2": "yor",
"iso639-1": "yo"
};
var Zapotec = {
name: "Zapotec",
names: [
"Zapotec"
],
"iso639-2": "zap",
"iso639-1": null
};
var Zaza = {
name: "Zaza",
names: [
"Zaza",
"Dimili",
"Dimli",
"Kirdki",
"Kirmanjki",
"Zazaki"
],
"iso639-2": "zza",
"iso639-1": null
};
var Zazaki = {
name: "Zazaki",
names: [
"Zaza",
"Dimili",
"Dimli",
"Kirdki",
"Kirmanjki",
"Zazaki"
],
"iso639-2": "zza",
"iso639-1": null
};
var Zenaga = {
name: "Zenaga",
names: [
"Zenaga"
],
"iso639-2": "zen",
"iso639-1": null
};
var Zhuang = {
name: "Zhuang",
names: [
"Zhuang",
"Chuang"
],
"iso639-2": "zha",
"iso639-1": "za"
};
var Zulu = {
name: "Zulu",
names: [
"Zulu"
],
"iso639-2": "zul",
"iso639-1": "zu"
};
var Zuni = {
name: "Zuni",
names: [
"Zuni"
],
"iso639-2": "zun",
"iso639-1": null
};
var iso = {
Abkhazian: Abkhazian,
Achinese: Achinese,
Acoli: Acoli,
Adangme: Adangme,
Adygei: Adygei,
Adyghe: Adyghe,
Afar: Afar,
Afrihili: Afrihili,
Afrikaans: Afrikaans,
"Afro-Asiatic languages": {
name: "Afro-Asiatic languages",
names: [
"Afro-Asiatic languages"
],
"iso639-2": "afa",
"iso639-1": null
},
Ainu: Ainu,
Akan: Akan,
Akkadian: Akkadian,
Albanian: Albanian,
Alemannic: Alemannic,
Aleut: Aleut,
"Algonquian languages": {
name: "Algonquian languages",
names: [
"Algonquian languages"
],
"iso639-2": "alg",
"iso639-1": null
},
Alsatian: Alsatian,
"Altaic languages": {
name: "Altaic languages",
names: [
"Altaic languages"
],
"iso639-2": "tut",
"iso639-1": null
},
Amharic: Amharic,
Angika: Angika,
"Apache languages": {
name: "Apache languages",
names: [
"Apache languages"
],
"iso639-2": "apa",
"iso639-1": null
},
Arabic: Arabic,
Aragonese: Aragonese,
Arapaho: Arapaho,
Arawak: Arawak,
Armenian: Armenian,
Aromanian: Aromanian,
"Artificial languages": {
name: "Artificial languages",
names: [
"Artificial languages"
],
"iso639-2": "art",
"iso639-1": null
},
Arumanian: Arumanian,
Assamese: Assamese,
Asturian: Asturian,
Asturleonese: Asturleonese,
"Athapascan languages": {
name: "Athapascan languages",
names: [
"Athapascan languages"
],
"iso639-2": "ath",
"iso639-1": null
},
"Australian languages": {
name: "Australian languages",
names: [
"Australian languages"
],
"iso639-2": "aus",
"iso639-1": null
},
"Austronesian languages": {
name: "Austronesian languages",
names: [
"Austronesian languages"
],
"iso639-2": "map",
"iso639-1": null
},
Avaric: Avaric,
Avestan: Avestan,
Awadhi: Awadhi,
Aymara: Aymara,
Azerbaijani: Azerbaijani,
Bable: Bable,
Balinese: Balinese,
"Baltic languages": {
name: "Baltic languages",
names: [
"Baltic languages"
],
"iso639-2": "bat",
"iso639-1": null
},
Baluchi: Baluchi,
Bambara: Bambara,
"Bamileke languages": {
name: "Bamileke languages",
names: [
"Bamileke languages"
],
"iso639-2": "bai",
"iso639-1": null
},
"Banda languages": {
name: "Banda languages",
names: [
"Banda languages"
],
"iso639-2": "bad",
"iso639-1": null
},
"Bantu languages": {
name: "Bantu languages",
names: [
"Bantu languages"
],
"iso639-2": "bnt",
"iso639-1": null
},
Basa: Basa,
Bashkir: Bashkir,
Basque: Basque,
"Batak languages": {
name: "Batak languages",
names: [
"Batak languages"
],
"iso639-2": "btk",
"iso639-1": null
},
Bedawiyet: Bedawiyet,
Beja: Beja,
Belarusian: Belarusian,
Bemba: Bemba,
Bengali: Bengali,
"Berber languages": {
name: "Berber languages",
names: [
"Berber languages"
],
"iso639-2": "ber",
"iso639-1": null
},
Bhojpuri: Bhojpuri,
"Bihari languages": {
name: "Bihari languages",
names: [
"Bihari languages"
],
"iso639-2": "bih",
"iso639-1": "bh"
},
Bikol: Bikol,
Bilin: Bilin,
Bini: Bini,
Bislama: Bislama,
Blin: Blin,
Bliss: Bliss,
Blissymbolics: Blissymbolics,
Blissymbols: Blissymbols,
"Bokmål, Norwegian": {
name: "Bokmål, Norwegian",
names: [
"Bokmål, Norwegian",
"Norwegian Bokmål"
],
"iso639-2": "nob",
"iso639-1": "nb"
},
Bosnian: Bosnian,
Braj: Braj,
Breton: Breton,
Buginese: Buginese,
Bulgarian: Bulgarian,
Buriat: Buriat,
Burmese: Burmese,
Caddo: Caddo,
Castilian: Castilian,
Catalan: Catalan,
"Caucasian languages": {
name: "Caucasian languages",
names: [
"Caucasian languages"
],
"iso639-2": "cau",
"iso639-1": null
},
Cebuano: Cebuano,
"Celtic languages": {
name: "Celtic languages",
names: [
"Celtic languages"
],
"iso639-2": "cel",
"iso639-1": null
},
"Central American Indian languages": {
name: "Central American Indian languages",
names: [
"Central American Indian languages"
],
"iso639-2": "cai",
"iso639-1": null
},
"Central Khmer": {
name: "Central Khmer",
names: [
"Central Khmer"
],
"iso639-2": "khm",
"iso639-1": "km"
},
Chagatai: Chagatai,
"Chamic languages": {
name: "Chamic languages",
names: [
"Chamic languages"
],
"iso639-2": "cmc",
"iso639-1": null
},
Chamorro: Chamorro,
Chechen: Chechen,
Cherokee: Cherokee,
Chewa: Chewa,
Cheyenne: Cheyenne,
Chibcha: Chibcha,
Chichewa: Chichewa,
Chinese: Chinese,
"Chinook jargon": {
name: "Chinook jargon",
names: [
"Chinook jargon"
],
"iso639-2": "chn",
"iso639-1": null
},
Chipewyan: Chipewyan,
Choctaw: Choctaw,
Chuang: Chuang,
"Church Slavic": {
name: "Church Slavic",
names: [
"Church Slavic",
"Old Slavonic",
"Church Slavonic",
"Old Bulgarian",
"Old Church Slavonic"
],
"iso639-2": "chu",
"iso639-1": "cu"
},
"Church Slavonic": {
name: "Church Slavonic",
names: [
"Church Slavic",
"Old Slavonic",
"Church Slavonic",
"Old Bulgarian",
"Old Church Slavonic"
],
"iso639-2": "chu",
"iso639-1": "cu"
},
Chuukese: Chuukese,
Chuvash: Chuvash,
"Classical Nepal Bhasa": {
name: "Classical Nepal Bhasa",
names: [
"Classical Newari",
"Old Newari",
"Classical Nepal Bhasa"
],
"iso639-2": "nwc",
"iso639-1": null
},
"Classical Newari": {
name: "Classical Newari",
names: [
"Classical Newari",
"Old Newari",
"Classical Nepal Bhasa"
],
"iso639-2": "nwc",
"iso639-1": null
},
"Classical Syriac": {
name: "Classical Syriac",
names: [
"Classical Syriac"
],
"iso639-2": "syc",
"iso639-1": null
},
"Cook Islands Maori": {
name: "Cook Islands Maori",
names: [
"Rarotongan",
"Cook Islands Maori"
],
"iso639-2": "rar",
"iso639-1": null
},
Coptic: Coptic,
Cornish: Cornish,
Corsican: Corsican,
Cree: Cree,
Creek: Creek,
"Creoles and pidgins": {
name: "Creoles and pidgins",
names: [
"Creoles and pidgins"
],
"iso639-2": "crp",
"iso639-1": null
},
"Creoles and pidgins, English based": {
name: "Creoles and pidgins, English based",
names: [
"Creoles and pidgins, English based"
],
"iso639-2": "cpe",
"iso639-1": null
},
"Creoles and pidgins, French-based": {
name: "Creoles and pidgins, French-based",
names: [
"Creoles and pidgins, French-based"
],
"iso639-2": "cpf",
"iso639-1": null
},
"Creoles and pidgins, Portuguese-based": {
name: "Creoles and pidgins, Portuguese-based",
names: [
"Creoles and pidgins, Portuguese-based"
],
"iso639-2": "cpp",
"iso639-1": null
},
"Crimean Tatar": {
name: "Crimean Tatar",
names: [
"Crimean Tatar",
"Crimean Turkish"
],
"iso639-2": "crh",
"iso639-1": null
},
"Crimean Turkish": {
name: "Crimean Turkish",
names: [
"Crimean Tatar",
"Crimean Turkish"
],
"iso639-2": "crh",
"iso639-1": null
},
Croatian: Croatian,
"Cushitic languages": {
name: "Cushitic languages",
names: [
"Cushitic languages"
],
"iso639-2": "cus",
"iso639-1": null
},
Czech: Czech,
Dakota: Dakota,
Danish: Danish,
Dargwa: Dargwa,
Delaware: Delaware,
"Dene Suline": {
name: "Dene Suline",
names: [
"Chipewyan",
"Dene Suline"
],
"iso639-2": "chp",
"iso639-1": null
},
Dhivehi: Dhivehi,
Dimili: Dimili,
Dimli: Dimli,
Dinka: Dinka,
Divehi: Divehi,
Dogri: Dogri,
Dogrib: Dogrib,
"Dravidian languages": {
name: "Dravidian languages",
names: [
"Dravidian languages"
],
"iso639-2": "dra",
"iso639-1": null
},
Duala: Duala,
Dutch: Dutch,
"Dutch, Middle (ca.1050-1350)": {
name: "Dutch, Middle (ca.1050-1350)",
names: [
"Dutch, Middle (ca.1050-1350)"
],
"iso639-2": "dum",
"iso639-1": null
},
Dyula: Dyula,
Dzongkha: Dzongkha,
"Eastern Frisian": {
name: "Eastern Frisian",
names: [
"Eastern Frisian"
],
"iso639-2": "frs",
"iso639-1": null
},
Edo: Edo,
Efik: Efik,
"Egyptian (Ancient)": {
name: "Egyptian (Ancient)",
names: [
"Egyptian (Ancient)"
],
"iso639-2": "egy",
"iso639-1": null
},
Ekajuk: Ekajuk,
Elamite: Elamite,
English: English,
"English, Middle (1100-1500)": {
name: "English, Middle (1100-1500)",
names: [
"English, Middle (1100-1500)"
],
"iso639-2": "enm",
"iso639-1": null
},
"English, Old (ca.450-1100)": {
name: "English, Old (ca.450-1100)",
names: [
"English, Old (ca.450-1100)"
],
"iso639-2": "ang",
"iso639-1": null
},
Erzya: Erzya,
Esperanto: Esperanto,
Estonian: Estonian,
Ewe: Ewe,
Ewondo: Ewondo,
Fang: Fang,
Fanti: Fanti,
Faroese: Faroese,
Fijian: Fijian,
Filipino: Filipino,
Finnish: Finnish,
"Finno-Ugrian languages": {
name: "Finno-Ugrian languages",
names: [
"Finno-Ugrian languages"
],
"iso639-2": "fiu",
"iso639-1": null
},
Flemish: Flemish,
Fon: Fon,
French: French,
"French, Middle (ca.1400-1600)": {
name: "French, Middle (ca.1400-1600)",
names: [
"French, Middle (ca.1400-1600)"
],
"iso639-2": "frm",
"iso639-1": null
},
"French, Old (842-ca.1400)": {
name: "French, Old (842-ca.1400)",
names: [
"French, Old (842-ca.1400)"
],
"iso639-2": "fro",
"iso639-1": null
},
Friulian: Friulian,
Fulah: Fulah,
Ga: Ga,
Gaelic: Gaelic,
"Galibi Carib": {
name: "Galibi Carib",
names: [
"Galibi Carib"
],
"iso639-2": "car",
"iso639-1": null
},
Galician: Galician,
Ganda: Ganda,
Gayo: Gayo,
Gbaya: Gbaya,
Geez: Geez,
Georgian: Georgian,
German: German,
"German, Low": {
name: "German, Low",
names: [
"Low German",
"Low Saxon",
"German, Low",
"Saxon, Low"
],
"iso639-2": "nds",
"iso639-1": null
},
"German, Middle High (ca.1050-1500)": {
name: "German, Middle High (ca.1050-1500)",
names: [
"German, Middle High (ca.1050-1500)"
],
"iso639-2": "gmh",
"iso639-1": null
},
"German, Old High (ca.750-1050)": {
name: "German, Old High (ca.750-1050)",
names: [
"German, Old High (ca.750-1050)"
],
"iso639-2": "goh",
"iso639-1": null
},
"Germanic languages": {
name: "Germanic languages",
names: [
"Germanic languages"
],
"iso639-2": "gem",
"iso639-1": null
},
Gikuyu: Gikuyu,
Gilbertese: Gilbertese,
Gondi: Gondi,
Gorontalo: Gorontalo,
Gothic: Gothic,
Grebo: Grebo,
"Greek, Ancient (to 1453)": {
name: "Greek, Ancient (to 1453)",
names: [
"Greek, Ancient (to 1453)"
],
"iso639-2": "grc",
"iso639-1": null
},
"Greek, Modern (1453-)": {
name: "Greek, Modern (1453-)",
names: [
"Greek, Modern (1453-)"
],
"iso639-2": "gre/ell",
"iso639-1": "el"
},
Greenlandic: Greenlandic,
Guarani: Guarani,
Gujarati: Gujarati,
"Gwich'in": {
name: "Gwich'in",
names: [
"Gwich'in"
],
"iso639-2": "gwi",
"iso639-1": null
},
Haida: Haida,
Haitian: Haitian,
"Haitian Creole": {
name: "Haitian Creole",
names: [
"Haitian",
"Haitian Creole"
],
"iso639-2": "hat",
"iso639-1": "ht"
},
Hausa: Hausa,
Hawaiian: Hawaiian,
Hebrew: Hebrew,
Herero: Herero,
Hiligaynon: Hiligaynon,
"Himachali languages": {
name: "Himachali languages",
names: [
"Himachali languages",
"Western Pahari languages"
],
"iso639-2": "him",
"iso639-1": null
},
Hindi: Hindi,
"Hiri Motu": {
name: "Hiri Motu",
names: [
"Hiri Motu"
],
"iso639-2": "hmo",
"iso639-1": "ho"
},
Hittite: Hittite,
Hmong: Hmong,
Hungarian: Hungarian,
Hupa: Hupa,
Iban: Iban,
Icelandic: Icelandic,
Ido: Ido,
Igbo: Igbo,
"Ijo languages": {
name: "Ijo languages",
names: [
"Ijo languages"
],
"iso639-2": "ijo",
"iso639-1": null
},
Iloko: Iloko,
"Imperial Aramaic (700-300 BCE)": {
name: "Imperial Aramaic (700-300 BCE)",
names: [
"Official Aramaic (700-300 BCE)",
"Imperial Aramaic (700-300 BCE)"
],
"iso639-2": "arc",
"iso639-1": null
},
"Inari Sami": {
name: "Inari Sami",
names: [
"Inari Sami"
],
"iso639-2": "smn",
"iso639-1": null
},
"Indic languages": {
name: "Indic languages",
names: [
"Indic languages"
],
"iso639-2": "inc",
"iso639-1": null
},
"Indo-European languages": {
name: "Indo-European languages",
names: [
"Indo-European languages"
],
"iso639-2": "ine",
"iso639-1": null
},
Indonesian: Indonesian,
Ingush: Ingush,
"Interlingua (International Auxiliary Language Association)": {
name: "Interlingua (International Auxiliary Language Association)",
names: [
"Interlingua (International Auxiliary Language Association)"
],
"iso639-2": "ina",
"iso639-1": "ia"
},
Interlingue: Interlingue,
Inuktitut: Inuktitut,
Inupiaq: Inupiaq,
"Iranian languages": {
name: "Iranian languages",
names: [
"Iranian languages"
],
"iso639-2": "ira",
"iso639-1": null
},
Irish: Irish,
"Irish, Middle (900-1200)": {
name: "Irish, Middle (900-1200)",
names: [
"Irish, Middle (900-1200)"
],
"iso639-2": "mga",
"iso639-1": null
},
"Irish, Old (to 900)": {
name: "Irish, Old (to 900)",
names: [
"Irish, Old (to 900)"
],
"iso639-2": "sga",
"iso639-1": null
},
"Iroquoian languages": {
name: "Iroquoian languages",
names: [
"Iroquoian languages"
],
"iso639-2": "iro",
"iso639-1": null
},
Italian: Italian,
Japanese: Japanese,
Javanese: Javanese,
Jingpho: Jingpho,
"Judeo-Arabic": {
name: "Judeo-Arabic",
names: [
"Judeo-Arabic"
],
"iso639-2": "jrb",
"iso639-1": null
},
"Judeo-Persian": {
name: "Judeo-Persian",
names: [
"Judeo-Persian"
],
"iso639-2": "jpr",
"iso639-1": null
},
Kabardian: Kabardian,
Kabyle: Kabyle,
Kachin: Kachin,
Kalaallisut: Kalaallisut,
Kalmyk: Kalmyk,
Kamba: Kamba,
Kannada: Kannada,
Kanuri: Kanuri,
Kapampangan: Kapampangan,
"Kara-Kalpak": {
name: "Kara-Kalpak",
names: [
"Kara-Kalpak"
],
"iso639-2": "kaa",
"iso639-1": null
},
"Karachay-Balkar": {
name: "Karachay-Balkar",
names: [
"Karachay-Balkar"
],
"iso639-2": "krc",
"iso639-1": null
},
Karelian: Karelian,
"Karen languages": {
name: "Karen languages",
names: [
"Karen languages"
],
"iso639-2": "kar",
"iso639-1": null
},
Kashmiri: Kashmiri,
Kashubian: Kashubian,
Kawi: Kawi,
Kazakh: Kazakh,
Khasi: Khasi,
"Khoisan languages": {
name: "Khoisan languages",
names: [
"Khoisan languages"
],
"iso639-2": "khi",
"iso639-1": null
},
Khotanese: Khotanese,
Kikuyu: Kikuyu,
Kimbundu: Kimbundu,
Kinyarwanda: Kinyarwanda,
Kirdki: Kirdki,
Kirghiz: Kirghiz,
Kirmanjki: Kirmanjki,
Klingon: Klingon,
Komi: Komi,
Kongo: Kongo,
Konkani: Konkani,
Korean: Korean,
Kosraean: Kosraean,
Kpelle: Kpelle,
"Kru languages": {
name: "Kru languages",
names: [
"Kru languages"
],
"iso639-2": "kro",
"iso639-1": null
},
Kuanyama: Kuanyama,
Kumyk: Kumyk,
Kurdish: Kurdish,
Kurukh: Kurukh,
Kutenai: Kutenai,
Kwanyama: Kwanyama,
Kyrgyz: Kyrgyz,
Ladino: Ladino,
Lahnda: Lahnda,
Lamba: Lamba,
"Land Dayak languages": {
name: "Land Dayak languages",
names: [
"Land Dayak languages"
],
"iso639-2": "day",
"iso639-1": null
},
Lao: Lao,
Latin: Latin,
Latvian: Latvian,
Leonese: Leonese,
Letzeburgesch: Letzeburgesch,
Lezghian: Lezghian,
Limburgan: Limburgan,
Limburger: Limburger,
Limburgish: Limburgish,
Lingala: Lingala,
Lithuanian: Lithuanian,
Lojban: Lojban,
"Low German": {
name: "Low German",
names: [
"Low German",
"Low Saxon",
"German, Low",
"Saxon, Low"
],
"iso639-2": "nds",
"iso639-1": null
},
"Low Saxon": {
name: "Low Saxon",
names: [
"Low German",
"Low Saxon",
"German, Low",
"Saxon, Low"
],
"iso639-2": "nds",
"iso639-1": null
},
"Lower Sorbian": {
name: "Lower Sorbian",
names: [
"Lower Sorbian"
],
"iso639-2": "dsb",
"iso639-1": null
},
Lozi: Lozi,
"Luba-Katanga": {
name: "Luba-Katanga",
names: [
"Luba-Katanga"
],
"iso639-2": "lub",
"iso639-1": "lu"
},
"Luba-Lulua": {
name: "Luba-Lulua",
names: [
"Luba-Lulua"
],
"iso639-2": "lua",
"iso639-1": null
},
Luiseno: Luiseno,
"Lule Sami": {
name: "Lule Sami",
names: [
"Lule Sami"
],
"iso639-2": "smj",
"iso639-1": null
},
Lunda: Lunda,
"Luo (Kenya and Tanzania)": {
name: "Luo (Kenya and Tanzania)",
names: [
"Luo (Kenya and Tanzania)"
],
"iso639-2": "luo",
"iso639-1": null
},
Lushai: Lushai,
Luxembourgish: Luxembourgish,
"Macedo-Romanian": {
name: "Macedo-Romanian",
names: [
"Aromanian",
"Arumanian",
"Macedo-Romanian"
],
"iso639-2": "rup",
"iso639-1": null
},
Macedonian: Macedonian,
Madurese: Madurese,
Magahi: Magahi,
Maithili: Maithili,
Makasar: Makasar,
Malagasy: Malagasy,
Malay: Malay,
Malayalam: Malayalam,
Maldivian: Maldivian,
Maltese: Maltese,
Manchu: Manchu,
Mandar: Mandar,
Mandingo: Mandingo,
Manipuri: Manipuri,
"Manobo languages": {
name: "Manobo languages",
names: [
"Manobo languages"
],
"iso639-2": "mno",
"iso639-1": null
},
Manx: Manx,
Maori: Maori,
Mapuche: Mapuche,
Mapudungun: Mapudungun,
Marathi: Marathi,
Mari: Mari,
Marshallese: Marshallese,
Marwari: Marwari,
Masai: Masai,
"Mayan languages": {
name: "Mayan languages",
names: [
"Mayan languages"
],
"iso639-2": "myn",
"iso639-1": null
},
Mende: Mende,
"Mi'kmaq": {
name: "Mi'kmaq",
names: [
"Mi'kmaq",
"Micmac"
],
"iso639-2": "mic",
"iso639-1": null
},
Micmac: Micmac,
Minangkabau: Minangkabau,
Mirandese: Mirandese,
Mohawk: Mohawk,
Moksha: Moksha,
Moldavian: Moldavian,
Moldovan: Moldovan,
"Mon-Khmer languages": {
name: "Mon-Khmer languages",
names: [
"Mon-Khmer languages"
],
"iso639-2": "mkh",
"iso639-1": null
},
Mong: Mong,
Mongo: Mongo,
Mongolian: Mongolian,
Montenegrin: Montenegrin,
Mossi: Mossi,
"Multiple languages": {
name: "Multiple languages",
names: [
"Multiple languages"
],
"iso639-2": "mul",
"iso639-1": null
},
"Munda languages": {
name: "Munda languages",
names: [
"Munda languages"
],
"iso639-2": "mun",
"iso639-1": null
},
"N'Ko": {
name: "N'Ko",
names: [
"N'Ko"
],
"iso639-2": "nqo",
"iso639-1": null
},
"Nahuatl languages": {
name: "Nahuatl languages",
names: [
"Nahuatl languages"
],
"iso639-2": "nah",
"iso639-1": null
},
Nauru: Nauru,
Navaho: Navaho,
Navajo: Navajo,
"Ndebele, North": {
name: "Ndebele, North",
names: [
"Ndebele, North",
"North Ndebele"
],
"iso639-2": "nde",
"iso639-1": "nd"
},
"Ndebele, South": {
name: "Ndebele, South",
names: [
"Ndebele, South",
"South Ndebele"
],
"iso639-2": "nbl",
"iso639-1": "nr"
},
Ndonga: Ndonga,
Neapolitan: Neapolitan,
"Nepal Bhasa": {
name: "Nepal Bhasa",
names: [
"Nepal Bhasa",
"Newari"
],
"iso639-2": "new",
"iso639-1": null
},
Nepali: Nepali,
Newari: Newari,
Nias: Nias,
"Niger-Kordofanian languages": {
name: "Niger-Kordofanian languages",
names: [
"Niger-Kordofanian languages"
],
"iso639-2": "nic",
"iso639-1": null
},
"Nilo-Saharan languages": {
name: "Nilo-Saharan languages",
names: [
"Nilo-Saharan languages"
],
"iso639-2": "ssa",
"iso639-1": null
},
Niuean: Niuean,
"No linguistic content": {
name: "No linguistic content",
names: [
"No linguistic content",
"Not applicable"
],
"iso639-2": "zxx",
"iso639-1": null
},
Nogai: Nogai,
"Norse, Old": {
name: "Norse, Old",
names: [
"Norse, Old"
],
"iso639-2": "non",
"iso639-1": null
},
"North American Indian languages": {
name: "North American Indian languages",
names: [
"North American Indian languages"
],
"iso639-2": "nai",
"iso639-1": null
},
"North Ndebele": {
name: "North Ndebele",
names: [
"Ndebele, North",
"North Ndebele"
],
"iso639-2": "nde",
"iso639-1": "nd"
},
"Northern Frisian": {
name: "Northern Frisian",
names: [
"Northern Frisian"
],
"iso639-2": "frr",
"iso639-1": null
},
"Northern Sami": {
name: "Northern Sami",
names: [
"Northern Sami"
],
"iso639-2": "sme",
"iso639-1": "se"
},
"Northern Sotho": {
name: "Northern Sotho",
names: [
"Pedi",
"Sepedi",
"Northern Sotho"
],
"iso639-2": "nso",
"iso639-1": null
},
Norwegian: Norwegian,
"Norwegian Bokmål": {
name: "Norwegian Bokmål",
names: [
"Bokmål, Norwegian",
"Norwegian Bokmål"
],
"iso639-2": "nob",
"iso639-1": "nb"
},
"Norwegian Nynorsk": {
name: "Norwegian Nynorsk",
names: [
"Norwegian Nynorsk",
"Nynorsk, Norwegian"
],
"iso639-2": "nno",
"iso639-1": "nn"
},
"Not applicable": {
name: "Not applicable",
names: [
"No linguistic content",
"Not applicable"
],
"iso639-2": "zxx",
"iso639-1": null
},
"Nubian languages": {
name: "Nubian languages",
names: [
"Nubian languages"
],
"iso639-2": "nub",
"iso639-1": null
},
Nuosu: Nuosu,
Nyamwezi: Nyamwezi,
Nyanja: Nyanja,
Nyankole: Nyankole,
"Nynorsk, Norwegian": {
name: "Nynorsk, Norwegian",
names: [
"Norwegian Nynorsk",
"Nynorsk, Norwegian"
],
"iso639-2": "nno",
"iso639-1": "nn"
},
Nyoro: Nyoro,
Nzima: Nzima,
Occidental: Occidental,
"Occitan (post 1500)": {
name: "Occitan (post 1500)",
names: [
"Occitan (post 1500)"
],
"iso639-2": "oci",
"iso639-1": "oc"
},
"Occitan, Old (to 1500)": {
name: "Occitan, Old (to 1500)",
names: [
"Provençal, Old (to 1500)",
"Occitan, Old (to 1500)"
],
"iso639-2": "pro",
"iso639-1": null
},
"Official Aramaic (700-300 BCE)": {
name: "Official Aramaic (700-300 BCE)",
names: [
"Official Aramaic (700-300 BCE)",
"Imperial Aramaic (700-300 BCE)"
],
"iso639-2": "arc",
"iso639-1": null
},
Oirat: Oirat,
Ojibwa: Ojibwa,
"Old Bulgarian": {
name: "Old Bulgarian",
names: [
"Church Slavic",
"Old Slavonic",
"Church Slavonic",
"Old Bulgarian",
"Old Church Slavonic"
],
"iso639-2": "chu",
"iso639-1": "cu"
},
"Old Church Slavonic": {
name: "Old Church Slavonic",
names: [
"Church Slavic",
"Old Slavonic",
"Church Slavonic",
"Old Bulgarian",
"Old Church Slavonic"
],
"iso639-2": "chu",
"iso639-1": "cu"
},
"Old Newari": {
name: "Old Newari",
names: [
"Classical Newari",
"Old Newari",
"Classical Nepal Bhasa"
],
"iso639-2": "nwc",
"iso639-1": null
},
"Old Slavonic": {
name: "Old Slavonic",
names: [
"Church Slavic",
"Old Slavonic",
"Church Slavonic",
"Old Bulgarian",
"Old Church Slavonic"
],
"iso639-2": "chu",
"iso639-1": "cu"
},
Oriya: Oriya,
Oromo: Oromo,
Osage: Osage,
Ossetian: Ossetian,
Ossetic: Ossetic,
"Otomian languages": {
name: "Otomian languages",
names: [
"Otomian languages"
],
"iso639-2": "oto",
"iso639-1": null
},
Pahlavi: Pahlavi,
Palauan: Palauan,
Pali: Pali,
Pampanga: Pampanga,
Pangasinan: Pangasinan,
Panjabi: Panjabi,
Papiamento: Papiamento,
"Papuan languages": {
name: "Papuan languages",
names: [
"Papuan languages"
],
"iso639-2": "paa",
"iso639-1": null
},
Pashto: Pashto,
Pedi: Pedi,
Persian: Persian,
"Persian, Old (ca.600-400 B.C.)": {
name: "Persian, Old (ca.600-400 B.C.)",
names: [
"Persian, Old (ca.600-400 B.C.)"
],
"iso639-2": "peo",
"iso639-1": null
},
"Philippine languages": {
name: "Philippine languages",
names: [
"Philippine languages"
],
"iso639-2": "phi",
"iso639-1": null
},
Phoenician: Phoenician,
Pilipino: Pilipino,
Pohnpeian: Pohnpeian,
Polish: Polish,
Portuguese: Portuguese,
"Prakrit languages": {
name: "Prakrit languages",
names: [
"Prakrit languages"
],
"iso639-2": "pra",
"iso639-1": null
},
"Provençal, Old (to 1500)": {
name: "Provençal, Old (to 1500)",
names: [
"Provençal, Old (to 1500)",
"Occitan, Old (to 1500)"
],
"iso639-2": "pro",
"iso639-1": null
},
Punjabi: Punjabi,
Pushto: Pushto,
Quechua: Quechua,
Rajasthani: Rajasthani,
Rapanui: Rapanui,
Rarotongan: Rarotongan,
"Reserved for local use": {
name: "Reserved for local use",
names: [
"Reserved for local use"
],
"iso639-2": "qaa-qtz",
"iso639-1": null
},
"Romance languages": {
name: "Romance languages",
names: [
"Romance languages"
],
"iso639-2": "roa",
"iso639-1": null
},
Romanian: Romanian,
Romansh: Romansh,
Romany: Romany,
Rundi: Rundi,
Russian: Russian,
Sakan: Sakan,
"Salishan languages": {
name: "Salishan languages",
names: [
"Salishan languages"
],
"iso639-2": "sal",
"iso639-1": null
},
"Samaritan Aramaic": {
name: "Samaritan Aramaic",
names: [
"Samaritan Aramaic"
],
"iso639-2": "sam",
"iso639-1": null
},
"Sami languages": {
name: "Sami languages",
names: [
"Sami languages"
],
"iso639-2": "smi",
"iso639-1": null
},
Samoan: Samoan,
Sandawe: Sandawe,
Sango: Sango,
Sanskrit: Sanskrit,
Santali: Santali,
Sardinian: Sardinian,
Sasak: Sasak,
"Saxon, Low": {
name: "Saxon, Low",
names: [
"Low German",
"Low Saxon",
"German, Low",
"Saxon, Low"
],
"iso639-2": "nds",
"iso639-1": null
},
Scots: Scots,
"Scottish Gaelic": {
name: "Scottish Gaelic",
names: [
"Gaelic",
"Scottish Gaelic"
],
"iso639-2": "gla",
"iso639-1": "gd"
},
Selkup: Selkup,
"Semitic languages": {
name: "Semitic languages",
names: [
"Semitic languages"
],
"iso639-2": "sem",
"iso639-1": null
},
Sepedi: Sepedi,
Serbian: Serbian,
Serer: Serer,
Shan: Shan,
Shona: Shona,
"Sichuan Yi": {
name: "Sichuan Yi",
names: [
"Sichuan Yi",
"Nuosu"
],
"iso639-2": "iii",
"iso639-1": "ii"
},
Sicilian: Sicilian,
Sidamo: Sidamo,
"Sign Languages": {
name: "Sign Languages",
names: [
"Sign Languages"
],
"iso639-2": "sgn",
"iso639-1": null
},
Siksika: Siksika,
Sindhi: Sindhi,
Sinhala: Sinhala,
Sinhalese: Sinhalese,
"Sino-Tibetan languages": {
name: "Sino-Tibetan languages",
names: [
"Sino-Tibetan languages"
],
"iso639-2": "sit",
"iso639-1": null
},
"Siouan languages": {
name: "Siouan languages",
names: [
"Siouan languages"
],
"iso639-2": "sio",
"iso639-1": null
},
"Skolt Sami": {
name: "Skolt Sami",
names: [
"Skolt Sami"
],
"iso639-2": "sms",
"iso639-1": null
},
"Slave (Athapascan)": {
name: "Slave (Athapascan)",
names: [
"Slave (Athapascan)"
],
"iso639-2": "den",
"iso639-1": null
},
"Slavic languages": {
name: "Slavic languages",
names: [
"Slavic languages"
],
"iso639-2": "sla",
"iso639-1": null
},
Slovak: Slovak,
Slovenian: Slovenian,
Sogdian: Sogdian,
Somali: Somali,
"Songhai languages": {
name: "Songhai languages",
names: [
"Songhai languages"
],
"iso639-2": "son",
"iso639-1": null
},
Soninke: Soninke,
"Sorbian languages": {
name: "Sorbian languages",
names: [
"Sorbian languages"
],
"iso639-2": "wen",
"iso639-1": null
},
"Sotho, Northern": {
name: "Sotho, Northern",
names: [
"Pedi",
"Sepedi",
"Northern Sotho"
],
"iso639-2": "nso",
"iso639-1": null
},
"Sotho, Southern": {
name: "Sotho, Southern",
names: [
"Sotho, Southern"
],
"iso639-2": "sot",
"iso639-1": "st"
},
"South American Indian languages": {
name: "South American Indian languages",
names: [
"South American Indian languages"
],
"iso639-2": "sai",
"iso639-1": null
},
"South Ndebele": {
name: "South Ndebele",
names: [
"Ndebele, South",
"South Ndebele"
],
"iso639-2": "nbl",
"iso639-1": "nr"
},
"Southern Altai": {
name: "Southern Altai",
names: [
"Southern Altai"
],
"iso639-2": "alt",
"iso639-1": null
},
"Southern Sami": {
name: "Southern Sami",
names: [
"Southern Sami"
],
"iso639-2": "sma",
"iso639-1": null
},
Spanish: Spanish,
"Sranan Tongo": {
name: "Sranan Tongo",
names: [
"Sranan Tongo"
],
"iso639-2": "srn",
"iso639-1": null
},
"Standard Moroccan Tamazight": {
name: "Standard Moroccan Tamazight",
names: [
"Standard Moroccan Tamazight"
],
"iso639-2": "zgh",
"iso639-1": null
},
Sukuma: Sukuma,
Sumerian: Sumerian,
Sundanese: Sundanese,
Susu: Susu,
Swahili: Swahili,
Swati: Swati,
Swedish: Swedish,
"Swiss German": {
name: "Swiss German",
names: [
"Swiss German",
"Alemannic",
"Alsatian"
],
"iso639-2": "gsw",
"iso639-1": null
},
Syriac: Syriac,
Tagalog: Tagalog,
Tahitian: Tahitian,
"Tai languages": {
name: "Tai languages",
names: [
"Tai languages"
],
"iso639-2": "tai",
"iso639-1": null
},
Tajik: Tajik,
Tamashek: Tamashek,
Tamil: Tamil,
Tatar: Tatar,
Telugu: Telugu,
Tereno: Tereno,
Tetum: Tetum,
Thai: Thai,
Tibetan: Tibetan,
Tigre: Tigre,
Tigrinya: Tigrinya,
Timne: Timne,
Tiv: Tiv,
"tlhIngan-Hol": {
name: "tlhIngan-Hol",
names: [
"Klingon",
"tlhIngan-Hol"
],
"iso639-2": "tlh",
"iso639-1": null
},
Tlingit: Tlingit,
"Tok Pisin": {
name: "Tok Pisin",
names: [
"Tok Pisin"
],
"iso639-2": "tpi",
"iso639-1": null
},
Tokelau: Tokelau,
"Tonga (Nyasa)": {
name: "Tonga (Nyasa)",
names: [
"Tonga (Nyasa)"
],
"iso639-2": "tog",
"iso639-1": null
},
"Tonga (Tonga Islands)": {
name: "Tonga (Tonga Islands)",
names: [
"Tonga (Tonga Islands)"
],
"iso639-2": "ton",
"iso639-1": "to"
},
Tsimshian: Tsimshian,
Tsonga: Tsonga,
Tswana: Tswana,
Tumbuka: Tumbuka,
"Tupi languages": {
name: "Tupi languages",
names: [
"Tupi languages"
],
"iso639-2": "tup",
"iso639-1": null
},
Turkish: Turkish,
"Turkish, Ottoman (1500-1928)": {
name: "Turkish, Ottoman (1500-1928)",
names: [
"Turkish, Ottoman (1500-1928)"
],
"iso639-2": "ota",
"iso639-1": null
},
Turkmen: Turkmen,
Tuvalu: Tuvalu,
Tuvinian: Tuvinian,
Twi: Twi,
Udmurt: Udmurt,
Ugaritic: Ugaritic,
Uighur: Uighur,
Ukrainian: Ukrainian,
Umbundu: Umbundu,
"Uncoded languages": {
name: "Uncoded languages",
names: [
"Uncoded languages"
],
"iso639-2": "mis",
"iso639-1": null
},
Undetermined: Undetermined,
"Upper Sorbian": {
name: "Upper Sorbian",
names: [
"Upper Sorbian"
],
"iso639-2": "hsb",
"iso639-1": null
},
Urdu: Urdu,
Uyghur: Uyghur,
Uzbek: Uzbek,
Vai: Vai,
Valencian: Valencian,
Venda: Venda,
Vietnamese: Vietnamese,
"Volapük": {
name: "Volapük",
names: [
"Volapük"
],
"iso639-2": "vol",
"iso639-1": "vo"
},
Votic: Votic,
"Wakashan languages": {
name: "Wakashan languages",
names: [
"Wakashan languages"
],
"iso639-2": "wak",
"iso639-1": null
},
Walloon: Walloon,
Waray: Waray,
Washo: Washo,
Welsh: Welsh,
"Western Frisian": {
name: "Western Frisian",
names: [
"Western Frisian"
],
"iso639-2": "fry",
"iso639-1": "fy"
},
"Western Pahari languages": {
name: "Western Pahari languages",
names: [
"Himachali languages",
"Western Pahari languages"
],
"iso639-2": "him",
"iso639-1": null
},
Wolaitta: Wolaitta,
Wolaytta: Wolaytta,
Wolof: Wolof,
Xhosa: Xhosa,
Yakut: Yakut,
Yao: Yao,
Yapese: Yapese,
Yiddish: Yiddish,
Yoruba: Yoruba,
"Yupik languages": {
name: "Yupik languages",
names: [
"Yupik languages"
],
"iso639-2": "ypk",
"iso639-1": null
},
"Zande languages": {
name: "Zande languages",
names: [
"Zande languages"
],
"iso639-2": "znd",
"iso639-1": null
},
Zapotec: Zapotec,
Zaza: Zaza,
Zazaki: Zazaki,
Zenaga: Zenaga,
Zhuang: Zhuang,
Zulu: Zulu,
Zuni: Zuni
};
function _defineProperty$1(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
var locales = [];
var isoKeys = Object.keys(iso);
Object.keys(lcid).map(function (id) {
var locale = lcid[id];
var isoLanguage = isoKeys.find(function (name) {
return name.toLowerCase() === locale.language.toLowerCase();
});
if (locale.location && isoLanguage) {
var _locales$push;
locales.push((_locales$push = {}, _defineProperty$1(_locales$push, "name", locale.language), _defineProperty$1(_locales$push, "location", locale.location), _defineProperty$1(_locales$push, "tag", locale.tag), _defineProperty$1(_locales$push, "lcid", locale.id), _defineProperty$1(_locales$push, "iso639-2", iso[isoLanguage]["iso639-2"]), _defineProperty$1(_locales$push, "iso639-1", iso[isoLanguage]["iso639-1"]), _locales$push));
}
});
var defaultLocales = {
ar: "ar-SA",
ca: "ca-ES",
da: "da-DK",
en: "en-US",
ko: "ko-KR",
pa: "pa-IN",
pt: "pt-BR",
sv: "sv-SE"
};
/**
* Converts a 2-digit language into a full language-LOCATION locale.
* @param {String} locale
*/
function findLocale (locale) {
if (typeof locale !== "string" || locale.length === 5) return locale;
if (defaultLocales[locale]) return defaultLocales[locale];
var list = locales.filter(function (d) {
return d["iso639-1"] === locale;
});
if (!list.length) return locale;else if (list.length === 1) return list[0].tag;else if (list.find(function (d) {
return d.tag === "".concat(locale, "-").concat(locale.toUpperCase());
})) return "".concat(locale, "-").concat(locale.toUpperCase());else return list[0].tag;
}
/**
@function s
@desc Returns 4 random characters, used for constructing unique identifiers.
@private
*/
function s$1() {
return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
}
/**
@function uuid
@summary Returns a unique identifier.
*/
function uuid () {
return "".concat(s$1()).concat(s$1(), "-").concat(s$1(), "-").concat(s$1(), "-").concat(s$1(), "-").concat(s$1()).concat(s$1()).concat(s$1());
}
/**
@constant RESET
@desc String constant used to reset an individual config property.
*/
var RESET = "D3PLUS-COMMON-RESET";
var esES = {
"and": "y",
"Back": "Atrás",
"Click to Expand": "Clic para Ampliar",
"Click to Hide": "Clic para Ocultar",
"Click to Highlight": "Clic para Resaltar",
"Click to Reset": "Clic para Restablecer",
"Download": "Descargar",
"Loading Visualization": "Cargando Visualización",
"No Data Available": "Datos No Disponibles",
"Powered by D3plus": "Funciona con D3plus",
"Share": "Porcentaje",
"Shift+Click to Hide": "Mayús+Clic para Ocultar",
"Total": "Total",
"Values": "Valores"
};
var dictionaries = {
"es-ES": esES
};
function _classCallCheck$1(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$1(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$1(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$1(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$1(Constructor, staticProps);
return Constructor;
}
/**
@desc Recursive function that resets nested Object configs.
@param {Object} obj
@param {Object} defaults
@private
*/
function nestedReset(obj, defaults) {
if (isObject(obj)) {
for (var nestedKey in obj) {
if ({}.hasOwnProperty.call(obj, nestedKey) && !nestedKey.startsWith("_")) {
var defaultValue = defaults && isObject(defaults) ? defaults[nestedKey] : undefined;
if (obj[nestedKey] === RESET) {
if (defaultValue) obj[nestedKey] = defaultValue;else delete obj[nestedKey];
} else if (isObject(obj[nestedKey])) {
nestedReset(obj[nestedKey], defaultValue);
}
}
}
}
}
/**
* @desc finds all prototype methods of a class and it's parent classes
* @param {*} obj
* @private
*/
function getAllMethods(obj) {
var props = [];
do {
props = props.concat(Object.getOwnPropertyNames(obj));
obj = Object.getPrototypeOf(obj);
} while (obj && obj !== Object.prototype);
return props.filter(function (e) {
return e.indexOf("_") !== 0 && !["config", "constructor", "parent", "render"].includes(e);
});
}
/**
@class BaseClass
@summary An abstract class that contains some global methods and functionality.
*/
var BaseClass = /*#__PURE__*/function () {
/**
@memberof BaseClass
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function BaseClass() {
var _this = this;
_classCallCheck$1(this, BaseClass);
this._locale = "en-US";
this._on = {};
this._parent = {};
this._translate = function (d) {
var locale = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _this._locale;
var dictionary = dictionaries[locale];
return dictionary && dictionary[d] ? dictionary[d] : d;
};
this._uuid = uuid();
}
/**
@memberof BaseClass
@desc If *value* is specified, sets the methods that correspond to the key/value pairs and returns this class. If *value* is not specified, returns the current configuration.
@param {Object} [*value*]
@chainable
*/
_createClass$1(BaseClass, [{
key: "config",
value: function config(_) {
var _this2 = this;
if (!this._configDefault) {
var config = {};
getAllMethods(this.__proto__).forEach(function (k) {
var v = _this2[k]();
if (v !== _this2) config[k] = isObject(v) ? assign({}, v) : v;
});
this._configDefault = config;
}
if (arguments.length) {
for (var k in _) {
if ({}.hasOwnProperty.call(_, k) && k in this) {
var v = _[k];
if (v === RESET) {
if (k === "on") this._on = this._configDefault[k];else this[k](this._configDefault[k]);
} else {
nestedReset(v, this._configDefault[k]);
this[k](v);
}
}
}
return this;
} else {
var _config = {};
getAllMethods(this.__proto__).forEach(function (k) {
_config[k] = _this2[k]();
});
return _config;
}
}
/**
@memberof BaseClass
@desc Sets the locale used for all text and number formatting. This method supports the locales defined in [d3plus-format](https://github.com/d3plus/d3plus-format/blob/master/src/locale.js). The locale can be defined as a complex Object (like in d3plus-format), a locale code (like "en-US"), or a 2-digit language code (like "en"). If a 2-digit code is provided, the "findLocale" function is used to identify the most approximate locale from d3plus-format.
@param {Object|String} [*value* = "en-US"]
@chainable
@example
{
separator: "",
suffixes: ["y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "B", "t", "q", "Q", "Z", "Y"],
grouping: [3],
delimiters: {
thousands: ",",
decimal: "."
},
currency: ["$", ""]
}
*/
}, {
key: "locale",
value: function locale(_) {
return arguments.length ? (this._locale = findLocale(_), this) : this._locale;
}
/**
@memberof BaseClass
@desc Adds or removes a *listener* to each object for the specified event *typenames*. If a *listener* is not specified, returns the currently assigned listener for the specified event *typename*. Mirrors the core [d3-selection](https://github.com/d3/d3-selection#selection_on) behavior.
@param {String} [*typenames*]
@param {Function} [*listener*]
@chainable
@example <caption>By default, listeners apply globally to all objects, however, passing a namespace with the class name gives control over specific elements:</caption>
new Plot
.on("click.Shape", function(d) {
console.log("data for shape clicked:", d);
})
.on("click.Legend", function(d) {
console.log("data for legend clicked:", d);
})
*/
}, {
key: "on",
value: function on(_, f) {
return arguments.length === 2 ? (this._on[_] = f, this) : arguments.length ? typeof _ === "string" ? this._on[_] : (this._on = Object.assign({}, this._on, _), this) : this._on;
}
/**
@memberof Viz
@desc If *value* is specified, sets the parent config used by the wrapper and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "parent",
value: function parent(_) {
return arguments.length ? (this._parent = _, this) : this._parent;
}
/**
@memberof BaseClass
@desc Defines how informational text strings should be displayed. By default, this function will try to find the string in question (which is the first argument provided to this function) inside of an internally managed translation Object. If you'd like to override to use custom text, simply pass this method your own custom formatting function.
@param {Function} [*value*]
@chainable
@example <caption>For example, if we wanted to only change the string "Back" and allow all other string to return in English:</caption>
.translate(function(d) {
return d === "Back" ? "Get outta here" : d;
})
*/
}, {
key: "translate",
value: function translate(_) {
return arguments.length ? (this._translate = _, this) : this._translate;
}
/**
@memberof Viz
@desc If *value* is specified, sets the config method for each shape and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "shapeConfig",
value: function shapeConfig(_) {
return arguments.length ? (this._shapeConfig = assign(this._shapeConfig, _), this) : this._shapeConfig;
}
}]);
return BaseClass;
}();
/**
@function closest
@desc Finds the closest numeric value in an array.
@param {Number} n The number value to use when searching the array.
@param {Array} arr The array of values to test against.
*/
function closest (n) {
var arr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
if (!arr || !(arr instanceof Array) || !arr.length) return undefined;
return arr.reduce(function (prev, curr) {
return Math.abs(curr - n) < Math.abs(prev - n) ? curr : prev;
});
}
function _typeof$2(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$2 = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$2 = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$2(obj);
}
/**
@function configPrep
@desc Preps a config object for d3plus data, and optionally bubbles up a specific nested type. When using this function, you must bind a d3plus class' `this` context.
@param {Object} [config = this._shapeConfig] The configuration object to parse.
@param {String} [type = "shape"] The event classifier to user for "on" events. For example, the default event type of "shape" will apply all events in the "on" config object with that key, like "click.shape" and "mouseleave.shape", in addition to any gloval events like "click" and "mouseleave".
@param {String} [nest] An optional nested key to bubble up to the parent config level.
*/
function configPrep() {
var _this = this;
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this._shapeConfig;
var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "shape";
var nest = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var newConfig = {
duration: this._duration,
on: {}
};
var wrapFunction = function wrapFunction(func) {
return function (d, i, s) {
var parent;
while (d.__d3plus__) {
if (parent) d.__d3plusParent__ = parent;
parent = d;
i = d.i;
d = d.data || d.feature;
}
return func.bind(_this)(d, i, s || parent);
};
};
var parseEvents = function parseEvents(newObj, on) {
for (var event in on) {
if ({}.hasOwnProperty.call(on, event) && !event.includes(".") || event.includes(".".concat(type))) {
newObj.on[event] = wrapFunction(on[event]);
}
}
};
var arrayEval = function arrayEval(arr) {
return arr.map(function (d) {
if (d instanceof Array) return arrayEval(d);else if (_typeof$2(d) === "object") return keyEval({}, d);else if (typeof d === "function") return wrapFunction(d);else return d;
});
};
var keyEval = function keyEval(newObj, obj) {
for (var key in obj) {
if ({}.hasOwnProperty.call(obj, key)) {
if (key === "on") parseEvents(newObj, obj[key]);else if (typeof obj[key] === "function") {
newObj[key] = wrapFunction(obj[key]);
} else if (obj[key] instanceof Array) {
newObj[key] = arrayEval(obj[key]);
} else if (_typeof$2(obj[key]) === "object") {
newObj[key] = {
on: {}
};
keyEval(newObj[key], obj[key]);
} else newObj[key] = obj[key];
}
}
};
keyEval(newConfig, config);
if (this._on) parseEvents(newConfig, this._on);
if (nest && config[nest]) {
keyEval(newConfig, config[nest]);
if (config[nest].on) parseEvents(newConfig, config[nest].on);
}
return newConfig;
}
/**
@function constant
@desc Wraps non-function variables in a simple return function.
@param {Array|Number|Object|String} value The value to be returned from the function.
@example <caption>this</caption>
constant(42);
@example <caption>returns this</caption>
function() {
return 42;
}
*/
function constant$1 (value) {
return function constant() {
return value;
};
}
var xhtml = "http://www.w3.org/1999/xhtml";
var namespaces = {
svg: "http://www.w3.org/2000/svg",
xhtml: xhtml,
xlink: "http://www.w3.org/1999/xlink",
xml: "http://www.w3.org/XML/1998/namespace",
xmlns: "http://www.w3.org/2000/xmlns/"
};
function namespace (name) {
var prefix = name += "",
i = prefix.indexOf(":");
if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
return namespaces.hasOwnProperty(prefix) ? {
space: namespaces[prefix],
local: name
} : name;
}
function creatorInherit(name) {
return function () {
var document = this.ownerDocument,
uri = this.namespaceURI;
return uri === xhtml && document.documentElement.namespaceURI === xhtml ? document.createElement(name) : document.createElementNS(uri, name);
};
}
function creatorFixed(fullname) {
return function () {
return this.ownerDocument.createElementNS(fullname.space, fullname.local);
};
}
function creator (name) {
var fullname = namespace(name);
return (fullname.local ? creatorFixed : creatorInherit)(fullname);
}
function none$2() {}
function selector (selector) {
return selector == null ? none$2 : function () {
return this.querySelector(selector);
};
}
function selection_select (select) {
if (typeof select !== "function") select = selector(select);
for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
if ("__data__" in node) subnode.__data__ = node.__data__;
subgroup[i] = subnode;
}
}
}
return new Selection(subgroups, this._parents);
}
function empty() {
return [];
}
function selectorAll (selector) {
return selector == null ? empty : function () {
return this.querySelectorAll(selector);
};
}
function selection_selectAll (select) {
if (typeof select !== "function") select = selectorAll(select);
for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
if (node = group[i]) {
subgroups.push(select.call(node, node.__data__, i, group));
parents.push(node);
}
}
}
return new Selection(subgroups, parents);
}
function matcher (selector) {
return function () {
return this.matches(selector);
};
}
function selection_filter (match) {
if (typeof match !== "function") match = matcher(match);
for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
subgroup.push(node);
}
}
}
return new Selection(subgroups, this._parents);
}
function sparse (update) {
return new Array(update.length);
}
function selection_enter () {
return new Selection(this._enter || this._groups.map(sparse), this._parents);
}
function EnterNode(parent, datum) {
this.ownerDocument = parent.ownerDocument;
this.namespaceURI = parent.namespaceURI;
this._next = null;
this._parent = parent;
this.__data__ = datum;
}
EnterNode.prototype = {
constructor: EnterNode,
appendChild: function appendChild(child) {
return this._parent.insertBefore(child, this._next);
},
insertBefore: function insertBefore(child, next) {
return this._parent.insertBefore(child, next);
},
querySelector: function querySelector(selector) {
return this._parent.querySelector(selector);
},
querySelectorAll: function querySelectorAll(selector) {
return this._parent.querySelectorAll(selector);
}
};
function constant$2 (x) {
return function () {
return x;
};
}
var keyPrefix = "$"; // Protect against keys like “__proto__”.
function bindIndex(parent, group, enter, update, exit, data) {
var i = 0,
node,
groupLength = group.length,
dataLength = data.length; // Put any non-null nodes that fit into update.
// Put any null nodes into enter.
// Put any remaining data into enter.
for (; i < dataLength; ++i) {
if (node = group[i]) {
node.__data__ = data[i];
update[i] = node;
} else {
enter[i] = new EnterNode(parent, data[i]);
}
} // Put any non-null nodes that dont fit into exit.
for (; i < groupLength; ++i) {
if (node = group[i]) {
exit[i] = node;
}
}
}
function bindKey(parent, group, enter, update, exit, data, key) {
var i,
node,
nodeByKeyValue = {},
groupLength = group.length,
dataLength = data.length,
keyValues = new Array(groupLength),
keyValue; // Compute the key for each node.
// If multiple nodes have the same key, the duplicates are added to exit.
for (i = 0; i < groupLength; ++i) {
if (node = group[i]) {
keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group);
if (keyValue in nodeByKeyValue) {
exit[i] = node;
} else {
nodeByKeyValue[keyValue] = node;
}
}
} // Compute the key for each datum.
// If there a node associated with this key, join and add it to update.
// If there is not (or the key is a duplicate), add it to enter.
for (i = 0; i < dataLength; ++i) {
keyValue = keyPrefix + key.call(parent, data[i], i, data);
if (node = nodeByKeyValue[keyValue]) {
update[i] = node;
node.__data__ = data[i];
nodeByKeyValue[keyValue] = null;
} else {
enter[i] = new EnterNode(parent, data[i]);
}
} // Add any remaining nodes that were not bound to data to exit.
for (i = 0; i < groupLength; ++i) {
if ((node = group[i]) && nodeByKeyValue[keyValues[i]] === node) {
exit[i] = node;
}
}
}
function selection_data (value, key) {
if (!value) {
data = new Array(this.size()), j = -1;
this.each(function (d) {
data[++j] = d;
});
return data;
}
var bind = key ? bindKey : bindIndex,
parents = this._parents,
groups = this._groups;
if (typeof value !== "function") value = constant$2(value);
for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
var parent = parents[j],
group = groups[j],
groupLength = group.length,
data = value.call(parent, parent && parent.__data__, j, parents),
dataLength = data.length,
enterGroup = enter[j] = new Array(dataLength),
updateGroup = update[j] = new Array(dataLength),
exitGroup = exit[j] = new Array(groupLength);
bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); // Now connect the enter nodes to their following update node, such that
// appendChild can insert the materialized enter node before this node,
// rather than at the end of the parent node.
for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
if (previous = enterGroup[i0]) {
if (i0 >= i1) i1 = i0 + 1;
while (!(next = updateGroup[i1]) && ++i1 < dataLength) {
}
previous._next = next || null;
}
}
}
update = new Selection(update, parents);
update._enter = enter;
update._exit = exit;
return update;
}
function selection_exit () {
return new Selection(this._exit || this._groups.map(sparse), this._parents);
}
function selection_join (onenter, onupdate, onexit) {
var enter = this.enter(),
update = this,
exit = this.exit();
enter = typeof onenter === "function" ? onenter(enter) : enter.append(onenter + "");
if (onupdate != null) update = onupdate(update);
if (onexit == null) exit.remove();else onexit(exit);
return enter && update ? enter.merge(update).order() : update;
}
function selection_merge (selection) {
for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
if (node = group0[i] || group1[i]) {
merge[i] = node;
}
}
}
for (; j < m0; ++j) {
merges[j] = groups0[j];
}
return new Selection(merges, this._parents);
}
function selection_order () {
for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
if (node = group[i]) {
if (next && node.compareDocumentPosition(next) ^ 4) next.parentNode.insertBefore(node, next);
next = node;
}
}
}
return this;
}
function selection_sort (compare) {
if (!compare) compare = ascending$2;
function compareNode(a, b) {
return a && b ? compare(a.__data__, b.__data__) : !a - !b;
}
for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
if (node = group[i]) {
sortgroup[i] = node;
}
}
sortgroup.sort(compareNode);
}
return new Selection(sortgroups, this._parents).order();
}
function ascending$2(a, b) {
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}
function selection_call () {
var callback = arguments[0];
arguments[0] = this;
callback.apply(null, arguments);
return this;
}
function selection_nodes () {
var nodes = new Array(this.size()),
i = -1;
this.each(function () {
nodes[++i] = this;
});
return nodes;
}
function selection_node () {
for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
var node = group[i];
if (node) return node;
}
}
return null;
}
function selection_size () {
var size = 0;
this.each(function () {
++size;
});
return size;
}
function selection_empty () {
return !this.node();
}
function selection_each (callback) {
for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
if (node = group[i]) callback.call(node, node.__data__, i, group);
}
}
return this;
}
function attrRemove(name) {
return function () {
this.removeAttribute(name);
};
}
function attrRemoveNS(fullname) {
return function () {
this.removeAttributeNS(fullname.space, fullname.local);
};
}
function attrConstant(name, value) {
return function () {
this.setAttribute(name, value);
};
}
function attrConstantNS(fullname, value) {
return function () {
this.setAttributeNS(fullname.space, fullname.local, value);
};
}
function attrFunction(name, value) {
return function () {
var v = value.apply(this, arguments);
if (v == null) this.removeAttribute(name);else this.setAttribute(name, v);
};
}
function attrFunctionNS(fullname, value) {
return function () {
var v = value.apply(this, arguments);
if (v == null) this.removeAttributeNS(fullname.space, fullname.local);else this.setAttributeNS(fullname.space, fullname.local, v);
};
}
function selection_attr (name, value) {
var fullname = namespace(name);
if (arguments.length < 2) {
var node = this.node();
return fullname.local ? node.getAttributeNS(fullname.space, fullname.local) : node.getAttribute(fullname);
}
return this.each((value == null ? fullname.local ? attrRemoveNS : attrRemove : typeof value === "function" ? fullname.local ? attrFunctionNS : attrFunction : fullname.local ? attrConstantNS : attrConstant)(fullname, value));
}
function defaultView (node) {
return node.ownerDocument && node.ownerDocument.defaultView || // node is a Node
node.document && node // node is a Window
|| node.defaultView; // node is a Document
}
function styleRemove(name) {
return function () {
this.style.removeProperty(name);
};
}
function styleConstant(name, value, priority) {
return function () {
this.style.setProperty(name, value, priority);
};
}
function styleFunction(name, value, priority) {
return function () {
var v = value.apply(this, arguments);
if (v == null) this.style.removeProperty(name);else this.style.setProperty(name, v, priority);
};
}
function selection_style (name, value, priority) {
return arguments.length > 1 ? this.each((value == null ? styleRemove : typeof value === "function" ? styleFunction : styleConstant)(name, value, priority == null ? "" : priority)) : styleValue(this.node(), name);
}
function styleValue(node, name) {
return node.style.getPropertyValue(name) || defaultView(node).getComputedStyle(node, null).getPropertyValue(name);
}
function propertyRemove(name) {
return function () {
delete this[name];
};
}
function propertyConstant(name, value) {
return function () {
this[name] = value;
};
}
function propertyFunction(name, value) {
return function () {
var v = value.apply(this, arguments);
if (v == null) delete this[name];else this[name] = v;
};
}
function selection_property (name, value) {
return arguments.length > 1 ? this.each((value == null ? propertyRemove : typeof value === "function" ? propertyFunction : propertyConstant)(name, value)) : this.node()[name];
}
function classArray(string) {
return string.trim().split(/^|\s+/);
}
function classList(node) {
return node.classList || new ClassList(node);
}
function ClassList(node) {
this._node = node;
this._names = classArray(node.getAttribute("class") || "");
}
ClassList.prototype = {
add: function add(name) {
var i = this._names.indexOf(name);
if (i < 0) {
this._names.push(name);
this._node.setAttribute("class", this._names.join(" "));
}
},
remove: function remove(name) {
var i = this._names.indexOf(name);
if (i >= 0) {
this._names.splice(i, 1);
this._node.setAttribute("class", this._names.join(" "));
}
},
contains: function contains(name) {
return this._names.indexOf(name) >= 0;
}
};
function classedAdd(node, names) {
var list = classList(node),
i = -1,
n = names.length;
while (++i < n) {
list.add(names[i]);
}
}
function classedRemove(node, names) {
var list = classList(node),
i = -1,
n = names.length;
while (++i < n) {
list.remove(names[i]);
}
}
function classedTrue(names) {
return function () {
classedAdd(this, names);
};
}
function classedFalse(names) {
return function () {
classedRemove(this, names);
};
}
function classedFunction(names, value) {
return function () {
(value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);
};
}
function selection_classed (name, value) {
var names = classArray(name + "");
if (arguments.length < 2) {
var list = classList(this.node()),
i = -1,
n = names.length;
while (++i < n) {
if (!list.contains(names[i])) return false;
}
return true;
}
return this.each((typeof value === "function" ? classedFunction : value ? classedTrue : classedFalse)(names, value));
}
function textRemove() {
this.textContent = "";
}
function textConstant(value) {
return function () {
this.textContent = value;
};
}
function textFunction(value) {
return function () {
var v = value.apply(this, arguments);
this.textContent = v == null ? "" : v;
};
}
function selection_text (value) {
return arguments.length ? this.each(value == null ? textRemove : (typeof value === "function" ? textFunction : textConstant)(value)) : this.node().textContent;
}
function htmlRemove() {
this.innerHTML = "";
}
function htmlConstant(value) {
return function () {
this.innerHTML = value;
};
}
function htmlFunction(value) {
return function () {
var v = value.apply(this, arguments);
this.innerHTML = v == null ? "" : v;
};
}
function selection_html (value) {
return arguments.length ? this.each(value == null ? htmlRemove : (typeof value === "function" ? htmlFunction : htmlConstant)(value)) : this.node().innerHTML;
}
function raise() {
if (this.nextSibling) this.parentNode.appendChild(this);
}
function selection_raise () {
return this.each(raise);
}
function lower() {
if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);
}
function selection_lower () {
return this.each(lower);
}
function selection_append (name) {
var create = typeof name === "function" ? name : creator(name);
return this.select(function () {
return this.appendChild(create.apply(this, arguments));
});
}
function constantNull() {
return null;
}
function selection_insert (name, before) {
var create = typeof name === "function" ? name : creator(name),
select = before == null ? constantNull : typeof before === "function" ? before : selector(before);
return this.select(function () {
return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
});
}
function remove() {
var parent = this.parentNode;
if (parent) parent.removeChild(this);
}
function selection_remove () {
return this.each(remove);
}
function selection_cloneShallow() {
var clone = this.cloneNode(false),
parent = this.parentNode;
return parent ? parent.insertBefore(clone, this.nextSibling) : clone;
}
function selection_cloneDeep() {
var clone = this.cloneNode(true),
parent = this.parentNode;
return parent ? parent.insertBefore(clone, this.nextSibling) : clone;
}
function selection_clone (deep) {
return this.select(deep ? selection_cloneDeep : selection_cloneShallow);
}
function selection_datum (value) {
return arguments.length ? this.property("__data__", value) : this.node().__data__;
}
var filterEvents = {};
var event$1 = null;
if (typeof document !== "undefined") {
var element = document.documentElement;
if (!("onmouseenter" in element)) {
filterEvents = {
mouseenter: "mouseover",
mouseleave: "mouseout"
};
}
}
function filterContextListener(listener, index, group) {
listener = contextListener(listener, index, group);
return function (event) {
var related = event.relatedTarget;
if (!related || related !== this && !(related.compareDocumentPosition(this) & 8)) {
listener.call(this, event);
}
};
}
function contextListener(listener, index, group) {
return function (event1) {
var event0 = event$1; // Events can be reentrant (e.g., focus).
event$1 = event1;
try {
listener.call(this, this.__data__, index, group);
} finally {
event$1 = event0;
}
};
}
function parseTypenames(typenames) {
return typenames.trim().split(/^|\s+/).map(function (t) {
var name = "",
i = t.indexOf(".");
if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
return {
type: t,
name: name
};
});
}
function onRemove(typename) {
return function () {
var on = this.__on;
if (!on) return;
for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
this.removeEventListener(o.type, o.listener, o.capture);
} else {
on[++i] = o;
}
}
if (++i) on.length = i;else delete this.__on;
};
}
function onAdd(typename, value, capture) {
var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener;
return function (d, i, group) {
var on = this.__on,
o,
listener = wrap(value, i, group);
if (on) for (var j = 0, m = on.length; j < m; ++j) {
if ((o = on[j]).type === typename.type && o.name === typename.name) {
this.removeEventListener(o.type, o.listener, o.capture);
this.addEventListener(o.type, o.listener = listener, o.capture = capture);
o.value = value;
return;
}
}
this.addEventListener(typename.type, listener, capture);
o = {
type: typename.type,
name: typename.name,
value: value,
listener: listener,
capture: capture
};
if (!on) this.__on = [o];else on.push(o);
};
}
function selection_on (typename, value, capture) {
var typenames = parseTypenames(typename + ""),
i,
n = typenames.length,
t;
if (arguments.length < 2) {
var on = this.node().__on;
if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
for (i = 0, o = on[j]; i < n; ++i) {
if ((t = typenames[i]).type === o.type && t.name === o.name) {
return o.value;
}
}
}
return;
}
on = value ? onAdd : onRemove;
if (capture == null) capture = false;
for (i = 0; i < n; ++i) {
this.each(on(typenames[i], value, capture));
}
return this;
}
function customEvent(event1, listener, that, args) {
var event0 = event$1;
event1.sourceEvent = event$1;
event$1 = event1;
try {
return listener.apply(that, args);
} finally {
event$1 = event0;
}
}
function dispatchEvent(node, type, params) {
var window = defaultView(node),
event = window.CustomEvent;
if (typeof event === "function") {
event = new event(type, params);
} else {
event = window.document.createEvent("Event");
if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;else event.initEvent(type, false, false);
}
node.dispatchEvent(event);
}
function dispatchConstant(type, params) {
return function () {
return dispatchEvent(this, type, params);
};
}
function dispatchFunction(type, params) {
return function () {
return dispatchEvent(this, type, params.apply(this, arguments));
};
}
function selection_dispatch (type, params) {
return this.each((typeof params === "function" ? dispatchFunction : dispatchConstant)(type, params));
}
var root = [null];
function Selection(groups, parents) {
this._groups = groups;
this._parents = parents;
}
function selection() {
return new Selection([[document.documentElement]], root);
}
Selection.prototype = selection.prototype = {
constructor: Selection,
select: selection_select,
selectAll: selection_selectAll,
filter: selection_filter,
data: selection_data,
enter: selection_enter,
exit: selection_exit,
join: selection_join,
merge: selection_merge,
order: selection_order,
sort: selection_sort,
call: selection_call,
nodes: selection_nodes,
node: selection_node,
size: selection_size,
empty: selection_empty,
each: selection_each,
attr: selection_attr,
style: selection_style,
property: selection_property,
classed: selection_classed,
text: selection_text,
html: selection_html,
raise: selection_raise,
lower: selection_lower,
append: selection_append,
insert: selection_insert,
remove: selection_remove,
clone: selection_clone,
datum: selection_datum,
on: selection_on,
dispatch: selection_dispatch
};
function _select (selector) {
return typeof selector === "string" ? new Selection([[document.querySelector(selector)]], [document.documentElement]) : new Selection([[selector]], root);
}
function sourceEvent () {
var current = event$1,
source;
while (source = current.sourceEvent) {
current = source;
}
return current;
}
function point (node, event) {
var svg = node.ownerSVGElement || node;
if (svg.createSVGPoint) {
var point = svg.createSVGPoint();
point.x = event.clientX, point.y = event.clientY;
point = point.matrixTransform(node.getScreenCTM().inverse());
return [point.x, point.y];
}
var rect = node.getBoundingClientRect();
return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
}
function mouse (node) {
var event = sourceEvent();
if (event.changedTouches) event = event.changedTouches[0];
return point(node, event);
}
function selectAll (selector) {
return typeof selector === "string" ? new Selection([document.querySelectorAll(selector)], [document.documentElement]) : new Selection([selector == null ? [] : selector], root);
}
function touch (node, touches, identifier) {
if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches;
for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) {
if ((touch = touches[i]).identifier === identifier) {
return point(node, touch);
}
}
return null;
}
var noop$1 = {
value: function value() {}
};
function dispatch() {
for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
if (!(t = arguments[i] + "") || t in _ || /[\s.]/.test(t)) throw new Error("illegal type: " + t);
_[t] = [];
}
return new Dispatch(_);
}
function Dispatch(_) {
this._ = _;
}
function parseTypenames$1(typenames, types) {
return typenames.trim().split(/^|\s+/).map(function (t) {
var name = "",
i = t.indexOf(".");
if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t);
return {
type: t,
name: name
};
});
}
Dispatch.prototype = dispatch.prototype = {
constructor: Dispatch,
on: function on(typename, callback) {
var _ = this._,
T = parseTypenames$1(typename + "", _),
t,
i = -1,
n = T.length; // If no callback was specified, return the callback of the given type and name.
if (arguments.length < 2) {
while (++i < n) {
if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t;
}
return;
} // If a type was specified, set the callback for the given type and name.
// Otherwise, if a null callback was specified, remove callbacks of the given name.
if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback);
while (++i < n) {
if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback);else if (callback == null) for (t in _) {
_[t] = set(_[t], typename.name, null);
}
}
return this;
},
copy: function copy() {
var copy = {},
_ = this._;
for (var t in _) {
copy[t] = _[t].slice();
}
return new Dispatch(copy);
},
call: function call(type, that) {
if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) {
args[i] = arguments[i + 2];
}
if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
for (t = this._[type], i = 0, n = t.length; i < n; ++i) {
t[i].value.apply(that, args);
}
},
apply: function apply(type, that, args) {
if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
for (var t = this._[type], i = 0, n = t.length; i < n; ++i) {
t[i].value.apply(that, args);
}
}
};
function get(type, name) {
for (var i = 0, n = type.length, c; i < n; ++i) {
if ((c = type[i]).name === name) {
return c.value;
}
}
}
function set(type, name, callback) {
for (var i = 0, n = type.length; i < n; ++i) {
if (type[i].name === name) {
type[i] = noop$1, type = type.slice(0, i).concat(type.slice(i + 1));
break;
}
}
if (callback != null) type.push({
name: name,
value: callback
});
return type;
}
var frame = 0,
// is an animation frame pending?
timeout = 0,
// is a timeout pending?
interval = 0,
// are any timers active?
pokeDelay = 1000,
// how frequently we check for clock skew
taskHead,
taskTail,
clockLast = 0,
clockNow = 0,
clockSkew = 0,
clock = (typeof performance === "undefined" ? "undefined" : _typeof(performance)) === "object" && performance.now ? performance : Date,
setFrame = (typeof window === "undefined" ? "undefined" : _typeof(window)) === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function (f) {
setTimeout(f, 17);
};
function now() {
return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);
}
function clearNow() {
clockNow = 0;
}
function Timer() {
this._call = this._time = this._next = null;
}
Timer.prototype = timer.prototype = {
constructor: Timer,
restart: function restart(callback, delay, time) {
if (typeof callback !== "function") throw new TypeError("callback is not a function");
time = (time == null ? now() : +time) + (delay == null ? 0 : +delay);
if (!this._next && taskTail !== this) {
if (taskTail) taskTail._next = this;else taskHead = this;
taskTail = this;
}
this._call = callback;
this._time = time;
sleep();
},
stop: function stop() {
if (this._call) {
this._call = null;
this._time = Infinity;
sleep();
}
}
};
function timer(callback, delay, time) {
var t = new Timer();
t.restart(callback, delay, time);
return t;
}
function timerFlush() {
now(); // Get the current time, if not already set.
++frame; // Pretend weve set an alarm, if we havent already.
var t = taskHead,
e;
while (t) {
if ((e = clockNow - t._time) >= 0) t._call.call(null, e);
t = t._next;
}
--frame;
}
function wake() {
clockNow = (clockLast = clock.now()) + clockSkew;
frame = timeout = 0;
try {
timerFlush();
} finally {
frame = 0;
nap();
clockNow = 0;
}
}
function poke() {
var now = clock.now(),
delay = now - clockLast;
if (delay > pokeDelay) clockSkew -= delay, clockLast = now;
}
function nap() {
var t0,
t1 = taskHead,
t2,
time = Infinity;
while (t1) {
if (t1._call) {
if (time > t1._time) time = t1._time;
t0 = t1, t1 = t1._next;
} else {
t2 = t1._next, t1._next = null;
t1 = t0 ? t0._next = t2 : taskHead = t2;
}
}
taskTail = t0;
sleep(time);
}
function sleep(time) {
if (frame) return; // Soonest alarm already set, or will be.
if (timeout) timeout = clearTimeout(timeout);
var delay = time - clockNow; // Strictly less than if we recomputed clockNow.
if (delay > 24) {
if (time < Infinity) timeout = setTimeout(wake, time - clock.now() - clockSkew);
if (interval) interval = clearInterval(interval);
} else {
if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay);
frame = 1, setFrame(wake);
}
}
function timeout$1 (callback, delay, time) {
var t = new Timer();
delay = delay == null ? 0 : +delay;
t.restart(function (elapsed) {
t.stop();
callback(elapsed + delay);
}, delay, time);
return t;
}
var emptyOn = dispatch("start", "end", "cancel", "interrupt");
var emptyTween = [];
var CREATED = 0;
var SCHEDULED = 1;
var STARTING = 2;
var STARTED = 3;
var RUNNING = 4;
var ENDING = 5;
var ENDED = 6;
function schedule (node, name, id, index, group, timing) {
var schedules = node.__transition;
if (!schedules) node.__transition = {};else if (id in schedules) return;
create(node, id, {
name: name,
index: index,
// For context during callback.
group: group,
// For context during callback.
on: emptyOn,
tween: emptyTween,
time: timing.time,
delay: timing.delay,
duration: timing.duration,
ease: timing.ease,
timer: null,
state: CREATED
});
}
function init(node, id) {
var schedule = get$1(node, id);
if (schedule.state > CREATED) throw new Error("too late; already scheduled");
return schedule;
}
function set$1(node, id) {
var schedule = get$1(node, id);
if (schedule.state > STARTED) throw new Error("too late; already running");
return schedule;
}
function get$1(node, id) {
var schedule = node.__transition;
if (!schedule || !(schedule = schedule[id])) throw new Error("transition not found");
return schedule;
}
function create(node, id, self) {
var schedules = node.__transition,
tween; // Initialize the self timer when the transition is created.
// Note the actual delay is not known until the first callback!
schedules[id] = self;
self.timer = timer(schedule, 0, self.time);
function schedule(elapsed) {
self.state = SCHEDULED;
self.timer.restart(start, self.delay, self.time); // If the elapsed delay is less than our first sleep, start immediately.
if (self.delay <= elapsed) start(elapsed - self.delay);
}
function start(elapsed) {
var i, j, n, o; // If the state is not SCHEDULED, then we previously errored on start.
if (self.state !== SCHEDULED) return stop();
for (i in schedules) {
o = schedules[i];
if (o.name !== self.name) continue; // While this element already has a starting transition during this frame,
// defer starting an interrupting transition until that transition has a
// chance to tick (and possibly end); see d3/d3-transition#54!
if (o.state === STARTED) return timeout$1(start); // Interrupt the active transition, if any.
if (o.state === RUNNING) {
o.state = ENDED;
o.timer.stop();
o.on.call("interrupt", node, node.__data__, o.index, o.group);
delete schedules[i];
} // Cancel any pre-empted transitions.
else if (+i < id) {
o.state = ENDED;
o.timer.stop();
o.on.call("cancel", node, node.__data__, o.index, o.group);
delete schedules[i];
}
} // Defer the first tick to end of the current frame; see d3/d3#1576.
// Note the transition may be canceled after start and before the first tick!
// Note this must be scheduled before the start event; see d3/d3-transition#16!
// Assuming this is successful, subsequent callbacks go straight to tick.
timeout$1(function () {
if (self.state === STARTED) {
self.state = RUNNING;
self.timer.restart(tick, self.delay, self.time);
tick(elapsed);
}
}); // Dispatch the start event.
// Note this must be done before the tween are initialized.
self.state = STARTING;
self.on.call("start", node, node.__data__, self.index, self.group);
if (self.state !== STARTING) return; // interrupted
self.state = STARTED; // Initialize the tween, deleting null tween.
tween = new Array(n = self.tween.length);
for (i = 0, j = -1; i < n; ++i) {
if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) {
tween[++j] = o;
}
}
tween.length = j + 1;
}
function tick(elapsed) {
var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1),
i = -1,
n = tween.length;
while (++i < n) {
tween[i].call(node, t);
} // Dispatch the end event.
if (self.state === ENDING) {
self.on.call("end", node, node.__data__, self.index, self.group);
stop();
}
}
function stop() {
self.state = ENDED;
self.timer.stop();
delete schedules[id];
for (var i in schedules) {
return;
} // eslint-disable-line no-unused-vars
delete node.__transition;
}
}
function interrupt (node, name) {
var schedules = node.__transition,
schedule,
active,
empty = true,
i;
if (!schedules) return;
name = name == null ? null : name + "";
for (i in schedules) {
if ((schedule = schedules[i]).name !== name) {
empty = false;
continue;
}
active = schedule.state > STARTING && schedule.state < ENDING;
schedule.state = ENDED;
schedule.timer.stop();
schedule.on.call(active ? "interrupt" : "cancel", node, node.__data__, schedule.index, schedule.group);
delete schedules[i];
}
if (empty) delete node.__transition;
}
function selection_interrupt (name) {
return this.each(function () {
interrupt(this, name);
});
}
function define (constructor, factory, prototype) {
constructor.prototype = factory.prototype = prototype;
prototype.constructor = constructor;
}
function extend(parent, definition) {
var prototype = Object.create(parent.prototype);
for (var key in definition) {
prototype[key] = definition[key];
}
return prototype;
}
function Color() {}
var _darker = 0.7;
var _brighter = 1 / _darker;
var reI = "\\s*([+-]?\\d+)\\s*",
reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",
reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
reHex3 = /^#([0-9a-f]{3})$/,
reHex6 = /^#([0-9a-f]{6})$/,
reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"),
reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"),
reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"),
reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"),
reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"),
reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
var named = {
aliceblue: 0xf0f8ff,
antiquewhite: 0xfaebd7,
aqua: 0x00ffff,
aquamarine: 0x7fffd4,
azure: 0xf0ffff,
beige: 0xf5f5dc,
bisque: 0xffe4c4,
black: 0x000000,
blanchedalmond: 0xffebcd,
blue: 0x0000ff,
blueviolet: 0x8a2be2,
brown: 0xa52a2a,
burlywood: 0xdeb887,
cadetblue: 0x5f9ea0,
chartreuse: 0x7fff00,
chocolate: 0xd2691e,
coral: 0xff7f50,
cornflowerblue: 0x6495ed,
cornsilk: 0xfff8dc,
crimson: 0xdc143c,
cyan: 0x00ffff,
darkblue: 0x00008b,
darkcyan: 0x008b8b,
darkgoldenrod: 0xb8860b,
darkgray: 0xa9a9a9,
darkgreen: 0x006400,
darkgrey: 0xa9a9a9,
darkkhaki: 0xbdb76b,
darkmagenta: 0x8b008b,
darkolivegreen: 0x556b2f,
darkorange: 0xff8c00,
darkorchid: 0x9932cc,
darkred: 0x8b0000,
darksalmon: 0xe9967a,
darkseagreen: 0x8fbc8f,
darkslateblue: 0x483d8b,
darkslategray: 0x2f4f4f,
darkslategrey: 0x2f4f4f,
darkturquoise: 0x00ced1,
darkviolet: 0x9400d3,
deeppink: 0xff1493,
deepskyblue: 0x00bfff,
dimgray: 0x696969,
dimgrey: 0x696969,
dodgerblue: 0x1e90ff,
firebrick: 0xb22222,
floralwhite: 0xfffaf0,
forestgreen: 0x228b22,
fuchsia: 0xff00ff,
gainsboro: 0xdcdcdc,
ghostwhite: 0xf8f8ff,
gold: 0xffd700,
goldenrod: 0xdaa520,
gray: 0x808080,
green: 0x008000,
greenyellow: 0xadff2f,
grey: 0x808080,
honeydew: 0xf0fff0,
hotpink: 0xff69b4,
indianred: 0xcd5c5c,
indigo: 0x4b0082,
ivory: 0xfffff0,
khaki: 0xf0e68c,
lavender: 0xe6e6fa,
lavenderblush: 0xfff0f5,
lawngreen: 0x7cfc00,
lemonchiffon: 0xfffacd,
lightblue: 0xadd8e6,
lightcoral: 0xf08080,
lightcyan: 0xe0ffff,
lightgoldenrodyellow: 0xfafad2,
lightgray: 0xd3d3d3,
lightgreen: 0x90ee90,
lightgrey: 0xd3d3d3,
lightpink: 0xffb6c1,
lightsalmon: 0xffa07a,
lightseagreen: 0x20b2aa,
lightskyblue: 0x87cefa,
lightslategray: 0x778899,
lightslategrey: 0x778899,
lightsteelblue: 0xb0c4de,
lightyellow: 0xffffe0,
lime: 0x00ff00,
limegreen: 0x32cd32,
linen: 0xfaf0e6,
magenta: 0xff00ff,
maroon: 0x800000,
mediumaquamarine: 0x66cdaa,
mediumblue: 0x0000cd,
mediumorchid: 0xba55d3,
mediumpurple: 0x9370db,
mediumseagreen: 0x3cb371,
mediumslateblue: 0x7b68ee,
mediumspringgreen: 0x00fa9a,
mediumturquoise: 0x48d1cc,
mediumvioletred: 0xc71585,
midnightblue: 0x191970,
mintcream: 0xf5fffa,
mistyrose: 0xffe4e1,
moccasin: 0xffe4b5,
navajowhite: 0xffdead,
navy: 0x000080,
oldlace: 0xfdf5e6,
olive: 0x808000,
olivedrab: 0x6b8e23,
orange: 0xffa500,
orangered: 0xff4500,
orchid: 0xda70d6,
palegoldenrod: 0xeee8aa,
palegreen: 0x98fb98,
paleturquoise: 0xafeeee,
palevioletred: 0xdb7093,
papayawhip: 0xffefd5,
peachpuff: 0xffdab9,
peru: 0xcd853f,
pink: 0xffc0cb,
plum: 0xdda0dd,
powderblue: 0xb0e0e6,
purple: 0x800080,
rebeccapurple: 0x663399,
red: 0xff0000,
rosybrown: 0xbc8f8f,
royalblue: 0x4169e1,
saddlebrown: 0x8b4513,
salmon: 0xfa8072,
sandybrown: 0xf4a460,
seagreen: 0x2e8b57,
seashell: 0xfff5ee,
sienna: 0xa0522d,
silver: 0xc0c0c0,
skyblue: 0x87ceeb,
slateblue: 0x6a5acd,
slategray: 0x708090,
slategrey: 0x708090,
snow: 0xfffafa,
springgreen: 0x00ff7f,
steelblue: 0x4682b4,
tan: 0xd2b48c,
teal: 0x008080,
thistle: 0xd8bfd8,
tomato: 0xff6347,
turquoise: 0x40e0d0,
violet: 0xee82ee,
wheat: 0xf5deb3,
white: 0xffffff,
whitesmoke: 0xf5f5f5,
yellow: 0xffff00,
yellowgreen: 0x9acd32
};
define(Color, color, {
displayable: function displayable() {
return this.rgb().displayable();
},
hex: function hex() {
return this.rgb().hex();
},
toString: function toString() {
return this.rgb() + "";
}
});
function color(format) {
var m;
format = (format + "").trim().toLowerCase();
return (m = reHex3.exec(format)) ? (m = parseInt(m[1], 16), new Rgb(m >> 8 & 0xf | m >> 4 & 0x0f0, m >> 4 & 0xf | m & 0xf0, (m & 0xf) << 4 | m & 0xf, 1) // #f00
) : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000
: (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
: (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
: (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
: (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
: (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
: (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
: named.hasOwnProperty(format) ? rgbn(named[format]) : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) : null;
}
function rgbn(n) {
return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
}
function rgba(r, g, b, a) {
if (a <= 0) r = g = b = NaN;
return new Rgb(r, g, b, a);
}
function rgbConvert(o) {
if (!(o instanceof Color)) o = color(o);
if (!o) return new Rgb();
o = o.rgb();
return new Rgb(o.r, o.g, o.b, o.opacity);
}
function rgb(r, g, b, opacity) {
return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
}
function Rgb(r, g, b, opacity) {
this.r = +r;
this.g = +g;
this.b = +b;
this.opacity = +opacity;
}
define(Rgb, rgb, extend(Color, {
brighter: function brighter(k) {
k = k == null ? _brighter : Math.pow(_brighter, k);
return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
},
darker: function darker(k) {
k = k == null ? _darker : Math.pow(_darker, k);
return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
},
rgb: function rgb() {
return this;
},
displayable: function displayable() {
return 0 <= this.r && this.r <= 255 && 0 <= this.g && this.g <= 255 && 0 <= this.b && this.b <= 255 && 0 <= this.opacity && this.opacity <= 1;
},
hex: function hex() {
return "#" + _hex(this.r) + _hex(this.g) + _hex(this.b);
},
toString: function toString() {
var a = this.opacity;
a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
return (a === 1 ? "rgb(" : "rgba(") + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " + Math.max(0, Math.min(255, Math.round(this.b) || 0)) + (a === 1 ? ")" : ", " + a + ")");
}
}));
function _hex(value) {
value = Math.max(0, Math.min(255, Math.round(value) || 0));
return (value < 16 ? "0" : "") + value.toString(16);
}
function hsla(h, s, l, a) {
if (a <= 0) h = s = l = NaN;else if (l <= 0 || l >= 1) h = s = NaN;else if (s <= 0) h = NaN;
return new Hsl(h, s, l, a);
}
function hslConvert(o) {
if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
if (!(o instanceof Color)) o = color(o);
if (!o) return new Hsl();
if (o instanceof Hsl) return o;
o = o.rgb();
var r = o.r / 255,
g = o.g / 255,
b = o.b / 255,
min = Math.min(r, g, b),
max = Math.max(r, g, b),
h = NaN,
s = max - min,
l = (max + min) / 2;
if (s) {
if (r === max) h = (g - b) / s + (g < b) * 6;else if (g === max) h = (b - r) / s + 2;else h = (r - g) / s + 4;
s /= l < 0.5 ? max + min : 2 - max - min;
h *= 60;
} else {
s = l > 0 && l < 1 ? 0 : h;
}
return new Hsl(h, s, l, o.opacity);
}
function hsl(h, s, l, opacity) {
return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
}
function Hsl(h, s, l, opacity) {
this.h = +h;
this.s = +s;
this.l = +l;
this.opacity = +opacity;
}
define(Hsl, hsl, extend(Color, {
brighter: function brighter(k) {
k = k == null ? _brighter : Math.pow(_brighter, k);
return new Hsl(this.h, this.s, this.l * k, this.opacity);
},
darker: function darker(k) {
k = k == null ? _darker : Math.pow(_darker, k);
return new Hsl(this.h, this.s, this.l * k, this.opacity);
},
rgb: function rgb() {
var h = this.h % 360 + (this.h < 0) * 360,
s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
l = this.l,
m2 = l + (l < 0.5 ? l : 1 - l) * s,
m1 = 2 * l - m2;
return new Rgb(hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), hsl2rgb(h, m1, m2), hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), this.opacity);
},
displayable: function displayable() {
return (0 <= this.s && this.s <= 1 || isNaN(this.s)) && 0 <= this.l && this.l <= 1 && 0 <= this.opacity && this.opacity <= 1;
}
}));
/* From FvD 13.37, CSS Color Module Level 3 */
function hsl2rgb(h, m1, m2) {
return (h < 60 ? m1 + (m2 - m1) * h / 60 : h < 180 ? m2 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 : m1) * 255;
}
var deg2rad = Math.PI / 180;
var rad2deg = 180 / Math.PI;
var K = 18,
Xn = 0.96422,
Yn = 1,
Zn = 0.82521,
t0 = 4 / 29,
t1 = 6 / 29,
t2 = 3 * t1 * t1,
t3 = t1 * t1 * t1;
function labConvert(o) {
if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity);
if (o instanceof Hcl) {
if (isNaN(o.h)) return new Lab(o.l, 0, 0, o.opacity);
var h = o.h * deg2rad;
return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity);
}
if (!(o instanceof Rgb)) o = rgbConvert(o);
var r = rgb2lrgb(o.r),
g = rgb2lrgb(o.g),
b = rgb2lrgb(o.b),
y = xyz2lab((0.2225045 * r + 0.7168786 * g + 0.0606169 * b) / Yn),
x,
z;
if (r === g && g === b) x = z = y;else {
x = xyz2lab((0.4360747 * r + 0.3850649 * g + 0.1430804 * b) / Xn);
z = xyz2lab((0.0139322 * r + 0.0971045 * g + 0.7141733 * b) / Zn);
}
return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity);
}
function lab(l, a, b, opacity) {
return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity);
}
function Lab(l, a, b, opacity) {
this.l = +l;
this.a = +a;
this.b = +b;
this.opacity = +opacity;
}
define(Lab, lab, extend(Color, {
brighter: function brighter(k) {
return new Lab(this.l + K * (k == null ? 1 : k), this.a, this.b, this.opacity);
},
darker: function darker(k) {
return new Lab(this.l - K * (k == null ? 1 : k), this.a, this.b, this.opacity);
},
rgb: function rgb() {
var y = (this.l + 16) / 116,
x = isNaN(this.a) ? y : y + this.a / 500,
z = isNaN(this.b) ? y : y - this.b / 200;
x = Xn * lab2xyz(x);
y = Yn * lab2xyz(y);
z = Zn * lab2xyz(z);
return new Rgb(lrgb2rgb(3.1338561 * x - 1.6168667 * y - 0.4906146 * z), lrgb2rgb(-0.9787684 * x + 1.9161415 * y + 0.0334540 * z), lrgb2rgb(0.0719453 * x - 0.2289914 * y + 1.4052427 * z), this.opacity);
}
}));
function xyz2lab(t) {
return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
}
function lab2xyz(t) {
return t > t1 ? t * t * t : t2 * (t - t0);
}
function lrgb2rgb(x) {
return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
}
function rgb2lrgb(x) {
return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
}
function hclConvert(o) {
if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity);
if (!(o instanceof Lab)) o = labConvert(o);
if (o.a === 0 && o.b === 0) return new Hcl(NaN, 0, o.l, o.opacity);
var h = Math.atan2(o.b, o.a) * rad2deg;
return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity);
}
function hcl(h, c, l, opacity) {
return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity);
}
function Hcl(h, c, l, opacity) {
this.h = +h;
this.c = +c;
this.l = +l;
this.opacity = +opacity;
}
define(Hcl, hcl, extend(Color, {
brighter: function brighter(k) {
return new Hcl(this.h, this.c, this.l + K * (k == null ? 1 : k), this.opacity);
},
darker: function darker(k) {
return new Hcl(this.h, this.c, this.l - K * (k == null ? 1 : k), this.opacity);
},
rgb: function rgb() {
return labConvert(this).rgb();
}
}));
var A = -0.14861,
B = +1.78277,
C = -0.29227,
D = -0.90649,
E = +1.97294,
ED = E * D,
EB = E * B,
BC_DA = B * C - D * A;
function cubehelixConvert(o) {
if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity);
if (!(o instanceof Rgb)) o = rgbConvert(o);
var r = o.r / 255,
g = o.g / 255,
b = o.b / 255,
l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB),
bl = b - l,
k = (E * (g - l) - C * bl) / D,
s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)),
// NaN if l=0 or l=1
h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN;
return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity);
}
function cubehelix(h, s, l, opacity) {
return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity);
}
function Cubehelix(h, s, l, opacity) {
this.h = +h;
this.s = +s;
this.l = +l;
this.opacity = +opacity;
}
define(Cubehelix, cubehelix, extend(Color, {
brighter: function brighter(k) {
k = k == null ? _brighter : Math.pow(_brighter, k);
return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
},
darker: function darker(k) {
k = k == null ? _darker : Math.pow(_darker, k);
return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
},
rgb: function rgb() {
var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad,
l = +this.l,
a = isNaN(this.s) ? 0 : this.s * l * (1 - l),
cosh = Math.cos(h),
sinh = Math.sin(h);
return new Rgb(255 * (l + a * (A * cosh + B * sinh)), 255 * (l + a * (C * cosh + D * sinh)), 255 * (l + a * (E * cosh)), this.opacity);
}
}));
function constant$3 (x) {
return function () {
return x;
};
}
function linear(a, d) {
return function (t) {
return a + t * d;
};
}
function exponential(a, b, y) {
return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function (t) {
return Math.pow(a + t * b, y);
};
}
function gamma(y) {
return (y = +y) === 1 ? nogamma : function (a, b) {
return b - a ? exponential(a, b, y) : constant$3(isNaN(a) ? b : a);
};
}
function nogamma(a, b) {
var d = b - a;
return d ? linear(a, d) : constant$3(isNaN(a) ? b : a);
}
var interpolateRgb = (function rgbGamma(y) {
var color = gamma(y);
function rgb$1(start, end) {
var r = color((start = rgb(start)).r, (end = rgb(end)).r),
g = color(start.g, end.g),
b = color(start.b, end.b),
opacity = nogamma(start.opacity, end.opacity);
return function (t) {
start.r = r(t);
start.g = g(t);
start.b = b(t);
start.opacity = opacity(t);
return start + "";
};
}
rgb$1.gamma = rgbGamma;
return rgb$1;
})(1);
function array (a, b) {
var nb = b ? b.length : 0,
na = a ? Math.min(nb, a.length) : 0,
x = new Array(na),
c = new Array(nb),
i;
for (i = 0; i < na; ++i) {
x[i] = interpolate(a[i], b[i]);
}
for (; i < nb; ++i) {
c[i] = b[i];
}
return function (t) {
for (i = 0; i < na; ++i) {
c[i] = x[i](t);
}
return c;
};
}
function date (a, b) {
var d = new Date();
return a = +a, b -= a, function (t) {
return d.setTime(a + b * t), d;
};
}
function interpolateNumber (a, b) {
return a = +a, b -= a, function (t) {
return a + b * t;
};
}
function object (a, b) {
var i = {},
c = {},
k;
if (a === null || _typeof(a) !== "object") a = {};
if (b === null || _typeof(b) !== "object") b = {};
for (k in b) {
if (k in a) {
i[k] = interpolate(a[k], b[k]);
} else {
c[k] = b[k];
}
}
return function (t) {
for (k in i) {
c[k] = i[k](t);
}
return c;
};
}
var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,
reB = new RegExp(reA.source, "g");
function zero(b) {
return function () {
return b;
};
}
function one(b) {
return function (t) {
return b(t) + "";
};
}
function interpolateString (a, b) {
var bi = reA.lastIndex = reB.lastIndex = 0,
// scan index for next number in b
am,
// current match in a
bm,
// current match in b
bs,
// string preceding current number in b, if any
i = -1,
// index in s
s = [],
// string constants and placeholders
q = []; // number interpolators
// Coerce inputs to strings.
a = a + "", b = b + ""; // Interpolate pairs of numbers in a & b.
while ((am = reA.exec(a)) && (bm = reB.exec(b))) {
if ((bs = bm.index) > bi) {
// a string precedes the next number in b
bs = b.slice(bi, bs);
if (s[i]) s[i] += bs; // coalesce with previous string
else s[++i] = bs;
}
if ((am = am[0]) === (bm = bm[0])) {
// numbers in a & b match
if (s[i]) s[i] += bm; // coalesce with previous string
else s[++i] = bm;
} else {
// interpolate non-matching numbers
s[++i] = null;
q.push({
i: i,
x: interpolateNumber(am, bm)
});
}
bi = reB.lastIndex;
} // Add remains of b.
if (bi < b.length) {
bs = b.slice(bi);
if (s[i]) s[i] += bs; // coalesce with previous string
else s[++i] = bs;
} // Special optimization for only a single match.
// Otherwise, interpolate each of the numbers and rejoin the string.
return s.length < 2 ? q[0] ? one(q[0].x) : zero(b) : (b = q.length, function (t) {
for (var i = 0, o; i < b; ++i) {
s[(o = q[i]).i] = o.x(t);
}
return s.join("");
});
}
function interpolate (a, b) {
var t = _typeof(b),
c;
return b == null || t === "boolean" ? constant$3(b) : (t === "number" ? interpolateNumber : t === "string" ? (c = color(b)) ? (b = c, interpolateRgb) : interpolateString : b instanceof color ? interpolateRgb : b instanceof Date ? date : Array.isArray(b) ? array : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object : interpolateNumber)(a, b);
}
function interpolateRound (a, b) {
return a = +a, b -= a, function (t) {
return Math.round(a + b * t);
};
}
var degrees = 180 / Math.PI;
var identity$1 = {
translateX: 0,
translateY: 0,
rotate: 0,
skewX: 0,
scaleX: 1,
scaleY: 1
};
function decompose (a, b, c, d, e, f) {
var scaleX, scaleY, skewX;
if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX;
if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX;
if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY;
if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX;
return {
translateX: e,
translateY: f,
rotate: Math.atan2(b, a) * degrees,
skewX: Math.atan(skewX) * degrees,
scaleX: scaleX,
scaleY: scaleY
};
}
var cssNode, cssRoot, cssView, svgNode;
function parseCss(value) {
if (value === "none") return identity$1;
if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView;
cssNode.style.transform = value;
value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform");
cssRoot.removeChild(cssNode);
value = value.slice(7, -1).split(",");
return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]);
}
function parseSvg(value) {
if (value == null) return identity$1;
if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g");
svgNode.setAttribute("transform", value);
if (!(value = svgNode.transform.baseVal.consolidate())) return identity$1;
value = value.matrix;
return decompose(value.a, value.b, value.c, value.d, value.e, value.f);
}
function interpolateTransform(parse, pxComma, pxParen, degParen) {
function pop(s) {
return s.length ? s.pop() + " " : "";
}
function translate(xa, ya, xb, yb, s, q) {
if (xa !== xb || ya !== yb) {
var i = s.push("translate(", null, pxComma, null, pxParen);
q.push({
i: i - 4,
x: interpolateNumber(xa, xb)
}, {
i: i - 2,
x: interpolateNumber(ya, yb)
});
} else if (xb || yb) {
s.push("translate(" + xb + pxComma + yb + pxParen);
}
}
function rotate(a, b, s, q) {
if (a !== b) {
if (a - b > 180) b += 360;else if (b - a > 180) a += 360; // shortest path
q.push({
i: s.push(pop(s) + "rotate(", null, degParen) - 2,
x: interpolateNumber(a, b)
});
} else if (b) {
s.push(pop(s) + "rotate(" + b + degParen);
}
}
function skewX(a, b, s, q) {
if (a !== b) {
q.push({
i: s.push(pop(s) + "skewX(", null, degParen) - 2,
x: interpolateNumber(a, b)
});
} else if (b) {
s.push(pop(s) + "skewX(" + b + degParen);
}
}
function scale(xa, ya, xb, yb, s, q) {
if (xa !== xb || ya !== yb) {
var i = s.push(pop(s) + "scale(", null, ",", null, ")");
q.push({
i: i - 4,
x: interpolateNumber(xa, xb)
}, {
i: i - 2,
x: interpolateNumber(ya, yb)
});
} else if (xb !== 1 || yb !== 1) {
s.push(pop(s) + "scale(" + xb + "," + yb + ")");
}
}
return function (a, b) {
var s = [],
// string constants and placeholders
q = []; // number interpolators
a = parse(a), b = parse(b);
translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q);
rotate(a.rotate, b.rotate, s, q);
skewX(a.skewX, b.skewX, s, q);
scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q);
a = b = null; // gc
return function (t) {
var i = -1,
n = q.length,
o;
while (++i < n) {
s[(o = q[i]).i] = o.x(t);
}
return s.join("");
};
};
}
var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)");
var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")");
var rho = Math.SQRT2,
rho2 = 2,
rho4 = 4,
epsilon2 = 1e-12;
function cosh(x) {
return ((x = Math.exp(x)) + 1 / x) / 2;
}
function sinh(x) {
return ((x = Math.exp(x)) - 1 / x) / 2;
}
function tanh(x) {
return ((x = Math.exp(2 * x)) - 1) / (x + 1);
} // p0 = [ux0, uy0, w0]
// p1 = [ux1, uy1, w1]
function interpolateZoom (p0, p1) {
var ux0 = p0[0],
uy0 = p0[1],
w0 = p0[2],
ux1 = p1[0],
uy1 = p1[1],
w1 = p1[2],
dx = ux1 - ux0,
dy = uy1 - uy0,
d2 = dx * dx + dy * dy,
i,
S; // Special case for u0 ≅ u1.
if (d2 < epsilon2) {
S = Math.log(w1 / w0) / rho;
i = function i(t) {
return [ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(rho * t * S)];
};
} // General case.
else {
var d1 = Math.sqrt(d2),
b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1),
b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1),
r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0),
r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);
S = (r1 - r0) / rho;
i = function i(t) {
var s = t * S,
coshr0 = cosh(r0),
u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0));
return [ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / cosh(rho * s + r0)];
};
}
i.duration = S * 1000;
return i;
}
function tweenRemove(id, name) {
var tween0, tween1;
return function () {
var schedule = set$1(this, id),
tween = schedule.tween; // If this node shared tween with the previous node,
// just assign the updated shared tween and were done!
// Otherwise, copy-on-write.
if (tween !== tween0) {
tween1 = tween0 = tween;
for (var i = 0, n = tween1.length; i < n; ++i) {
if (tween1[i].name === name) {
tween1 = tween1.slice();
tween1.splice(i, 1);
break;
}
}
}
schedule.tween = tween1;
};
}
function tweenFunction(id, name, value) {
var tween0, tween1;
if (typeof value !== "function") throw new Error();
return function () {
var schedule = set$1(this, id),
tween = schedule.tween; // If this node shared tween with the previous node,
// just assign the updated shared tween and were done!
// Otherwise, copy-on-write.
if (tween !== tween0) {
tween1 = (tween0 = tween).slice();
for (var t = {
name: name,
value: value
}, i = 0, n = tween1.length; i < n; ++i) {
if (tween1[i].name === name) {
tween1[i] = t;
break;
}
}
if (i === n) tween1.push(t);
}
schedule.tween = tween1;
};
}
function transition_tween (name, value) {
var id = this._id;
name += "";
if (arguments.length < 2) {
var tween = get$1(this.node(), id).tween;
for (var i = 0, n = tween.length, t; i < n; ++i) {
if ((t = tween[i]).name === name) {
return t.value;
}
}
return null;
}
return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value));
}
function tweenValue(transition, name, value) {
var id = transition._id;
transition.each(function () {
var schedule = set$1(this, id);
(schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments);
});
return function (node) {
return get$1(node, id).value[name];
};
}
function interpolate$1 (a, b) {
var c;
return (typeof b === "number" ? interpolateNumber : b instanceof color ? interpolateRgb : (c = color(b)) ? (b = c, interpolateRgb) : interpolateString)(a, b);
}
function attrRemove$1(name) {
return function () {
this.removeAttribute(name);
};
}
function attrRemoveNS$1(fullname) {
return function () {
this.removeAttributeNS(fullname.space, fullname.local);
};
}
function attrConstant$1(name, interpolate, value1) {
var string00,
string1 = value1 + "",
interpolate0;
return function () {
var string0 = this.getAttribute(name);
return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);
};
}
function attrConstantNS$1(fullname, interpolate, value1) {
var string00,
string1 = value1 + "",
interpolate0;
return function () {
var string0 = this.getAttributeNS(fullname.space, fullname.local);
return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);
};
}
function attrFunction$1(name, interpolate, value) {
var string00, string10, interpolate0;
return function () {
var string0,
value1 = value(this),
string1;
if (value1 == null) return void this.removeAttribute(name);
string0 = this.getAttribute(name);
string1 = value1 + "";
return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));
};
}
function attrFunctionNS$1(fullname, interpolate, value) {
var string00, string10, interpolate0;
return function () {
var string0,
value1 = value(this),
string1;
if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local);
string0 = this.getAttributeNS(fullname.space, fullname.local);
string1 = value1 + "";
return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));
};
}
function transition_attr (name, value) {
var fullname = namespace(name),
i = fullname === "transform" ? interpolateTransformSvg : interpolate$1;
return this.attrTween(name, typeof value === "function" ? (fullname.local ? attrFunctionNS$1 : attrFunction$1)(fullname, i, tweenValue(this, "attr." + name, value)) : value == null ? (fullname.local ? attrRemoveNS$1 : attrRemove$1)(fullname) : (fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, i, value));
}
function attrInterpolate(name, i) {
return function (t) {
this.setAttribute(name, i.call(this, t));
};
}
function attrInterpolateNS(fullname, i) {
return function (t) {
this.setAttributeNS(fullname.space, fullname.local, i.call(this, t));
};
}
function attrTweenNS(fullname, value) {
var t0, i0;
function tween() {
var i = value.apply(this, arguments);
if (i !== i0) t0 = (i0 = i) && attrInterpolateNS(fullname, i);
return t0;
}
tween._value = value;
return tween;
}
function attrTween(name, value) {
var t0, i0;
function tween() {
var i = value.apply(this, arguments);
if (i !== i0) t0 = (i0 = i) && attrInterpolate(name, i);
return t0;
}
tween._value = value;
return tween;
}
function transition_attrTween (name, value) {
var key = "attr." + name;
if (arguments.length < 2) return (key = this.tween(key)) && key._value;
if (value == null) return this.tween(key, null);
if (typeof value !== "function") throw new Error();
var fullname = namespace(name);
return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value));
}
function delayFunction(id, value) {
return function () {
init(this, id).delay = +value.apply(this, arguments);
};
}
function delayConstant(id, value) {
return value = +value, function () {
init(this, id).delay = value;
};
}
function transition_delay (value) {
var id = this._id;
return arguments.length ? this.each((typeof value === "function" ? delayFunction : delayConstant)(id, value)) : get$1(this.node(), id).delay;
}
function durationFunction(id, value) {
return function () {
set$1(this, id).duration = +value.apply(this, arguments);
};
}
function durationConstant(id, value) {
return value = +value, function () {
set$1(this, id).duration = value;
};
}
function transition_duration (value) {
var id = this._id;
return arguments.length ? this.each((typeof value === "function" ? durationFunction : durationConstant)(id, value)) : get$1(this.node(), id).duration;
}
function easeConstant(id, value) {
if (typeof value !== "function") throw new Error();
return function () {
set$1(this, id).ease = value;
};
}
function transition_ease (value) {
var id = this._id;
return arguments.length ? this.each(easeConstant(id, value)) : get$1(this.node(), id).ease;
}
function transition_filter (match) {
if (typeof match !== "function") match = matcher(match);
for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
subgroup.push(node);
}
}
}
return new Transition(subgroups, this._parents, this._name, this._id);
}
function transition_merge (transition) {
if (transition._id !== this._id) throw new Error();
for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
if (node = group0[i] || group1[i]) {
merge[i] = node;
}
}
}
for (; j < m0; ++j) {
merges[j] = groups0[j];
}
return new Transition(merges, this._parents, this._name, this._id);
}
function start(name) {
return (name + "").trim().split(/^|\s+/).every(function (t) {
var i = t.indexOf(".");
if (i >= 0) t = t.slice(0, i);
return !t || t === "start";
});
}
function onFunction(id, name, listener) {
var on0,
on1,
sit = start(name) ? init : set$1;
return function () {
var schedule = sit(this, id),
on = schedule.on; // If this node shared a dispatch with the previous node,
// just assign the updated shared dispatch and were done!
// Otherwise, copy-on-write.
if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener);
schedule.on = on1;
};
}
function transition_on (name, listener) {
var id = this._id;
return arguments.length < 2 ? get$1(this.node(), id).on.on(name) : this.each(onFunction(id, name, listener));
}
function removeFunction(id) {
return function () {
var parent = this.parentNode;
for (var i in this.__transition) {
if (+i !== id) return;
}
if (parent) parent.removeChild(this);
};
}
function transition_remove () {
return this.on("end.remove", removeFunction(this._id));
}
function transition_select (select) {
var name = this._name,
id = this._id;
if (typeof select !== "function") select = selector(select);
for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
if ("__data__" in node) subnode.__data__ = node.__data__;
subgroup[i] = subnode;
schedule(subgroup[i], name, id, i, subgroup, get$1(node, id));
}
}
}
return new Transition(subgroups, this._parents, name, id);
}
function transition_selectAll (select) {
var name = this._name,
id = this._id;
if (typeof select !== "function") select = selectorAll(select);
for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
if (node = group[i]) {
for (var children = select.call(node, node.__data__, i, group), child, inherit = get$1(node, id), k = 0, l = children.length; k < l; ++k) {
if (child = children[k]) {
schedule(child, name, id, k, children, inherit);
}
}
subgroups.push(children);
parents.push(node);
}
}
}
return new Transition(subgroups, parents, name, id);
}
var Selection$1 = selection.prototype.constructor;
function transition_selection () {
return new Selection$1(this._groups, this._parents);
}
function styleNull(name, interpolate) {
var string00, string10, interpolate0;
return function () {
var string0 = styleValue(this, name),
string1 = (this.style.removeProperty(name), styleValue(this, name));
return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : interpolate0 = interpolate(string00 = string0, string10 = string1);
};
}
function styleRemove$1(name) {
return function () {
this.style.removeProperty(name);
};
}
function styleConstant$1(name, interpolate, value1) {
var string00,
string1 = value1 + "",
interpolate0;
return function () {
var string0 = styleValue(this, name);
return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);
};
}
function styleFunction$1(name, interpolate, value) {
var string00, string10, interpolate0;
return function () {
var string0 = styleValue(this, name),
value1 = value(this),
string1 = value1 + "";
if (value1 == null) string1 = value1 = (this.style.removeProperty(name), styleValue(this, name));
return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));
};
}
function styleMaybeRemove(id, name) {
var on0,
on1,
listener0,
key = "style." + name,
event = "end." + key,
remove;
return function () {
var schedule = set$1(this, id),
on = schedule.on,
listener = schedule.value[key] == null ? remove || (remove = styleRemove$1(name)) : undefined; // If this node shared a dispatch with the previous node,
// just assign the updated shared dispatch and were done!
// Otherwise, copy-on-write.
if (on !== on0 || listener0 !== listener) (on1 = (on0 = on).copy()).on(event, listener0 = listener);
schedule.on = on1;
};
}
function transition_style (name, value, priority) {
var i = (name += "") === "transform" ? interpolateTransformCss : interpolate$1;
return value == null ? this.styleTween(name, styleNull(name, i)).on("end.style." + name, styleRemove$1(name)) : typeof value === "function" ? this.styleTween(name, styleFunction$1(name, i, tweenValue(this, "style." + name, value))).each(styleMaybeRemove(this._id, name)) : this.styleTween(name, styleConstant$1(name, i, value), priority).on("end.style." + name, null);
}
function styleInterpolate(name, i, priority) {
return function (t) {
this.style.setProperty(name, i.call(this, t), priority);
};
}
function styleTween(name, value, priority) {
var t, i0;
function tween() {
var i = value.apply(this, arguments);
if (i !== i0) t = (i0 = i) && styleInterpolate(name, i, priority);
return t;
}
tween._value = value;
return tween;
}
function transition_styleTween (name, value, priority) {
var key = "style." + (name += "");
if (arguments.length < 2) return (key = this.tween(key)) && key._value;
if (value == null) return this.tween(key, null);
if (typeof value !== "function") throw new Error();
return this.tween(key, styleTween(name, value, priority == null ? "" : priority));
}
function textConstant$1(value) {
return function () {
this.textContent = value;
};
}
function textFunction$1(value) {
return function () {
var value1 = value(this);
this.textContent = value1 == null ? "" : value1;
};
}
function transition_text (value) {
return this.tween("text", typeof value === "function" ? textFunction$1(tweenValue(this, "text", value)) : textConstant$1(value == null ? "" : value + ""));
}
function textInterpolate(i) {
return function (t) {
this.textContent = i.call(this, t);
};
}
function textTween(value) {
var t0, i0;
function tween() {
var i = value.apply(this, arguments);
if (i !== i0) t0 = (i0 = i) && textInterpolate(i);
return t0;
}
tween._value = value;
return tween;
}
function transition_textTween (value) {
var key = "text";
if (arguments.length < 1) return (key = this.tween(key)) && key._value;
if (value == null) return this.tween(key, null);
if (typeof value !== "function") throw new Error();
return this.tween(key, textTween(value));
}
function transition_transition () {
var name = this._name,
id0 = this._id,
id1 = newId();
for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
if (node = group[i]) {
var inherit = get$1(node, id0);
schedule(node, name, id1, i, group, {
time: inherit.time + inherit.delay + inherit.duration,
delay: 0,
duration: inherit.duration,
ease: inherit.ease
});
}
}
}
return new Transition(groups, this._parents, name, id1);
}
function transition_end () {
var on0,
on1,
that = this,
id = that._id,
size = that.size();
return new Promise(function (resolve, reject) {
var cancel = {
value: reject
},
end = {
value: function value() {
if (--size === 0) resolve();
}
};
that.each(function () {
var schedule = set$1(this, id),
on = schedule.on; // If this node shared a dispatch with the previous node,
// just assign the updated shared dispatch and were done!
// Otherwise, copy-on-write.
if (on !== on0) {
on1 = (on0 = on).copy();
on1._.cancel.push(cancel);
on1._.interrupt.push(cancel);
on1._.end.push(end);
}
schedule.on = on1;
});
});
}
var id$1 = 0;
function Transition(groups, parents, name, id) {
this._groups = groups;
this._parents = parents;
this._name = name;
this._id = id;
}
function transition(name) {
return selection().transition(name);
}
function newId() {
return ++id$1;
}
var selection_prototype = selection.prototype;
Transition.prototype = transition.prototype = {
constructor: Transition,
select: transition_select,
selectAll: transition_selectAll,
filter: transition_filter,
merge: transition_merge,
selection: transition_selection,
transition: transition_transition,
call: selection_prototype.call,
nodes: selection_prototype.nodes,
node: selection_prototype.node,
size: selection_prototype.size,
empty: selection_prototype.empty,
each: selection_prototype.each,
on: transition_on,
attr: transition_attr,
attrTween: transition_attrTween,
style: transition_style,
styleTween: transition_styleTween,
text: transition_text,
textTween: transition_textTween,
remove: transition_remove,
tween: transition_tween,
delay: transition_delay,
duration: transition_duration,
ease: transition_ease,
end: transition_end
};
function cubicInOut(t) {
return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
}
var defaultTiming = {
time: null,
// Set on use.
delay: 0,
duration: 250,
ease: cubicInOut
};
function inherit(node, id) {
var timing;
while (!(timing = node.__transition) || !(timing = timing[id])) {
if (!(node = node.parentNode)) {
return defaultTiming.time = now(), defaultTiming;
}
}
return timing;
}
function selection_transition (name) {
var id, timing;
if (name instanceof Transition) {
id = name._id, name = name._name;
} else {
id = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + "";
}
for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
if (node = group[i]) {
schedule(node, name, id, i, group, timing || inherit(node, id));
}
}
}
return new Transition(groups, this._parents, name, id);
}
selection.prototype.interrupt = selection_interrupt;
selection.prototype.transition = selection_transition;
/**
@function elem
@desc Manages the enter/update/exit pattern for a single DOM element.
@param {String} selector A D3 selector, which must include the tagname and a class and/or ID.
@param {Object} params Additional parameters.
@param {Boolean} [params.condition = true] Whether or not the element should be rendered (or removed).
@param {Object} [params.enter = {}] A collection of key/value pairs that map to attributes to be given on enter.
@param {Object} [params.exit = {}] A collection of key/value pairs that map to attributes to be given on exit.
@param {D3Selection} [params.parent = d3.select("body")] The parent element for this new element to be appended to.
@param {D3Transition} [params.transition = d3.transition().duration(0)] The transition to use when animated the different life cycle stages.
@param {Object} [params.update = {}] A collection of key/value pairs that map to attributes to be given on update.
*/
function elem (selector, p) {
// overrides default params
p = Object.assign({}, {
condition: true,
enter: {},
exit: {},
parent: _select("body"),
transition: transition().duration(0),
update: {}
}, p);
var className = /\.([^#]+)/g.exec(selector),
id = /#([^\.]+)/g.exec(selector),
tag = /^([^.^#]+)/g.exec(selector)[1];
var elem = p.parent.selectAll(selector.includes(":") ? selector.split(":")[1] : selector).data(p.condition ? [null] : []);
var enter = elem.enter().append(tag).call(attrize, p.enter);
if (id) enter.attr("id", id[1]);
if (className) enter.attr("class", className[1]);
elem.exit().transition(p.transition).call(attrize, p.exit).remove();
var update = enter.merge(elem);
update.transition(p.transition).call(attrize, p.update);
return update;
}
var prefix = "$";
function Map() {}
Map.prototype = map.prototype = {
constructor: Map,
has: function has(key) {
return prefix + key in this;
},
get: function get(key) {
return this[prefix + key];
},
set: function set(key, value) {
this[prefix + key] = value;
return this;
},
remove: function remove(key) {
var property = prefix + key;
return property in this && delete this[property];
},
clear: function clear() {
for (var property in this) {
if (property[0] === prefix) delete this[property];
}
},
keys: function keys() {
var keys = [];
for (var property in this) {
if (property[0] === prefix) keys.push(property.slice(1));
}
return keys;
},
values: function values() {
var values = [];
for (var property in this) {
if (property[0] === prefix) values.push(this[property]);
}
return values;
},
entries: function entries() {
var entries = [];
for (var property in this) {
if (property[0] === prefix) entries.push({
key: property.slice(1),
value: this[property]
});
}
return entries;
},
size: function size() {
var size = 0;
for (var property in this) {
if (property[0] === prefix) ++size;
}
return size;
},
empty: function empty() {
for (var property in this) {
if (property[0] === prefix) return false;
}
return true;
},
each: function each(f) {
for (var property in this) {
if (property[0] === prefix) f(this[property], property.slice(1), this);
}
}
};
function map(object, f) {
var map = new Map(); // Copy constructor.
if (object instanceof Map) object.each(function (value, key) {
map.set(key, value);
}); // Index array by numeric index or specified key function.
else if (Array.isArray(object)) {
var i = -1,
n = object.length,
o;
if (f == null) while (++i < n) {
map.set(i, object[i]);
} else while (++i < n) {
map.set(f(o = object[i], i, object), o);
}
} // Convert object to map.
else if (object) for (var key in object) {
map.set(key, object[key]);
}
return map;
}
function nest () {
var keys = [],
_sortKeys = [],
_sortValues,
_rollup,
nest;
function apply(array, depth, createResult, setResult) {
if (depth >= keys.length) {
if (_sortValues != null) array.sort(_sortValues);
return _rollup != null ? _rollup(array) : array;
}
var i = -1,
n = array.length,
key = keys[depth++],
keyValue,
value,
valuesByKey = map(),
values,
result = createResult();
while (++i < n) {
if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) {
values.push(value);
} else {
valuesByKey.set(keyValue, [value]);
}
}
valuesByKey.each(function (values, key) {
setResult(result, key, apply(values, depth, createResult, setResult));
});
return result;
}
function _entries(map, depth) {
if (++depth > keys.length) return map;
var array,
sortKey = _sortKeys[depth - 1];
if (_rollup != null && depth >= keys.length) array = map.entries();else array = [], map.each(function (v, k) {
array.push({
key: k,
values: _entries(v, depth)
});
});
return sortKey != null ? array.sort(function (a, b) {
return sortKey(a.key, b.key);
}) : array;
}
return nest = {
object: function object(array) {
return apply(array, 0, createObject, setObject);
},
map: function map(array) {
return apply(array, 0, createMap, setMap);
},
entries: function entries(array) {
return _entries(apply(array, 0, createMap, setMap), 0);
},
key: function key(d) {
keys.push(d);
return nest;
},
sortKeys: function sortKeys(order) {
_sortKeys[keys.length - 1] = order;
return nest;
},
sortValues: function sortValues(order) {
_sortValues = order;
return nest;
},
rollup: function rollup(f) {
_rollup = f;
return nest;
}
};
}
function createObject() {
return {};
}
function setObject(object, key, value) {
object[key] = value;
}
function createMap() {
return map();
}
function setMap(map, key, value) {
map.set(key, value);
}
function Set$1() {}
var proto = map.prototype;
Set$1.prototype = set$2.prototype = {
constructor: Set$1,
has: proto.has,
add: function add(value) {
value += "";
this[prefix + value] = value;
return this;
},
remove: proto.remove,
clear: proto.clear,
values: proto.keys,
size: proto.size,
empty: proto.empty,
each: proto.each
};
function set$2(object, f) {
var set = new Set$1(); // Copy constructor.
if (object instanceof Set$1) object.each(function (value) {
set.add(value);
}); // Otherwise, assume its an array.
else if (object) {
var i = -1,
n = object.length;
if (f == null) while (++i < n) {
set.add(object[i]);
} else while (++i < n) {
set.add(f(object[i], i, object));
}
}
return set;
}
function keys (map) {
var keys = [];
for (var key in map) {
keys.push(key);
}
return keys;
}
/**
@function unique
@desc ES5 implementation to reduce an Array of values to unique instances.
@param {Array} objects The Array of objects to be filtered.
@example <caption>this</caption>
unique(["apple", "banana", "apple"]);
@example <caption>returns this</caption>
["apple", "banana"]
*/
function unique (arr) {
return arr.filter(function (k, i, a) {
return a.indexOf(k) === i;
});
}
/**
@function merge
@desc Combines an Array of Objects together and returns a new Object.
@param {Array} objects The Array of objects to be merged together.
@param {Object} aggs An object containing specific aggregation methods (functions) for each key type. By default, numbers are summed and strings are returned as an array of unique values.
@example <caption>this</caption>
merge([
{id: "foo", group: "A", value: 10, links: [1, 2]},
{id: "bar", group: "A", value: 20, links: [1, 3]}
]);
@example <caption>returns this</caption>
{id: ["bar", "foo"], group: "A", value: 30, links: [1, 2, 3]}
*/
function objectMerge(objects) {
var aggs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var availableKeys = unique(arrayMerge(objects.map(function (o) {
return keys(o);
}))),
newObject = {};
availableKeys.forEach(function (k) {
var value;
if (aggs[k]) value = aggs[k](objects, function (o) {
return o[k];
});else {
var values = objects.map(function (o) {
return o[k];
});
var types = values.map(function (v) {
return v || v === false ? v.constructor : v;
}).filter(function (v) {
return v !== void 0;
});
if (!types.length) value = undefined;else if (types.indexOf(Array) >= 0) {
value = arrayMerge(values.map(function (v) {
return v instanceof Array ? v : [v];
}));
value = unique(value);
if (value.length === 1) value = value[0];
} else if (types.indexOf(String) >= 0) {
value = unique(values);
if (value.length === 1) value = value[0];
} else if (types.indexOf(Number) >= 0) value = sum(values);else if (types.indexOf(Object) >= 0) {
value = unique(values.filter(function (v) {
return v;
}));
if (value.length === 1) value = value[0];else value = objectMerge(value);
} else {
value = unique(values.filter(function (v) {
return v !== void 0;
}));
if (value.length === 1) value = value[0];
}
}
newObject[k] = value;
});
return newObject;
}
/**
@function parseSides
@desc Converts a string of directional CSS shorthand values into an object with the values expanded.
@param {String|Number} sides The CSS shorthand string to expand.
*/
function parseSides (sides) {
var values;
if (typeof sides === "number") values = [sides];else values = sides.split(/\s+/);
if (values.length === 1) values = [values[0], values[0], values[0], values[0]];else if (values.length === 2) values = values.concat(values);else if (values.length === 3) values.push(values[1]);
return ["top", "right", "bottom", "left"].reduce(function (acc, direction, i) {
var value = parseFloat(values[i]);
acc[direction] = value || 0;
return acc;
}, {});
}
/**
@function prefix
@desc Returns the appropriate CSS vendor prefix, given the current browser.
*/
function prefix$1 () {
if ("-webkit-transform" in document.body.style) return "-webkit-";else if ("-moz-transform" in document.body.style) return "-moz-";else if ("-ms-transform" in document.body.style) return "-ms-";else if ("-o-transform" in document.body.style) return "-o-";else return "";
}
/**
@function stylize
@desc Applies each key/value in an object as a style.
@param {D3selection} elem The D3 element to apply the styles to.
@param {Object} styles An object of key/value style pairs.
*/
function stylize (e) {
var s = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
for (var k in s) {
if ({}.hasOwnProperty.call(s, k)) e.style(k, s[k]);
}
}
function _classCallCheck$2(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$2(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$2(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$2(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$2(Constructor, staticProps);
return Constructor;
}
/**
@class Image
@desc Creates SVG images based on an array of data.
@example <caption>a sample row of data</caption>
var data = {"url": "file.png", "width": "100", "height": "50"};
@example <caption>passed to the generator</caption>
new Image().data([data]).render();
@example <caption>creates the following</caption>
<image class="d3plus-Image" opacity="1" href="file.png" width="100" height="50" x="0" y="0"></image>
@example <caption>this is shorthand for the following</caption>
image().data([data])();
@example <caption>which also allows a post-draw callback function</caption>
image().data([data])(function() { alert("draw complete!"); })
*/
var Image$1 = /*#__PURE__*/function () {
/**
@memberof Image
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function Image() {
_classCallCheck$2(this, Image);
this._duration = 600;
this._height = accessor("height");
this._id = accessor("id");
this._opacity = constant$1(1);
this._pointerEvents = constant$1("auto");
this._select;
this._url = accessor("url");
this._width = accessor("width");
this._x = accessor("x", 0);
this._y = accessor("y", 0);
}
/**
@memberof Image
@desc Renders the current Image to the page. If a *callback* is specified, it will be called once the images are done drawing.
@param {Function} [*callback*]
@chainable
*/
_createClass$2(Image, [{
key: "render",
value: function render(callback) {
var _this = this;
if (this._select === void 0) this.select(_select("body").append("svg").style("width", "".concat(window.innerWidth, "px")).style("height", "".concat(window.innerHeight, "px")).style("display", "block").node());
var images = this._select.selectAll(".d3plus-Image").data(this._data, this._id);
var enter = images.enter().append("image").attr("class", "d3plus-Image").attr("opacity", 0).attr("width", 0).attr("height", 0).attr("x", function (d, i) {
return _this._x(d, i) + _this._width(d, i) / 2;
}).attr("y", function (d, i) {
return _this._y(d, i) + _this._height(d, i) / 2;
});
var t = transition().duration(this._duration),
that = this,
update = enter.merge(images);
update.attr("xlink:href", this._url).style("pointer-events", this._pointerEvents).transition(t).attr("opacity", this._opacity).attr("width", function (d, i) {
return _this._width(d, i);
}).attr("height", function (d, i) {
return _this._height(d, i);
}).attr("x", function (d, i) {
return _this._x(d, i);
}).attr("y", function (d, i) {
return _this._y(d, i);
}).each(function (d, i) {
var image = _select(this),
link = that._url(d, i);
var fullAddress = link.indexOf("http://") === 0 || link.indexOf("https://") === 0;
if (!fullAddress || link.indexOf(window.location.hostname) === 0) {
var img = new Image();
img.src = link;
img.crossOrigin = "Anonymous";
img.onload = function () {
var canvas = document.createElement("canvas");
canvas.width = this.width;
canvas.height = this.height;
var context = canvas.getContext("2d");
context.drawImage(this, 0, 0);
image.attr("xlink:href", canvas.toDataURL("image/png"));
};
}
});
images.exit().transition(t).attr("width", function (d, i) {
return _this._width(d, i);
}).attr("height", function (d, i) {
return _this._height(d, i);
}).attr("x", function (d, i) {
return _this._x(d, i);
}).attr("y", function (d, i) {
return _this._y(d, i);
}).attr("opacity", 0).remove();
if (callback) setTimeout(callback, this._duration + 100);
return this;
}
/**
@memberof Image
@desc If *data* is specified, sets the data array to the specified array and returns the current class instance. If *data* is not specified, returns the current data array. An <image> tag will be drawn for each object in the array.
@param {Array} [*data* = []]
@chainable
*/
}, {
key: "data",
value: function data(_) {
return arguments.length ? (this._data = _, this) : this._data;
}
/**
@memberof Image
@desc If *ms* is specified, sets the animation duration to the specified number and returns the current class instance. If *ms* is not specified, returns the current animation duration.
@param {Number} [*ms* = 600]
@chainable
*/
}, {
key: "duration",
value: function duration(_) {
return arguments.length ? (this._duration = _, this) : this._duration;
}
/**
@memberof Image
@desc If *value* is specified, sets the height accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.height;
}
*/
}, {
key: "height",
value: function height(_) {
return arguments.length ? (this._height = typeof _ === "function" ? _ : constant$1(_), this) : this._height;
}
/**
@memberof Image
@desc If *value* is specified, sets the id accessor to the specified function and returns the current class instance.
@param {Function} [*value*]
@chainable
@example
function(d) {
return d.id;
}
*/
}, {
key: "id",
value: function id(_) {
return arguments.length ? (this._id = _, this) : this._id;
}
/**
@memberof Image
@desc Sets the opacity of the image.
@param {Number} [*value* = 1]
@chainable
*/
}, {
key: "opacity",
value: function opacity(_) {
return arguments.length ? (this._opacity = typeof _ === "function" ? _ : constant$1(_), this) : this._opacity;
}
/**
@memberof Image
@desc If *value* is specified, sets the pointer-events accessor to the specified function or string and returns the current class instance.
@param {Function|String} [*value* = "auto"]
@chainable
*/
}, {
key: "pointerEvents",
value: function pointerEvents(_) {
return arguments.length ? (this._pointerEvents = typeof _ === "function" ? _ : constant$1(_), this) : this._pointerEvents;
}
/**
@memberof Image
@desc If *selector* is specified, sets the SVG container element to the specified d3 selector or DOM element and returns the current class instance. If *selector* is not specified, returns the current SVG container element.
@param {String|HTMLElement} [*selector* = d3.select("body").append("svg")]
@chainable
*/
}, {
key: "select",
value: function select(_) {
return arguments.length ? (this._select = _select(_), this) : this._select;
}
/**
@memberof Image
@desc If *value* is specified, sets the URL accessor to the specified function and returns the current class instance.
@param {Function} [*value*]
@chainable
@example
function(d) {
return d.url;
}
*/
}, {
key: "url",
value: function url(_) {
return arguments.length ? (this._url = _, this) : this._url;
}
/**
@memberof Image
@desc If *value* is specified, sets the width accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.width;
}
*/
}, {
key: "width",
value: function width(_) {
return arguments.length ? (this._width = typeof _ === "function" ? _ : constant$1(_), this) : this._width;
}
/**
@memberof Image
@desc If *value* is specified, sets the x accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.x || 0;
}
*/
}, {
key: "x",
value: function x(_) {
return arguments.length ? (this._x = typeof _ === "function" ? _ : constant$1(_), this) : this._x;
}
/**
@memberof Image
@desc If *value* is specified, sets the y accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.y || 0;
}
*/
}, {
key: "y",
value: function y(_) {
return arguments.length ? (this._y = typeof _ === "function" ? _ : constant$1(_), this) : this._y;
}
}]);
return Image;
}();
function define$1 (constructor, factory, prototype) {
constructor.prototype = factory.prototype = prototype;
prototype.constructor = constructor;
}
function extend$1(parent, definition) {
var prototype = Object.create(parent.prototype);
for (var key in definition) {
prototype[key] = definition[key];
}
return prototype;
}
function Color$1() {}
var _darker$1 = 0.7;
var _brighter$1 = 1 / _darker$1;
var reI$1 = "\\s*([+-]?\\d+)\\s*",
reN$1 = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",
reP$1 = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
reHex = /^#([0-9a-f]{3,8})$/,
reRgbInteger$1 = new RegExp("^rgb\\(" + [reI$1, reI$1, reI$1] + "\\)$"),
reRgbPercent$1 = new RegExp("^rgb\\(" + [reP$1, reP$1, reP$1] + "\\)$"),
reRgbaInteger$1 = new RegExp("^rgba\\(" + [reI$1, reI$1, reI$1, reN$1] + "\\)$"),
reRgbaPercent$1 = new RegExp("^rgba\\(" + [reP$1, reP$1, reP$1, reN$1] + "\\)$"),
reHslPercent$1 = new RegExp("^hsl\\(" + [reN$1, reP$1, reP$1] + "\\)$"),
reHslaPercent$1 = new RegExp("^hsla\\(" + [reN$1, reP$1, reP$1, reN$1] + "\\)$");
var named$1 = {
aliceblue: 0xf0f8ff,
antiquewhite: 0xfaebd7,
aqua: 0x00ffff,
aquamarine: 0x7fffd4,
azure: 0xf0ffff,
beige: 0xf5f5dc,
bisque: 0xffe4c4,
black: 0x000000,
blanchedalmond: 0xffebcd,
blue: 0x0000ff,
blueviolet: 0x8a2be2,
brown: 0xa52a2a,
burlywood: 0xdeb887,
cadetblue: 0x5f9ea0,
chartreuse: 0x7fff00,
chocolate: 0xd2691e,
coral: 0xff7f50,
cornflowerblue: 0x6495ed,
cornsilk: 0xfff8dc,
crimson: 0xdc143c,
cyan: 0x00ffff,
darkblue: 0x00008b,
darkcyan: 0x008b8b,
darkgoldenrod: 0xb8860b,
darkgray: 0xa9a9a9,
darkgreen: 0x006400,
darkgrey: 0xa9a9a9,
darkkhaki: 0xbdb76b,
darkmagenta: 0x8b008b,
darkolivegreen: 0x556b2f,
darkorange: 0xff8c00,
darkorchid: 0x9932cc,
darkred: 0x8b0000,
darksalmon: 0xe9967a,
darkseagreen: 0x8fbc8f,
darkslateblue: 0x483d8b,
darkslategray: 0x2f4f4f,
darkslategrey: 0x2f4f4f,
darkturquoise: 0x00ced1,
darkviolet: 0x9400d3,
deeppink: 0xff1493,
deepskyblue: 0x00bfff,
dimgray: 0x696969,
dimgrey: 0x696969,
dodgerblue: 0x1e90ff,
firebrick: 0xb22222,
floralwhite: 0xfffaf0,
forestgreen: 0x228b22,
fuchsia: 0xff00ff,
gainsboro: 0xdcdcdc,
ghostwhite: 0xf8f8ff,
gold: 0xffd700,
goldenrod: 0xdaa520,
gray: 0x808080,
green: 0x008000,
greenyellow: 0xadff2f,
grey: 0x808080,
honeydew: 0xf0fff0,
hotpink: 0xff69b4,
indianred: 0xcd5c5c,
indigo: 0x4b0082,
ivory: 0xfffff0,
khaki: 0xf0e68c,
lavender: 0xe6e6fa,
lavenderblush: 0xfff0f5,
lawngreen: 0x7cfc00,
lemonchiffon: 0xfffacd,
lightblue: 0xadd8e6,
lightcoral: 0xf08080,
lightcyan: 0xe0ffff,
lightgoldenrodyellow: 0xfafad2,
lightgray: 0xd3d3d3,
lightgreen: 0x90ee90,
lightgrey: 0xd3d3d3,
lightpink: 0xffb6c1,
lightsalmon: 0xffa07a,
lightseagreen: 0x20b2aa,
lightskyblue: 0x87cefa,
lightslategray: 0x778899,
lightslategrey: 0x778899,
lightsteelblue: 0xb0c4de,
lightyellow: 0xffffe0,
lime: 0x00ff00,
limegreen: 0x32cd32,
linen: 0xfaf0e6,
magenta: 0xff00ff,
maroon: 0x800000,
mediumaquamarine: 0x66cdaa,
mediumblue: 0x0000cd,
mediumorchid: 0xba55d3,
mediumpurple: 0x9370db,
mediumseagreen: 0x3cb371,
mediumslateblue: 0x7b68ee,
mediumspringgreen: 0x00fa9a,
mediumturquoise: 0x48d1cc,
mediumvioletred: 0xc71585,
midnightblue: 0x191970,
mintcream: 0xf5fffa,
mistyrose: 0xffe4e1,
moccasin: 0xffe4b5,
navajowhite: 0xffdead,
navy: 0x000080,
oldlace: 0xfdf5e6,
olive: 0x808000,
olivedrab: 0x6b8e23,
orange: 0xffa500,
orangered: 0xff4500,
orchid: 0xda70d6,
palegoldenrod: 0xeee8aa,
palegreen: 0x98fb98,
paleturquoise: 0xafeeee,
palevioletred: 0xdb7093,
papayawhip: 0xffefd5,
peachpuff: 0xffdab9,
peru: 0xcd853f,
pink: 0xffc0cb,
plum: 0xdda0dd,
powderblue: 0xb0e0e6,
purple: 0x800080,
rebeccapurple: 0x663399,
red: 0xff0000,
rosybrown: 0xbc8f8f,
royalblue: 0x4169e1,
saddlebrown: 0x8b4513,
salmon: 0xfa8072,
sandybrown: 0xf4a460,
seagreen: 0x2e8b57,
seashell: 0xfff5ee,
sienna: 0xa0522d,
silver: 0xc0c0c0,
skyblue: 0x87ceeb,
slateblue: 0x6a5acd,
slategray: 0x708090,
slategrey: 0x708090,
snow: 0xfffafa,
springgreen: 0x00ff7f,
steelblue: 0x4682b4,
tan: 0xd2b48c,
teal: 0x008080,
thistle: 0xd8bfd8,
tomato: 0xff6347,
turquoise: 0x40e0d0,
violet: 0xee82ee,
wheat: 0xf5deb3,
white: 0xffffff,
whitesmoke: 0xf5f5f5,
yellow: 0xffff00,
yellowgreen: 0x9acd32
};
define$1(Color$1, color$1, {
copy: function copy(channels) {
return Object.assign(new this.constructor(), this, channels);
},
displayable: function displayable() {
return this.rgb().displayable();
},
hex: color_formatHex,
// Deprecated! Use color.formatHex.
formatHex: color_formatHex,
formatHsl: color_formatHsl,
formatRgb: color_formatRgb,
toString: color_formatRgb
});
function color_formatHex() {
return this.rgb().formatHex();
}
function color_formatHsl() {
return hslConvert$1(this).formatHsl();
}
function color_formatRgb() {
return this.rgb().formatRgb();
}
function color$1(format) {
var m, l;
format = (format + "").trim().toLowerCase();
return (m = reHex.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn$1(m) // #ff0000
: l === 3 ? new Rgb$1(m >> 8 & 0xf | m >> 4 & 0xf0, m >> 4 & 0xf | m & 0xf0, (m & 0xf) << 4 | m & 0xf, 1) // #f00
: l === 8 ? rgba$1(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000
: l === 4 ? rgba$1(m >> 12 & 0xf | m >> 8 & 0xf0, m >> 8 & 0xf | m >> 4 & 0xf0, m >> 4 & 0xf | m & 0xf0, ((m & 0xf) << 4 | m & 0xf) / 0xff) // #f000
: null // invalid hex
) : (m = reRgbInteger$1.exec(format)) ? new Rgb$1(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
: (m = reRgbPercent$1.exec(format)) ? new Rgb$1(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
: (m = reRgbaInteger$1.exec(format)) ? rgba$1(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
: (m = reRgbaPercent$1.exec(format)) ? rgba$1(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
: (m = reHslPercent$1.exec(format)) ? hsla$1(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
: (m = reHslaPercent$1.exec(format)) ? hsla$1(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
: named$1.hasOwnProperty(format) ? rgbn$1(named$1[format]) // eslint-disable-line no-prototype-builtins
: format === "transparent" ? new Rgb$1(NaN, NaN, NaN, 0) : null;
}
function rgbn$1(n) {
return new Rgb$1(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
}
function rgba$1(r, g, b, a) {
if (a <= 0) r = g = b = NaN;
return new Rgb$1(r, g, b, a);
}
function rgbConvert$1(o) {
if (!(o instanceof Color$1)) o = color$1(o);
if (!o) return new Rgb$1();
o = o.rgb();
return new Rgb$1(o.r, o.g, o.b, o.opacity);
}
function rgb$1(r, g, b, opacity) {
return arguments.length === 1 ? rgbConvert$1(r) : new Rgb$1(r, g, b, opacity == null ? 1 : opacity);
}
function Rgb$1(r, g, b, opacity) {
this.r = +r;
this.g = +g;
this.b = +b;
this.opacity = +opacity;
}
define$1(Rgb$1, rgb$1, extend$1(Color$1, {
brighter: function brighter(k) {
k = k == null ? _brighter$1 : Math.pow(_brighter$1, k);
return new Rgb$1(this.r * k, this.g * k, this.b * k, this.opacity);
},
darker: function darker(k) {
k = k == null ? _darker$1 : Math.pow(_darker$1, k);
return new Rgb$1(this.r * k, this.g * k, this.b * k, this.opacity);
},
rgb: function rgb() {
return this;
},
displayable: function displayable() {
return -0.5 <= this.r && this.r < 255.5 && -0.5 <= this.g && this.g < 255.5 && -0.5 <= this.b && this.b < 255.5 && 0 <= this.opacity && this.opacity <= 1;
},
hex: rgb_formatHex,
// Deprecated! Use color.formatHex.
formatHex: rgb_formatHex,
formatRgb: rgb_formatRgb,
toString: rgb_formatRgb
}));
function rgb_formatHex() {
return "#" + hex(this.r) + hex(this.g) + hex(this.b);
}
function rgb_formatRgb() {
var a = this.opacity;
a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
return (a === 1 ? "rgb(" : "rgba(") + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " + Math.max(0, Math.min(255, Math.round(this.b) || 0)) + (a === 1 ? ")" : ", " + a + ")");
}
function hex(value) {
value = Math.max(0, Math.min(255, Math.round(value) || 0));
return (value < 16 ? "0" : "") + value.toString(16);
}
function hsla$1(h, s, l, a) {
if (a <= 0) h = s = l = NaN;else if (l <= 0 || l >= 1) h = s = NaN;else if (s <= 0) h = NaN;
return new Hsl$1(h, s, l, a);
}
function hslConvert$1(o) {
if (o instanceof Hsl$1) return new Hsl$1(o.h, o.s, o.l, o.opacity);
if (!(o instanceof Color$1)) o = color$1(o);
if (!o) return new Hsl$1();
if (o instanceof Hsl$1) return o;
o = o.rgb();
var r = o.r / 255,
g = o.g / 255,
b = o.b / 255,
min = Math.min(r, g, b),
max = Math.max(r, g, b),
h = NaN,
s = max - min,
l = (max + min) / 2;
if (s) {
if (r === max) h = (g - b) / s + (g < b) * 6;else if (g === max) h = (b - r) / s + 2;else h = (r - g) / s + 4;
s /= l < 0.5 ? max + min : 2 - max - min;
h *= 60;
} else {
s = l > 0 && l < 1 ? 0 : h;
}
return new Hsl$1(h, s, l, o.opacity);
}
function hsl$1(h, s, l, opacity) {
return arguments.length === 1 ? hslConvert$1(h) : new Hsl$1(h, s, l, opacity == null ? 1 : opacity);
}
function Hsl$1(h, s, l, opacity) {
this.h = +h;
this.s = +s;
this.l = +l;
this.opacity = +opacity;
}
define$1(Hsl$1, hsl$1, extend$1(Color$1, {
brighter: function brighter(k) {
k = k == null ? _brighter$1 : Math.pow(_brighter$1, k);
return new Hsl$1(this.h, this.s, this.l * k, this.opacity);
},
darker: function darker(k) {
k = k == null ? _darker$1 : Math.pow(_darker$1, k);
return new Hsl$1(this.h, this.s, this.l * k, this.opacity);
},
rgb: function rgb() {
var h = this.h % 360 + (this.h < 0) * 360,
s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
l = this.l,
m2 = l + (l < 0.5 ? l : 1 - l) * s,
m1 = 2 * l - m2;
return new Rgb$1(hsl2rgb$1(h >= 240 ? h - 240 : h + 120, m1, m2), hsl2rgb$1(h, m1, m2), hsl2rgb$1(h < 120 ? h + 240 : h - 120, m1, m2), this.opacity);
},
displayable: function displayable() {
return (0 <= this.s && this.s <= 1 || isNaN(this.s)) && 0 <= this.l && this.l <= 1 && 0 <= this.opacity && this.opacity <= 1;
},
formatHsl: function formatHsl() {
var a = this.opacity;
a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
return (a === 1 ? "hsl(" : "hsla(") + (this.h || 0) + ", " + (this.s || 0) * 100 + "%, " + (this.l || 0) * 100 + "%" + (a === 1 ? ")" : ", " + a + ")");
}
}));
/* From FvD 13.37, CSS Color Module Level 3 */
function hsl2rgb$1(h, m1, m2) {
return (h < 60 ? m1 + (m2 - m1) * h / 60 : h < 180 ? m2 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 : m1) * 255;
}
function define$2 (constructor, factory, prototype) {
constructor.prototype = factory.prototype = prototype;
prototype.constructor = constructor;
}
function extend$2(parent, definition) {
var prototype = Object.create(parent.prototype);
for (var key in definition) {
prototype[key] = definition[key];
}
return prototype;
}
function Color$2() {}
var _darker$2 = 0.7;
var _brighter$2 = 1 / _darker$2;
var reI$2 = "\\s*([+-]?\\d+)\\s*",
reN$2 = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",
reP$2 = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
reHex$1 = /^#([0-9a-f]{3,8})$/,
reRgbInteger$2 = new RegExp("^rgb\\(" + [reI$2, reI$2, reI$2] + "\\)$"),
reRgbPercent$2 = new RegExp("^rgb\\(" + [reP$2, reP$2, reP$2] + "\\)$"),
reRgbaInteger$2 = new RegExp("^rgba\\(" + [reI$2, reI$2, reI$2, reN$2] + "\\)$"),
reRgbaPercent$2 = new RegExp("^rgba\\(" + [reP$2, reP$2, reP$2, reN$2] + "\\)$"),
reHslPercent$2 = new RegExp("^hsl\\(" + [reN$2, reP$2, reP$2] + "\\)$"),
reHslaPercent$2 = new RegExp("^hsla\\(" + [reN$2, reP$2, reP$2, reN$2] + "\\)$");
var named$2 = {
aliceblue: 0xf0f8ff,
antiquewhite: 0xfaebd7,
aqua: 0x00ffff,
aquamarine: 0x7fffd4,
azure: 0xf0ffff,
beige: 0xf5f5dc,
bisque: 0xffe4c4,
black: 0x000000,
blanchedalmond: 0xffebcd,
blue: 0x0000ff,
blueviolet: 0x8a2be2,
brown: 0xa52a2a,
burlywood: 0xdeb887,
cadetblue: 0x5f9ea0,
chartreuse: 0x7fff00,
chocolate: 0xd2691e,
coral: 0xff7f50,
cornflowerblue: 0x6495ed,
cornsilk: 0xfff8dc,
crimson: 0xdc143c,
cyan: 0x00ffff,
darkblue: 0x00008b,
darkcyan: 0x008b8b,
darkgoldenrod: 0xb8860b,
darkgray: 0xa9a9a9,
darkgreen: 0x006400,
darkgrey: 0xa9a9a9,
darkkhaki: 0xbdb76b,
darkmagenta: 0x8b008b,
darkolivegreen: 0x556b2f,
darkorange: 0xff8c00,
darkorchid: 0x9932cc,
darkred: 0x8b0000,
darksalmon: 0xe9967a,
darkseagreen: 0x8fbc8f,
darkslateblue: 0x483d8b,
darkslategray: 0x2f4f4f,
darkslategrey: 0x2f4f4f,
darkturquoise: 0x00ced1,
darkviolet: 0x9400d3,
deeppink: 0xff1493,
deepskyblue: 0x00bfff,
dimgray: 0x696969,
dimgrey: 0x696969,
dodgerblue: 0x1e90ff,
firebrick: 0xb22222,
floralwhite: 0xfffaf0,
forestgreen: 0x228b22,
fuchsia: 0xff00ff,
gainsboro: 0xdcdcdc,
ghostwhite: 0xf8f8ff,
gold: 0xffd700,
goldenrod: 0xdaa520,
gray: 0x808080,
green: 0x008000,
greenyellow: 0xadff2f,
grey: 0x808080,
honeydew: 0xf0fff0,
hotpink: 0xff69b4,
indianred: 0xcd5c5c,
indigo: 0x4b0082,
ivory: 0xfffff0,
khaki: 0xf0e68c,
lavender: 0xe6e6fa,
lavenderblush: 0xfff0f5,
lawngreen: 0x7cfc00,
lemonchiffon: 0xfffacd,
lightblue: 0xadd8e6,
lightcoral: 0xf08080,
lightcyan: 0xe0ffff,
lightgoldenrodyellow: 0xfafad2,
lightgray: 0xd3d3d3,
lightgreen: 0x90ee90,
lightgrey: 0xd3d3d3,
lightpink: 0xffb6c1,
lightsalmon: 0xffa07a,
lightseagreen: 0x20b2aa,
lightskyblue: 0x87cefa,
lightslategray: 0x778899,
lightslategrey: 0x778899,
lightsteelblue: 0xb0c4de,
lightyellow: 0xffffe0,
lime: 0x00ff00,
limegreen: 0x32cd32,
linen: 0xfaf0e6,
magenta: 0xff00ff,
maroon: 0x800000,
mediumaquamarine: 0x66cdaa,
mediumblue: 0x0000cd,
mediumorchid: 0xba55d3,
mediumpurple: 0x9370db,
mediumseagreen: 0x3cb371,
mediumslateblue: 0x7b68ee,
mediumspringgreen: 0x00fa9a,
mediumturquoise: 0x48d1cc,
mediumvioletred: 0xc71585,
midnightblue: 0x191970,
mintcream: 0xf5fffa,
mistyrose: 0xffe4e1,
moccasin: 0xffe4b5,
navajowhite: 0xffdead,
navy: 0x000080,
oldlace: 0xfdf5e6,
olive: 0x808000,
olivedrab: 0x6b8e23,
orange: 0xffa500,
orangered: 0xff4500,
orchid: 0xda70d6,
palegoldenrod: 0xeee8aa,
palegreen: 0x98fb98,
paleturquoise: 0xafeeee,
palevioletred: 0xdb7093,
papayawhip: 0xffefd5,
peachpuff: 0xffdab9,
peru: 0xcd853f,
pink: 0xffc0cb,
plum: 0xdda0dd,
powderblue: 0xb0e0e6,
purple: 0x800080,
rebeccapurple: 0x663399,
red: 0xff0000,
rosybrown: 0xbc8f8f,
royalblue: 0x4169e1,
saddlebrown: 0x8b4513,
salmon: 0xfa8072,
sandybrown: 0xf4a460,
seagreen: 0x2e8b57,
seashell: 0xfff5ee,
sienna: 0xa0522d,
silver: 0xc0c0c0,
skyblue: 0x87ceeb,
slateblue: 0x6a5acd,
slategray: 0x708090,
slategrey: 0x708090,
snow: 0xfffafa,
springgreen: 0x00ff7f,
steelblue: 0x4682b4,
tan: 0xd2b48c,
teal: 0x008080,
thistle: 0xd8bfd8,
tomato: 0xff6347,
turquoise: 0x40e0d0,
violet: 0xee82ee,
wheat: 0xf5deb3,
white: 0xffffff,
whitesmoke: 0xf5f5f5,
yellow: 0xffff00,
yellowgreen: 0x9acd32
};
define$2(Color$2, color$2, {
copy: function copy(channels) {
return Object.assign(new this.constructor(), this, channels);
},
displayable: function displayable() {
return this.rgb().displayable();
},
hex: color_formatHex$1,
// Deprecated! Use color.formatHex.
formatHex: color_formatHex$1,
formatHsl: color_formatHsl$1,
formatRgb: color_formatRgb$1,
toString: color_formatRgb$1
});
function color_formatHex$1() {
return this.rgb().formatHex();
}
function color_formatHsl$1() {
return hslConvert$2(this).formatHsl();
}
function color_formatRgb$1() {
return this.rgb().formatRgb();
}
function color$2(format) {
var m, l;
format = (format + "").trim().toLowerCase();
return (m = reHex$1.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn$2(m) // #ff0000
: l === 3 ? new Rgb$2(m >> 8 & 0xf | m >> 4 & 0xf0, m >> 4 & 0xf | m & 0xf0, (m & 0xf) << 4 | m & 0xf, 1) // #f00
: l === 8 ? rgba$2(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000
: l === 4 ? rgba$2(m >> 12 & 0xf | m >> 8 & 0xf0, m >> 8 & 0xf | m >> 4 & 0xf0, m >> 4 & 0xf | m & 0xf0, ((m & 0xf) << 4 | m & 0xf) / 0xff) // #f000
: null // invalid hex
) : (m = reRgbInteger$2.exec(format)) ? new Rgb$2(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
: (m = reRgbPercent$2.exec(format)) ? new Rgb$2(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
: (m = reRgbaInteger$2.exec(format)) ? rgba$2(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
: (m = reRgbaPercent$2.exec(format)) ? rgba$2(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
: (m = reHslPercent$2.exec(format)) ? hsla$2(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
: (m = reHslaPercent$2.exec(format)) ? hsla$2(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
: named$2.hasOwnProperty(format) ? rgbn$2(named$2[format]) // eslint-disable-line no-prototype-builtins
: format === "transparent" ? new Rgb$2(NaN, NaN, NaN, 0) : null;
}
function rgbn$2(n) {
return new Rgb$2(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
}
function rgba$2(r, g, b, a) {
if (a <= 0) r = g = b = NaN;
return new Rgb$2(r, g, b, a);
}
function rgbConvert$2(o) {
if (!(o instanceof Color$2)) o = color$2(o);
if (!o) return new Rgb$2();
o = o.rgb();
return new Rgb$2(o.r, o.g, o.b, o.opacity);
}
function rgb$2(r, g, b, opacity) {
return arguments.length === 1 ? rgbConvert$2(r) : new Rgb$2(r, g, b, opacity == null ? 1 : opacity);
}
function Rgb$2(r, g, b, opacity) {
this.r = +r;
this.g = +g;
this.b = +b;
this.opacity = +opacity;
}
define$2(Rgb$2, rgb$2, extend$2(Color$2, {
brighter: function brighter(k) {
k = k == null ? _brighter$2 : Math.pow(_brighter$2, k);
return new Rgb$2(this.r * k, this.g * k, this.b * k, this.opacity);
},
darker: function darker(k) {
k = k == null ? _darker$2 : Math.pow(_darker$2, k);
return new Rgb$2(this.r * k, this.g * k, this.b * k, this.opacity);
},
rgb: function rgb() {
return this;
},
displayable: function displayable() {
return -0.5 <= this.r && this.r < 255.5 && -0.5 <= this.g && this.g < 255.5 && -0.5 <= this.b && this.b < 255.5 && 0 <= this.opacity && this.opacity <= 1;
},
hex: rgb_formatHex$1,
// Deprecated! Use color.formatHex.
formatHex: rgb_formatHex$1,
formatRgb: rgb_formatRgb$1,
toString: rgb_formatRgb$1
}));
function rgb_formatHex$1() {
return "#" + hex$1(this.r) + hex$1(this.g) + hex$1(this.b);
}
function rgb_formatRgb$1() {
var a = this.opacity;
a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
return (a === 1 ? "rgb(" : "rgba(") + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " + Math.max(0, Math.min(255, Math.round(this.b) || 0)) + (a === 1 ? ")" : ", " + a + ")");
}
function hex$1(value) {
value = Math.max(0, Math.min(255, Math.round(value) || 0));
return (value < 16 ? "0" : "") + value.toString(16);
}
function hsla$2(h, s, l, a) {
if (a <= 0) h = s = l = NaN;else if (l <= 0 || l >= 1) h = s = NaN;else if (s <= 0) h = NaN;
return new Hsl$2(h, s, l, a);
}
function hslConvert$2(o) {
if (o instanceof Hsl$2) return new Hsl$2(o.h, o.s, o.l, o.opacity);
if (!(o instanceof Color$2)) o = color$2(o);
if (!o) return new Hsl$2();
if (o instanceof Hsl$2) return o;
o = o.rgb();
var r = o.r / 255,
g = o.g / 255,
b = o.b / 255,
min = Math.min(r, g, b),
max = Math.max(r, g, b),
h = NaN,
s = max - min,
l = (max + min) / 2;
if (s) {
if (r === max) h = (g - b) / s + (g < b) * 6;else if (g === max) h = (b - r) / s + 2;else h = (r - g) / s + 4;
s /= l < 0.5 ? max + min : 2 - max - min;
h *= 60;
} else {
s = l > 0 && l < 1 ? 0 : h;
}
return new Hsl$2(h, s, l, o.opacity);
}
function hsl$2(h, s, l, opacity) {
return arguments.length === 1 ? hslConvert$2(h) : new Hsl$2(h, s, l, opacity == null ? 1 : opacity);
}
function Hsl$2(h, s, l, opacity) {
this.h = +h;
this.s = +s;
this.l = +l;
this.opacity = +opacity;
}
define$2(Hsl$2, hsl$2, extend$2(Color$2, {
brighter: function brighter(k) {
k = k == null ? _brighter$2 : Math.pow(_brighter$2, k);
return new Hsl$2(this.h, this.s, this.l * k, this.opacity);
},
darker: function darker(k) {
k = k == null ? _darker$2 : Math.pow(_darker$2, k);
return new Hsl$2(this.h, this.s, this.l * k, this.opacity);
},
rgb: function rgb() {
var h = this.h % 360 + (this.h < 0) * 360,
s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
l = this.l,
m2 = l + (l < 0.5 ? l : 1 - l) * s,
m1 = 2 * l - m2;
return new Rgb$2(hsl2rgb$2(h >= 240 ? h - 240 : h + 120, m1, m2), hsl2rgb$2(h, m1, m2), hsl2rgb$2(h < 120 ? h + 240 : h - 120, m1, m2), this.opacity);
},
displayable: function displayable() {
return (0 <= this.s && this.s <= 1 || isNaN(this.s)) && 0 <= this.l && this.l <= 1 && 0 <= this.opacity && this.opacity <= 1;
},
formatHsl: function formatHsl() {
var a = this.opacity;
a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
return (a === 1 ? "hsl(" : "hsla(") + (this.h || 0) + ", " + (this.s || 0) * 100 + "%, " + (this.l || 0) * 100 + "%" + (a === 1 ? ")" : ", " + a + ")");
}
}));
/* From FvD 13.37, CSS Color Module Level 3 */
function hsl2rgb$2(h, m1, m2) {
return (h < 60 ? m1 + (m2 - m1) * h / 60 : h < 180 ? m2 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 : m1) * 255;
}
function initRange(domain, range) {
switch (arguments.length) {
case 0:
break;
case 1:
this.range(domain);
break;
default:
this.range(range).domain(domain);
break;
}
return this;
}
function initInterpolator(domain, interpolator) {
switch (arguments.length) {
case 0:
break;
case 1:
this.interpolator(domain);
break;
default:
this.interpolator(interpolator).domain(domain);
break;
}
return this;
}
var array$1 = Array.prototype;
var map$1 = array$1.map;
var slice$1 = array$1.slice;
var implicit = {
name: "implicit"
};
function ordinal() {
var index = map(),
domain = [],
range = [],
unknown = implicit;
function scale(d) {
var key = d + "",
i = index.get(key);
if (!i) {
if (unknown !== implicit) return unknown;
index.set(key, i = domain.push(d));
}
return range[(i - 1) % range.length];
}
scale.domain = function (_) {
if (!arguments.length) return domain.slice();
domain = [], index = map();
var i = -1,
n = _.length,
d,
key;
while (++i < n) {
if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d));
}
return scale;
};
scale.range = function (_) {
return arguments.length ? (range = slice$1.call(_), scale) : range.slice();
};
scale.unknown = function (_) {
return arguments.length ? (unknown = _, scale) : unknown;
};
scale.copy = function () {
return ordinal(domain, range).unknown(unknown);
};
initRange.apply(scale, arguments);
return scale;
}
function band() {
var scale = ordinal().unknown(undefined),
domain = scale.domain,
ordinalRange = scale.range,
range$1 = [0, 1],
step,
bandwidth,
round = false,
paddingInner = 0,
paddingOuter = 0,
align = 0.5;
delete scale.unknown;
function rescale() {
var n = domain().length,
reverse = range$1[1] < range$1[0],
start = range$1[reverse - 0],
stop = range$1[1 - reverse];
step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2);
if (round) step = Math.floor(step);
start += (stop - start - step * (n - paddingInner)) * align;
bandwidth = step * (1 - paddingInner);
if (round) start = Math.round(start), bandwidth = Math.round(bandwidth);
var values = range(n).map(function (i) {
return start + step * i;
});
return ordinalRange(reverse ? values.reverse() : values);
}
scale.domain = function (_) {
return arguments.length ? (domain(_), rescale()) : domain();
};
scale.range = function (_) {
return arguments.length ? (range$1 = [+_[0], +_[1]], rescale()) : range$1.slice();
};
scale.rangeRound = function (_) {
return range$1 = [+_[0], +_[1]], round = true, rescale();
};
scale.bandwidth = function () {
return bandwidth;
};
scale.step = function () {
return step;
};
scale.round = function (_) {
return arguments.length ? (round = !!_, rescale()) : round;
};
scale.padding = function (_) {
return arguments.length ? (paddingInner = Math.min(1, paddingOuter = +_), rescale()) : paddingInner;
};
scale.paddingInner = function (_) {
return arguments.length ? (paddingInner = Math.min(1, _), rescale()) : paddingInner;
};
scale.paddingOuter = function (_) {
return arguments.length ? (paddingOuter = +_, rescale()) : paddingOuter;
};
scale.align = function (_) {
return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align;
};
scale.copy = function () {
return band(domain(), range$1).round(round).paddingInner(paddingInner).paddingOuter(paddingOuter).align(align);
};
return initRange.apply(rescale(), arguments);
}
function pointish(scale) {
var copy = scale.copy;
scale.padding = scale.paddingOuter;
delete scale.paddingInner;
delete scale.paddingOuter;
scale.copy = function () {
return pointish(copy());
};
return scale;
}
function point$1() {
return pointish(band.apply(null, arguments).paddingInner(1));
}
function constant$4 (x) {
return function () {
return x;
};
}
function number$1 (x) {
return +x;
}
var unit = [0, 1];
function identity$2(x) {
return x;
}
function normalize(a, b) {
return (b -= a = +a) ? function (x) {
return (x - a) / b;
} : constant$4(isNaN(b) ? NaN : 0.5);
}
function clamper(domain) {
var a = domain[0],
b = domain[domain.length - 1],
t;
if (a > b) t = a, a = b, b = t;
return function (x) {
return Math.max(a, Math.min(b, x));
};
} // normalize(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1].
// interpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding range value x in [a,b].
function bimap(domain, range, interpolate) {
var d0 = domain[0],
d1 = domain[1],
r0 = range[0],
r1 = range[1];
if (d1 < d0) d0 = normalize(d1, d0), r0 = interpolate(r1, r0);else d0 = normalize(d0, d1), r0 = interpolate(r0, r1);
return function (x) {
return r0(d0(x));
};
}
function polymap(domain, range, interpolate) {
var j = Math.min(domain.length, range.length) - 1,
d = new Array(j),
r = new Array(j),
i = -1; // Reverse descending domains.
if (domain[j] < domain[0]) {
domain = domain.slice().reverse();
range = range.slice().reverse();
}
while (++i < j) {
d[i] = normalize(domain[i], domain[i + 1]);
r[i] = interpolate(range[i], range[i + 1]);
}
return function (x) {
var i = bisectRight(domain, x, 1, j) - 1;
return r[i](d[i](x));
};
}
function copy(source, target) {
return target.domain(source.domain()).range(source.range()).interpolate(source.interpolate()).clamp(source.clamp()).unknown(source.unknown());
}
function transformer() {
var domain = unit,
range = unit,
interpolate$1 = interpolate,
transform,
untransform,
unknown,
clamp = identity$2,
piecewise,
output,
input;
function rescale() {
piecewise = Math.min(domain.length, range.length) > 2 ? polymap : bimap;
output = input = null;
return scale;
}
function scale(x) {
return isNaN(x = +x) ? unknown : (output || (output = piecewise(domain.map(transform), range, interpolate$1)))(transform(clamp(x)));
}
scale.invert = function (y) {
return clamp(untransform((input || (input = piecewise(range, domain.map(transform), interpolateNumber)))(y)));
};
scale.domain = function (_) {
return arguments.length ? (domain = map$1.call(_, number$1), clamp === identity$2 || (clamp = clamper(domain)), rescale()) : domain.slice();
};
scale.range = function (_) {
return arguments.length ? (range = slice$1.call(_), rescale()) : range.slice();
};
scale.rangeRound = function (_) {
return range = slice$1.call(_), interpolate$1 = interpolateRound, rescale();
};
scale.clamp = function (_) {
return arguments.length ? (clamp = _ ? clamper(domain) : identity$2, scale) : clamp !== identity$2;
};
scale.interpolate = function (_) {
return arguments.length ? (interpolate$1 = _, rescale()) : interpolate$1;
};
scale.unknown = function (_) {
return arguments.length ? (unknown = _, scale) : unknown;
};
return function (t, u) {
transform = t, untransform = u;
return rescale();
};
}
function continuous(transform, untransform) {
return transformer()(transform, untransform);
}
// Computes the decimal coefficient and exponent of the specified number x with
// significant digits p, where x is positive and p is in [1, 21] or undefined.
// For example, formatDecimal(1.23) returns ["123", 0].
function formatDecimal (x, p) {
if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
var i,
coefficient = x.slice(0, i); // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
// (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
return [coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, +x.slice(i + 1)];
}
function exponent (x) {
return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
}
function formatGroup (grouping, thousands) {
return function (value, width) {
var i = value.length,
t = [],
j = 0,
g = grouping[0],
length = 0;
while (i > 0 && g > 0) {
if (length + g + 1 > width) g = Math.max(1, width - length);
t.push(value.substring(i -= g, i + g));
if ((length += g + 1) > width) break;
g = grouping[j = (j + 1) % grouping.length];
}
return t.reverse().join(thousands);
};
}
function formatNumerals (numerals) {
return function (value) {
return value.replace(/[0-9]/g, function (i) {
return numerals[+i];
});
};
}
// [[fill]align][sign][symbol][0][width][,][.precision][~][type]
var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;
function formatSpecifier(specifier) {
return new FormatSpecifier(specifier);
}
formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof
function FormatSpecifier(specifier) {
if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
var match;
this.fill = match[1] || " ";
this.align = match[2] || ">";
this.sign = match[3] || "-";
this.symbol = match[4] || "";
this.zero = !!match[5];
this.width = match[6] && +match[6];
this.comma = !!match[7];
this.precision = match[8] && +match[8].slice(1);
this.trim = !!match[9];
this.type = match[10] || "";
}
FormatSpecifier.prototype.toString = function () {
return this.fill + this.align + this.sign + this.symbol + (this.zero ? "0" : "") + (this.width == null ? "" : Math.max(1, this.width | 0)) + (this.comma ? "," : "") + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0)) + (this.trim ? "~" : "") + this.type;
};
// Trims insignificant zeros, e.g., replaces 1.2000k with 1.2k.
function formatTrim (s) {
out: for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) {
switch (s[i]) {
case ".":
i0 = i1 = i;
break;
case "0":
if (i0 === 0) i0 = i;
i1 = i;
break;
default:
if (i0 > 0) {
if (!+s[i]) break out;
i0 = 0;
}
break;
}
}
return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s;
}
var prefixExponent;
function formatPrefixAuto (x, p) {
var d = formatDecimal(x, p);
if (!d) return x + "";
var coefficient = d[0],
exponent = d[1],
i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
n = coefficient.length;
return i === n ? coefficient : i > n ? coefficient + new Array(i - n + 1).join("0") : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y!
}
function formatRounded (x, p) {
var d = formatDecimal(x, p);
if (!d) return x + "";
var coefficient = d[0],
exponent = d[1];
return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) : coefficient + new Array(exponent - coefficient.length + 2).join("0");
}
var formatTypes = {
"%": function _(x, p) {
return (x * 100).toFixed(p);
},
"b": function b(x) {
return Math.round(x).toString(2);
},
"c": function c(x) {
return x + "";
},
"d": function d(x) {
return Math.round(x).toString(10);
},
"e": function e(x, p) {
return x.toExponential(p);
},
"f": function f(x, p) {
return x.toFixed(p);
},
"g": function g(x, p) {
return x.toPrecision(p);
},
"o": function o(x) {
return Math.round(x).toString(8);
},
"p": function p(x, _p) {
return formatRounded(x * 100, _p);
},
"r": formatRounded,
"s": formatPrefixAuto,
"X": function X(x) {
return Math.round(x).toString(16).toUpperCase();
},
"x": function x(_x) {
return Math.round(_x).toString(16);
}
};
function identity$3 (x) {
return x;
}
var prefixes = ["y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y"];
function formatLocale (locale) {
var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity$3,
currency = locale.currency,
decimal = locale.decimal,
numerals = locale.numerals ? formatNumerals(locale.numerals) : identity$3,
percent = locale.percent || "%";
function newFormat(specifier) {
specifier = formatSpecifier(specifier);
var fill = specifier.fill,
align = specifier.align,
sign = specifier.sign,
symbol = specifier.symbol,
zero = specifier.zero,
width = specifier.width,
comma = specifier.comma,
precision = specifier.precision,
trim = specifier.trim,
type = specifier.type; // The "n" type is an alias for ",g".
if (type === "n") comma = true, type = "g"; // The "" type, and any invalid type, is an alias for ".12~g".
else if (!formatTypes[type]) precision == null && (precision = 12), trim = true, type = "g"; // If zero fill is specified, padding goes after sign and before digits.
if (zero || fill === "0" && align === "=") zero = true, fill = "0", align = "="; // Compute the prefix and suffix.
// For SI-prefix, the suffix is lazily computed.
var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? percent : ""; // What format function should we use?
// Is this an integer type?
// Can this type generate exponential notation?
var formatType = formatTypes[type],
maybeSuffix = /[defgprs%]/.test(type); // Set the default precision if not specified,
// or clamp the specified precision to the supported range.
// For significant precision, it must be in [1, 21].
// For fixed precision, it must be in [0, 20].
precision = precision == null ? 6 : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) : Math.max(0, Math.min(20, precision));
function format(value) {
var valuePrefix = prefix,
valueSuffix = suffix,
i,
n,
c;
if (type === "c") {
valueSuffix = formatType(value) + valueSuffix;
value = "";
} else {
value = +value; // Perform the initial formatting.
var valueNegative = value < 0;
value = formatType(Math.abs(value), precision); // Trim insignificant zeros.
if (trim) value = formatTrim(value); // If a negative value rounds to zero during formatting, treat as positive.
if (valueNegative && +value === 0) valueNegative = false; // Compute the prefix and suffix.
valuePrefix = (valueNegative ? sign === "(" ? sign : "-" : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
valueSuffix = (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : ""); // Break the formatted value into the integer “value” part that can be
// grouped, and fractional or exponential “suffix” part that is not.
if (maybeSuffix) {
i = -1, n = value.length;
while (++i < n) {
if (c = value.charCodeAt(i), 48 > c || c > 57) {
valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
value = value.slice(0, i);
break;
}
}
}
} // If the fill character is not "0", grouping is applied before padding.
if (comma && !zero) value = group(value, Infinity); // Compute the padding.
var length = valuePrefix.length + value.length + valueSuffix.length,
padding = length < width ? new Array(width - length + 1).join(fill) : ""; // If the fill character is "0", grouping is applied after padding.
if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; // Reconstruct the final output based on the desired alignment.
switch (align) {
case "<":
value = valuePrefix + value + valueSuffix + padding;
break;
case "=":
value = valuePrefix + padding + value + valueSuffix;
break;
case "^":
value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length);
break;
default:
value = padding + valuePrefix + value + valueSuffix;
break;
}
return numerals(value);
}
format.toString = function () {
return specifier + "";
};
return format;
}
function formatPrefix(specifier, value) {
var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
k = Math.pow(10, -e),
prefix = prefixes[8 + e / 3];
return function (value) {
return f(k * value) + prefix;
};
}
return {
format: newFormat,
formatPrefix: formatPrefix
};
}
var locale;
var format;
var formatPrefix;
defaultLocale({
decimal: ".",
thousands: ",",
grouping: [3],
currency: ["$", ""]
});
function defaultLocale(definition) {
locale = formatLocale(definition);
format = locale.format;
formatPrefix = locale.formatPrefix;
return locale;
}
function precisionFixed (step) {
return Math.max(0, -exponent(Math.abs(step)));
}
function precisionPrefix (step, value) {
return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step)));
}
function precisionRound (step, max) {
step = Math.abs(step), max = Math.abs(max) - step;
return Math.max(0, exponent(max) - exponent(step)) + 1;
}
function tickFormat (start, stop, count, specifier) {
var step = tickStep(start, stop, count),
precision;
specifier = formatSpecifier(specifier == null ? ",f" : specifier);
switch (specifier.type) {
case "s":
{
var value = Math.max(Math.abs(start), Math.abs(stop));
if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
return formatPrefix(specifier, value);
}
case "":
case "e":
case "g":
case "p":
case "r":
{
if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
break;
}
case "f":
case "%":
{
if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
break;
}
}
return format(specifier);
}
function linearish(scale) {
var domain = scale.domain;
scale.ticks = function (count) {
var d = domain();
return d3Ticks(d[0], d[d.length - 1], count == null ? 10 : count);
};
scale.tickFormat = function (count, specifier) {
var d = domain();
return tickFormat(d[0], d[d.length - 1], count == null ? 10 : count, specifier);
};
scale.nice = function (count) {
if (count == null) count = 10;
var d = domain(),
i0 = 0,
i1 = d.length - 1,
start = d[i0],
stop = d[i1],
step;
if (stop < start) {
step = start, start = stop, stop = step;
step = i0, i0 = i1, i1 = step;
}
step = tickIncrement(start, stop, count);
if (step > 0) {
start = Math.floor(start / step) * step;
stop = Math.ceil(stop / step) * step;
step = tickIncrement(start, stop, count);
} else if (step < 0) {
start = Math.ceil(start * step) / step;
stop = Math.floor(stop * step) / step;
step = tickIncrement(start, stop, count);
}
if (step > 0) {
d[i0] = Math.floor(start / step) * step;
d[i1] = Math.ceil(stop / step) * step;
domain(d);
} else if (step < 0) {
d[i0] = Math.ceil(start * step) / step;
d[i1] = Math.floor(stop * step) / step;
domain(d);
}
return scale;
};
return scale;
}
function linear$1() {
var scale = continuous(identity$2, identity$2);
scale.copy = function () {
return copy(scale, linear$1());
};
initRange.apply(scale, arguments);
return linearish(scale);
}
function identity$4(domain) {
var unknown;
function scale(x) {
return isNaN(x = +x) ? unknown : x;
}
scale.invert = scale;
scale.domain = scale.range = function (_) {
return arguments.length ? (domain = map$1.call(_, number$1), scale) : domain.slice();
};
scale.unknown = function (_) {
return arguments.length ? (unknown = _, scale) : unknown;
};
scale.copy = function () {
return identity$4(domain).unknown(unknown);
};
domain = arguments.length ? map$1.call(domain, number$1) : [0, 1];
return linearish(scale);
}
function nice (domain, interval) {
domain = domain.slice();
var i0 = 0,
i1 = domain.length - 1,
x0 = domain[i0],
x1 = domain[i1],
t;
if (x1 < x0) {
t = i0, i0 = i1, i1 = t;
t = x0, x0 = x1, x1 = t;
}
domain[i0] = interval.floor(x0);
domain[i1] = interval.ceil(x1);
return domain;
}
function transformLog(x) {
return Math.log(x);
}
function transformExp(x) {
return Math.exp(x);
}
function transformLogn(x) {
return -Math.log(-x);
}
function transformExpn(x) {
return -Math.exp(-x);
}
function pow10(x) {
return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x;
}
function powp(base) {
return base === 10 ? pow10 : base === Math.E ? Math.exp : function (x) {
return Math.pow(base, x);
};
}
function logp(base) {
return base === Math.E ? Math.log : base === 10 && Math.log10 || base === 2 && Math.log2 || (base = Math.log(base), function (x) {
return Math.log(x) / base;
});
}
function reflect(f) {
return function (x) {
return -f(-x);
};
}
function loggish(transform) {
var scale = transform(transformLog, transformExp),
domain = scale.domain,
base = 10,
logs,
pows;
function rescale() {
logs = logp(base), pows = powp(base);
if (domain()[0] < 0) {
logs = reflect(logs), pows = reflect(pows);
transform(transformLogn, transformExpn);
} else {
transform(transformLog, transformExp);
}
return scale;
}
scale.base = function (_) {
return arguments.length ? (base = +_, rescale()) : base;
};
scale.domain = function (_) {
return arguments.length ? (domain(_), rescale()) : domain();
};
scale.ticks = function (count) {
var d = domain(),
u = d[0],
v = d[d.length - 1],
r;
if (r = v < u) i = u, u = v, v = i;
var i = logs(u),
j = logs(v),
p,
k,
t,
n = count == null ? 10 : +count,
z = [];
if (!(base % 1) && j - i < n) {
i = Math.round(i) - 1, j = Math.round(j) + 1;
if (u > 0) for (; i < j; ++i) {
for (k = 1, p = pows(i); k < base; ++k) {
t = p * k;
if (t < u) continue;
if (t > v) break;
z.push(t);
}
} else for (; i < j; ++i) {
for (k = base - 1, p = pows(i); k >= 1; --k) {
t = p * k;
if (t < u) continue;
if (t > v) break;
z.push(t);
}
}
} else {
z = d3Ticks(i, j, Math.min(j - i, n)).map(pows);
}
return r ? z.reverse() : z;
};
scale.tickFormat = function (count, specifier) {
if (specifier == null) specifier = base === 10 ? ".0e" : ",";
if (typeof specifier !== "function") specifier = format(specifier);
if (count === Infinity) return specifier;
if (count == null) count = 10;
var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate?
return function (d) {
var i = d / pows(Math.round(logs(d)));
if (i * base < base - 0.5) i *= base;
return i <= k ? specifier(d) : "";
};
};
scale.nice = function () {
return domain(nice(domain(), {
floor: function floor(x) {
return pows(Math.floor(logs(x)));
},
ceil: function ceil(x) {
return pows(Math.ceil(logs(x)));
}
}));
};
return scale;
}
function log() {
var scale = loggish(transformer()).domain([1, 10]);
scale.copy = function () {
return copy(scale, log()).base(scale.base());
};
initRange.apply(scale, arguments);
return scale;
}
function transformSymlog(c) {
return function (x) {
return Math.sign(x) * Math.log1p(Math.abs(x / c));
};
}
function transformSymexp(c) {
return function (x) {
return Math.sign(x) * Math.expm1(Math.abs(x)) * c;
};
}
function symlogish(transform) {
var c = 1,
scale = transform(transformSymlog(c), transformSymexp(c));
scale.constant = function (_) {
return arguments.length ? transform(transformSymlog(c = +_), transformSymexp(c)) : c;
};
return linearish(scale);
}
function symlog() {
var scale = symlogish(transformer());
scale.copy = function () {
return copy(scale, symlog()).constant(scale.constant());
};
return initRange.apply(scale, arguments);
}
function transformPow(exponent) {
return function (x) {
return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent);
};
}
function transformSqrt(x) {
return x < 0 ? -Math.sqrt(-x) : Math.sqrt(x);
}
function transformSquare(x) {
return x < 0 ? -x * x : x * x;
}
function powish(transform) {
var scale = transform(identity$2, identity$2),
exponent = 1;
function rescale() {
return exponent === 1 ? transform(identity$2, identity$2) : exponent === 0.5 ? transform(transformSqrt, transformSquare) : transform(transformPow(exponent), transformPow(1 / exponent));
}
scale.exponent = function (_) {
return arguments.length ? (exponent = +_, rescale()) : exponent;
};
return linearish(scale);
}
function pow() {
var scale = powish(transformer());
scale.copy = function () {
return copy(scale, pow()).exponent(scale.exponent());
};
initRange.apply(scale, arguments);
return scale;
}
function sqrt$1() {
return pow.apply(null, arguments).exponent(0.5);
}
function quantile$1() {
var domain = [],
range = [],
thresholds = [],
unknown;
function rescale() {
var i = 0,
n = Math.max(1, range.length);
thresholds = new Array(n - 1);
while (++i < n) {
thresholds[i - 1] = quantile(domain, i / n);
}
return scale;
}
function scale(x) {
return isNaN(x = +x) ? unknown : range[bisectRight(thresholds, x)];
}
scale.invertExtent = function (y) {
var i = range.indexOf(y);
return i < 0 ? [NaN, NaN] : [i > 0 ? thresholds[i - 1] : domain[0], i < thresholds.length ? thresholds[i] : domain[domain.length - 1]];
};
scale.domain = function (_) {
if (!arguments.length) return domain.slice();
domain = [];
for (var i = 0, n = _.length, d; i < n; ++i) {
if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d);
}
domain.sort(ascending);
return rescale();
};
scale.range = function (_) {
return arguments.length ? (range = slice$1.call(_), rescale()) : range.slice();
};
scale.unknown = function (_) {
return arguments.length ? (unknown = _, scale) : unknown;
};
scale.quantiles = function () {
return thresholds.slice();
};
scale.copy = function () {
return quantile$1().domain(domain).range(range).unknown(unknown);
};
return initRange.apply(scale, arguments);
}
function quantize() {
var x0 = 0,
x1 = 1,
n = 1,
domain = [0.5],
range = [0, 1],
unknown;
function scale(x) {
return x <= x ? range[bisectRight(domain, x, 0, n)] : unknown;
}
function rescale() {
var i = -1;
domain = new Array(n);
while (++i < n) {
domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1);
}
return scale;
}
scale.domain = function (_) {
return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1];
};
scale.range = function (_) {
return arguments.length ? (n = (range = slice$1.call(_)).length - 1, rescale()) : range.slice();
};
scale.invertExtent = function (y) {
var i = range.indexOf(y);
return i < 0 ? [NaN, NaN] : i < 1 ? [x0, domain[0]] : i >= n ? [domain[n - 1], x1] : [domain[i - 1], domain[i]];
};
scale.unknown = function (_) {
return arguments.length ? (unknown = _, scale) : scale;
};
scale.thresholds = function () {
return domain.slice();
};
scale.copy = function () {
return quantize().domain([x0, x1]).range(range).unknown(unknown);
};
return initRange.apply(linearish(scale), arguments);
}
function threshold() {
var domain = [0.5],
range = [0, 1],
unknown,
n = 1;
function scale(x) {
return x <= x ? range[bisectRight(domain, x, 0, n)] : unknown;
}
scale.domain = function (_) {
return arguments.length ? (domain = slice$1.call(_), n = Math.min(domain.length, range.length - 1), scale) : domain.slice();
};
scale.range = function (_) {
return arguments.length ? (range = slice$1.call(_), n = Math.min(domain.length, range.length - 1), scale) : range.slice();
};
scale.invertExtent = function (y) {
var i = range.indexOf(y);
return [domain[i - 1], domain[i]];
};
scale.unknown = function (_) {
return arguments.length ? (unknown = _, scale) : unknown;
};
scale.copy = function () {
return threshold().domain(domain).range(range).unknown(unknown);
};
return initRange.apply(scale, arguments);
}
var t0$1 = new Date(),
t1$1 = new Date();
function newInterval(floori, offseti, count, field) {
function interval(date) {
return floori(date = new Date(+date)), date;
}
interval.floor = interval;
interval.ceil = function (date) {
return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date;
};
interval.round = function (date) {
var d0 = interval(date),
d1 = interval.ceil(date);
return date - d0 < d1 - date ? d0 : d1;
};
interval.offset = function (date, step) {
return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
};
interval.range = function (start, stop, step) {
var range = [],
previous;
start = interval.ceil(start);
step = step == null ? 1 : Math.floor(step);
if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
do {
range.push(previous = new Date(+start)), offseti(start, step), floori(start);
} while (previous < start && start < stop);
return range;
};
interval.filter = function (test) {
return newInterval(function (date) {
if (date >= date) while (floori(date), !test(date)) {
date.setTime(date - 1);
}
}, function (date, step) {
if (date >= date) {
if (step < 0) while (++step <= 0) {
while (offseti(date, -1), !test(date)) {} // eslint-disable-line no-empty
} else while (--step >= 0) {
while (offseti(date, +1), !test(date)) {} // eslint-disable-line no-empty
}
}
});
};
if (count) {
interval.count = function (start, end) {
t0$1.setTime(+start), t1$1.setTime(+end);
floori(t0$1), floori(t1$1);
return Math.floor(count(t0$1, t1$1));
};
interval.every = function (step) {
step = Math.floor(step);
return !isFinite(step) || !(step > 0) ? null : !(step > 1) ? interval : interval.filter(field ? function (d) {
return field(d) % step === 0;
} : function (d) {
return interval.count(0, d) % step === 0;
});
};
}
return interval;
}
var millisecond = newInterval(function () {// noop
}, function (date, step) {
date.setTime(+date + step);
}, function (start, end) {
return end - start;
}); // An optimized implementation for this simple case.
millisecond.every = function (k) {
k = Math.floor(k);
if (!isFinite(k) || !(k > 0)) return null;
if (!(k > 1)) return millisecond;
return newInterval(function (date) {
date.setTime(Math.floor(date / k) * k);
}, function (date, step) {
date.setTime(+date + step * k);
}, function (start, end) {
return (end - start) / k;
});
};
var durationSecond = 1e3;
var durationMinute = 6e4;
var durationHour = 36e5;
var durationDay = 864e5;
var durationWeek = 6048e5;
var second = newInterval(function (date) {
date.setTime(date - date.getMilliseconds());
}, function (date, step) {
date.setTime(+date + step * durationSecond);
}, function (start, end) {
return (end - start) / durationSecond;
}, function (date) {
return date.getUTCSeconds();
});
var minute = newInterval(function (date) {
date.setTime(date - date.getMilliseconds() - date.getSeconds() * durationSecond);
}, function (date, step) {
date.setTime(+date + step * durationMinute);
}, function (start, end) {
return (end - start) / durationMinute;
}, function (date) {
return date.getMinutes();
});
var hour = newInterval(function (date) {
date.setTime(date - date.getMilliseconds() - date.getSeconds() * durationSecond - date.getMinutes() * durationMinute);
}, function (date, step) {
date.setTime(+date + step * durationHour);
}, function (start, end) {
return (end - start) / durationHour;
}, function (date) {
return date.getHours();
});
var day = newInterval(function (date) {
date.setHours(0, 0, 0, 0);
}, function (date, step) {
date.setDate(date.getDate() + step);
}, function (start, end) {
return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationDay;
}, function (date) {
return date.getDate() - 1;
});
function weekday(i) {
return newInterval(function (date) {
date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);
date.setHours(0, 0, 0, 0);
}, function (date, step) {
date.setDate(date.getDate() + step * 7);
}, function (start, end) {
return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationWeek;
});
}
var sunday = weekday(0);
var monday = weekday(1);
var tuesday = weekday(2);
var wednesday = weekday(3);
var thursday = weekday(4);
var friday = weekday(5);
var saturday = weekday(6);
var month = newInterval(function (date) {
date.setDate(1);
date.setHours(0, 0, 0, 0);
}, function (date, step) {
date.setMonth(date.getMonth() + step);
}, function (start, end) {
return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12;
}, function (date) {
return date.getMonth();
});
var year = newInterval(function (date) {
date.setMonth(0, 1);
date.setHours(0, 0, 0, 0);
}, function (date, step) {
date.setFullYear(date.getFullYear() + step);
}, function (start, end) {
return end.getFullYear() - start.getFullYear();
}, function (date) {
return date.getFullYear();
}); // An optimized implementation for this simple case.
year.every = function (k) {
return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function (date) {
date.setFullYear(Math.floor(date.getFullYear() / k) * k);
date.setMonth(0, 1);
date.setHours(0, 0, 0, 0);
}, function (date, step) {
date.setFullYear(date.getFullYear() + step * k);
});
};
var utcMinute = newInterval(function (date) {
date.setUTCSeconds(0, 0);
}, function (date, step) {
date.setTime(+date + step * durationMinute);
}, function (start, end) {
return (end - start) / durationMinute;
}, function (date) {
return date.getUTCMinutes();
});
var utcHour = newInterval(function (date) {
date.setUTCMinutes(0, 0, 0);
}, function (date, step) {
date.setTime(+date + step * durationHour);
}, function (start, end) {
return (end - start) / durationHour;
}, function (date) {
return date.getUTCHours();
});
var utcDay = newInterval(function (date) {
date.setUTCHours(0, 0, 0, 0);
}, function (date, step) {
date.setUTCDate(date.getUTCDate() + step);
}, function (start, end) {
return (end - start) / durationDay;
}, function (date) {
return date.getUTCDate() - 1;
});
function utcWeekday(i) {
return newInterval(function (date) {
date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);
date.setUTCHours(0, 0, 0, 0);
}, function (date, step) {
date.setUTCDate(date.getUTCDate() + step * 7);
}, function (start, end) {
return (end - start) / durationWeek;
});
}
var utcSunday = utcWeekday(0);
var utcMonday = utcWeekday(1);
var utcTuesday = utcWeekday(2);
var utcWednesday = utcWeekday(3);
var utcThursday = utcWeekday(4);
var utcFriday = utcWeekday(5);
var utcSaturday = utcWeekday(6);
var utcMonth = newInterval(function (date) {
date.setUTCDate(1);
date.setUTCHours(0, 0, 0, 0);
}, function (date, step) {
date.setUTCMonth(date.getUTCMonth() + step);
}, function (start, end) {
return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12;
}, function (date) {
return date.getUTCMonth();
});
var utcYear = newInterval(function (date) {
date.setUTCMonth(0, 1);
date.setUTCHours(0, 0, 0, 0);
}, function (date, step) {
date.setUTCFullYear(date.getUTCFullYear() + step);
}, function (start, end) {
return end.getUTCFullYear() - start.getUTCFullYear();
}, function (date) {
return date.getUTCFullYear();
}); // An optimized implementation for this simple case.
utcYear.every = function (k) {
return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function (date) {
date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k);
date.setUTCMonth(0, 1);
date.setUTCHours(0, 0, 0, 0);
}, function (date, step) {
date.setUTCFullYear(date.getUTCFullYear() + step * k);
});
};
function localDate(d) {
if (0 <= d.y && d.y < 100) {
var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);
date.setFullYear(d.y);
return date;
}
return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);
}
function utcDate(d) {
if (0 <= d.y && d.y < 100) {
var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));
date.setUTCFullYear(d.y);
return date;
}
return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));
}
function newYear(y) {
return {
y: y,
m: 0,
d: 1,
H: 0,
M: 0,
S: 0,
L: 0
};
}
function formatLocale$1(locale) {
var locale_dateTime = locale.dateTime,
locale_date = locale.date,
locale_time = locale.time,
locale_periods = locale.periods,
locale_weekdays = locale.days,
locale_shortWeekdays = locale.shortDays,
locale_months = locale.months,
locale_shortMonths = locale.shortMonths;
var periodRe = formatRe(locale_periods),
periodLookup = formatLookup(locale_periods),
weekdayRe = formatRe(locale_weekdays),
weekdayLookup = formatLookup(locale_weekdays),
shortWeekdayRe = formatRe(locale_shortWeekdays),
shortWeekdayLookup = formatLookup(locale_shortWeekdays),
monthRe = formatRe(locale_months),
monthLookup = formatLookup(locale_months),
shortMonthRe = formatRe(locale_shortMonths),
shortMonthLookup = formatLookup(locale_shortMonths);
var formats = {
"a": formatShortWeekday,
"A": formatWeekday,
"b": formatShortMonth,
"B": formatMonth,
"c": null,
"d": formatDayOfMonth,
"e": formatDayOfMonth,
"f": formatMicroseconds,
"H": formatHour24,
"I": formatHour12,
"j": formatDayOfYear,
"L": formatMilliseconds,
"m": formatMonthNumber,
"M": formatMinutes,
"p": formatPeriod,
"Q": formatUnixTimestamp,
"s": formatUnixTimestampSeconds,
"S": formatSeconds,
"u": formatWeekdayNumberMonday,
"U": formatWeekNumberSunday,
"V": formatWeekNumberISO,
"w": formatWeekdayNumberSunday,
"W": formatWeekNumberMonday,
"x": null,
"X": null,
"y": formatYear,
"Y": formatFullYear,
"Z": formatZone,
"%": formatLiteralPercent
};
var utcFormats = {
"a": formatUTCShortWeekday,
"A": formatUTCWeekday,
"b": formatUTCShortMonth,
"B": formatUTCMonth,
"c": null,
"d": formatUTCDayOfMonth,
"e": formatUTCDayOfMonth,
"f": formatUTCMicroseconds,
"H": formatUTCHour24,
"I": formatUTCHour12,
"j": formatUTCDayOfYear,
"L": formatUTCMilliseconds,
"m": formatUTCMonthNumber,
"M": formatUTCMinutes,
"p": formatUTCPeriod,
"Q": formatUnixTimestamp,
"s": formatUnixTimestampSeconds,
"S": formatUTCSeconds,
"u": formatUTCWeekdayNumberMonday,
"U": formatUTCWeekNumberSunday,
"V": formatUTCWeekNumberISO,
"w": formatUTCWeekdayNumberSunday,
"W": formatUTCWeekNumberMonday,
"x": null,
"X": null,
"y": formatUTCYear,
"Y": formatUTCFullYear,
"Z": formatUTCZone,
"%": formatLiteralPercent
};
var parses = {
"a": parseShortWeekday,
"A": parseWeekday,
"b": parseShortMonth,
"B": parseMonth,
"c": parseLocaleDateTime,
"d": parseDayOfMonth,
"e": parseDayOfMonth,
"f": parseMicroseconds,
"H": parseHour24,
"I": parseHour24,
"j": parseDayOfYear,
"L": parseMilliseconds,
"m": parseMonthNumber,
"M": parseMinutes,
"p": parsePeriod,
"Q": parseUnixTimestamp,
"s": parseUnixTimestampSeconds,
"S": parseSeconds,
"u": parseWeekdayNumberMonday,
"U": parseWeekNumberSunday,
"V": parseWeekNumberISO,
"w": parseWeekdayNumberSunday,
"W": parseWeekNumberMonday,
"x": parseLocaleDate,
"X": parseLocaleTime,
"y": parseYear,
"Y": parseFullYear,
"Z": parseZone,
"%": parseLiteralPercent
}; // These recursive directive definitions must be deferred.
formats.x = newFormat(locale_date, formats);
formats.X = newFormat(locale_time, formats);
formats.c = newFormat(locale_dateTime, formats);
utcFormats.x = newFormat(locale_date, utcFormats);
utcFormats.X = newFormat(locale_time, utcFormats);
utcFormats.c = newFormat(locale_dateTime, utcFormats);
function newFormat(specifier, formats) {
return function (date) {
var string = [],
i = -1,
j = 0,
n = specifier.length,
c,
pad,
format;
if (!(date instanceof Date)) date = new Date(+date);
while (++i < n) {
if (specifier.charCodeAt(i) === 37) {
string.push(specifier.slice(j, i));
if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i);else pad = c === "e" ? " " : "0";
if (format = formats[c]) c = format(date, pad);
string.push(c);
j = i + 1;
}
}
string.push(specifier.slice(j, i));
return string.join("");
};
}
function newParse(specifier, newDate) {
return function (string) {
var d = newYear(1900),
i = parseSpecifier(d, specifier, string += "", 0),
week,
day$1;
if (i != string.length) return null; // If a UNIX timestamp is specified, return it.
if ("Q" in d) return new Date(d.Q); // The am-pm flag is 0 for AM, and 1 for PM.
if ("p" in d) d.H = d.H % 12 + d.p * 12; // Convert day-of-week and week-of-year to day-of-year.
if ("V" in d) {
if (d.V < 1 || d.V > 53) return null;
if (!("w" in d)) d.w = 1;
if ("Z" in d) {
week = utcDate(newYear(d.y)), day$1 = week.getUTCDay();
week = day$1 > 4 || day$1 === 0 ? utcMonday.ceil(week) : utcMonday(week);
week = utcDay.offset(week, (d.V - 1) * 7);
d.y = week.getUTCFullYear();
d.m = week.getUTCMonth();
d.d = week.getUTCDate() + (d.w + 6) % 7;
} else {
week = newDate(newYear(d.y)), day$1 = week.getDay();
week = day$1 > 4 || day$1 === 0 ? monday.ceil(week) : monday(week);
week = day.offset(week, (d.V - 1) * 7);
d.y = week.getFullYear();
d.m = week.getMonth();
d.d = week.getDate() + (d.w + 6) % 7;
}
} else if ("W" in d || "U" in d) {
if (!("w" in d)) d.w = "u" in d ? d.u % 7 : "W" in d ? 1 : 0;
day$1 = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay();
d.m = 0;
d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day$1 + 5) % 7 : d.w + d.U * 7 - (day$1 + 6) % 7;
} // If a time zone is specified, all fields are interpreted as UTC and then
// offset according to the specified time zone.
if ("Z" in d) {
d.H += d.Z / 100 | 0;
d.M += d.Z % 100;
return utcDate(d);
} // Otherwise, all fields are in local time.
return newDate(d);
};
}
function parseSpecifier(d, specifier, string, j) {
var i = 0,
n = specifier.length,
m = string.length,
c,
parse;
while (i < n) {
if (j >= m) return -1;
c = specifier.charCodeAt(i++);
if (c === 37) {
c = specifier.charAt(i++);
parse = parses[c in pads ? specifier.charAt(i++) : c];
if (!parse || (j = parse(d, string, j)) < 0) return -1;
} else if (c != string.charCodeAt(j++)) {
return -1;
}
}
return j;
}
function parsePeriod(d, string, i) {
var n = periodRe.exec(string.slice(i));
return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1;
}
function parseShortWeekday(d, string, i) {
var n = shortWeekdayRe.exec(string.slice(i));
return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
}
function parseWeekday(d, string, i) {
var n = weekdayRe.exec(string.slice(i));
return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
}
function parseShortMonth(d, string, i) {
var n = shortMonthRe.exec(string.slice(i));
return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
}
function parseMonth(d, string, i) {
var n = monthRe.exec(string.slice(i));
return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
}
function parseLocaleDateTime(d, string, i) {
return parseSpecifier(d, locale_dateTime, string, i);
}
function parseLocaleDate(d, string, i) {
return parseSpecifier(d, locale_date, string, i);
}
function parseLocaleTime(d, string, i) {
return parseSpecifier(d, locale_time, string, i);
}
function formatShortWeekday(d) {
return locale_shortWeekdays[d.getDay()];
}
function formatWeekday(d) {
return locale_weekdays[d.getDay()];
}
function formatShortMonth(d) {
return locale_shortMonths[d.getMonth()];
}
function formatMonth(d) {
return locale_months[d.getMonth()];
}
function formatPeriod(d) {
return locale_periods[+(d.getHours() >= 12)];
}
function formatUTCShortWeekday(d) {
return locale_shortWeekdays[d.getUTCDay()];
}
function formatUTCWeekday(d) {
return locale_weekdays[d.getUTCDay()];
}
function formatUTCShortMonth(d) {
return locale_shortMonths[d.getUTCMonth()];
}
function formatUTCMonth(d) {
return locale_months[d.getUTCMonth()];
}
function formatUTCPeriod(d) {
return locale_periods[+(d.getUTCHours() >= 12)];
}
return {
format: function format(specifier) {
var f = newFormat(specifier += "", formats);
f.toString = function () {
return specifier;
};
return f;
},
parse: function parse(specifier) {
var p = newParse(specifier += "", localDate);
p.toString = function () {
return specifier;
};
return p;
},
utcFormat: function utcFormat(specifier) {
var f = newFormat(specifier += "", utcFormats);
f.toString = function () {
return specifier;
};
return f;
},
utcParse: function utcParse(specifier) {
var p = newParse(specifier, utcDate);
p.toString = function () {
return specifier;
};
return p;
}
};
}
var pads = {
"-": "",
"_": " ",
"0": "0"
},
numberRe = /^\s*\d+/,
// note: ignores next directive
percentRe = /^%/,
requoteRe = /[\\^$*+?|[\]().{}]/g;
function pad(value, fill, width) {
var sign = value < 0 ? "-" : "",
string = (sign ? -value : value) + "",
length = string.length;
return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
}
function requote(s) {
return s.replace(requoteRe, "\\$&");
}
function formatRe(names) {
return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i");
}
function formatLookup(names) {
var map = {},
i = -1,
n = names.length;
while (++i < n) {
map[names[i].toLowerCase()] = i;
}
return map;
}
function parseWeekdayNumberSunday(d, string, i) {
var n = numberRe.exec(string.slice(i, i + 1));
return n ? (d.w = +n[0], i + n[0].length) : -1;
}
function parseWeekdayNumberMonday(d, string, i) {
var n = numberRe.exec(string.slice(i, i + 1));
return n ? (d.u = +n[0], i + n[0].length) : -1;
}
function parseWeekNumberSunday(d, string, i) {
var n = numberRe.exec(string.slice(i, i + 2));
return n ? (d.U = +n[0], i + n[0].length) : -1;
}
function parseWeekNumberISO(d, string, i) {
var n = numberRe.exec(string.slice(i, i + 2));
return n ? (d.V = +n[0], i + n[0].length) : -1;
}
function parseWeekNumberMonday(d, string, i) {
var n = numberRe.exec(string.slice(i, i + 2));
return n ? (d.W = +n[0], i + n[0].length) : -1;
}
function parseFullYear(d, string, i) {
var n = numberRe.exec(string.slice(i, i + 4));
return n ? (d.y = +n[0], i + n[0].length) : -1;
}
function parseYear(d, string, i) {
var n = numberRe.exec(string.slice(i, i + 2));
return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1;
}
function parseZone(d, string, i) {
var n = /^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(string.slice(i, i + 6));
return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1;
}
function parseMonthNumber(d, string, i) {
var n = numberRe.exec(string.slice(i, i + 2));
return n ? (d.m = n[0] - 1, i + n[0].length) : -1;
}
function parseDayOfMonth(d, string, i) {
var n = numberRe.exec(string.slice(i, i + 2));
return n ? (d.d = +n[0], i + n[0].length) : -1;
}
function parseDayOfYear(d, string, i) {
var n = numberRe.exec(string.slice(i, i + 3));
return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;
}
function parseHour24(d, string, i) {
var n = numberRe.exec(string.slice(i, i + 2));
return n ? (d.H = +n[0], i + n[0].length) : -1;
}
function parseMinutes(d, string, i) {
var n = numberRe.exec(string.slice(i, i + 2));
return n ? (d.M = +n[0], i + n[0].length) : -1;
}
function parseSeconds(d, string, i) {
var n = numberRe.exec(string.slice(i, i + 2));
return n ? (d.S = +n[0], i + n[0].length) : -1;
}
function parseMilliseconds(d, string, i) {
var n = numberRe.exec(string.slice(i, i + 3));
return n ? (d.L = +n[0], i + n[0].length) : -1;
}
function parseMicroseconds(d, string, i) {
var n = numberRe.exec(string.slice(i, i + 6));
return n ? (d.L = Math.floor(n[0] / 1000), i + n[0].length) : -1;
}
function parseLiteralPercent(d, string, i) {
var n = percentRe.exec(string.slice(i, i + 1));
return n ? i + n[0].length : -1;
}
function parseUnixTimestamp(d, string, i) {
var n = numberRe.exec(string.slice(i));
return n ? (d.Q = +n[0], i + n[0].length) : -1;
}
function parseUnixTimestampSeconds(d, string, i) {
var n = numberRe.exec(string.slice(i));
return n ? (d.Q = +n[0] * 1000, i + n[0].length) : -1;
}
function formatDayOfMonth(d, p) {
return pad(d.getDate(), p, 2);
}
function formatHour24(d, p) {
return pad(d.getHours(), p, 2);
}
function formatHour12(d, p) {
return pad(d.getHours() % 12 || 12, p, 2);
}
function formatDayOfYear(d, p) {
return pad(1 + day.count(year(d), d), p, 3);
}
function formatMilliseconds(d, p) {
return pad(d.getMilliseconds(), p, 3);
}
function formatMicroseconds(d, p) {
return formatMilliseconds(d, p) + "000";
}
function formatMonthNumber(d, p) {
return pad(d.getMonth() + 1, p, 2);
}
function formatMinutes(d, p) {
return pad(d.getMinutes(), p, 2);
}
function formatSeconds(d, p) {
return pad(d.getSeconds(), p, 2);
}
function formatWeekdayNumberMonday(d) {
var day = d.getDay();
return day === 0 ? 7 : day;
}
function formatWeekNumberSunday(d, p) {
return pad(sunday.count(year(d), d), p, 2);
}
function formatWeekNumberISO(d, p) {
var day = d.getDay();
d = day >= 4 || day === 0 ? thursday(d) : thursday.ceil(d);
return pad(thursday.count(year(d), d) + (year(d).getDay() === 4), p, 2);
}
function formatWeekdayNumberSunday(d) {
return d.getDay();
}
function formatWeekNumberMonday(d, p) {
return pad(monday.count(year(d), d), p, 2);
}
function formatYear(d, p) {
return pad(d.getFullYear() % 100, p, 2);
}
function formatFullYear(d, p) {
return pad(d.getFullYear() % 10000, p, 4);
}
function formatZone(d) {
var z = d.getTimezoneOffset();
return (z > 0 ? "-" : (z *= -1, "+")) + pad(z / 60 | 0, "0", 2) + pad(z % 60, "0", 2);
}
function formatUTCDayOfMonth(d, p) {
return pad(d.getUTCDate(), p, 2);
}
function formatUTCHour24(d, p) {
return pad(d.getUTCHours(), p, 2);
}
function formatUTCHour12(d, p) {
return pad(d.getUTCHours() % 12 || 12, p, 2);
}
function formatUTCDayOfYear(d, p) {
return pad(1 + utcDay.count(utcYear(d), d), p, 3);
}
function formatUTCMilliseconds(d, p) {
return pad(d.getUTCMilliseconds(), p, 3);
}
function formatUTCMicroseconds(d, p) {
return formatUTCMilliseconds(d, p) + "000";
}
function formatUTCMonthNumber(d, p) {
return pad(d.getUTCMonth() + 1, p, 2);
}
function formatUTCMinutes(d, p) {
return pad(d.getUTCMinutes(), p, 2);
}
function formatUTCSeconds(d, p) {
return pad(d.getUTCSeconds(), p, 2);
}
function formatUTCWeekdayNumberMonday(d) {
var dow = d.getUTCDay();
return dow === 0 ? 7 : dow;
}
function formatUTCWeekNumberSunday(d, p) {
return pad(utcSunday.count(utcYear(d), d), p, 2);
}
function formatUTCWeekNumberISO(d, p) {
var day = d.getUTCDay();
d = day >= 4 || day === 0 ? utcThursday(d) : utcThursday.ceil(d);
return pad(utcThursday.count(utcYear(d), d) + (utcYear(d).getUTCDay() === 4), p, 2);
}
function formatUTCWeekdayNumberSunday(d) {
return d.getUTCDay();
}
function formatUTCWeekNumberMonday(d, p) {
return pad(utcMonday.count(utcYear(d), d), p, 2);
}
function formatUTCYear(d, p) {
return pad(d.getUTCFullYear() % 100, p, 2);
}
function formatUTCFullYear(d, p) {
return pad(d.getUTCFullYear() % 10000, p, 4);
}
function formatUTCZone() {
return "+0000";
}
function formatLiteralPercent() {
return "%";
}
function formatUnixTimestamp(d) {
return +d;
}
function formatUnixTimestampSeconds(d) {
return Math.floor(+d / 1000);
}
var locale$1;
var timeFormat;
var timeParse;
var utcFormat;
var utcParse;
defaultLocale$1({
dateTime: "%x, %X",
date: "%-m/%-d/%Y",
time: "%-I:%M:%S %p",
periods: ["AM", "PM"],
days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
});
function defaultLocale$1(definition) {
locale$1 = formatLocale$1(definition);
timeFormat = locale$1.format;
timeParse = locale$1.parse;
utcFormat = locale$1.utcFormat;
utcParse = locale$1.utcParse;
return locale$1;
}
var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ";
function formatIsoNative(date) {
return date.toISOString();
}
var formatIso = Date.prototype.toISOString ? formatIsoNative : utcFormat(isoSpecifier);
function parseIsoNative(string) {
var date = new Date(string);
return isNaN(date) ? null : date;
}
var parseIso = +new Date("2000-01-01T00:00:00.000Z") ? parseIsoNative : utcParse(isoSpecifier);
var durationSecond$1 = 1000,
durationMinute$1 = durationSecond$1 * 60,
durationHour$1 = durationMinute$1 * 60,
durationDay$1 = durationHour$1 * 24,
durationWeek$1 = durationDay$1 * 7,
durationMonth = durationDay$1 * 30,
durationYear = durationDay$1 * 365;
function date$1(t) {
return new Date(t);
}
function number$2(t) {
return t instanceof Date ? +t : +new Date(+t);
}
function calendar(year, month, week, day, hour, minute, second, millisecond, format) {
var scale = continuous(identity$2, identity$2),
invert = scale.invert,
domain = scale.domain;
var formatMillisecond = format(".%L"),
formatSecond = format(":%S"),
formatMinute = format("%I:%M"),
formatHour = format("%I %p"),
formatDay = format("%a %d"),
formatWeek = format("%b %d"),
formatMonth = format("%B"),
formatYear = format("%Y");
var tickIntervals = [[second, 1, durationSecond$1], [second, 5, 5 * durationSecond$1], [second, 15, 15 * durationSecond$1], [second, 30, 30 * durationSecond$1], [minute, 1, durationMinute$1], [minute, 5, 5 * durationMinute$1], [minute, 15, 15 * durationMinute$1], [minute, 30, 30 * durationMinute$1], [hour, 1, durationHour$1], [hour, 3, 3 * durationHour$1], [hour, 6, 6 * durationHour$1], [hour, 12, 12 * durationHour$1], [day, 1, durationDay$1], [day, 2, 2 * durationDay$1], [week, 1, durationWeek$1], [month, 1, durationMonth], [month, 3, 3 * durationMonth], [year, 1, durationYear]];
function tickFormat(date) {
return (second(date) < date ? formatMillisecond : minute(date) < date ? formatSecond : hour(date) < date ? formatMinute : day(date) < date ? formatHour : month(date) < date ? week(date) < date ? formatDay : formatWeek : year(date) < date ? formatMonth : formatYear)(date);
}
function tickInterval(interval, start, stop, step) {
if (interval == null) interval = 10; // If a desired tick count is specified, pick a reasonable tick interval
// based on the extent of the domain and a rough estimate of tick size.
// Otherwise, assume interval is already a time interval and use it.
if (typeof interval === "number") {
var target = Math.abs(stop - start) / interval,
i = bisector(function (i) {
return i[2];
}).right(tickIntervals, target);
if (i === tickIntervals.length) {
step = tickStep(start / durationYear, stop / durationYear, interval);
interval = year;
} else if (i) {
i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i];
step = i[1];
interval = i[0];
} else {
step = Math.max(tickStep(start, stop, interval), 1);
interval = millisecond;
}
}
return step == null ? interval : interval.every(step);
}
scale.invert = function (y) {
return new Date(invert(y));
};
scale.domain = function (_) {
return arguments.length ? domain(map$1.call(_, number$2)) : domain().map(date$1);
};
scale.ticks = function (interval, step) {
var d = domain(),
t0 = d[0],
t1 = d[d.length - 1],
r = t1 < t0,
t;
if (r) t = t0, t0 = t1, t1 = t;
t = tickInterval(interval, t0, t1, step);
t = t ? t.range(t0, t1 + 1) : []; // inclusive stop
return r ? t.reverse() : t;
};
scale.tickFormat = function (count, specifier) {
return specifier == null ? tickFormat : format(specifier);
};
scale.nice = function (interval, step) {
var d = domain();
return (interval = tickInterval(interval, d[0], d[d.length - 1], step)) ? domain(nice(d, interval)) : scale;
};
scale.copy = function () {
return copy(scale, calendar(year, month, week, day, hour, minute, second, millisecond, format));
};
return scale;
}
function scaleTime () {
return initRange.apply(calendar(year, month, sunday, day, hour, minute, second, millisecond, timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]), arguments);
}
function utcTime () {
return initRange.apply(calendar(utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, millisecond, utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]), arguments);
}
function transformer$1() {
var x0 = 0,
x1 = 1,
t0,
t1,
k10,
transform,
interpolator = identity$2,
clamp = false,
unknown;
function scale(x) {
return isNaN(x = +x) ? unknown : interpolator(k10 === 0 ? 0.5 : (x = (transform(x) - t0) * k10, clamp ? Math.max(0, Math.min(1, x)) : x));
}
scale.domain = function (_) {
return arguments.length ? (t0 = transform(x0 = +_[0]), t1 = transform(x1 = +_[1]), k10 = t0 === t1 ? 0 : 1 / (t1 - t0), scale) : [x0, x1];
};
scale.clamp = function (_) {
return arguments.length ? (clamp = !!_, scale) : clamp;
};
scale.interpolator = function (_) {
return arguments.length ? (interpolator = _, scale) : interpolator;
};
scale.unknown = function (_) {
return arguments.length ? (unknown = _, scale) : unknown;
};
return function (t) {
transform = t, t0 = t(x0), t1 = t(x1), k10 = t0 === t1 ? 0 : 1 / (t1 - t0);
return scale;
};
}
function copy$1(source, target) {
return target.domain(source.domain()).interpolator(source.interpolator()).clamp(source.clamp()).unknown(source.unknown());
}
function sequential() {
var scale = linearish(transformer$1()(identity$2));
scale.copy = function () {
return copy$1(scale, sequential());
};
return initInterpolator.apply(scale, arguments);
}
function sequentialLog() {
var scale = loggish(transformer$1()).domain([1, 10]);
scale.copy = function () {
return copy$1(scale, sequentialLog()).base(scale.base());
};
return initInterpolator.apply(scale, arguments);
}
function sequentialSymlog() {
var scale = symlogish(transformer$1());
scale.copy = function () {
return copy$1(scale, sequentialSymlog()).constant(scale.constant());
};
return initInterpolator.apply(scale, arguments);
}
function sequentialPow() {
var scale = powish(transformer$1());
scale.copy = function () {
return copy$1(scale, sequentialPow()).exponent(scale.exponent());
};
return initInterpolator.apply(scale, arguments);
}
function sequentialSqrt() {
return sequentialPow.apply(null, arguments).exponent(0.5);
}
function sequentialQuantile() {
var domain = [],
interpolator = identity$2;
function scale(x) {
if (!isNaN(x = +x)) return interpolator((bisectRight(domain, x) - 1) / (domain.length - 1));
}
scale.domain = function (_) {
if (!arguments.length) return domain.slice();
domain = [];
for (var i = 0, n = _.length, d; i < n; ++i) {
if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d);
}
domain.sort(ascending);
return scale;
};
scale.interpolator = function (_) {
return arguments.length ? (interpolator = _, scale) : interpolator;
};
scale.copy = function () {
return sequentialQuantile(interpolator).domain(domain);
};
return initInterpolator.apply(scale, arguments);
}
function transformer$2() {
var x0 = 0,
x1 = 0.5,
x2 = 1,
t0,
t1,
t2,
k10,
k21,
interpolator = identity$2,
transform,
clamp = false,
unknown;
function scale(x) {
return isNaN(x = +x) ? unknown : (x = 0.5 + ((x = +transform(x)) - t1) * (x < t1 ? k10 : k21), interpolator(clamp ? Math.max(0, Math.min(1, x)) : x));
}
scale.domain = function (_) {
return arguments.length ? (t0 = transform(x0 = +_[0]), t1 = transform(x1 = +_[1]), t2 = transform(x2 = +_[2]), k10 = t0 === t1 ? 0 : 0.5 / (t1 - t0), k21 = t1 === t2 ? 0 : 0.5 / (t2 - t1), scale) : [x0, x1, x2];
};
scale.clamp = function (_) {
return arguments.length ? (clamp = !!_, scale) : clamp;
};
scale.interpolator = function (_) {
return arguments.length ? (interpolator = _, scale) : interpolator;
};
scale.unknown = function (_) {
return arguments.length ? (unknown = _, scale) : unknown;
};
return function (t) {
transform = t, t0 = t(x0), t1 = t(x1), t2 = t(x2), k10 = t0 === t1 ? 0 : 0.5 / (t1 - t0), k21 = t1 === t2 ? 0 : 0.5 / (t2 - t1);
return scale;
};
}
function diverging$1() {
var scale = linearish(transformer$2()(identity$2));
scale.copy = function () {
return copy$1(scale, diverging$1());
};
return initInterpolator.apply(scale, arguments);
}
function divergingLog() {
var scale = loggish(transformer$2()).domain([0.1, 1, 10]);
scale.copy = function () {
return copy$1(scale, divergingLog()).base(scale.base());
};
return initInterpolator.apply(scale, arguments);
}
function divergingSymlog() {
var scale = symlogish(transformer$2());
scale.copy = function () {
return copy$1(scale, divergingSymlog()).constant(scale.constant());
};
return initInterpolator.apply(scale, arguments);
}
function divergingPow() {
var scale = powish(transformer$2());
scale.copy = function () {
return copy$1(scale, divergingPow()).exponent(scale.exponent());
};
return initInterpolator.apply(scale, arguments);
}
function divergingSqrt() {
return divergingPow.apply(null, arguments).exponent(0.5);
}
var scales = /*#__PURE__*/Object.freeze({
__proto__: null,
scaleBand: band,
scalePoint: point$1,
scaleIdentity: identity$4,
scaleLinear: linear$1,
scaleLog: log,
scaleSymlog: symlog,
scaleOrdinal: ordinal,
scaleImplicit: implicit,
scalePow: pow,
scaleSqrt: sqrt$1,
scaleQuantile: quantile$1,
scaleQuantize: quantize,
scaleThreshold: threshold,
scaleTime: scaleTime,
scaleUtc: utcTime,
scaleSequential: sequential,
scaleSequentialLog: sequentialLog,
scaleSequentialPow: sequentialPow,
scaleSequentialSqrt: sequentialSqrt,
scaleSequentialSymlog: sequentialSymlog,
scaleSequentialQuantile: sequentialQuantile,
scaleDiverging: diverging$1,
scaleDivergingLog: divergingLog,
scaleDivergingPow: divergingPow,
scaleDivergingSqrt: divergingSqrt,
scaleDivergingSymlog: divergingSymlog,
tickFormat: tickFormat
});
/**
@namespace {Object} colorDefaults
@desc A set of default color values used when assigning colors based on data.
*
* | Name | Default | Description |
* |---|---|---|
* | dark | #444444 | Used in the [contrast](#contrast) function when the color given is very light. |
* | light | #f7f7f7 | Used in the [contrast](#contrast) function when the color given is very dark. |
* | missing | #cccccc | Used in the [assign](#assign) function when the value passed is `null` or `undefined`. |
* | off | #b22200 | Used in the [assign](#assign) function when the value passed is `false`. |
* | on | #224f20 | Used in the [assign](#assign) function when the value passed is `true`. |
* | scale | #b22200, #eace3f, #282f6b, #b35c1e, #224f20, #5f487c, #759143, #419391, #993c88, #e89c89, #ffee8d, #afd5e8, #f7ba77, #a5c697, #c5b5e5, #d1d392, #bbefd0, #e099cf | An ordinal scale used in the [assign](#assign) function for non-valid color strings and numbers. |
*/
var defaults = {
dark: "#444444",
light: "#f7f7f7",
missing: "#cccccc",
off: "#b22200",
on: "#224f20",
scale: ordinal().range(["#b22200", "#282f6b", "#eace3f", "#b35c1e", "#224f20", "#5f487c", "#759143", "#419391", "#993c88", "#e89c89", "#ffee8d", "#afd5e8", "#f7ba77", "#a5c697", "#c5b5e5", "#d1d392", "#bbefd0", "#e099cf"])
};
/**
Returns a color based on a key, whether it is present in a user supplied object or in the default object.
@returns {String}
@private
*/
function getColor(k) {
var u = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
return k in u ? u[k] : k in defaults ? defaults[k] : defaults.missing;
}
/**
@function colorAssign
@desc Assigns a color to a value using a predefined set of defaults.
@param {String} c A valid CSS color string.
@param {Object} [u = defaults] An object containing overrides of the default colors.
@returns {String}
*/
function colorAssign (c) {
var u = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; // If the value is null or undefined, set to grey.
if ([null, void 0].indexOf(c) >= 0) return getColor("missing", u); // Else if the value is true, set to green.
else if (c === true) return getColor("on", u); // Else if the value is false, set to red.
else if (c === false) return getColor("off", u);
var p = color$2(c); // If the value is not a valid color string, use the color scale.
if (!p) return getColor("scale", u)(c);
return c.toString();
}
/**
@function colorContrast
@desc A set of default color values used when assigning colors based on data.
@param {String} c A valid CSS color string.
@param {Object} [u = defaults] An object containing overrides of the default colors.
@returns {String}
*/
function colorContrast (c) {
var u = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
c = rgb$2(c);
var yiq = (c.r * 299 + c.g * 587 + c.b * 114) / 1000;
return yiq >= 128 ? getColor("dark", u) : getColor("light", u);
}
/**
@function colorLighter
@desc Similar to d3.color.brighter, except that this also reduces saturation so that colors don't appear neon.
@param {String} c A valid CSS color string.
@param {String} [i = 0.5] A value from 0 to 1 dictating the strength of the function.
@returns {String}
*/
function colorLighter (c) {
var i = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.5;
c = hsl$2(c);
i *= 1 - c.l;
c.l += i;
c.s -= i;
return c.toString();
}
/**
* Strips HTML and "un-escapes" escape characters.
* @param {String} input
*/
function htmlDecode(input) {
if (input.replace(/\s+/g, "") === "") return input;
var doc = new DOMParser().parseFromString(input.replace(/<[^>]+>/g, ""), "text/html");
return doc.documentElement ? doc.documentElement.textContent : input;
}
/**
@function textWidth
@desc Given a text string, returns the predicted pixel width of the string when placed into DOM.
@param {String|Array} text Can be either a single string or an array of strings to analyze.
@param {Object} [style] An object of CSS font styles to apply. Accepts any of the valid [CSS font property](http://www.w3schools.com/cssref/pr_font_font.asp) values.
*/
function textWidth (text, style) {
style = Object.assign({
"font-size": 10,
"font-family": "sans-serif",
"font-style": "normal",
"font-weight": 400,
"font-variant": "normal"
}, style);
var context = document.createElement("canvas").getContext("2d");
var font = [];
font.push(style["font-style"]);
font.push(style["font-variant"]);
font.push(style["font-weight"]);
font.push(typeof style["font-size"] === "string" ? style["font-size"] : "".concat(style["font-size"], "px"));
font.push(style["font-family"]);
context.font = font.join(" ");
if (text instanceof Array) return text.map(function (t) {
return context.measureText(htmlDecode(t)).width;
});
return context.measureText(htmlDecode(text)).width;
}
/**
@function trim
@desc Cross-browser implementation of [trim](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim).
@param {String} str
*/
function trim(str) {
return str.toString().replace(/^\s+|\s+$/g, "");
}
/**
@function trimRight
@desc Cross-browser implementation of [trimRight](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/TrimRight).
@param {String} str
*/
function trimRight(str) {
return str.toString().replace(/\s+$/, "");
}
var alpha = "abcdefghiABCDEFGHI_!@#$%^&*()_+1234567890",
checked = {},
height = 32;
var dejavu, macos, monospace, proportional;
/**
@function fontExists
@desc Given either a single font-family or a list of fonts, returns the name of the first font that can be rendered, or `false` if none are installed on the user's machine.
@param {String|Array} font Can be either a valid CSS font-family string (single or comma-separated names) or an Array of string names.
*/
var fontExists = function fontExists(font) {
if (!dejavu) {
dejavu = textWidth(alpha, {
"font-family": "DejaVuSans",
"font-size": height
});
macos = textWidth(alpha, {
"font-family": "-apple-system",
"font-size": height
});
monospace = textWidth(alpha, {
"font-family": "monospace",
"font-size": height
});
proportional = textWidth(alpha, {
"font-family": "sans-serif",
"font-size": height
});
}
if (!(font instanceof Array)) font = font.split(",");
font = font.map(function (f) {
return trim(f);
});
for (var i = 0; i < font.length; i++) {
var fam = font[i];
if (checked[fam] || ["-apple-system", "monospace", "sans-serif", "DejaVuSans"].includes(fam)) return fam;else if (checked[fam] === false) continue;
var width = textWidth(alpha, {
"font-family": fam,
"font-size": height
});
checked[fam] = width !== monospace;
if (checked[fam]) checked[fam] = width !== proportional;
if (macos && checked[fam]) checked[fam] = width !== macos;
if (dejavu && checked[fam]) checked[fam] = width !== dejavu;
if (checked[fam]) return fam;
}
return false;
};
/**
@function rtl
@desc Returns `true` if the HTML or body element has either the "dir" HTML attribute or the "direction" CSS property set to "rtl".
*/
var detectRTL = (function () {
return _select("html").attr("dir") === "rtl" || _select("body").attr("dir") === "rtl" || _select("html").style("direction") === "rtl" || _select("body").style("direction") === "rtl";
});
/**
@function stringify
@desc Coerces value into a String.
@param {String} value
*/
function stringify (value) {
if (value === void 0) value = "undefined";else if (!(typeof value === "string" || value instanceof String)) value = JSON.stringify(value);
return value;
}
// great unicode list: http://asecuritysite.com/coding/asc2
var diacritics = [[/[\300-\305]/g, "A"], [/[\340-\345]/g, "a"], [/[\306]/g, "AE"], [/[\346]/g, "ae"], [/[\337]/g, "B"], [/[\307]/g, "C"], [/[\347]/g, "c"], [/[\320\336\376]/g, "D"], [/[\360]/g, "d"], [/[\310-\313]/g, "E"], [/[\350-\353]/g, "e"], [/[\314-\317]/g, "I"], [/[\354-\357]/g, "i"], [/[\321]/g, "N"], [/[\361]/g, "n"], [/[\u014c\322-\326\330]/g, "O"], [/[\u014d\362-\366\370]/g, "o"], [/[\u016a\331-\334]/g, "U"], [/[\u016b\371-\374]/g, "u"], [/[\327]/g, "x"], [/[\335]/g, "Y"], [/[\375\377]/g, "y"]];
/**
@function strip
@desc Removes all non ASCII characters from a string.
@param {String} value
*/
function strip (value) {
return "".concat(value).replace(/[^A-Za-z0-9\-_]/g, function (_char) {
if (_char === " ") return "-";
var ret = false;
for (var d = 0; d < diacritics.length; d++) {
if (new RegExp(diacritics[d][0]).test(_char)) {
ret = diacritics[d][1];
break;
}
}
return ret || "";
});
}
// scraped from http://www.fileformat.info/info/unicode/category/Mc/list.htm
// and http://www.fileformat.info/info/unicode/category/Mn/list.htm
// JSON.stringify([].slice.call(document.getElementsByClassName("table-list")[0].getElementsByTagName("tr")).filter(function(d){ return d.getElementsByTagName("a").length && d.getElementsByTagName("a")[0].innerHTML.length === 6; }).map(function(d){ return d.getElementsByTagName("a")[0].innerHTML.replace("U", "u").replace("+", ""); }).sort());
// The following unicode characters combine to form new characters and should never be split from surrounding characters.
var a$1 = ["u0903", "u093B", "u093E", "u093F", "u0940", "u0949", "u094A", "u094B", "u094C", "u094E", "u094F", "u0982", "u0983", "u09BE", "u09BF", "u09C0", "u09C7", "u09C8", "u09CB", "u09CC", "u09D7", "u0A03", "u0A3E", "u0A3F", "u0A40", "u0A83", "u0ABE", "u0ABF", "u0AC0", "u0AC9", "u0ACB", "u0ACC", "u0B02", "u0B03", "u0B3E", "u0B40", "u0B47", "u0B48", "u0B4B", "u0B4C", "u0B57", "u0BBE", "u0BBF", "u0BC1", "u0BC2", "u0BC6", "u0BC7", "u0BC8", "u0BCA", "u0BCB", "u0BCC", "u0BD7", "u0C01", "u0C02", "u0C03", "u0C41", "u0C42", "u0C43", "u0C44", "u0C82", "u0C83", "u0CBE", "u0CC0", "u0CC1", "u0CC2", "u0CC3", "u0CC4", "u0CC7", "u0CC8", "u0CCA", "u0CCB", "u0CD5", "u0CD6", "u0D02", "u0D03", "u0D3E", "u0D3F", "u0D40", "u0D46", "u0D47", "u0D48", "u0D4A", "u0D4B", "u0D4C", "u0D57", "u0D82", "u0D83", "u0DCF", "u0DD0", "u0DD1", "u0DD8", "u0DD9", "u0DDA", "u0DDB", "u0DDC", "u0DDD", "u0DDE", "u0DDF", "u0DF2", "u0DF3", "u0F3E", "u0F3F", "u0F7F", "u102B", "u102C", "u1031", "u1038", "u103B", "u103C", "u1056", "u1057", "u1062", "u1063", "u1064", "u1067", "u1068", "u1069", "u106A", "u106B", "u106C", "u106D", "u1083", "u1084", "u1087", "u1088", "u1089", "u108A", "u108B", "u108C", "u108F", "u109A", "u109B", "u109C", "u17B6", "u17BE", "u17BF", "u17C0", "u17C1", "u17C2", "u17C3", "u17C4", "u17C5", "u17C7", "u17C8", "u1923", "u1924", "u1925", "u1926", "u1929", "u192A", "u192B", "u1930", "u1931", "u1933", "u1934", "u1935", "u1936", "u1937", "u1938", "u1A19", "u1A1A", "u1A55", "u1A57", "u1A61", "u1A63", "u1A64", "u1A6D", "u1A6E", "u1A6F", "u1A70", "u1A71", "u1A72", "u1B04", "u1B35", "u1B3B", "u1B3D", "u1B3E", "u1B3F", "u1B40", "u1B41", "u1B43", "u1B44", "u1B82", "u1BA1", "u1BA6", "u1BA7", "u1BAA", "u1BE7", "u1BEA", "u1BEB", "u1BEC", "u1BEE", "u1BF2", "u1BF3", "u1C24", "u1C25", "u1C26", "u1C27", "u1C28", "u1C29", "u1C2A", "u1C2B", "u1C34", "u1C35", "u1CE1", "u1CF2", "u1CF3", "u302E", "u302F", "uA823", "uA824", "uA827", "uA880", "uA881", "uA8B4", "uA8B5", "uA8B6", "uA8B7", "uA8B8", "uA8B9", "uA8BA", "uA8BB", "uA8BC", "uA8BD", "uA8BE", "uA8BF", "uA8C0", "uA8C1", "uA8C2", "uA8C3", "uA952", "uA953", "uA983", "uA9B4", "uA9B5", "uA9BA", "uA9BB", "uA9BD", "uA9BE", "uA9BF", "uA9C0", "uAA2F", "uAA30", "uAA33", "uAA34", "uAA4D", "uAA7B", "uAA7D", "uAAEB", "uAAEE", "uAAEF", "uAAF5", "uABE3", "uABE4", "uABE6", "uABE7", "uABE9", "uABEA", "uABEC"];
var b = ["u0300", "u0301", "u0302", "u0303", "u0304", "u0305", "u0306", "u0307", "u0308", "u0309", "u030A", "u030B", "u030C", "u030D", "u030E", "u030F", "u0310", "u0311", "u0312", "u0313", "u0314", "u0315", "u0316", "u0317", "u0318", "u0319", "u031A", "u031B", "u031C", "u031D", "u031E", "u031F", "u0320", "u0321", "u0322", "u0323", "u0324", "u0325", "u0326", "u0327", "u0328", "u0329", "u032A", "u032B", "u032C", "u032D", "u032E", "u032F", "u0330", "u0331", "u0332", "u0333", "u0334", "u0335", "u0336", "u0337", "u0338", "u0339", "u033A", "u033B", "u033C", "u033D", "u033E", "u033F", "u0340", "u0341", "u0342", "u0343", "u0344", "u0345", "u0346", "u0347", "u0348", "u0349", "u034A", "u034B", "u034C", "u034D", "u034E", "u034F", "u0350", "u0351", "u0352", "u0353", "u0354", "u0355", "u0356", "u0357", "u0358", "u0359", "u035A", "u035B", "u035C", "u035D", "u035E", "u035F", "u0360", "u0361", "u0362", "u0363", "u0364", "u0365", "u0366", "u0367", "u0368", "u0369", "u036A", "u036B", "u036C", "u036D", "u036E", "u036F", "u0483", "u0484", "u0485", "u0486", "u0487", "u0591", "u0592", "u0593", "u0594", "u0595", "u0596", "u0597", "u0598", "u0599", "u059A", "u059B", "u059C", "u059D", "u059E", "u059F", "u05A0", "u05A1", "u05A2", "u05A3", "u05A4", "u05A5", "u05A6", "u05A7", "u05A8", "u05A9", "u05AA", "u05AB", "u05AC", "u05AD", "u05AE", "u05AF", "u05B0", "u05B1", "u05B2", "u05B3", "u05B4", "u05B5", "u05B6", "u05B7", "u05B8", "u05B9", "u05BA", "u05BB", "u05BC", "u05BD", "u05BF", "u05C1", "u05C2", "u05C4", "u05C5", "u05C7", "u0610", "u0611", "u0612", "u0613", "u0614", "u0615", "u0616", "u0617", "u0618", "u0619", "u061A", "u064B", "u064C", "u064D", "u064E", "u064F", "u0650", "u0651", "u0652", "u0653", "u0654", "u0655", "u0656", "u0657", "u0658", "u0659", "u065A", "u065B", "u065C", "u065D", "u065E", "u065F", "u0670", "u06D6", "u06D7", "u06D8", "u06D9", "u06DA", "u06DB", "u06DC", "u06DF", "u06E0", "u06E1", "u06E2", "u06E3", "u06E4", "u06E7", "u06E8", "u06EA", "u06EB", "u06EC", "u06ED", "u0711", "u0730", "u0731", "u0732", "u0733", "u0734", "u0735", "u0736", "u0737", "u0738", "u0739", "u073A", "u073B", "u073C", "u073D", "u073E", "u073F", "u0740", "u0741", "u0742", "u0743", "u0744", "u0745", "u0746", "u0747", "u0748", "u0749", "u074A", "u07A6", "u07A7", "u07A8", "u07A9", "u07AA", "u07AB", "u07AC", "u07AD", "u07AE", "u07AF", "u07B0", "u07EB", "u07EC", "u07ED", "u07EE", "u07EF", "u07F0", "u07F1", "u07F2", "u07F3", "u0816", "u0817", "u0818", "u0819", "u081B", "u081C", "u081D", "u081E", "u081F", "u0820", "u0821", "u0822", "u0823", "u0825", "u0826", "u0827", "u0829", "u082A", "u082B", "u082C", "u082D", "u0859", "u085A", "u085B", "u08E3", "u08E4", "u08E5", "u08E6", "u08E7", "u08E8", "u08E9", "u08EA", "u08EB", "u08EC", "u08ED", "u08EE", "u08EF", "u08F0", "u08F1", "u08F2", "u08F3", "u08F4", "u08F5", "u08F6", "u08F7", "u08F8", "u08F9", "u08FA", "u08FB", "u08FC", "u08FD", "u08FE", "u08FF", "u0900", "u0901", "u0902", "u093A", "u093C", "u0941", "u0942", "u0943", "u0944", "u0945", "u0946", "u0947", "u0948", "u094D", "u0951", "u0952", "u0953", "u0954", "u0955", "u0956", "u0957", "u0962", "u0963", "u0981", "u09BC", "u09C1", "u09C2", "u09C3", "u09C4", "u09CD", "u09E2", "u09E3", "u0A01", "u0A02", "u0A3C", "u0A41", "u0A42", "u0A47", "u0A48", "u0A4B", "u0A4C", "u0A4D", "u0A51", "u0A70", "u0A71", "u0A75", "u0A81", "u0A82", "u0ABC", "u0AC1", "u0AC2", "u0AC3", "u0AC4", "u0AC5", "u0AC7", "u0AC8", "u0ACD", "u0AE2", "u0AE3", "u0B01", "u0B3C", "u0B3F", "u0B41", "u0B42", "u0B43", "u0B44", "u0B4D", "u0B56", "u0B62", "u0B63", "u0B82", "u0BC0", "u0BCD", "u0C00", "u0C3E", "u0C3F", "u0C40", "u0C46", "u0C47", "u0C48", "u0C4A", "u0C4B", "u0C4C", "u0C4D", "u0C55", "u0C56", "u0C62", "u0C63", "u0C81", "u0CBC", "u0CBF", "u0CC6", "u0CCC", "u0CCD", "u0CE2", "u0CE3", "u0D01", "u0D41", "u0D42", "u0D43", "u0D44", "u0D4D", "u0D62", "u0D63", "u0DCA", "u0DD2", "u0DD3", "u0DD4", "u0DD6", "u0E31", "u0E34", "u0E35", "u0E36", "u0E37", "u0E38", "u0E39", "u0E3A", "u0E47", "u0E48", "u0E49", "u0E4A", "u0E4B", "u0E4C", "u0E4D", "u0E4E", "u0EB1", "u0EB4", "u0EB5", "u0EB6", "u0EB7", "u0EB8", "u0EB9", "u0EBB", "u0EBC", "u0EC8", "u0EC9", "u0ECA", "u0ECB", "u0ECC", "u0ECD", "u0F18", "u0F19", "u0F35", "u0F37", "u0F39", "u0F71", "u0F72", "u0F73", "u0F74", "u0F75", "u0F76", "u0F77", "u0F78", "u0F79", "u0F7A", "u0F7B", "u0F7C", "u0F7D", "u0F7E", "u0F80", "u0F81", "u0F82", "u0F83", "u0F84", "u0F86", "u0F87", "u0F8D", "u0F8E", "u0F8F", "u0F90", "u0F91", "u0F92", "u0F93", "u0F94", "u0F95", "u0F96", "u0F97", "u0F99", "u0F9A", "u0F9B", "u0F9C", "u0F9D", "u0F9E", "u0F9F", "u0FA0", "u0FA1", "u0FA2", "u0FA3", "u0FA4", "u0FA5", "u0FA6", "u0FA7", "u0FA8", "u0FA9", "u0FAA", "u0FAB", "u0FAC", "u0FAD", "u0FAE", "u0FAF", "u0FB0", "u0FB1", "u0FB2", "u0FB3", "u0FB4", "u0FB5", "u0FB6", "u0FB7", "u0FB8", "u0FB9", "u0FBA", "u0FBB", "u0FBC", "u0FC6", "u102D", "u102E", "u102F", "u1030", "u1032", "u1033", "u1034", "u1035", "u1036", "u1037", "u1039", "u103A", "u103D", "u103E", "u1058", "u1059", "u105E", "u105F", "u1060", "u1071", "u1072", "u1073", "u1074", "u1082", "u1085", "u1086", "u108D", "u109D", "u135D", "u135E", "u135F", "u1712", "u1713", "u1714", "u1732", "u1733", "u1734", "u1752", "u1753", "u1772", "u1773", "u17B4", "u17B5", "u17B7", "u17B8", "u17B9", "u17BA", "u17BB", "u17BC", "u17BD", "u17C6", "u17C9", "u17CA", "u17CB", "u17CC", "u17CD", "u17CE", "u17CF", "u17D0", "u17D1", "u17D2", "u17D3", "u17DD", "u180B", "u180C", "u180D", "u18A9", "u1920", "u1921", "u1922", "u1927", "u1928", "u1932", "u1939", "u193A", "u193B", "u1A17", "u1A18", "u1A1B", "u1A56", "u1A58", "u1A59", "u1A5A", "u1A5B", "u1A5C", "u1A5D", "u1A5E", "u1A60", "u1A62", "u1A65", "u1A66", "u1A67", "u1A68", "u1A69", "u1A6A", "u1A6B", "u1A6C", "u1A73", "u1A74", "u1A75", "u1A76", "u1A77", "u1A78", "u1A79", "u1A7A", "u1A7B", "u1A7C", "u1A7F", "u1AB0", "u1AB1", "u1AB2", "u1AB3", "u1AB4", "u1AB5", "u1AB6", "u1AB7", "u1AB8", "u1AB9", "u1ABA", "u1ABB", "u1ABC", "u1ABD", "u1B00", "u1B01", "u1B02", "u1B03", "u1B34", "u1B36", "u1B37", "u1B38", "u1B39", "u1B3A", "u1B3C", "u1B42", "u1B6B", "u1B6C", "u1B6D", "u1B6E", "u1B6F", "u1B70", "u1B71", "u1B72", "u1B73", "u1B80", "u1B81", "u1BA2", "u1BA3", "u1BA4", "u1BA5", "u1BA8", "u1BA9", "u1BAB", "u1BAC", "u1BAD", "u1BE6", "u1BE8", "u1BE9", "u1BED", "u1BEF", "u1BF0", "u1BF1", "u1C2C", "u1C2D", "u1C2E", "u1C2F", "u1C30", "u1C31", "u1C32", "u1C33", "u1C36", "u1C37", "u1CD0", "u1CD1", "u1CD2", "u1CD4", "u1CD5", "u1CD6", "u1CD7", "u1CD8", "u1CD9", "u1CDA", "u1CDB", "u1CDC", "u1CDD", "u1CDE", "u1CDF", "u1CE0", "u1CE2", "u1CE3", "u1CE4", "u1CE5", "u1CE6", "u1CE7", "u1CE8", "u1CED", "u1CF4", "u1CF8", "u1CF9", "u1DC0", "u1DC1", "u1DC2", "u1DC3", "u1DC4", "u1DC5", "u1DC6", "u1DC7", "u1DC8", "u1DC9", "u1DCA", "u1DCB", "u1DCC", "u1DCD", "u1DCE", "u1DCF", "u1DD0", "u1DD1", "u1DD2", "u1DD3", "u1DD4", "u1DD5", "u1DD6", "u1DD7", "u1DD8", "u1DD9", "u1DDA", "u1DDB", "u1DDC", "u1DDD", "u1DDE", "u1DDF", "u1DE0", "u1DE1", "u1DE2", "u1DE3", "u1DE4", "u1DE5", "u1DE6", "u1DE7", "u1DE8", "u1DE9", "u1DEA", "u1DEB", "u1DEC", "u1DED", "u1DEE", "u1DEF", "u1DF0", "u1DF1", "u1DF2", "u1DF3", "u1DF4", "u1DF5", "u1DFC", "u1DFD", "u1DFE", "u1DFF", "u20D0", "u20D1", "u20D2", "u20D3", "u20D4", "u20D5", "u20D6", "u20D7", "u20D8", "u20D9", "u20DA", "u20DB", "u20DC", "u20E1", "u20E5", "u20E6", "u20E7", "u20E8", "u20E9", "u20EA", "u20EB", "u20EC", "u20ED", "u20EE", "u20EF", "u20F0", "u2CEF", "u2CF0", "u2CF1", "u2D7F", "u2DE0", "u2DE1", "u2DE2", "u2DE3", "u2DE4", "u2DE5", "u2DE6", "u2DE7", "u2DE8", "u2DE9", "u2DEA", "u2DEB", "u2DEC", "u2DED", "u2DEE", "u2DEF", "u2DF0", "u2DF1", "u2DF2", "u2DF3", "u2DF4", "u2DF5", "u2DF6", "u2DF7", "u2DF8", "u2DF9", "u2DFA", "u2DFB", "u2DFC", "u2DFD", "u2DFE", "u2DFF", "u302A", "u302B", "u302C", "u302D", "u3099", "u309A", "uA66F", "uA674", "uA675", "uA676", "uA677", "uA678", "uA679", "uA67A", "uA67B", "uA67C", "uA67D", "uA69E", "uA69F", "uA6F0", "uA6F1", "uA802", "uA806", "uA80B", "uA825", "uA826", "uA8C4", "uA8E0", "uA8E1", "uA8E2", "uA8E3", "uA8E4", "uA8E5", "uA8E6", "uA8E7", "uA8E8", "uA8E9", "uA8EA", "uA8EB", "uA8EC", "uA8ED", "uA8EE", "uA8EF", "uA8F0", "uA8F1", "uA926", "uA927", "uA928", "uA929", "uA92A", "uA92B", "uA92C", "uA92D", "uA947", "uA948", "uA949", "uA94A", "uA94B", "uA94C", "uA94D", "uA94E", "uA94F", "uA950", "uA951", "uA980", "uA981", "uA982", "uA9B3", "uA9B6", "uA9B7", "uA9B8", "uA9B9", "uA9BC", "uA9E5", "uAA29", "uAA2A", "uAA2B", "uAA2C", "uAA2D", "uAA2E", "uAA31", "uAA32", "uAA35", "uAA36", "uAA43", "uAA4C", "uAA7C", "uAAB0", "uAAB2", "uAAB3", "uAAB4", "uAAB7", "uAAB8", "uAABE", "uAABF", "uAAC1", "uAAEC", "uAAED", "uAAF6", "uABE5", "uABE8", "uABED", "uFB1E", "uFE00", "uFE01", "uFE02", "uFE03", "uFE04", "uFE05", "uFE06", "uFE07", "uFE08", "uFE09", "uFE0A", "uFE0B", "uFE0C", "uFE0D", "uFE0E", "uFE0F", "uFE20", "uFE21", "uFE22", "uFE23", "uFE24", "uFE25", "uFE26", "uFE27", "uFE28", "uFE29", "uFE2A", "uFE2B", "uFE2C", "uFE2D", "uFE2E", "uFE2F"];
var combiningMarks = a$1.concat(b);
var splitChars = ["-", ";", ":", "&", "|", "u0E2F", // thai character pairannoi
"u0EAF", // lao ellipsis
"u0EC6", // lao ko la (word repetition)
"u0ECC", // lao cancellation mark
"u104A", // myanmar sign little section
"u104B", // myanmar sign section
"u104C", // myanmar symbol locative
"u104D", // myanmar symbol completed
"u104E", // myanmar symbol aforementioned
"u104F", // myanmar symbol genitive
"u2013", // en dash
"u2014", // em dash
"u2027", // simplified chinese hyphenation point
"u3000", // simplified chinese ideographic space
"u3001", // simplified chinese ideographic comma
"u3002", // simplified chinese ideographic full stop
"uFF0C", // full-width comma
"uFF5E" // wave dash
];
var prefixChars = ["'", "<", "(", "{", "[", "u00AB", // left-pointing double angle quotation mark
"u300A", // left double angle bracket
"u3008" // left angle bracket
];
var suffixChars = ["'", ">", ")", "}", "]", ".", "!", "?", "/", "u00BB", // right-pointing double angle quotation mark
"u300B", // right double angle bracket
"u3009" // right angle bracket
].concat(splitChars);
var burmeseRange = "\u1000-\u102A\u103F-\u1049\u1050-\u1055";
var japaneseRange = "\u3040-\u309F\u30A0-\u30FF\uFF00-\uFF0B\uFF0D-\uFF5D\uFF5F-\uFF9F\u3400-\u4DBF";
var chineseRange = "\u3400-\u9FBF";
var laoRange = "\u0E81-\u0EAE\u0EB0-\u0EC4\u0EC8-\u0ECB\u0ECD-\u0EDD";
var noSpaceRange = burmeseRange + chineseRange + japaneseRange + laoRange;
var splitWords = new RegExp("(\\".concat(splitChars.join("|\\"), ")*[^\\s|\\").concat(splitChars.join("|\\"), "]*(\\").concat(splitChars.join("|\\"), ")*"), "g");
var noSpaceLanguage = new RegExp("[".concat(noSpaceRange, "]"));
var splitAllChars = new RegExp("(\\".concat(prefixChars.join("|\\"), ")*[").concat(noSpaceRange, "](\\").concat(suffixChars.join("|\\"), "|\\").concat(combiningMarks.join("|\\"), ")*|[a-z0-9]+"), "gi");
/**
@function textSplit
@desc Splits a given sentence into an array of words.
@param {String} sentence
*/
function textSplit (sentence) {
if (!noSpaceLanguage.test(sentence)) return stringify(sentence).match(splitWords).filter(function (w) {
return w.length;
});
return arrayMerge(stringify(sentence).match(splitWords).map(function (d) {
if (noSpaceLanguage.test(d)) return d.match(splitAllChars);
return [d];
}));
}
/**
@function textWrap
@desc Based on the defined styles and dimensions, breaks a string into an array of strings for each line of text.
*/
function textWrap () {
var fontFamily = "sans-serif",
fontSize = 10,
fontWeight = 400,
height = 200,
lineHeight,
maxLines = null,
overflow = false,
split = textSplit,
width = 200;
/**
The inner return object and wraps the text and returns the line data array.
@private
*/
function textWrap(sentence) {
sentence = stringify(sentence);
if (lineHeight === void 0) lineHeight = Math.ceil(fontSize * 1.4);
var words = split(sentence);
var style = {
"font-family": fontFamily,
"font-size": fontSize,
"font-weight": fontWeight,
"line-height": lineHeight
};
var line = 1,
textProg = "",
truncated = false,
widthProg = 0;
var lineData = [],
sizes = textWidth(words, style),
space = textWidth(" ", style);
for (var i = 0; i < words.length; i++) {
var word = words[i];
var wordWidth = sizes[words.indexOf(word)];
word += sentence.slice(textProg.length + word.length).match("^( |\n)*", "g")[0];
if (textProg.slice(-1) === "\n" || widthProg + wordWidth > width) {
if (!i && !overflow) {
truncated = true;
break;
}
if (lineData.length >= line) lineData[line - 1] = trimRight(lineData[line - 1]);
line++;
if (lineHeight * line > height || wordWidth > width && !overflow || maxLines && line > maxLines) {
truncated = true;
break;
}
widthProg = 0;
lineData.push(word);
} else if (!i) lineData[0] = word;else lineData[line - 1] += word;
textProg += word;
widthProg += wordWidth;
widthProg += word.match(/[\s]*$/g)[0].length * space;
}
return {
lines: lineData,
sentence: sentence,
truncated: truncated,
widths: textWidth(lineData, style),
words: words
};
}
/**
@memberof textWrap
@desc If *value* is specified, sets the font family accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current font family.
@param {Function|String} [*value* = "sans-serif"]
*/
textWrap.fontFamily = function (_) {
return arguments.length ? (fontFamily = _, textWrap) : fontFamily;
};
/**
@memberof textWrap
@desc If *value* is specified, sets the font size accessor to the specified function or number and returns this generator. If *value* is not specified, returns the current font size.
@param {Function|Number} [*value* = 10]
*/
textWrap.fontSize = function (_) {
return arguments.length ? (fontSize = _, textWrap) : fontSize;
};
/**
@memberof textWrap
@desc If *value* is specified, sets the font weight accessor to the specified function or number and returns this generator. If *value* is not specified, returns the current font weight.
@param {Function|Number|String} [*value* = 400]
*/
textWrap.fontWeight = function (_) {
return arguments.length ? (fontWeight = _, textWrap) : fontWeight;
};
/**
@memberof textWrap
@desc If *value* is specified, sets height limit to the specified value and returns this generator. If *value* is not specified, returns the current value.
@param {Number} [*value* = 200]
*/
textWrap.height = function (_) {
return arguments.length ? (height = _, textWrap) : height;
};
/**
@memberof textWrap
@desc If *value* is specified, sets the line height accessor to the specified function or number and returns this generator. If *value* is not specified, returns the current line height accessor, which is 1.1 times the [font size](#textWrap.fontSize) by default.
@param {Function|Number} [*value*]
*/
textWrap.lineHeight = function (_) {
return arguments.length ? (lineHeight = _, textWrap) : lineHeight;
};
/**
@memberof textWrap
@desc If *value* is specified, sets the maximum number of lines allowed when wrapping.
@param {Function|Number} [*value*]
*/
textWrap.maxLines = function (_) {
return arguments.length ? (maxLines = _, textWrap) : maxLines;
};
/**
@memberof textWrap
@desc If *value* is specified, sets the overflow to the specified boolean and returns this generator. If *value* is not specified, returns the current overflow value.
@param {Boolean} [*value* = false]
*/
textWrap.overflow = function (_) {
return arguments.length ? (overflow = _, textWrap) : overflow;
};
/**
@memberof textWrap
@desc If *value* is specified, sets the word split function to the specified function and returns this generator. If *value* is not specified, returns the current word split function.
@param {Function} [*value*] A function that, when passed a string, is expected to return that string split into an array of words to textWrap. The default split function splits strings on the following characters: `-`, `/`, `;`, `:`, `&`
*/
textWrap.split = function (_) {
return arguments.length ? (split = _, textWrap) : split;
};
/**
@memberof textWrap
@desc If *value* is specified, sets width limit to the specified value and returns this generator. If *value* is not specified, returns the current value.
@param {Number} [*value* = 200]
*/
textWrap.width = function (_) {
return arguments.length ? (width = _, textWrap) : width;
};
return textWrap;
}
function _typeof$3(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$3 = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$3 = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$3(obj);
}
function _classCallCheck$3(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$3(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$3(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$3(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$3(Constructor, staticProps);
return Constructor;
}
function _inherits$1(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$1(subClass, superClass);
}
function _setPrototypeOf$1(o, p) {
_setPrototypeOf$1 = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$1(o, p);
}
function _createSuper$1(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$1();
return function _createSuperInternal() {
var Super = _getPrototypeOf$1(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$1(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$1(this, result);
};
}
function _possibleConstructorReturn$1(self, call) {
if (call && (_typeof$3(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$1(self);
}
function _assertThisInitialized$1(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$1() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$1(o) {
_getPrototypeOf$1 = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$1(o);
}
var defaultHtmlLookup = {
i: "font-style: italic;",
em: "font-style: italic;",
b: "font-weight: bold;",
strong: "font-weight: bold;"
};
/**
@class TextBox
@extends external:BaseClass
@desc Creates a wrapped text box for each point in an array of data. See [this example](https://d3plus.org/examples/d3plus-text/getting-started/) for help getting started using the TextBox class.
*/
var TextBox = /*#__PURE__*/function (_BaseClass) {
_inherits$1(TextBox, _BaseClass);
var _super = _createSuper$1(TextBox);
/**
@memberof TextBox
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function TextBox() {
var _this;
_classCallCheck$3(this, TextBox);
_this = _super.call(this);
_this._ariaHidden = constant$1("false");
_this._delay = 0;
_this._duration = 0;
_this._ellipsis = function (text, line) {
return line ? "".concat(text.replace(/\.|,$/g, ""), "...") : "";
};
_this._fontColor = constant$1("black");
_this._fontFamily = constant$1(["Roboto", "Helvetica Neue", "HelveticaNeue", "Helvetica", "Arial", "sans-serif"]);
_this._fontMax = constant$1(50);
_this._fontMin = constant$1(8);
_this._fontOpacity = constant$1(1);
_this._fontResize = constant$1(false);
_this._fontSize = constant$1(10);
_this._fontStroke = constant$1("transparent");
_this._fontStrokeWidth = constant$1(0);
_this._fontWeight = constant$1(400);
_this._height = accessor("height", 200);
_this._html = defaultHtmlLookup;
_this._id = function (d, i) {
return d.id || "".concat(i);
};
_this._lineHeight = function (d, i) {
return _this._fontSize(d, i) * 1.2;
};
_this._maxLines = constant$1(null);
_this._on = {};
_this._overflow = constant$1(false);
_this._padding = constant$1(0);
_this._pointerEvents = constant$1("auto");
_this._rotate = constant$1(0);
_this._rotateAnchor = function (d) {
return [d.w / 2, d.h / 2];
};
_this._split = textSplit;
_this._text = accessor("text");
_this._textAnchor = constant$1("start");
_this._verticalAlign = constant$1("top");
_this._width = accessor("width", 200);
_this._x = accessor("x", 0);
_this._y = accessor("y", 0);
return _this;
}
/**
@memberof TextBox
@desc Renders the text boxes. If a *callback* is specified, it will be called once the shapes are done drawing.
@param {Function} [*callback* = undefined]
*/
_createClass$3(TextBox, [{
key: "render",
value: function render(callback) {
var _this2 = this;
if (this._select === void 0) this.select(_select("body").append("svg").style("width", "".concat(window.innerWidth, "px")).style("height", "".concat(window.innerHeight, "px")).node());
var that = this;
var boxes = this._select.selectAll(".d3plus-textBox").data(this._data.reduce(function (arr, d, i) {
var t = _this2._text(d, i);
if (t === void 0) return arr;
t = trim(t);
var resize = _this2._fontResize(d, i);
var lHRatio = _this2._lineHeight(d, i) / _this2._fontSize(d, i);
var fS = resize ? _this2._fontMax(d, i) : _this2._fontSize(d, i),
lH = resize ? fS * lHRatio : _this2._lineHeight(d, i),
line = 1,
lineData = [],
sizes,
wrapResults;
var style = {
"font-family": fontExists(_this2._fontFamily(d, i)),
"font-size": fS,
"font-weight": _this2._fontWeight(d, i),
"line-height": lH
};
var padding = parseSides(_this2._padding(d, i));
var h = _this2._height(d, i) - (padding.top + padding.bottom),
w = _this2._width(d, i) - (padding.left + padding.right);
var wrapper = textWrap().fontFamily(style["font-family"]).fontSize(fS).fontWeight(style["font-weight"]).lineHeight(lH).maxLines(_this2._maxLines(d, i)).height(h).overflow(_this2._overflow(d, i)).width(w).split(_this2._split);
var fMax = _this2._fontMax(d, i),
fMin = _this2._fontMin(d, i),
vA = _this2._verticalAlign(d, i),
words = _this2._split(t, i);
/**
Figures out the lineData to be used for wrapping.
@private
*/
function checkSize() {
var truncate = function truncate() {
if (line < 1) lineData = [that._ellipsis("", line)];else lineData[line - 1] = that._ellipsis(lineData[line - 1], line);
}; // Constraint the font size
fS = max([fS, fMin]);
fS = min([fS, fMax]);
if (resize) {
lH = fS * lHRatio;
wrapper.fontSize(fS).lineHeight(lH);
style["font-size"] = fS;
style["line-height"] = lH;
}
wrapResults = wrapper(t);
lineData = wrapResults.lines.filter(function (l) {
return l !== "";
});
line = lineData.length;
if (wrapResults.truncated) {
if (resize) {
fS--;
if (fS < fMin) {
fS = fMin;
truncate();
return;
} else checkSize();
} else truncate();
}
}
if (w > fMin && (h > lH || resize && h > fMin * lHRatio)) {
if (resize) {
sizes = textWidth(words, style);
var areaMod = 1.165 + w / h * 0.1,
boxArea = w * h,
maxWidth = max(sizes),
textArea = sum(sizes, function (d) {
return d * lH;
}) * areaMod;
if (maxWidth > w || textArea > boxArea) {
var areaRatio = Math.sqrt(boxArea / textArea),
widthRatio = w / maxWidth;
var sizeRatio = min([areaRatio, widthRatio]);
fS = Math.floor(fS * sizeRatio);
}
var heightMax = Math.floor(h * 0.8);
if (fS > heightMax) fS = heightMax;
}
checkSize();
}
if (lineData.length) {
var tH = line * lH;
var r = _this2._rotate(d, i);
var yP = r === 0 ? vA === "top" ? 0 : vA === "middle" ? h / 2 - tH / 2 : h - tH : 0;
yP -= lH * 0.1;
arr.push({
aH: _this2._ariaHidden(d, i),
data: d,
i: i,
lines: lineData,
fC: _this2._fontColor(d, i),
fStroke: _this2._fontStroke(d, i),
fSW: _this2._fontStrokeWidth(d, i),
fF: style["font-family"],
fO: _this2._fontOpacity(d, i),
fW: style["font-weight"],
id: _this2._id(d, i),
tA: _this2._textAnchor(d, i),
vA: _this2._verticalAlign(d, i),
widths: wrapResults.widths,
fS: fS,
lH: lH,
w: w,
h: h,
r: r,
x: _this2._x(d, i) + padding.left,
y: _this2._y(d, i) + yP + padding.top
});
}
return arr;
}, []), function (d) {
return _this2._id(d.data, d.i);
});
var t = transition().duration(this._duration);
if (this._duration === 0) {
boxes.exit().remove();
} else {
boxes.exit().transition().delay(this._duration).remove();
boxes.exit().selectAll("text").transition(t).attr("opacity", 0).style("opacity", 0);
}
/**
* Applies translate and rotate to a text element.
* @param {D3Selection} text
* @private
*/
function rotate(text) {
text.attr("transform", function (d, i) {
var rotateAnchor = that._rotateAnchor(d, i);
return "translate(".concat(d.x, ", ").concat(d.y, ") rotate(").concat(d.r, ", ").concat(rotateAnchor[0], ", ").concat(rotateAnchor[1], ")");
});
}
var update = boxes.enter().append("g").attr("class", "d3plus-textBox").attr("id", function (d) {
return "d3plus-textBox-".concat(strip(d.id));
}).call(rotate).merge(boxes);
var rtl = detectRTL();
update.style("pointer-events", function (d) {
return _this2._pointerEvents(d.data, d.i);
}).each(function (d) {
/**
Sets the inner text content of each <text> element.
@private
*/
function textContent(text) {
text[that._html ? "html" : "text"](function (t) {
return trimRight(t).replace(/&([^\;&]*)/g, function (str, a) {
return a === "amp" ? str : "&amp;".concat(a);
}) // replaces all non-HTML ampersands with escaped entity
.replace(/<([^A-z^/]+)/g, function (str, a) {
return "&lt;".concat(a);
}).replace(/<$/g, "&lt;") // replaces all non-HTML left angle brackets with escaped entity
.replace(/(<[^>^\/]+>)([^<^>]+)$/g, function (str, a, b) {
return "".concat(a).concat(b).concat(a.replace("<", "</"));
}) // ands end tag to lines before mid-HTML break
.replace(/^([^<^>]+)(<\/[^>]+>)/g, function (str, a, b) {
return "".concat(b.replace("</", "<")).concat(a).concat(b);
}) // ands start tag to lines after mid-HTML break
.replace(/<([A-z]+)[^>]*>([^<^>]+)<\/[^>]+>/g, function (str, a, b) {
var tag = that._html[a] ? "<tspan style=\"".concat(that._html[a], "\">") : "";
return "".concat(tag.length ? tag : "").concat(b).concat(tag.length ? "</tspan>" : "");
});
});
}
/**
Styles to apply to each <text> element.
@private
*/
function textStyle(text) {
text.attr("aria-hidden", d.aH).attr("dir", rtl ? "rtl" : "ltr").attr("fill", d.fC).attr("stroke", d.fStroke).attr("stroke-width", d.fSW).attr("text-anchor", d.tA).attr("font-family", d.fF).style("font-family", d.fF).attr("font-size", "".concat(d.fS, "px")).style("font-size", "".concat(d.fS, "px")).attr("font-weight", d.fW).style("font-weight", d.fW).attr("x", "".concat(d.tA === "middle" ? d.w / 2 : rtl ? d.tA === "start" ? d.w : 0 : d.tA === "end" ? d.w : 2 * Math.sin(Math.PI * d.r / 180), "px")).attr("y", function (t, i) {
return d.r === 0 || d.vA === "top" ? "".concat((i + 1) * d.lH - (d.lH - d.fS), "px") : d.vA === "middle" ? "".concat((d.h + d.fS) / 2 - (d.lH - d.fS) + (i - d.lines.length / 2 + 0.5) * d.lH, "px") : "".concat(d.h - 2 * (d.lH - d.fS) - (d.lines.length - (i + 1)) * d.lH + 2 * Math.cos(Math.PI * d.r / 180), "px");
});
}
var texts = _select(this).selectAll("text").data(d.lines);
if (that._duration === 0) {
texts.call(textContent).call(textStyle);
texts.exit().remove();
texts.enter().append("text").attr("dominant-baseline", "alphabetic").style("baseline-shift", "0%").attr("unicode-bidi", "bidi-override").call(textContent).call(textStyle).attr("opacity", d.fO).style("opacity", d.fO);
} else {
texts.call(textContent).transition(t).call(textStyle);
texts.exit().transition(t).attr("opacity", 0).remove();
texts.enter().append("text").attr("dominant-baseline", "alphabetic").style("baseline-shift", "0%").attr("opacity", 0).style("opacity", 0).call(textContent).call(textStyle).merge(texts).transition(t).delay(that._delay).call(textStyle).attr("opacity", d.fO).style("opacity", d.fO);
}
}).transition(t).call(rotate);
var events = Object.keys(this._on),
on = events.reduce(function (obj, e) {
obj[e] = function (d, i) {
return _this2._on[e](d.data, i);
};
return obj;
}, {});
for (var e = 0; e < events.length; e++) {
update.on(events[e], on[events[e]]);
}
if (callback) setTimeout(callback, this._duration + 100);
return this;
}
/**
@memberof TextBox
@desc If *value* is specified, sets the aria-hidden attribute to the specified function or string and returns the current class instance.
@param {Function|String} *value*
@chainable
*/
}, {
key: "ariaHidden",
value: function ariaHidden(_) {
return _ !== undefined ? (this._ariaHidden = typeof _ === "function" ? _ : constant$1(_), this) : this._ariaHidden;
}
/**
@memberof TextBox
@desc Sets the data array to the specified array. A text box will be drawn for each object in the array.
@param {Array} [*data* = []]
@chainable
*/
}, {
key: "data",
value: function data(_) {
return arguments.length ? (this._data = _, this) : this._data;
}
/**
@memberof TextBox
@desc Sets the animation delay to the specified number in milliseconds.
@param {Number} [*value* = 0]
@chainable
*/
}, {
key: "delay",
value: function delay(_) {
return arguments.length ? (this._delay = _, this) : this._delay;
}
/**
@memberof TextBox
@desc Sets the animation duration to the specified number in milliseconds.
@param {Number} [*value* = 0]
@chainable
*/
}, {
key: "duration",
value: function duration(_) {
return arguments.length ? (this._duration = _, this) : this._duration;
}
/**
@memberof TextBox
@desc Sets the function that handles what to do when a line is truncated. It should return the new value for the line, and is passed 2 arguments: the String of text for the line in question, and the number of the line. By default, an ellipsis is added to the end of any line except if it is the first word that cannot fit (in that case, an empty string is returned).
@param {Function|String} [*value*]
@chainable
@example <caption>default accessor</caption>
function(text, line) {
return line ? text.replace(/\.|,$/g, "") + "..." : "";
}
*/
}, {
key: "ellipsis",
value: function ellipsis(_) {
return arguments.length ? (this._ellipsis = typeof _ === "function" ? _ : constant$1(_), this) : this._ellipsis;
}
/**
@memberof TextBox
@desc Sets the font color to the specified accessor function or static string, which is inferred from the [DOM selection](#textBox.select) by default.
@param {Function|String} [*value* = "black"]
@chainable
*/
}, {
key: "fontColor",
value: function fontColor(_) {
return arguments.length ? (this._fontColor = typeof _ === "function" ? _ : constant$1(_), this) : this._fontColor;
}
/**
@memberof TextBox
@desc Defines the font-family to be used. The value passed can be either a *String* name of a font, a comma-separated list of font-family fallbacks, an *Array* of fallbacks, or a *Function* that returns either a *String* or an *Array*. If supplying multiple fallback fonts, the [fontExists](#fontExists) function will be used to determine the first available font on the client's machine.
@param {Array|Function|String} [*value* = ["Roboto", "Helvetica Neue", "HelveticaNeue", "Helvetica", "Arial", "sans-serif"]]
@chainable
*/
}, {
key: "fontFamily",
value: function fontFamily(_) {
return arguments.length ? (this._fontFamily = typeof _ === "function" ? _ : constant$1(_), this) : this._fontFamily;
}
/**
@memberof TextBox
@desc Sets the maximum font size to the specified accessor function or static number (which corresponds to pixel units), which is used when [dynamically resizing fonts](#textBox.fontResize).
@param {Function|Number} [*value* = 50]
@chainable
*/
}, {
key: "fontMax",
value: function fontMax(_) {
return arguments.length ? (this._fontMax = typeof _ === "function" ? _ : constant$1(_), this) : this._fontMax;
}
/**
@memberof TextBox
@desc Sets the minimum font size to the specified accessor function or static number (which corresponds to pixel units), which is used when [dynamically resizing fonts](#textBox.fontResize).
@param {Function|Number} [*value* = 8]
@chainable
*/
}, {
key: "fontMin",
value: function fontMin(_) {
return arguments.length ? (this._fontMin = typeof _ === "function" ? _ : constant$1(_), this) : this._fontMin;
}
/**
@memberof TextBox
@desc Sets the font opacity to the specified accessor function or static number between 0 and 1.
@param {Function|Number} [*value* = 1]
@chainable
*/
}, {
key: "fontOpacity",
value: function fontOpacity(_) {
return arguments.length ? (this._fontOpacity = typeof _ === "function" ? _ : constant$1(_), this) : this._fontOpacity;
}
/**
@memberof TextBox
@desc Toggles font resizing, which can either be defined as a static boolean for all data points, or an accessor function that returns a boolean. See [this example](http://d3plus.org/examples/d3plus-text/resizing-text/) for a side-by-side comparison.
@param {Function|Boolean} [*value* = false]
@chainable
*/
}, {
key: "fontResize",
value: function fontResize(_) {
return arguments.length ? (this._fontResize = typeof _ === "function" ? _ : constant$1(_), this) : this._fontResize;
}
/**
@memberof TextBox
@desc Sets the font size to the specified accessor function or static number (which corresponds to pixel units), which is inferred from the [DOM selection](#textBox.select) by default.
@param {Function|Number} [*value* = 10]
@chainable
*/
}, {
key: "fontSize",
value: function fontSize(_) {
return arguments.length ? (this._fontSize = typeof _ === "function" ? _ : constant$1(_), this) : this._fontSize;
}
/**
@memberof TextBox
@desc Sets the font stroke color for the rendered text.
@param {Function|String} [*value* = "transparent"]
@chainable
*/
}, {
key: "fontStroke",
value: function fontStroke(_) {
return arguments.length ? (this._fontStroke = typeof _ === "function" ? _ : constant$1(_), this) : this._fontStroke;
}
/**
@memberof TextBox
@desc Sets the font stroke width for the rendered text.
@param {Function|Number} [*value* = 0]
@chainable
*/
}, {
key: "fontStrokeWidth",
value: function fontStrokeWidth(_) {
return arguments.length ? (this._fontStrokeWidth = typeof _ === "function" ? _ : constant$1(_), this) : this._fontStrokeWidth;
}
/**
@memberof TextBox
@desc Sets the font weight to the specified accessor function or static number, which is inferred from the [DOM selection](#textBox.select) by default.
@param {Function|Number|String} [*value* = 400]
@chainable
*/
}, {
key: "fontWeight",
value: function fontWeight(_) {
return arguments.length ? (this._fontWeight = typeof _ === "function" ? _ : constant$1(_), this) : this._fontWeight;
}
/**
@memberof TextBox
@desc Sets the height for each box to the specified accessor function or static number.
@param {Function|Number} [*value*]
@chainable
@example <caption>default accessor</caption>
function(d) {
return d.height || 200;
}
*/
}, {
key: "height",
value: function height(_) {
return arguments.length ? (this._height = typeof _ === "function" ? _ : constant$1(_), this) : this._height;
}
/**
@memberof TextBox
@desc Configures the ability to render simple HTML tags. Defaults to supporting `<b>`, `<strong>`, `<i>`, and `<em>`, set to false to disable or provide a mapping of tags to svg styles
@param {Object|Boolean} [*value* = {
i: 'font-style: italic;',
em: 'font-style: italic;',
b: 'font-weight: bold;',
strong: 'font-weight: bold;'
}]
@chainable
*/
}, {
key: "html",
value: function html(_) {
return arguments.length ? (this._html = typeof _ === "boolean" ? _ ? defaultHtmlLookup : false : _, this) : this._html;
}
/**
@memberof TextBox
@desc Defines the unique id for each box to the specified accessor function or static number.
@param {Function|Number} [*value*]
@chainable
@example <caption>default accessor</caption>
function(d, i) {
return d.id || i + "";
}
*/
}, {
key: "id",
value: function id(_) {
return arguments.length ? (this._id = typeof _ === "function" ? _ : constant$1(_), this) : this._id;
}
/**
@memberof TextBox
@desc Sets the line height to the specified accessor function or static number, which is 1.2 times the [font size](#textBox.fontSize) by default.
@param {Function|Number} [*value*]
@chainable
*/
}, {
key: "lineHeight",
value: function lineHeight(_) {
return arguments.length ? (this._lineHeight = typeof _ === "function" ? _ : constant$1(_), this) : this._lineHeight;
}
/**
@memberof TextBox
@desc Restricts the maximum number of lines to wrap onto, which is null (unlimited) by default.
@param {Function|Number} [*value*]
@chainable
*/
}, {
key: "maxLines",
value: function maxLines(_) {
return arguments.length ? (this._maxLines = typeof _ === "function" ? _ : constant$1(_), this) : this._maxLines;
}
/**
@memberof TextBox
@desc Sets the text overflow to the specified accessor function or static boolean.
@param {Function|Boolean} [*value* = false]
@chainable
*/
}, {
key: "overflow",
value: function overflow(_) {
return arguments.length ? (this._overflow = typeof _ === "function" ? _ : constant$1(_), this) : this._overflow;
}
/**
@memberof TextBox
@desc Sets the padding to the specified accessor function, CSS shorthand string, or static number, which is 0 by default.
@param {Function|Number|String} [*value*]
@chainable
*/
}, {
key: "padding",
value: function padding(_) {
return arguments.length ? (this._padding = typeof _ === "function" ? _ : constant$1(_), this) : this._padding;
}
/**
@memberof TextBox
@desc Sets the pointer-events to the specified accessor function or static string.
@param {Function|String} [*value* = "auto"]
@chainable
*/
}, {
key: "pointerEvents",
value: function pointerEvents(_) {
return arguments.length ? (this._pointerEvents = typeof _ === "function" ? _ : constant$1(_), this) : this._pointerEvents;
}
/**
@memberof TextBox
@desc Sets the rotate percentage for each box to the specified accessor function or static string.
@param {Function|Number} [*value* = 0]
@chainable
*/
}, {
key: "rotate",
value: function rotate(_) {
return arguments.length ? (this._rotate = typeof _ === "function" ? _ : constant$1(_), this) : this._rotate;
}
/**
@memberof TextBox
@desc Sets the anchor point around which to rotate the text box.
@param {Function|Number[]}
@chainable
*/
}, {
key: "rotateAnchor",
value: function rotateAnchor(_) {
return arguments.length ? (this._rotateAnchor = typeof _ === "function" ? _ : constant$1(_), this) : this._rotateAnchor;
}
/**
@memberof TextBox
@desc Sets the SVG container element to the specified d3 selector or DOM element. If not explicitly specified, an SVG element will be added to the page for use.
@param {String|HTMLElement} [*selector*]
@chainable
*/
}, {
key: "select",
value: function select(_) {
return arguments.length ? (this._select = _select(_), this) : this._select;
}
/**
@memberof TextBox
@desc Sets the word split behavior to the specified function, which when passed a string is expected to return that string split into an array of words.
@param {Function} [*value*]
@chainable
*/
}, {
key: "split",
value: function split(_) {
return arguments.length ? (this._split = _, this) : this._split;
}
/**
@memberof TextBox
@desc Sets the text for each box to the specified accessor function or static string.
@param {Function|String} [*value*]
@chainable
@example <caption>default accessor</caption>
function(d) {
return d.text;
}
*/
}, {
key: "text",
value: function text(_) {
return arguments.length ? (this._text = typeof _ === "function" ? _ : constant$1(_), this) : this._text;
}
/**
@memberof TextBox
@desc Sets the horizontal text anchor to the specified accessor function or static string, whose values are analagous to the SVG [text-anchor](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor) property.
@param {Function|String} [*value* = "start"]
@chainable
*/
}, {
key: "textAnchor",
value: function textAnchor(_) {
return arguments.length ? (this._textAnchor = typeof _ === "function" ? _ : constant$1(_), this) : this._textAnchor;
}
/**
@memberof TextBox
@desc Sets the vertical alignment to the specified accessor function or static string. Accepts `"top"`, `"middle"`, and `"bottom"`.
@param {Function|String} [*value* = "top"]
@chainable
*/
}, {
key: "verticalAlign",
value: function verticalAlign(_) {
return arguments.length ? (this._verticalAlign = typeof _ === "function" ? _ : constant$1(_), this) : this._verticalAlign;
}
/**
@memberof TextBox
@desc Sets the width for each box to the specified accessor function or static number.
@param {Function|Number} [*value*]
@chainable
@example <caption>default accessor</caption>
function(d) {
return d.width || 200;
}
*/
}, {
key: "width",
value: function width(_) {
return arguments.length ? (this._width = typeof _ === "function" ? _ : constant$1(_), this) : this._width;
}
/**
@memberof TextBox
@desc Sets the x position for each box to the specified accessor function or static number. The number given should correspond to the left side of the textBox.
@param {Function|Number} [*value*]
@chainable
@example <caption>default accessor</caption>
function(d) {
return d.x || 0;
}
*/
}, {
key: "x",
value: function x(_) {
return arguments.length ? (this._x = typeof _ === "function" ? _ : constant$1(_), this) : this._x;
}
/**
@memberof TextBox
@desc Sets the y position for each box to the specified accessor function or static number. The number given should correspond to the top side of the textBox.
@param {Function|Number} [*value*]
@chainable
@example <caption>default accessor</caption>
function(d) {
return d.y || 0;
}
*/
}, {
key: "y",
value: function y(_) {
return arguments.length ? (this._y = typeof _ === "function" ? _ : constant$1(_), this) : this._y;
}
}]);
return TextBox;
}(BaseClass);
/**
@function pointDistanceSquared
@desc Returns the squared euclidean distance between two points.
@param {Array} p1 The first point, which should always be an `[x, y]` formatted Array.
@param {Array} p2 The second point, which should always be an `[x, y]` formatted Array.
@returns {Number}
*/
var pointDistanceSquared = (function (p1, p2) {
var dx = p2[0] - p1[0],
dy = p2[1] - p1[1];
return dx * dx + dy * dy;
});
/**
@function pointDistance
@desc Calculates the pixel distance between two points.
@param {Array} p1 The first point, which should always be an `[x, y]` formatted Array.
@param {Array} p2 The second point, which should always be an `[x, y]` formatted Array.
@returns {Number}
*/
var pointDistance = (function (p1, p2) {
return Math.sqrt(pointDistanceSquared(p1, p2));
});
function _typeof$4(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$4 = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$4 = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$4(obj);
}
function _classCallCheck$4(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$4(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$4(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$4(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$4(Constructor, staticProps);
return Constructor;
}
function _inherits$2(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$2(subClass, superClass);
}
function _setPrototypeOf$2(o, p) {
_setPrototypeOf$2 = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$2(o, p);
}
function _createSuper$2(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$2();
return function _createSuperInternal() {
var Super = _getPrototypeOf$2(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$2(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$2(this, result);
};
}
function _possibleConstructorReturn$2(self, call) {
if (call && (_typeof$4(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$2(self);
}
function _assertThisInitialized$2(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$2() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$2(o) {
_getPrototypeOf$2 = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$2(o);
}
/**
@class Shape
@extends external:BaseClass
@desc An abstracted class for generating shapes.
*/
var Shape = /*#__PURE__*/function (_BaseClass) {
_inherits$2(Shape, _BaseClass);
var _super = _createSuper$2(Shape);
/**
@memberof Shape
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function Shape() {
var _this;
var tagName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "g";
_classCallCheck$4(this, Shape);
_this = _super.call(this);
_this._activeOpacity = 0.25;
_this._activeStyle = {
"stroke": function stroke(d, i) {
var c = _this._fill(d, i);
if (["transparent", "none"].includes(c)) c = _this._stroke(d, i);
return color$1(c).darker(1);
},
"stroke-width": function strokeWidth(d, i) {
var s = _this._strokeWidth(d, i) || 1;
return s * 3;
}
};
_this._ariaLabel = constant$1("");
_this._backgroundImage = constant$1(false);
_this._backgroundImageClass = new Image$1();
_this._data = [];
_this._duration = 600;
_this._fill = constant$1("black");
_this._fillOpacity = constant$1(1);
_this._hoverOpacity = 0.5;
_this._hoverStyle = {
"stroke": function stroke(d, i) {
var c = _this._fill(d, i);
if (["transparent", "none"].includes(c)) c = _this._stroke(d, i);
return color$1(c).darker(0.5);
},
"stroke-width": function strokeWidth(d, i) {
var s = _this._strokeWidth(d, i) || 1;
return s * 2;
}
};
_this._id = function (d, i) {
return d.id !== void 0 ? d.id : i;
};
_this._label = constant$1(false);
_this._labelClass = new TextBox();
_this._labelConfig = {
fontColor: function fontColor(d, i) {
return colorContrast(_this._fill(d, i));
},
fontSize: 12,
padding: 5
};
_this._name = "Shape";
_this._opacity = constant$1(1);
_this._pointerEvents = constant$1("visiblePainted");
_this._role = constant$1("presentation");
_this._rotate = constant$1(0);
_this._rx = constant$1(0);
_this._ry = constant$1(0);
_this._scale = constant$1(1);
_this._shapeRendering = constant$1("geometricPrecision");
_this._stroke = function (d, i) {
return color$1(_this._fill(d, i)).darker(1);
};
_this._strokeDasharray = constant$1("0");
_this._strokeLinecap = constant$1("butt");
_this._strokeOpacity = constant$1(1);
_this._strokeWidth = constant$1(0);
_this._tagName = tagName;
_this._textAnchor = constant$1("start");
_this._vectorEffect = constant$1("non-scaling-stroke");
_this._verticalAlign = constant$1("top");
_this._x = accessor("x", 0);
_this._y = accessor("y", 0);
return _this;
}
/**
@memberof Shape
@desc Given a specific data point and index, returns the aesthetic properties of the shape.
@param {Object} *data point*
@param {Number} *index*
@private
*/
_createClass$4(Shape, [{
key: "_aes",
value: function _aes() {
return {};
}
/**
@memberof Shape
@desc Adds event listeners to each shape group or hit area.
@param {D3Selection} *update* The update cycle of the data binding.
@private
*/
}, {
key: "_applyEvents",
value: function _applyEvents(handler) {
var _this2 = this;
var events = Object.keys(this._on);
var _loop = function _loop(e) {
handler.on(events[e], function (d, i) {
if (!_this2._on[events[e]]) return;
if (d.i !== void 0) i = d.i;
if (d.nested && d.values) {
var calcPoint = function calcPoint(d, i) {
if (_this2._discrete === "x") return [_this2._x(d, i), cursor[1]];else if (_this2._discrete === "y") return [cursor[0], _this2._y(d, i)];else return [_this2._x(d, i), _this2._y(d, i)];
};
var cursor = mouse(_this2._select.node()),
values = d.values.map(function (d) {
return pointDistance(cursor, calcPoint(d, i));
});
i = values.indexOf(min(values));
d = d.values[i];
}
_this2._on[events[e]].bind(_this2)(d, i);
});
};
for (var e = 0; e < events.length; e++) {
_loop(e);
}
}
/**
@memberof Shape
@desc Provides the updated styling to the given shape elements.
@param {HTMLElement} *elem*
@param {Object} *style*
@private
*/
}, {
key: "_updateStyle",
value: function _updateStyle(elem, style) {
var that = this;
if (elem.size() && elem.node().tagName === "g") elem = elem.selectAll("*");
/**
@desc Determines whether a shape is a nested collection of data points, and uses the appropriate data and index for the given function context.
@param {Object} *d* data point
@param {Number} *i* index
@private
*/
function styleLogic(d, i) {
return typeof this !== "function" ? this : d.nested && d.key && d.values ? this(d.values[0], that._data.indexOf(d.values[0])) : this(d, i);
}
var styleObject = {};
for (var key in style) {
if ({}.hasOwnProperty.call(style, key)) {
styleObject[key] = styleLogic.bind(style[key]);
}
}
elem.transition().duration(0).call(attrize, styleObject);
}
/**
@memberof Shape
@desc Provides the default styling to the shape elements.
@param {HTMLElement} *elem*
@private
*/
}, {
key: "_applyStyle",
value: function _applyStyle(elem) {
var that = this;
if (elem.size() && elem.node().tagName === "g") elem = elem.selectAll("*");
/**
@desc Determines whether a shape is a nested collection of data points, and uses the appropriate data and index for the given function context.
@param {Object} *d* data point
@param {Number} *i* index
@private
*/
function styleLogic(d, i) {
return typeof this !== "function" ? this : d.nested && d.key && d.values ? this(d.values[0], that._data.indexOf(d.values[0])) : this(d, i);
}
elem.attr("fill", styleLogic.bind(this._fill)).attr("fill-opacity", styleLogic.bind(this._fillOpacity)).attr("rx", styleLogic.bind(this._rx)).attr("ry", styleLogic.bind(this._ry)).attr("stroke", styleLogic.bind(this._stroke)).attr("stroke-dasharray", styleLogic.bind(this._strokeDasharray)).attr("stroke-linecap", styleLogic.bind(this._strokeLinecap)).attr("stroke-opacity", styleLogic.bind(this._strokeOpacity)).attr("stroke-width", styleLogic.bind(this._strokeWidth)).attr("vector-effect", styleLogic.bind(this._vectorEffect));
}
/**
@memberof Shape
@desc Calculates the transform for the group elements.
@param {HTMLElement} *elem*
@private
*/
}, {
key: "_applyTransform",
value: function _applyTransform(elem) {
var _this3 = this;
elem.attr("transform", function (d, i) {
return "\n translate(".concat(d.__d3plusShape__ ? d.translate ? d.translate : "".concat(_this3._x(d.data, d.i), ",").concat(_this3._y(d.data, d.i)) : "".concat(_this3._x(d, i), ",").concat(_this3._y(d, i)), ")\n scale(").concat(d.__d3plusShape__ ? d.scale || _this3._scale(d.data, d.i) : _this3._scale(d, i), ")\n rotate(").concat(d.__d3plusShape__ ? d.rotate ? d.rotate : _this3._rotate(d.data || d, d.i) : _this3._rotate(d.data || d, d.i), ")");
});
}
/**
@memberof Shape
@desc Checks for nested data and uses the appropriate variables for accessor functions.
@param {HTMLElement} *elem*
@private
*/
}, {
key: "_nestWrapper",
value: function _nestWrapper(method) {
return function (d, i) {
return method(d.__d3plusShape__ ? d.data : d, d.__d3plusShape__ ? d.i : i);
};
}
/**
@memberof Shape
@desc Modifies existing shapes to show active status.
@private
*/
}, {
key: "_renderActive",
value: function _renderActive() {
var that = this;
this._group.selectAll(".d3plus-Shape, .d3plus-Image, .d3plus-textBox").each(function (d, i) {
if (!d) d = {};
if (!d.parentNode) d.parentNode = this.parentNode;
var parent = d.parentNode;
if (_select(this).classed("d3plus-textBox")) d = d.data;
if (d.__d3plusShape__ || d.__d3plus__) {
while (d && (d.__d3plusShape__ || d.__d3plus__)) {
i = d.i;
d = d.data;
}
} else i = that._data.indexOf(d);
var group = !that._active || typeof that._active !== "function" || !that._active(d, i) ? parent : that._activeGroup.node();
if (group !== this.parentNode) {
group.appendChild(this);
if (this.className.baseVal.includes("d3plus-Shape")) {
if (parent === group) _select(this).call(that._applyStyle.bind(that));else _select(this).call(that._updateStyle.bind(that, _select(this), that._activeStyle));
}
}
}); // this._renderImage();
// this._renderLabels();
this._group.selectAll("g.d3plus-".concat(this._name, "-shape, g.d3plus-").concat(this._name, "-image, g.d3plus-").concat(this._name, "-text")).attr("opacity", this._hover ? this._hoverOpacity : this._active ? this._activeOpacity : 1);
}
/**
@memberof Shape
@desc Modifies existing shapes to show hover status.
@private
*/
}, {
key: "_renderHover",
value: function _renderHover() {
var that = this;
this._group.selectAll("g.d3plus-".concat(this._name, "-shape, g.d3plus-").concat(this._name, "-image, g.d3plus-").concat(this._name, "-text, g.d3plus-").concat(this._name, "-hover")).selectAll(".d3plus-Shape, .d3plus-Image, .d3plus-textBox").each(function (d, i) {
if (!d) d = {};
if (!d.parentNode) d.parentNode = this.parentNode;
var parent = d.parentNode;
if (_select(this).classed("d3plus-textBox")) d = d.data;
if (d.__d3plusShape__ || d.__d3plus__) {
while (d && (d.__d3plusShape__ || d.__d3plus__)) {
i = d.i;
d = d.data;
}
} else i = that._data.indexOf(d);
var group = !that._hover || typeof that._hover !== "function" || !that._hover(d, i) ? parent : that._hoverGroup.node();
if (group !== this.parentNode) group.appendChild(this);
if (this.className.baseVal.includes("d3plus-Shape")) {
if (parent === group) _select(this).call(that._applyStyle.bind(that));else _select(this).call(that._updateStyle.bind(that, _select(this), that._hoverStyle));
}
}); // this._renderImage();
// this._renderLabels();
this._group.selectAll("g.d3plus-".concat(this._name, "-shape, g.d3plus-").concat(this._name, "-image, g.d3plus-").concat(this._name, "-text")).attr("opacity", this._hover ? this._hoverOpacity : this._active ? this._activeOpacity : 1);
}
/**
@memberof Shape
@desc Adds background image to each shape group.
@private
*/
}, {
key: "_renderImage",
value: function _renderImage() {
var _this4 = this;
var imageData = [];
this._update.merge(this._enter).data().forEach(function (datum, i) {
var aes = _this4._aes(datum, i);
if (aes.r || aes.width && aes.height) {
var d = datum;
if (datum.nested && datum.key && datum.values) {
d = datum.values[0];
i = _this4._data.indexOf(d);
}
var height = aes.r ? aes.r * 2 : aes.height,
url = _this4._backgroundImage(d, i),
width = aes.r ? aes.r * 2 : aes.width;
if (url) {
var x = d.__d3plusShape__ ? d.translate ? d.translate[0] : _this4._x(d.data, d.i) : _this4._x(d, i),
y = d.__d3plusShape__ ? d.translate ? d.translate[1] : _this4._y(d.data, d.i) : _this4._y(d, i);
if (aes.x) x += aes.x;
if (aes.y) y += aes.y;
if (d.__d3plusShape__) {
d = d.data;
i = d.i;
}
imageData.push({
__d3plus__: true,
data: d,
height: height,
i: i,
id: _this4._id(d, i),
url: url,
width: width,
x: x + -width / 2,
y: y + -height / 2
});
}
}
});
this._backgroundImageClass.data(imageData).duration(this._duration).opacity(this._nestWrapper(this._opacity)).pointerEvents("none").select(elem("g.d3plus-".concat(this._name, "-image"), {
parent: this._group,
update: {
opacity: this._active ? this._activeOpacity : 1
}
}).node()).render();
}
/**
@memberof Shape
@desc Adds labels to each shape group.
@private
*/
}, {
key: "_renderLabels",
value: function _renderLabels() {
var _this5 = this;
var labelData = [];
this._update.merge(this._enter).data().forEach(function (datum, i) {
var d = datum;
if (datum.nested && datum.key && datum.values) {
d = datum.values[0];
i = _this5._data.indexOf(d);
}
var labels = _this5._label(d, i);
if (_this5._labelBounds && labels !== false && labels !== undefined && labels !== null) {
var bounds = _this5._labelBounds(d, i, _this5._aes(datum, i));
if (bounds) {
if (labels.constructor !== Array) labels = [labels];
var x = d.__d3plusShape__ ? d.translate ? d.translate[0] : _this5._x(d.data, d.i) : _this5._x(d, i),
y = d.__d3plusShape__ ? d.translate ? d.translate[1] : _this5._y(d.data, d.i) : _this5._y(d, i);
if (d.__d3plusShape__) {
d = d.data;
i = d.i;
}
for (var l = 0; l < labels.length; l++) {
var b = bounds.constructor === Array ? bounds[l] : Object.assign({}, bounds);
var rotate = _this5._rotate(d, i);
var r = d.labelConfig && d.labelConfig.rotate ? d.labelConfig.rotate : bounds.angle !== undefined ? bounds.angle : 0;
r += rotate;
var rotateAnchor = rotate !== 0 ? [b.x * -1 || 0, b.y * -1 || 0] : [b.width / 2, b.height / 2];
labelData.push({
__d3plus__: true,
data: d,
height: b.height,
l: l,
id: "".concat(_this5._id(d, i), "_").concat(l),
r: r,
rotateAnchor: rotateAnchor,
text: labels[l],
width: b.width,
x: x + b.x,
y: y + b.y
});
}
}
}
});
this._labelClass.data(labelData).duration(this._duration).fontOpacity(this._nestWrapper(this._opacity)).pointerEvents("none").rotate(function (d) {
return d.__d3plus__ ? d.r : d.data.r;
}).rotateAnchor(function (d) {
return d.__d3plus__ ? d.rotateAnchor : d.data.rotateAnchor;
}).select(elem("g.d3plus-".concat(this._name, "-text"), {
parent: this._group,
update: {
opacity: this._active ? this._activeOpacity : 1
}
}).node()).config(configPrep.bind(this)(this._labelConfig)).render();
}
/**
@memberof Shape
@desc Renders the current Shape to the page. If a *callback* is specified, it will be called once the shapes are done drawing.
@param {Function} [*callback*]
@chainable
*/
}, {
key: "render",
value: function render(callback) {
var _this6 = this;
if (this._select === void 0) {
this.select(_select("body").append("svg").style("width", "".concat(window.innerWidth, "px")).style("height", "".concat(window.innerHeight, "px")).style("display", "block").node());
}
this._transition = transition().duration(this._duration);
var data = this._data,
key = this._id;
if (this._dataFilter) {
data = this._dataFilter(data);
if (data.key) key = data.key;
}
if (this._sort) {
data = data.sort(function (a, b) {
while (a.__d3plusShape__ || a.__d3plus__) {
a = a.data;
}
while (b.__d3plusShape__ || b.__d3plus__) {
b = b.data;
}
return _this6._sort(a, b);
});
}
selectAll("g.d3plus-".concat(this._name, "-hover > *, g.d3plus-").concat(this._name, "-active > *")).each(function (d) {
if (d && d.parentNode) d.parentNode.appendChild(this);else this.parentNode.removeChild(this);
}); // Makes the update state of the group selection accessible.
this._group = elem("g.d3plus-".concat(this._name, "-group"), {
parent: this._select
});
var update = this._update = elem("g.d3plus-".concat(this._name, "-shape"), {
parent: this._group,
update: {
opacity: this._active ? this._activeOpacity : 1
}
}).selectAll(".d3plus-".concat(this._name)).data(data, key); // Orders and transforms the updating Shapes.
update.order();
if (this._duration) {
update.transition(this._transition).call(this._applyTransform.bind(this));
} else {
update.call(this._applyTransform.bind(this));
} // Makes the enter state of the group selection accessible.
var enter = this._enter = update.enter().append(this._tagName).attr("class", function (d, i) {
return "d3plus-Shape d3plus-".concat(_this6._name, " d3plus-id-").concat(strip(_this6._nestWrapper(_this6._id)(d, i)));
}).call(this._applyTransform.bind(this)).attr("aria-label", this._ariaLabel).attr("role", this._role).attr("opacity", this._nestWrapper(this._opacity));
var enterUpdate = enter.merge(update);
var enterUpdateRender = enterUpdate.attr("shape-rendering", this._nestWrapper(this._shapeRendering));
if (this._duration) {
enterUpdateRender = enterUpdateRender.attr("pointer-events", "none").transition(this._transition).transition().delay(100).attr("pointer-events", this._pointerEvents);
}
enterUpdateRender.attr("opacity", this._nestWrapper(this._opacity)); // Makes the exit state of the group selection accessible.
var exit = this._exit = update.exit();
if (this._duration) exit.transition().delay(this._duration).remove();else exit.remove();
this._renderImage();
this._renderLabels();
this._hoverGroup = elem("g.d3plus-".concat(this._name, "-hover"), {
parent: this._group
});
this._activeGroup = elem("g.d3plus-".concat(this._name, "-active"), {
parent: this._group
});
var hitAreas = this._group.selectAll(".d3plus-HitArea").data(this._hitArea && Object.keys(this._on).length ? data : [], key);
hitAreas.order().call(this._applyTransform.bind(this));
var isLine = this._name === "Line";
isLine && this._path.curve(paths["curve".concat(this._curve.charAt(0).toUpperCase()).concat(this._curve.slice(1))]).defined(this._defined).x(this._x).y(this._y);
var hitEnter = hitAreas.enter().append(isLine ? "path" : "rect").attr("class", function (d, i) {
return "d3plus-HitArea d3plus-id-".concat(strip(_this6._nestWrapper(_this6._id)(d, i)));
}).attr("fill", "black").attr("stroke", "black").attr("pointer-events", "painted").attr("opacity", 0).call(this._applyTransform.bind(this));
var that = this;
var hitUpdates = hitAreas.merge(hitEnter).each(function (d) {
var i = that._data.indexOf(d);
var h = that._hitArea(d, i, that._aes(d, i));
return h && !(that._name === "Line" && parseFloat(that._strokeWidth(d, i)) > 10) ? _select(this).call(attrize, h) : _select(this).remove();
});
hitAreas.exit().remove();
this._applyEvents(this._hitArea ? hitUpdates : enterUpdate);
setTimeout(function () {
if (_this6._active) _this6._renderActive();else if (_this6._hover) _this6._renderHover();
if (callback) callback();
}, this._duration + 100);
return this;
}
/**
@memberof Shape
@desc If *value* is specified, sets the highlight accessor to the specified function and returns the current class instance.
@param {Function} [*value*]
@chainable
*/
}, {
key: "active",
value: function active(_) {
if (!arguments.length || _ === undefined) return this._active;
this._active = _;
if (this._group) {
// this._renderImage();
// this._renderLabels();
this._renderActive();
}
return this;
}
/**
@memberof Shape
@desc When shapes are active, this is the opacity of any shape that is not active.
@param {Number} *value* = 0.25
@chainable
*/
}, {
key: "activeOpacity",
value: function activeOpacity(_) {
return arguments.length ? (this._activeOpacity = _, this) : this._activeOpacity;
}
/**
@memberof Shape
@desc The style to apply to active shapes.
@param {Object} *value*
@chainable
*/
}, {
key: "activeStyle",
value: function activeStyle(_) {
return arguments.length ? (this._activeStyle = assign({}, this._activeStyle, _), this) : this._activeStyle;
}
/**
@memberof Shape
@desc If *value* is specified, sets the aria-label attribute to the specified function or string and returns the current class instance.
@param {Function|String} *value*
@chainable
*/
}, {
key: "ariaLabel",
value: function ariaLabel(_) {
return _ !== undefined ? (this._ariaLabel = typeof _ === "function" ? _ : constant$1(_), this) : this._ariaLabel;
}
/**
@memberof Shape
@desc If *value* is specified, sets the background-image accessor to the specified function or string and returns the current class instance.
@param {Function|String} [*value* = false]
@chainable
*/
}, {
key: "backgroundImage",
value: function backgroundImage(_) {
return arguments.length ? (this._backgroundImage = typeof _ === "function" ? _ : constant$1(_), this) : this._backgroundImage;
}
/**
@memberof Shape
@desc If *data* is specified, sets the data array to the specified array and returns the current class instance. If *data* is not specified, returns the current data array. A shape will be drawn for each object in the array.
@param {Array} [*data* = []]
@chainable
*/
}, {
key: "data",
value: function data(_) {
return arguments.length ? (this._data = _, this) : this._data;
}
/**
@memberof Shape
@desc Determines if either the X or Y position is discrete along a Line, which helps in determining the nearest data point on a line for a hit area event.
@param {String} *value*
@chainable
*/
}, {
key: "discrete",
value: function discrete(_) {
return arguments.length ? (this._discrete = _, this) : this._discrete;
}
/**
@memberof Shape
@desc If *ms* is specified, sets the animation duration to the specified number and returns the current class instance. If *ms* is not specified, returns the current animation duration.
@param {Number} [*ms* = 600]
@chainable
*/
}, {
key: "duration",
value: function duration(_) {
return arguments.length ? (this._duration = _, this) : this._duration;
}
/**
@memberof Shape
@desc If *value* is specified, sets the fill accessor to the specified function or string and returns the current class instance.
@param {Function|String} [*value* = "black"]
@chainable
*/
}, {
key: "fill",
value: function fill(_) {
return arguments.length ? (this._fill = typeof _ === "function" ? _ : constant$1(_), this) : this._fill;
}
/**
@memberof Shape
@desc Defines the "fill-opacity" attribute for the shapes.
@param {Function|Number} [*value* = 1]
@chainable
*/
}, {
key: "fillOpacity",
value: function fillOpacity(_) {
return arguments.length ? (this._fillOpacity = typeof _ === "function" ? _ : constant$1(_), this) : this._fillOpacity;
}
/**
@memberof Shape
@desc If *value* is specified, sets the highlight accessor to the specified function and returns the current class instance.
@param {Function} [*value*]
@chainable
*/
}, {
key: "hover",
value: function hover(_) {
if (!arguments.length || _ === void 0) return this._hover;
this._hover = _;
if (this._group) {
// this._renderImage();
// this._renderLabels();
this._renderHover();
}
return this;
}
/**
@memberof Shape
@desc The style to apply to hovered shapes.
@param {Object} *value*
@chainable
*/
}, {
key: "hoverStyle",
value: function hoverStyle(_) {
return arguments.length ? (this._hoverStyle = assign({}, this._hoverStyle, _), this) : this._hoverStyle;
}
/**
@memberof Shape
@desc If *value* is specified, sets the hover opacity to the specified function and returns the current class instance.
@param {Number} [*value* = 0.5]
@chainable
*/
}, {
key: "hoverOpacity",
value: function hoverOpacity(_) {
return arguments.length ? (this._hoverOpacity = _, this) : this._hoverOpacity;
}
/**
@memberof Shape
@desc If *bounds* is specified, sets the mouse hit area to the specified function and returns the current class instance. If *bounds* is not specified, returns the current mouse hit area accessor.
@param {Function} [*bounds*] The given function is passed the data point, index, and internally defined properties of the shape and should return an object containing the following values: `width`, `height`, `x`, `y`.
@chainable
@example
function(d, i, shape) {
return {
"width": shape.width,
"height": shape.height,
"x": -shape.width / 2,
"y": -shape.height / 2
};
}
*/
}, {
key: "hitArea",
value: function hitArea(_) {
return arguments.length ? (this._hitArea = typeof _ === "function" ? _ : constant$1(_), this) : this._hitArea;
}
/**
@memberof Shape
@desc If *value* is specified, sets the id accessor to the specified function and returns the current class instance.
@param {Function} [*value*]
@chainable
*/
}, {
key: "id",
value: function id(_) {
return arguments.length ? (this._id = _, this) : this._id;
}
/**
@memberof Shape
@desc If *value* is specified, sets the label accessor to the specified function or string and returns the current class instance.
@param {Function|String|Array} [*value*]
@chainable
*/
}, {
key: "label",
value: function label(_) {
return arguments.length ? (this._label = typeof _ === "function" ? _ : constant$1(_), this) : this._label;
}
/**
@memberof Shape
@desc If *bounds* is specified, sets the label bounds to the specified function and returns the current class instance. If *bounds* is not specified, returns the current inner bounds accessor.
@param {Function} [*bounds*] The given function is passed the data point, index, and internally defined properties of the shape and should return an object containing the following values: `width`, `height`, `x`, `y`. If an array is returned from the function, each value will be used in conjunction with each label.
@chainable
@example
function(d, i, shape) {
return {
"width": shape.width,
"height": shape.height,
"x": -shape.width / 2,
"y": -shape.height / 2
};
}
*/
}, {
key: "labelBounds",
value: function labelBounds(_) {
return arguments.length ? (this._labelBounds = typeof _ === "function" ? _ : constant$1(_), this) : this._labelBounds;
}
/**
@memberof Shape
@desc A pass-through to the config method of the TextBox class used to create a shape's labels.
@param {Object} [*value*]
@chainable
*/
}, {
key: "labelConfig",
value: function labelConfig(_) {
return arguments.length ? (this._labelConfig = assign(this._labelConfig, _), this) : this._labelConfig;
}
/**
@memberof Shape
@desc If *value* is specified, sets the opacity accessor to the specified function or number and returns the current class instance.
@param {Number} [*value* = 1]
@chainable
*/
}, {
key: "opacity",
value: function opacity(_) {
return arguments.length ? (this._opacity = typeof _ === "function" ? _ : constant$1(_), this) : this._opacity;
}
/**
@memberof Shape
@desc If *value* is specified, sets the pointerEvents accessor to the specified function or string and returns the current class instance.
@param {String} [*value*]
@chainable
*/
}, {
key: "pointerEvents",
value: function pointerEvents(_) {
return arguments.length ? (this._pointerEvents = typeof _ === "function" ? _ : constant$1(_), this) : this._pointerEvents;
}
/**
@memberof Shape
@desc If *value* is specified, sets the role attribute to the specified function or string and returns the current class instance.
@param {Function|String} *value*
@chainable
*/
}, {
key: "role",
value: function role(_) {
return _ !== undefined ? (this._role = typeof _ === "function" ? _ : constant$1(_), this) : this._role;
}
/**
@memberof Shape
@desc If *value* is specified, sets the rotate accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value* = 0]
@chainable
*/
}, {
key: "rotate",
value: function rotate(_) {
return arguments.length ? (this._rotate = typeof _ === "function" ? _ : constant$1(_), this) : this._rotate;
}
/**
@memberof Shape
@desc Defines the "rx" attribute for the shapes.
@param {Function|Number} [*value* = 0]
@chainable
*/
}, {
key: "rx",
value: function rx(_) {
return arguments.length ? (this._rx = typeof _ === "function" ? _ : constant$1(_), this) : this._rx;
}
/**
@memberof Shape
@desc Defines the "rx" attribute for the shapes.
@param {Function|Number} [*value* = 0]
@chainable
*/
}, {
key: "ry",
value: function ry(_) {
return arguments.length ? (this._ry = typeof _ === "function" ? _ : constant$1(_), this) : this._ry;
}
/**
@memberof Shape
@desc If *value* is specified, sets the scale accessor to the specified function or string and returns the current class instance.
@param {Function|Number} [*value* = 1]
@chainable
*/
}, {
key: "scale",
value: function scale(_) {
return arguments.length ? (this._scale = typeof _ === "function" ? _ : constant$1(_), this) : this._scale;
}
/**
@memberof Shape
@desc If *selector* is specified, sets the SVG container element to the specified d3 selector or DOM element and returns the current class instance. If *selector* is not specified, returns the current SVG container element.
@param {String|HTMLElement} [*selector* = d3.select("body").append("svg")]
@chainable
*/
}, {
key: "select",
value: function select(_) {
return arguments.length ? (this._select = _select(_), this) : this._select;
}
/**
@memberof Shape
@desc If *value* is specified, sets the shape-rendering accessor to the specified function or string and returns the current class instance.
@param {Function|String} [*value* = "geometricPrecision"]
@chainable
@example
function(d) {
return d.x;
}
*/
}, {
key: "shapeRendering",
value: function shapeRendering(_) {
return arguments.length ? (this._shapeRendering = typeof _ === "function" ? _ : constant$1(_), this) : this._shapeRendering;
}
/**
@memberof Shape
@desc If *value* is specified, sets the sort comparator to the specified function and returns the current class instance.
@param {false|Function} [*value* = []]
@chainable
*/
}, {
key: "sort",
value: function sort(_) {
return arguments.length ? (this._sort = _, this) : this._sort;
}
/**
@memberof Shape
@desc If *value* is specified, sets the stroke accessor to the specified function or string and returns the current class instance.
@param {Function|String} [*value* = "black"]
@chainable
*/
}, {
key: "stroke",
value: function stroke(_) {
return arguments.length ? (this._stroke = typeof _ === "function" ? _ : constant$1(_), this) : this._stroke;
}
/**
@memberof Shape
@desc Defines the "stroke-dasharray" attribute for the shapes.
@param {Function|String} [*value* = "1"]
@chainable
*/
}, {
key: "strokeDasharray",
value: function strokeDasharray(_) {
return arguments.length ? (this._strokeDasharray = typeof _ === "function" ? _ : constant$1(_), this) : this._strokeDasharray;
}
/**
@memberof Shape
@desc Defines the "stroke-linecap" attribute for the shapes. Accepted values are `"butt"`, `"round"`, and `"square"`.
@param {Function|String} [*value* = "butt"]
@chainable
*/
}, {
key: "strokeLinecap",
value: function strokeLinecap(_) {
return arguments.length ? (this._strokeLinecap = typeof _ === "function" ? _ : constant$1(_), this) : this._strokeLinecap;
}
/**
@memberof Shape
@desc Defines the "stroke-opacity" attribute for the shapes.
@param {Function|Number} [*value* = 1]
@chainable
*/
}, {
key: "strokeOpacity",
value: function strokeOpacity(_) {
return arguments.length ? (this._strokeOpacity = typeof _ === "function" ? _ : constant$1(_), this) : this._strokeOpacity;
}
/**
@memberof Shape
@desc If *value* is specified, sets the stroke-width accessor to the specified function or string and returns the current class instance.
@param {Function|Number} [*value* = 0]
@chainable
*/
}, {
key: "strokeWidth",
value: function strokeWidth(_) {
return arguments.length ? (this._strokeWidth = typeof _ === "function" ? _ : constant$1(_), this) : this._strokeWidth;
}
/**
@memberof Shape
@desc If *value* is specified, sets the text-anchor accessor to the specified function or string and returns the current class instance.
@param {Function|String|Array} [*value* = "start"]
@chainable
*/
}, {
key: "textAnchor",
value: function textAnchor(_) {
return arguments.length ? (this._textAnchor = typeof _ === "function" ? _ : constant$1(_), this) : this._textAnchor;
}
/**
@memberof Shape
@desc If *value* is specified, sets the vector-effect accessor to the specified function or string and returns the current class instance.
@param {Function|String} [*value* = "non-scaling-stroke"]
@chainable
*/
}, {
key: "vectorEffect",
value: function vectorEffect(_) {
return arguments.length ? (this._vectorEffect = typeof _ === "function" ? _ : constant$1(_), this) : this._vectorEffect;
}
/**
@memberof Shape
@desc If *value* is specified, sets the vertical alignment accessor to the specified function or string and returns the current class instance.
@param {Function|String|Array} [*value* = "start"]
@chainable
*/
}, {
key: "verticalAlign",
value: function verticalAlign(_) {
return arguments.length ? (this._verticalAlign = typeof _ === "function" ? _ : constant$1(_), this) : this._verticalAlign;
}
/**
@memberof Shape
@desc If *value* is specified, sets the x accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.x;
}
*/
}, {
key: "x",
value: function x(_) {
return arguments.length ? (this._x = typeof _ === "function" ? _ : constant$1(_), this) : this._x;
}
/**
@memberof Shape
@desc If *value* is specified, sets the y accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.y;
}
*/
}, {
key: "y",
value: function y(_) {
return arguments.length ? (this._y = typeof _ === "function" ? _ : constant$1(_), this) : this._y;
}
}]);
return Shape;
}(BaseClass);
/**
* de Casteljau's algorithm for drawing and splitting bezier curves.
* Inspired by https://pomax.github.io/bezierinfo/
*
* @param {Number[][]} points Array of [x,y] points: [start, control1, control2, ..., end]
* The original segment to split.
* @param {Number} t Where to split the curve (value between [0, 1])
* @return {Object} An object { left, right } where left is the segment from 0..t and
* right is the segment from t..1.
*/
function decasteljau(points, t) {
var left = [];
var right = [];
function decasteljauRecurse(points, t) {
if (points.length === 1) {
left.push(points[0]);
right.push(points[0]);
} else {
var newPoints = Array(points.length - 1);
for (var i = 0; i < newPoints.length; i++) {
if (i === 0) {
left.push(points[0]);
}
if (i === newPoints.length - 1) {
right.push(points[i + 1]);
}
newPoints[i] = [(1 - t) * points[i][0] + t * points[i + 1][0], (1 - t) * points[i][1] + t * points[i + 1][1]];
}
decasteljauRecurse(newPoints, t);
}
}
if (points.length) {
decasteljauRecurse(points, t);
}
return {
left: left,
right: right.reverse()
};
}
/**
* Convert segments represented as points back into a command object
*
* @param {Number[][]} points Array of [x,y] points: [start, control1, control2, ..., end]
* Represents a segment
* @return {Object} A command object representing the segment.
*/
function pointsToCommand(points) {
var command = {};
if (points.length === 4) {
command.x2 = points[2][0];
command.y2 = points[2][1];
}
if (points.length >= 3) {
command.x1 = points[1][0];
command.y1 = points[1][1];
}
command.x = points[points.length - 1][0];
command.y = points[points.length - 1][1];
if (points.length === 4) {
// start, control1, control2, end
command.type = 'C';
} else if (points.length === 3) {
// start, control, end
command.type = 'Q';
} else {
// start, end
command.type = 'L';
}
return command;
}
/**
* Runs de Casteljau's algorithm enough times to produce the desired number of segments.
*
* @param {Number[][]} points Array of [x,y] points for de Casteljau (the initial segment to split)
* @param {Number} segmentCount Number of segments to split the original into
* @return {Number[][][]} Array of segments
*/
function splitCurveAsPoints(points, segmentCount) {
segmentCount = segmentCount || 2;
var segments = [];
var remainingCurve = points;
var tIncrement = 1 / segmentCount; // x-----x-----x-----x
// t= 0.33 0.66 1
// x-----o-----------x
// r= 0.33
// x-----o-----x
// r= 0.5 (0.33 / (1 - 0.33)) === tIncrement / (1 - (tIncrement * (i - 1))
// x-----x-----x-----x----x
// t= 0.25 0.5 0.75 1
// x-----o----------------x
// r= 0.25
// x-----o----------x
// r= 0.33 (0.25 / (1 - 0.25))
// x-----o----x
// r= 0.5 (0.25 / (1 - 0.5))
for (var i = 0; i < segmentCount - 1; i++) {
var tRelative = tIncrement / (1 - tIncrement * i);
var split = decasteljau(remainingCurve, tRelative);
segments.push(split.left);
remainingCurve = split.right;
} // last segment is just to the end from the last point
segments.push(remainingCurve);
return segments;
}
/**
* Convert command objects to arrays of points, run de Casteljau's algorithm on it
* to split into to the desired number of segments.
*
* @param {Object} commandStart The start command object
* @param {Object} commandEnd The end command object
* @param {Number} segmentCount The number of segments to create
* @return {Object[]} An array of commands representing the segments in sequence
*/
function splitCurve(commandStart, commandEnd, segmentCount) {
var points = [[commandStart.x, commandStart.y]];
if (commandEnd.x1 != null) {
points.push([commandEnd.x1, commandEnd.y1]);
}
if (commandEnd.x2 != null) {
points.push([commandEnd.x2, commandEnd.y2]);
}
points.push([commandEnd.x, commandEnd.y]);
return splitCurveAsPoints(points, segmentCount).map(pointsToCommand);
}
var commandTokenRegex = /[MLCSTQAHVmlcstqahv]|-?[\d.e+-]+/g;
/**
* List of params for each command type in a path `d` attribute
*/
var typeMap = {
M: ['x', 'y'],
L: ['x', 'y'],
H: ['x'],
V: ['y'],
C: ['x1', 'y1', 'x2', 'y2', 'x', 'y'],
S: ['x2', 'y2', 'x', 'y'],
Q: ['x1', 'y1', 'x', 'y'],
T: ['x', 'y'],
A: ['rx', 'ry', 'xAxisRotation', 'largeArcFlag', 'sweepFlag', 'x', 'y']
}; // Add lower case entries too matching uppercase (e.g. 'm' == 'M')
Object.keys(typeMap).forEach(function (key) {
typeMap[key.toLowerCase()] = typeMap[key];
});
function arrayOfLength(length, value) {
var array = Array(length);
for (var i = 0; i < length; i++) {
array[i] = value;
}
return array;
}
/**
* Converts a command object to a string to be used in a `d` attribute
* @param {Object} command A command object
* @return {String} The string for the `d` attribute
*/
function commandToString(command) {
return "".concat(command.type).concat(typeMap[command.type].map(function (p) {
return command[p];
}).join(','));
}
/**
* Converts command A to have the same type as command B.
*
* e.g., L0,5 -> C0,5,0,5,0,5
*
* Uses these rules:
* x1 <- x
* x2 <- x
* y1 <- y
* y2 <- y
* rx <- 0
* ry <- 0
* xAxisRotation <- read from B
* largeArcFlag <- read from B
* sweepflag <- read from B
*
* @param {Object} aCommand Command object from path `d` attribute
* @param {Object} bCommand Command object from path `d` attribute to match against
* @return {Object} aCommand converted to type of bCommand
*/
function convertToSameType(aCommand, bCommand) {
var conversionMap = {
x1: 'x',
y1: 'y',
x2: 'x',
y2: 'y'
};
var readFromBKeys = ['xAxisRotation', 'largeArcFlag', 'sweepFlag']; // convert (but ignore M types)
if (aCommand.type !== bCommand.type && bCommand.type.toUpperCase() !== 'M') {
var aConverted = {};
Object.keys(bCommand).forEach(function (bKey) {
var bValue = bCommand[bKey]; // first read from the A command
var aValue = aCommand[bKey]; // if it is one of these values, read from B no matter what
if (aValue === undefined) {
if (readFromBKeys.includes(bKey)) {
aValue = bValue;
} else {
// if it wasn't in the A command, see if an equivalent was
if (aValue === undefined && conversionMap[bKey]) {
aValue = aCommand[conversionMap[bKey]];
} // if it doesn't have a converted value, use 0
if (aValue === undefined) {
aValue = 0;
}
}
}
aConverted[bKey] = aValue;
}); // update the type to match B
aConverted.type = bCommand.type;
aCommand = aConverted;
}
return aCommand;
}
/**
* Interpolate between command objects commandStart and commandEnd segmentCount times.
* If the types are L, Q, or C then the curves are split as per de Casteljau's algorithm.
* Otherwise we just copy commandStart segmentCount - 1 times, finally ending with commandEnd.
*
* @param {Object} commandStart Command object at the beginning of the segment
* @param {Object} commandEnd Command object at the end of the segment
* @param {Number} segmentCount The number of segments to split this into. If only 1
* Then [commandEnd] is returned.
* @return {Object[]} Array of ~segmentCount command objects between commandStart and
* commandEnd. (Can be segmentCount+1 objects if commandStart is type M).
*/
function splitSegment(commandStart, commandEnd, segmentCount) {
var segments = []; // line, quadratic bezier, or cubic bezier
if (commandEnd.type === 'L' || commandEnd.type === 'Q' || commandEnd.type === 'C') {
segments = segments.concat(splitCurve(commandStart, commandEnd, segmentCount)); // general case - just copy the same point
} else {
var copyCommand = Object.assign({}, commandStart); // convert M to L
if (copyCommand.type === 'M') {
copyCommand.type = 'L';
}
segments = segments.concat(arrayOfLength(segmentCount - 1).map(function () {
return copyCommand;
}));
segments.push(commandEnd);
}
return segments;
}
/**
* Extends an array of commandsToExtend to the length of the referenceCommands by
* splitting segments until the number of commands match. Ensures all the actual
* points of commandsToExtend are in the extended array.
*
* @param {Object[]} commandsToExtend The command object array to extend
* @param {Object[]} referenceCommands The command object array to match in length
* @param {Function} excludeSegment a function that takes a start command object and
* end command object and returns true if the segment should be excluded from splitting.
* @return {Object[]} The extended commandsToExtend array
*/
function extend$3(commandsToExtend, referenceCommands, excludeSegment) {
// compute insertion points:
// number of segments in the path to extend
var numSegmentsToExtend = commandsToExtend.length - 1; // number of segments in the reference path.
var numReferenceSegments = referenceCommands.length - 1; // this value is always between [0, 1].
var segmentRatio = numSegmentsToExtend / numReferenceSegments; // create a map, mapping segments in referenceCommands to how many points
// should be added in that segment (should always be >= 1 since we need each
// point itself).
// 0 = segment 0-1, 1 = segment 1-2, n-1 = last vertex
var countPointsPerSegment = arrayOfLength(numReferenceSegments).reduce(function (accum, d, i) {
var insertIndex = Math.floor(segmentRatio * i); // handle excluding segments
if (excludeSegment && insertIndex < commandsToExtend.length - 1 && excludeSegment(commandsToExtend[insertIndex], commandsToExtend[insertIndex + 1])) {
// set the insertIndex to the segment that this point should be added to:
// round the insertIndex essentially so we split half and half on
// neighbouring segments. hence the segmentRatio * i < 0.5
var addToPriorSegment = segmentRatio * i % 1 < 0.5; // only skip segment if we already have 1 point in it (can't entirely remove a segment)
if (accum[insertIndex]) {
// TODO - Note this is a naive algorithm that should work for most d3-area use cases
// but if two adjacent segments are supposed to be skipped, this will not perform as
// expected. Could be updated to search for nearest segment to place the point in, but
// will only do that if necessary.
// add to the prior segment
if (addToPriorSegment) {
if (insertIndex > 0) {
insertIndex -= 1; // not possible to add to previous so adding to next
} else if (insertIndex < commandsToExtend.length - 1) {
insertIndex += 1;
} // add to next segment
} else if (insertIndex < commandsToExtend.length - 1) {
insertIndex += 1; // not possible to add to next so adding to previous
} else if (insertIndex > 0) {
insertIndex -= 1;
}
}
}
accum[insertIndex] = (accum[insertIndex] || 0) + 1;
return accum;
}, []); // extend each segment to have the correct number of points for a smooth interpolation
var extended = countPointsPerSegment.reduce(function (extended, segmentCount, i) {
// if last command, just add `segmentCount` number of times
if (i === commandsToExtend.length - 1) {
var lastCommandCopies = arrayOfLength(segmentCount, Object.assign({}, commandsToExtend[commandsToExtend.length - 1])); // convert M to L
if (lastCommandCopies[0].type === 'M') {
lastCommandCopies.forEach(function (d) {
d.type = 'L';
});
}
return extended.concat(lastCommandCopies);
} // otherwise, split the segment segmentCount times.
return extended.concat(splitSegment(commandsToExtend[i], commandsToExtend[i + 1], segmentCount));
}, []); // add in the very first point since splitSegment only adds in the ones after it
extended.unshift(commandsToExtend[0]);
return extended;
}
/**
* Takes a path `d` string and converts it into an array of command
* objects. Drops the `Z` character.
*
* @param {String|null} d A path `d` string
*/
function makeCommands(d) {
// split into valid tokens
var tokens = (d || '').match(commandTokenRegex) || [];
var commands = [];
var commandArgs;
var command; // iterate over each token, checking if we are at a new command
// by presence in the typeMap
for (var i = 0; i < tokens.length; ++i) {
commandArgs = typeMap[tokens[i]]; // new command found:
if (commandArgs) {
command = {
type: tokens[i]
}; // add each of the expected args for this command:
for (var a = 0; a < commandArgs.length; ++a) {
command[commandArgs[a]] = +tokens[i + a + 1];
} // need to increment our token index appropriately since
// we consumed token args
i += commandArgs.length;
commands.push(command);
}
}
return commands;
}
/**
* Interpolate from A to B by extending A and B during interpolation to have
* the same number of points. This allows for a smooth transition when they
* have a different number of points.
*
* Ignores the `Z` character in paths unless both A and B end with it.
*
* @param {String} a The `d` attribute for a path
* @param {String} b The `d` attribute for a path
* @param {Function} excludeSegment a function that takes a start command object and
* end command object and returns true if the segment should be excluded from splitting.
* @returns {Function} Interpolation function that maps t ([0, 1]) to a path `d` string.
*/
function interpolatePath(a, b, excludeSegment) {
var aCommands = makeCommands(a);
var bCommands = makeCommands(b);
if (!aCommands.length && !bCommands.length) {
return function nullInterpolator() {
return '';
};
} // if A is empty, treat it as if it used to contain just the first point
// of B. This makes it so the line extends out of from that first point.
if (!aCommands.length) {
aCommands.push(bCommands[0]); // otherwise if B is empty, treat it as if it contains the first point
// of A. This makes it so the line retracts into the first point.
} else if (!bCommands.length) {
bCommands.push(aCommands[0]);
} // extend to match equal size
var numPointsToExtend = Math.abs(bCommands.length - aCommands.length);
if (numPointsToExtend !== 0) {
// B has more points than A, so add points to A before interpolating
if (bCommands.length > aCommands.length) {
aCommands = extend$3(aCommands, bCommands, excludeSegment); // else if A has more points than B, add more points to B
} else if (bCommands.length < aCommands.length) {
bCommands = extend$3(bCommands, aCommands, excludeSegment);
}
} // commands have same length now.
// convert commands in A to the same type as those in B
aCommands = aCommands.map(function (aCommand, i) {
return convertToSameType(aCommand, bCommands[i]);
}); // create mutable interpolated command objects
var interpolatedCommands = aCommands.map(function (aCommand) {
return _objectSpread2({}, aCommand);
});
var addZ = (a == null || a[a.length - 1] === 'Z') && (b == null || b[b.length - 1] === 'Z');
return function pathInterpolator(t) {
// at 1 return the final value without the extensions used during interpolation
if (t === 1) {
return b == null ? '' : b;
} // interpolate the commands using the mutable interpolated command objs
// we can skip at t=0 since we copied aCommands to begin
if (t > 0) {
for (var i = 0; i < interpolatedCommands.length; ++i) {
var aCommand = aCommands[i];
var bCommand = bCommands[i];
var interpolatedCommand = interpolatedCommands[i];
var _iterator = _createForOfIteratorHelper(typeMap[interpolatedCommand.type]),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var arg = _step.value;
interpolatedCommand[arg] = (1 - t) * aCommand[arg] + t * bCommand[arg]; // do not use floats for flags (#27), round to integer
if (arg === 'largeArcFlag' || arg === 'sweepFlag') {
interpolatedCommand[arg] = Math.round(interpolatedCommand[arg]);
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
}
} // convert to a string (fastest concat: https://jsperf.com/join-concat/150)
var interpolatedString = '';
var _iterator2 = _createForOfIteratorHelper(interpolatedCommands),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var _interpolatedCommand = _step2.value;
interpolatedString += commandToString(_interpolatedCommand);
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
if (addZ) {
interpolatedString += 'Z';
}
return interpolatedString;
};
}
function polygonArea (polygon) {
var i = -1,
n = polygon.length,
a,
b = polygon[n - 1],
area = 0;
while (++i < n) {
a = b;
b = polygon[i];
area += a[1] * b[0] - a[0] * b[1];
}
return area / 2;
}
function polygonCentroid (polygon) {
var i = -1,
n = polygon.length,
x = 0,
y = 0,
a,
b = polygon[n - 1],
c,
k = 0;
while (++i < n) {
a = b;
b = polygon[i];
k += c = a[0] * b[1] - b[0] * a[1];
x += (a[0] + b[0]) * c;
y += (a[1] + b[1]) * c;
}
return k *= 3, [x / k, y / k];
}
function polygonContains (polygon, point) {
var n = polygon.length,
p = polygon[n - 1],
x = point[0],
y = point[1],
x0 = p[0],
y0 = p[1],
x1,
y1,
inside = false;
for (var i = 0; i < n; ++i) {
p = polygon[i], x1 = p[0], y1 = p[1];
if (y1 > y !== y0 > y && x < (x0 - x1) * (y - y1) / (y0 - y1) + x1) inside = !inside;
x0 = x1, y0 = y1;
}
return inside;
}
/**
@function lineIntersection
@desc Finds the intersection point (if there is one) of the lines p1q1 and p2q2.
@param {Array} p1 The first point of the first line segment, which should always be an `[x, y]` formatted Array.
@param {Array} q1 The second point of the first line segment, which should always be an `[x, y]` formatted Array.
@param {Array} p2 The first point of the second line segment, which should always be an `[x, y]` formatted Array.
@param {Array} q2 The second point of the second line segment, which should always be an `[x, y]` formatted Array.
@returns {Boolean}
*/
function lineIntersection (p1, q1, p2, q2) {
// allow for some margins due to numerical errors
var eps = 1e-9; // find the intersection point between the two infinite lines
var dx1 = p1[0] - q1[0],
dx2 = p2[0] - q2[0],
dy1 = p1[1] - q1[1],
dy2 = p2[1] - q2[1];
var denom = dx1 * dy2 - dy1 * dx2;
if (Math.abs(denom) < eps) return null;
var cross1 = p1[0] * q1[1] - p1[1] * q1[0],
cross2 = p2[0] * q2[1] - p2[1] * q2[0];
var px = (cross1 * dx2 - cross2 * dx1) / denom,
py = (cross1 * dy2 - cross2 * dy1) / denom;
return [px, py];
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray$1(arr, i) || _nonIterableRest();
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _unsupportedIterableToArray$1(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray$1(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$1(o, minLen);
}
function _arrayLikeToArray$1(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) {
arr2[i] = arr[i];
}
return arr2;
}
function _iterableToArrayLimit(arr, i) {
if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
/**
@function segmentBoxContains
@desc Checks whether a point is inside the bounding box of a line segment.
@param {Array} s1 The first point of the line segment to be used for the bounding box, which should always be an `[x, y]` formatted Array.
@param {Array} s2 The second point of the line segment to be used for the bounding box, which should always be an `[x, y]` formatted Array.
@param {Array} p The point to be checked, which should always be an `[x, y]` formatted Array.
@returns {Boolean}
*/
function segmentBoxContains (s1, s2, p) {
var eps = 1e-9,
_p = _slicedToArray(p, 2),
px = _p[0],
py = _p[1];
return !(px < Math.min(s1[0], s2[0]) - eps || px > Math.max(s1[0], s2[0]) + eps || py < Math.min(s1[1], s2[1]) - eps || py > Math.max(s1[1], s2[1]) + eps);
}
/**
@function segmentsIntersect
@desc Checks whether the line segments p1q1 && p2q2 intersect.
@param {Array} p1 The first point of the first line segment, which should always be an `[x, y]` formatted Array.
@param {Array} q1 The second point of the first line segment, which should always be an `[x, y]` formatted Array.
@param {Array} p2 The first point of the second line segment, which should always be an `[x, y]` formatted Array.
@param {Array} q2 The second point of the second line segment, which should always be an `[x, y]` formatted Array.
@returns {Boolean}
*/
function segmentsIntersect (p1, q1, p2, q2) {
var p = lineIntersection(p1, q1, p2, q2);
if (!p) return false;
return segmentBoxContains(p1, q1, p) && segmentBoxContains(p2, q2, p);
}
/**
@function polygonInside
@desc Checks if one polygon is inside another polygon.
@param {Array} polyA An Array of `[x, y]` points to be used as the inner polygon, checking if it is inside polyA.
@param {Array} polyB An Array of `[x, y]` points to be used as the containing polygon.
@returns {Boolean}
*/
function polygonInside (polyA, polyB) {
var iA = -1;
var nA = polyA.length;
var nB = polyB.length;
var bA = polyA[nA - 1];
while (++iA < nA) {
var aA = bA;
bA = polyA[iA];
var iB = -1;
var bB = polyB[nB - 1];
while (++iB < nB) {
var aB = bB;
bB = polyB[iB];
if (segmentsIntersect(aA, bA, aB, bB)) return false;
}
}
return polygonContains(polyB, polyA[0]);
}
function _slicedToArray$1(arr, i) {
return _arrayWithHoles$1(arr) || _iterableToArrayLimit$1(arr, i) || _unsupportedIterableToArray$2(arr, i) || _nonIterableRest$1();
}
function _nonIterableRest$1() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _unsupportedIterableToArray$2(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray$2(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$2(o, minLen);
}
function _arrayLikeToArray$2(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) {
arr2[i] = arr[i];
}
return arr2;
}
function _iterableToArrayLimit$1(arr, i) {
if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _arrayWithHoles$1(arr) {
if (Array.isArray(arr)) return arr;
}
/**
@function polygonRayCast
@desc Gives the two closest intersection points between a ray cast from a point inside a polygon. The two points should lie on opposite sides of the origin.
@param {Array} poly The polygon to test against, which should be an `[x, y]` formatted Array.
@param {Array} origin The origin point of the ray to be cast, which should be an `[x, y]` formatted Array.
@param {Number} [alpha = 0] The angle in radians of the ray.
@returns {Array} An array containing two values, the closest point on the left and the closest point on the right. If either point cannot be found, that value will be `null`.
*/
function polygonRayCast (poly, origin) {
var alpha = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var eps = 1e-9;
origin = [origin[0] + eps * Math.cos(alpha), origin[1] + eps * Math.sin(alpha)];
var _origin = origin,
_origin2 = _slicedToArray$1(_origin, 2),
x0 = _origin2[0],
y0 = _origin2[1];
var shiftedOrigin = [x0 + Math.cos(alpha), y0 + Math.sin(alpha)];
var idx = 0;
if (Math.abs(shiftedOrigin[0] - x0) < eps) idx = 1;
var i = -1;
var n = poly.length;
var b = poly[n - 1];
var minSqDistLeft = Number.MAX_VALUE;
var minSqDistRight = Number.MAX_VALUE;
var closestPointLeft = null;
var closestPointRight = null;
while (++i < n) {
var a = b;
b = poly[i];
var p = lineIntersection(origin, shiftedOrigin, a, b);
if (p && segmentBoxContains(a, b, p)) {
var sqDist = pointDistanceSquared(origin, p);
if (p[idx] < origin[idx]) {
if (sqDist < minSqDistLeft) {
minSqDistLeft = sqDist;
closestPointLeft = p;
}
} else if (p[idx] > origin[idx]) {
if (sqDist < minSqDistRight) {
minSqDistRight = sqDist;
closestPointRight = p;
}
}
}
}
return [closestPointLeft, closestPointRight];
}
/**
@function pointRotate
@desc Rotates a point around a given origin.
@param {Array} p The point to be rotated, which should always be an `[x, y]` formatted Array.
@param {Number} alpha The angle in radians to rotate.
@param {Array} [origin = [0, 0]] The origin point of the rotation, which should always be an `[x, y]` formatted Array.
@returns {Boolean}
*/
function pointRotate (p, alpha) {
var origin = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [0, 0];
var cosAlpha = Math.cos(alpha),
sinAlpha = Math.sin(alpha),
xshifted = p[0] - origin[0],
yshifted = p[1] - origin[1];
return [cosAlpha * xshifted - sinAlpha * yshifted + origin[0], sinAlpha * xshifted + cosAlpha * yshifted + origin[1]];
}
/**
@function polygonRotate
@desc Rotates a point around a given origin.
@param {Array} poly The polygon to be rotated, which should be an Array of `[x, y]` values.
@param {Number} alpha The angle in radians to rotate.
@param {Array} [origin = [0, 0]] The origin point of the rotation, which should be an `[x, y]` formatted Array.
@returns {Boolean}
*/
var polygonRotate = (function (poly, alpha) {
var origin = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [0, 0];
return poly.map(function (p) {
return pointRotate(p, alpha, origin);
});
});
/**
@desc square distance from a point to a segment
@param {Array} point
@param {Array} segmentAnchor1
@param {Array} segmentAnchor2
@private
*/
function getSqSegDist(p, p1, p2) {
var x = p1[0],
y = p1[1];
var dx = p2[0] - x,
dy = p2[1] - y;
if (dx !== 0 || dy !== 0) {
var t = ((p[0] - x) * dx + (p[1] - y) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = p2[0];
y = p2[1];
} else if (t > 0) {
x += dx * t;
y += dy * t;
}
}
dx = p[0] - x;
dy = p[1] - y;
return dx * dx + dy * dy;
}
/**
@desc basic distance-based simplification
@param {Array} polygon
@param {Number} sqTolerance
@private
*/
function simplifyRadialDist(poly, sqTolerance) {
var point,
prevPoint = poly[0];
var newPoints = [prevPoint];
for (var i = 1, len = poly.length; i < len; i++) {
point = poly[i];
if (pointDistanceSquared(point, prevPoint) > sqTolerance) {
newPoints.push(point);
prevPoint = point;
}
}
if (prevPoint !== point) newPoints.push(point);
return newPoints;
}
/**
@param {Array} polygon
@param {Number} first
@param {Number} last
@param {Number} sqTolerance
@param {Array} simplified
@private
*/
function simplifyDPStep(poly, first, last, sqTolerance, simplified) {
var index,
maxSqDist = sqTolerance;
for (var i = first + 1; i < last; i++) {
var sqDist = getSqSegDist(poly[i], poly[first], poly[last]);
if (sqDist > maxSqDist) {
index = i;
maxSqDist = sqDist;
}
}
if (maxSqDist > sqTolerance) {
if (index - first > 1) simplifyDPStep(poly, first, index, sqTolerance, simplified);
simplified.push(poly[index]);
if (last - index > 1) simplifyDPStep(poly, index, last, sqTolerance, simplified);
}
}
/**
@desc simplification using Ramer-Douglas-Peucker algorithm
@param {Array} polygon
@param {Number} sqTolerance
@private
*/
function simplifyDouglasPeucker(poly, sqTolerance) {
var last = poly.length - 1;
var simplified = [poly[0]];
simplifyDPStep(poly, 0, last, sqTolerance, simplified);
simplified.push(poly[last]);
return simplified;
}
/**
@function largestRect
@desc Simplifies the points of a polygon using both the Ramer-Douglas-Peucker algorithm and basic distance-based simplification. Adapted to an ES6 module from the excellent [Simplify.js](http://mourner.github.io/simplify-js/).
@author Vladimir Agafonkin
@param {Array} poly An Array of points that represent a polygon.
@param {Number} [tolerance = 1] Affects the amount of simplification (in the same metric as the point coordinates).
@param {Boolean} [highestQuality = false] Excludes distance-based preprocessing step which leads to highest quality simplification but runs ~10-20 times slower.
*/
var simplify = (function (poly) {
var tolerance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
var highestQuality = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
if (poly.length <= 2) return poly;
var sqTolerance = tolerance * tolerance;
poly = highestQuality ? poly : simplifyRadialDist(poly, sqTolerance);
poly = simplifyDouglasPeucker(poly, sqTolerance);
return poly;
});
function _slicedToArray$2(arr, i) {
return _arrayWithHoles$2(arr) || _iterableToArrayLimit$2(arr, i) || _unsupportedIterableToArray$3(arr, i) || _nonIterableRest$2();
}
function _nonIterableRest$2() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _unsupportedIterableToArray$3(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray$3(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$3(o, minLen);
}
function _arrayLikeToArray$3(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) {
arr2[i] = arr[i];
}
return arr2;
}
function _iterableToArrayLimit$2(arr, i) {
if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _arrayWithHoles$2(arr) {
if (Array.isArray(arr)) return arr;
}
var aspectRatioStep = 0.5; // step size for the aspect ratio
var angleStep = 5; // step size for angles (in degrees); has linear impact on running time
var polyCache = {};
/**
@typedef {Object} LargestRect
@desc The returned Object of the largestRect function.
@property {Number} width The width of the rectangle
@property {Number} height The height of the rectangle
@property {Number} cx The x coordinate of the rectangle's center
@property {Number} cy The y coordinate of the rectangle's center
@property {Number} angle The rotation angle of the rectangle in degrees. The anchor of rotation is the center point.
@property {Number} area The area of the largest rectangle.
@property {Array} points An array of x/y coordinates for each point in the rectangle, useful for rendering paths.
*/
/**
@function largestRect
@author Daniel Smilkov [dsmilkov@gmail.com]
@desc An angle of zero means that the longer side of the polygon (the width) will be aligned with the x axis. An angle of 90 and/or -90 means that the longer side of the polygon (the width) will be aligned with the y axis. The value can be a number between -90 and 90 specifying the angle of rotation of the polygon, a string which is parsed to a number, or an array of numbers specifying the possible rotations of the polygon.
@param {Array} poly An Array of points that represent a polygon.
@param {Object} [options] An Object that allows for overriding various parameters of the algorithm.
@param {Number|String|Array} [options.angle = d3.range(-90, 95, 5)] The allowed rotations of the final rectangle.
@param {Number|String|Array} [options.aspectRatio] The ratio between the width and height of the rectangle. The value can be a number, a string which is parsed to a number, or an array of numbers specifying the possible aspect ratios of the final rectangle.
@param {Number} [options.maxAspectRatio = 15] The maximum aspect ratio (width/height) allowed for the rectangle. This property should only be used if the aspectRatio is not provided.
@param {Number} [options.minAspectRatio = 1] The minimum aspect ratio (width/height) allowed for the rectangle. This property should only be used if the aspectRatio is not provided.
@param {Number} [options.nTries = 20] The number of randomly drawn points inside the polygon which the algorithm explores as possible center points of the maximal rectangle.
@param {Number} [options.minHeight = 0] The minimum height of the rectangle.
@param {Number} [options.minWidth = 0] The minimum width of the rectangle.
@param {Number} [options.tolerance = 0.02] The simplification tolerance factor, between 0 and 1. A larger tolerance corresponds to more extensive simplification.
@param {Array} [options.origin] The center point of the rectangle. If specified, the rectangle will be fixed at that point, otherwise the algorithm optimizes across all possible points. The given value can be either a two dimensional array specifying the x and y coordinate of the origin or an array of two dimensional points specifying multiple possible center points of the rectangle.
@param {Boolean} [options.cache] Whether or not to cache the result, which would be used in subsequent calculations to preserve consistency and speed up calculation time.
@return {LargestRect}
*/
function largestRect (poly) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
if (poly.length < 3) {
if (options.verbose) console.error("polygon has to have at least 3 points", poly);
return null;
} // For visualization debugging purposes
var events = []; // User's input normalization
options = Object.assign({
angle: range(-90, 90 + angleStep, angleStep),
cache: true,
maxAspectRatio: 15,
minAspectRatio: 1,
minHeight: 0,
minWidth: 0,
nTries: 20,
tolerance: 0.02,
verbose: false
}, options);
var angles = options.angle instanceof Array ? options.angle : typeof options.angle === "number" ? [options.angle] : typeof options.angle === "string" && !isNaN(options.angle) ? [Number(options.angle)] : [];
var aspectRatios = options.aspectRatio instanceof Array ? options.aspectRatio : typeof options.aspectRatio === "number" ? [options.aspectRatio] : typeof options.aspectRatio === "string" && !isNaN(options.aspectRatio) ? [Number(options.aspectRatio)] : [];
var origins = options.origin && options.origin instanceof Array ? options.origin[0] instanceof Array ? options.origin : [options.origin] : [];
var cacheString;
if (options.cache) {
cacheString = arrayMerge(poly).join(",");
cacheString += "-".concat(options.minAspectRatio);
cacheString += "-".concat(options.maxAspectRatio);
cacheString += "-".concat(options.minHeight);
cacheString += "-".concat(options.minWidth);
cacheString += "-".concat(angles.join(","));
cacheString += "-".concat(origins.join(","));
if (polyCache[cacheString]) return polyCache[cacheString];
}
var area = Math.abs(polygonArea(poly)); // take absolute value of the signed area
if (area === 0) {
if (options.verbose) console.error("polygon has 0 area", poly);
return null;
} // get the width of the bounding box of the original polygon to determine tolerance
var _extent = extent(poly, function (d) {
return d[0];
}),
_extent2 = _slicedToArray$2(_extent, 2),
minx = _extent2[0],
maxx = _extent2[1];
var _extent3 = extent(poly, function (d) {
return d[1];
}),
_extent4 = _slicedToArray$2(_extent3, 2),
miny = _extent4[0],
maxy = _extent4[1]; // simplify polygon
var tolerance = Math.min(maxx - minx, maxy - miny) * options.tolerance;
if (tolerance > 0) poly = simplify(poly, tolerance);
if (options.events) events.push({
type: "simplify",
poly: poly
}); // get the width of the bounding box of the simplified polygon
var _extent5 = extent(poly, function (d) {
return d[0];
});
var _extent6 = _slicedToArray$2(_extent5, 2);
minx = _extent6[0];
maxx = _extent6[1];
var _extent7 = extent(poly, function (d) {
return d[1];
});
var _extent8 = _slicedToArray$2(_extent7, 2);
miny = _extent8[0];
maxy = _extent8[1];
var boxWidth = maxx - minx,
boxHeight = maxy - miny; // discretize the binary search for optimal width to a resolution of this times the polygon width
var widthStep = Math.min(boxWidth, boxHeight) / 50; // populate possible center points with random points inside the polygon
if (!origins.length) {
// get the centroid of the polygon
var centroid = polygonCentroid(poly);
if (!isFinite(centroid[0])) {
if (options.verbose) console.error("cannot find centroid", poly);
return null;
}
if (polygonContains(poly, centroid)) origins.push(centroid);
var nTries = options.nTries; // get few more points inside the polygon
while (nTries) {
var rndX = Math.random() * boxWidth + minx;
var rndY = Math.random() * boxHeight + miny;
var rndPoint = [rndX, rndY];
if (polygonContains(poly, rndPoint)) {
origins.push(rndPoint);
}
nTries--;
}
}
if (options.events) events.push({
type: "origins",
points: origins
});
var maxArea = 0;
var maxRect = null;
for (var ai = 0; ai < angles.length; ai++) {
var angle = angles[ai];
var angleRad = -angle * Math.PI / 180;
if (options.events) events.push({
type: "angle",
angle: angle
});
for (var i = 0; i < origins.length; i++) {
var origOrigin = origins[i]; // generate improved origins
var _polygonRayCast = polygonRayCast(poly, origOrigin, angleRad),
_polygonRayCast2 = _slicedToArray$2(_polygonRayCast, 2),
p1W = _polygonRayCast2[0],
p2W = _polygonRayCast2[1];
var _polygonRayCast3 = polygonRayCast(poly, origOrigin, angleRad + Math.PI / 2),
_polygonRayCast4 = _slicedToArray$2(_polygonRayCast3, 2),
p1H = _polygonRayCast4[0],
p2H = _polygonRayCast4[1];
var modifOrigins = [];
if (p1W && p2W) modifOrigins.push([(p1W[0] + p2W[0]) / 2, (p1W[1] + p2W[1]) / 2]); // average along with width axis
if (p1H && p2H) modifOrigins.push([(p1H[0] + p2H[0]) / 2, (p1H[1] + p2H[1]) / 2]); // average along with height axis
if (options.events) events.push({
type: "modifOrigin",
idx: i,
p1W: p1W,
p2W: p2W,
p1H: p1H,
p2H: p2H,
modifOrigins: modifOrigins
});
for (var _i2 = 0; _i2 < modifOrigins.length; _i2++) {
var origin = modifOrigins[_i2];
if (options.events) events.push({
type: "origin",
cx: origin[0],
cy: origin[1]
});
var _polygonRayCast5 = polygonRayCast(poly, origin, angleRad),
_polygonRayCast6 = _slicedToArray$2(_polygonRayCast5, 2),
_p1W = _polygonRayCast6[0],
_p2W = _polygonRayCast6[1];
if (_p1W === null || _p2W === null) continue;
var minSqDistW = Math.min(pointDistanceSquared(origin, _p1W), pointDistanceSquared(origin, _p2W));
var maxWidth = 2 * Math.sqrt(minSqDistW);
var _polygonRayCast7 = polygonRayCast(poly, origin, angleRad + Math.PI / 2),
_polygonRayCast8 = _slicedToArray$2(_polygonRayCast7, 2),
_p1H = _polygonRayCast8[0],
_p2H = _polygonRayCast8[1];
if (_p1H === null || _p2H === null) continue;
var minSqDistH = Math.min(pointDistanceSquared(origin, _p1H), pointDistanceSquared(origin, _p2H));
var maxHeight = 2 * Math.sqrt(minSqDistH);
if (maxWidth * maxHeight < maxArea) continue;
var aRatios = aspectRatios;
if (!aRatios.length) {
var minAspectRatio = Math.max(options.minAspectRatio, options.minWidth / maxHeight, maxArea / (maxHeight * maxHeight));
var maxAspectRatio = Math.min(options.maxAspectRatio, maxWidth / options.minHeight, maxWidth * maxWidth / maxArea);
aRatios = range(minAspectRatio, maxAspectRatio + aspectRatioStep, aspectRatioStep);
}
for (var a = 0; a < aRatios.length; a++) {
var aRatio = aRatios[a]; // do a binary search to find the max width that works
var left = Math.max(options.minWidth, Math.sqrt(maxArea * aRatio));
var right = Math.min(maxWidth, maxHeight * aRatio);
if (right * maxHeight < maxArea) continue;
if (options.events && right - left >= widthStep) events.push({
type: "aRatio",
aRatio: aRatio
});
while (right - left >= widthStep) {
var width = (left + right) / 2;
var height = width / aRatio;
var _origin = _slicedToArray$2(origin, 2),
cx = _origin[0],
cy = _origin[1];
var rectPoly = [[cx - width / 2, cy - height / 2], [cx + width / 2, cy - height / 2], [cx + width / 2, cy + height / 2], [cx - width / 2, cy + height / 2]];
rectPoly = polygonRotate(rectPoly, angleRad, origin);
var insidePoly = polygonInside(rectPoly, poly);
if (insidePoly) {
// we know that the area is already greater than the maxArea found so far
maxArea = width * height;
rectPoly.push(rectPoly[0]);
maxRect = {
area: maxArea,
cx: cx,
cy: cy,
width: width,
height: height,
angle: -angle,
points: rectPoly
};
left = width; // increase the width in the binary search
} else {
right = width; // decrease the width in the binary search
}
if (options.events) events.push({
type: "rectangle",
areaFraction: width * height / area,
cx: cx,
cy: cy,
width: width,
height: height,
angle: angle,
insidePoly: insidePoly
});
}
}
}
}
}
if (options.cache) {
polyCache[cacheString] = maxRect;
}
return options.events ? Object.assign(maxRect || {}, {
events: events
}) : maxRect;
}
function _typeof$5(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$5 = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$5 = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$5(obj);
}
function _classCallCheck$5(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$5(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$5(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$5(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$5(Constructor, staticProps);
return Constructor;
}
function _get$1(target, property, receiver) {
if (typeof Reflect !== "undefined" && Reflect.get) {
_get$1 = Reflect.get;
} else {
_get$1 = function _get(target, property, receiver) {
var base = _superPropBase$1(target, property);
if (!base) return;
var desc = Object.getOwnPropertyDescriptor(base, property);
if (desc.get) {
return desc.get.call(receiver);
}
return desc.value;
};
}
return _get$1(target, property, receiver || target);
}
function _superPropBase$1(object, property) {
while (!Object.prototype.hasOwnProperty.call(object, property)) {
object = _getPrototypeOf$3(object);
if (object === null) break;
}
return object;
}
function _inherits$3(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$3(subClass, superClass);
}
function _setPrototypeOf$3(o, p) {
_setPrototypeOf$3 = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$3(o, p);
}
function _createSuper$3(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$3();
return function _createSuperInternal() {
var Super = _getPrototypeOf$3(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$3(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$3(this, result);
};
}
function _possibleConstructorReturn$3(self, call) {
if (call && (_typeof$5(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$3(self);
}
function _assertThisInitialized$3(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$3() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$3(o) {
_getPrototypeOf$3 = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$3(o);
}
/**
@class Area
@extends Shape
@desc Creates SVG areas based on an array of data.
*/
var Area = /*#__PURE__*/function (_Shape) {
_inherits$3(Area, _Shape);
var _super = _createSuper$3(Area);
/**
@memberof Area
@desc Invoked when creating a new class instance, and overrides any default parameters inherited from Shape.
@private
*/
function Area() {
var _this;
_classCallCheck$5(this, Area);
_this = _super.call(this);
_this._curve = "linear";
_this._defined = function () {
return true;
};
_this._labelBounds = function (d, i, aes) {
var r = largestRect(aes.points);
if (!r) return null;
return {
angle: r.angle,
width: r.width,
height: r.height,
x: r.cx - r.width / 2 - _this._x(d, i),
y: r.cy - r.height / 2 - _this._y(d, i)
};
};
_this._labelConfig = Object.assign(_this._labelConfig, {
textAnchor: "middle",
verticalAlign: "middle"
});
_this._name = "Area";
_this._x = accessor("x");
_this._x0 = accessor("x");
_this._x1 = null;
_this._y = constant$1(0);
_this._y0 = constant$1(0);
_this._y1 = accessor("y");
return _this;
}
/**
@memberof Area
@desc Given a specific data point and index, returns the aesthetic properties of the shape.
@param {Object} *data point*
@param {Number} *index*
@private
*/
_createClass$5(Area, [{
key: "_aes",
value: function _aes(d) {
var _this2 = this;
var values = d.values.slice().sort(function (a, b) {
return _this2._y1 ? _this2._x(a) - _this2._x(b) : _this2._y(a) - _this2._y(b);
});
var points1 = values.map(function (v, z) {
return [_this2._x0(v, z), _this2._y0(v, z)];
});
var points2 = values.reverse().map(function (v, z) {
return _this2._y1 ? [_this2._x(v, z), _this2._y1(v, z)] : [_this2._x1(v, z), _this2._y(v, z)];
});
var points = points1.concat(points2);
if (points1[0][1] > points2[0][1]) points = points.reverse();
points.push(points[0]);
return {
points: points
};
}
/**
@memberof Area
@desc Filters/manipulates the data array before binding each point to an SVG group.
@param {Array} [*data* = the data array to be filtered]
@private
*/
}, {
key: "_dataFilter",
value: function _dataFilter(data) {
var _this3 = this;
var areas = nest().key(this._id).entries(data).map(function (d) {
d.data = objectMerge(d.values);
d.i = data.indexOf(d.values[0]);
var x = extent(d.values.map(_this3._x).concat(d.values.map(_this3._x0)).concat(_this3._x1 ? d.values.map(_this3._x1) : []));
d.xR = x;
d.width = x[1] - x[0];
d.x = x[0] + d.width / 2;
var y = extent(d.values.map(_this3._y).concat(d.values.map(_this3._y0)).concat(_this3._y1 ? d.values.map(_this3._y1) : []));
d.yR = y;
d.height = y[1] - y[0];
d.y = y[0] + d.height / 2;
d.nested = true;
d.translate = [d.x, d.y];
d.__d3plusShape__ = true;
return d;
});
areas.key = function (d) {
return d.key;
};
return areas;
}
/**
@memberof Area
@desc Draws the area polygons.
@param {Function} [*callback*]
@chainable
*/
}, {
key: "render",
value: function render(callback) {
var _this4 = this;
_get$1(_getPrototypeOf$3(Area.prototype), "render", this).call(this, callback);
var path = this._path = area().defined(this._defined).curve(paths["curve".concat(this._curve.charAt(0).toUpperCase()).concat(this._curve.slice(1))]).x(this._x).x0(this._x0).x1(this._x1).y(this._y).y0(this._y0).y1(this._y1);
var exitPath = area().defined(function (d) {
return d;
}).curve(paths["curve".concat(this._curve.charAt(0).toUpperCase()).concat(this._curve.slice(1))]).x(this._x).y(this._y).x0(function (d, i) {
return _this4._x1 ? _this4._x0(d, i) + (_this4._x1(d, i) - _this4._x0(d, i)) / 2 : _this4._x0(d, i);
}).x1(function (d, i) {
return _this4._x1 ? _this4._x0(d, i) + (_this4._x1(d, i) - _this4._x0(d, i)) / 2 : _this4._x0(d, i);
}).y0(function (d, i) {
return _this4._y1 ? _this4._y0(d, i) + (_this4._y1(d, i) - _this4._y0(d, i)) / 2 : _this4._y0(d, i);
}).y1(function (d, i) {
return _this4._y1 ? _this4._y0(d, i) + (_this4._y1(d, i) - _this4._y0(d, i)) / 2 : _this4._y0(d, i);
});
this._enter.append("path").attr("transform", function (d) {
return "translate(".concat(-d.xR[0] - d.width / 2, ", ").concat(-d.yR[0] - d.height / 2, ")");
}).attr("d", function (d) {
return exitPath(d.values);
}).call(this._applyStyle.bind(this)).transition(this._transition).attrTween("d", function (d) {
return interpolatePath(_select(this).attr("d"), path(d.values));
});
this._update.select("path").transition(this._transition).attr("transform", function (d) {
return "translate(".concat(-d.xR[0] - d.width / 2, ", ").concat(-d.yR[0] - d.height / 2, ")");
}).attrTween("d", function (d) {
return interpolatePath(_select(this).attr("d"), path(d.values));
}).call(this._applyStyle.bind(this));
this._exit.select("path").transition(this._transition).attrTween("d", function (d) {
return interpolatePath(_select(this).attr("d"), exitPath(d.values));
});
return this;
}
/**
@memberof Area
@desc If *value* is specified, sets the area curve to the specified string and returns the current class instance. If *value* is not specified, returns the current area curve.
@param {String} [*value* = "linear"]
@chainable
*/
}, {
key: "curve",
value: function curve(_) {
return arguments.length ? (this._curve = _, this) : this._curve;
}
/**
@memberof Area
@desc If *value* is specified, sets the defined accessor to the specified function and returns the current class instance. If *value* is not specified, returns the current defined accessor.
@param {Function} [*value*]
@chainable
*/
}, {
key: "defined",
value: function defined(_) {
return arguments.length ? (this._defined = _, this) : this._defined;
}
/**
@memberof Area
@desc If *value* is specified, sets the x accessor to the specified function or number and returns the current class instance. If *value* is not specified, returns the current x accessor.
@param {Function|Number} [*value*]
@chainable
*/
}, {
key: "x",
value: function x(_) {
if (!arguments.length) return this._x;
this._x = typeof _ === "function" ? _ : constant$1(_);
this._x0 = this._x;
return this;
}
/**
@memberof Area
@desc If *value* is specified, sets the x0 accessor to the specified function or number and returns the current class instance. If *value* is not specified, returns the current x0 accessor.
@param {Function|Number} [*value*]
@chainable
*/
}, {
key: "x0",
value: function x0(_) {
if (!arguments.length) return this._x0;
this._x0 = typeof _ === "function" ? _ : constant$1(_);
this._x = this._x0;
return this;
}
/**
@memberof Area
@desc If *value* is specified, sets the x1 accessor to the specified function or number and returns the current class instance. If *value* is not specified, returns the current x1 accessor.
@param {Function|Number|null} [*value*]
@chainable
*/
}, {
key: "x1",
value: function x1(_) {
return arguments.length ? (this._x1 = typeof _ === "function" || _ === null ? _ : constant$1(_), this) : this._x1;
}
/**
@memberof Area
@desc If *value* is specified, sets the y accessor to the specified function or number and returns the current class instance. If *value* is not specified, returns the current y accessor.
@param {Function|Number} [*value*]
@chainable
*/
}, {
key: "y",
value: function y(_) {
if (!arguments.length) return this._y;
this._y = typeof _ === "function" ? _ : constant$1(_);
this._y0 = this._y;
return this;
}
/**
@memberof Area
@desc If *value* is specified, sets the y0 accessor to the specified function or number and returns the current class instance. If *value* is not specified, returns the current y0 accessor.
@param {Function|Number} [*value*]
@chainable
*/
}, {
key: "y0",
value: function y0(_) {
if (!arguments.length) return this._y0;
this._y0 = typeof _ === "function" ? _ : constant$1(_);
this._y = this._y0;
return this;
}
/**
@memberof Area
@desc If *value* is specified, sets the y1 accessor to the specified function or number and returns the current class instance. If *value* is not specified, returns the current y1 accessor.
@param {Function|Number|null} [*value*]
@chainable
*/
}, {
key: "y1",
value: function y1(_) {
return arguments.length ? (this._y1 = typeof _ === "function" || _ === null ? _ : constant$1(_), this) : this._y1;
}
}]);
return Area;
}(Shape);
function _typeof$6(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$6 = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$6 = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$6(obj);
}
function _classCallCheck$6(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$6(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$6(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$6(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$6(Constructor, staticProps);
return Constructor;
}
function _get$2(target, property, receiver) {
if (typeof Reflect !== "undefined" && Reflect.get) {
_get$2 = Reflect.get;
} else {
_get$2 = function _get(target, property, receiver) {
var base = _superPropBase$2(target, property);
if (!base) return;
var desc = Object.getOwnPropertyDescriptor(base, property);
if (desc.get) {
return desc.get.call(receiver);
}
return desc.value;
};
}
return _get$2(target, property, receiver || target);
}
function _superPropBase$2(object, property) {
while (!Object.prototype.hasOwnProperty.call(object, property)) {
object = _getPrototypeOf$4(object);
if (object === null) break;
}
return object;
}
function _inherits$4(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$4(subClass, superClass);
}
function _setPrototypeOf$4(o, p) {
_setPrototypeOf$4 = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$4(o, p);
}
function _createSuper$4(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$4();
return function _createSuperInternal() {
var Super = _getPrototypeOf$4(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$4(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$4(this, result);
};
}
function _possibleConstructorReturn$4(self, call) {
if (call && (_typeof$6(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$4(self);
}
function _assertThisInitialized$4(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$4() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$4(o) {
_getPrototypeOf$4 = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$4(o);
}
/**
@class Bar
@extends Shape
@desc Creates SVG areas based on an array of data.
*/
var Bar = /*#__PURE__*/function (_Shape) {
_inherits$4(Bar, _Shape);
var _super = _createSuper$4(Bar);
/**
@memberof Bar
@desc Invoked when creating a new class instance, and overrides any default parameters inherited from Shape.
@private
*/
function Bar() {
var _this;
_classCallCheck$6(this, Bar);
_this = _super.call(this, "rect");
_this._name = "Bar";
_this._height = constant$1(10);
_this._labelBounds = function (d, i, s) {
return {
width: s.width,
height: s.height,
x: _this._x1 !== null ? _this._getX(d, i) : -s.width / 2,
y: _this._x1 === null ? _this._getY(d, i) : -s.height / 2
};
};
_this._width = constant$1(10);
_this._x = accessor("x");
_this._x0 = accessor("x");
_this._x1 = null;
_this._y = constant$1(0);
_this._y0 = constant$1(0);
_this._y1 = accessor("y");
return _this;
}
/**
@memberof Bar
@desc Draws the bars.
@param {Function} [*callback*]
@chainable
*/
_createClass$6(Bar, [{
key: "render",
value: function render(callback) {
var _this2 = this;
_get$2(_getPrototypeOf$4(Bar.prototype), "render", this).call(this, callback);
var enter = this._enter.attr("width", function (d, i) {
return _this2._x1 === null ? _this2._getWidth(d, i) : 0;
}).attr("height", function (d, i) {
return _this2._x1 !== null ? _this2._getHeight(d, i) : 0;
}).attr("x", function (d, i) {
return _this2._x1 === null ? -_this2._getWidth(d, i) / 2 : 0;
}).attr("y", function (d, i) {
return _this2._x1 !== null ? -_this2._getHeight(d, i) / 2 : 0;
}).call(this._applyStyle.bind(this));
var update = this._update;
if (this._duration) {
enter = enter.transition(this._transition);
update = update.transition(this._transition);
this._exit.transition(this._transition).attr("width", function (d, i) {
return _this2._x1 === null ? _this2._getWidth(d, i) : 0;
}).attr("height", function (d, i) {
return _this2._x1 !== null ? _this2._getHeight(d, i) : 0;
}).attr("x", function (d, i) {
return _this2._x1 === null ? -_this2._getWidth(d, i) / 2 : 0;
}).attr("y", function (d, i) {
return _this2._x1 !== null ? -_this2._getHeight(d, i) / 2 : 0;
});
}
enter.call(this._applyPosition.bind(this));
update.call(this._applyStyle.bind(this)).call(this._applyPosition.bind(this));
return this;
}
/**
@memberof Bar
@desc Given a specific data point and index, returns the aesthetic properties of the shape.
@param {Object} *data point*
@param {Number} *index*
@private
*/
}, {
key: "_aes",
value: function _aes(d, i) {
return {
height: this._getHeight(d, i),
width: this._getWidth(d, i)
};
}
/**
@memberof Bar
@desc Provides the default positioning to the <rect> elements.
@param {D3Selection} *elem*
@private
*/
}, {
key: "_applyPosition",
value: function _applyPosition(elem) {
var _this3 = this;
elem.attr("width", function (d, i) {
return _this3._getWidth(d, i);
}).attr("height", function (d, i) {
return _this3._getHeight(d, i);
}).attr("x", function (d, i) {
return _this3._x1 !== null ? _this3._getX(d, i) : -_this3._getWidth(d, i) / 2;
}).attr("y", function (d, i) {
return _this3._x1 === null ? _this3._getY(d, i) : -_this3._getHeight(d, i) / 2;
});
}
/**
@memberof Bar
@desc Calculates the height of the <rect> by assessing the x and y properties.
@param {Object} *d*
@param {Number} *i*
@private
*/
}, {
key: "_getHeight",
value: function _getHeight(d, i) {
if (this._x1 !== null) return this._height(d, i);
return Math.abs(this._y1(d, i) - this._y(d, i));
}
/**
@memberof Bar
@desc Calculates the width of the <rect> by assessing the x and y properties.
@param {Object} *d*
@param {Number} *i*
@private
*/
}, {
key: "_getWidth",
value: function _getWidth(d, i) {
if (this._x1 === null) return this._width(d, i);
return Math.abs(this._x1(d, i) - this._x(d, i));
}
/**
@memberof Bar
@desc Calculates the x of the <rect> by assessing the x and width properties.
@param {Object} *d*
@param {Number} *i*
@private
*/
}, {
key: "_getX",
value: function _getX(d, i) {
var w = this._x1 === null ? this._x(d, i) : this._x1(d, i) - this._x(d, i);
if (w < 0) return w;else return 0;
}
/**
@memberof Bar
@desc Calculates the y of the <rect> by assessing the y and height properties.
@param {Object} *d*
@param {Number} *i*
@private
*/
}, {
key: "_getY",
value: function _getY(d, i) {
var h = this._x1 !== null ? this._y(d, i) : this._y1(d, i) - this._y(d, i);
if (h < 0) return h;else return 0;
}
/**
@memberof Bar
@desc If *value* is specified, sets the height accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.height;
}
*/
}, {
key: "height",
value: function height(_) {
return arguments.length ? (this._height = typeof _ === "function" ? _ : constant$1(_), this) : this._height;
}
/**
@memberof Bar
@desc If *value* is specified, sets the width accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.width;
}
*/
}, {
key: "width",
value: function width(_) {
return arguments.length ? (this._width = typeof _ === "function" ? _ : constant$1(_), this) : this._width;
}
/**
@memberof Bar
@desc If *value* is specified, sets the x0 accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
*/
}, {
key: "x0",
value: function x0(_) {
if (!arguments.length) return this._x0;
this._x0 = typeof _ === "function" ? _ : constant$1(_);
this._x = this._x0;
return this;
}
/**
@memberof Bar
@desc If *value* is specified, sets the x1 accessor to the specified function or number and returns the current class instance.
@param {Function|Number|null} [*value*]
@chainable
*/
}, {
key: "x1",
value: function x1(_) {
return arguments.length ? (this._x1 = typeof _ === "function" || _ === null ? _ : constant$1(_), this) : this._x1;
}
/**
@memberof Bar
@desc If *value* is specified, sets the y0 accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
*/
}, {
key: "y0",
value: function y0(_) {
if (!arguments.length) return this._y0;
this._y0 = typeof _ === "function" ? _ : constant$1(_);
this._y = this._y0;
return this;
}
/**
@memberof Bar
@desc If *value* is specified, sets the y1 accessor to the specified function or number and returns the current class instance.
@param {Function|Number|null} [*value*]
@chainable
*/
}, {
key: "y1",
value: function y1(_) {
return arguments.length ? (this._y1 = typeof _ === "function" || _ === null ? _ : constant$1(_), this) : this._y1;
}
}]);
return Bar;
}(Shape);
function _typeof$7(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$7 = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$7 = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$7(obj);
}
function _classCallCheck$7(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$7(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$7(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$7(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$7(Constructor, staticProps);
return Constructor;
}
function _get$3(target, property, receiver) {
if (typeof Reflect !== "undefined" && Reflect.get) {
_get$3 = Reflect.get;
} else {
_get$3 = function _get(target, property, receiver) {
var base = _superPropBase$3(target, property);
if (!base) return;
var desc = Object.getOwnPropertyDescriptor(base, property);
if (desc.get) {
return desc.get.call(receiver);
}
return desc.value;
};
}
return _get$3(target, property, receiver || target);
}
function _superPropBase$3(object, property) {
while (!Object.prototype.hasOwnProperty.call(object, property)) {
object = _getPrototypeOf$5(object);
if (object === null) break;
}
return object;
}
function _inherits$5(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$5(subClass, superClass);
}
function _setPrototypeOf$5(o, p) {
_setPrototypeOf$5 = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$5(o, p);
}
function _createSuper$5(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$5();
return function _createSuperInternal() {
var Super = _getPrototypeOf$5(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$5(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$5(this, result);
};
}
function _possibleConstructorReturn$5(self, call) {
if (call && (_typeof$7(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$5(self);
}
function _assertThisInitialized$5(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$5() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$5(o) {
_getPrototypeOf$5 = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$5(o);
}
/**
@class Circle
@extends Shape
@desc Creates SVG circles based on an array of data.
*/
var Circle = /*#__PURE__*/function (_Shape) {
_inherits$5(Circle, _Shape);
var _super = _createSuper$5(Circle);
/**
@memberof Circle
@desc Invoked when creating a new class instance, and overrides any default parameters inherited from Shape.
@private
*/
function Circle() {
var _this;
_classCallCheck$7(this, Circle);
_this = _super.call(this, "circle");
_this._labelBounds = function (d, i, s) {
return {
width: s.r * 1.5,
height: s.r * 1.5,
x: -s.r * 0.75,
y: -s.r * 0.75
};
};
_this._labelConfig = assign(_this._labelConfig, {
textAnchor: "middle",
verticalAlign: "middle"
});
_this._name = "Circle";
_this._r = accessor("r");
return _this;
}
/**
@memberof Circle
@desc Provides the default positioning to the <rect> elements.
@private
*/
_createClass$7(Circle, [{
key: "_applyPosition",
value: function _applyPosition(elem) {
var _this2 = this;
elem.attr("r", function (d, i) {
return _this2._r(d, i);
}).attr("x", function (d, i) {
return -_this2._r(d, i) / 2;
}).attr("y", function (d, i) {
return -_this2._r(d, i) / 2;
});
}
/**
@memberof Circle
@desc Draws the circles.
@param {Function} [*callback*]
@chainable
*/
}, {
key: "render",
value: function render(callback) {
_get$3(_getPrototypeOf$5(Circle.prototype), "render", this).call(this, callback);
var enter = this._enter.call(this._applyStyle.bind(this));
var update = this._update;
if (this._duration) {
enter.attr("r", 0).attr("x", 0).attr("y", 0).transition(this._transition).call(this._applyPosition.bind(this));
update = update.transition(this._transition);
this._exit.transition(this._transition).attr("r", 0).attr("x", 0).attr("y", 0);
} else {
enter.call(this._applyPosition.bind(this));
}
update.call(this._applyStyle.bind(this)).call(this._applyPosition.bind(this));
return this;
}
/**
@memberof Circle
@desc Given a specific data point and index, returns the aesthetic properties of the shape.
@param {Object} *data point*
@param {Number} *index*
@private
*/
}, {
key: "_aes",
value: function _aes(d, i) {
return {
r: this._r(d, i)
};
}
/**
@memberof Circle
@desc If *value* is specified, sets the radius accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.r;
}
*/
}, {
key: "r",
value: function r(_) {
return arguments.length ? (this._r = typeof _ === "function" ? _ : constant$1(_), this) : this._r;
}
}]);
return Circle;
}(Shape);
function _typeof$8(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$8 = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$8 = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$8(obj);
}
function _classCallCheck$8(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$8(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$8(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$8(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$8(Constructor, staticProps);
return Constructor;
}
function _get$4(target, property, receiver) {
if (typeof Reflect !== "undefined" && Reflect.get) {
_get$4 = Reflect.get;
} else {
_get$4 = function _get(target, property, receiver) {
var base = _superPropBase$4(target, property);
if (!base) return;
var desc = Object.getOwnPropertyDescriptor(base, property);
if (desc.get) {
return desc.get.call(receiver);
}
return desc.value;
};
}
return _get$4(target, property, receiver || target);
}
function _superPropBase$4(object, property) {
while (!Object.prototype.hasOwnProperty.call(object, property)) {
object = _getPrototypeOf$6(object);
if (object === null) break;
}
return object;
}
function _inherits$6(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$6(subClass, superClass);
}
function _setPrototypeOf$6(o, p) {
_setPrototypeOf$6 = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$6(o, p);
}
function _createSuper$6(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$6();
return function _createSuperInternal() {
var Super = _getPrototypeOf$6(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$6(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$6(this, result);
};
}
function _possibleConstructorReturn$6(self, call) {
if (call && (_typeof$8(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$6(self);
}
function _assertThisInitialized$6(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$6() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$6(o) {
_getPrototypeOf$6 = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$6(o);
}
/**
@class Rect
@extends Shape
@desc Creates SVG rectangles based on an array of data. See [this example](https://d3plus.org/examples/d3plus-shape/getting-started/) for help getting started using the rectangle generator.
*/
var Rect = /*#__PURE__*/function (_Shape) {
_inherits$6(Rect, _Shape);
var _super = _createSuper$6(Rect);
/**
@memberof Rect
@desc Invoked when creating a new class instance, and overrides any default parameters inherited from Shape.
@private
*/
function Rect() {
var _this;
_classCallCheck$8(this, Rect);
_this = _super.call(this, "rect");
_this._height = accessor("height");
_this._labelBounds = function (d, i, s) {
return {
width: s.width,
height: s.height,
x: -s.width / 2,
y: -s.height / 2
};
};
_this._name = "Rect";
_this._width = accessor("width");
return _this;
}
/**
@memberof Rect
@desc Draws the rectangles.
@param {Function} [*callback*]
@chainable
*/
_createClass$8(Rect, [{
key: "render",
value: function render(callback) {
_get$4(_getPrototypeOf$6(Rect.prototype), "render", this).call(this, callback);
var enter = this._enter.attr("width", 0).attr("height", 0).attr("x", 0).attr("y", 0).call(this._applyStyle.bind(this));
var update = this._update;
if (this._duration) {
enter = enter.transition(this._transition);
update = update.transition(this._transition);
this._exit.transition(this._transition).attr("width", 0).attr("height", 0).attr("x", 0).attr("y", 0);
}
enter.call(this._applyPosition.bind(this));
update.call(this._applyStyle.bind(this)).call(this._applyPosition.bind(this));
return this;
}
/**
@memberof Rect
@desc Given a specific data point and index, returns the aesthetic properties of the shape.
@param {Object} *data point*
@param {Number} *index*
@private
*/
}, {
key: "_aes",
value: function _aes(d, i) {
return {
width: this._width(d, i),
height: this._height(d, i)
};
}
/**
@memberof Rect
@desc Provides the default positioning to the <rect> elements.
@param {D3Selection} *elem*
@private
*/
}, {
key: "_applyPosition",
value: function _applyPosition(elem) {
var _this2 = this;
elem.attr("width", function (d, i) {
return _this2._width(d, i);
}).attr("height", function (d, i) {
return _this2._height(d, i);
}).attr("x", function (d, i) {
return -_this2._width(d, i) / 2;
}).attr("y", function (d, i) {
return -_this2._height(d, i) / 2;
});
}
/**
@memberof Rect
@desc If *value* is specified, sets the height accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.height;
}
*/
}, {
key: "height",
value: function height(_) {
return arguments.length ? (this._height = typeof _ === "function" ? _ : constant$1(_), this) : this._height;
}
/**
@memberof Rect
@desc If *value* is specified, sets the width accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.width;
}
*/
}, {
key: "width",
value: function width(_) {
return arguments.length ? (this._width = typeof _ === "function" ? _ : constant$1(_), this) : this._width;
}
}]);
return Rect;
}(Shape);
function _typeof$9(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$9 = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$9 = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$9(obj);
}
function _classCallCheck$9(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$9(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$9(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$9(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$9(Constructor, staticProps);
return Constructor;
}
function _get$5(target, property, receiver) {
if (typeof Reflect !== "undefined" && Reflect.get) {
_get$5 = Reflect.get;
} else {
_get$5 = function _get(target, property, receiver) {
var base = _superPropBase$5(target, property);
if (!base) return;
var desc = Object.getOwnPropertyDescriptor(base, property);
if (desc.get) {
return desc.get.call(receiver);
}
return desc.value;
};
}
return _get$5(target, property, receiver || target);
}
function _superPropBase$5(object, property) {
while (!Object.prototype.hasOwnProperty.call(object, property)) {
object = _getPrototypeOf$7(object);
if (object === null) break;
}
return object;
}
function _inherits$7(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$7(subClass, superClass);
}
function _setPrototypeOf$7(o, p) {
_setPrototypeOf$7 = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$7(o, p);
}
function _createSuper$7(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$7();
return function _createSuperInternal() {
var Super = _getPrototypeOf$7(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$7(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$7(this, result);
};
}
function _possibleConstructorReturn$7(self, call) {
if (call && (_typeof$9(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$7(self);
}
function _assertThisInitialized$7(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$7() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$7(o) {
_getPrototypeOf$7 = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$7(o);
}
/**
@class Line
@extends Shape
@desc Creates SVG lines based on an array of data.
*/
var Line = /*#__PURE__*/function (_Shape) {
_inherits$7(Line, _Shape);
var _super = _createSuper$7(Line);
/**
@memberof Line
@desc Invoked when creating a new class instance, and overrides any default parameters inherited from Shape.
@private
*/
function Line() {
var _this;
_classCallCheck$9(this, Line);
_this = _super.call(this);
_this._curve = "linear";
_this._defined = function (d) {
return d;
};
_this._fill = constant$1("none");
_this._hitArea = constant$1({
"d": function d(_d) {
return _this._path(_d.values);
},
"fill": "none",
"stroke-width": 10,
"transform": null
});
_this._name = "Line";
_this._path = line();
_this._stroke = constant$1("black");
_this._strokeWidth = constant$1(1);
return _this;
}
/**
@memberof Line
@desc Filters/manipulates the data array before binding each point to an SVG group.
@param {Array} [*data* = the data array to be filtered]
@private
*/
_createClass$9(Line, [{
key: "_dataFilter",
value: function _dataFilter(data) {
var _this2 = this;
var lines = nest().key(this._id).entries(data).map(function (d) {
d.data = objectMerge(d.values);
d.i = data.indexOf(d.values[0]);
var x = extent(d.values, _this2._x);
d.xR = x;
d.width = x[1] - x[0];
d.x = x[0] + d.width / 2;
var y = extent(d.values, _this2._y);
d.yR = y;
d.height = y[1] - y[0];
d.y = y[0] + d.height / 2;
d.nested = true;
d.translate = [d.x, d.y];
d.__d3plusShape__ = true;
return d;
});
lines.key = function (d) {
return d.key;
};
return lines;
}
/**
@memberof Line
@desc Draws the lines.
@param {Function} [*callback*]
@chainable
*/
}, {
key: "render",
value: function render(callback) {
var _this3 = this;
_get$5(_getPrototypeOf$7(Line.prototype), "render", this).call(this, callback);
var that = this;
/**
@desc Calculates the stroke-dasharray used for animations
@param {Object} *d* data point
@private
*/
function calculateStrokeDashArray(d) {
d.initialLength = this.getTotalLength();
var strokeArray = that._strokeDasharray(d.values[0], that._data.indexOf(d.values[0])).split(" ").map(Number);
if (strokeArray.length === 1 && strokeArray[0] === 0) strokeArray = [d.initialLength];else if (strokeArray.length === 1) strokeArray.push(strokeArray[0]);else if (strokeArray.length % 2) strokeArray = strokeArray.concat(strokeArray);
var newStrokeArray = [];
var strokeLength = 0;
while (strokeLength < d.initialLength) {
for (var i = 0; i < strokeArray.length; i++) {
var num = strokeArray[i];
strokeLength += num;
newStrokeArray.push(num);
if (strokeLength >= d.initialLength) break;
}
}
if (newStrokeArray.length > 1 && newStrokeArray.length % 2) newStrokeArray.pop();
newStrokeArray[newStrokeArray.length - 1] += d.initialLength - sum(newStrokeArray);
if (newStrokeArray.length % 2 === 0) newStrokeArray.push(0);
d.initialStrokeArray = newStrokeArray.join(" ");
}
this._path.curve(paths["curve".concat(this._curve.charAt(0).toUpperCase()).concat(this._curve.slice(1))]).defined(this._defined).x(this._x).y(this._y);
var enter = this._enter.append("path").attr("transform", function (d) {
return "translate(".concat(-d.xR[0] - d.width / 2, ", ").concat(-d.yR[0] - d.height / 2, ")");
}).attr("d", function (d) {
return _this3._path(d.values);
}).call(this._applyStyle.bind(this));
var update = this._update.select("path").attr("stroke-dasharray", function (d) {
return that._strokeDasharray(d.values[0], that._data.indexOf(d.values[0]));
});
if (this._duration) {
enter.each(calculateStrokeDashArray).attr("stroke-dasharray", function (d) {
return "".concat(d.initialStrokeArray, " ").concat(d.initialLength);
}).attr("stroke-dashoffset", function (d) {
return d.initialLength;
}).transition(this._transition).attr("stroke-dashoffset", 0);
update = update.transition(this._transition).attrTween("d", function (d) {
return interpolatePath(_select(this).attr("d"), that._path(d.values));
});
this._exit.selectAll("path").each(calculateStrokeDashArray).attr("stroke-dasharray", function (d) {
return "".concat(d.initialStrokeArray, " ").concat(d.initialLength);
}).transition(this._transition).attr("stroke-dashoffset", function (d) {
return -d.initialLength;
});
} else {
update = update.attr("d", function (d) {
return that._path(d.values);
});
}
update.attr("transform", function (d) {
return "translate(".concat(-d.xR[0] - d.width / 2, ", ").concat(-d.yR[0] - d.height / 2, ")");
}).call(this._applyStyle.bind(this));
return this;
}
/**
@memberof Line
@desc Given a specific data point and index, returns the aesthetic properties of the shape.
@param {Object} *data point*
@param {Number} *index*
@private
*/
}, {
key: "_aes",
value: function _aes(d, i) {
var _this4 = this;
return {
points: d.values.map(function (p) {
return [_this4._x(p, i), _this4._y(p, i)];
})
};
}
/**
@memberof Line
@desc If *value* is specified, sets the line curve to the specified string and returns the current class instance. If *value* is not specified, returns the current line curve.
@param {String} [*value* = "linear"]
@chainable
*/
}, {
key: "curve",
value: function curve(_) {
return arguments.length ? (this._curve = _, this) : this._curve;
}
/**
@memberof Line
@desc If *value* is specified, sets the defined accessor to the specified function and returns the current class instance. If *value* is not specified, returns the current defined accessor.
@param {Function} [*value*]
@chainable
*/
}, {
key: "defined",
value: function defined(_) {
return arguments.length ? (this._defined = _, this) : this._defined;
}
}]);
return Line;
}(Shape);
function _typeof$a(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$a = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$a = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$a(obj);
}
function _classCallCheck$a(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$a(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$a(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$a(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$a(Constructor, staticProps);
return Constructor;
}
function _inherits$8(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$8(subClass, superClass);
}
function _setPrototypeOf$8(o, p) {
_setPrototypeOf$8 = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$8(o, p);
}
function _createSuper$8(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$8();
return function _createSuperInternal() {
var Super = _getPrototypeOf$8(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$8(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$8(this, result);
};
}
function _possibleConstructorReturn$8(self, call) {
if (call && (_typeof$a(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$8(self);
}
function _assertThisInitialized$8(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$8() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$8(o) {
_getPrototypeOf$8 = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$8(o);
}
var shapes = {
Circle: Circle,
Rect: Rect
};
/**
@class Whisker
@extends BaseClass
@desc Creates SVG whisker based on an array of data.
*/
var Whisker = /*#__PURE__*/function (_BaseClass) {
_inherits$8(Whisker, _BaseClass);
var _super = _createSuper$8(Whisker);
/**
@memberof Whisker
@desc Invoked when creating a new class instance, and overrides any default parameters inherited from BaseClass.
@private
*/
function Whisker() {
var _this;
_classCallCheck$a(this, Whisker);
_this = _super.call(this);
_this._endpoint = accessor("endpoint", "Rect");
_this._endpointConfig = {
Circle: {
r: accessor("r", 5)
}
};
_this._length = accessor("length", 25);
_this._lineConfig = {};
_this._orient = accessor("orient", "top");
_this._x = accessor("x", 0);
_this._y = accessor("y", 0);
return _this;
}
/**
@memberof Whisker
@desc Draws the whisker.
@param {Function} [*callback*]
@chainable
*/
_createClass$a(Whisker, [{
key: "render",
value: function render(callback) {
var _this2 = this;
if (this._select === void 0) {
this.select(_select("body").append("svg").style("width", "".concat(window.innerWidth, "px")).style("height", "".concat(window.innerHeight, "px")).style("display", "block").node());
}
var lineData = [];
this._data.forEach(function (d, i) {
var orient = _this2._orient(d, i);
var x = _this2._x(d, i);
var y = _this2._y(d, i);
var endpointX = x;
if (orient === "left") endpointX -= _this2._length(d, i);else if (orient === "right") endpointX += _this2._length(d, i);
var endpointY = y;
if (orient === "top") endpointY -= _this2._length(d, i);else if (orient === "bottom") endpointY += _this2._length(d, i);
lineData.push({
__d3plus__: true,
data: d,
i: i,
id: i,
x: x,
y: y
});
lineData.push({
__d3plus__: true,
data: d,
i: i,
id: i,
x: endpointX,
y: endpointY
});
}); // Draw whisker line.
this._line = new Line().data(lineData).select(elem("g.d3plus-Whisker", {
parent: this._select
}).node()).config(configPrep.bind(this)(this._lineConfig, "shape")).render(callback);
var whiskerData = this._data.map(function (d, i) {
var dataObj = {};
dataObj.__d3plus__ = true;
dataObj.data = d;
dataObj.i = i;
dataObj.endpoint = _this2._endpoint(d, i);
dataObj.length = _this2._length(d, i);
dataObj.orient = _this2._orient(d, i);
var endpointX = _this2._x(d, i);
if (dataObj.orient === "left") endpointX -= dataObj.length;else if (dataObj.orient === "right") endpointX += dataObj.length;
var endpointY = _this2._y(d, i);
if (dataObj.orient === "top") endpointY -= dataObj.length;else if (dataObj.orient === "bottom") endpointY += dataObj.length;
dataObj.x = endpointX;
dataObj.y = endpointY;
return dataObj;
}); // Draw whisker endpoint.
this._whiskerEndpoint = [];
nest().key(function (d) {
return d.endpoint;
}).entries(whiskerData).forEach(function (shapeData) {
var shapeName = shapeData.key;
_this2._whiskerEndpoint.push(new shapes[shapeName]().data(shapeData.values).select(elem("g.d3plus-Whisker-Endpoint-".concat(shapeName), {
parent: _this2._select
}).node()).config({
height: function height(d) {
return d.orient === "top" || d.orient === "bottom" ? 5 : 20;
},
width: function width(d) {
return d.orient === "top" || d.orient === "bottom" ? 20 : 5;
}
}).config(configPrep.bind(_this2)(_this2._endpointConfig, "shape", shapeName)).render());
});
return this;
}
/**
@memberof Whisker
@desc Sets the highlight accessor to the Shape class's active function.
@param {Function} [*value*]
@chainable
*/
}, {
key: "active",
value: function active(_) {
if (this._line) this._line.active(_);
if (this._whiskerEndpoint) this._whiskerEndpoint.forEach(function (endPoint) {
return endPoint.active(_);
});
}
/**
@memberof Whisker
@desc If *data* is specified, sets the data array to the specified array and returns the current class instance. If *data* is not specified, returns the current data array.
@param {Array} [*data* = []]
@chainable
*/
}, {
key: "data",
value: function data(_) {
return arguments.length ? (this._data = _, this) : this._data;
}
/**
@memberof Whisker
@desc If *value* is specified, sets the endpoint accessor to the specified function or string and returns the current class instance.
@param {Function|String}
@chainable
*/
}, {
key: "endpoint",
value: function endpoint(_) {
return arguments.length ? (this._endpoint = typeof _ === "function" ? _ : constant$1(_), this) : this._endpoint;
}
/**
@memberof Whisker
@desc If *value* is specified, sets the config method for each endpoint and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "endpointConfig",
value: function endpointConfig(_) {
return arguments.length ? (this._endpointConfig = assign(this._endpointConfig, _), this) : this._endpointConfig;
}
/**
@memberof Whisker
@desc Sets the highlight accessor to the Shape class's hover function.
@param {Function} [*value*]
@chainable
*/
}, {
key: "hover",
value: function hover(_) {
if (this._line) this._line.hover(_);
if (this._whiskerEndpoint) this._whiskerEndpoint.forEach(function (endPoint) {
return endPoint.hover(_);
});
}
/**
@memberof Whisker
@desc If *value* is specified, sets the length accessor for whisker and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
*/
}, {
key: "length",
value: function length(_) {
return arguments.length ? (this._length = typeof _ === "function" ? _ : constant$1(_), this) : this._length;
}
/**
@memberof Whisker
@desc If *value* is specified, sets the config method for line shape and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "lineConfig",
value: function lineConfig(_) {
return arguments.length ? (this._lineConfig = assign(this._lineConfig, _), this) : this._lineConfig;
}
/**
@memberof Whisker
@desc If *value* is specified, sets the orientation to the specified value. If *value* is not specified, returns the current orientation.
@param {Function|String} [*value* = "top"] Accepts "top", "right", "bottom" or "left"
@chainable
*/
}, {
key: "orient",
value: function orient(_) {
return arguments.length ? (this._orient = typeof _ === "function" ? _ : constant$1(_), this) : this._orient;
}
/**
@memberof Whisker
@desc If *selector* is specified, sets the SVG container element to the specified d3 selector or DOM element and returns the current class instance. If *selector* is not specified, returns the current SVG container element.
@param {String|HTMLElement} [*selector* = d3.select("body").append("svg")]
@chainable
*/
}, {
key: "select",
value: function select(_) {
return arguments.length ? (this._select = _select(_), this) : this._select;
}
/**
@memberof Whisker
@desc If *value* is specified, sets the x axis to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.x;
}
*/
}, {
key: "x",
value: function x(_) {
return arguments.length ? (this._x = typeof _ === "function" ? _ : constant$1(_), this) : this._x;
}
/**
@memberof Whisker
@desc If *value* is specified, sets the y axis to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.y;
}
*/
}, {
key: "y",
value: function y(_) {
return arguments.length ? (this._y = typeof _ === "function" ? _ : constant$1(_), this) : this._y;
}
}]);
return Whisker;
}(BaseClass);
function _typeof$b(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$b = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$b = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$b(obj);
}
function _classCallCheck$b(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$b(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$b(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$b(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$b(Constructor, staticProps);
return Constructor;
}
function _inherits$9(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$9(subClass, superClass);
}
function _setPrototypeOf$9(o, p) {
_setPrototypeOf$9 = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$9(o, p);
}
function _createSuper$9(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$9();
return function _createSuperInternal() {
var Super = _getPrototypeOf$9(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$9(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$9(this, result);
};
}
function _possibleConstructorReturn$9(self, call) {
if (call && (_typeof$b(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$9(self);
}
function _assertThisInitialized$9(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$9() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$9(o) {
_getPrototypeOf$9 = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$9(o);
}
var shapes$1 = {
Circle: Circle,
Rect: Rect
};
/**
@class Box
@extends BaseClass
@desc Creates SVG box based on an array of data.
*/
var Box = /*#__PURE__*/function (_BaseClass) {
_inherits$9(Box, _BaseClass);
var _super = _createSuper$9(Box);
/**
@memberof Box
@desc Invoked when creating a new class instance, and overrides any default parameters inherited from BaseClass.
@private
*/
function Box() {
var _this;
_classCallCheck$b(this, Box);
_this = _super.call(this);
_this._medianConfig = {
fill: constant$1("black")
};
_this._orient = accessor("orient", "vertical");
_this._outlier = accessor("outlier", "Circle");
_this._outlierConfig = {
Circle: {
r: accessor("r", 5)
},
Rect: {
height: function height(d, i) {
return _this._orient(d, i) === "vertical" ? 5 : 20;
},
width: function width(d, i) {
return _this._orient(d, i) === "vertical" ? 20 : 5;
}
}
};
_this._rectConfig = {
fill: constant$1("white"),
stroke: constant$1("black"),
strokeWidth: constant$1(1)
};
_this._rectWidth = constant$1(50);
_this._whiskerConfig = {};
_this._whiskerMode = ["tukey", "tukey"];
_this._x = accessor("x", 250);
_this._y = accessor("y", 250);
return _this;
}
/**
@memberof Box
@desc Draws the Box.
@param {Function} [*callback*]
@chainable
*/
_createClass$b(Box, [{
key: "render",
value: function render() {
var _this2 = this;
if (this._select === void 0) {
this.select(_select("body").append("svg").style("width", "".concat(window.innerWidth, "px")).style("height", "".concat(window.innerHeight, "px")).style("display", "block").node());
}
var outlierData = [];
var filteredData = nest().key(function (d, i) {
return _this2._orient(d, i) === "vertical" ? _this2._x(d, i) : _this2._y(d, i);
}).entries(this._data).map(function (d) {
d.data = objectMerge(d.values);
d.i = _this2._data.indexOf(d.values[0]);
d.orient = _this2._orient(d.data, d.i);
var values = d.values.map(d.orient === "vertical" ? _this2._y : _this2._x);
values.sort(function (a, b) {
return a - b;
});
d.first = quantile(values, 0.25);
d.median = quantile(values, 0.50);
d.third = quantile(values, 0.75);
var mode = _this2._whiskerMode;
if (mode[0] === "tukey") {
d.lowerLimit = d.first - (d.third - d.first) * 1.5;
if (d.lowerLimit < min(values)) d.lowerLimit = min(values);
} else if (mode[0] === "extent") d.lowerLimit = min(values);else if (typeof mode[0] === "number") d.lowerLimit = quantile(values, mode[0]);
if (mode[1] === "tukey") {
d.upperLimit = d.third + (d.third - d.first) * 1.5;
if (d.upperLimit > max(values)) d.upperLimit = max(values);
} else if (mode[1] === "extent") d.upperLimit = max(values);else if (typeof mode[1] === "number") d.upperLimit = quantile(values, mode[1]);
var rectLength = d.third - d.first; // Compute values for vertical orientation.
if (d.orient === "vertical") {
d.height = rectLength;
d.width = _this2._rectWidth(d.data, d.i);
d.x = _this2._x(d.data, d.i);
d.y = d.first + rectLength / 2;
} else if (d.orient === "horizontal") {
// Compute values for horizontal orientation.
d.height = _this2._rectWidth(d.data, d.i);
d.width = rectLength;
d.x = d.first + rectLength / 2;
d.y = _this2._y(d.data, d.i);
} // Compute data for outliers.
d.values.forEach(function (eachValue, index) {
var value = d.orient === "vertical" ? _this2._y(eachValue, index) : _this2._x(eachValue, index);
if (value < d.lowerLimit || value > d.upperLimit) {
var dataObj = {};
dataObj.__d3plus__ = true;
dataObj.data = eachValue;
dataObj.i = index;
dataObj.outlier = _this2._outlier(eachValue, index);
if (d.orient === "vertical") {
dataObj.x = d.x;
dataObj.y = value;
outlierData.push(dataObj);
} else if (d.orient === "horizontal") {
dataObj.y = d.y;
dataObj.x = value;
outlierData.push(dataObj);
}
}
});
d.__d3plus__ = true;
return d;
}); // Draw box.
this._box = new Rect().data(filteredData).x(function (d) {
return d.x;
}).y(function (d) {
return d.y;
}).select(elem("g.d3plus-Box", {
parent: this._select
}).node()).config(configPrep.bind(this)(this._rectConfig, "shape")).render(); // Draw median.
this._median = new Rect().data(filteredData).x(function (d) {
return d.orient === "vertical" ? d.x : d.median;
}).y(function (d) {
return d.orient === "vertical" ? d.median : d.y;
}).height(function (d) {
return d.orient === "vertical" ? 1 : d.height;
}).width(function (d) {
return d.orient === "vertical" ? d.width : 1;
}).select(elem("g.d3plus-Box-Median", {
parent: this._select
}).node()).config(configPrep.bind(this)(this._medianConfig, "shape")).render(); // Draw 2 lines using Whisker class.
// Construct coordinates for whisker startpoints and push it to the whiskerData.
var whiskerData = [];
filteredData.forEach(function (d, i) {
var x = d.x;
var y = d.y;
var topLength = d.first - d.lowerLimit;
var bottomLength = d.upperLimit - d.third;
if (d.orient === "vertical") {
var topY = y - d.height / 2;
var bottomY = y + d.height / 2;
whiskerData.push({
__d3plus__: true,
data: d,
i: i,
x: x,
y: topY,
length: topLength,
orient: "top"
}, {
__d3plus__: true,
data: d,
i: i,
x: x,
y: bottomY,
length: bottomLength,
orient: "bottom"
});
} else if (d.orient === "horizontal") {
var topX = x + d.width / 2;
var bottomX = x - d.width / 2;
whiskerData.push({
__d3plus__: true,
data: d,
i: i,
x: topX,
y: y,
length: bottomLength,
orient: "right"
}, {
__d3plus__: true,
data: d,
i: i,
x: bottomX,
y: y,
length: topLength,
orient: "left"
});
}
}); // Draw whiskers.
this._whisker = new Whisker().data(whiskerData).select(elem("g.d3plus-Box-Whisker", {
parent: this._select
}).node()).config(configPrep.bind(this)(this._whiskerConfig, "shape")).render(); // Draw outliers.
this._whiskerEndpoint = [];
nest().key(function (d) {
return d.outlier;
}).entries(outlierData).forEach(function (shapeData) {
var shapeName = shapeData.key;
_this2._whiskerEndpoint.push(new shapes$1[shapeName]().data(shapeData.values).select(elem("g.d3plus-Box-Outlier-".concat(shapeName), {
parent: _this2._select
}).node()).config(configPrep.bind(_this2)(_this2._outlierConfig, "shape", shapeName)).render());
});
return this;
}
/**
@memberof Box
@desc Sets the highlight accessor to the Shape class's active function.
@param {Function} [*value*]
@chainable
*/
}, {
key: "active",
value: function active(_) {
if (this._box) this._box.active(_);
if (this._median) this._median.active(_);
if (this._whisker) this._whisker.active(_);
if (this._whiskerEndpoint) this._whiskerEndpoint.forEach(function (endPoint) {
return endPoint.active(_);
});
}
/**
@memberof Box
@desc If *data* is specified, sets the data array to the specified array and returns the current class instance. If *data* is not specified, returns the current data array.
@param {Array} [*data* = []]
@chainable
*/
}, {
key: "data",
value: function data(_) {
return arguments.length ? (this._data = _, this) : this._data;
}
/**
@memberof Box
@desc Sets the highlight accessor to the Shape class's hover function.
@param {Function} [*value*]
@chainable
*/
}, {
key: "hover",
value: function hover(_) {
if (this._box) this._box.hover(_);
if (this._median) this._median.hover(_);
if (this._whisker) this._whisker.hover(_);
if (this._whiskerEndpoint) this._whiskerEndpoint.forEach(function (endPoint) {
return endPoint.hover(_);
});
}
/**
@memberof Box
@desc If *value* is specified, sets the config method for median and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "medianConfig",
value: function medianConfig(_) {
return arguments.length ? (this._medianConfig = assign(this._medianConfig, _), this) : this._medianConfig;
}
/**
@memberof Box
@desc If *value* is specified, sets the orientation to the specified value. If *value* is not specified, returns the current orientation.
@param {Function|String} [*value* = "vertical"] Accepts "vertical" or "horizontal"
@chainable
*/
}, {
key: "orient",
value: function orient(_) {
return arguments.length ? (this._orient = typeof _ === "function" ? _ : constant$1(_), this) : this._orient;
}
/**
@memberof Box
@desc If *value* is specified, sets the outlier accessor to the specified function or string and returns the current class instance.
@param {Function|String}
@chainable
*/
}, {
key: "outlier",
value: function outlier(_) {
return arguments.length ? (this._outlier = typeof _ === "function" ? _ : constant$1(_), this) : this._outlier;
}
/**
@memberof Box
@desc If *value* is specified, sets the config method for each outlier point and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "outlierConfig",
value: function outlierConfig(_) {
return arguments.length ? (this._outlierConfig = assign(this._outlierConfig, _), this) : this._outlierConfig;
}
/**
@memberof Box
@desc If *value* is specified, sets the config method for rect shape and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "rectConfig",
value: function rectConfig(_) {
return arguments.length ? (this._rectConfig = assign(this._rectConfig, _), this) : this._rectConfig;
}
/**
@memberof Box
@desc If *value* is specified, sets the width accessor to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.width;
}
*/
}, {
key: "rectWidth",
value: function rectWidth(_) {
return arguments.length ? (this._rectWidth = typeof _ === "function" ? _ : constant$1(_), this) : this._rectWidth;
}
/**
@memberof Box
@desc If *selector* is specified, sets the SVG container element to the specified d3 selector or DOM element and returns the current class instance. If *selector* is not specified, returns the current SVG container element.
@param {String|HTMLElement} [*selector* = d3.select("body").append("svg")]
@chainable
*/
}, {
key: "select",
value: function select(_) {
return arguments.length ? (this._select = _select(_), this) : this._select;
}
/**
@memberof Box
@desc If *value* is specified, sets the config method for whisker and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "whiskerConfig",
value: function whiskerConfig(_) {
return arguments.length ? (this._whiskerConfig = assign(this._whiskerConfig, _), this) : this._whiskerConfig;
}
/**
@memberof Box
@desc Determines the value used for each whisker. Can be passed a single value to apply for both whiskers, or an Array of 2 values for the lower and upper whiskers (in that order). Accepted values are `"tukey"`, `"extent"`, or a Number representing a quantile.
@param {String|Number|String[]|Number[]} [*value* = "tukey"]
@chainable
*/
}, {
key: "whiskerMode",
value: function whiskerMode(_) {
return arguments.length ? (this._whiskerMode = _ instanceof Array ? _ : [_, _], this) : this._whiskerMode;
}
/**
@memberof Box
@desc If *value* is specified, sets the x axis to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.x;
}
*/
}, {
key: "x",
value: function x(_) {
return arguments.length ? (this._x = typeof _ === "function" ? _ : accessor(_), this) : this._x;
}
/**
@memberof Box
@desc If *value* is specified, sets the y axis to the specified function or number and returns the current class instance.
@param {Function|Number} [*value*]
@chainable
@example
function(d) {
return d.y;
}
*/
}, {
key: "y",
value: function y(_) {
return arguments.length ? (this._y = typeof _ === "function" ? _ : accessor(_), this) : this._y;
}
}]);
return Box;
}(BaseClass);
var pi$2 = Math.PI;
/**
@function shapeEdgePoint
@desc Calculates the x/y position of a point at the edge of a shape, from the center of the shape, given a specified pixel distance and radian angle.
@param {Number} angle The angle, in radians, of the offset point.
@param {Number} distance The pixel distance away from the origin.
@returns {String} [shape = "circle"] The type of shape, which can be either "circle" or "square".
*/
var shapeEdgePoint = (function (angle, distance) {
var shape = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "circle";
if (angle < 0) angle = pi$2 * 2 + angle;
if (shape === "square") {
var diagonal = 45 * (pi$2 / 180);
var x = 0,
y = 0;
if (angle < pi$2 / 2) {
var tan = Math.tan(angle);
x += angle < diagonal ? distance : distance / tan;
y += angle < diagonal ? tan * distance : distance;
} else if (angle <= pi$2) {
var _tan = Math.tan(pi$2 - angle);
x -= angle < pi$2 - diagonal ? distance / _tan : distance;
y += angle < pi$2 - diagonal ? distance : _tan * distance;
} else if (angle < diagonal + pi$2) {
x -= distance;
y -= Math.tan(angle - pi$2) * distance;
} else if (angle < 3 * pi$2 / 2) {
x -= distance / Math.tan(angle - pi$2);
y -= distance;
} else if (angle < 2 * pi$2 - diagonal) {
x += distance / Math.tan(2 * pi$2 - angle);
y -= distance;
} else {
x += distance;
y -= Math.tan(2 * pi$2 - angle) * distance;
}
return [x, y];
} else if (shape === "circle") {
return [distance * Math.cos(angle), distance * Math.sin(angle)];
} else return null;
});
var pi$3 = Math.PI;
/**
@function path2polygon
@desc Transforms a path string into an Array of points.
@param {String} path An SVG string path, commonly the "d" property of a <path> element.
@param {Number} [segmentLength = 20] The lenght of line segments when converting curves line segments. Higher values lower computation time, but will result in curves that are more rigid.
@returns {Array}
*/
var path2polygon = (function (path) {
var segmentLength = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 20;
var poly = [],
regex = /([MLA])([^MLAZ]+)/ig;
var match = regex.exec(path);
while (match !== null) {
if (["M", "L"].includes(match[1])) poly.push(match[2].split(",").map(Number));else if (match[1] === "A") {
var points = match[2].split(",").map(Number);
var last = points.slice(points.length - 2, points.length),
prev = poly[poly.length - 1],
radius = points[0],
width = pointDistance(prev, last);
var angle = Math.acos((radius * radius + radius * radius - width * width) / (2 * radius * radius));
if (points[2]) angle = pi$3 * 2 - angle;
var step = angle / (angle / (pi$3 * 2) * (radius * pi$3 * 2) / segmentLength);
var start = Math.atan2(-prev[1], -prev[0]) - pi$3;
var i = step;
while (i < angle) {
poly.push(shapeEdgePoint(points[4] ? start + i : start - i, radius));
i += step;
}
poly.push(last);
}
match = regex.exec(path);
}
return poly;
});
function _typeof$c(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$c = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$c = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$c(obj);
}
function _classCallCheck$c(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$c(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$c(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$c(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$c(Constructor, staticProps);
return Constructor;
}
function _get$6(target, property, receiver) {
if (typeof Reflect !== "undefined" && Reflect.get) {
_get$6 = Reflect.get;
} else {
_get$6 = function _get(target, property, receiver) {
var base = _superPropBase$6(target, property);
if (!base) return;
var desc = Object.getOwnPropertyDescriptor(base, property);
if (desc.get) {
return desc.get.call(receiver);
}
return desc.value;
};
}
return _get$6(target, property, receiver || target);
}
function _superPropBase$6(object, property) {
while (!Object.prototype.hasOwnProperty.call(object, property)) {
object = _getPrototypeOf$a(object);
if (object === null) break;
}
return object;
}
function _inherits$a(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$a(subClass, superClass);
}
function _setPrototypeOf$a(o, p) {
_setPrototypeOf$a = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$a(o, p);
}
function _createSuper$a(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$a();
return function _createSuperInternal() {
var Super = _getPrototypeOf$a(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$a(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$a(this, result);
};
}
function _possibleConstructorReturn$a(self, call) {
if (call && (_typeof$c(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$a(self);
}
function _assertThisInitialized$a(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$a() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$a(o) {
_getPrototypeOf$a = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$a(o);
}
/**
@class Path
@extends Shape
@desc Creates SVG Paths based on an array of data.
*/
var Path$1 = /*#__PURE__*/function (_Shape) {
_inherits$a(Path, _Shape);
var _super = _createSuper$a(Path);
/**
@memberof Path
@desc Invoked when creating a new class instance, and overrides any default parameters inherited from Shape.
@private
*/
function Path() {
var _this;
_classCallCheck$c(this, Path);
_this = _super.call(this, "path");
_this._d = accessor("path");
_this._labelBounds = function (d, i, aes) {
var r = largestRect(aes.points, {
angle: _this._labelConfig.rotate ? _this._labelConfig.rotate(d, i) : 0
});
return r ? {
angle: r.angle,
width: r.width,
height: r.height,
x: r.cx - r.width / 2,
y: r.cy - r.height / 2
} : false;
};
_this._name = "Path";
_this._labelConfig = Object.assign(_this._labelConfig, {
textAnchor: "middle",
verticalAlign: "middle"
});
return _this;
}
/**
@memberof Path
@desc Given a specific data point and index, returns the aesthetic properties of the shape.
@param {Object} *data point*
@param {Number} *index*
@private
*/
_createClass$c(Path, [{
key: "_aes",
value: function _aes(d, i) {
return {
points: path2polygon(this._d(d, i))
};
}
/**
@memberof Path
@desc Draws the paths.
@param {Function} [*callback*]
@chainable
*/
}, {
key: "render",
value: function render(callback) {
_get$6(_getPrototypeOf$a(Path.prototype), "render", this).call(this, callback);
var enter = this._enter.attr("d", this._d).call(this._applyStyle.bind(this));
var update = this._update;
if (this._duration) {
enter.attr("opacity", 0).transition(this._transition).attr("opacity", 1);
update = update.transition(this._transition);
this._exit.transition(this._transition).attr("opacity", 0);
}
update.call(this._applyStyle.bind(this)).attr("d", this._d);
return this;
}
/**
@memberof Path
@desc If *value* is specified, sets the "d" attribute accessor to the specified function or number and returns the current class instance.
@param {Function|String} [*value*]
@chainable
@example
function(d) {
return d.path;
}
*/
}, {
key: "d",
value: function d(_) {
return arguments.length ? (this._d = typeof _ === "function" ? _ : constant$1(_), this) : this._d;
}
}]);
return Path;
}(Shape);
var shapes$2 = /*#__PURE__*/Object.freeze({
__proto__: null,
Image: Image$1,
Shape: Shape,
Area: Area,
Bar: Bar,
Box: Box,
Circle: Circle,
Line: Line,
Path: Path$1,
Rect: Rect,
Whisker: Whisker,
largestRect: largestRect,
lineIntersection: lineIntersection,
path2polygon: path2polygon,
pointDistance: pointDistance,
pointDistanceSquared: pointDistanceSquared,
pointRotate: pointRotate,
polygonInside: polygonInside,
polygonRayCast: polygonRayCast,
polygonRotate: polygonRotate,
segmentBoxContains: segmentBoxContains,
segmentsIntersect: segmentsIntersect,
shapeEdgePoint: shapeEdgePoint,
simplify: simplify
});
/**
@function dataConcat
@desc Reduce and concat all the elements included in arrayOfArrays if they are arrays. If it is a JSON object try to concat the array under given key data. If the key doesn't exists in object item, a warning message is lauched to the console. You need to implement DataFormat callback to concat the arrays manually.
@param {Array} arrayOfArray Array of elements
@param {String} [data = "data"] The key used for the flat data array if exists inside of the JSON object.
*/
var concat = (function (arrayOfArrays) {
var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "data";
return arrayOfArrays.reduce(function (acc, item) {
var dataArray = [];
if (Array.isArray(item)) {
dataArray = item;
} else {
if (item[data]) {
dataArray = item[data];
} else {
console.warn("d3plus-viz: Please implement a \"dataFormat\" callback to concat the arrays manually (consider using the d3plus.dataConcat method in your callback). Currently unable to concatenate (using key: \"".concat(data, "\") the following response:"), item);
}
}
return acc.concat(dataArray);
}, []);
});
/**
@function dataFold
@desc Given a JSON object where the data values and headers have been split into separate key lookups, this function will combine the data values with the headers and returns one large array of objects.
@param {Object} json A JSON data Object with `data` and `headers` keys.
@param {String} [data = "data"] The key used for the flat data array inside of the JSON object.
@param {String} [headers = "headers"] The key used for the flat headers array inside of the JSON object.
*/
var fold = (function (json) {
var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "data";
var headers = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "headers";
return json[data].map(function (data) {
return json[headers].reduce(function (obj, header, i) {
return obj[header] = data[i], obj;
}, {});
});
});
function request (url, callback) {
var request,
event = dispatch("beforesend", "progress", "load", "error"),
_mimeType,
headers = map(),
xhr = new XMLHttpRequest(),
_user = null,
_password = null,
_response,
_responseType,
_timeout = 0; // If IE does not support CORS, use XDomainRequest.
if (typeof XDomainRequest !== "undefined" && !("withCredentials" in xhr) && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest();
"onload" in xhr ? xhr.onload = xhr.onerror = xhr.ontimeout = respond : xhr.onreadystatechange = function (o) {
xhr.readyState > 3 && respond(o);
};
function respond(o) {
var status = xhr.status,
result;
if (!status && hasResponse(xhr) || status >= 200 && status < 300 || status === 304) {
if (_response) {
try {
result = _response.call(request, xhr);
} catch (e) {
event.call("error", request, e);
return;
}
} else {
result = xhr;
}
event.call("load", request, result);
} else {
event.call("error", request, o);
}
}
xhr.onprogress = function (e) {
event.call("progress", request, e);
};
request = {
header: function header(name, value) {
name = (name + "").toLowerCase();
if (arguments.length < 2) return headers.get(name);
if (value == null) headers.remove(name);else headers.set(name, value + "");
return request;
},
// If mimeType is non-null and no Accept header is set, a default is used.
mimeType: function mimeType(value) {
if (!arguments.length) return _mimeType;
_mimeType = value == null ? null : value + "";
return request;
},
// Specifies what type the response value should take;
// for instance, arraybuffer, blob, document, or text.
responseType: function responseType(value) {
if (!arguments.length) return _responseType;
_responseType = value;
return request;
},
timeout: function timeout(value) {
if (!arguments.length) return _timeout;
_timeout = +value;
return request;
},
user: function user(value) {
return arguments.length < 1 ? _user : (_user = value == null ? null : value + "", request);
},
password: function password(value) {
return arguments.length < 1 ? _password : (_password = value == null ? null : value + "", request);
},
// Specify how to convert the response content to a specific type;
// changes the callback value on "load" events.
response: function response(value) {
_response = value;
return request;
},
// Alias for send("GET", …).
get: function get(data, callback) {
return request.send("GET", data, callback);
},
// Alias for send("POST", …).
post: function post(data, callback) {
return request.send("POST", data, callback);
},
// If callback is non-null, it will be used for error and load events.
send: function send(method, data, callback) {
xhr.open(method, url, true, _user, _password);
if (_mimeType != null && !headers.has("accept")) headers.set("accept", _mimeType + ",*/*");
if (xhr.setRequestHeader) headers.each(function (value, name) {
xhr.setRequestHeader(name, value);
});
if (_mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(_mimeType);
if (_responseType != null) xhr.responseType = _responseType;
if (_timeout > 0) xhr.timeout = _timeout;
if (callback == null && typeof data === "function") callback = data, data = null;
if (callback != null && callback.length === 1) callback = fixCallback(callback);
if (callback != null) request.on("error", callback).on("load", function (xhr) {
callback(null, xhr);
});
event.call("beforesend", request, xhr);
xhr.send(data == null ? null : data);
return request;
},
abort: function abort() {
xhr.abort();
return request;
},
on: function on() {
var value = event.on.apply(event, arguments);
return value === event ? request : value;
}
};
if (callback != null) {
if (typeof callback !== "function") throw new Error("invalid callback: " + callback);
return request.get(callback);
}
return request;
}
function fixCallback(callback) {
return function (error, xhr) {
callback(error == null ? xhr : null);
};
}
function hasResponse(xhr) {
var type = xhr.responseType;
return type && type !== "text" ? xhr.response // null on error
: xhr.responseText; // "" on error
}
function type (defaultMimeType, response) {
return function (url, callback) {
var r = request(url).mimeType(defaultMimeType).response(response);
if (callback != null) {
if (typeof callback !== "function") throw new Error("invalid callback: " + callback);
return r.get(callback);
}
return r;
};
}
var json = type("application/json", function (xhr) {
return JSON.parse(xhr.responseText);
});
var text = type("text/plain", function (xhr) {
return xhr.responseText;
});
var EOL = {},
EOF = {},
QUOTE = 34,
NEWLINE = 10,
RETURN = 13;
function objectConverter(columns) {
return new Function("d", "return {" + columns.map(function (name, i) {
return JSON.stringify(name) + ": d[" + i + "] || \"\"";
}).join(",") + "}");
}
function customConverter(columns, f) {
var object = objectConverter(columns);
return function (row, i) {
return f(object(row), i, columns);
};
} // Compute unique columns in order of discovery.
function inferColumns(rows) {
var columnSet = Object.create(null),
columns = [];
rows.forEach(function (row) {
for (var column in row) {
if (!(column in columnSet)) {
columns.push(columnSet[column] = column);
}
}
});
return columns;
}
function pad$1(value, width) {
var s = value + "",
length = s.length;
return length < width ? new Array(width - length + 1).join(0) + s : s;
}
function formatYear$1(year) {
return year < 0 ? "-" + pad$1(-year, 6) : year > 9999 ? "+" + pad$1(year, 6) : pad$1(year, 4);
}
function formatDate(date) {
var hours = date.getUTCHours(),
minutes = date.getUTCMinutes(),
seconds = date.getUTCSeconds(),
milliseconds = date.getUTCMilliseconds();
return isNaN(date) ? "Invalid Date" : formatYear$1(date.getUTCFullYear()) + "-" + pad$1(date.getUTCMonth() + 1, 2) + "-" + pad$1(date.getUTCDate(), 2) + (milliseconds ? "T" + pad$1(hours, 2) + ":" + pad$1(minutes, 2) + ":" + pad$1(seconds, 2) + "." + pad$1(milliseconds, 3) + "Z" : seconds ? "T" + pad$1(hours, 2) + ":" + pad$1(minutes, 2) + ":" + pad$1(seconds, 2) + "Z" : minutes || hours ? "T" + pad$1(hours, 2) + ":" + pad$1(minutes, 2) + "Z" : "");
}
function dsv (delimiter) {
var reFormat = new RegExp("[\"" + delimiter + "\n\r]"),
DELIMITER = delimiter.charCodeAt(0);
function parse(text, f) {
var convert,
columns,
rows = parseRows(text, function (row, i) {
if (convert) return convert(row, i - 1);
columns = row, convert = f ? customConverter(row, f) : objectConverter(row);
});
rows.columns = columns || [];
return rows;
}
function parseRows(text, f) {
var rows = [],
// output rows
N = text.length,
I = 0,
// current character index
n = 0,
// current line number
t,
// current token
eof = N <= 0,
// current token followed by EOF?
eol = false; // current token followed by EOL?
// Strip the trailing newline.
if (text.charCodeAt(N - 1) === NEWLINE) --N;
if (text.charCodeAt(N - 1) === RETURN) --N;
function token() {
if (eof) return EOF;
if (eol) return eol = false, EOL; // Unescape quotes.
var i,
j = I,
c;
if (text.charCodeAt(j) === QUOTE) {
while (I++ < N && text.charCodeAt(I) !== QUOTE || text.charCodeAt(++I) === QUOTE) {
}
if ((i = I) >= N) eof = true;else if ((c = text.charCodeAt(I++)) === NEWLINE) eol = true;else if (c === RETURN) {
eol = true;
if (text.charCodeAt(I) === NEWLINE) ++I;
}
return text.slice(j + 1, i - 1).replace(/""/g, "\"");
} // Find next delimiter or newline.
while (I < N) {
if ((c = text.charCodeAt(i = I++)) === NEWLINE) eol = true;else if (c === RETURN) {
eol = true;
if (text.charCodeAt(I) === NEWLINE) ++I;
} else if (c !== DELIMITER) continue;
return text.slice(j, i);
} // Return last token before EOF.
return eof = true, text.slice(j, N);
}
while ((t = token()) !== EOF) {
var row = [];
while (t !== EOL && t !== EOF) {
row.push(t), t = token();
}
if (f && (row = f(row, n++)) == null) continue;
rows.push(row);
}
return rows;
}
function preformatBody(rows, columns) {
return rows.map(function (row) {
return columns.map(function (column) {
return formatValue(row[column]);
}).join(delimiter);
});
}
function format(rows, columns) {
if (columns == null) columns = inferColumns(rows);
return [columns.map(formatValue).join(delimiter)].concat(preformatBody(rows, columns)).join("\n");
}
function formatBody(rows, columns) {
if (columns == null) columns = inferColumns(rows);
return preformatBody(rows, columns).join("\n");
}
function formatRows(rows) {
return rows.map(formatRow).join("\n");
}
function formatRow(row) {
return row.map(formatValue).join(delimiter);
}
function formatValue(value) {
return value == null ? "" : value instanceof Date ? formatDate(value) : reFormat.test(value += "") ? "\"" + value.replace(/"/g, "\"\"") + "\"" : value;
}
return {
parse: parse,
parseRows: parseRows,
format: format,
formatBody: formatBody,
formatRows: formatRows,
formatRow: formatRow,
formatValue: formatValue
};
}
var csv = dsv(",");
var csvParse = csv.parse;
var tsv = dsv("\t");
var tsvParse = tsv.parse;
function dsv$1 (defaultMimeType, parse) {
return function (url, row, callback) {
if (arguments.length < 3) callback = row, row = null;
var r = request(url).mimeType(defaultMimeType);
r.row = function (_) {
return arguments.length ? r.response(responseOf(parse, row = _)) : row;
};
r.row(row);
return callback ? r.get(callback) : r;
};
}
function responseOf(parse, row) {
return function (request) {
return parse(request.responseText, row);
};
}
var csv$1 = dsv$1("text/csv", csvParse);
var tsv$1 = dsv$1("text/tab-separated-values", tsvParse);
function _typeof$d(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$d = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$d = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$d(obj);
}
/**
@function dataLoad
@desc Loads data from a filepath or URL, converts it to a valid JSON object, and returns it to a callback function.
@param {Array|String} path The path to the file or url to be loaded. Also support array of paths strings. If an Array of objects is passed, the xhr request logic is skipped.
@param {Function} [formatter] An optional formatter function that is run on the loaded data.
@param {String} [key] The key in the `this` context to save the resulting data to.
@param {Function} [callback] A function that is called when the final data is loaded. It is passed 2 variables, any error present and the data loaded.
*/
function load (path, formatter, key, callback) {
var _this = this;
var parser;
var getParser = function getParser(path) {
var ext = path.slice(path.length - 4);
switch (ext) {
case ".csv":
return csv$1;
case ".tsv":
return tsv$1;
case ".txt":
return text;
default:
return json;
}
};
var validateData = function validateData(err, parser, data) {
if (parser !== json && !err && data && data instanceof Array) {
data.forEach(function (d) {
for (var k in d) {
if (!isNaN(d[k])) d[k] = parseFloat(d[k]);else if (d[k].toLowerCase() === "false") d[k] = false;else if (d[k].toLowerCase() === "true") d[k] = true;else if (d[k].toLowerCase() === "null") d[k] = null;else if (d[k].toLowerCase() === "undefined") d[k] = undefined;
}
});
}
return data;
};
var loadedLength = function loadedLength(loadedArray) {
return loadedArray.reduce(function (prev, current) {
return current ? prev + 1 : prev;
}, 0);
};
var getPathIndex = function getPathIndex(url, array) {
return array.indexOf(url);
}; // If path param is a not an Array then convert path to a 1 element Array to re-use logic
if (!(path instanceof Array)) path = [path];
var isData = function isData(dataItem) {
return typeof dataItem === "string" || _typeof$d(dataItem) === "object" && dataItem.url && dataItem.headers;
};
var needToLoad = path.find(isData);
var loaded = new Array(path.length);
var toLoad = []; // If there is a string I'm assuming is a Array to merge, urls or data
if (needToLoad) {
path.forEach(function (dataItem, ix) {
if (isData(dataItem)) toLoad.push(dataItem);else loaded[ix] = dataItem;
});
} // Data array itself
else {
loaded[0] = path;
} // Load all urls an combine them with data arrays
var alreadyLoaded = loadedLength(loaded);
toLoad.forEach(function (dataItem) {
var headers = {},
url = dataItem;
if (_typeof$d(dataItem) === "object") {
url = dataItem.url;
headers = dataItem.headers;
}
parser = getParser(url);
var request = parser(url);
for (var _key in headers) {
if ({}.hasOwnProperty.call(headers, _key)) {
request.header(_key, headers[_key]);
}
}
request.get(function (err, data) {
data = err ? [] : data;
if (data && !(data instanceof Array) && data.data && data.headers) data = fold(data);
data = validateData(err, parser, data);
loaded[getPathIndex(url, path)] = data;
if (loadedLength(loaded) - alreadyLoaded === toLoad.length) {
// All urls loaded
// Format data
data = loadedLength(loaded) === 1 ? loaded[0] : loaded;
if (_this._cache) _this._lrucache.set("".concat(key, "_").concat(url), data);
if (formatter) {
data = formatter(loadedLength(loaded) === 1 ? loaded[0] : loaded);
} else if (key === "data") {
data = concat(loaded, "data");
}
if (key && "_".concat(key) in _this) _this["_".concat(key)] = data;
if (callback) callback(err, data);
}
});
}); // If there is no data to Load response is immediately
if (toLoad.length === 0) {
loaded = loaded.map(function (data) {
if (data && !(data instanceof Array) && data.data && data.headers) data = fold(data);
return data;
}); // Format data
var data = loadedLength(loaded) === 1 ? loaded[0] : loaded;
if (formatter) {
data = formatter(loadedLength(loaded) === 1 ? loaded[0] : loaded);
} else if (key === "data") {
data = concat(loaded, "data");
}
if (key && "_".concat(key) in this) this["_".concat(key)] = data;
if (callback) callback(null, data);
}
}
function noevent () {
event$1.preventDefault();
event$1.stopImmediatePropagation();
}
function dragDisable (view) {
var root = view.document.documentElement,
selection = _select(view).on("dragstart.drag", noevent, true);
if ("onselectstart" in root) {
selection.on("selectstart.drag", noevent, true);
} else {
root.__noselect = root.style.MozUserSelect;
root.style.MozUserSelect = "none";
}
}
function yesdrag(view, noclick) {
var root = view.document.documentElement,
selection = _select(view).on("dragstart.drag", null);
if (noclick) {
selection.on("click.drag", noevent, true);
setTimeout(function () {
selection.on("click.drag", null);
}, 0);
}
if ("onselectstart" in root) {
selection.on("selectstart.drag", null);
} else {
root.style.MozUserSelect = root.__noselect;
delete root.__noselect;
}
}
function constant$5 (x) {
return function () {
return x;
};
}
function BrushEvent (target, type, selection) {
this.target = target;
this.type = type;
this.selection = selection;
}
function nopropagation() {
event$1.stopImmediatePropagation();
}
function noevent$1 () {
event$1.preventDefault();
event$1.stopImmediatePropagation();
}
var MODE_DRAG = {
name: "drag"
},
MODE_SPACE = {
name: "space"
},
MODE_HANDLE = {
name: "handle"
},
MODE_CENTER = {
name: "center"
};
function number1(e) {
return [+e[0], +e[1]];
}
function number2(e) {
return [number1(e[0]), number1(e[1])];
}
function toucher(identifier) {
return function (target) {
return touch(target, event$1.touches, identifier);
};
}
var X = {
name: "x",
handles: ["w", "e"].map(type$1),
input: function input(x, e) {
return x == null ? null : [[+x[0], e[0][1]], [+x[1], e[1][1]]];
},
output: function output(xy) {
return xy && [xy[0][0], xy[1][0]];
}
};
var Y = {
name: "y",
handles: ["n", "s"].map(type$1),
input: function input(y, e) {
return y == null ? null : [[e[0][0], +y[0]], [e[1][0], +y[1]]];
},
output: function output(xy) {
return xy && [xy[0][1], xy[1][1]];
}
};
var XY = {
name: "xy",
handles: ["n", "w", "e", "s", "nw", "ne", "sw", "se"].map(type$1),
input: function input(xy) {
return xy == null ? null : number2(xy);
},
output: function output(xy) {
return xy;
}
};
var cursors = {
overlay: "crosshair",
selection: "move",
n: "ns-resize",
e: "ew-resize",
s: "ns-resize",
w: "ew-resize",
nw: "nwse-resize",
ne: "nesw-resize",
se: "nwse-resize",
sw: "nesw-resize"
};
var flipX = {
e: "w",
w: "e",
nw: "ne",
ne: "nw",
se: "sw",
sw: "se"
};
var flipY = {
n: "s",
s: "n",
nw: "sw",
ne: "se",
se: "ne",
sw: "nw"
};
var signsX = {
overlay: +1,
selection: +1,
n: null,
e: +1,
s: null,
w: -1,
nw: -1,
ne: +1,
se: +1,
sw: -1
};
var signsY = {
overlay: +1,
selection: +1,
n: -1,
e: null,
s: +1,
w: null,
nw: -1,
ne: -1,
se: +1,
sw: +1
};
function type$1(t) {
return {
type: t
};
} // Ignore right-click, since that should open the context menu.
function defaultFilter() {
return !event$1.ctrlKey && !event$1.button;
}
function defaultExtent() {
var svg = this.ownerSVGElement || this;
if (svg.hasAttribute("viewBox")) {
svg = svg.viewBox.baseVal;
return [[svg.x, svg.y], [svg.x + svg.width, svg.y + svg.height]];
}
return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]];
}
function defaultTouchable() {
return navigator.maxTouchPoints || "ontouchstart" in this;
} // Like d3.local, but with the name “__brush” rather than auto-generated.
function local(node) {
while (!node.__brush) {
if (!(node = node.parentNode)) return;
}
return node.__brush;
}
function empty$1(extent) {
return extent[0][0] === extent[1][0] || extent[0][1] === extent[1][1];
}
function brushX() {
return brush$1(X);
}
function brush () {
return brush$1(XY);
}
function brush$1(dim) {
var extent = defaultExtent,
filter = defaultFilter,
touchable = defaultTouchable,
keys = true,
listeners = dispatch("start", "brush", "end"),
handleSize = 6,
touchending;
function brush(group) {
var overlay = group.property("__brush", initialize).selectAll(".overlay").data([type$1("overlay")]);
overlay.enter().append("rect").attr("class", "overlay").attr("pointer-events", "all").attr("cursor", cursors.overlay).merge(overlay).each(function () {
var extent = local(this).extent;
_select(this).attr("x", extent[0][0]).attr("y", extent[0][1]).attr("width", extent[1][0] - extent[0][0]).attr("height", extent[1][1] - extent[0][1]);
});
group.selectAll(".selection").data([type$1("selection")]).enter().append("rect").attr("class", "selection").attr("cursor", cursors.selection).attr("fill", "#777").attr("fill-opacity", 0.3).attr("stroke", "#fff").attr("shape-rendering", "crispEdges");
var handle = group.selectAll(".handle").data(dim.handles, function (d) {
return d.type;
});
handle.exit().remove();
handle.enter().append("rect").attr("class", function (d) {
return "handle handle--" + d.type;
}).attr("cursor", function (d) {
return cursors[d.type];
});
group.each(redraw).attr("fill", "none").attr("pointer-events", "all").on("mousedown.brush", started).filter(touchable).on("touchstart.brush", started).on("touchmove.brush", touchmoved).on("touchend.brush touchcancel.brush", touchended).style("touch-action", "none").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
}
brush.move = function (group, selection) {
if (group.selection) {
group.on("start.brush", function () {
emitter(this, arguments).beforestart().start();
}).on("interrupt.brush end.brush", function () {
emitter(this, arguments).end();
}).tween("brush", function () {
var that = this,
state = that.__brush,
emit = emitter(that, arguments),
selection0 = state.selection,
selection1 = dim.input(typeof selection === "function" ? selection.apply(this, arguments) : selection, state.extent),
i = interpolate(selection0, selection1);
function tween(t) {
state.selection = t === 1 && selection1 === null ? null : i(t);
redraw.call(that);
emit.brush();
}
return selection0 !== null && selection1 !== null ? tween : tween(1);
});
} else {
group.each(function () {
var that = this,
args = arguments,
state = that.__brush,
selection1 = dim.input(typeof selection === "function" ? selection.apply(that, args) : selection, state.extent),
emit = emitter(that, args).beforestart();
interrupt(that);
state.selection = selection1 === null ? null : selection1;
redraw.call(that);
emit.start().brush().end();
});
}
};
brush.clear = function (group) {
brush.move(group, null);
};
function redraw() {
var group = _select(this),
selection = local(this).selection;
if (selection) {
group.selectAll(".selection").style("display", null).attr("x", selection[0][0]).attr("y", selection[0][1]).attr("width", selection[1][0] - selection[0][0]).attr("height", selection[1][1] - selection[0][1]);
group.selectAll(".handle").style("display", null).attr("x", function (d) {
return d.type[d.type.length - 1] === "e" ? selection[1][0] - handleSize / 2 : selection[0][0] - handleSize / 2;
}).attr("y", function (d) {
return d.type[0] === "s" ? selection[1][1] - handleSize / 2 : selection[0][1] - handleSize / 2;
}).attr("width", function (d) {
return d.type === "n" || d.type === "s" ? selection[1][0] - selection[0][0] + handleSize : handleSize;
}).attr("height", function (d) {
return d.type === "e" || d.type === "w" ? selection[1][1] - selection[0][1] + handleSize : handleSize;
});
} else {
group.selectAll(".selection,.handle").style("display", "none").attr("x", null).attr("y", null).attr("width", null).attr("height", null);
}
}
function emitter(that, args, clean) {
return !clean && that.__brush.emitter || new Emitter(that, args);
}
function Emitter(that, args) {
this.that = that;
this.args = args;
this.state = that.__brush;
this.active = 0;
}
Emitter.prototype = {
beforestart: function beforestart() {
if (++this.active === 1) this.state.emitter = this, this.starting = true;
return this;
},
start: function start() {
if (this.starting) this.starting = false, this.emit("start");else this.emit("brush");
return this;
},
brush: function brush() {
this.emit("brush");
return this;
},
end: function end() {
if (--this.active === 0) delete this.state.emitter, this.emit("end");
return this;
},
emit: function emit(type) {
customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]);
}
};
function started() {
if (touchending && !event$1.touches) return;
if (!filter.apply(this, arguments)) return;
var that = this,
type = event$1.target.__data__.type,
mode = (keys && event$1.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : keys && event$1.altKey ? MODE_CENTER : MODE_HANDLE,
signX = dim === Y ? null : signsX[type],
signY = dim === X ? null : signsY[type],
state = local(that),
extent = state.extent,
selection = state.selection,
W = extent[0][0],
w0,
w1,
N = extent[0][1],
n0,
n1,
E = extent[1][0],
e0,
e1,
S = extent[1][1],
s0,
s1,
dx = 0,
dy = 0,
moving,
shifting = signX && signY && keys && event$1.shiftKey,
lockX,
lockY,
pointer = event$1.touches ? toucher(event$1.changedTouches[0].identifier) : mouse,
point0 = pointer(that),
point = point0,
emit = emitter(that, arguments, true).beforestart();
if (type === "overlay") {
if (selection) moving = true;
state.selection = selection = [[w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]], [e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0]];
} else {
w0 = selection[0][0];
n0 = selection[0][1];
e0 = selection[1][0];
s0 = selection[1][1];
}
w1 = w0;
n1 = n0;
e1 = e0;
s1 = s0;
var group = _select(that).attr("pointer-events", "none");
var overlay = group.selectAll(".overlay").attr("cursor", cursors[type]);
if (event$1.touches) {
emit.moved = moved;
emit.ended = ended;
} else {
var view = _select(event$1.view).on("mousemove.brush", moved, true).on("mouseup.brush", ended, true);
if (keys) view.on("keydown.brush", keydowned, true).on("keyup.brush", keyupped, true);
dragDisable(event$1.view);
}
nopropagation();
interrupt(that);
redraw.call(that);
emit.start();
function moved() {
var point1 = pointer(that);
if (shifting && !lockX && !lockY) {
if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true;else lockX = true;
}
point = point1;
moving = true;
noevent$1();
move();
}
function move() {
var t;
dx = point[0] - point0[0];
dy = point[1] - point0[1];
switch (mode) {
case MODE_SPACE:
case MODE_DRAG:
{
if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx;
if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy;
break;
}
case MODE_HANDLE:
{
if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0;else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx;
if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0;else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy;
break;
}
case MODE_CENTER:
{
if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX));
if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY));
break;
}
}
if (e1 < w1) {
signX *= -1;
t = w0, w0 = e0, e0 = t;
t = w1, w1 = e1, e1 = t;
if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]);
}
if (s1 < n1) {
signY *= -1;
t = n0, n0 = s0, s0 = t;
t = n1, n1 = s1, s1 = t;
if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]);
}
if (state.selection) selection = state.selection; // May be set by brush.move!
if (lockX) w1 = selection[0][0], e1 = selection[1][0];
if (lockY) n1 = selection[0][1], s1 = selection[1][1];
if (selection[0][0] !== w1 || selection[0][1] !== n1 || selection[1][0] !== e1 || selection[1][1] !== s1) {
state.selection = [[w1, n1], [e1, s1]];
redraw.call(that);
emit.brush();
}
}
function ended() {
nopropagation();
if (event$1.touches) {
if (event$1.touches.length) return;
if (touchending) clearTimeout(touchending);
touchending = setTimeout(function () {
touchending = null;
}, 500); // Ghost clicks are delayed!
} else {
yesdrag(event$1.view, moving);
view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null);
}
group.attr("pointer-events", "all");
overlay.attr("cursor", cursors.overlay);
if (state.selection) selection = state.selection; // May be set by brush.move (on start)!
if (empty$1(selection)) state.selection = null, redraw.call(that);
emit.end();
}
function keydowned() {
switch (event$1.keyCode) {
case 16:
{
// SHIFT
shifting = signX && signY;
break;
}
case 18:
{
// ALT
if (mode === MODE_HANDLE) {
if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
mode = MODE_CENTER;
move();
}
break;
}
case 32:
{
// SPACE; takes priority over ALT
if (mode === MODE_HANDLE || mode === MODE_CENTER) {
if (signX < 0) e0 = e1 - dx;else if (signX > 0) w0 = w1 - dx;
if (signY < 0) s0 = s1 - dy;else if (signY > 0) n0 = n1 - dy;
mode = MODE_SPACE;
overlay.attr("cursor", cursors.selection);
move();
}
break;
}
default:
return;
}
noevent$1();
}
function keyupped() {
switch (event$1.keyCode) {
case 16:
{
// SHIFT
if (shifting) {
lockX = lockY = shifting = false;
move();
}
break;
}
case 18:
{
// ALT
if (mode === MODE_CENTER) {
if (signX < 0) e0 = e1;else if (signX > 0) w0 = w1;
if (signY < 0) s0 = s1;else if (signY > 0) n0 = n1;
mode = MODE_HANDLE;
move();
}
break;
}
case 32:
{
// SPACE
if (mode === MODE_SPACE) {
if (event$1.altKey) {
if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
mode = MODE_CENTER;
} else {
if (signX < 0) e0 = e1;else if (signX > 0) w0 = w1;
if (signY < 0) s0 = s1;else if (signY > 0) n0 = n1;
mode = MODE_HANDLE;
}
overlay.attr("cursor", cursors[type]);
move();
}
break;
}
default:
return;
}
noevent$1();
}
}
function touchmoved() {
emitter(this, arguments).moved();
}
function touchended() {
emitter(this, arguments).ended();
}
function initialize() {
var state = this.__brush || {
selection: null
};
state.extent = number2(extent.apply(this, arguments));
state.dim = dim;
return state;
}
brush.extent = function (_) {
return arguments.length ? (extent = typeof _ === "function" ? _ : constant$5(number2(_)), brush) : extent;
};
brush.filter = function (_) {
return arguments.length ? (filter = typeof _ === "function" ? _ : constant$5(!!_), brush) : filter;
};
brush.touchable = function (_) {
return arguments.length ? (touchable = typeof _ === "function" ? _ : constant$5(!!_), brush) : touchable;
};
brush.handleSize = function (_) {
return arguments.length ? (handleSize = +_, brush) : handleSize;
};
brush.keyModifiers = function (_) {
return arguments.length ? (keys = !!_, brush) : keys;
};
brush.on = function () {
var value = listeners.on.apply(listeners, arguments);
return value === listeners ? brush : value;
};
return brush;
}
function define$3 (constructor, factory, prototype) {
constructor.prototype = factory.prototype = prototype;
prototype.constructor = constructor;
}
function extend$4(parent, definition) {
var prototype = Object.create(parent.prototype);
for (var key in definition) {
prototype[key] = definition[key];
}
return prototype;
}
function Color$3() {}
var _darker$3 = 0.7;
var _brighter$3 = 1 / _darker$3;
var reI$3 = "\\s*([+-]?\\d+)\\s*",
reN$3 = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",
reP$3 = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
reHex$2 = /^#([0-9a-f]{3,8})$/,
reRgbInteger$3 = new RegExp("^rgb\\(" + [reI$3, reI$3, reI$3] + "\\)$"),
reRgbPercent$3 = new RegExp("^rgb\\(" + [reP$3, reP$3, reP$3] + "\\)$"),
reRgbaInteger$3 = new RegExp("^rgba\\(" + [reI$3, reI$3, reI$3, reN$3] + "\\)$"),
reRgbaPercent$3 = new RegExp("^rgba\\(" + [reP$3, reP$3, reP$3, reN$3] + "\\)$"),
reHslPercent$3 = new RegExp("^hsl\\(" + [reN$3, reP$3, reP$3] + "\\)$"),
reHslaPercent$3 = new RegExp("^hsla\\(" + [reN$3, reP$3, reP$3, reN$3] + "\\)$");
var named$3 = {
aliceblue: 0xf0f8ff,
antiquewhite: 0xfaebd7,
aqua: 0x00ffff,
aquamarine: 0x7fffd4,
azure: 0xf0ffff,
beige: 0xf5f5dc,
bisque: 0xffe4c4,
black: 0x000000,
blanchedalmond: 0xffebcd,
blue: 0x0000ff,
blueviolet: 0x8a2be2,
brown: 0xa52a2a,
burlywood: 0xdeb887,
cadetblue: 0x5f9ea0,
chartreuse: 0x7fff00,
chocolate: 0xd2691e,
coral: 0xff7f50,
cornflowerblue: 0x6495ed,
cornsilk: 0xfff8dc,
crimson: 0xdc143c,
cyan: 0x00ffff,
darkblue: 0x00008b,
darkcyan: 0x008b8b,
darkgoldenrod: 0xb8860b,
darkgray: 0xa9a9a9,
darkgreen: 0x006400,
darkgrey: 0xa9a9a9,
darkkhaki: 0xbdb76b,
darkmagenta: 0x8b008b,
darkolivegreen: 0x556b2f,
darkorange: 0xff8c00,
darkorchid: 0x9932cc,
darkred: 0x8b0000,
darksalmon: 0xe9967a,
darkseagreen: 0x8fbc8f,
darkslateblue: 0x483d8b,
darkslategray: 0x2f4f4f,
darkslategrey: 0x2f4f4f,
darkturquoise: 0x00ced1,
darkviolet: 0x9400d3,
deeppink: 0xff1493,
deepskyblue: 0x00bfff,
dimgray: 0x696969,
dimgrey: 0x696969,
dodgerblue: 0x1e90ff,
firebrick: 0xb22222,
floralwhite: 0xfffaf0,
forestgreen: 0x228b22,
fuchsia: 0xff00ff,
gainsboro: 0xdcdcdc,
ghostwhite: 0xf8f8ff,
gold: 0xffd700,
goldenrod: 0xdaa520,
gray: 0x808080,
green: 0x008000,
greenyellow: 0xadff2f,
grey: 0x808080,
honeydew: 0xf0fff0,
hotpink: 0xff69b4,
indianred: 0xcd5c5c,
indigo: 0x4b0082,
ivory: 0xfffff0,
khaki: 0xf0e68c,
lavender: 0xe6e6fa,
lavenderblush: 0xfff0f5,
lawngreen: 0x7cfc00,
lemonchiffon: 0xfffacd,
lightblue: 0xadd8e6,
lightcoral: 0xf08080,
lightcyan: 0xe0ffff,
lightgoldenrodyellow: 0xfafad2,
lightgray: 0xd3d3d3,
lightgreen: 0x90ee90,
lightgrey: 0xd3d3d3,
lightpink: 0xffb6c1,
lightsalmon: 0xffa07a,
lightseagreen: 0x20b2aa,
lightskyblue: 0x87cefa,
lightslategray: 0x778899,
lightslategrey: 0x778899,
lightsteelblue: 0xb0c4de,
lightyellow: 0xffffe0,
lime: 0x00ff00,
limegreen: 0x32cd32,
linen: 0xfaf0e6,
magenta: 0xff00ff,
maroon: 0x800000,
mediumaquamarine: 0x66cdaa,
mediumblue: 0x0000cd,
mediumorchid: 0xba55d3,
mediumpurple: 0x9370db,
mediumseagreen: 0x3cb371,
mediumslateblue: 0x7b68ee,
mediumspringgreen: 0x00fa9a,
mediumturquoise: 0x48d1cc,
mediumvioletred: 0xc71585,
midnightblue: 0x191970,
mintcream: 0xf5fffa,
mistyrose: 0xffe4e1,
moccasin: 0xffe4b5,
navajowhite: 0xffdead,
navy: 0x000080,
oldlace: 0xfdf5e6,
olive: 0x808000,
olivedrab: 0x6b8e23,
orange: 0xffa500,
orangered: 0xff4500,
orchid: 0xda70d6,
palegoldenrod: 0xeee8aa,
palegreen: 0x98fb98,
paleturquoise: 0xafeeee,
palevioletred: 0xdb7093,
papayawhip: 0xffefd5,
peachpuff: 0xffdab9,
peru: 0xcd853f,
pink: 0xffc0cb,
plum: 0xdda0dd,
powderblue: 0xb0e0e6,
purple: 0x800080,
rebeccapurple: 0x663399,
red: 0xff0000,
rosybrown: 0xbc8f8f,
royalblue: 0x4169e1,
saddlebrown: 0x8b4513,
salmon: 0xfa8072,
sandybrown: 0xf4a460,
seagreen: 0x2e8b57,
seashell: 0xfff5ee,
sienna: 0xa0522d,
silver: 0xc0c0c0,
skyblue: 0x87ceeb,
slateblue: 0x6a5acd,
slategray: 0x708090,
slategrey: 0x708090,
snow: 0xfffafa,
springgreen: 0x00ff7f,
steelblue: 0x4682b4,
tan: 0xd2b48c,
teal: 0x008080,
thistle: 0xd8bfd8,
tomato: 0xff6347,
turquoise: 0x40e0d0,
violet: 0xee82ee,
wheat: 0xf5deb3,
white: 0xffffff,
whitesmoke: 0xf5f5f5,
yellow: 0xffff00,
yellowgreen: 0x9acd32
};
define$3(Color$3, color$3, {
copy: function copy(channels) {
return Object.assign(new this.constructor(), this, channels);
},
displayable: function displayable() {
return this.rgb().displayable();
},
hex: color_formatHex$2,
// Deprecated! Use color.formatHex.
formatHex: color_formatHex$2,
formatHsl: color_formatHsl$2,
formatRgb: color_formatRgb$2,
toString: color_formatRgb$2
});
function color_formatHex$2() {
return this.rgb().formatHex();
}
function color_formatHsl$2() {
return hslConvert$3(this).formatHsl();
}
function color_formatRgb$2() {
return this.rgb().formatRgb();
}
function color$3(format) {
var m, l;
format = (format + "").trim().toLowerCase();
return (m = reHex$2.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn$3(m) // #ff0000
: l === 3 ? new Rgb$3(m >> 8 & 0xf | m >> 4 & 0xf0, m >> 4 & 0xf | m & 0xf0, (m & 0xf) << 4 | m & 0xf, 1) // #f00
: l === 8 ? rgba$3(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000
: l === 4 ? rgba$3(m >> 12 & 0xf | m >> 8 & 0xf0, m >> 8 & 0xf | m >> 4 & 0xf0, m >> 4 & 0xf | m & 0xf0, ((m & 0xf) << 4 | m & 0xf) / 0xff) // #f000
: null // invalid hex
) : (m = reRgbInteger$3.exec(format)) ? new Rgb$3(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
: (m = reRgbPercent$3.exec(format)) ? new Rgb$3(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
: (m = reRgbaInteger$3.exec(format)) ? rgba$3(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
: (m = reRgbaPercent$3.exec(format)) ? rgba$3(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
: (m = reHslPercent$3.exec(format)) ? hsla$3(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
: (m = reHslaPercent$3.exec(format)) ? hsla$3(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
: named$3.hasOwnProperty(format) ? rgbn$3(named$3[format]) // eslint-disable-line no-prototype-builtins
: format === "transparent" ? new Rgb$3(NaN, NaN, NaN, 0) : null;
}
function rgbn$3(n) {
return new Rgb$3(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
}
function rgba$3(r, g, b, a) {
if (a <= 0) r = g = b = NaN;
return new Rgb$3(r, g, b, a);
}
function rgbConvert$3(o) {
if (!(o instanceof Color$3)) o = color$3(o);
if (!o) return new Rgb$3();
o = o.rgb();
return new Rgb$3(o.r, o.g, o.b, o.opacity);
}
function rgb$3(r, g, b, opacity) {
return arguments.length === 1 ? rgbConvert$3(r) : new Rgb$3(r, g, b, opacity == null ? 1 : opacity);
}
function Rgb$3(r, g, b, opacity) {
this.r = +r;
this.g = +g;
this.b = +b;
this.opacity = +opacity;
}
define$3(Rgb$3, rgb$3, extend$4(Color$3, {
brighter: function brighter(k) {
k = k == null ? _brighter$3 : Math.pow(_brighter$3, k);
return new Rgb$3(this.r * k, this.g * k, this.b * k, this.opacity);
},
darker: function darker(k) {
k = k == null ? _darker$3 : Math.pow(_darker$3, k);
return new Rgb$3(this.r * k, this.g * k, this.b * k, this.opacity);
},
rgb: function rgb() {
return this;
},
displayable: function displayable() {
return -0.5 <= this.r && this.r < 255.5 && -0.5 <= this.g && this.g < 255.5 && -0.5 <= this.b && this.b < 255.5 && 0 <= this.opacity && this.opacity <= 1;
},
hex: rgb_formatHex$2,
// Deprecated! Use color.formatHex.
formatHex: rgb_formatHex$2,
formatRgb: rgb_formatRgb$2,
toString: rgb_formatRgb$2
}));
function rgb_formatHex$2() {
return "#" + hex$2(this.r) + hex$2(this.g) + hex$2(this.b);
}
function rgb_formatRgb$2() {
var a = this.opacity;
a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
return (a === 1 ? "rgb(" : "rgba(") + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " + Math.max(0, Math.min(255, Math.round(this.b) || 0)) + (a === 1 ? ")" : ", " + a + ")");
}
function hex$2(value) {
value = Math.max(0, Math.min(255, Math.round(value) || 0));
return (value < 16 ? "0" : "") + value.toString(16);
}
function hsla$3(h, s, l, a) {
if (a <= 0) h = s = l = NaN;else if (l <= 0 || l >= 1) h = s = NaN;else if (s <= 0) h = NaN;
return new Hsl$3(h, s, l, a);
}
function hslConvert$3(o) {
if (o instanceof Hsl$3) return new Hsl$3(o.h, o.s, o.l, o.opacity);
if (!(o instanceof Color$3)) o = color$3(o);
if (!o) return new Hsl$3();
if (o instanceof Hsl$3) return o;
o = o.rgb();
var r = o.r / 255,
g = o.g / 255,
b = o.b / 255,
min = Math.min(r, g, b),
max = Math.max(r, g, b),
h = NaN,
s = max - min,
l = (max + min) / 2;
if (s) {
if (r === max) h = (g - b) / s + (g < b) * 6;else if (g === max) h = (b - r) / s + 2;else h = (r - g) / s + 4;
s /= l < 0.5 ? max + min : 2 - max - min;
h *= 60;
} else {
s = l > 0 && l < 1 ? 0 : h;
}
return new Hsl$3(h, s, l, o.opacity);
}
function hsl$3(h, s, l, opacity) {
return arguments.length === 1 ? hslConvert$3(h) : new Hsl$3(h, s, l, opacity == null ? 1 : opacity);
}
function Hsl$3(h, s, l, opacity) {
this.h = +h;
this.s = +s;
this.l = +l;
this.opacity = +opacity;
}
define$3(Hsl$3, hsl$3, extend$4(Color$3, {
brighter: function brighter(k) {
k = k == null ? _brighter$3 : Math.pow(_brighter$3, k);
return new Hsl$3(this.h, this.s, this.l * k, this.opacity);
},
darker: function darker(k) {
k = k == null ? _darker$3 : Math.pow(_darker$3, k);
return new Hsl$3(this.h, this.s, this.l * k, this.opacity);
},
rgb: function rgb() {
var h = this.h % 360 + (this.h < 0) * 360,
s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
l = this.l,
m2 = l + (l < 0.5 ? l : 1 - l) * s,
m1 = 2 * l - m2;
return new Rgb$3(hsl2rgb$3(h >= 240 ? h - 240 : h + 120, m1, m2), hsl2rgb$3(h, m1, m2), hsl2rgb$3(h < 120 ? h + 240 : h - 120, m1, m2), this.opacity);
},
displayable: function displayable() {
return (0 <= this.s && this.s <= 1 || isNaN(this.s)) && 0 <= this.l && this.l <= 1 && 0 <= this.opacity && this.opacity <= 1;
},
formatHsl: function formatHsl() {
var a = this.opacity;
a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
return (a === 1 ? "hsl(" : "hsla(") + (this.h || 0) + ", " + (this.s || 0) * 100 + "%, " + (this.l || 0) * 100 + "%" + (a === 1 ? ")" : ", " + a + ")");
}
}));
/* From FvD 13.37, CSS Color Module Level 3 */
function hsl2rgb$3(h, m1, m2) {
return (h < 60 ? m1 + (m2 - m1) * h / 60 : h < 180 ? m2 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 : m1) * 255;
}
var slice$2 = [].slice;
var noabort = {};
function Queue(size) {
this._size = size;
this._call = this._error = null;
this._tasks = [];
this._data = [];
this._waiting = this._active = this._ended = this._start = 0; // inside a synchronous task callback?
}
Queue.prototype = queue.prototype = {
constructor: Queue,
defer: function defer(callback) {
if (typeof callback !== "function") throw new Error("invalid callback");
if (this._call) throw new Error("defer after await");
if (this._error != null) return this;
var t = slice$2.call(arguments, 1);
t.push(callback);
++this._waiting, this._tasks.push(t);
poke$1(this);
return this;
},
abort: function abort() {
if (this._error == null) _abort(this, new Error("abort"));
return this;
},
"await": function _await(callback) {
if (typeof callback !== "function") throw new Error("invalid callback");
if (this._call) throw new Error("multiple await");
this._call = function (error, results) {
callback.apply(null, [error].concat(results));
};
maybeNotify(this);
return this;
},
awaitAll: function awaitAll(callback) {
if (typeof callback !== "function") throw new Error("invalid callback");
if (this._call) throw new Error("multiple await");
this._call = callback;
maybeNotify(this);
return this;
}
};
function poke$1(q) {
if (!q._start) {
try {
start$1(q);
} // let the current task complete
catch (e) {
if (q._tasks[q._ended + q._active - 1]) _abort(q, e); // task errored synchronously
else if (!q._data) throw e; // await callback errored synchronously
}
}
}
function start$1(q) {
while (q._start = q._waiting && q._active < q._size) {
var i = q._ended + q._active,
t = q._tasks[i],
j = t.length - 1,
c = t[j];
t[j] = end(q, i);
--q._waiting, ++q._active;
t = c.apply(null, t);
if (!q._tasks[i]) continue; // task finished synchronously
q._tasks[i] = t || noabort;
}
}
function end(q, i) {
return function (e, r) {
if (!q._tasks[i]) return; // ignore multiple callbacks
--q._active, ++q._ended;
q._tasks[i] = null;
if (q._error != null) return; // ignore secondary errors
if (e != null) {
_abort(q, e);
} else {
q._data[i] = r;
if (q._waiting) poke$1(q);else maybeNotify(q);
}
};
}
function _abort(q, e) {
var i = q._tasks.length,
t;
q._error = e; // ignore active callbacks
q._data = undefined; // allow gc
q._waiting = NaN; // prevent starting
while (--i >= 0) {
if (t = q._tasks[i]) {
q._tasks[i] = null;
if (t.abort) {
try {
t.abort();
} catch (e) {
/* ignore */
}
}
}
}
q._active = NaN; // allow notification
maybeNotify(q);
}
function maybeNotify(q) {
if (!q._active && q._call) {
var d = q._data;
q._data = undefined; // allow gc
q._call(q._error, d);
}
}
function queue(concurrency) {
if (concurrency == null) concurrency = Infinity;else if (!((concurrency = +concurrency) >= 1)) throw new Error("invalid concurrency");
return new Queue(concurrency);
}
function constant$6 (x) {
return function () {
return x;
};
}
function ZoomEvent(target, type, transform) {
this.target = target;
this.type = type;
this.transform = transform;
}
function Transform(k, x, y) {
this.k = k;
this.x = x;
this.y = y;
}
Transform.prototype = {
constructor: Transform,
scale: function scale(k) {
return k === 1 ? this : new Transform(this.k * k, this.x, this.y);
},
translate: function translate(x, y) {
return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y);
},
apply: function apply(point) {
return [point[0] * this.k + this.x, point[1] * this.k + this.y];
},
applyX: function applyX(x) {
return x * this.k + this.x;
},
applyY: function applyY(y) {
return y * this.k + this.y;
},
invert: function invert(location) {
return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k];
},
invertX: function invertX(x) {
return (x - this.x) / this.k;
},
invertY: function invertY(y) {
return (y - this.y) / this.k;
},
rescaleX: function rescaleX(x) {
return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x));
},
rescaleY: function rescaleY(y) {
return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y));
},
toString: function toString() {
return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")";
}
};
var identity$5 = new Transform(1, 0, 0);
transform.prototype = Transform.prototype;
function transform(node) {
while (!node.__zoom) {
if (!(node = node.parentNode)) return identity$5;
}
return node.__zoom;
}
function nopropagation$1() {
event$1.stopImmediatePropagation();
}
function noevent$2 () {
event$1.preventDefault();
event$1.stopImmediatePropagation();
}
function defaultFilter$1() {
return !event$1.ctrlKey && !event$1.button;
}
function defaultExtent$1() {
var e = this;
if (e instanceof SVGElement) {
e = e.ownerSVGElement || e;
if (e.hasAttribute("viewBox")) {
e = e.viewBox.baseVal;
return [[e.x, e.y], [e.x + e.width, e.y + e.height]];
}
return [[0, 0], [e.width.baseVal.value, e.height.baseVal.value]];
}
return [[0, 0], [e.clientWidth, e.clientHeight]];
}
function defaultTransform() {
return this.__zoom || identity$5;
}
function defaultWheelDelta() {
return -event$1.deltaY * (event$1.deltaMode === 1 ? 0.05 : event$1.deltaMode ? 1 : 0.002);
}
function defaultTouchable$1() {
return navigator.maxTouchPoints || "ontouchstart" in this;
}
function defaultConstrain(transform, extent, translateExtent) {
var dx0 = transform.invertX(extent[0][0]) - translateExtent[0][0],
dx1 = transform.invertX(extent[1][0]) - translateExtent[1][0],
dy0 = transform.invertY(extent[0][1]) - translateExtent[0][1],
dy1 = transform.invertY(extent[1][1]) - translateExtent[1][1];
return transform.translate(dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1), dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1));
}
function zoom () {
var filter = defaultFilter$1,
extent = defaultExtent$1,
constrain = defaultConstrain,
wheelDelta = defaultWheelDelta,
touchable = defaultTouchable$1,
scaleExtent = [0, Infinity],
translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]],
duration = 250,
interpolate = interpolateZoom,
listeners = dispatch("start", "zoom", "end"),
touchstarting,
touchending,
touchDelay = 500,
wheelDelay = 150,
clickDistance2 = 0;
function zoom(selection) {
selection.property("__zoom", defaultTransform).on("wheel.zoom", wheeled).on("mousedown.zoom", mousedowned).on("dblclick.zoom", dblclicked).filter(touchable).on("touchstart.zoom", touchstarted).on("touchmove.zoom", touchmoved).on("touchend.zoom touchcancel.zoom", touchended).style("touch-action", "none").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
}
zoom.transform = function (collection, transform, point) {
var selection = collection.selection ? collection.selection() : collection;
selection.property("__zoom", defaultTransform);
if (collection !== selection) {
schedule(collection, transform, point);
} else {
selection.interrupt().each(function () {
gesture(this, arguments).start().zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform).end();
});
}
};
zoom.scaleBy = function (selection, k, p) {
zoom.scaleTo(selection, function () {
var k0 = this.__zoom.k,
k1 = typeof k === "function" ? k.apply(this, arguments) : k;
return k0 * k1;
}, p);
};
zoom.scaleTo = function (selection, k, p) {
zoom.transform(selection, function () {
var e = extent.apply(this, arguments),
t0 = this.__zoom,
p0 = p == null ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p,
p1 = t0.invert(p0),
k1 = typeof k === "function" ? k.apply(this, arguments) : k;
return constrain(translate(scale(t0, k1), p0, p1), e, translateExtent);
}, p);
};
zoom.translateBy = function (selection, x, y) {
zoom.transform(selection, function () {
return constrain(this.__zoom.translate(typeof x === "function" ? x.apply(this, arguments) : x, typeof y === "function" ? y.apply(this, arguments) : y), extent.apply(this, arguments), translateExtent);
});
};
zoom.translateTo = function (selection, x, y, p) {
zoom.transform(selection, function () {
var e = extent.apply(this, arguments),
t = this.__zoom,
p0 = p == null ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p;
return constrain(identity$5.translate(p0[0], p0[1]).scale(t.k).translate(typeof x === "function" ? -x.apply(this, arguments) : -x, typeof y === "function" ? -y.apply(this, arguments) : -y), e, translateExtent);
}, p);
};
function scale(transform, k) {
k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k));
return k === transform.k ? transform : new Transform(k, transform.x, transform.y);
}
function translate(transform, p0, p1) {
var x = p0[0] - p1[0] * transform.k,
y = p0[1] - p1[1] * transform.k;
return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y);
}
function centroid(extent) {
return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2];
}
function schedule(transition, transform, point) {
transition.on("start.zoom", function () {
gesture(this, arguments).start();
}).on("interrupt.zoom end.zoom", function () {
gesture(this, arguments).end();
}).tween("zoom", function () {
var that = this,
args = arguments,
g = gesture(that, args),
e = extent.apply(that, args),
p = point == null ? centroid(e) : typeof point === "function" ? point.apply(that, args) : point,
w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
a = that.__zoom,
b = typeof transform === "function" ? transform.apply(that, args) : transform,
i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
return function (t) {
if (t === 1) t = b; // Avoid rounding error on end.
else {
var l = i(t),
k = w / l[2];
t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k);
}
g.zoom(null, t);
};
});
}
function gesture(that, args, clean) {
return !clean && that.__zooming || new Gesture(that, args);
}
function Gesture(that, args) {
this.that = that;
this.args = args;
this.active = 0;
this.extent = extent.apply(that, args);
this.taps = 0;
}
Gesture.prototype = {
start: function start() {
if (++this.active === 1) {
this.that.__zooming = this;
this.emit("start");
}
return this;
},
zoom: function zoom(key, transform) {
if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]);
if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]);
if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]);
this.that.__zoom = transform;
this.emit("zoom");
return this;
},
end: function end() {
if (--this.active === 0) {
delete this.that.__zooming;
this.emit("end");
}
return this;
},
emit: function emit(type) {
customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]);
}
};
function wheeled() {
if (!filter.apply(this, arguments)) return;
var g = gesture(this, arguments),
t = this.__zoom,
k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))),
p = mouse(this); // If the mouse is in the same location as before, reuse it.
// If there were recent wheel events, reset the wheel idle timeout.
if (g.wheel) {
if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {
g.mouse[1] = t.invert(g.mouse[0] = p);
}
clearTimeout(g.wheel);
} // If this wheel event wont trigger a transform change, ignore it.
else if (t.k === k) return; // Otherwise, capture the mouse point and location at the start.
else {
g.mouse = [p, t.invert(p)];
interrupt(this);
g.start();
}
noevent$2();
g.wheel = setTimeout(wheelidled, wheelDelay);
g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent, translateExtent));
function wheelidled() {
g.wheel = null;
g.end();
}
}
function mousedowned() {
if (touchending || !filter.apply(this, arguments)) return;
var g = gesture(this, arguments, true),
v = _select(event$1.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true),
p = mouse(this),
x0 = event$1.clientX,
y0 = event$1.clientY;
dragDisable(event$1.view);
nopropagation$1();
g.mouse = [p, this.__zoom.invert(p)];
interrupt(this);
g.start();
function mousemoved() {
noevent$2();
if (!g.moved) {
var dx = event$1.clientX - x0,
dy = event$1.clientY - y0;
g.moved = dx * dx + dy * dy > clickDistance2;
}
g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = mouse(g.that), g.mouse[1]), g.extent, translateExtent));
}
function mouseupped() {
v.on("mousemove.zoom mouseup.zoom", null);
yesdrag(event$1.view, g.moved);
noevent$2();
g.end();
}
}
function dblclicked() {
if (!filter.apply(this, arguments)) return;
var t0 = this.__zoom,
p0 = mouse(this),
p1 = t0.invert(p0),
k1 = t0.k * (event$1.shiftKey ? 0.5 : 2),
t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments), translateExtent);
noevent$2();
if (duration > 0) _select(this).transition().duration(duration).call(schedule, t1, p0);else _select(this).call(zoom.transform, t1);
}
function touchstarted() {
if (!filter.apply(this, arguments)) return;
var touches = event$1.touches,
n = touches.length,
g = gesture(this, arguments, event$1.changedTouches.length === n),
started,
i,
t,
p;
nopropagation$1();
for (i = 0; i < n; ++i) {
t = touches[i], p = touch(this, touches, t.identifier);
p = [p, this.__zoom.invert(p), t.identifier];
if (!g.touch0) g.touch0 = p, started = true, g.taps = 1 + !!touchstarting;else if (!g.touch1 && g.touch0[2] !== p[2]) g.touch1 = p, g.taps = 0;
}
if (touchstarting) touchstarting = clearTimeout(touchstarting);
if (started) {
if (g.taps < 2) touchstarting = setTimeout(function () {
touchstarting = null;
}, touchDelay);
interrupt(this);
g.start();
}
}
function touchmoved() {
if (!this.__zooming) return;
var g = gesture(this, arguments),
touches = event$1.changedTouches,
n = touches.length,
i,
t,
p,
l;
noevent$2();
if (touchstarting) touchstarting = clearTimeout(touchstarting);
g.taps = 0;
for (i = 0; i < n; ++i) {
t = touches[i], p = touch(this, touches, t.identifier);
if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p;else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p;
}
t = g.that.__zoom;
if (g.touch1) {
var p0 = g.touch0[0],
l0 = g.touch0[1],
p1 = g.touch1[0],
l1 = g.touch1[1],
dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp,
dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
t = scale(t, Math.sqrt(dp / dl));
p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
} else if (g.touch0) p = g.touch0[0], l = g.touch0[1];else return;
g.zoom("touch", constrain(translate(t, p, l), g.extent, translateExtent));
}
function touchended() {
if (!this.__zooming) return;
var g = gesture(this, arguments),
touches = event$1.changedTouches,
n = touches.length,
i,
t;
nopropagation$1();
if (touchending) clearTimeout(touchending);
touchending = setTimeout(function () {
touchending = null;
}, touchDelay);
for (i = 0; i < n; ++i) {
t = touches[i];
if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0;else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1;
}
if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1;
if (g.touch0) g.touch0[1] = this.__zoom.invert(g.touch0[0]);else {
g.end(); // If this was a dbltap, reroute to the (optional) dblclick.zoom handler.
if (g.taps === 2) {
var p = _select(this).on("dblclick.zoom");
if (p) p.apply(this, arguments);
}
}
}
zoom.wheelDelta = function (_) {
return arguments.length ? (wheelDelta = typeof _ === "function" ? _ : constant$6(+_), zoom) : wheelDelta;
};
zoom.filter = function (_) {
return arguments.length ? (filter = typeof _ === "function" ? _ : constant$6(!!_), zoom) : filter;
};
zoom.touchable = function (_) {
return arguments.length ? (touchable = typeof _ === "function" ? _ : constant$6(!!_), zoom) : touchable;
};
zoom.extent = function (_) {
return arguments.length ? (extent = typeof _ === "function" ? _ : constant$6([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent;
};
zoom.scaleExtent = function (_) {
return arguments.length ? (scaleExtent[0] = +_[0], scaleExtent[1] = +_[1], zoom) : [scaleExtent[0], scaleExtent[1]];
};
zoom.translateExtent = function (_) {
return arguments.length ? (translateExtent[0][0] = +_[0][0], translateExtent[1][0] = +_[1][0], translateExtent[0][1] = +_[0][1], translateExtent[1][1] = +_[1][1], zoom) : [[translateExtent[0][0], translateExtent[0][1]], [translateExtent[1][0], translateExtent[1][1]]];
};
zoom.constrain = function (_) {
return arguments.length ? (constrain = _, zoom) : constrain;
};
zoom.duration = function (_) {
return arguments.length ? (duration = +_, zoom) : duration;
};
zoom.interpolate = function (_) {
return arguments.length ? (interpolate = _, zoom) : interpolate;
};
zoom.on = function () {
var value = listeners.on.apply(listeners, arguments);
return value === listeners ? zoom : value;
};
zoom.clickDistance = function (_) {
return arguments.length ? (clickDistance2 = (_ = +_) * _, zoom) : Math.sqrt(clickDistance2);
};
return zoom;
}
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function commonjsRequire () {
throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs');
}
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var lrucache = createCommonjsModule(function (module) {
(function (root, factory) {
{
module.exports = factory();
}
})((typeof window === "undefined" ? "undefined" : _typeof(window)) === 'object' ? window : commonjsGlobal, function () {
var undef = void 0;
function LRUCache(capacity) {
if (!(this instanceof LRUCache)) return new LRUCache(capacity);
this._LRUCacheState = new CacheState(capacity);
}
var proto = LRUCache.prototype;
proto.get = function (key) {
var state = this._LRUCacheState;
var lruEntry = state.hash[key];
if (!lruEntry) return;
refresh(state.linkedList, lruEntry);
return state.data[key];
};
proto.set = function (key, value) {
var state = this._LRUCacheState;
var lruEntry = state.hash[key];
if (value === undef) return this;
if (!lruEntry) {
state.hash[key] = new LRUEntry(key);
state.linkedList.length += 1;
lruEntry = state.hash[key];
}
refresh(state.linkedList, lruEntry);
state.data[key] = value;
if (state.linkedList.length > state.capacity) this.remove(state.linkedList.end.key);
return this;
};
proto.update = function (key, parseFn) {
if (this.has(key)) this.set(key, parseFn(this.get(key)));
return this;
};
proto.remove = function (key) {
var state = this._LRUCacheState;
var lruEntry = state.hash[key];
if (!lruEntry) return this;
if (lruEntry === state.linkedList.head) state.linkedList.head = lruEntry.p;
if (lruEntry === state.linkedList.end) state.linkedList.end = lruEntry.n;
link(lruEntry.n, lruEntry.p);
delete state.hash[key];
delete state.data[key];
state.linkedList.length -= 1;
return this;
};
proto.removeAll = function () {
this._LRUCacheState = new CacheState(this._LRUCacheState.capacity);
return this;
};
proto.info = function () {
var state = this._LRUCacheState;
return {
capacity: state.capacity,
length: state.linkedList.length
};
};
proto.keys = function () {
var keys = [];
var lruEntry = this._LRUCacheState.linkedList.head;
while (lruEntry) {
keys.push(lruEntry.key);
lruEntry = lruEntry.p;
}
return keys;
};
proto.has = function (key) {
return !!this._LRUCacheState.hash[key];
};
proto.staleKey = function () {
return this._LRUCacheState.linkedList.end && this._LRUCacheState.linkedList.end.key;
};
proto.popStale = function () {
var staleKey = this.staleKey();
if (!staleKey) return null;
var stale = [staleKey, this._LRUCacheState.data[staleKey]];
this.remove(staleKey);
return stale;
};
function CacheState(capacity) {
this.capacity = capacity > 0 ? +capacity : Number.MAX_SAFE_INTEGER || Number.MAX_VALUE;
this.data = Object.create ? Object.create(null) : {};
this.hash = Object.create ? Object.create(null) : {};
this.linkedList = new LinkedList();
}
function LinkedList() {
this.length = 0;
this.head = null;
this.end = null;
}
function LRUEntry(key) {
this.key = key;
this.p = null;
this.n = null;
} // 更新链表把get或put方法操作的key提到链表head即表示最新
function refresh(linkedList, entry) {
if (entry === linkedList.head) return;
if (!linkedList.end) {
linkedList.end = entry;
} else if (linkedList.end === entry) {
linkedList.end = entry.n;
}
link(entry.n, entry.p);
link(entry, linkedList.head);
linkedList.head = entry;
linkedList.head.n = null;
} // 对两个链表对象建立链接,形成一条链
function link(nextEntry, prevEntry) {
if (nextEntry === prevEntry) return;
if (nextEntry) nextEntry.p = prevEntry;
if (prevEntry) prevEntry.n = nextEntry;
}
return LRUCache;
});
});
// Computes the decimal coefficient and exponent of the specified number x with
// significant digits p, where x is positive and p is in [1, 21] or undefined.
// For example, formatDecimal(1.23) returns ["123", 0].
function formatDecimal$1 (x, p) {
if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
var i,
coefficient = x.slice(0, i); // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
// (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
return [coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, +x.slice(i + 1)];
}
function exponent$1 (x) {
return x = formatDecimal$1(Math.abs(x)), x ? x[1] : NaN;
}
function formatGroup$1 (grouping, thousands) {
return function (value, width) {
var i = value.length,
t = [],
j = 0,
g = grouping[0],
length = 0;
while (i > 0 && g > 0) {
if (length + g + 1 > width) g = Math.max(1, width - length);
t.push(value.substring(i -= g, i + g));
if ((length += g + 1) > width) break;
g = grouping[j = (j + 1) % grouping.length];
}
return t.reverse().join(thousands);
};
}
function formatNumerals$1 (numerals) {
return function (value) {
return value.replace(/[0-9]/g, function (i) {
return numerals[+i];
});
};
}
// [[fill]align][sign][symbol][0][width][,][.precision][~][type]
var re$1 = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;
function formatSpecifier$1(specifier) {
if (!(match = re$1.exec(specifier))) throw new Error("invalid format: " + specifier);
var match;
return new FormatSpecifier$1({
fill: match[1],
align: match[2],
sign: match[3],
symbol: match[4],
zero: match[5],
width: match[6],
comma: match[7],
precision: match[8] && match[8].slice(1),
trim: match[9],
type: match[10]
});
}
formatSpecifier$1.prototype = FormatSpecifier$1.prototype; // instanceof
function FormatSpecifier$1(specifier) {
this.fill = specifier.fill === undefined ? " " : specifier.fill + "";
this.align = specifier.align === undefined ? ">" : specifier.align + "";
this.sign = specifier.sign === undefined ? "-" : specifier.sign + "";
this.symbol = specifier.symbol === undefined ? "" : specifier.symbol + "";
this.zero = !!specifier.zero;
this.width = specifier.width === undefined ? undefined : +specifier.width;
this.comma = !!specifier.comma;
this.precision = specifier.precision === undefined ? undefined : +specifier.precision;
this.trim = !!specifier.trim;
this.type = specifier.type === undefined ? "" : specifier.type + "";
}
FormatSpecifier$1.prototype.toString = function () {
return this.fill + this.align + this.sign + this.symbol + (this.zero ? "0" : "") + (this.width === undefined ? "" : Math.max(1, this.width | 0)) + (this.comma ? "," : "") + (this.precision === undefined ? "" : "." + Math.max(0, this.precision | 0)) + (this.trim ? "~" : "") + this.type;
};
// Trims insignificant zeros, e.g., replaces 1.2000k with 1.2k.
function formatTrim$1 (s) {
out: for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) {
switch (s[i]) {
case ".":
i0 = i1 = i;
break;
case "0":
if (i0 === 0) i0 = i;
i1 = i;
break;
default:
if (!+s[i]) break out;
if (i0 > 0) i0 = 0;
break;
}
}
return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s;
}
var prefixExponent$1;
function formatPrefixAuto$1 (x, p) {
var d = formatDecimal$1(x, p);
if (!d) return x + "";
var coefficient = d[0],
exponent = d[1],
i = exponent - (prefixExponent$1 = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
n = coefficient.length;
return i === n ? coefficient : i > n ? coefficient + new Array(i - n + 1).join("0") : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) : "0." + new Array(1 - i).join("0") + formatDecimal$1(x, Math.max(0, p + i - 1))[0]; // less than 1y!
}
function formatRounded$1 (x, p) {
var d = formatDecimal$1(x, p);
if (!d) return x + "";
var coefficient = d[0],
exponent = d[1];
return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) : coefficient + new Array(exponent - coefficient.length + 2).join("0");
}
var formatTypes$1 = {
"%": function _(x, p) {
return (x * 100).toFixed(p);
},
"b": function b(x) {
return Math.round(x).toString(2);
},
"c": function c(x) {
return x + "";
},
"d": function d(x) {
return Math.round(x).toString(10);
},
"e": function e(x, p) {
return x.toExponential(p);
},
"f": function f(x, p) {
return x.toFixed(p);
},
"g": function g(x, p) {
return x.toPrecision(p);
},
"o": function o(x) {
return Math.round(x).toString(8);
},
"p": function p(x, _p) {
return formatRounded$1(x * 100, _p);
},
"r": formatRounded$1,
"s": formatPrefixAuto$1,
"X": function X(x) {
return Math.round(x).toString(16).toUpperCase();
},
"x": function x(_x) {
return Math.round(_x).toString(16);
}
};
function identity$6 (x) {
return x;
}
var map$2 = Array.prototype.map,
prefixes$1 = ["y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y"];
function formatLocale$2 (locale) {
var group = locale.grouping === undefined || locale.thousands === undefined ? identity$6 : formatGroup$1(map$2.call(locale.grouping, Number), locale.thousands + ""),
currencyPrefix = locale.currency === undefined ? "" : locale.currency[0] + "",
currencySuffix = locale.currency === undefined ? "" : locale.currency[1] + "",
decimal = locale.decimal === undefined ? "." : locale.decimal + "",
numerals = locale.numerals === undefined ? identity$6 : formatNumerals$1(map$2.call(locale.numerals, String)),
percent = locale.percent === undefined ? "%" : locale.percent + "",
minus = locale.minus === undefined ? "-" : locale.minus + "",
nan = locale.nan === undefined ? "NaN" : locale.nan + "";
function newFormat(specifier) {
specifier = formatSpecifier$1(specifier);
var fill = specifier.fill,
align = specifier.align,
sign = specifier.sign,
symbol = specifier.symbol,
zero = specifier.zero,
width = specifier.width,
comma = specifier.comma,
precision = specifier.precision,
trim = specifier.trim,
type = specifier.type; // The "n" type is an alias for ",g".
if (type === "n") comma = true, type = "g"; // The "" type, and any invalid type, is an alias for ".12~g".
else if (!formatTypes$1[type]) precision === undefined && (precision = 12), trim = true, type = "g"; // If zero fill is specified, padding goes after sign and before digits.
if (zero || fill === "0" && align === "=") zero = true, fill = "0", align = "="; // Compute the prefix and suffix.
// For SI-prefix, the suffix is lazily computed.
var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type) ? percent : ""; // What format function should we use?
// Is this an integer type?
// Can this type generate exponential notation?
var formatType = formatTypes$1[type],
maybeSuffix = /[defgprs%]/.test(type); // Set the default precision if not specified,
// or clamp the specified precision to the supported range.
// For significant precision, it must be in [1, 21].
// For fixed precision, it must be in [0, 20].
precision = precision === undefined ? 6 : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) : Math.max(0, Math.min(20, precision));
function format(value) {
var valuePrefix = prefix,
valueSuffix = suffix,
i,
n,
c;
if (type === "c") {
valueSuffix = formatType(value) + valueSuffix;
value = "";
} else {
value = +value; // Determine the sign. -0 is not less than 0, but 1 / -0 is!
var valueNegative = value < 0 || 1 / value < 0; // Perform the initial formatting.
value = isNaN(value) ? nan : formatType(Math.abs(value), precision); // Trim insignificant zeros.
if (trim) value = formatTrim$1(value); // If a negative value rounds to zero after formatting, and no explicit positive sign is requested, hide the sign.
if (valueNegative && +value === 0 && sign !== "+") valueNegative = false; // Compute the prefix and suffix.
valuePrefix = (valueNegative ? sign === "(" ? sign : minus : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
valueSuffix = (type === "s" ? prefixes$1[8 + prefixExponent$1 / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : ""); // Break the formatted value into the integer “value” part that can be
// grouped, and fractional or exponential “suffix” part that is not.
if (maybeSuffix) {
i = -1, n = value.length;
while (++i < n) {
if (c = value.charCodeAt(i), 48 > c || c > 57) {
valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
value = value.slice(0, i);
break;
}
}
}
} // If the fill character is not "0", grouping is applied before padding.
if (comma && !zero) value = group(value, Infinity); // Compute the padding.
var length = valuePrefix.length + value.length + valueSuffix.length,
padding = length < width ? new Array(width - length + 1).join(fill) : ""; // If the fill character is "0", grouping is applied after padding.
if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; // Reconstruct the final output based on the desired alignment.
switch (align) {
case "<":
value = valuePrefix + value + valueSuffix + padding;
break;
case "=":
value = valuePrefix + padding + value + valueSuffix;
break;
case "^":
value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length);
break;
default:
value = padding + valuePrefix + value + valueSuffix;
break;
}
return numerals(value);
}
format.toString = function () {
return specifier + "";
};
return format;
}
function formatPrefix(specifier, value) {
var f = newFormat((specifier = formatSpecifier$1(specifier), specifier.type = "f", specifier)),
e = Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3,
k = Math.pow(10, -e),
prefix = prefixes$1[8 + e / 3];
return function (value) {
return f(k * value) + prefix;
};
}
return {
format: newFormat,
formatPrefix: formatPrefix
};
}
/**
@namespace {Object} formatLocale
@desc A set of default locale formatters used when assigning suffixes and currency in numbers.
*
* | Name | Default | Description |
* |---|---|---|
* | separator | "" | Separation between the number with the suffix. |
* | suffixes | [] | List of suffixes used to format numbers. |
* | grouping | [3] | The array of group sizes, |
* | delimiters | {thousands: ",", decimal: "."} | Decimal and group separators. |
* | currency | ["$", ""] | The currency prefix and suffix. |
*/
var formatLocale$3 = {
"en-GB": {
separator: "",
suffixes: ["y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "B", "T", "q", "Q", "Z", "Y"],
grouping: [3],
delimiters: {
thousands: ",",
decimal: "."
},
currency: ["£", ""]
},
"en-US": {
separator: "",
suffixes: ["y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "B", "T", "q", "Q", "Z", "Y"],
grouping: [3],
delimiters: {
thousands: ",",
decimal: "."
},
currency: ["$", ""]
},
"es-CL": {
separator: "",
suffixes: ["y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "MM", "B", "T", "Q", "Z", "Y"],
grouping: [3],
delimiters: {
thousands: ".",
decimal: ","
},
currency: ["$", ""]
},
"es-MX": {
separator: "",
suffixes: ["y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "MM", "B", "T", "Q", "Z", "Y"],
grouping: [3],
delimiters: {
thousands: ",",
decimal: "."
},
currency: ["$", ""]
},
"es-ES": {
separator: "",
suffixes: ["y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "mm", "b", "t", "q", "Q", "Z", "Y"],
grouping: [3],
delimiters: {
thousands: ".",
decimal: ","
},
currency: ["€", ""]
},
"et-EE": {
separator: " ",
suffixes: ["y", "z", "a", "f", "p", "n", "µ", "m", "", "tuhat", "miljonit", "miljardit", "triljonit", "q", "Q", "Z", "Y"],
grouping: [3],
delimiters: {
thousands: " ",
decimal: ","
},
currency: ["", "eurot"]
},
"fr-FR": {
suffixes: ["y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "m", "b", "t", "q", "Q", "Z", "Y"],
grouping: [3],
delimiters: {
thousands: " ",
decimal: ","
},
currency: ["€", ""]
}
};
function _typeof$e(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$e = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$e = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$e(obj);
}
var round = function round(x, n) {
return parseFloat(Math.round(x * Math.pow(10, n)) / Math.pow(10, n)).toFixed(n);
};
/**
* @private
*/
function formatSuffix(value, precision, suffixes) {
var i = 0;
if (value) {
if (value < 0) value *= -1;
i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3));
}
var d = suffixes[8 + i / 3];
return {
number: round(d.scale(value), precision),
symbol: d.symbol
};
}
/**
* @private
*/
function parseSuffixes(d, i) {
var k = Math.pow(10, Math.abs(8 - i) * 3);
return {
scale: i > 8 ? function (d) {
return d / k;
} : function (d) {
return d * k;
},
symbol: d
};
}
/**
@function formatAbbreviate
@desc Formats a number to an appropriate number of decimal places and rounding, adding suffixes if applicable (ie. `1200000` to `"1.2M"`).
@param {Number|String} n The number to be formatted.
@param {Object|String} locale The locale config to be used. If *value* is an object, the function will format the numbers according the object. The object must include `suffixes`, `delimiter` and `currency` properties.
@returns {String}
*/
function formatAbbreviate (n) {
var locale = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "en-US";
var precision = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
if (isFinite(n)) n *= 1;else return "N/A";
var negative = n < 0;
var length = n.toString().split(".")[0].replace("-", "").length,
localeConfig = _typeof$e(locale) === "object" ? locale : formatLocale$3[locale] || formatLocale$3["en-US"],
suffixes = localeConfig.suffixes.map(parseSuffixes);
var decimal = localeConfig.delimiters.decimal || ".",
separator = localeConfig.separator || "",
thousands = localeConfig.delimiters.thousands || ",";
var d3plusFormatLocale = formatLocale$2({
currency: localeConfig.currency || ["$", ""],
decimal: decimal,
grouping: localeConfig.grouping || [3],
thousands: thousands
});
var val;
if (precision) val = d3plusFormatLocale.format(precision)(n);else if (n === 0) val = "0";else if (length >= 3) {
var f = formatSuffix(d3plusFormatLocale.format(".3r")(n), 2, suffixes);
var num = parseFloat(f.number).toString().replace(".", decimal);
var _char = f.symbol;
val = "".concat(num).concat(separator).concat(_char);
} else if (length === 3) val = d3plusFormatLocale.format(",f")(n);else if (n < 1 && n > -1) val = d3plusFormatLocale.format(".2g")(n);else val = d3plusFormatLocale.format(".3g")(n);
return "".concat(negative && val.charAt(0) !== "-" ? "-" : "").concat(val).replace(/(\.[0]*[1-9]*)[0]*$/g, "$1") // removes any trailing zeros
.replace(/\.[0]*$/g, ""); // removes any trailing decimal point
}
/**
@function date
@summary Parses numbers and strings to valid Javascript Date objects.
@description Returns a javascript Date object for a given a Number (representing either a 4-digit year or milliseconds since epoch) or a String that is in [valid dateString format](http://dygraphs.com/date-formats.html). Besides the 4-digit year parsing, this function is useful when needing to parse negative (BC) years, which the vanilla Date object cannot parse.
@param {Number|String} *date*
*/
function date$2 (d) {
// returns if already Date object
if (d.constructor === Date) return d; // detects if milliseconds
else if (d.constructor === Number && "".concat(d).length > 5 && d % 1 === 0) return new Date(d);
var s = "".concat(d);
var dayFormat = new RegExp(/^\d{1,2}[./-]\d{1,2}[./-](-*\d{1,4})$/g).exec(s),
strFormat = new RegExp(/^[A-z]{1,3} [A-z]{1,3} \d{1,2} (-*\d{1,4}) \d{1,2}:\d{1,2}:\d{1,2} [A-z]{1,3}-*\d{1,4} \([A-z]{1,3}\)/g).exec(s); // tests for XX/XX/XXXX format
if (dayFormat) {
var year = dayFormat[1];
if (year.indexOf("-") === 0) s = s.replace(year, year.substr(1));
var date = new Date(s);
date.setFullYear(year);
return date;
} // tests for full Date object string format
else if (strFormat) {
var _year = strFormat[1];
if (_year.indexOf("-") === 0) s = s.replace(_year, _year.substr(1));
var _date = new Date(s);
_date.setFullYear(_year);
return _date;
} // detects if only passing a year value
else if (!s.includes("/") && !s.includes(" ") && (!s.includes("-") || !s.indexOf("-"))) {
var _date2 = new Date("".concat(s, "/01/01"));
_date2.setFullYear(d);
return _date2;
} // parses string to Date object
else return new Date(s);
}
var locale$2 = {
"de-DE": {
dateTime: "%A, der %e. %B %Y, %X",
date: "%d.%m.%Y",
time: "%H:%M:%S",
periods: ["AM", "PM"],
days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
shortDays: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
shortMonths: ["Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"]
},
"en-GB": {
dateTime: "%a %e %b %X %Y",
date: "%d/%m/%Y",
time: "%H:%M:%S",
periods: ["AM", "PM"],
days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
},
"en-US": {
dateTime: "%x, %X",
date: "%-m/%-d/%Y",
time: "%-I:%M:%S %p",
periods: ["AM", "PM"],
days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
},
"es-ES": {
dateTime: "%A, %e de %B de %Y, %X",
date: "%d/%m/%Y",
time: "%H:%M:%S",
periods: ["AM", "PM"],
days: ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"],
shortDays: ["dom", "lun", "mar", "mié", "jue", "vie", "sáb"],
months: ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"],
shortMonths: ["ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic"]
},
"es-MX": {
dateTime: "%x, %X",
date: "%d/%m/%Y",
time: "%-I:%M:%S %p",
periods: ["AM", "PM"],
days: ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"],
shortDays: ["dom", "lun", "mar", "mié", "jue", "vie", "sáb"],
months: ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"],
shortMonths: ["ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic"]
},
"fr-FR": {
dateTime: "%A, le %e %B %Y, %X",
date: "%d/%m/%Y",
time: "%H:%M:%S",
periods: ["AM", "PM"],
days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"],
shortDays: ["dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam."],
months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"],
shortMonths: ["janv.", "févr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc."]
},
"it-IT": {
dateTime: "%A %e %B %Y, %X",
date: "%d/%m/%Y",
time: "%H:%M:%S",
periods: ["AM", "PM"],
days: ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"],
shortDays: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"],
months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"],
shortMonths: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"]
},
"pt-BR": {
dateTime: "%A, %e de %B de %Y. %X",
date: "%d/%m/%Y",
time: "%H:%M:%S",
periods: ["AM", "PM"],
days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"],
shortDays: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"],
months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
shortMonths: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"]
}
};
function _defineProperty$2(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _toConsumableArray$1(arr) {
return _arrayWithoutHoles$1(arr) || _iterableToArray$1(arr) || _unsupportedIterableToArray$4(arr) || _nonIterableSpread$1();
}
function _nonIterableSpread$1() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _unsupportedIterableToArray$4(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray$4(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$4(o, minLen);
}
function _iterableToArray$1(iter) {
if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
}
function _arrayWithoutHoles$1(arr) {
if (Array.isArray(arr)) return _arrayLikeToArray$4(arr);
}
function _arrayLikeToArray$4(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) {
arr2[i] = arr[i];
}
return arr2;
}
function _typeof$f(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$f = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$f = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$f(obj);
}
function _classCallCheck$d(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$d(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$d(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$d(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$d(Constructor, staticProps);
return Constructor;
}
function _inherits$b(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$b(subClass, superClass);
}
function _setPrototypeOf$b(o, p) {
_setPrototypeOf$b = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$b(o, p);
}
function _createSuper$b(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$b();
return function _createSuperInternal() {
var Super = _getPrototypeOf$b(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$b(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$b(this, result);
};
}
function _possibleConstructorReturn$b(self, call) {
if (call && (_typeof$f(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$b(self);
}
function _assertThisInitialized$b(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$b() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$b(o) {
_getPrototypeOf$b = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$b(o);
}
/**
@class Axis
@extends external:BaseClass
@desc Creates an SVG scale based on an array of data.
*/
var Axis = /*#__PURE__*/function (_BaseClass) {
_inherits$b(Axis, _BaseClass);
var _super = _createSuper$b(Axis);
/**
@memberof Axis
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function Axis() {
var _this;
_classCallCheck$d(this, Axis);
_this = _super.call(this);
_this._align = "middle";
_this._barConfig = {
"stroke": "#000",
"stroke-width": 1
};
_this._domain = [0, 10];
_this._duration = 600;
_this._gridConfig = {
"stroke": "#ccc",
"stroke-width": 1
};
_this._gridLog = false;
_this._height = 400;
_this._labelOffset = true;
_this.orient("bottom");
_this._outerBounds = {
width: 0,
height: 0,
x: 0,
y: 0
};
_this._padding = 5;
_this._paddingInner = 0.1;
_this._paddingOuter = 0.1;
_this._rotateLabels = false;
_this._scale = "linear";
_this._scalePadding = 0.5;
_this._shape = "Line";
_this._shapeConfig = {
fill: "#000",
height: function height(d) {
return d.tick ? 8 : 0;
},
label: function label(d) {
return d.text;
},
labelBounds: function labelBounds(d) {
return d.labelBounds;
},
labelConfig: {
fontColor: "#000",
fontFamily: new TextBox().fontFamily(),
fontResize: false,
fontSize: constant$1(10),
padding: 0,
textAnchor: function textAnchor() {
var rtl = detectRTL();
return _this._orient === "left" ? rtl ? "start" : "end" : _this._orient === "right" ? rtl ? "end" : "start" : _this._rotateLabels ? _this._orient === "bottom" ? "end" : "start" : "middle";
},
verticalAlign: function verticalAlign() {
return _this._orient === "bottom" ? "top" : _this._orient === "top" ? "bottom" : "middle";
}
},
r: function r(d) {
return d.tick ? 4 : 0;
},
stroke: "#000",
strokeWidth: 1,
width: function width(d) {
return d.tick ? 8 : 0;
}
};
_this._tickSize = 5;
_this._tickSpecifier = undefined;
_this._tickSuffix = "normal";
_this._tickUnit = 0;
_this._timeLocale = undefined;
_this._titleClass = new TextBox();
_this._titleConfig = {
fontSize: 12,
textAnchor: "middle"
};
_this._width = 400;
return _this;
}
/**
@memberof Axis
@desc Sets positioning for the axis bar.
@param {D3Selection} *bar*
@private
*/
_createClass$d(Axis, [{
key: "_barPosition",
value: function _barPosition(bar) {
var _this$_position = this._position,
height = _this$_position.height,
x = _this$_position.x,
y = _this$_position.y,
opposite = _this$_position.opposite,
domain = this._getDomain(),
offset = this._margin[opposite],
position = ["top", "left"].includes(this._orient) ? this._outerBounds[y] + this._outerBounds[height] - offset : this._outerBounds[y] + offset;
var x1mod = this._scale === "band" ? this._d3Scale.step() - this._d3Scale.bandwidth() : this._scale === "point" ? this._d3Scale.step() * this._d3Scale.padding() * -1 : 0;
var x2mod = this._scale === "band" ? this._d3Scale.step() : this._scale === "point" ? this._d3Scale.step() * this._d3Scale.padding() * -1 : 0;
bar.call(attrize, this._barConfig).attr("".concat(x, "1"), this._getPosition(domain[0]) - x1mod).attr("".concat(x, "2"), this._getPosition(domain[domain.length - 1]) + x2mod).attr("".concat(y, "1"), position).attr("".concat(y, "2"), position);
}
/**
@memberof Axis
@desc Returns the scale's domain, taking into account negative and positive log scales.
@private
*/
}, {
key: "_getDomain",
value: function _getDomain() {
var ticks = [];
if (this._d3ScaleNegative) ticks = this._d3ScaleNegative.domain();
if (this._d3Scale) ticks = ticks.concat(this._d3Scale.domain());
var domain = ["band", "ordinal", "point"].includes(this._scale) ? ticks : extent(ticks);
return ticks[0] > ticks[1] ? domain.reverse() : domain;
}
/**
@memberof Axis
@desc Returns a value's scale position, taking into account negative and positive log scales.
@param {Number|String} *d*
@private
*/
}, {
key: "_getPosition",
value: function _getPosition(d) {
return d < 0 && this._d3ScaleNegative ? this._d3ScaleNegative(d) : this._d3Scale(d);
}
/**
@memberof Axis
@desc Returns the scale's range, taking into account negative and positive log scales.
@private
*/
}, {
key: "_getRange",
value: function _getRange() {
var ticks = [];
if (this._d3ScaleNegative) ticks = this._d3ScaleNegative.range();
if (this._d3Scale) ticks = ticks.concat(this._d3Scale.range());
return ticks[0] > ticks[1] ? extent(ticks).reverse() : extent(ticks);
}
/**
@memberof Axis
@desc Returns the scale's ticks, taking into account negative and positive log scales.
@private
*/
}, {
key: "_getTicks",
value: function _getTicks() {
var tickScale = sqrt$1().domain([10, 400]).range([10, 50]);
var ticks = [];
if (this._d3ScaleNegative) {
var negativeRange = this._d3ScaleNegative.range();
var size = negativeRange[1] - negativeRange[0];
ticks = this._d3ScaleNegative.ticks(Math.floor(size / tickScale(size)));
}
if (this._d3Scale) {
var positiveRange = this._d3Scale.range();
var _size = positiveRange[1] - positiveRange[0];
ticks = ticks.concat(this._d3Scale.ticks(Math.floor(_size / tickScale(_size))));
}
return ticks;
}
/**
@memberof Axis
@desc Sets positioning for the grid lines.
@param {D3Selection} *lines*
@private
*/
}, {
key: "_gridPosition",
value: function _gridPosition(lines) {
var last = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var _this$_position2 = this._position,
height = _this$_position2.height,
x = _this$_position2.x,
y = _this$_position2.y,
opposite = _this$_position2.opposite,
offset = this._margin[opposite],
position = ["top", "left"].includes(this._orient) ? this._outerBounds[y] + this._outerBounds[height] - offset : this._outerBounds[y] + offset,
scale = last ? this._lastScale || this._getPosition.bind(this) : this._getPosition.bind(this),
size = ["top", "left"].includes(this._orient) ? offset : -offset,
xDiff = this._scale === "band" ? this._d3Scale.bandwidth() / 2 : 0,
xPos = function xPos(d) {
return scale(d.id) + xDiff;
};
lines.call(attrize, this._gridConfig).attr("".concat(x, "1"), xPos).attr("".concat(x, "2"), xPos).attr("".concat(y, "1"), position).attr("".concat(y, "2"), last ? position : position + size);
}
/**
@memberof Axis
@desc Renders the current Axis to the page. If a *callback* is specified, it will be called once the legend is done drawing.
@param {Function} [*callback* = undefined]
@chainable
*/
}, {
key: "render",
value: function render(callback) {
var _this2 = this,
_this$_outerBounds;
/**
* Creates an SVG element to contain the axis if none
* has been specified using the "select" method.
*/
if (this._select === void 0) {
this.select(_select("body").append("svg").attr("width", "".concat(this._width, "px")).attr("height", "".concat(this._height, "px")).node());
}
var timeLocale = this._timeLocale || locale$2[this._locale] || locale$2["en-US"];
defaultLocale$1(timeLocale).format();
var formatDay = timeFormat("%a %d"),
formatHour = timeFormat("%I %p"),
formatMillisecond = timeFormat(".%L"),
formatMinute = timeFormat("%I:%M"),
formatMonth = timeFormat("%b"),
formatSecond = timeFormat(":%S"),
formatWeek = timeFormat("%b %d"),
formatYear = timeFormat("%Y");
/**
* Declares some commonly used variables.
*/
var _this$_position3 = this._position,
width = _this$_position3.width,
height = _this$_position3.height,
x = _this$_position3.x,
y = _this$_position3.y,
horizontal = _this$_position3.horizontal,
opposite = _this$_position3.opposite,
clipId = "d3plus-Axis-clip-".concat(this._uuid),
flip = ["top", "left"].includes(this._orient),
p = this._padding,
parent = this._select,
rangeOuter = [p, this["_".concat(width)] - p],
t = transition().duration(this._duration);
var tickValue = this._shape === "Circle" ? this._shapeConfig.r : this._shape === "Rect" ? this._shapeConfig[width] : this._shapeConfig.strokeWidth;
var tickGet = typeof tickValue !== "function" ? function () {
return tickValue;
} : tickValue;
/**
* Zeros out the margins for re-calculation.
*/
var margin = this._margin = {
top: 0,
right: 0,
bottom: 0,
left: 0
};
var labels, range$1, ticks;
/**
* Constructs the tick formatter function.
*/
var tickFormat = this._tickFormat ? this._tickFormat : function (d) {
if (_this2._scale === "time") {
return (second(d) < d ? formatMillisecond : minute(d) < d ? formatSecond : hour(d) < d ? formatMinute : day(d) < d ? formatHour : month(d) < d ? sunday(d) < d ? formatDay : formatWeek : year(d) < d ? formatMonth : formatYear)(d);
} else if (["band", "ordinal", "point"].includes(_this2._scale)) {
return d;
}
if (isNaN(d)) {
return d;
} else if (_this2._scale === "linear" && _this2._tickSuffix === "smallest") {
var _locale = _typeof$f(_this2._locale) === "object" ? _this2._locale : formatLocale$3[_this2._locale];
var separator = _locale.separator,
suffixes = _locale.suffixes;
var suff = d >= 1000 ? suffixes[_this2._tickUnit + 8] : "";
var tick = d / Math.pow(10, 3 * _this2._tickUnit);
var number = formatAbbreviate(tick, _locale, ",.".concat(tick.toString().length, "r"));
return "".concat(number).concat(separator).concat(suff);
} else {
return formatAbbreviate(d, _this2._locale);
}
};
/**
* (Re)calculates the internal d3 scale
* @param {} newRange
*/
function setScale() {
var _this3 = this;
var newRange = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this._range;
/**
* Calculates the internal "range" array to use, including
* fallbacks if not specified with the "range" method.
*/
range$1 = newRange ? newRange.slice() : [undefined, undefined];
var minRange = rangeOuter[0],
maxRange = rangeOuter[1];
if (this._range) {
if (this._range[0] !== undefined) minRange = this._range[0];
if (this._range[this._range.length - 1] !== undefined) maxRange = this._range[this._range.length - 1];
}
if (range$1[0] === undefined || range$1[0] < minRange) range$1[0] = minRange;
if (range$1[1] === undefined || range$1[1] > maxRange) range$1[1] = maxRange;
var sizeInner = maxRange - minRange;
if (this._scale === "ordinal" && this._domain.length > range$1.length) {
if (newRange === this._range) {
var buckets = this._domain.length + 1;
range$1 = range(buckets).map(function (d) {
return range$1[0] + sizeInner * (d / (buckets - 1));
}).slice(1, buckets);
range$1 = range$1.map(function (d) {
return d - range$1[0] / 2;
});
} else {
var _buckets = this._domain.length;
var size = range$1[1] - range$1[0];
range$1 = range(_buckets).map(function (d) {
return range$1[0] + size * (d / (_buckets - 1));
});
}
} else if (newRange === this._range) {
var tickScale = sqrt$1().domain([10, 400]).range([10, 50]);
var domain = this._scale === "time" ? this._domain.map(date$2) : this._domain;
var scaleTicks = d3Ticks(domain[0], domain[1], Math.floor(sizeInner / tickScale(sizeInner)));
ticks = (this._ticks ? this._scale === "time" ? this._ticks.map(date$2) : this._ticks : scaleTicks).slice();
labels = (this._labels ? this._scale === "time" ? this._labels.map(date$2) : this._labels : scaleTicks).slice();
var _buckets2 = labels.length;
if (_buckets2) {
var pad = Math.ceil(sizeInner / _buckets2 / 2);
range$1 = [range$1[0] + pad, range$1[1] - pad];
}
}
/**
* Sets up the initial d3 scale, using this._domain and the
* previously defined range variable.
*/
var scale = "scale".concat(this._scale.charAt(0).toUpperCase()).concat(this._scale.slice(1));
this._d3Scale = scales[scale]().domain(this._scale === "time" ? this._domain.map(date$2) : this._domain).range(range$1);
if (this._d3Scale.padding) this._d3Scale.padding(this._scalePadding);
if (this._d3Scale.paddingInner) this._d3Scale.paddingInner(this._paddingInner);
if (this._d3Scale.paddingOuter) this._d3Scale.paddingOuter(this._paddingOuter);
/**
* Constructs a separate "negative only" scale for logarithmic
* domains, as they cannot pass zero.
*/
this._d3ScaleNegative = null;
if (this._scale === "log") {
var _domain = this._d3Scale.domain();
if (_domain[0] === 0) {
_domain[0] = Math.abs(_domain[_domain.length - 1]) <= 1 ? 1e-6 : 1;
if (_domain[_domain.length - 1] < 0) _domain[0] *= -1;
} else if (_domain[_domain.length - 1] === 0) {
_domain[_domain.length - 1] = Math.abs(_domain[0]) <= 1 ? 1e-6 : 1;
if (_domain[0] < 0) _domain[_domain.length - 1] *= -1;
}
var _range = this._d3Scale.range();
if (_domain[0] < 0 && _domain[_domain.length - 1] < 0) {
this._d3ScaleNegative = this._d3Scale.copy().domain(_domain).range(_range);
this._d3Scale = null;
} else if (_domain[0] > 0 && _domain[_domain.length - 1] > 0) {
this._d3Scale.domain(_domain).range(_range);
} else {
var percentScale = log().domain([1, _domain[_domain[1] > 0 ? 1 : 0]]).range([0, 1]);
var leftPercentage = percentScale(Math.abs(_domain[_domain[1] < 0 ? 1 : 0]));
var zero = leftPercentage / (leftPercentage + 1) * (_range[1] - _range[0]);
if (_domain[0] > 0) zero = _range[1] - _range[0] - zero;
this._d3ScaleNegative = this._d3Scale.copy();
(_domain[0] < 0 ? this._d3Scale : this._d3ScaleNegative).domain([Math.sign(_domain[1]), _domain[1]]).range([_range[0] + zero, _range[1]]);
(_domain[0] < 0 ? this._d3ScaleNegative : this._d3Scale).domain([_domain[0], Math.sign(_domain[0])]).range([_range[0], _range[0] + zero]);
}
}
/**
* Determines the of values array to use
* for the "ticks" and the "labels"
*/
ticks = (this._ticks ? this._scale === "time" ? this._ticks.map(date$2) : this._ticks : (this._d3Scale ? this._d3Scale.ticks : this._d3ScaleNegative.ticks) ? this._getTicks() : this._domain).slice();
labels = (this._labels ? this._scale === "time" ? this._labels.map(date$2) : this._labels : (this._d3Scale ? this._d3Scale.ticks : this._d3ScaleNegative.ticks) ? this._getTicks() : ticks).slice();
if (this._scale === "log") {
var tens = labels.filter(function (t) {
return Math.abs(t).toString().charAt(0) === "1" && (_this3._d3Scale ? t !== -1 : t !== 1);
});
if (tens.length > 2) {
labels = tens;
ticks = tens;
} else if (labels.length >= 10) {
labels = labels.filter(function (t) {
return t % 5 === 0 || tickFormat(t).substr(-1) === "1";
});
}
}
if (this._scale === "time") {
ticks = ticks.map(Number);
labels = labels.map(Number);
}
ticks = ticks.sort(function (a, b) {
return _this3._getPosition(a) - _this3._getPosition(b);
});
labels = labels.sort(function (a, b) {
return _this3._getPosition(a) - _this3._getPosition(b);
});
/**
* Get the smallest suffix.
*/
if (this._scale === "linear" && this._tickSuffix === "smallest") {
var suffixes = labels.filter(function (d) {
return d >= 1000;
});
if (suffixes.length > 0) {
var _min = Math.min.apply(Math, _toConsumableArray$1(suffixes));
var i = 1;
while (i && i < 7) {
var n = Math.pow(10, 3 * i);
if (_min / n >= 1) {
this._tickUnit = i;
i += 1;
} else {
break;
}
}
}
}
/**
* Removes ticks when they overlap other ticks.
*/
var pixels = [];
this._availableTicks = ticks;
ticks.forEach(function (d, i) {
var s = tickGet({
id: d,
tick: true
}, i);
if (_this3._shape === "Circle") s *= 2;
var t = _this3._getPosition(d);
if (!pixels.length || Math.abs(closest(t, pixels) - t) > s * 2) pixels.push(t);else pixels.push(false);
});
ticks = ticks.filter(function (d, i) {
return pixels[i] !== false;
});
this._visibleTicks = ticks;
}
setScale.bind(this)();
/**
* Calculates the space available for a given label.
* @param {Object} datum
*/
function calculateSpace(datum) {
var diff = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
var i = datum.i,
position = datum.position;
if (this._scale === "band") {
return this._d3Scale.bandwidth();
} else {
var prevPosition = i - diff < 0 ? textData.length === 1 || !this._range ? rangeOuter[0] : (position - textData[i + diff].position) / 2 - position : position - (position - textData[i - diff].position) / 2;
var prevSpace = Math.abs(position - prevPosition);
var nextPosition = i + diff > textData.length - 1 ? textData.length === 1 || !this._range ? rangeOuter[1] : (position - textData[i - diff].position) / 2 - position : position - (position - textData[i + diff].position) / 2;
var nextSpace = Math.abs(position - nextPosition);
return min([prevSpace, nextSpace]) * 2;
}
}
/**
* Pre-calculates the size of the title, if defined, in order
* to adjust the internal margins.
*/
if (this._title) {
var _this$_titleConfig = this._titleConfig,
fontFamily = _this$_titleConfig.fontFamily,
fontSize = _this$_titleConfig.fontSize,
lineHeight = _this$_titleConfig.lineHeight;
var titleWrap = textWrap().fontFamily(typeof fontFamily === "function" ? fontFamily() : fontFamily).fontSize(typeof fontSize === "function" ? fontSize() : fontSize).lineHeight(typeof lineHeight === "function" ? lineHeight() : lineHeight).width(range$1[range$1.length - 1] - range$1[0] - p * 2).height(this["_".concat(height)] - this._tickSize - p * 2);
var lines = titleWrap(this._title).lines.length;
margin[this._orient] = lines * titleWrap.lineHeight() + p;
}
var hBuff = this._shape === "Circle" ? typeof this._shapeConfig.r === "function" ? this._shapeConfig.r({
tick: true
}) : this._shapeConfig.r : this._shape === "Rect" ? typeof this._shapeConfig[height] === "function" ? this._shapeConfig[height]({
tick: true
}) : this._shapeConfig[height] : this._tickSize,
wBuff = tickGet({
tick: true
});
if (typeof hBuff === "function") hBuff = max(ticks.map(hBuff));
if (this._shape === "Rect") hBuff /= 2;
if (typeof wBuff === "function") wBuff = max(ticks.map(wBuff));
if (this._shape !== "Circle") wBuff /= 2;
/**
* Calculates the space each label would take up, given
* the provided this._space size.
*/
var textData = labels.map(function (d, i) {
var fF = _this2._shapeConfig.labelConfig.fontFamily(d, i),
fS = _this2._shapeConfig.labelConfig.fontSize(d, i),
position = _this2._getPosition(d);
var lineHeight = _this2._shapeConfig.lineHeight ? _this2._shapeConfig.lineHeight(d, i) : fS * 1.4;
return {
d: d,
i: i,
fF: fF,
fS: fS,
lineHeight: lineHeight,
position: position
};
});
/**
* Calculates the text wrapping and size of a given textData object.
* @param {Object} datum
*/
function calculateLabelSize(datum) {
var d = datum.d,
i = datum.i,
fF = datum.fF,
fS = datum.fS,
rotate = datum.rotate,
space = datum.space;
var h = rotate ? "width" : "height",
w = rotate ? "height" : "width";
var wSize = min([this._maxSize, this._width]);
var hSize = min([this._maxSize, this._height]);
var wrap = textWrap().fontFamily(fF).fontSize(fS).lineHeight(this._shapeConfig.lineHeight ? this._shapeConfig.lineHeight(d, i) : undefined)[w](horizontal ? space : wSize - hBuff - p - this._margin.left - this._margin.right)[h](horizontal ? hSize - hBuff - p - this._margin.top - this._margin.bottom : space);
var res = wrap(tickFormat(d));
res.lines = res.lines.filter(function (d) {
return d !== "";
});
res.width = res.lines.length ? Math.ceil(max(res.widths)) + fS / 4 : 0;
if (res.width % 2) res.width++;
res.height = res.lines.length ? Math.ceil(res.lines.length * wrap.lineHeight()) + fS / 4 : 0;
if (res.height % 2) res.height++;
return res;
}
textData = textData.map(function (datum) {
datum.rotate = _this2._labelRotation;
datum.space = calculateSpace.bind(_this2)(datum);
var res = calculateLabelSize.bind(_this2)(datum);
return Object.assign(res, datum);
});
this._rotateLabels = horizontal && this._labelRotation === undefined ? textData.some(function (d) {
return d.truncated;
}) : this._labelRotation;
if (this._rotateLabels) {
textData = textData.map(function (datum) {
datum.rotate = true;
var res = calculateLabelSize.bind(_this2)(datum);
return Object.assign(datum, res);
});
}
/**
* "spillover" will contain the pixel spillover of the first and last label,
* and then adjust the scale range accordingly.
*/
var spillover = [0, 0];
for (var index = 0; index < 2; index++) {
var datum = textData[index ? textData.length - 1 : 0];
if (!datum) break;
var _height = datum.height,
position = datum.position,
rotate = datum.rotate,
_width = datum.width;
var compPosition = index ? rangeOuter[1] : rangeOuter[0];
var halfSpace = (rotate || !horizontal ? _height : _width) / 2;
var spill = index ? position + halfSpace - compPosition : position - halfSpace - compPosition;
spillover[index] = spill;
}
var first = range$1[0];
var last = range$1[range$1.length - 1];
var newRange = [first - spillover[0], last - spillover[1]];
if (this._range) {
if (this._range[0] !== undefined) newRange[0] = this._range[0];
if (this._range[this._range.length - 1] !== undefined) newRange[1] = this._range[this._range.length - 1];
}
if (newRange[0] !== first || newRange[1] !== last) {
setScale.bind(this)(newRange);
textData = labels.map(function (d, i) {
var fF = _this2._shapeConfig.labelConfig.fontFamily(d, i),
fS = _this2._shapeConfig.labelConfig.fontSize(d, i),
position = _this2._getPosition(d);
var lineHeight = _this2._shapeConfig.lineHeight ? _this2._shapeConfig.lineHeight(d, i) : fS * 1.4;
return {
d: d,
i: i,
fF: fF,
fS: fS,
lineHeight: lineHeight,
position: position
};
});
textData = textData.map(function (datum) {
datum.rotate = _this2._rotateLabels;
datum.space = calculateSpace.bind(_this2)(datum);
var res = calculateLabelSize.bind(_this2)(datum);
return Object.assign(res, datum);
});
}
var labelHeight = max(textData, function (t) {
return t.height;
}) || 0;
this._rotateLabels = horizontal && this._labelRotation === undefined ? textData.some(function (datum) {
var i = datum.i,
height = datum.height,
position = datum.position,
truncated = datum.truncated;
var prev = textData[i - 1];
return truncated || i && prev.position + prev.height / 2 > position - height / 2;
}) : this._labelRotation;
if (this._rotateLabels) {
var offset = 0;
textData = textData.map(function (datum) {
datum.space = calculateSpace.bind(_this2)(datum, 2);
var res = calculateLabelSize.bind(_this2)(datum);
datum = Object.assign(datum, res);
var prev = textData[datum.i - 1];
if (!prev) {
offset = 1;
} else if (prev.position + prev.height / 2 > datum.position) {
if (offset) {
datum.offset = prev.width;
offset = 0;
} else offset = 1;
}
return datum;
});
}
var globalOffset = this._labelOffset ? max(textData, function (d) {
return d.offset || 0;
}) : 0;
textData.forEach(function (datum) {
return datum.offset = datum.offset ? globalOffset : 0;
});
var tBuff = this._shape === "Line" ? 0 : hBuff;
var bounds = this._outerBounds = (_this$_outerBounds = {}, _defineProperty$2(_this$_outerBounds, height, (max(textData, function (t) {
return Math.ceil(t[t.rotate || !horizontal ? "width" : "height"] + t.offset);
}) || 0) + (textData.length ? p : 0)), _defineProperty$2(_this$_outerBounds, width, rangeOuter[rangeOuter.length - 1] - rangeOuter[0]), _defineProperty$2(_this$_outerBounds, x, rangeOuter[0]), _this$_outerBounds);
bounds[height] = max([this._minSize, bounds[height]]);
margin[this._orient] += hBuff;
margin[opposite] = this._gridSize !== undefined ? max([this._gridSize, tBuff]) : this["_".concat(height)] - margin[this._orient] - bounds[height] - p;
bounds[height] += margin[opposite] + margin[this._orient];
bounds[y] = this._align === "start" ? this._padding : this._align === "end" ? this["_".concat(height)] - bounds[height] - this._padding : this["_".concat(height)] / 2 - bounds[height] / 2;
var group = elem("g#d3plus-Axis-".concat(this._uuid), {
parent: parent
});
this._group = group;
var grid = elem("g.grid", {
parent: group
}).selectAll("line").data((this._gridSize !== 0 ? this._grid || this._scale === "log" && !this._gridLog ? labels : ticks : []).map(function (d) {
return {
id: d
};
}), function (d) {
return d.id;
});
grid.exit().transition(t).attr("opacity", 0).call(this._gridPosition.bind(this)).remove();
grid.enter().append("line").attr("opacity", 0).attr("clip-path", "url(#".concat(clipId, ")")).call(this._gridPosition.bind(this), true).merge(grid).transition(t).attr("opacity", 1).call(this._gridPosition.bind(this));
var labelOnly = labels.filter(function (d, i) {
return textData[i].lines.length && !ticks.includes(d);
});
var rotated = textData.some(function (d) {
return d.rotate;
});
var tickData = ticks.concat(labelOnly).map(function (d) {
var _tickConfig;
var data = textData.find(function (td) {
return td.d === d;
});
var xPos = _this2._getPosition(d);
var space = data ? data.space : 0;
var lines = data ? data.lines.length : 1;
var lineHeight = data ? data.lineHeight : 1;
var labelOffset = data && _this2._labelOffset ? data.offset : 0;
var labelWidth = horizontal ? space : bounds.width - margin[_this2._position.opposite] - hBuff - margin[_this2._orient] + p;
var offset = margin[opposite],
size = (hBuff + labelOffset) * (flip ? -1 : 1),
yPos = flip ? bounds[y] + bounds[height] - offset : bounds[y] + offset;
var tickConfig = (_tickConfig = {
id: d,
labelBounds: rotated && data ? {
x: -data.width / 2 + data.fS / 4,
y: _this2._orient === "bottom" ? size + p + (data.width - lineHeight * lines) / 2 : size - p * 2 - (data.width + lineHeight * lines) / 2,
width: data.width,
height: data.height
} : {
x: horizontal ? -space / 2 : _this2._orient === "left" ? -labelWidth - p + size : size + p,
y: horizontal ? _this2._orient === "bottom" ? size + p : size - p - labelHeight : -space / 2,
width: horizontal ? space : labelWidth,
height: horizontal ? labelHeight : space
},
rotate: data ? data.rotate : false,
size: labels.includes(d) ? size : 0,
text: labels.includes(d) ? tickFormat(d) : false,
tick: ticks.includes(d)
}, _defineProperty$2(_tickConfig, x, xPos + (_this2._scale === "band" ? _this2._d3Scale.bandwidth() / 2 : 0)), _defineProperty$2(_tickConfig, y, yPos), _tickConfig);
return tickConfig;
});
if (this._shape === "Line") {
tickData = tickData.concat(tickData.map(function (d) {
var dupe = Object.assign({}, d);
dupe[y] += d.size;
return dupe;
}));
}
new shapes$2[this._shape]().data(tickData).duration(this._duration).labelConfig({
ellipsis: function ellipsis(d) {
return d && d.length ? "".concat(d, "...") : "";
},
rotate: function rotate(d) {
return d.rotate ? -90 : 0;
}
}).select(elem("g.ticks", {
parent: group
}).node()).config(this._shapeConfig).render();
var bar = group.selectAll("line.bar").data([null]);
bar.enter().append("line").attr("class", "bar").attr("opacity", 0).call(this._barPosition.bind(this)).merge(bar).transition(t).attr("opacity", 1).call(this._barPosition.bind(this));
this._titleClass.data(this._title ? [{
text: this._title
}] : []).duration(this._duration).height(margin[this._orient]).rotate(this._orient === "left" ? -90 : this._orient === "right" ? 90 : 0).select(elem("g.d3plus-Axis-title", {
parent: group
}).node()).text(function (d) {
return d.text;
}).verticalAlign("middle").width(range$1[range$1.length - 1] - range$1[0]).x(horizontal ? range$1[0] : this._orient === "left" ? bounds.x + margin.left / 2 - (range$1[range$1.length - 1] - range$1[0]) / 2 : bounds.x + bounds.width - margin.right / 2 - (range$1[range$1.length - 1] - range$1[0]) / 2).y(horizontal ? this._orient === "bottom" ? bounds.y + bounds.height - margin.bottom : bounds.y : range$1[0] + (range$1[range$1.length - 1] - range$1[0]) / 2 - margin[this._orient] / 2).config(this._titleConfig).render();
this._lastScale = this._getPosition.bind(this);
if (callback) setTimeout(callback, this._duration + 100);
return this;
}
/**
@memberof Axis
@desc If *value* is specified, sets the horizontal alignment to the specified value and returns the current class instance.
@param {String} [*value* = "center"] Supports `"left"` and `"center"` and `"right"`.
@chainable
*/
}, {
key: "align",
value: function align(_) {
return arguments.length ? (this._align = _, this) : this._align;
}
/**
@memberof Axis
@desc If *value* is specified, sets the axis line style and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "barConfig",
value: function barConfig(_) {
return arguments.length ? (this._barConfig = Object.assign(this._barConfig, _), this) : this._barConfig;
}
/**
@memberof Axis
@desc If *value* is specified, sets the scale domain of the axis and returns the current class instance.
@param {Array} [*value* = [0, 10]]
@chainable
*/
}, {
key: "domain",
value: function domain(_) {
return arguments.length ? (this._domain = _, this) : this._domain;
}
/**
@memberof Axis
@desc If *value* is specified, sets the transition duration of the axis and returns the current class instance.
@param {Number} [*value* = 600]
@chainable
*/
}, {
key: "duration",
value: function duration(_) {
return arguments.length ? (this._duration = _, this) : this._duration;
}
/**
@memberof Axis
@desc If *value* is specified, sets the grid values of the axis and returns the current class instance.
@param {Array} [*value*]
@chainable
*/
}, {
key: "grid",
value: function grid(_) {
return arguments.length ? (this._grid = _, this) : this._grid;
}
/**
@memberof Axis
@desc If *value* is specified, sets the grid config of the axis and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "gridConfig",
value: function gridConfig(_) {
return arguments.length ? (this._gridConfig = Object.assign(this._gridConfig, _), this) : this._gridConfig;
}
/**
@memberof Axis
@desc If *value* is specified, sets the grid behavior of the axis when scale is logarithmic and returns the current class instance.
@param {Boolean} [*value* = false]
@chainable
*/
}, {
key: "gridLog",
value: function gridLog(_) {
return arguments.length ? (this._gridLog = _, this) : this._gridLog;
}
/**
@memberof Axis
@desc If *value* is specified, sets the grid size of the axis and returns the current class instance.
@param {Number} [*value* = undefined]
@chainable
*/
}, {
key: "gridSize",
value: function gridSize(_) {
return arguments.length ? (this._gridSize = _, this) : this._gridSize;
}
/**
@memberof Axis
@desc If *value* is specified, sets the overall height of the axis and returns the current class instance.
@param {Number} [*value* = 100]
@chainable
*/
}, {
key: "height",
value: function height(_) {
return arguments.length ? (this._height = _, this) : this._height;
}
/**
@memberof Axis
@desc If *value* is specified, sets the visible tick labels of the axis and returns the current class instance.
@param {Array} [*value*]
@chainable
*/
}, {
key: "labels",
value: function labels(_) {
return arguments.length ? (this._labels = _, this) : this._labels;
}
/**
@memberof Axis
@desc If *value* is specified, sets whether offsets will be used to position some labels further away from the axis in order to allow space for the text.
@param {Boolean} [*value* = true]
@chainable
*/
}, {
key: "labelOffset",
value: function labelOffset(_) {
return arguments.length ? (this._labelOffset = _, this) : this._labelOffset;
}
/**
@memberof Axis
@desc If *value* is specified, sets whether whether horizontal axis labels are rotated -90 degrees.
@param {Boolean}
@chainable
*/
}, {
key: "labelRotation",
value: function labelRotation(_) {
return arguments.length ? (this._labelRotation = _, this) : this._labelRotation;
}
/**
@memberof Axis
@desc If *value* is specified, sets the maximum size allowed for the space that contains the axis tick labels and title.
@param {Number}
@chainable
*/
}, {
key: "maxSize",
value: function maxSize(_) {
return arguments.length ? (this._maxSize = _, this) : this._maxSize;
}
/**
@memberof Axis
@desc If *value* is specified, sets the minimum size alloted for the space that contains the axis tick labels and title.
@param {Number}
@chainable
*/
}, {
key: "minSize",
value: function minSize(_) {
return arguments.length ? (this._minSize = _, this) : this._minSize;
}
/**
@memberof Axis
@desc If *orient* is specified, sets the orientation of the shape and returns the current class instance. If *orient* is not specified, returns the current orientation.
@param {String} [*orient* = "bottom"] Supports `"top"`, `"right"`, `"bottom"`, and `"left"` orientations.
@chainable
*/
}, {
key: "orient",
value: function orient(_) {
if (arguments.length) {
var horizontal = ["top", "bottom"].includes(_),
opps = {
top: "bottom",
right: "left",
bottom: "top",
left: "right"
};
this._position = {
horizontal: horizontal,
width: horizontal ? "width" : "height",
height: horizontal ? "height" : "width",
x: horizontal ? "x" : "y",
y: horizontal ? "y" : "x",
opposite: opps[_]
};
return this._orient = _, this;
}
return this._orient;
}
/**
@memberof Axis
@desc If called after the elements have been drawn to DOM, will returns the outer bounds of the axis content.
@example
{"width": 180, "height": 24, "x": 10, "y": 20}
*/
}, {
key: "outerBounds",
value: function outerBounds() {
return this._outerBounds;
}
/**
@memberof Axis
@desc If *value* is specified, sets the padding between each tick label to the specified number and returns the current class instance.
@param {Number} [*value* = 10]
@chainable
*/
}, {
key: "padding",
value: function padding(_) {
return arguments.length ? (this._padding = _, this) : this._padding;
}
/**
@memberof Axis
@desc If *value* is specified, sets the inner padding of band scale to the specified number and returns the current class instance.
@param {Number} [*value* = 0.1]
@chainable
*/
}, {
key: "paddingInner",
value: function paddingInner(_) {
return arguments.length ? (this._paddingInner = _, this) : this._paddingInner;
}
/**
@memberof Axis
@desc If *value* is specified, sets the outer padding of band scales to the specified number and returns the current class instance.
@param {Number} [*value* = 0.1]
@chainable
*/
}, {
key: "paddingOuter",
value: function paddingOuter(_) {
return arguments.length ? (this._paddingOuter = _, this) : this._paddingOuter;
}
/**
@memberof Axis
@desc If *value* is specified, sets the scale range (in pixels) of the axis and returns the current class instance. The given array must have 2 values, but one may be `undefined` to allow the default behavior for that value.
@param {Array} [*value*]
@chainable
*/
}, {
key: "range",
value: function range(_) {
return arguments.length ? (this._range = _, this) : this._range;
}
/**
@memberof Axis
@desc If *value* is specified, sets the scale of the axis and returns the current class instance.
@param {String} [*value* = "linear"]
@chainable
*/
}, {
key: "scale",
value: function scale(_) {
return arguments.length ? (this._scale = _, this) : this._scale;
}
/**
@memberof Axis
@desc Sets the "padding" property of the scale, often used in point scales.
@param {Number} [*value* = 0.5]
@chainable
*/
}, {
key: "scalePadding",
value: function scalePadding(_) {
return arguments.length ? (this._scalePadding = _, this) : this._scalePadding;
}
/**
@memberof Axis
@desc If *selector* is specified, sets the SVG container element to the specified d3 selector or DOM element and returns the current class instance. If *selector* is not specified, returns the current SVG container element.
@param {String|HTMLElement} [*selector* = d3.select("body").append("svg")]
@chainable
*/
}, {
key: "select",
value: function select(_) {
return arguments.length ? (this._select = _select(_), this) : this._select;
}
/**
@memberof Axis
@desc If *value* is specified, sets the tick shape constructor and returns the current class instance.
@param {String} [*value* = "Line"]
@chainable
*/
}, {
key: "shape",
value: function shape(_) {
return arguments.length ? (this._shape = _, this) : this._shape;
}
/**
@memberof Axis
@desc If *value* is specified, sets the tick style of the axis and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "shapeConfig",
value: function shapeConfig(_) {
return arguments.length ? (this._shapeConfig = assign(this._shapeConfig, _), this) : this._shapeConfig;
}
/**
@memberof Axis
@desc If *value* is specified, sets the tick formatter and returns the current class instance.
@param {Function} [*value*]
@chainable
*/
}, {
key: "tickFormat",
value: function tickFormat(_) {
return arguments.length ? (this._tickFormat = _, this) : this._tickFormat;
}
/**
@memberof Axis
@desc If *value* is specified, sets the tick values of the axis and returns the current class instance.
@param {Array} [*value*]
@chainable
*/
}, {
key: "ticks",
value: function ticks(_) {
return arguments.length ? (this._ticks = _, this) : this._ticks;
}
/**
@memberof Axis
@desc If *value* is specified, sets the tick size of the axis and returns the current class instance.
@param {Number} [*value* = 5]
@chainable
*/
}, {
key: "tickSize",
value: function tickSize(_) {
return arguments.length ? (this._tickSize = _, this) : this._tickSize;
}
/**
@memberof Axis
@desc Sets the tick specifier for the [tickFormat](https://github.com/d3/d3-scale#continuous_tickFormat) function. If this method is called without any arguments, the default tick specifier is returned.
@param {String} [*value* = undefined]
@chainable
*/
}, {
key: "tickSpecifier",
value: function tickSpecifier(_) {
return arguments.length ? (this._tickSpecifier = _, this) : this._tickSpecifier;
}
/**
@memberof Axis
@desc Sets the behavior of the abbreviations when you are using linear scale. This method accepts two options: "normal" (uses formatAbbreviate to determinate the abbreviation) and "smallest" (uses suffix from the smallest tick as reference in every tick).
@param {String} [*value* = "normal"]
@chainable
*/
}, {
key: "tickSuffix",
value: function tickSuffix(_) {
return arguments.length ? (this._tickSuffix = _, this) : this._tickSuffix;
}
/**
@memberof Axis
@desc Defines a custom locale object to be used in time scale. This object must include the following properties: dateTime, date, time, periods, days, shortDays, months, shortMonths. For more information, you can revise [d3p.d3-time-format](https://github.com/d3/d3-time-format/blob/master/README.md#timeFormatLocale).
@param {Object} [*value* = undefined]
@chainable
*/
}, {
key: "timeLocale",
value: function timeLocale(_) {
return arguments.length ? (this._timeLocale = _, this) : this._timeLocale;
}
/**
@memberof Axis
@desc If *value* is specified, sets the title of the axis and returns the current class instance.
@param {String} [*value*]
@chainable
*/
}, {
key: "title",
value: function title(_) {
return arguments.length ? (this._title = _, this) : this._title;
}
/**
@memberof Axis
@desc If *value* is specified, sets the title configuration of the axis and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "titleConfig",
value: function titleConfig(_) {
return arguments.length ? (this._titleConfig = Object.assign(this._titleConfig, _), this) : this._titleConfig;
}
/**
@memberof Axis
@desc If *value* is specified, sets the overall width of the axis and returns the current class instance.
@param {Number} [*value* = 400]
@chainable
*/
}, {
key: "width",
value: function width(_) {
return arguments.length ? (this._width = _, this) : this._width;
}
}]);
return Axis;
}(BaseClass);
function _typeof$g(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$g = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$g = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$g(obj);
}
function _classCallCheck$e(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$e(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$e(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$e(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$e(Constructor, staticProps);
return Constructor;
}
function _inherits$c(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$c(subClass, superClass);
}
function _setPrototypeOf$c(o, p) {
_setPrototypeOf$c = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$c(o, p);
}
function _createSuper$c(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$c();
return function _createSuperInternal() {
var Super = _getPrototypeOf$c(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$c(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$c(this, result);
};
}
function _possibleConstructorReturn$c(self, call) {
if (call && (_typeof$g(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$c(self);
}
function _assertThisInitialized$c(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$c() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$c(o) {
_getPrototypeOf$c = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$c(o);
}
/**
@class Button
@extends external:BaseClass
@desc Creates a set of HTML radio input elements.
*/
var Button = /*#__PURE__*/function (_BaseClass) {
_inherits$c(Button, _BaseClass);
var _super = _createSuper$c(Button);
/**
@memberof Button
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function Button() {
var _this;
_classCallCheck$e(this, Button);
_this = _super.call(this);
_this._buttonStyle = {
"font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
"font-size": "14px",
"margin": "0 5px"
};
_this._data = [];
_this._text = accessor("text");
_this._value = accessor("value");
return _this;
}
/**
@memberof Button
@desc Renders the element to the page.
@chainable
*/
_createClass$e(Button, [{
key: "render",
value: function render() {
var _this2 = this;
if (this._container === void 0) this.container(_select("body").append("div").node());
var container = this._container.selectAll("div#d3plus-Form-".concat(this._uuid)).data([0]);
var svg = this._container.node().tagName.toLowerCase() === "foreignobject";
container = container.enter().append(svg ? "xhtml:div" : "div").attr("id", "d3plus-Form-".concat(this._uuid)).attr("class", "d3plus-Form d3plus-Form-Button").merge(container);
var button = container.selectAll("button").data(this._data, function (d, i) {
return _this2._value(d, i);
});
button.exit().remove();
button = button.enter().append("button").attr("class", "d3plus-Button").attr("type", "button").merge(button).call(stylize, this._buttonStyle).html(function (d, i) {
return _this2._text(d, i);
});
for (var event in this._on) {
if ({}.hasOwnProperty.call(this._on, event)) button.on(event, this._on[event]);
}
return this;
}
/**
@memberof Button
@desc Sets the css styles for the <input type="radio"> elements.
@param {Object} [*value*]
@chainable
*/
}, {
key: "buttonStyle",
value: function buttonStyle(_) {
return arguments.length ? (this._buttonStyle = _, this) : this._buttonStyle;
}
/**
@memberof Button
@desc If *selector* is specified, sets the SVG container element to the specified d3 selector or DOM element and returns the current class instance. If *selector* is not specified, returns the current SVG container element, which is `undefined` by default.
@param {String|HTMLElement} [*selector*]
@chainable
*/
}, {
key: "container",
value: function container(_) {
return arguments.length ? (this._container = _select(_), this) : this._container;
}
/**
@memberof Radio
@desc Defines the array of values to be created as <button> tags. If no value is passed, the current array is returned.
@param {Array} [*value* = []]
@chainable
*/
}, {
key: "data",
value: function data(_) {
return arguments.length ? (this._data = _, this) : this._data;
}
/**
@memberof Button
@desc Sets the inner text for each <button> element.
@param {Function|String} [*value* = function(d) { return d.text; }]
@chainable
*/
}, {
key: "text",
value: function text(_) {
return arguments.length ? (this._text = typeof _ === "function" ? _ : constant$1(_), this) : this._text;
}
/**
@memberof Button
@desc Sets the value for each <button> element.
@param {Function} [*value* = function(d) { return d.value; }]
@chainable
*/
}, {
key: "value",
value: function value(_) {
return arguments.length ? (this._value = _, this) : this._value;
}
}]);
return Button;
}(BaseClass);
function _typeof$h(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$h = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$h = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$h(obj);
}
function _classCallCheck$f(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$f(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$f(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$f(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$f(Constructor, staticProps);
return Constructor;
}
function _inherits$d(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$d(subClass, superClass);
}
function _setPrototypeOf$d(o, p) {
_setPrototypeOf$d = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$d(o, p);
}
function _createSuper$d(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$d();
return function _createSuperInternal() {
var Super = _getPrototypeOf$d(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$d(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$d(this, result);
};
}
function _possibleConstructorReturn$d(self, call) {
if (call && (_typeof$h(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$d(self);
}
function _assertThisInitialized$d(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$d() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$d(o) {
_getPrototypeOf$d = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$d(o);
}
/**
@class Radio
@extends external:BaseClass
@desc Creates a set of HTML radio input elements.
*/
var Radio = /*#__PURE__*/function (_BaseClass) {
_inherits$d(Radio, _BaseClass);
var _super = _createSuper$d(Radio);
/**
@memberof Radio
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function Radio() {
var _this;
_classCallCheck$f(this, Radio);
_this = _super.call(this);
_this._labelStyle = {
"font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
"font-size": "14px",
"padding-right": "5px"
};
_this._legendStyle = {
"font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
"font-size": "14px",
"padding-right": "5px"
};
_this._options = [];
_this._radioStyle = {
"margin-right": "10px"
};
_this._text = accessor("text");
_this._value = accessor("value");
return _this;
}
/**
@memberof Radio
@desc Renders the element to the page.
@chainable
*/
_createClass$f(Radio, [{
key: "render",
value: function render() {
var _this2 = this;
if (this._container === void 0) this.container(_select("body").append("div").node());
var that = this;
var container = this._container.selectAll("div#d3plus-Form-".concat(this._uuid)).data([0]);
var svg = this._container.node().tagName.toLowerCase() === "foreignobject";
container = container.enter().append(svg ? "xhtml:div" : "div").attr("id", "d3plus-Form-".concat(this._uuid)).attr("class", "d3plus-Form d3plus-Form-Radio").merge(container);
var radios = container.selectAll("label").data(this._options, function (d, i) {
return _this2._value(d, i);
});
radios.exit().each(function () {
_select(this.nextSibling).remove();
}).remove();
radios = radios.enter().append("label").attr("class", "d3plus-Label").attr("for", function (d, i) {
return "".concat(_this2._uuid, "-").concat(_this2._value(d, i));
}).each(function (d, i) {
var input = document.createElement("input");
input.setAttribute("type", "radio");
input.setAttribute("name", "d3plus-Radio-".concat(that._uuid));
input.setAttribute("id", "".concat(that._uuid, "-").concat(that._value(d, i)));
input.setAttribute("value", that._value(d, i));
this.parentNode.insertBefore(input, this.nextSibling);
}).merge(radios).call(stylize, this._labelStyle).html(function (d, i) {
return _this2._text(d, i);
}).each(function (d, i) {
var checked = that._checked === void 0 ? !i : "".concat(that._value(d, i)) === "".concat(that._checked);
_select(this).classed("active", checked).style("cursor", checked ? "default" : "pointer");
var input = _select(this.nextSibling).property("checked", checked).call(stylize, that._radioStyle).style("cursor", checked ? "default" : "pointer").on("change.d3plus", function () {
that.checked(this.value);
radios.each(function (d, i) {
var checked = "".concat(that._value(d, i)) === "".concat(that._checked);
_select(this).classed("active", checked).style("cursor", checked ? "default" : "pointer");
_select(this.nextSibling).style("cursor", checked ? "default" : "pointer");
});
});
for (var event in that._on) {
if ({}.hasOwnProperty.call(that._on, event)) input.on(event, that._on[event]);
}
});
var legend = container.selectAll("legend#d3plus-Legend-".concat(this._uuid)).data(this._legend ? [0] : []);
legend.exit().remove();
legend.enter().insert("legend", ".d3plus-Label").attr("id", "d3plus-Legend-".concat(this._uuid)).attr("class", "d3plus-Legend").merge(legend).call(stylize, this._legendStyle).html(this._legend);
return this;
}
/**
@memberof Radio
@desc Defines the checked input.
@param {Function} [*value*]
@chainable
*/
}, {
key: "checked",
value: function checked(_) {
return arguments.length ? (this._checked = _, this) : this._checked;
}
/**
@memberof Radio
@desc If *selector* is specified, sets the SVG container element to the specified d3 selector or DOM element and returns the current class instance. If *selector* is not specified, returns the current SVG container element, which is `undefined` by default.
@param {String|HTMLElement} [*selector*]
@chainable
*/
}, {
key: "container",
value: function container(_) {
return arguments.length ? (this._container = _select(_), this) : this._container;
}
/**
@memberof Radio
@desc Sets the css styles for the <label> element.
@param {Object} [*value*]
@chainable
*/
}, {
key: "labelStyle",
value: function labelStyle(_) {
return arguments.length ? (this._labelStyle = _, this) : this._labelStyle;
}
/**
@memberof Radio
@desc Creates a <legend> tag for the <select> element.
@param {String} [*value*]
@chainable
*/
}, {
key: "legend",
value: function legend(_) {
return arguments.length ? (this._legend = _, this) : this._legend;
}
/**
@memberof Radio
@desc Sets the css styles for the <legend> element.
@param {Object} [*value*]
@chainable
*/
}, {
key: "legendStyle",
value: function legendStyle(_) {
return arguments.length ? (this._legendStyle = _, this) : this._legendStyle;
}
/**
@memberof Radio
@desc Defines the array of values to be used as <option> tags inside of the <select> element. If no value is passed, the current array is returned.
@param {Array} [*value* = []]
@chainable
*/
}, {
key: "options",
value: function options(_) {
return arguments.length ? (this._options = _, this) : this._options;
}
/**
@memberof Radio
@desc Sets the css styles for the <input type="radio"> elements.
@param {Object} [*value*]
@chainable
*/
}, {
key: "radioStyle",
value: function radioStyle(_) {
return arguments.length ? (this._radioStyle = _, this) : this._radioStyle;
}
/**
@memberof Radio
@desc Sets the inner text for each <option> element.
@param {Function|String} [*value* = function(d) { return d.text; }]
@chainable
*/
}, {
key: "text",
value: function text(_) {
return arguments.length ? (this._text = typeof _ === "function" ? _ : constant$1(_), this) : this._text;
}
/**
@memberof Radio
@desc Sets the value for each <option> element.
@param {Function} [*value* = function(d) { return d.value; }]
@chainable
*/
}, {
key: "value",
value: function value(_) {
return arguments.length ? (this._value = _, this) : this._value;
}
}]);
return Radio;
}(BaseClass);
function _typeof$i(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$i = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$i = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$i(obj);
}
function _classCallCheck$g(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$g(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$g(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$g(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$g(Constructor, staticProps);
return Constructor;
}
function _inherits$e(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$e(subClass, superClass);
}
function _setPrototypeOf$e(o, p) {
_setPrototypeOf$e = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$e(o, p);
}
function _createSuper$e(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$e();
return function _createSuperInternal() {
var Super = _getPrototypeOf$e(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$e(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$e(this, result);
};
}
function _possibleConstructorReturn$e(self, call) {
if (call && (_typeof$i(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$e(self);
}
function _assertThisInitialized$e(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$e() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$e(o) {
_getPrototypeOf$e = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$e(o);
}
/**
@class Select
@extends external:BaseClass
@desc Creates an HTML select element.
*/
var Select = /*#__PURE__*/function (_BaseClass) {
_inherits$e(Select, _BaseClass);
var _super = _createSuper$e(Select);
/**
@memberof Select
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function Select() {
var _this;
_classCallCheck$g(this, Select);
_this = _super.call(this);
_this._labelStyle = {
"font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
"font-size": "14px",
"margin-right": "5px"
};
_this._options = [];
_this._optionStyle = {
"font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
"font-size": "14px"
};
_this._selectStyle = {
"background": "#fafafa",
"border": "1px solid #ccc",
"border-radius": "0",
"font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
"font-size": "14px",
"outline": "0",
"padding": "3px 5px 4px"
};
_this._text = accessor("text");
_this._value = accessor("value");
return _this;
}
/**
@memberof Select
@desc Renders the element to the page.
@chainable
*/
_createClass$g(Select, [{
key: "render",
value: function render() {
var _this2 = this;
if (this._container === void 0) this.container(select("body").append("div").node());
var that = this;
var container = this._container.selectAll("div#d3plus-Form-".concat(this._uuid)).data([0]);
var svg = this._container.node().tagName.toLowerCase() === "foreignobject";
container = container.enter().append(svg ? "xhtml:div" : "div").attr("id", "d3plus-Form-".concat(this._uuid)).attr("class", "d3plus-Form d3plus-Form-Select").merge(container);
var select = container.selectAll("select#d3plus-Select-".concat(this._uuid)).data([0]);
select = select.enter().append("select").attr("id", "d3plus-Select-".concat(this._uuid)).attr("class", "d3plus-Select").merge(select).call(stylize, this._selectStyle).on("change.d3plus", function () {
that.selected(this.value);
});
for (var event in this._on) {
if ({}.hasOwnProperty.call(this._on, event)) select.on(event, this._on[event]);
}
var options = select.selectAll("option").data(this._options, function (d, i) {
return _this2._value(d, i);
});
options.exit().remove();
options.enter().append("option").attr("class", "d3plus-Option").merge(options).call(stylize, this._optionStyle).attr("value", function (d, i) {
return _this2._value(d, i);
}).html(function (d, i) {
return _this2._text(d, i);
}).property("selected", function (d, i) {
return _this2._selected === void 0 ? !i : "".concat(_this2._value(d, i)) === "".concat(_this2._selected);
});
var label = container.selectAll("label#d3plus-Label-".concat(this._uuid)).data(this._label ? [0] : []);
label.exit().remove();
label.enter().insert("label", "#d3plus-Select-".concat(this._uuid)).attr("id", "d3plus-Label-".concat(this._uuid)).attr("class", "d3plus-Label").attr("for", "d3plus-Select-".concat(this._uuid)).merge(label).call(stylize, this._labelStyle).html(this._label);
return this;
}
/**
@memberof Select
@desc If *selector* is specified, sets the SVG container element to the specified d3 selector or DOM element and returns the current class instance. If *selector* is not specified, returns the current SVG container element, which is `undefined` by default.
@param {String|HTMLElement} [*selector*]
@chainable
*/
}, {
key: "container",
value: function container(_) {
return arguments.length ? (this._container = _select(_), this) : this._container;
}
/**
@memberof Select
@desc Creates a <label> tag for the <select> element.
@param {String} [*value*]
@chainable
*/
}, {
key: "label",
value: function label(_) {
return arguments.length ? (this._label = _, this) : this._label;
}
/**
@memberof Select
@desc Sets the css styles for the <label> element.
@param {Object} [*value*]
@chainable
*/
}, {
key: "labelStyle",
value: function labelStyle(_) {
return arguments.length ? (this._labelStyle = _, this) : this._labelStyle;
}
/**
@memberof Select
@desc Defines the array of values to be used as <option> tags inside of the <select> element. If no value is passed, the current array is returned.
@param {Array} [*value* = []]
@chainable
*/
}, {
key: "options",
value: function options(_) {
return arguments.length ? (this._options = _, this) : this._options;
}
/**
@memberof Select
@desc Sets the css styles for the <option> elements.
@param {Object} [*value*]
@chainable
*/
}, {
key: "optionStyle",
value: function optionStyle(_) {
return arguments.length ? (this._optionStyle = _, this) : this._optionStyle;
}
/**
@memberof Select
@desc Defines the selected option.
@param {Function} [*value*]
@chainable
*/
}, {
key: "selected",
value: function selected(_) {
return arguments.length ? (this._selected = _, this) : this._selected;
}
/**
@memberof Select
@desc Sets the css styles for the <select> element.
@param {Object} [*value*]
@chainable
*/
}, {
key: "selectStyle",
value: function selectStyle(_) {
return arguments.length ? (this._selectStyle = _, this) : this._selectStyle;
}
/**
@memberof Select
@desc Sets the inner text for each <option> element.
@param {Function|String} [*value* = function(d) { return d.text; }]
@chainable
*/
}, {
key: "text",
value: function text(_) {
return arguments.length ? (this._text = typeof _ === "function" ? _ : constant$1(_), this) : this._text;
}
/**
@memberof Select
@desc Sets the value for each <option> element.
@param {Function} [*value* = function(d) { return d.value; }]
@chainable
*/
}, {
key: "value",
value: function value(_) {
return arguments.length ? (this._value = _, this) : this._value;
}
}]);
return Select;
}(BaseClass);
/**
@desc Sort an array of numbers by their numeric value, ensuring that the array is not changed in place.
This is necessary because the default behavior of .sort in JavaScript is to sort arrays as string values
[1, 10, 12, 102, 20].sort()
// output
[1, 10, 102, 12, 20]
@param {Array<number>} array input array
@return {Array<number>} sorted array
@private
@example
numericSort([3, 2, 1]) // => [1, 2, 3]
*/
function numericSort(array) {
return array.slice().sort(function (a, b) {
return a - b;
});
}
/**
For a sorted input, counting the number of unique values is possible in constant time and constant memory. This is a simple implementation of the algorithm.
Values are compared with `===`, so objects and non-primitive objects are not handled in any special way.
@private
@param {Array} input an array of primitive values.
@returns {number} count of unique values
@example
uniqueCountSorted([1, 2, 3]); // => 3
uniqueCountSorted([1, 1, 1]); // => 1
*/
function uniqueCountSorted(input) {
var lastSeenValue,
uniqueValueCount = 0;
for (var i = 0; i < input.length; i++) {
if (i === 0 || input[i] !== lastSeenValue) {
lastSeenValue = input[i];
uniqueValueCount++;
}
}
return uniqueValueCount;
}
/**
Create a new column x row matrix.
@private
@param {number} columns
@param {number} rows
@return {Array<Array<number>>} matrix
@example
makeMatrix(10, 10);
*/
function makeMatrix(columns, rows) {
var matrix = [];
for (var i = 0; i < columns; i++) {
var column = [];
for (var j = 0; j < rows; j++) {
column.push(0);
}
matrix.push(column);
}
return matrix;
}
/**
Generates incrementally computed values based on the sums and sums of squares for the data array
@private
@param {number} j
@param {number} i
@param {Array<number>} sums
@param {Array<number>} sumsOfSquares
@return {number}
@example
ssq(0, 1, [-1, 0, 2], [1, 1, 5]);
*/
function ssq(j, i, sums, sumsOfSquares) {
var sji; // s(j, i)
if (j > 0) {
var muji = (sums[i] - sums[j - 1]) / (i - j + 1); // mu(j, i)
sji = sumsOfSquares[i] - sumsOfSquares[j - 1] - (i - j + 1) * muji * muji;
} else sji = sumsOfSquares[i] - sums[i] * sums[i] / (i + 1);
if (sji < 0) return 0;
return sji;
}
/**
Function that recursively divides and conquers computations for cluster j
@private
@param {number} iMin Minimum index in cluster to be computed
@param {number} iMax Maximum index in cluster to be computed
@param {number} cluster Index of the cluster currently being computed
@param {Array<Array<number>>} matrix
@param {Array<Array<number>>} backtrackMatrix
@param {Array<number>} sums
@param {Array<number>} sumsOfSquares
*/
function fillMatrixColumn(iMin, iMax, cluster, matrix, backtrackMatrix, sums, sumsOfSquares) {
if (iMin > iMax) return; // Start at midpoint between iMin and iMax
var i = Math.floor((iMin + iMax) / 2);
matrix[cluster][i] = matrix[cluster - 1][i - 1];
backtrackMatrix[cluster][i] = i;
var jlow = cluster; // the lower end for j
if (iMin > cluster) jlow = Math.max(jlow, backtrackMatrix[cluster][iMin - 1] || 0);
jlow = Math.max(jlow, backtrackMatrix[cluster - 1][i] || 0);
var jhigh = i - 1; // the upper end for j
if (iMax < matrix.length - 1) jhigh = Math.min(jhigh, backtrackMatrix[cluster][iMax + 1] || 0);
for (var j = jhigh; j >= jlow; --j) {
var sji = ssq(j, i, sums, sumsOfSquares);
if (sji + matrix[cluster - 1][jlow - 1] >= matrix[cluster][i]) break; // Examine the lower bound of the cluster border
var sjlowi = ssq(jlow, i, sums, sumsOfSquares);
var ssqjlow = sjlowi + matrix[cluster - 1][jlow - 1];
if (ssqjlow < matrix[cluster][i]) {
// Shrink the lower bound
matrix[cluster][i] = ssqjlow;
backtrackMatrix[cluster][i] = jlow;
}
jlow++;
var ssqj = sji + matrix[cluster - 1][j - 1];
if (ssqj < matrix[cluster][i]) {
matrix[cluster][i] = ssqj;
backtrackMatrix[cluster][i] = j;
}
}
fillMatrixColumn(iMin, i - 1, cluster, matrix, backtrackMatrix, sums, sumsOfSquares);
fillMatrixColumn(i + 1, iMax, cluster, matrix, backtrackMatrix, sums, sumsOfSquares);
}
/**
Initializes the main matrices used in Ckmeans and kicks off the divide and conquer cluster computation strategy
@private
@param {Array<number>} data sorted array of values
@param {Array<Array<number>>} matrix
@param {Array<Array<number>>} backtrackMatrix
*/
function fillMatrices(data, matrix, backtrackMatrix) {
var nValues = matrix[0] ? matrix[0].length : 0; // Shift values by the median to improve numeric stability
var shift = data[Math.floor(nValues / 2)]; // Cumulative sum and cumulative sum of squares for all values in data array
var sums = [];
var sumsOfSquares = []; // Initialize first column in matrix & backtrackMatrix
for (var i = 0, shiftedValue = void 0; i < nValues; ++i) {
shiftedValue = data[i] - shift;
if (i === 0) {
sums.push(shiftedValue);
sumsOfSquares.push(shiftedValue * shiftedValue);
} else {
sums.push(sums[i - 1] + shiftedValue);
sumsOfSquares.push(sumsOfSquares[i - 1] + shiftedValue * shiftedValue);
} // Initialize for cluster = 0
matrix[0][i] = ssq(0, i, sums, sumsOfSquares);
backtrackMatrix[0][i] = 0;
} // Initialize the rest of the columns
for (var cluster = 1; cluster < matrix.length; ++cluster) {
var iMin = nValues - 1;
if (cluster < matrix.length - 1) iMin = cluster;
fillMatrixColumn(iMin, nValues - 1, cluster, matrix, backtrackMatrix, sums, sumsOfSquares);
}
}
/**
@desc Ported to ES6 from the excellent [simple-statistics](https://github.com/simple-statistics/simple-statistics) packages.
Ckmeans clustering is an improvement on heuristic-based clustering approaches like Jenks. The algorithm was developed in [Haizhou Wang and Mingzhou Song](http://journal.r-project.org/archive/2011-2/RJournal_2011-2_Wang+Song.pdf) as a [dynamic programming](https://en.wikipedia.org/wiki/Dynamic_programming) approach to the problem of clustering numeric data into groups with the least within-group sum-of-squared-deviations.
Minimizing the difference within groups - what Wang & Song refer to as `withinss`, or within sum-of-squares, means that groups are optimally homogenous within and the data is split into representative groups. This is very useful for visualization, where you may want to represent a continuous variable in discrete color or style groups. This function can provide groups that emphasize differences between data.
Being a dynamic approach, this algorithm is based on two matrices that store incrementally-computed values for squared deviations and backtracking indexes.
This implementation is based on Ckmeans 3.4.6, which introduced a new divide and conquer approach that improved runtime from O(kn^2) to O(kn log(n)).
Unlike the [original implementation](https://cran.r-project.org/web/packages/Ckmeans.1d.dp/index.html), this implementation does not include any code to automatically determine the optimal number of clusters: this information needs to be explicitly provided.
### References
_Ckmeans.1d.dp: Optimal k-means Clustering in One Dimension by Dynamic
Programming_ Haizhou Wang and Mingzhou Song ISSN 2073-4859 from The R Journal Vol. 3/2, December 2011
@param {Array<number>} data input data, as an array of number values
@param {number} nClusters number of desired classes. This cannot be greater than the number of values in the data array.
@returns {Array<Array<number>>} clustered input
@example
ckmeans([-1, 2, -1, 2, 4, 5, 6, -1, 2, -1], 3);
// The input, clustered into groups of similar numbers.
//= [[-1, -1, -1, -1], [2, 2, 2], [4, 5, 6]]);
*/
function ckmeans (data, nClusters) {
if (nClusters > data.length) {
throw new Error("Cannot generate more classes than there are data values");
}
var sorted = numericSort(data); // we'll use this as the maximum number of clusters
var uniqueCount = uniqueCountSorted(sorted); // if all of the input values are identical, there's one cluster with all of the input in it.
if (uniqueCount === 1) {
return [sorted];
}
var backtrackMatrix = makeMatrix(nClusters, sorted.length),
matrix = makeMatrix(nClusters, sorted.length); // This is a dynamic programming way to solve the problem of minimizing within-cluster sum of squares. It's similar to linear regression in this way, and this calculation incrementally computes the sum of squares that are later read.
fillMatrices(sorted, matrix, backtrackMatrix); // The real work of Ckmeans clustering happens in the matrix generation: the generated matrices encode all possible clustering combinations, and once they're generated we can solve for the best clustering groups very quickly.
var clusterRight = backtrackMatrix[0] ? backtrackMatrix[0].length - 1 : 0;
var clusters = []; // Backtrack the clusters from the dynamic programming matrix. This starts at the bottom-right corner of the matrix (if the top-left is 0, 0), and moves the cluster target with the loop.
for (var cluster = backtrackMatrix.length - 1; cluster >= 0; cluster--) {
var clusterLeft = backtrackMatrix[cluster][clusterRight]; // fill the cluster from the sorted input by taking a slice of the array. the backtrack matrix makes this easy - it stores the indexes where the cluster should start and end.
clusters[cluster] = sorted.slice(clusterLeft, clusterRight + 1);
if (cluster > 0) clusterRight = clusterLeft - 1;
}
return clusters;
}
function _typeof$j(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$j = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$j = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$j(obj);
}
function _classCallCheck$h(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$h(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$h(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$h(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$h(Constructor, staticProps);
return Constructor;
}
function _inherits$f(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$f(subClass, superClass);
}
function _setPrototypeOf$f(o, p) {
_setPrototypeOf$f = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$f(o, p);
}
function _createSuper$f(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$f();
return function _createSuperInternal() {
var Super = _getPrototypeOf$f(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$f(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$f(this, result);
};
}
function _possibleConstructorReturn$f(self, call) {
if (call && (_typeof$j(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$f(self);
}
function _assertThisInitialized$f(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$f() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$f(o) {
_getPrototypeOf$f = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$f(o);
}
/**
@class Legend
@extends external:BaseClass
@desc Creates an SVG scale based on an array of data. If *data* is specified, immediately draws based on the specified array and returns the current class instance. If *data* is not specified on instantiation, it can be passed/updated after instantiation using the [data](#shape.data) method.
*/
var Legend = /*#__PURE__*/function (_BaseClass) {
_inherits$f(Legend, _BaseClass);
var _super = _createSuper$f(Legend);
/**
@memberof Legend
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function Legend() {
var _this;
_classCallCheck$h(this, Legend);
_this = _super.call(this);
_this._align = "center";
_this._data = [];
_this._direction = "row";
_this._duration = 600;
_this._height = 200;
_this._id = accessor("id");
_this._label = accessor("id");
_this._lineData = [];
_this._outerBounds = {
width: 0,
height: 0,
x: 0,
y: 0
};
_this._padding = 5;
_this._shape = constant$1("Rect");
_this._shapes = [];
_this._shapeConfig = {
fill: accessor("color"),
height: constant$1(10),
hitArea: function hitArea(dd, i) {
var d = _this._lineData[i],
h = max([d.height, d.shapeHeight]);
return {
width: d.width + d.shapeWidth,
height: h,
x: -d.shapeWidth / 2,
y: -h / 2
};
},
labelBounds: function labelBounds(dd, i) {
var d = _this._lineData[i];
var x = d.shapeWidth;
if (d.shape === "Circle") x -= d.shapeR;
var height = max([d.shapeHeight, d.height]);
return {
width: d.width,
height: height,
x: x,
y: -height / 2
};
},
labelConfig: {
fontColor: constant$1("#444"),
fontFamily: new TextBox().fontFamily(),
fontResize: false,
fontSize: constant$1(10),
verticalAlign: "middle"
},
opacity: 1,
r: constant$1(5),
width: constant$1(10),
x: function x(d, i) {
var datum = _this._lineData[i];
var y = datum.y;
var pad = _this._align === "left" || _this._align === "right" && _this._direction === "column" ? 0 : _this._align === "center" ? (_this._outerBounds.width - _this._rowWidth(_this._lineData.filter(function (l) {
return y === l.y;
}))) / 2 : _this._outerBounds.width - _this._rowWidth(_this._lineData.filter(function (l) {
return y === l.y;
}));
var prevWords = _this._lineData.slice(0, i).filter(function (l) {
return y === l.y;
});
return _this._rowWidth(prevWords) + _this._padding * (prevWords.length ? datum.sentence ? 2 : 1 : 0) + _this._outerBounds.x + datum.shapeWidth / 2 + pad;
},
y: function y(d, i) {
var ld = _this._lineData[i];
return ld.y + _this._titleHeight + _this._outerBounds.y + max(_this._lineData.filter(function (l) {
return ld.y === l.y;
}).map(function (l) {
return l.height;
}).concat(_this._data.map(function (l, x) {
return _this._fetchConfig("height", l, x);
}))) / 2;
}
};
_this._titleClass = new TextBox();
_this._titleConfig = {};
_this._verticalAlign = "middle";
_this._width = 400;
return _this;
}
_createClass$h(Legend, [{
key: "_fetchConfig",
value: function _fetchConfig(key, d, i) {
var val = this._shapeConfig[key] !== undefined ? this._shapeConfig[key] : this._shapeConfig.labelConfig[key];
if (!val && key === "lineHeight") return this._fetchConfig("fontSize", d, i) * 1.4;
return typeof val === "function" ? val(d, i) : val;
}
}, {
key: "_rowHeight",
value: function _rowHeight(row) {
return max(row.map(function (d) {
return d.height;
}).concat(row.map(function (d) {
return d.shapeHeight;
}))) + this._padding;
}
}, {
key: "_rowWidth",
value: function _rowWidth(row) {
var _this2 = this;
return sum(row.map(function (d, i) {
var p = _this2._padding * (i === row.length - 1 ? 0 : d.width ? 2 : 1);
return d.shapeWidth + d.width + p;
}));
}
/**
@memberof Legend
@desc Renders the current Legend to the page. If a *callback* is specified, it will be called once the legend is done drawing.
@param {Function} [*callback* = undefined]
@chainable
*/
}, {
key: "render",
value: function render(callback) {
var _this3 = this;
if (this._select === void 0) this.select(_select("body").append("svg").attr("width", "".concat(this._width, "px")).attr("height", "".concat(this._height, "px")).node()); // Legend Container <g> Groups
this._group = elem("g.d3plus-Legend", {
parent: this._select
});
this._titleGroup = elem("g.d3plus-Legend-title", {
parent: this._group
});
this._shapeGroup = elem("g.d3plus-Legend-shape", {
parent: this._group
});
var availableHeight = this._height;
this._titleHeight = 0;
this._titleWidth = 0;
if (this._title) {
var f = this._titleConfig.fontFamily || this._titleClass.fontFamily()(),
s = this._titleConfig.fontSize || this._titleClass.fontSize()();
var lH = lH = this._titleConfig.lineHeight || this._titleClass.lineHeight();
lH = lH ? lH() : s * 1.4;
var res = textWrap().fontFamily(f).fontSize(s).lineHeight(lH).width(this._width).height(this._height)(this._title);
this._titleHeight = lH + res.lines.length + this._padding;
this._titleWidth = max(res.widths);
availableHeight -= this._titleHeight;
} // Calculate Text Sizes
this._lineData = this._data.map(function (d, i) {
var label = _this3._label(d, i);
var shape = _this3._shape(d, i);
var r = _this3._fetchConfig("r", d, i);
var res = {
data: d,
i: i,
id: _this3._id(d, i),
shape: shape,
shapeR: r,
shapeWidth: shape === "Circle" ? r * 2 : _this3._fetchConfig("width", d, i),
shapeHeight: shape === "Circle" ? r * 2 : _this3._fetchConfig("height", d, i),
y: 0
};
if (!label) {
res.sentence = false;
res.words = [];
res.height = 0;
res.width = 0;
return res;
}
var f = _this3._fetchConfig("fontFamily", d, i),
lh = _this3._fetchConfig("lineHeight", d, i),
s = _this3._fetchConfig("fontSize", d, i);
var h = availableHeight - (_this3._data.length + 1) * _this3._padding,
w = _this3._width;
res = Object.assign(res, textWrap().fontFamily(f).fontSize(s).lineHeight(lh).width(w).height(h)(label));
res.width = Math.ceil(max(res.lines.map(function (t) {
return textWidth(t, {
"font-family": f,
"font-size": s
});
}))) + s * 0.75;
res.height = Math.ceil(res.lines.length * (lh + 1));
res.og = {
height: res.height,
width: res.width
};
res.f = f;
res.s = s;
res.lh = lh;
return res;
});
var spaceNeeded;
var availableWidth = this._width - this._padding * 2;
spaceNeeded = this._rowWidth(this._lineData);
if (this._direction === "column" || spaceNeeded > availableWidth) {
var lines = 1,
newRows = [];
var maxLines = max(this._lineData.map(function (d) {
return d.words.length;
}));
this._wrapLines = function () {
var _this4 = this;
lines++;
if (lines > maxLines) return;
var wrappable = lines === 1 ? this._lineData.slice() : this._lineData.filter(function (d) {
return d.width + d.shapeWidth + _this4._padding * (d.width ? 2 : 1) > availableWidth && d.words.length >= lines;
}).sort(function (a, b) {
return b.sentence.length - a.sentence.length;
});
if (wrappable.length && availableHeight > wrappable[0].height * lines) {
var truncated = false;
var _loop = function _loop(x) {
var label = wrappable[x];
var h = label.og.height * lines,
w = label.og.width * (1.5 * (1 / lines));
var res = textWrap().fontFamily(label.f).fontSize(label.s).lineHeight(label.lh).width(w).height(h)(label.sentence);
if (!res.truncated) {
label.width = Math.ceil(max(res.lines.map(function (t) {
return textWidth(t, {
"font-family": label.f,
"font-size": label.s
});
}))) + label.s;
label.height = res.lines.length * (label.lh + 1);
} else {
truncated = true;
return "break";
}
};
for (var x = 0; x < wrappable.length; x++) {
var _ret = _loop(x);
if (_ret === "break") break;
}
if (!truncated) this._wrapRows();
} else {
newRows = [];
return;
}
};
this._wrapRows = function () {
newRows = [];
var row = 1,
rowWidth = 0;
for (var i = 0; i < this._lineData.length; i++) {
var d = this._lineData[i],
w = d.width + this._padding * (d.width ? 2 : 1) + d.shapeWidth;
if (sum(newRows.map(function (row) {
return max(row, function (d) {
return max([d.height, d.shapeHeight]);
});
})) > availableHeight) {
newRows = [];
break;
}
if (w > availableWidth) {
newRows = [];
this._wrapLines();
break;
} else if (rowWidth + w < availableWidth) {
rowWidth += w;
} else if (this._direction !== "column") {
rowWidth = w;
row++;
}
if (!newRows[row - 1]) newRows[row - 1] = [];
newRows[row - 1].push(d);
if (this._direction === "column") {
rowWidth = 0;
row++;
}
}
};
this._wrapRows();
if (!newRows.length || sum(newRows, this._rowHeight.bind(this)) + this._padding > availableHeight) {
spaceNeeded = sum(this._lineData.map(function (d) {
return d.shapeWidth + _this3._padding;
})) - this._padding;
for (var i = 0; i < this._lineData.length; i++) {
this._lineData[i].width = 0;
this._lineData[i].height = 0;
}
this._wrapRows();
}
if (newRows.length && sum(newRows, this._rowHeight.bind(this)) + this._padding < availableHeight) {
newRows.forEach(function (row, i) {
row.forEach(function (d) {
if (i) {
d.y = sum(newRows.slice(0, i), _this3._rowHeight.bind(_this3));
}
});
});
spaceNeeded = max(newRows, this._rowWidth.bind(this));
}
}
var innerHeight = max(this._lineData, function (d, i) {
return max([d.height, _this3._fetchConfig("height", d.data, i)]) + d.y;
}) + this._titleHeight,
innerWidth = max([spaceNeeded, this._titleWidth]);
this._outerBounds.width = innerWidth;
this._outerBounds.height = innerHeight;
var xOffset = this._padding,
yOffset = this._padding;
if (this._align === "center") xOffset = (this._width - innerWidth) / 2;else if (this._align === "right") xOffset = this._width - this._padding - innerWidth;
if (this._verticalAlign === "middle") yOffset = (this._height - innerHeight) / 2;else if (this._verticalAlign === "bottom") yOffset = this._height - this._padding - innerHeight;
this._outerBounds.x = xOffset;
this._outerBounds.y = yOffset;
this._titleClass.data(this._title ? [{
text: this._title
}] : []).duration(this._duration).select(this._titleGroup.node()).textAnchor({
left: "start",
center: "middle",
right: "end"
}[this._align]).width(this._width - this._padding * 2).x(this._padding).y(this._outerBounds.y).config(this._titleConfig).render();
this._shapes = [];
var baseConfig = configPrep.bind(this)(this._shapeConfig, "legend"),
config = {
id: function id(d) {
return d.id;
},
label: function label(d) {
return d.label;
},
lineHeight: function lineHeight(d) {
return d.lH;
}
};
var data = this._data.map(function (d, i) {
var obj = {
__d3plus__: true,
data: d,
i: i,
id: _this3._id(d, i),
label: _this3._lineData[i].width ? _this3._label(d, i) : false,
lH: _this3._fetchConfig("lineHeight", d, i),
shape: _this3._shape(d, i)
};
return obj;
}); // Legend Shapes
this._shapes = [];
["Circle", "Rect"].forEach(function (Shape) {
_this3._shapes.push(new shapes$2[Shape]().parent(_this3).data(data.filter(function (d) {
return d.shape === Shape;
})).duration(_this3._duration).labelConfig({
padding: 0
}).select(_this3._shapeGroup.node()).verticalAlign("top").config(assign({}, baseConfig, config)).render());
});
if (callback) setTimeout(callback, this._duration + 100);
return this;
}
/**
@memberof Legend
@desc If *value* is specified, sets the active method for all shapes to the specified function and returns the current class instance. If *value* is not specified, returns the current active method.
@param {Function} [*value*]
@chainable
*/
}, {
key: "active",
value: function active(_) {
this._shapes.forEach(function (s) {
return s.active(_);
});
return this;
}
/**
@memberof Legend
@desc If *value* is specified, sets the horizontal alignment to the specified value and returns the current class instance. If *value* is not specified, returns the current horizontal alignment.
@param {String} [*value* = "center"] Supports `"left"` and `"center"` and `"right"`.
@chainable
*/
}, {
key: "align",
value: function align(_) {
return arguments.length ? (this._align = _, this) : this._align;
}
/**
@memberof Legend
@desc If *data* is specified, sets the data array to the specified array and returns the current class instance. If *data* is not specified, returns the current data array. A shape key will be drawn for each object in the array.
@param {Array} [*data* = []]
@chainable
*/
}, {
key: "data",
value: function data(_) {
return arguments.length ? (this._data = _, this) : this._data;
}
/**
@memberof Legend
@desc Sets the flow of the items inside the legend. If no value is passed, the current flow will be returned.
@param {String} [*value* = "row"]
@chainable
*/
}, {
key: "direction",
value: function direction(_) {
return arguments.length ? (this._direction = _, this) : this._direction;
}
/**
@memberof Legend
@desc If *value* is specified, sets the transition duration of the legend and returns the current class instance. If *value* is not specified, returns the current duration.
@param {Number} [*value* = 600]
@chainable
*/
}, {
key: "duration",
value: function duration(_) {
return arguments.length ? (this._duration = _, this) : this._duration;
}
/**
@memberof Legend
@desc If *value* is specified, sets the overall height of the legend and returns the current class instance. If *value* is not specified, returns the current height value.
@param {Number} [*value* = 100]
@chainable
*/
}, {
key: "height",
value: function height(_) {
return arguments.length ? (this._height = _, this) : this._height;
}
/**
@memberof Legend
@desc If *value* is specified, sets the hover method for all shapes to the specified function and returns the current class instance. If *value* is not specified, returns the current hover method.
@param {Function} [*value*]
@chainable
*/
}, {
key: "hover",
value: function hover(_) {
this._shapes.forEach(function (s) {
return s.hover(_);
});
return this;
}
/**
@memberof Legend
@desc If *value* is specified, sets the id accessor to the specified function and returns the current class instance. If *value* is not specified, returns the current id accessor.
@param {Function} [*value*]
@chainable
@example
function value(d) {
return d.id;
}
*/
}, {
key: "id",
value: function id(_) {
return arguments.length ? (this._id = _, this) : this._id;
}
/**
@memberof Legend
@desc If *value* is specified, sets the label accessor to the specified function or string and returns the current class instance. If *value* is not specified, returns the current label accessor, which is the [id](#shape.id) accessor by default.
@param {Function|String} [*value*]
@chainable
*/
}, {
key: "label",
value: function label(_) {
return arguments.length ? (this._label = typeof _ === "function" ? _ : constant$1(_), this) : this._label;
}
/**
@memberof Legend
@desc If called after the elements have been drawn to DOM, will returns the outer bounds of the legend content.
@example
{"width": 180, "height": 24, "x": 10, "y": 20}
*/
}, {
key: "outerBounds",
value: function outerBounds() {
return this._outerBounds;
}
/**
@memberof Legend
@desc If *value* is specified, sets the padding between each key to the specified number and returns the current class instance. If *value* is not specified, returns the current padding value.
@param {Number} [*value* = 10]
@chainable
*/
}, {
key: "padding",
value: function padding(_) {
return arguments.length ? (this._padding = _, this) : this._padding;
}
/**
@memberof Legend
@desc If *selector* is specified, sets the SVG container element to the specified d3 selector or DOM element and returns the current class instance. If *selector* is not specified, returns the current SVG container element.
@param {String|HTMLElement} [*selector* = d3.select("body").append("svg")]
@chainable
*/
}, {
key: "select",
value: function select(_) {
return arguments.length ? (this._select = _select(_), this) : this._select;
}
/**
@memberof Legend
@desc If *value* is specified, sets the shape accessor to the specified function or string and returns the current class instance. If *value* is not specified, returns the current shape accessor.
@param {Function|String} [*value* = "Rect"]
@chainable
*/
}, {
key: "shape",
value: function shape(_) {
return arguments.length ? (this._shape = typeof _ === "function" ? _ : constant$1(_), this) : this._shape;
}
/**
@memberof Legend
@desc If *config* is specified, sets the methods that correspond to the key/value pairs for each shape and returns the current class instance. If *config* is not specified, returns the current shape configuration.
@param {Object} [*config* = {}]
@chainable
*/
}, {
key: "shapeConfig",
value: function shapeConfig(_) {
return arguments.length ? (this._shapeConfig = assign(this._shapeConfig, _), this) : this._shapeConfig;
}
/**
@memberof Legend
@desc If *value* is specified, sets the title of the legend and returns the current class instance. If *value* is not specified, returns the current title.
@param {String} [*value*]
@chainable
*/
}, {
key: "title",
value: function title(_) {
return arguments.length ? (this._title = _, this) : this._title;
}
/**
@memberof Legend
@desc If *value* is specified, sets the title configuration of the legend and returns the current class instance. If *value* is not specified, returns the current title configuration.
@param {Object} [*value*]
@chainable
*/
}, {
key: "titleConfig",
value: function titleConfig(_) {
return arguments.length ? (this._titleConfig = assign(this._titleConfig, _), this) : this._titleConfig;
}
/**
@memberof Legend
@desc If *value* is specified, sets the vertical alignment to the specified value and returns the current class instance. If *value* is not specified, returns the current vertical alignment.
@param {String} [*value* = "middle"] Supports `"top"` and `"middle"` and `"bottom"`.
@chainable
*/
}, {
key: "verticalAlign",
value: function verticalAlign(_) {
return arguments.length ? (this._verticalAlign = _, this) : this._verticalAlign;
}
/**
@memberof Legend
@desc If *value* is specified, sets the overall width of the legend and returns the current class instance. If *value* is not specified, returns the current width value.
@param {Number} [*value* = 400]
@chainable
*/
}, {
key: "width",
value: function width(_) {
return arguments.length ? (this._width = _, this) : this._width;
}
}]);
return Legend;
}(BaseClass);
function _typeof$k(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$k = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$k = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$k(obj);
}
function _defineProperty$3(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _classCallCheck$i(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$i(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$i(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$i(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$i(Constructor, staticProps);
return Constructor;
}
function _inherits$g(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$g(subClass, superClass);
}
function _setPrototypeOf$g(o, p) {
_setPrototypeOf$g = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$g(o, p);
}
function _createSuper$g(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$g();
return function _createSuperInternal() {
var Super = _getPrototypeOf$g(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$g(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$g(this, result);
};
}
function _possibleConstructorReturn$g(self, call) {
if (call && (_typeof$k(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$g(self);
}
function _assertThisInitialized$g(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$g() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$g(o) {
_getPrototypeOf$g = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$g(o);
}
/**
@class ColorScale
@extends external:BaseClass
@desc Creates an SVG scale based on an array of data. If *data* is specified, immediately draws based on the specified array and returns the current class instance. If *data* is not specified on instantiation, it can be passed/updated after instantiation using the [data](#shape.data) method.
*/
var ColorScale = /*#__PURE__*/function (_BaseClass) {
_inherits$g(ColorScale, _BaseClass);
var _super = _createSuper$g(ColorScale);
/**
@memberof ColorScale
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function ColorScale() {
var _this;
_classCallCheck$i(this, ColorScale);
_this = _super.call(this);
_this._axisClass = new Axis();
_this._axisConfig = {
gridSize: 0,
shapeConfig: {
labelConfig: {
fontColor: "#222"
}
},
titleConfig: {
fontSize: 12
}
};
_this._axisTest = new Axis();
_this._align = "middle";
_this._buckets = 5;
_this._bucketAxis = false;
_this._centered = true;
_this._colorMax = "#0C8040";
_this._colorMid = "#f7f7f7";
_this._colorMin = "#b22200";
_this._data = [];
_this._duration = 600;
_this._height = 200;
_this._labelClass = new TextBox();
_this._legendClass = new Legend();
_this._legendConfig = {
shapeConfig: {
labelConfig: {
fontColor: "#222"
},
stroke: "#444",
strokeWidth: 1
}
};
_this._midpoint = 0;
_this._orient = "bottom";
_this._outerBounds = {
width: 0,
height: 0,
x: 0,
y: 0
};
_this._padding = 5;
_this._rectClass = new Rect().parent(_assertThisInitialized$g(_this));
_this._rectConfig = {
stroke: "#444",
strokeWidth: 1
};
_this._scale = "linear";
_this._size = 10;
_this._value = accessor("value");
_this._width = 400;
return _this;
}
/**
@memberof ColorScale
@desc Renders the current ColorScale to the page. If a *callback* is specified, it will be called once the ColorScale is done drawing.
@param {Function} [*callback* = undefined]
@chainable
*/
_createClass$i(ColorScale, [{
key: "render",
value: function render(callback) {
var _this2 = this;
if (this._select === void 0) this.select(_select("body").append("svg").attr("width", "".concat(this._width, "px")).attr("height", "".concat(this._height, "px")).node());
var horizontal = ["bottom", "top"].includes(this._orient);
var height = horizontal ? "height" : "width",
width = horizontal ? "width" : "height",
x = horizontal ? "x" : "y",
y = horizontal ? "y" : "x"; // Shape <g> Group
this._group = elem("g.d3plus-ColorScale", {
parent: this._select
});
var allValues = this._data.map(this._value).sort(function (a, b) {
return a - b;
});
var domain = extent(allValues);
var negative = domain[0] < this._midpoint;
var positive = domain[1] > this._midpoint;
var diverging = negative && positive;
var colors = this._color,
labels,
ticks;
if (colors && !(colors instanceof Array)) {
colors = range(0, this._buckets, 1).map(function (i) {
return colorLighter(colors, (i + 1) / _this2._buckets);
}).reverse();
}
if (this._scale === "jenks") {
var data = this._data.map(this._value).filter(function (d) {
return d !== null && typeof d === "number";
});
var buckets = min([colors ? colors.length : this._buckets, data.length]);
var jenks = [];
if (diverging && this._centered) {
var half = Math.floor(buckets / 2);
var residual = buckets % 2;
var negatives = data.filter(function (d) {
return d < _this2._midpoint;
});
var negativesDeviation = deviation(negatives);
var positives = data.concat(this._midpoint).filter(function (d) {
return d >= _this2._midpoint;
});
var positivesDeviation = deviation(positives);
var isNegativeMax = negativesDeviation > positivesDeviation ? 1 : 0;
var isPositiveMax = positivesDeviation > negativesDeviation ? 1 : 0;
var negativeJenks = ckmeans(negatives, half + residual * isNegativeMax);
var positiveJenks = ckmeans(positives, half + residual * isPositiveMax);
jenks = negativeJenks.concat(positiveJenks);
} else {
jenks = ckmeans(data, buckets);
}
ticks = arrayMerge(jenks.map(function (c, i) {
return i === jenks.length - 1 ? [c[0], c[c.length - 1]] : [c[0]];
}));
var tickSet = new Set(ticks);
if (ticks.length !== tickSet.size) {
labels = Array.from(tickSet);
}
if (!colors) {
if (diverging) {
colors = [this._colorMin, this._colorMid, this._colorMax];
var _negatives = ticks.slice(0, buckets).filter(function (d, i) {
return d < _this2._midpoint && ticks[i + 1] <= _this2._midpoint;
});
var spanning = ticks.slice(0, buckets).filter(function (d, i) {
return d <= _this2._midpoint && ticks[i + 1] > _this2._midpoint;
});
var _positives = ticks.slice(0, buckets).filter(function (d, i) {
return d > _this2._midpoint && ticks[i + 1] > _this2._midpoint;
});
var negativeColors = _negatives.map(function (d, i) {
return !i ? colors[0] : colorLighter(colors[0], i / _negatives.length);
});
var spanningColors = spanning.map(function () {
return colors[1];
});
var positiveColors = _positives.map(function (d, i) {
return i === _positives.length - 1 ? colors[2] : colorLighter(colors[2], 1 - (i + 1) / _positives.length);
});
colors = negativeColors.concat(spanningColors).concat(positiveColors);
} else {
colors = range(0, this._buckets, 1).map(function (i) {
return colorLighter(_this2._colorMax, i / _this2._buckets);
}).reverse();
}
}
if (data.length <= buckets) {
colors = colors.slice(buckets - data.length);
}
this._colorScale = threshold().domain(ticks).range(["black"].concat(colors).concat(colors[colors.length - 1]));
} else {
var _buckets;
if (diverging && !colors) {
var _half = Math.floor(this._buckets / 2);
var _negativeColors = range(0, _half, 1).map(function (i) {
return !i ? _this2._colorMin : colorLighter(_this2._colorMin, i / _half);
});
var _spanningColors = (this._buckets % 2 ? [0] : []).map(function () {
return _this2._colorMid;
});
var _positiveColors = range(0, _half, 1).map(function (i) {
return !i ? _this2._colorMax : colorLighter(_this2._colorMax, i / _half);
}).reverse();
colors = _negativeColors.concat(_spanningColors).concat(_positiveColors);
var step = (colors.length - 1) / 2;
_buckets = [domain[0], this._midpoint, domain[1]];
_buckets = range(domain[0], this._midpoint, -(domain[0] - this._midpoint) / step).concat(range(this._midpoint, domain[1], (domain[1] - this._midpoint) / step)).concat([domain[1]]);
} else {
if (!colors) {
if (this._scale === "buckets" || this._scale === "quantile") {
colors = range(0, this._buckets, 1).map(function (i) {
return colorLighter(negative ? _this2._colorMin : _this2._colorMax, i / _this2._buckets);
});
if (positive) colors = colors.reverse();
} else {
colors = negative ? [this._colorMin, colorLighter(this._colorMin, 0.8)] : [colorLighter(this._colorMax, 0.8), this._colorMax];
}
}
if (this._scale === "quantile") {
var _step = 1 / (colors.length - 1);
_buckets = range(0, 1 + _step / 2, _step).map(function (d) {
return quantile(allValues, d);
});
} else if (diverging && this._color && this._centered) {
var negativeStep = (this._midpoint - domain[0]) / Math.floor(colors.length / 2);
var positiveStep = (domain[1] - this._midpoint) / Math.floor(colors.length / 2);
var negativeBuckets = range(domain[0], this._midpoint, negativeStep);
var positiveBuckets = range(this._midpoint, domain[1] + positiveStep / 2, positiveStep);
_buckets = negativeBuckets.concat(positiveBuckets);
} else {
var _step2 = (domain[1] - domain[0]) / (colors.length - 1);
_buckets = range(domain[0], domain[1] + _step2 / 2, _step2);
}
}
if (this._scale === "buckets" || this._scale === "quantile") {
ticks = _buckets.concat([_buckets[_buckets.length - 1]]);
} else if (this._scale === "log") {
var _negativeBuckets = _buckets.filter(function (d) {
return d < 0;
});
if (_negativeBuckets.length) {
var minVal = _negativeBuckets[0];
var newNegativeBuckets = _negativeBuckets.map(function (d) {
return -Math.pow(Math.abs(minVal), d / minVal);
});
_negativeBuckets.forEach(function (bucket, i) {
_buckets[_buckets.indexOf(bucket)] = newNegativeBuckets[i];
});
}
var _positiveBuckets = _buckets.filter(function (d) {
return d > 0;
});
if (_positiveBuckets.length) {
var maxVal = _positiveBuckets[_positiveBuckets.length - 1];
var newPositiveBuckets = _positiveBuckets.map(function (d) {
return Math.pow(maxVal, d / maxVal);
});
_positiveBuckets.forEach(function (bucket, i) {
_buckets[_buckets.indexOf(bucket)] = newPositiveBuckets[i];
});
}
if (_buckets.includes(0)) _buckets[_buckets.indexOf(0)] = 1;
}
this._colorScale = linear$1().domain(_buckets).range(colors);
}
var gradient = this._bucketAxis || !["buckets", "jenks", "quantile"].includes(this._scale);
var t = transition().duration(this._duration);
var groupParams = {
enter: {
opacity: 0
},
exit: {
opacity: 0
},
parent: this._group,
transition: t,
update: {
opacity: 1
}
};
var labelGroup = elem("g.d3plus-ColorScale-labels", Object.assign({
condition: gradient
}, groupParams));
var rectGroup = elem("g.d3plus-ColorScale-Rect", Object.assign({
condition: gradient
}, groupParams));
var legendGroup = elem("g.d3plus-ColorScale-legend", Object.assign({
condition: !gradient
}, groupParams));
if (gradient) {
var _assign;
var offsets = {
x: 0,
y: 0
};
var axisConfig = assign({
domain: horizontal ? domain : domain.reverse(),
duration: this._duration,
height: this._height,
labels: labels || ticks,
orient: this._orient,
padding: this._padding,
scale: this._scale === "log" ? "log" : "linear",
ticks: ticks,
width: this._width
}, this._axisConfig);
var labelConfig = assign({
height: this["_".concat(height)] / 2,
width: this["_".concat(width)] / 2
}, this._labelConfig || this._axisConfig.titleConfig);
this._labelClass.config(labelConfig);
var labelData = [];
if (horizontal && this._labelMin) {
var labelCSS = {
"font-family": this._labelClass.fontFamily()(this._labelMin),
"font-size": this._labelClass.fontSize()(this._labelMin),
"font-weight": this._labelClass.fontWeight()(this._labelMin)
};
if (labelCSS["font-family"] instanceof Array) labelCSS["font-family"] = labelCSS["font-family"][0];
var labelMinWidth = textWidth(this._labelMin, labelCSS);
if (labelMinWidth && labelMinWidth < this["_".concat(width)] / 2) {
labelData.push(this._labelMin);
labelMinWidth += this._padding;
if (horizontal) offsets.x += labelMinWidth;
axisConfig[width] -= labelMinWidth;
}
}
if (horizontal && this._labelMax) {
var _labelCSS = {
"font-family": this._labelClass.fontFamily()(this._labelMax),
"font-size": this._labelClass.fontSize()(this._labelMax),
"font-weight": this._labelClass.fontWeight()(this._labelMax)
};
if (_labelCSS["font-family"] instanceof Array) _labelCSS["font-family"] = _labelCSS["font-family"][0];
var labelMaxWidth = textWidth(this._labelMax, _labelCSS);
if (labelMaxWidth && labelMaxWidth < this["_".concat(width)] / 2) {
labelData.push(this._labelMax);
labelMaxWidth += this._padding;
if (!horizontal) offsets.y += labelMaxWidth;
axisConfig[width] -= labelMaxWidth;
}
}
this._axisTest.select(elem("g.d3plus-ColorScale-axisTest", {
enter: {
opacity: 0
},
parent: this._group
}).node()).config(axisConfig).duration(0).render();
var axisBounds = this._axisTest.outerBounds();
this._outerBounds[width] = this["_".concat(width)] - this._padding * 2;
this._outerBounds[height] = axisBounds[height] + this._size;
this._outerBounds[x] = this._padding;
this._outerBounds[y] = this._padding;
if (this._align === "middle") this._outerBounds[y] = (this["_".concat(height)] - this._outerBounds[height]) / 2;else if (this._align === "end") this._outerBounds[y] = this["_".concat(height)] - this._padding - this._outerBounds[height];
var axisGroupOffset = this._outerBounds[y] + (["bottom", "right"].includes(this._orient) ? this._size : 0) - (axisConfig.padding || this._axisClass.padding());
var transform = "translate(".concat(offsets.x + (horizontal ? 0 : axisGroupOffset), ", ").concat(offsets.y + (horizontal ? axisGroupOffset : 0), ")");
this._axisClass.select(elem("g.d3plus-ColorScale-axis", assign(groupParams, {
condition: true,
enter: {
transform: transform
},
update: {
transform: transform
}
})).node()).config(axisConfig).align("start").render();
var axisScale = this._axisTest._getPosition.bind(this._axisTest);
var scaleRange = this._axisTest._getRange();
var defs = this._group.selectAll("defs").data([0]);
var defsEnter = defs.enter().append("defs");
defsEnter.append("linearGradient").attr("id", "gradient-".concat(this._uuid));
defs = defsEnter.merge(defs);
defs.select("linearGradient").attr("".concat(x, "1"), horizontal ? "0%" : "100%").attr("".concat(x, "2"), horizontal ? "100%" : "0%").attr("".concat(y, "1"), "0%").attr("".concat(y, "2"), "0%");
var stops = defs.select("linearGradient").selectAll("stop").data(horizontal ? colors : colors);
var scaleDomain = this._colorScale.domain();
var offsetScale = linear$1().domain(scaleRange).range(horizontal ? [0, 100] : [100, 0]);
stops.enter().append("stop").merge(stops).attr("offset", function (d, i) {
return "".concat(offsetScale(axisScale(scaleDomain[i])), "%");
}).attr("stop-color", String);
/** determines the width of buckets */
var bucketWidth = function bucketWidth(d, i) {
var w = Math.abs(axisScale(ticks[i + 1]) - axisScale(d));
return w || 2;
};
var rectConfig = assign((_assign = {
duration: this._duration,
fill: ticks ? function (d) {
return _this2._colorScale(d);
} : "url(#gradient-".concat(this._uuid, ")")
}, _defineProperty$3(_assign, x, ticks ? function (d, i) {
return axisScale(d) + bucketWidth(d, i) / 2 - (["left", "right"].includes(_this2._orient) ? bucketWidth(d, i) : 0);
} : scaleRange[0] + (scaleRange[1] - scaleRange[0]) / 2 + offsets[x]), _defineProperty$3(_assign, y, this._outerBounds[y] + (["top", "left"].includes(this._orient) ? axisBounds[height] : 0) + this._size / 2 + offsets[y]), _defineProperty$3(_assign, width, ticks ? bucketWidth : scaleRange[1] - scaleRange[0]), _defineProperty$3(_assign, height, this._size), _assign), this._rectConfig);
this._rectClass.data(ticks ? ticks.slice(0, ticks.length - 1) : [0]).id(function (d, i) {
return i;
}).select(rectGroup.node()).config(rectConfig).render();
labelConfig.height = this._outerBounds[height];
labelConfig.width = this._outerBounds[width];
this._labelClass.config(labelConfig).data(labelData).select(labelGroup.node()).x(function (d) {
return d === _this2._labelMax ? rectConfig.x + rectConfig.width / 2 + _this2._padding : _this2._outerBounds.x;
}).y(function (d) {
return rectConfig.y - _this2._labelClass.fontSize()(d) / 2;
}).text(function (d) {
return d;
}).rotate(horizontal ? 0 : this._orient === "right" ? 90 : -90).render();
} else {
elem("g.d3plus-ColorScale-axis", Object.assign({
condition: gradient
}, groupParams));
var format = this._axisConfig.tickFormat ? this._axisConfig.tickFormat : formatAbbreviate;
var legendData = ticks.reduce(function (arr, tick, i) {
if (i !== ticks.length - 1) {
var next = ticks[i + 1];
arr.push({
color: colors[i],
id: tick === next ? "".concat(format(tick), "+") : "".concat(format(tick), " - ").concat(format(next))
});
}
return arr;
}, []);
var legendConfig = assign({
align: horizontal ? "center" : {
start: "left",
middle: "center",
end: "right"
}[this._align],
direction: horizontal ? "row" : "column",
duration: this._duration,
height: this._height,
padding: this._padding,
shapeConfig: assign({
duration: this._duration
}, this._axisConfig.shapeConfig || {}),
title: this._axisConfig.title,
titleConfig: this._axisConfig.titleConfig || {},
width: this._width,
verticalAlign: horizontal ? {
start: "top",
middle: "middle",
end: "bottom"
}[this._align] : "middle"
}, this._legendConfig);
this._legendClass.data(legendData).select(legendGroup.node()).config(legendConfig).render();
this._outerBounds = this._legendClass.outerBounds();
}
if (callback) setTimeout(callback, this._duration + 100);
return this;
}
/**
@memberof ColorScale
@desc The [ColorScale](http://d3plus.org/docs/#ColorScale) is constructed by combining an [Axis](http://d3plus.org/docs/#Axis) for the ticks/labels and a [Rect](http://d3plus.org/docs/#Rect) for the actual color box (or multiple boxes, as in a jenks scale). Because of this, there are separate configs for the [Axis](http://d3plus.org/docs/#Axis) class used to display the text ([axisConfig](http://d3plus.org/docs/#ColorScale.axisConfig)) and the [Rect](http://d3plus.org/docs/#Rect) class used to draw the color breaks ([rectConfig](http://d3plus.org/docs/#ColorScale.rectConfig)). This method acts as a pass-through to the config method of the [Axis](http://d3plus.org/docs/#Axis). An example usage of this method can be seen [here](http://d3plus.org/examples/d3plus-legend/colorScale-dark/).
@param {Object} [*value*]
@chainable
*/
}, {
key: "axisConfig",
value: function axisConfig(_) {
return arguments.length ? (this._axisConfig = assign(this._axisConfig, _), this) : this._axisConfig;
}
/**
@memberof ColorScale
@desc If *value* is specified, sets the horizontal alignment to the specified value and returns the current class instance. If *value* is not specified, returns the current horizontal alignment.
@param {String} [*value* = "center"] Supports `"left"` and `"center"` and `"right"`.
@chainable
*/
}, {
key: "align",
value: function align(_) {
return arguments.length ? (this._align = _, this) : this._align;
}
/**
@memberof ColorScale
@desc The number of discrete buckets to create in a bucketed color scale. Will be overridden by any custom Array of colors passed to the `color` method.
@param {Number} [*value* = 5]
@chainable
*/
}, {
key: "buckets",
value: function buckets(_) {
return arguments.length ? (this._buckets = _, this) : this._buckets;
}
/**
@memberof ColorScale
@desc Determines whether or not to use an Axis to display bucket scales (both "buckets" and "jenks"). When set to `false`, bucketed scales will use the `Legend` class to display squares for each range of data. When set to `true`, bucketed scales will be displayed on an `Axis`, similar to "linear" scales.
@param {Boolean} [*value* = false]
@chainable
*/
}, {
key: "bucketAxis",
value: function bucketAxis(_) {
return arguments.length ? (this._bucketAxis = _, this) : this._bucketAxis;
}
/**
@memberof ColorScale
@desc Determines whether or not to display a midpoint centered Axis. Does not apply to quantile scales.
@param {Boolean} [*value* = false]
@chainable
*/
}, {
key: "centered",
value: function centered(_) {
return arguments.length ? (this._centered = _, this) : this._centered;
}
/**
@memberof ColorScale
@desc Overrides the default internal logic of `colorMin`, `colorMid`, and `colorMax` to only use just this specified color. If a single color is given as a String, then the scale is interpolated by lightening that color. Otherwise, the function expects an Array of color values to be used in order for the scale.
@param {String|Array} [*value*]
@chainable
*/
}, {
key: "color",
value: function color(_) {
return arguments.length ? (this._color = _, this) : this._color;
}
/**
@memberof ColorScale
@desc Defines the color to be used for numbers greater than the value of the `midpoint` on the scale (defaults to `0`). Colors in between this value and the value of `colorMid` will be interpolated, unless a custom Array of colors has been specified using the `color` method.
@param {String} [*value* = "#0C8040"]
@chainable
*/
}, {
key: "colorMax",
value: function colorMax(_) {
return arguments.length ? (this._colorMax = _, this) : this._colorMax;
}
/**
@memberof ColorScale
@desc Defines the color to be used for the midpoint of a diverging scale, based on the current value of the `midpoint` method (defaults to `0`). Colors in between this value and the values of `colorMin` and `colorMax` will be interpolated, unless a custom Array of colors has been specified using the `color` method.
@param {String} [*value* = "#f7f7f7"]
@chainable
*/
}, {
key: "colorMid",
value: function colorMid(_) {
return arguments.length ? (this._colorMid = _, this) : this._colorMid;
}
/**
@memberof ColorScale
@desc Defines the color to be used for numbers less than the value of the `midpoint` on the scale (defaults to `0`). Colors in between this value and the value of `colorMid` will be interpolated, unless a custom Array of colors has been specified using the `color` method.
@param {String} [*value* = "#b22200"]
@chainable
*/
}, {
key: "colorMin",
value: function colorMin(_) {
return arguments.length ? (this._colorMin = _, this) : this._colorMin;
}
/**
@memberof ColorScale
@desc If *data* is specified, sets the data array to the specified array and returns the current class instance. If *data* is not specified, returns the current data array. A shape key will be drawn for each object in the array.
@param {Array} [*data* = []]
@chainable
*/
}, {
key: "data",
value: function data(_) {
return arguments.length ? (this._data = _, this) : this._data;
}
/**
@memberof ColorScale
@desc If *value* is specified, sets the transition duration of the ColorScale and returns the current class instance. If *value* is not specified, returns the current duration.
@param {Number} [*value* = 600]
@chainable
*/
}, {
key: "duration",
value: function duration(_) {
return arguments.length ? (this._duration = _, this) : this._duration;
}
/**
@memberof ColorScale
@desc If *value* is specified, sets the overall height of the ColorScale and returns the current class instance. If *value* is not specified, returns the current height value.
@param {Number} [*value* = 100]
@chainable
*/
}, {
key: "height",
value: function height(_) {
return arguments.length ? (this._height = _, this) : this._height;
}
/**
@memberof ColorScale
@desc A pass-through for the [TextBox](http://d3plus.org/docs/#TextBox) class used to style the labelMin and labelMax text.
@param {Object} [*value*]
@chainable
*/
}, {
key: "labelConfig",
value: function labelConfig(_) {
return arguments.length ? (this._labelConfig = _, this) : this._labelConfig;
}
/**
@memberof ColorScale
@desc Defines a text label to be displayed off of the end of the minimum point in the scale (currently only available in horizontal orientation).
@param {String} [*value*]
@chainable
*/
}, {
key: "labelMin",
value: function labelMin(_) {
return arguments.length ? (this._labelMin = _, this) : this._labelMin;
}
/**
@memberof ColorScale
@desc Defines a text label to be displayed off of the end of the maximum point in the scale (currently only available in horizontal orientation).
@param {String} [*value*]
@chainable
*/
}, {
key: "labelMax",
value: function labelMax(_) {
return arguments.length ? (this._labelMax = _, this) : this._labelMax;
}
/**
@memberof ColorScale
@desc The [ColorScale](http://d3plus.org/docs/#ColorScale) is constructed by combining an [Axis](http://d3plus.org/docs/#Axis) for the ticks/labels and a [Rect](http://d3plus.org/docs/#Rect) for the actual color box (or multiple boxes, as in a jenks scale). Because of this, there are separate configs for the [Axis](http://d3plus.org/docs/#Axis) class used to display the text ([axisConfig](http://d3plus.org/docs/#ColorScale.axisConfig)) and the [Rect](http://d3plus.org/docs/#Rect) class used to draw the color breaks ([rectConfig](http://d3plus.org/docs/#ColorScale.rectConfig)). This method acts as a pass-through to the config method of the [Axis](http://d3plus.org/docs/#Axis). An example usage of this method can be seen [here](http://d3plus.org/examples/d3plus-legend/colorScale-dark/).
@param {Object} [*value*]
@chainable
*/
}, {
key: "legendConfig",
value: function legendConfig(_) {
return arguments.length ? (this._legendConfig = assign(this._legendConfig, _), this) : this._legendConfig;
}
/**
@memberof ColorScale
@desc The number value to be used as the anchor for `colorMid`, and defines the center point of the diverging color scale.
@param {Number} [*value* = 0]
@chainable
*/
}, {
key: "midpoint",
value: function midpoint(_) {
return arguments.length ? (this._midpoint = _, this) : this._midpoint;
}
/**
@memberof ColorScale
@desc Sets the flow of the items inside the ColorScale. If no value is passed, the current flow will be returned.
@param {String} [*value* = "bottom"]
@chainable
*/
}, {
key: "orient",
value: function orient(_) {
return arguments.length ? (this._orient = _, this) : this._orient;
}
/**
@memberof ColorScale
@desc If called after the elements have been drawn to DOM, will returns the outer bounds of the ColorScale content.
@example
{"width": 180, "height": 24, "x": 10, "y": 20}
*/
}, {
key: "outerBounds",
value: function outerBounds() {
return this._outerBounds;
}
/**
@memberof ColorScale
@desc If *value* is specified, sets the padding between each key to the specified number and returns the current class instance. If *value* is not specified, returns the current padding value.
@param {Number} [*value* = 10]
@chainable
*/
}, {
key: "padding",
value: function padding(_) {
return arguments.length ? (this._padding = _, this) : this._padding;
}
/**
@memberof ColorScale
@desc The [ColorScale](http://d3plus.org/docs/#ColorScale) is constructed by combining an [Axis](http://d3plus.org/docs/#Axis) for the ticks/labels and a [Rect](http://d3plus.org/docs/#Rect) for the actual color box (or multiple boxes, as in a jenks scale). Because of this, there are separate configs for the [Axis](http://d3plus.org/docs/#Axis) class used to display the text ([axisConfig](http://d3plus.org/docs/#ColorScale.axisConfig)) and the [Rect](http://d3plus.org/docs/#Rect) class used to draw the color breaks ([rectConfig](http://d3plus.org/docs/#ColorScale.rectConfig)). This method acts as a pass-through to the config method of the [Rect](http://d3plus.org/docs/#Rect). An example usage of this method can be seen [here](http://d3plus.org/examples/d3plus-legend/colorScale-dark/).
@param {Object} [*value*]
@chainable
*/
}, {
key: "rectConfig",
value: function rectConfig(_) {
return arguments.length ? (this._rectConfig = assign(this._rectConfig, _), this) : this._rectConfig;
}
/**
@memberof ColorScale
@desc If *value* is specified, sets the scale of the ColorScale and returns the current class instance. If *value* is not specified, returns the current scale value.
@param {String} [*value* = "linear"] Can either be "linear", "jenks", or "buckets".
@chainable
*/
}, {
key: "scale",
value: function scale(_) {
return arguments.length ? (this._scale = _, this) : this._scale;
}
/**
@memberof ColorScale
@desc If *selector* is specified, sets the SVG container element to the specified d3 selector or DOM element and returns the current class instance. If *selector* is not specified, returns the current SVG container element.
@param {String|HTMLElement} [*selector* = d3.select("body").append("svg")]
@chainable
*/
}, {
key: "select",
value: function select(_) {
return arguments.length ? (this._select = _select(_), this) : this._select;
}
/**
@memberof ColorScale
@desc The height of horizontal color scales, and width when positioned vertical.
@param {Number} [*value* = 10]
@chainable
*/
}, {
key: "size",
value: function size(_) {
return arguments.length ? (this._size = _, this) : this._size;
}
/**
@memberof ColorScale
@desc If *value* is specified, sets the value accessor to the specified function or string and returns the current class instance. If *value* is not specified, returns the current value accessor.
@param {Function|String} [*value*]
@chainable
@example
function value(d) {
return d.value;
}
*/
}, {
key: "value",
value: function value(_) {
return arguments.length ? (this._value = typeof _ === "function" ? _ : constant$1(_), this) : this._value;
}
/**
@memberof ColorScale
@desc If *value* is specified, sets the overall width of the ColorScale and returns the current class instance. If *value* is not specified, returns the current width value.
@param {Number} [*value* = 400]
@chainable
*/
}, {
key: "width",
value: function width(_) {
return arguments.length ? (this._width = _, this) : this._width;
}
}]);
return ColorScale;
}(BaseClass);
function _typeof$l(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$l = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$l = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$l(obj);
}
function _classCallCheck$j(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$j(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$j(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$j(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$j(Constructor, staticProps);
return Constructor;
}
function _get$7(target, property, receiver) {
if (typeof Reflect !== "undefined" && Reflect.get) {
_get$7 = Reflect.get;
} else {
_get$7 = function _get(target, property, receiver) {
var base = _superPropBase$7(target, property);
if (!base) return;
var desc = Object.getOwnPropertyDescriptor(base, property);
if (desc.get) {
return desc.get.call(receiver);
}
return desc.value;
};
}
return _get$7(target, property, receiver || target);
}
function _superPropBase$7(object, property) {
while (!Object.prototype.hasOwnProperty.call(object, property)) {
object = _getPrototypeOf$h(object);
if (object === null) break;
}
return object;
}
function _inherits$h(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$h(subClass, superClass);
}
function _setPrototypeOf$h(o, p) {
_setPrototypeOf$h = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$h(o, p);
}
function _createSuper$h(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$h();
return function _createSuperInternal() {
var Super = _getPrototypeOf$h(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$h(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$h(this, result);
};
}
function _possibleConstructorReturn$h(self, call) {
if (call && (_typeof$l(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$h(self);
}
function _assertThisInitialized$h(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$h() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$h(o) {
_getPrototypeOf$h = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$h(o);
}
/**
@class Timeline
@extends external:Axis
*/
var Timeline = /*#__PURE__*/function (_Axis) {
_inherits$h(Timeline, _Axis);
var _super = _createSuper$h(Timeline);
/**
@memberof Timeline
@desc Invoked when creating a new class instance, and overrides any default parameters inherited from Axis.
@private
*/
function Timeline() {
var _this;
_classCallCheck$j(this, Timeline);
_this = _super.call(this);
_this._barConfig = Object.assign({}, _this._barConfig, {
"stroke-width": function strokeWidth() {
return _this._buttonBehaviorCurrent === "buttons" ? 0 : 1;
}
});
_this._brushing = true;
_this._brushFilter = function () {
return !event$1.button && event$1.detail < 2;
};
_this._buttonAlign = "middle";
_this._buttonBehavior = "auto";
_this._buttonPadding = 10;
_this._buttonHeight = 30;
_this._domain = [2001, 2010];
_this._gridSize = 0;
_this._handleConfig = {
fill: "#444"
};
_this._handleSize = 6;
_this._height = 100;
_this._labelOffset = false;
_this._on = {};
_this.orient("bottom");
_this._scale = "time";
_this._selectionConfig = {
"fill": "#777",
"stroke-width": 0
};
_this._shape = "Rect";
_this._shapeConfig = Object.assign({}, _this._shapeConfig, {
labelBounds: function labelBounds(d) {
return _this._buttonBehaviorCurrent === "buttons" ? {
x: d.labelBounds.x,
y: -5,
width: d.labelBounds.width,
height: _this._buttonHeight
} : d.labelBounds;
},
fill: function fill() {
return _this._buttonBehaviorCurrent === "buttons" ? "#EEE" : "#444";
},
height: function height(d) {
return _this._buttonBehaviorCurrent === "buttons" ? _this._buttonHeight : d.tick ? 10 : 0;
},
width: function width(d) {
return _this._buttonBehaviorCurrent === "buttons" ? _this._ticksWidth / _this._availableTicks.length : d.tick ? _this._domain.map(function (t) {
return date$2(t).getTime();
}).includes(d.id) ? 2 : 1 : 0;
},
y: function y(d) {
return _this._buttonBehaviorCurrent === "buttons" ? _this._align === "middle" ? _this._height / 2 : _this._align === "start" ? _this._margin.top + _this._buttonHeight / 2 : _this._height - _this._buttonHeight / 2 - _this._margin.bottom : d.y;
}
});
_this._snapping = true;
return _this;
}
/**
@memberof Timeline
@desc Triggered on brush "brush".
@private
*/
_createClass$j(Timeline, [{
key: "_brushBrush",
value: function _brushBrush() {
if (event$1.sourceEvent && event$1.sourceEvent.offsetX && event$1.selection !== null && (!this._brushing || this._snapping)) {
var domain = this._updateDomain();
this._brushGroup.call(this._brush.move, this._updateBrushLimit(domain));
}
this._brushStyle();
if (this._on.brush) this._on.brush(this._selection);
}
/**
@memberof Timeline
@desc Triggered on brush "end".
@private
*/
}, {
key: "_brushEnd",
value: function _brushEnd() {
if (!event$1.sourceEvent) return; // Only transition after input.
var domain = this._updateDomain();
this._brushStyle();
if (this._brushing || !this._snapping) this._brushGroup.transition(this._transition).call(this._brush.move, this._updateBrushLimit(domain));
if (this._on.end) this._on.end(this._selection);
}
/**
@memberof Timeline
@desc Triggered on brush "start".
@private
*/
}, {
key: "_brushStart",
value: function _brushStart() {
if (event$1.sourceEvent !== null && (!this._brushing || this._snapping)) {
var domain = this._updateDomain();
this._brushGroup.call(this._brush.move, this._updateBrushLimit(domain));
}
this._brushStyle();
if (this._on.start) this._on.start();
}
/**
@memberof Timeline
@desc Overrides the default brush styles.
@private
*/
}, {
key: "_brushStyle",
value: function _brushStyle() {
var height = this._position.height;
var timelineHeight = this._shape === "Circle" ? typeof this._shapeConfig.r === "function" ? this._shapeConfig.r({
tick: true
}) * 2 : this._shapeConfig.r : this._shape === "Rect" ? typeof this._shapeConfig[height] === "function" ? this._shapeConfig[height]({
tick: true
}) : this._shapeConfig[height] : this._tickSize;
var brushOverlay = this._brushGroup.selectAll(".overlay").attr("cursor", this._brushing ? "crosshair" : "pointer");
var brushSelection = this._brushGroup.selectAll(".selection").call(attrize, this._selectionConfig).attr("height", timelineHeight);
var brushHandle = this._brushGroup.selectAll(".handle").call(attrize, this._handleConfig).attr("height", this._buttonBehaviorCurrent === "buttons" ? this._buttonHeight : timelineHeight + this._handleSize);
if (this._buttonBehaviorCurrent === "buttons") {
var yTransform = this._align === "middle" ? this._height / 2 - this._buttonHeight / 2 : this._align === "start" ? this._margin.top : this._height - this._buttonHeight - this._margin.bottom;
brushHandle.attr("y", yTransform);
brushOverlay.attr("x", this._marginLeft).attr("width", this._ticksWidth);
brushSelection.attr("y", yTransform);
}
}
/**
@memberof Timeline
@desc Updates domain of the timeline used in brush functions.
@private
*/
}, {
key: "_updateDomain",
value: function _updateDomain() {
var x = mouse(this._select.node())[0];
var domain = event$1.selection && this._brushing ? event$1.selection : [x, x];
if (this._buttonBehaviorCurrent === "ticks") domain = domain.map(this._d3Scale.invert);
domain = domain.map(Number);
if (event$1.type === "brush" && this._brushing && this._buttonBehaviorCurrent === "buttons") {
var diffs = event$1.selection.map(function (d) {
return Math.abs(d - event$1.sourceEvent.offsetX);
});
domain = diffs[1] <= diffs[0] ? [event$1.selection[0], event$1.sourceEvent.offsetX].sort(function (a, b) {
return a - b;
}) : [event$1.sourceEvent.offsetX, event$1.selection[1]].sort(function (a, b) {
return a - b;
});
}
var ticks = this._buttonBehaviorCurrent === "ticks" ? this._availableTicks.map(Number) : this._d3Scale.range();
if (this._buttonBehaviorCurrent === "ticks") {
domain[0] = date$2(closest(domain[0], ticks));
domain[1] = date$2(closest(domain[1], ticks));
} else {
domain[0] = closest(domain[0], ticks);
domain[1] = closest(domain[1], ticks);
}
var single = +domain[0] === +domain[1];
if (event$1.type === "brush" || event$1.type === "end") {
this._selection = this._buttonBehaviorCurrent === "ticks" ? single ? domain[0] : domain : single ? date$2(this._availableTicks[ticks.indexOf(domain[0])]) : [date$2(this._availableTicks[ticks.indexOf(domain[0])]), date$2(this._availableTicks[ticks.indexOf(domain[1])])];
}
return domain;
}
/**
@memberof Timeline
@desc Updates limits of the brush.
@private
*/
}, {
key: "_updateBrushLimit",
value: function _updateBrushLimit(domain) {
var selection = this._buttonBehaviorCurrent === "ticks" ? domain.map(date$2).map(this._d3Scale) : domain;
if (selection[0] === selection[1]) {
selection[0] -= 0.1;
selection[1] += 0.1;
}
if (this._buttonBehaviorCurrent === "buttons") {
var buttonWidth = 0.5 * (this._ticksWidth / this._availableTicks.length - this._handleSize);
selection[0] -= buttonWidth;
selection[1] += buttonWidth;
}
return selection;
}
/**
@memberof Timeline
@desc Draws the timeline.
@param {Function} [*callback* = undefined]
@chainable
*/
}, {
key: "render",
value: function render(callback) {
var _this2 = this;
var _this$_position = this._position,
height = _this$_position.height,
y = _this$_position.y;
if (this._buttonBehavior !== "ticks") {
var ticks = this._ticks ? this._ticks.map(date$2) : this._domain.map(date$2);
var d3Scale = scaleTime().domain(ticks).range([0, this._width]);
ticks = this._ticks ? ticks : d3Scale.ticks();
if (!this._tickFormat) this._tickFormat = d3Scale.tickFormat(ticks.length - 1, this._tickSpecifier); // Measures size of ticks
var maxLabel = 0;
ticks.forEach(function (d, i) {
var f = _this2._shapeConfig.labelConfig.fontFamily(d, i),
s = _this2._shapeConfig.labelConfig.fontSize(d, i);
var wrap = textWrap().fontFamily(f).fontSize(s).lineHeight(_this2._shapeConfig.lineHeight ? _this2._shapeConfig.lineHeight(d, i) : undefined);
var res = wrap(d3Scale.tickFormat(ticks.length - 1, _this2._tickSpecifier)(d));
var width = res.lines.length ? Math.ceil(max(res.lines.map(function (line) {
return textWidth(line, {
"font-family": f,
"font-size": s
});
}))) + s / 4 : 0;
if (width % 2) width++;
if (maxLabel < width) maxLabel = width + 2 * _this2._buttonPadding;
});
this._ticksWidth = maxLabel * ticks.length;
}
this._buttonBehaviorCurrent = this._buttonBehavior === "auto" ? this._ticksWidth < this._width ? "buttons" : "ticks" : this._buttonBehavior;
if (this._buttonBehaviorCurrent === "buttons") {
this._scale = "ordinal";
this._labelRotation = 0;
if (!this._brushing) this._handleSize = 0;
var domain = scaleTime().domain(this._domain.map(date$2)).ticks().map(this._tickFormat).map(Number);
this._domain = this._ticks ? this._ticks.map(date$2) : Array.from(Array(domain[domain.length - 1] - domain[0] + 1), function (_, x) {
return domain[0] + x;
}).map(date$2);
this._ticks = this._domain;
var buttonMargin = 0.5 * this._ticksWidth / this._ticks.length;
this._marginLeft = this._buttonAlign === "middle" ? (this._width - this._ticksWidth) / 2 : this._buttonAlign === "end" ? this._width - this._ticksWidth : 0;
var marginRight = this._buttonAlign === "middle" ? (this._width + this._ticksWidth) / 2 : this._buttonAlign === "start" ? this._ticksWidth : undefined;
this._range = [this._buttonAlign === "start" ? undefined : this._marginLeft + buttonMargin, this._buttonAlign === "end" ? undefined : marginRight - buttonMargin];
}
if (this._ticks) this._domain = this._buttonBehaviorCurrent === "ticks" ? [this._ticks[0], this._ticks[this._ticks.length - 1]] : this._ticks.map(date$2);
this._labels = this._ticks;
_get$7(_getPrototypeOf$h(Timeline.prototype), "render", this).call(this, callback);
var offset = this._outerBounds[y],
range = this._d3Scale.range();
var brush = this._brush = brushX().extent([[range[0], offset], [range[range.length - 1], offset + this._outerBounds[height]]]).filter(this._brushFilter).handleSize(this._handleSize).on("start", this._brushStart.bind(this)).on("brush", this._brushBrush.bind(this)).on("end", this._brushEnd.bind(this));
var latest = this._buttonBehaviorCurrent === "ticks" ? this._availableTicks[this._availableTicks.length - 1] : range[range.length - 1];
var selection = this._selection === void 0 ? [latest, latest] : this._selection instanceof Array ? this._buttonBehaviorCurrent === "buttons" ? this._selection.map(function (d) {
return range[_this2._ticks.map(Number).indexOf(+d)];
}).slice() : this._selection.slice() : this._buttonBehaviorCurrent === "buttons" ? [range[this._ticks.map(Number).indexOf(+this._selection)], range[this._ticks.map(Number).indexOf(+this._selection)]] : [this._selection, this._selection];
this._updateBrushLimit(selection);
this._brushGroup = elem("g.brushGroup", {
parent: this._group
});
this._brushGroup.call(brush).transition(this._transition).call(brush.move, this._buttonBehaviorCurrent === "ticks" ? this._updateBrushLimit(selection) : selection);
this._outerBounds.y -= this._handleSize / 2;
this._outerBounds.height += this._handleSize / 2;
return this;
}
/**
@memberof Timeline
@desc If *value* is specified, sets the button padding and returns the current class instance. If *value* is not specified, returns the current button padding.
@param {Number} [*value* = 10]
@chainable
*/
}, {
key: "buttonPadding",
value: function buttonPadding(_) {
return arguments.length ? (this._buttonPadding = _, this) : this._buttonPadding;
}
/**
@memberof Timeline
@desc If *value* is specified, toggles the brushing value and returns the current class instance. If *value* is not specified, returns the current brushing value.
@param {Boolean} [*value* = true]
@chainable
*/
}, {
key: "brushing",
value: function brushing(_) {
return arguments.length ? (this._brushing = _, this) : this._brushing;
}
/**
@memberof Timeline
@desc If *value* is specified, sets the brush event filter and returns the current class instance. If *value* is not specified, returns the current brush event filter.
@param {Function} [*value*]
@chainable
@example
function() {
return !event.button && event.detail < 2;
}
*/
}, {
key: "brushFilter",
value: function brushFilter(_) {
return arguments.length ? (this._brushFilter = _, this) : this._brushFilter;
}
/**
@memberof Timeline
@desc If *value* is specified, toggles the horizontal alignment of the button timeline. Accepted values are `"start"`, `"middle"` and `"end"`. If *value* is not specified, returns the current button value.
@param {String} [*value* = "middle"]
@chainable
*/
}, {
key: "buttonAlign",
value: function buttonAlign(_) {
return arguments.length ? (this._buttonAlign = _, this) : this._buttonAlign;
}
/**
@memberof Timeline
@desc If *value* is specified, toggles the style of the timeline. Accepted values are `"auto"`, `"buttons"` and `"ticks"`. If *value* is not specified, returns the current button value.
@param {String} [*value* = "auto"]
@chainable
*/
}, {
key: "buttonBehavior",
value: function buttonBehavior(_) {
return arguments.length ? (this._buttonBehavior = _, this) : this._buttonBehavior;
}
/**
@memberof Timeline
@desc If *value* is specified, sets the button height and returns the current class instance. If *value* is not specified, returns the current button height.
@param {Number} [*value* = 30]
@chainable
*/
}, {
key: "buttonHeight",
value: function buttonHeight(_) {
return arguments.length ? (this._buttonHeight = _, this) : this._buttonHeight;
}
/**
@memberof Timeline
@desc If *value* is specified, sets the handle style and returns the current class instance. If *value* is not specified, returns the current handle style.
@param {Object} [*value*]
@chainable
*/
}, {
key: "handleConfig",
value: function handleConfig(_) {
return arguments.length ? (this._handleConfig = Object.assign(this._handleConfig, _), this) : this._handleConfig;
}
/**
@memberof Timeline
@desc If *value* is specified, sets the handle size and returns the current class instance. If *value* is not specified, returns the current handle size.
@param {Number} [*value* = 6]
@chainable
*/
}, {
key: "handleSize",
value: function handleSize(_) {
return arguments.length ? (this._handleSize = _, this) : this._handleSize;
}
/**
@memberof Timeline
@desc Adds or removes a *listener* for the specified brush event *typename*. If a *listener* is not specified, returns the currently-assigned listener for the specified event *typename*. Mirrors the core [d3-brush](https://github.com/d3/d3-brush#brush_on) behavior.
@param {String|Object} [*typename*]
@param {Function} [*listener*]
@chainable
*/
}, {
key: "on",
value: function on(_, f) {
return arguments.length === 2 ? (this._on[_] = f, this) : arguments.length ? typeof _ === "string" ? this._on[_] : (this._on = Object.assign({}, this._on, _), this) : this._on;
}
/**
@memberof Timeline
@desc If *value* is specified, sets the selection style and returns the current class instance. If *value* is not specified, returns the current selection style.
@param {Object} [*value*]
@chainable
*/
}, {
key: "selectionConfig",
value: function selectionConfig(_) {
return arguments.length ? (this._selectionConfig = Object.assign(this._selectionConfig, _), this) : this._selectionConfig;
}
/**
@memberof Timeline
@desc If *value* is specified, sets the selection and returns the current class instance. If *value* is not specified, returns the current selection. Defaults to the most recent year in the timeline.
@param {Array|Date|Number|String} [*value*]
@chainable
*/
}, {
key: "selection",
value: function selection(_) {
return arguments.length ? (this._selection = _, this) : this._selection;
}
/**
@memberof Timeline
@desc If *value* is specified, toggles the snapping value and returns the current class instance. If *value* is not specified, returns the current snapping value.
@param {Boolean} [*value* = true]
@chainable
*/
}, {
key: "snapping",
value: function snapping(_) {
return arguments.length ? (this._snapping = _, this) : this._snapping;
}
}]);
return Timeline;
}(Axis);
/**!
* @fileOverview Kickass library to create and place poppers near their reference elements.
* @version 1.16.1
* @license
* Copyright (c) 2016 Federico Zivolo and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && typeof navigator !== 'undefined';
var timeoutDuration = function () {
var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
return 1;
}
}
return 0;
}();
function microtaskDebounce(fn) {
var called = false;
return function () {
if (called) {
return;
}
called = true;
window.Promise.resolve().then(function () {
called = false;
fn();
});
};
}
function taskDebounce(fn) {
var scheduled = false;
return function () {
if (!scheduled) {
scheduled = true;
setTimeout(function () {
scheduled = false;
fn();
}, timeoutDuration);
}
};
}
var supportsMicroTasks = isBrowser && window.Promise;
/**
* Create a debounced version of a method, that's asynchronously deferred
* but called in the minimum time possible.
*
* @method
* @memberof Popper.Utils
* @argument {Function} fn
* @returns {Function}
*/
var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;
/**
* Check if the given variable is a function
* @method
* @memberof Popper.Utils
* @argument {Any} functionToCheck - variable to check
* @returns {Boolean} answer to: is a function?
*/
function isFunction(functionToCheck) {
var getType = {};
return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
}
/**
* Get CSS computed property of the given element
* @method
* @memberof Popper.Utils
* @argument {Eement} element
* @argument {String} property
*/
function getStyleComputedProperty(element, property) {
if (element.nodeType !== 1) {
return [];
} // NOTE: 1 DOM access here
var window = element.ownerDocument.defaultView;
var css = window.getComputedStyle(element, null);
return property ? css[property] : css;
}
/**
* Returns the parentNode or the host of the element
* @method
* @memberof Popper.Utils
* @argument {Element} element
* @returns {Element} parent
*/
function getParentNode(element) {
if (element.nodeName === 'HTML') {
return element;
}
return element.parentNode || element.host;
}
/**
* Returns the scrolling parent of the given element
* @method
* @memberof Popper.Utils
* @argument {Element} element
* @returns {Element} scroll parent
*/
function getScrollParent(element) {
// Return body, `getScroll` will take care to get the correct `scrollTop` from it
if (!element) {
return document.body;
}
switch (element.nodeName) {
case 'HTML':
case 'BODY':
return element.ownerDocument.body;
case '#document':
return element.body;
} // Firefox want us to check `-x` and `-y` variations as well
var _getStyleComputedProp = getStyleComputedProperty(element),
overflow = _getStyleComputedProp.overflow,
overflowX = _getStyleComputedProp.overflowX,
overflowY = _getStyleComputedProp.overflowY;
if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {
return element;
}
return getScrollParent(getParentNode(element));
}
/**
* Returns the reference node of the reference object, or the reference object itself.
* @method
* @memberof Popper.Utils
* @param {Element|Object} reference - the reference element (the popper will be relative to this)
* @returns {Element} parent
*/
function getReferenceNode(reference) {
return reference && reference.referenceNode ? reference.referenceNode : reference;
}
var isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);
var isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);
/**
* Determines if the browser is Internet Explorer
* @method
* @memberof Popper.Utils
* @param {Number} version to check
* @returns {Boolean} isIE
*/
function isIE(version) {
if (version === 11) {
return isIE11;
}
if (version === 10) {
return isIE10;
}
return isIE11 || isIE10;
}
/**
* Returns the offset parent of the given element
* @method
* @memberof Popper.Utils
* @argument {Element} element
* @returns {Element} offset parent
*/
function getOffsetParent(element) {
if (!element) {
return document.documentElement;
}
var noOffsetParent = isIE(10) ? document.body : null; // NOTE: 1 DOM access here
var offsetParent = element.offsetParent || null; // Skip hidden elements which don't have an offsetParent
while (offsetParent === noOffsetParent && element.nextElementSibling) {
offsetParent = (element = element.nextElementSibling).offsetParent;
}
var nodeName = offsetParent && offsetParent.nodeName;
if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
return element ? element.ownerDocument.documentElement : document.documentElement;
} // .offsetParent will return the closest TH, TD or TABLE in case
// no offsetParent is present, I hate this job...
if (['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {
return getOffsetParent(offsetParent);
}
return offsetParent;
}
function isOffsetContainer(element) {
var nodeName = element.nodeName;
if (nodeName === 'BODY') {
return false;
}
return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;
}
/**
* Finds the root node (document, shadowDOM root) of the given element
* @method
* @memberof Popper.Utils
* @argument {Element} node
* @returns {Element} root node
*/
function getRoot(node) {
if (node.parentNode !== null) {
return getRoot(node.parentNode);
}
return node;
}
/**
* Finds the offset parent common to the two provided nodes
* @method
* @memberof Popper.Utils
* @argument {Element} element1
* @argument {Element} element2
* @returns {Element} common offset parent
*/
function findCommonOffsetParent(element1, element2) {
// This check is needed to avoid errors in case one of the elements isn't defined for any reason
if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
return document.documentElement;
} // Here we make sure to give as "start" the element that comes first in the DOM
var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;
var start = order ? element1 : element2;
var end = order ? element2 : element1; // Get common ancestor container
var range = document.createRange();
range.setStart(start, 0);
range.setEnd(end, 0);
var commonAncestorContainer = range.commonAncestorContainer; // Both nodes are inside #document
if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {
if (isOffsetContainer(commonAncestorContainer)) {
return commonAncestorContainer;
}
return getOffsetParent(commonAncestorContainer);
} // one of the nodes is inside shadowDOM, find which one
var element1root = getRoot(element1);
if (element1root.host) {
return findCommonOffsetParent(element1root.host, element2);
} else {
return findCommonOffsetParent(element1, getRoot(element2).host);
}
}
/**
* Gets the scroll value of the given element in the given side (top and left)
* @method
* @memberof Popper.Utils
* @argument {Element} element
* @argument {String} side `top` or `left`
* @returns {number} amount of scrolled pixels
*/
function getScroll(element) {
var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';
var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
var nodeName = element.nodeName;
if (nodeName === 'BODY' || nodeName === 'HTML') {
var html = element.ownerDocument.documentElement;
var scrollingElement = element.ownerDocument.scrollingElement || html;
return scrollingElement[upperSide];
}
return element[upperSide];
}
/*
* Sum or subtract the element scroll values (left and top) from a given rect object
* @method
* @memberof Popper.Utils
* @param {Object} rect - Rect object you want to change
* @param {HTMLElement} element - The element from the function reads the scroll values
* @param {Boolean} subtract - set to true if you want to subtract the scroll values
* @return {Object} rect - The modifier rect object
*/
function includeScroll(rect, element) {
var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var scrollTop = getScroll(element, 'top');
var scrollLeft = getScroll(element, 'left');
var modifier = subtract ? -1 : 1;
rect.top += scrollTop * modifier;
rect.bottom += scrollTop * modifier;
rect.left += scrollLeft * modifier;
rect.right += scrollLeft * modifier;
return rect;
}
/*
* Helper to detect borders of a given element
* @method
* @memberof Popper.Utils
* @param {CSSStyleDeclaration} styles
* Result of `getStyleComputedProperty` on the given element
* @param {String} axis - `x` or `y`
* @return {number} borders - The borders size of the given axis
*/
function getBordersSize(styles, axis) {
var sideA = axis === 'x' ? 'Left' : 'Top';
var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
return parseFloat(styles['border' + sideA + 'Width']) + parseFloat(styles['border' + sideB + 'Width']);
}
function getSize(axis, body, html, computedStyle) {
return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? parseInt(html['offset' + axis]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')]) : 0);
}
function getWindowSizes(document) {
var body = document.body;
var html = document.documentElement;
var computedStyle = isIE(10) && getComputedStyle(html);
return {
height: getSize('Height', body, html, computedStyle),
width: getSize('Width', body, html, computedStyle)
};
}
var classCallCheck = function classCallCheck(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 defineProperty = function defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
};
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;
};
/**
* Given element offsets, generate an output similar to getBoundingClientRect
* @method
* @memberof Popper.Utils
* @argument {Object} offsets
* @returns {Object} ClientRect like output
*/
function getClientRect(offsets) {
return _extends({}, offsets, {
right: offsets.left + offsets.width,
bottom: offsets.top + offsets.height
});
}
/**
* Get bounding client rect of given element
* @method
* @memberof Popper.Utils
* @param {HTMLElement} element
* @return {Object} client rect
*/
function getBoundingClientRect(element) {
var rect = {}; // IE10 10 FIX: Please, don't ask, the element isn't
// considered in DOM in some circumstances...
// This isn't reproducible in IE10 compatibility mode of IE11
try {
if (isIE(10)) {
rect = element.getBoundingClientRect();
var scrollTop = getScroll(element, 'top');
var scrollLeft = getScroll(element, 'left');
rect.top += scrollTop;
rect.left += scrollLeft;
rect.bottom += scrollTop;
rect.right += scrollLeft;
} else {
rect = element.getBoundingClientRect();
}
} catch (e) {}
var result = {
left: rect.left,
top: rect.top,
width: rect.right - rect.left,
height: rect.bottom - rect.top
}; // subtract scrollbar size from sizes
var sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : {};
var width = sizes.width || element.clientWidth || result.width;
var height = sizes.height || element.clientHeight || result.height;
var horizScrollbar = element.offsetWidth - width;
var vertScrollbar = element.offsetHeight - height; // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
// we make this check conditional for performance reasons
if (horizScrollbar || vertScrollbar) {
var styles = getStyleComputedProperty(element);
horizScrollbar -= getBordersSize(styles, 'x');
vertScrollbar -= getBordersSize(styles, 'y');
result.width -= horizScrollbar;
result.height -= vertScrollbar;
}
return getClientRect(result);
}
function getOffsetRectRelativeToArbitraryNode(children, parent) {
var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var isIE10 = isIE(10);
var isHTML = parent.nodeName === 'HTML';
var childrenRect = getBoundingClientRect(children);
var parentRect = getBoundingClientRect(parent);
var scrollParent = getScrollParent(children);
var styles = getStyleComputedProperty(parent);
var borderTopWidth = parseFloat(styles.borderTopWidth);
var borderLeftWidth = parseFloat(styles.borderLeftWidth); // In cases where the parent is fixed, we must ignore negative scroll in offset calc
if (fixedPosition && isHTML) {
parentRect.top = Math.max(parentRect.top, 0);
parentRect.left = Math.max(parentRect.left, 0);
}
var offsets = getClientRect({
top: childrenRect.top - parentRect.top - borderTopWidth,
left: childrenRect.left - parentRect.left - borderLeftWidth,
width: childrenRect.width,
height: childrenRect.height
});
offsets.marginTop = 0;
offsets.marginLeft = 0; // Subtract margins of documentElement in case it's being used as parent
// we do this only on HTML because it's the only element that behaves
// differently when margins are applied to it. The margins are included in
// the box of the documentElement, in the other cases not.
if (!isIE10 && isHTML) {
var marginTop = parseFloat(styles.marginTop);
var marginLeft = parseFloat(styles.marginLeft);
offsets.top -= borderTopWidth - marginTop;
offsets.bottom -= borderTopWidth - marginTop;
offsets.left -= borderLeftWidth - marginLeft;
offsets.right -= borderLeftWidth - marginLeft; // Attach marginTop and marginLeft because in some circumstances we may need them
offsets.marginTop = marginTop;
offsets.marginLeft = marginLeft;
}
if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {
offsets = includeScroll(offsets, parent);
}
return offsets;
}
function getViewportOffsetRectRelativeToArtbitraryNode(element) {
var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var html = element.ownerDocument.documentElement;
var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);
var width = Math.max(html.clientWidth, window.innerWidth || 0);
var height = Math.max(html.clientHeight, window.innerHeight || 0);
var scrollTop = !excludeScroll ? getScroll(html) : 0;
var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;
var offset = {
top: scrollTop - relativeOffset.top + relativeOffset.marginTop,
left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,
width: width,
height: height
};
return getClientRect(offset);
}
/**
* Check if the given element is fixed or is inside a fixed parent
* @method
* @memberof Popper.Utils
* @argument {Element} element
* @argument {Element} customContainer
* @returns {Boolean} answer to "isFixed?"
*/
function isFixed(element) {
var nodeName = element.nodeName;
if (nodeName === 'BODY' || nodeName === 'HTML') {
return false;
}
if (getStyleComputedProperty(element, 'position') === 'fixed') {
return true;
}
var parentNode = getParentNode(element);
if (!parentNode) {
return false;
}
return isFixed(parentNode);
}
/**
* Finds the first parent of an element that has a transformed property defined
* @method
* @memberof Popper.Utils
* @argument {Element} element
* @returns {Element} first transformed parent or documentElement
*/
function getFixedPositionOffsetParent(element) {
// This check is needed to avoid errors in case one of the elements isn't defined for any reason
if (!element || !element.parentElement || isIE()) {
return document.documentElement;
}
var el = element.parentElement;
while (el && getStyleComputedProperty(el, 'transform') === 'none') {
el = el.parentElement;
}
return el || document.documentElement;
}
/**
* Computed the boundaries limits and return them
* @method
* @memberof Popper.Utils
* @param {HTMLElement} popper
* @param {HTMLElement} reference
* @param {number} padding
* @param {HTMLElement} boundariesElement - Element used to define the boundaries
* @param {Boolean} fixedPosition - Is in fixed position mode
* @returns {Object} Coordinates of the boundaries
*/
function getBoundaries(popper, reference, padding, boundariesElement) {
var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; // NOTE: 1 DOM access here
var boundaries = {
top: 0,
left: 0
};
var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference)); // Handle viewport case
if (boundariesElement === 'viewport') {
boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);
} else {
// Handle other cases based on DOM element used as boundaries
var boundariesNode = void 0;
if (boundariesElement === 'scrollParent') {
boundariesNode = getScrollParent(getParentNode(reference));
if (boundariesNode.nodeName === 'BODY') {
boundariesNode = popper.ownerDocument.documentElement;
}
} else if (boundariesElement === 'window') {
boundariesNode = popper.ownerDocument.documentElement;
} else {
boundariesNode = boundariesElement;
}
var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition); // In case of HTML, we need a different computation
if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {
var _getWindowSizes = getWindowSizes(popper.ownerDocument),
height = _getWindowSizes.height,
width = _getWindowSizes.width;
boundaries.top += offsets.top - offsets.marginTop;
boundaries.bottom = height + offsets.top;
boundaries.left += offsets.left - offsets.marginLeft;
boundaries.right = width + offsets.left;
} else {
// for all the other DOM elements, this one is good
boundaries = offsets;
}
} // Add paddings
padding = padding || 0;
var isPaddingNumber = typeof padding === 'number';
boundaries.left += isPaddingNumber ? padding : padding.left || 0;
boundaries.top += isPaddingNumber ? padding : padding.top || 0;
boundaries.right -= isPaddingNumber ? padding : padding.right || 0;
boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0;
return boundaries;
}
function getArea(_ref) {
var width = _ref.width,
height = _ref.height;
return width * height;
}
/**
* Utility used to transform the `auto` placement to the placement with more
* available space.
* @method
* @memberof Popper.Utils
* @argument {Object} data - The data object generated by update method
* @argument {Object} options - Modifiers configuration and options
* @returns {Object} The data object, properly modified
*/
function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {
var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
if (placement.indexOf('auto') === -1) {
return placement;
}
var boundaries = getBoundaries(popper, reference, padding, boundariesElement);
var rects = {
top: {
width: boundaries.width,
height: refRect.top - boundaries.top
},
right: {
width: boundaries.right - refRect.right,
height: boundaries.height
},
bottom: {
width: boundaries.width,
height: boundaries.bottom - refRect.bottom
},
left: {
width: refRect.left - boundaries.left,
height: boundaries.height
}
};
var sortedAreas = Object.keys(rects).map(function (key) {
return _extends({
key: key
}, rects[key], {
area: getArea(rects[key])
});
}).sort(function (a, b) {
return b.area - a.area;
});
var filteredAreas = sortedAreas.filter(function (_ref2) {
var width = _ref2.width,
height = _ref2.height;
return width >= popper.clientWidth && height >= popper.clientHeight;
});
var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;
var variation = placement.split('-')[1];
return computedPlacement + (variation ? '-' + variation : '');
}
/**
* Get offsets to the reference element
* @method
* @memberof Popper.Utils
* @param {Object} state
* @param {Element} popper - the popper element
* @param {Element} reference - the reference element (the popper will be relative to this)
* @param {Element} fixedPosition - is in fixed position mode
* @returns {Object} An object containing the offsets which will be applied to the popper
*/
function getReferenceOffsets(state, popper, reference) {
var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference));
return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);
}
/**
* Get the outer sizes of the given element (offset size + margins)
* @method
* @memberof Popper.Utils
* @argument {Element} element
* @returns {Object} object containing width and height properties
*/
function getOuterSizes(element) {
var window = element.ownerDocument.defaultView;
var styles = window.getComputedStyle(element);
var x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0);
var y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0);
var result = {
width: element.offsetWidth + y,
height: element.offsetHeight + x
};
return result;
}
/**
* Get the opposite placement of the given one
* @method
* @memberof Popper.Utils
* @argument {String} placement
* @returns {String} flipped placement
*/
function getOppositePlacement(placement) {
var hash = {
left: 'right',
right: 'left',
bottom: 'top',
top: 'bottom'
};
return placement.replace(/left|right|bottom|top/g, function (matched) {
return hash[matched];
});
}
/**
* Get offsets to the popper
* @method
* @memberof Popper.Utils
* @param {Object} position - CSS position the Popper will get applied
* @param {HTMLElement} popper - the popper element
* @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)
* @param {String} placement - one of the valid placement options
* @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper
*/
function getPopperOffsets(popper, referenceOffsets, placement) {
placement = placement.split('-')[0]; // Get popper node sizes
var popperRect = getOuterSizes(popper); // Add position, width and height to our offsets object
var popperOffsets = {
width: popperRect.width,
height: popperRect.height
}; // depending by the popper placement we have to compute its offsets slightly differently
var isHoriz = ['right', 'left'].indexOf(placement) !== -1;
var mainSide = isHoriz ? 'top' : 'left';
var secondarySide = isHoriz ? 'left' : 'top';
var measurement = isHoriz ? 'height' : 'width';
var secondaryMeasurement = !isHoriz ? 'height' : 'width';
popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;
if (placement === secondarySide) {
popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];
} else {
popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];
}
return popperOffsets;
}
/**
* Mimics the `find` method of Array
* @method
* @memberof Popper.Utils
* @argument {Array} arr
* @argument prop
* @argument value
* @returns index or -1
*/
function find(arr, check) {
// use native find if supported
if (Array.prototype.find) {
return arr.find(check);
} // use `filter` to obtain the same behavior of `find`
return arr.filter(check)[0];
}
/**
* Return the index of the matching object
* @method
* @memberof Popper.Utils
* @argument {Array} arr
* @argument prop
* @argument value
* @returns index or -1
*/
function findIndex(arr, prop, value) {
// use native findIndex if supported
if (Array.prototype.findIndex) {
return arr.findIndex(function (cur) {
return cur[prop] === value;
});
} // use `find` + `indexOf` if `findIndex` isn't supported
var match = find(arr, function (obj) {
return obj[prop] === value;
});
return arr.indexOf(match);
}
/**
* Loop trough the list of modifiers and run them in order,
* each of them will then edit the data object.
* @method
* @memberof Popper.Utils
* @param {dataObject} data
* @param {Array} modifiers
* @param {String} ends - Optional modifier name used as stopper
* @returns {dataObject}
*/
function runModifiers(modifiers, data, ends) {
var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
modifiersToRun.forEach(function (modifier) {
if (modifier['function']) {
// eslint-disable-line dot-notation
console.warn('`modifier.function` is deprecated, use `modifier.fn`!');
}
var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation
if (modifier.enabled && isFunction(fn)) {
// Add properties to offsets to make them a complete clientRect object
// we do this before each modifier to make sure the previous one doesn't
// mess with these values
data.offsets.popper = getClientRect(data.offsets.popper);
data.offsets.reference = getClientRect(data.offsets.reference);
data = fn(data, modifier);
}
});
return data;
}
/**
* Updates the position of the popper, computing the new offsets and applying
* the new style.<br />
* Prefer `scheduleUpdate` over `update` because of performance reasons.
* @method
* @memberof Popper
*/
function update() {
// if popper is destroyed, don't perform any further update
if (this.state.isDestroyed) {
return;
}
var data = {
instance: this,
styles: {},
arrowStyles: {},
attributes: {},
flipped: false,
offsets: {}
}; // compute reference element offsets
data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed); // compute auto placement, store placement inside the data object,
// modifiers will be able to edit `placement` if needed
// and refer to originalPlacement to know the original value
data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding); // store the computed placement inside `originalPlacement`
data.originalPlacement = data.placement;
data.positionFixed = this.options.positionFixed; // compute the popper offsets
data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);
data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute'; // run the modifiers
data = runModifiers(this.modifiers, data); // the first `update` will call `onCreate` callback
// the other ones will call `onUpdate` callback
if (!this.state.isCreated) {
this.state.isCreated = true;
this.options.onCreate(data);
} else {
this.options.onUpdate(data);
}
}
/**
* Helper used to know if the given modifier is enabled.
* @method
* @memberof Popper.Utils
* @returns {Boolean}
*/
function isModifierEnabled(modifiers, modifierName) {
return modifiers.some(function (_ref) {
var name = _ref.name,
enabled = _ref.enabled;
return enabled && name === modifierName;
});
}
/**
* Get the prefixed supported property name
* @method
* @memberof Popper.Utils
* @argument {String} property (camelCase)
* @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)
*/
function getSupportedPropertyName(property) {
var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];
var upperProp = property.charAt(0).toUpperCase() + property.slice(1);
for (var i = 0; i < prefixes.length; i++) {
var prefix = prefixes[i];
var toCheck = prefix ? '' + prefix + upperProp : property;
if (typeof document.body.style[toCheck] !== 'undefined') {
return toCheck;
}
}
return null;
}
/**
* Destroys the popper.
* @method
* @memberof Popper
*/
function destroy() {
this.state.isDestroyed = true; // touch DOM only if `applyStyle` modifier is enabled
if (isModifierEnabled(this.modifiers, 'applyStyle')) {
this.popper.removeAttribute('x-placement');
this.popper.style.position = '';
this.popper.style.top = '';
this.popper.style.left = '';
this.popper.style.right = '';
this.popper.style.bottom = '';
this.popper.style.willChange = '';
this.popper.style[getSupportedPropertyName('transform')] = '';
}
this.disableEventListeners(); // remove the popper if user explicitly asked for the deletion on destroy
// do not use `remove` because IE11 doesn't support it
if (this.options.removeOnDestroy) {
this.popper.parentNode.removeChild(this.popper);
}
return this;
}
/**
* Get the window associated with the element
* @argument {Element} element
* @returns {Window}
*/
function getWindow(element) {
var ownerDocument = element.ownerDocument;
return ownerDocument ? ownerDocument.defaultView : window;
}
function attachToScrollParents(scrollParent, event, callback, scrollParents) {
var isBody = scrollParent.nodeName === 'BODY';
var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;
target.addEventListener(event, callback, {
passive: true
});
if (!isBody) {
attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);
}
scrollParents.push(target);
}
/**
* Setup needed event listeners used to update the popper position
* @method
* @memberof Popper.Utils
* @private
*/
function setupEventListeners(reference, options, state, updateBound) {
// Resize event listener on window
state.updateBound = updateBound;
getWindow(reference).addEventListener('resize', state.updateBound, {
passive: true
}); // Scroll event listener on scroll parents
var scrollElement = getScrollParent(reference);
attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);
state.scrollElement = scrollElement;
state.eventsEnabled = true;
return state;
}
/**
* It will add resize/scroll events and start recalculating
* position of the popper element when they are triggered.
* @method
* @memberof Popper
*/
function enableEventListeners() {
if (!this.state.eventsEnabled) {
this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);
}
}
/**
* Remove event listeners used to update the popper position
* @method
* @memberof Popper.Utils
* @private
*/
function removeEventListeners(reference, state) {
// Remove resize event listener on window
getWindow(reference).removeEventListener('resize', state.updateBound); // Remove scroll event listener on scroll parents
state.scrollParents.forEach(function (target) {
target.removeEventListener('scroll', state.updateBound);
}); // Reset state
state.updateBound = null;
state.scrollParents = [];
state.scrollElement = null;
state.eventsEnabled = false;
return state;
}
/**
* It will remove resize/scroll events and won't recalculate popper position
* when they are triggered. It also won't trigger `onUpdate` callback anymore,
* unless you call `update` method manually.
* @method
* @memberof Popper
*/
function disableEventListeners() {
if (this.state.eventsEnabled) {
cancelAnimationFrame(this.scheduleUpdate);
this.state = removeEventListeners(this.reference, this.state);
}
}
/**
* Tells if a given input is a number
* @method
* @memberof Popper.Utils
* @param {*} input to check
* @return {Boolean}
*/
function isNumeric(n) {
return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
}
/**
* Set the style to the given popper
* @method
* @memberof Popper.Utils
* @argument {Element} element - Element to apply the style to
* @argument {Object} styles
* Object with a list of properties and values which will be applied to the element
*/
function setStyles(element, styles) {
Object.keys(styles).forEach(function (prop) {
var unit = ''; // add unit if the value is numeric and is one of the following
if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
unit = 'px';
}
element.style[prop] = styles[prop] + unit;
});
}
/**
* Set the attributes to the given popper
* @method
* @memberof Popper.Utils
* @argument {Element} element - Element to apply the attributes to
* @argument {Object} styles
* Object with a list of properties and values which will be applied to the element
*/
function setAttributes(element, attributes) {
Object.keys(attributes).forEach(function (prop) {
var value = attributes[prop];
if (value !== false) {
element.setAttribute(prop, attributes[prop]);
} else {
element.removeAttribute(prop);
}
});
}
/**
* @function
* @memberof Modifiers
* @argument {Object} data - The data object generated by `update` method
* @argument {Object} data.styles - List of style properties - values to apply to popper element
* @argument {Object} data.attributes - List of attribute properties - values to apply to popper element
* @argument {Object} options - Modifiers configuration and options
* @returns {Object} The same data object
*/
function applyStyle(data) {
// any property present in `data.styles` will be applied to the popper,
// in this way we can make the 3rd party modifiers add custom styles to it
// Be aware, modifiers could override the properties defined in the previous
// lines of this modifier!
setStyles(data.instance.popper, data.styles); // any property present in `data.attributes` will be applied to the popper,
// they will be set as HTML attributes of the element
setAttributes(data.instance.popper, data.attributes); // if arrowElement is defined and arrowStyles has some properties
if (data.arrowElement && Object.keys(data.arrowStyles).length) {
setStyles(data.arrowElement, data.arrowStyles);
}
return data;
}
/**
* Set the x-placement attribute before everything else because it could be used
* to add margins to the popper margins needs to be calculated to get the
* correct popper offsets.
* @method
* @memberof Popper.modifiers
* @param {HTMLElement} reference - The reference element used to position the popper
* @param {HTMLElement} popper - The HTML element used as popper
* @param {Object} options - Popper.js options
*/
function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {
// compute reference element offsets
var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed); // compute auto placement, store placement inside the data object,
// modifiers will be able to edit `placement` if needed
// and refer to originalPlacement to know the original value
var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);
popper.setAttribute('x-placement', placement); // Apply `position` to popper before anything else because
// without the position applied we can't guarantee correct computations
setStyles(popper, {
position: options.positionFixed ? 'fixed' : 'absolute'
});
return options;
}
/**
* @function
* @memberof Popper.Utils
* @argument {Object} data - The data object generated by `update` method
* @argument {Boolean} shouldRound - If the offsets should be rounded at all
* @returns {Object} The popper's position offsets rounded
*
* The tale of pixel-perfect positioning. It's still not 100% perfect, but as
* good as it can be within reason.
* Discussion here: https://github.com/FezVrasta/popper.js/pull/715
*
* Low DPI screens cause a popper to be blurry if not using full pixels (Safari
* as well on High DPI screens).
*
* Firefox prefers no rounding for positioning and does not have blurriness on
* high DPI screens.
*
* Only horizontal placement and left/right values need to be considered.
*/
function getRoundedOffsets(data, shouldRound) {
var _data$offsets = data.offsets,
popper = _data$offsets.popper,
reference = _data$offsets.reference;
var round = Math.round,
floor = Math.floor;
var noRound = function noRound(v) {
return v;
};
var referenceWidth = round(reference.width);
var popperWidth = round(popper.width);
var isVertical = ['left', 'right'].indexOf(data.placement) !== -1;
var isVariation = data.placement.indexOf('-') !== -1;
var sameWidthParity = referenceWidth % 2 === popperWidth % 2;
var bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1;
var horizontalToInteger = !shouldRound ? noRound : isVertical || isVariation || sameWidthParity ? round : floor;
var verticalToInteger = !shouldRound ? noRound : round;
return {
left: horizontalToInteger(bothOddWidth && !isVariation && shouldRound ? popper.left - 1 : popper.left),
top: verticalToInteger(popper.top),
bottom: verticalToInteger(popper.bottom),
right: horizontalToInteger(popper.right)
};
}
var isFirefox = isBrowser && /Firefox/i.test(navigator.userAgent);
/**
* @function
* @memberof Modifiers
* @argument {Object} data - The data object generated by `update` method
* @argument {Object} options - Modifiers configuration and options
* @returns {Object} The data object, properly modified
*/
function computeStyle(data, options) {
var x = options.x,
y = options.y;
var popper = data.offsets.popper; // Remove this legacy support in Popper.js v2
var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {
return modifier.name === 'applyStyle';
}).gpuAcceleration;
if (legacyGpuAccelerationOption !== undefined) {
console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');
}
var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;
var offsetParent = getOffsetParent(data.instance.popper);
var offsetParentRect = getBoundingClientRect(offsetParent); // Styles
var styles = {
position: popper.position
};
var offsets = getRoundedOffsets(data, window.devicePixelRatio < 2 || !isFirefox);
var sideA = x === 'bottom' ? 'top' : 'bottom';
var sideB = y === 'right' ? 'left' : 'right'; // if gpuAcceleration is set to `true` and transform is supported,
// we use `translate3d` to apply the position to the popper we
// automatically use the supported prefixed version if needed
var prefixedProperty = getSupportedPropertyName('transform'); // now, let's make a step back and look at this code closely (wtf?)
// If the content of the popper grows once it's been positioned, it
// may happen that the popper gets misplaced because of the new content
// overflowing its reference element
// To avoid this problem, we provide two options (x and y), which allow
// the consumer to define the offset origin.
// If we position a popper on top of a reference element, we can set
// `x` to `top` to make the popper grow towards its top instead of
// its bottom.
var left = void 0,
top = void 0;
if (sideA === 'bottom') {
// when offsetParent is <html> the positioning is relative to the bottom of the screen (excluding the scrollbar)
// and not the bottom of the html element
if (offsetParent.nodeName === 'HTML') {
top = -offsetParent.clientHeight + offsets.bottom;
} else {
top = -offsetParentRect.height + offsets.bottom;
}
} else {
top = offsets.top;
}
if (sideB === 'right') {
if (offsetParent.nodeName === 'HTML') {
left = -offsetParent.clientWidth + offsets.right;
} else {
left = -offsetParentRect.width + offsets.right;
}
} else {
left = offsets.left;
}
if (gpuAcceleration && prefixedProperty) {
styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
styles[sideA] = 0;
styles[sideB] = 0;
styles.willChange = 'transform';
} else {
// othwerise, we use the standard `top`, `left`, `bottom` and `right` properties
var invertTop = sideA === 'bottom' ? -1 : 1;
var invertLeft = sideB === 'right' ? -1 : 1;
styles[sideA] = top * invertTop;
styles[sideB] = left * invertLeft;
styles.willChange = sideA + ', ' + sideB;
} // Attributes
var attributes = {
'x-placement': data.placement
}; // Update `data` attributes, styles and arrowStyles
data.attributes = _extends({}, attributes, data.attributes);
data.styles = _extends({}, styles, data.styles);
data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);
return data;
}
/**
* Helper used to know if the given modifier depends from another one.<br />
* It checks if the needed modifier is listed and enabled.
* @method
* @memberof Popper.Utils
* @param {Array} modifiers - list of modifiers
* @param {String} requestingName - name of requesting modifier
* @param {String} requestedName - name of requested modifier
* @returns {Boolean}
*/
function isModifierRequired(modifiers, requestingName, requestedName) {
var requesting = find(modifiers, function (_ref) {
var name = _ref.name;
return name === requestingName;
});
var isRequired = !!requesting && modifiers.some(function (modifier) {
return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;
});
if (!isRequired) {
var _requesting = '`' + requestingName + '`';
var requested = '`' + requestedName + '`';
console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');
}
return isRequired;
}
/**
* @function
* @memberof Modifiers
* @argument {Object} data - The data object generated by update method
* @argument {Object} options - Modifiers configuration and options
* @returns {Object} The data object, properly modified
*/
function arrow(data, options) {
var _data$offsets$arrow; // arrow depends on keepTogether in order to work
if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
return data;
}
var arrowElement = options.element; // if arrowElement is a string, suppose it's a CSS selector
if (typeof arrowElement === 'string') {
arrowElement = data.instance.popper.querySelector(arrowElement); // if arrowElement is not found, don't run the modifier
if (!arrowElement) {
return data;
}
} else {
// if the arrowElement isn't a query selector we must check that the
// provided DOM node is child of its popper node
if (!data.instance.popper.contains(arrowElement)) {
console.warn('WARNING: `arrow.element` must be child of its popper element!');
return data;
}
}
var placement = data.placement.split('-')[0];
var _data$offsets = data.offsets,
popper = _data$offsets.popper,
reference = _data$offsets.reference;
var isVertical = ['left', 'right'].indexOf(placement) !== -1;
var len = isVertical ? 'height' : 'width';
var sideCapitalized = isVertical ? 'Top' : 'Left';
var side = sideCapitalized.toLowerCase();
var altSide = isVertical ? 'left' : 'top';
var opSide = isVertical ? 'bottom' : 'right';
var arrowElementSize = getOuterSizes(arrowElement)[len]; //
// extends keepTogether behavior making sure the popper and its
// reference have enough pixels in conjunction
//
// top/left side
if (reference[opSide] - arrowElementSize < popper[side]) {
data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
} // bottom/right side
if (reference[side] + arrowElementSize > popper[opSide]) {
data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
}
data.offsets.popper = getClientRect(data.offsets.popper); // compute center of the popper
var center = reference[side] + reference[len] / 2 - arrowElementSize / 2; // Compute the sideValue using the updated popper offsets
// take popper margin in account because we don't have this info available
var css = getStyleComputedProperty(data.instance.popper);
var popperMarginSide = parseFloat(css['margin' + sideCapitalized]);
var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width']);
var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide; // prevent arrowElement from being placed not contiguously to its popper
sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
data.arrowElement = arrowElement;
data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);
return data;
}
/**
* Get the opposite placement variation of the given one
* @method
* @memberof Popper.Utils
* @argument {String} placement variation
* @returns {String} flipped placement variation
*/
function getOppositeVariation(variation) {
if (variation === 'end') {
return 'start';
} else if (variation === 'start') {
return 'end';
}
return variation;
}
/**
* List of accepted placements to use as values of the `placement` option.<br />
* Valid placements are:
* - `auto`
* - `top`
* - `right`
* - `bottom`
* - `left`
*
* Each placement can have a variation from this list:
* - `-start`
* - `-end`
*
* Variations are interpreted easily if you think of them as the left to right
* written languages. Horizontally (`top` and `bottom`), `start` is left and `end`
* is right.<br />
* Vertically (`left` and `right`), `start` is top and `end` is bottom.
*
* Some valid examples are:
* - `top-end` (on top of reference, right aligned)
* - `right-start` (on right of reference, top aligned)
* - `bottom` (on bottom, centered)
* - `auto-end` (on the side with more space available, alignment depends by placement)
*
* @static
* @type {Array}
* @enum {String}
* @readonly
* @method placements
* @memberof Popper
*/
var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start']; // Get rid of `auto` `auto-start` and `auto-end`
var validPlacements = placements.slice(3);
/**
* Given an initial placement, returns all the subsequent placements
* clockwise (or counter-clockwise).
*
* @method
* @memberof Popper.Utils
* @argument {String} placement - A valid placement (it accepts variations)
* @argument {Boolean} counter - Set to true to walk the placements counterclockwise
* @returns {Array} placements including their variations
*/
function clockwise(placement) {
var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var index = validPlacements.indexOf(placement);
var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));
return counter ? arr.reverse() : arr;
}
var BEHAVIORS = {
FLIP: 'flip',
CLOCKWISE: 'clockwise',
COUNTERCLOCKWISE: 'counterclockwise'
};
/**
* @function
* @memberof Modifiers
* @argument {Object} data - The data object generated by update method
* @argument {Object} options - Modifiers configuration and options
* @returns {Object} The data object, properly modified
*/
function flip(data, options) {
// if `inner` modifier is enabled, we can't use the `flip` modifier
if (isModifierEnabled(data.instance.modifiers, 'inner')) {
return data;
}
if (data.flipped && data.placement === data.originalPlacement) {
// seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
return data;
}
var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);
var placement = data.placement.split('-')[0];
var placementOpposite = getOppositePlacement(placement);
var variation = data.placement.split('-')[1] || '';
var flipOrder = [];
switch (options.behavior) {
case BEHAVIORS.FLIP:
flipOrder = [placement, placementOpposite];
break;
case BEHAVIORS.CLOCKWISE:
flipOrder = clockwise(placement);
break;
case BEHAVIORS.COUNTERCLOCKWISE:
flipOrder = clockwise(placement, true);
break;
default:
flipOrder = options.behavior;
}
flipOrder.forEach(function (step, index) {
if (placement !== step || flipOrder.length === index + 1) {
return data;
}
placement = data.placement.split('-')[0];
placementOpposite = getOppositePlacement(placement);
var popperOffsets = data.offsets.popper;
var refOffsets = data.offsets.reference; // using floor because the reference offsets may contain decimals we are not going to consider here
var floor = Math.floor;
var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);
var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);
var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);
var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);
var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);
var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom; // flip the variation if required
var isVertical = ['top', 'bottom'].indexOf(placement) !== -1; // flips variation if reference element overflows boundaries
var flippedVariationByRef = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom); // flips variation if popper content overflows boundaries
var flippedVariationByContent = !!options.flipVariationsByContent && (isVertical && variation === 'start' && overflowsRight || isVertical && variation === 'end' && overflowsLeft || !isVertical && variation === 'start' && overflowsBottom || !isVertical && variation === 'end' && overflowsTop);
var flippedVariation = flippedVariationByRef || flippedVariationByContent;
if (overlapsRef || overflowsBoundaries || flippedVariation) {
// this boolean to detect any flip loop
data.flipped = true;
if (overlapsRef || overflowsBoundaries) {
placement = flipOrder[index + 1];
}
if (flippedVariation) {
variation = getOppositeVariation(variation);
}
data.placement = placement + (variation ? '-' + variation : ''); // this object contains `position`, we want to preserve it along with
// any additional property we may add in the future
data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));
data = runModifiers(data.instance.modifiers, data, 'flip');
}
});
return data;
}
/**
* @function
* @memberof Modifiers
* @argument {Object} data - The data object generated by update method
* @argument {Object} options - Modifiers configuration and options
* @returns {Object} The data object, properly modified
*/
function keepTogether(data) {
var _data$offsets = data.offsets,
popper = _data$offsets.popper,
reference = _data$offsets.reference;
var placement = data.placement.split('-')[0];
var floor = Math.floor;
var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
var side = isVertical ? 'right' : 'bottom';
var opSide = isVertical ? 'left' : 'top';
var measurement = isVertical ? 'width' : 'height';
if (popper[side] < floor(reference[opSide])) {
data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];
}
if (popper[opSide] > floor(reference[side])) {
data.offsets.popper[opSide] = floor(reference[side]);
}
return data;
}
/**
* Converts a string containing value + unit into a px value number
* @function
* @memberof {modifiers~offset}
* @private
* @argument {String} str - Value + unit string
* @argument {String} measurement - `height` or `width`
* @argument {Object} popperOffsets
* @argument {Object} referenceOffsets
* @returns {Number|String}
* Value in pixels, or original string if no values were extracted
*/
function toValue(str, measurement, popperOffsets, referenceOffsets) {
// separate value from unit
var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/);
var value = +split[1];
var unit = split[2]; // If it's not a number it's an operator, I guess
if (!value) {
return str;
}
if (unit.indexOf('%') === 0) {
var element = void 0;
switch (unit) {
case '%p':
element = popperOffsets;
break;
case '%':
case '%r':
default:
element = referenceOffsets;
}
var rect = getClientRect(element);
return rect[measurement] / 100 * value;
} else if (unit === 'vh' || unit === 'vw') {
// if is a vh or vw, we calculate the size based on the viewport
var size = void 0;
if (unit === 'vh') {
size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
} else {
size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
}
return size / 100 * value;
} else {
// if is an explicit pixel unit, we get rid of the unit and keep the value
// if is an implicit unit, it's px, and we return just the value
return value;
}
}
/**
* Parse an `offset` string to extrapolate `x` and `y` numeric offsets.
* @function
* @memberof {modifiers~offset}
* @private
* @argument {String} offset
* @argument {Object} popperOffsets
* @argument {Object} referenceOffsets
* @argument {String} basePlacement
* @returns {Array} a two cells array with x and y offsets in numbers
*/
function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {
var offsets = [0, 0]; // Use height if placement is left or right and index is 0 otherwise use width
// in this way the first offset will use an axis and the second one
// will use the other one
var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1; // Split the offset string to obtain a list of values and operands
// The regex addresses values with the plus or minus sign in front (+10, -20, etc)
var fragments = offset.split(/(\+|\-)/).map(function (frag) {
return frag.trim();
}); // Detect if the offset string contains a pair of values or a single one
// they could be separated by comma or space
var divider = fragments.indexOf(find(fragments, function (frag) {
return frag.search(/,|\s/) !== -1;
}));
if (fragments[divider] && fragments[divider].indexOf(',') === -1) {
console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');
} // If divider is found, we divide the list of values and operands to divide
// them by ofset X and Y.
var splitRegex = /\s*,\s*|\s+/;
var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments]; // Convert the values with units to absolute pixels to allow our computations
ops = ops.map(function (op, index) {
// Most of the units rely on the orientation of the popper
var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';
var mergeWithPrevious = false;
return op // This aggregates any `+` or `-` sign that aren't considered operators
// e.g.: 10 + +5 => [10, +, +5]
.reduce(function (a, b) {
if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {
a[a.length - 1] = b;
mergeWithPrevious = true;
return a;
} else if (mergeWithPrevious) {
a[a.length - 1] += b;
mergeWithPrevious = false;
return a;
} else {
return a.concat(b);
}
}, []) // Here we convert the string values into number values (in px)
.map(function (str) {
return toValue(str, measurement, popperOffsets, referenceOffsets);
});
}); // Loop trough the offsets arrays and execute the operations
ops.forEach(function (op, index) {
op.forEach(function (frag, index2) {
if (isNumeric(frag)) {
offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);
}
});
});
return offsets;
}
/**
* @function
* @memberof Modifiers
* @argument {Object} data - The data object generated by update method
* @argument {Object} options - Modifiers configuration and options
* @argument {Number|String} options.offset=0
* The offset value as described in the modifier description
* @returns {Object} The data object, properly modified
*/
function offset(data, _ref) {
var offset = _ref.offset;
var placement = data.placement,
_data$offsets = data.offsets,
popper = _data$offsets.popper,
reference = _data$offsets.reference;
var basePlacement = placement.split('-')[0];
var offsets = void 0;
if (isNumeric(+offset)) {
offsets = [+offset, 0];
} else {
offsets = parseOffset(offset, popper, reference, basePlacement);
}
if (basePlacement === 'left') {
popper.top += offsets[0];
popper.left -= offsets[1];
} else if (basePlacement === 'right') {
popper.top += offsets[0];
popper.left += offsets[1];
} else if (basePlacement === 'top') {
popper.left += offsets[0];
popper.top -= offsets[1];
} else if (basePlacement === 'bottom') {
popper.left += offsets[0];
popper.top += offsets[1];
}
data.popper = popper;
return data;
}
/**
* @function
* @memberof Modifiers
* @argument {Object} data - The data object generated by `update` method
* @argument {Object} options - Modifiers configuration and options
* @returns {Object} The data object, properly modified
*/
function preventOverflow(data, options) {
var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper); // If offsetParent is the reference element, we really want to
// go one step up and use the next offsetParent as reference to
// avoid to make this modifier completely useless and look like broken
if (data.instance.reference === boundariesElement) {
boundariesElement = getOffsetParent(boundariesElement);
} // NOTE: DOM access here
// resets the popper's position so that the document size can be calculated excluding
// the size of the popper element itself
var transformProp = getSupportedPropertyName('transform');
var popperStyles = data.instance.popper.style; // assignment to help minification
var top = popperStyles.top,
left = popperStyles.left,
transform = popperStyles[transformProp];
popperStyles.top = '';
popperStyles.left = '';
popperStyles[transformProp] = '';
var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed); // NOTE: DOM access here
// restores the original style properties after the offsets have been computed
popperStyles.top = top;
popperStyles.left = left;
popperStyles[transformProp] = transform;
options.boundaries = boundaries;
var order = options.priority;
var popper = data.offsets.popper;
var check = {
primary: function primary(placement) {
var value = popper[placement];
if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {
value = Math.max(popper[placement], boundaries[placement]);
}
return defineProperty({}, placement, value);
},
secondary: function secondary(placement) {
var mainSide = placement === 'right' ? 'left' : 'top';
var value = popper[mainSide];
if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {
value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));
}
return defineProperty({}, mainSide, value);
}
};
order.forEach(function (placement) {
var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
popper = _extends({}, popper, check[side](placement));
});
data.offsets.popper = popper;
return data;
}
/**
* @function
* @memberof Modifiers
* @argument {Object} data - The data object generated by `update` method
* @argument {Object} options - Modifiers configuration and options
* @returns {Object} The data object, properly modified
*/
function shift(data) {
var placement = data.placement;
var basePlacement = placement.split('-')[0];
var shiftvariation = placement.split('-')[1]; // if shift shiftvariation is specified, run the modifier
if (shiftvariation) {
var _data$offsets = data.offsets,
reference = _data$offsets.reference,
popper = _data$offsets.popper;
var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;
var side = isVertical ? 'left' : 'top';
var measurement = isVertical ? 'width' : 'height';
var shiftOffsets = {
start: defineProperty({}, side, reference[side]),
end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])
};
data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);
}
return data;
}
/**
* @function
* @memberof Modifiers
* @argument {Object} data - The data object generated by update method
* @argument {Object} options - Modifiers configuration and options
* @returns {Object} The data object, properly modified
*/
function hide(data) {
if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {
return data;
}
var refRect = data.offsets.reference;
var bound = find(data.instance.modifiers, function (modifier) {
return modifier.name === 'preventOverflow';
}).boundaries;
if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
// Avoid unnecessary DOM access if visibility hasn't changed
if (data.hide === true) {
return data;
}
data.hide = true;
data.attributes['x-out-of-boundaries'] = '';
} else {
// Avoid unnecessary DOM access if visibility hasn't changed
if (data.hide === false) {
return data;
}
data.hide = false;
data.attributes['x-out-of-boundaries'] = false;
}
return data;
}
/**
* @function
* @memberof Modifiers
* @argument {Object} data - The data object generated by `update` method
* @argument {Object} options - Modifiers configuration and options
* @returns {Object} The data object, properly modified
*/
function inner(data) {
var placement = data.placement;
var basePlacement = placement.split('-')[0];
var _data$offsets = data.offsets,
popper = _data$offsets.popper,
reference = _data$offsets.reference;
var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;
var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;
popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);
data.placement = getOppositePlacement(placement);
data.offsets.popper = getClientRect(popper);
return data;
}
/**
* Modifier function, each modifier can have a function of this type assigned
* to its `fn` property.<br />
* These functions will be called on each update, this means that you must
* make sure they are performant enough to avoid performance bottlenecks.
*
* @function ModifierFn
* @argument {dataObject} data - The data object generated by `update` method
* @argument {Object} options - Modifiers configuration and options
* @returns {dataObject} The data object, properly modified
*/
/**
* Modifiers are plugins used to alter the behavior of your poppers.<br />
* Popper.js uses a set of 9 modifiers to provide all the basic functionalities
* needed by the library.
*
* Usually you don't want to override the `order`, `fn` and `onLoad` props.
* All the other properties are configurations that could be tweaked.
* @namespace modifiers
*/
var modifiers = {
/**
* Modifier used to shift the popper on the start or end of its reference
* element.<br />
* It will read the variation of the `placement` property.<br />
* It can be one either `-end` or `-start`.
* @memberof modifiers
* @inner
*/
shift: {
/** @prop {number} order=100 - Index used to define the order of execution */
order: 100,
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
enabled: true,
/** @prop {ModifierFn} */
fn: shift
},
/**
* The `offset` modifier can shift your popper on both its axis.
*
* It accepts the following units:
* - `px` or unit-less, interpreted as pixels
* - `%` or `%r`, percentage relative to the length of the reference element
* - `%p`, percentage relative to the length of the popper element
* - `vw`, CSS viewport width unit
* - `vh`, CSS viewport height unit
*
* For length is intended the main axis relative to the placement of the popper.<br />
* This means that if the placement is `top` or `bottom`, the length will be the
* `width`. In case of `left` or `right`, it will be the `height`.
*
* You can provide a single value (as `Number` or `String`), or a pair of values
* as `String` divided by a comma or one (or more) white spaces.<br />
* The latter is a deprecated method because it leads to confusion and will be
* removed in v2.<br />
* Additionally, it accepts additions and subtractions between different units.
* Note that multiplications and divisions aren't supported.
*
* Valid examples are:
* ```
* 10
* '10%'
* '10, 10'
* '10%, 10'
* '10 + 10%'
* '10 - 5vh + 3%'
* '-10px + 5vh, 5px - 6%'
* ```
* > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap
* > with their reference element, unfortunately, you will have to disable the `flip` modifier.
* > You can read more on this at this [issue](https://github.com/FezVrasta/popper.js/issues/373).
*
* @memberof modifiers
* @inner
*/
offset: {
/** @prop {number} order=200 - Index used to define the order of execution */
order: 200,
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
enabled: true,
/** @prop {ModifierFn} */
fn: offset,
/** @prop {Number|String} offset=0
* The offset value as described in the modifier description
*/
offset: 0
},
/**
* Modifier used to prevent the popper from being positioned outside the boundary.
*
* A scenario exists where the reference itself is not within the boundaries.<br />
* We can say it has "escaped the boundaries" — or just "escaped".<br />
* In this case we need to decide whether the popper should either:
*
* - detach from the reference and remain "trapped" in the boundaries, or
* - if it should ignore the boundary and "escape with its reference"
*
* When `escapeWithReference` is set to`true` and reference is completely
* outside its boundaries, the popper will overflow (or completely leave)
* the boundaries in order to remain attached to the edge of the reference.
*
* @memberof modifiers
* @inner
*/
preventOverflow: {
/** @prop {number} order=300 - Index used to define the order of execution */
order: 300,
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
enabled: true,
/** @prop {ModifierFn} */
fn: preventOverflow,
/**
* @prop {Array} [priority=['left','right','top','bottom']]
* Popper will try to prevent overflow following these priorities by default,
* then, it could overflow on the left and on top of the `boundariesElement`
*/
priority: ['left', 'right', 'top', 'bottom'],
/**
* @prop {number} padding=5
* Amount of pixel used to define a minimum distance between the boundaries
* and the popper. This makes sure the popper always has a little padding
* between the edges of its container
*/
padding: 5,
/**
* @prop {String|HTMLElement} boundariesElement='scrollParent'
* Boundaries used by the modifier. Can be `scrollParent`, `window`,
* `viewport` or any DOM element.
*/
boundariesElement: 'scrollParent'
},
/**
* Modifier used to make sure the reference and its popper stay near each other
* without leaving any gap between the two. Especially useful when the arrow is
* enabled and you want to ensure that it points to its reference element.
* It cares only about the first axis. You can still have poppers with margin
* between the popper and its reference element.
* @memberof modifiers
* @inner
*/
keepTogether: {
/** @prop {number} order=400 - Index used to define the order of execution */
order: 400,
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
enabled: true,
/** @prop {ModifierFn} */
fn: keepTogether
},
/**
* This modifier is used to move the `arrowElement` of the popper to make
* sure it is positioned between the reference element and its popper element.
* It will read the outer size of the `arrowElement` node to detect how many
* pixels of conjunction are needed.
*
* It has no effect if no `arrowElement` is provided.
* @memberof modifiers
* @inner
*/
arrow: {
/** @prop {number} order=500 - Index used to define the order of execution */
order: 500,
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
enabled: true,
/** @prop {ModifierFn} */
fn: arrow,
/** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */
element: '[x-arrow]'
},
/**
* Modifier used to flip the popper's placement when it starts to overlap its
* reference element.
*
* Requires the `preventOverflow` modifier before it in order to work.
*
* **NOTE:** this modifier will interrupt the current update cycle and will
* restart it if it detects the need to flip the placement.
* @memberof modifiers
* @inner
*/
flip: {
/** @prop {number} order=600 - Index used to define the order of execution */
order: 600,
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
enabled: true,
/** @prop {ModifierFn} */
fn: flip,
/**
* @prop {String|Array} behavior='flip'
* The behavior used to change the popper's placement. It can be one of
* `flip`, `clockwise`, `counterclockwise` or an array with a list of valid
* placements (with optional variations)
*/
behavior: 'flip',
/**
* @prop {number} padding=5
* The popper will flip if it hits the edges of the `boundariesElement`
*/
padding: 5,
/**
* @prop {String|HTMLElement} boundariesElement='viewport'
* The element which will define the boundaries of the popper position.
* The popper will never be placed outside of the defined boundaries
* (except if `keepTogether` is enabled)
*/
boundariesElement: 'viewport',
/**
* @prop {Boolean} flipVariations=false
* The popper will switch placement variation between `-start` and `-end` when
* the reference element overlaps its boundaries.
*
* The original placement should have a set variation.
*/
flipVariations: false,
/**
* @prop {Boolean} flipVariationsByContent=false
* The popper will switch placement variation between `-start` and `-end` when
* the popper element overlaps its reference boundaries.
*
* The original placement should have a set variation.
*/
flipVariationsByContent: false
},
/**
* Modifier used to make the popper flow toward the inner of the reference element.
* By default, when this modifier is disabled, the popper will be placed outside
* the reference element.
* @memberof modifiers
* @inner
*/
inner: {
/** @prop {number} order=700 - Index used to define the order of execution */
order: 700,
/** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */
enabled: false,
/** @prop {ModifierFn} */
fn: inner
},
/**
* Modifier used to hide the popper when its reference element is outside of the
* popper boundaries. It will set a `x-out-of-boundaries` attribute which can
* be used to hide with a CSS selector the popper when its reference is
* out of boundaries.
*
* Requires the `preventOverflow` modifier before it in order to work.
* @memberof modifiers
* @inner
*/
hide: {
/** @prop {number} order=800 - Index used to define the order of execution */
order: 800,
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
enabled: true,
/** @prop {ModifierFn} */
fn: hide
},
/**
* Computes the style that will be applied to the popper element to gets
* properly positioned.
*
* Note that this modifier will not touch the DOM, it just prepares the styles
* so that `applyStyle` modifier can apply it. This separation is useful
* in case you need to replace `applyStyle` with a custom implementation.
*
* This modifier has `850` as `order` value to maintain backward compatibility
* with previous versions of Popper.js. Expect the modifiers ordering method
* to change in future major versions of the library.
*
* @memberof modifiers
* @inner
*/
computeStyle: {
/** @prop {number} order=850 - Index used to define the order of execution */
order: 850,
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
enabled: true,
/** @prop {ModifierFn} */
fn: computeStyle,
/**
* @prop {Boolean} gpuAcceleration=true
* If true, it uses the CSS 3D transformation to position the popper.
* Otherwise, it will use the `top` and `left` properties
*/
gpuAcceleration: true,
/**
* @prop {string} [x='bottom']
* Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.
* Change this if your popper should grow in a direction different from `bottom`
*/
x: 'bottom',
/**
* @prop {string} [x='left']
* Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.
* Change this if your popper should grow in a direction different from `right`
*/
y: 'right'
},
/**
* Applies the computed styles to the popper element.
*
* All the DOM manipulations are limited to this modifier. This is useful in case
* you want to integrate Popper.js inside a framework or view library and you
* want to delegate all the DOM manipulations to it.
*
* Note that if you disable this modifier, you must make sure the popper element
* has its position set to `absolute` before Popper.js can do its work!
*
* Just disable this modifier and define your own to achieve the desired effect.
*
* @memberof modifiers
* @inner
*/
applyStyle: {
/** @prop {number} order=900 - Index used to define the order of execution */
order: 900,
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
enabled: true,
/** @prop {ModifierFn} */
fn: applyStyle,
/** @prop {Function} */
onLoad: applyStyleOnLoad,
/**
* @deprecated since version 1.10.0, the property moved to `computeStyle` modifier
* @prop {Boolean} gpuAcceleration=true
* If true, it uses the CSS 3D transformation to position the popper.
* Otherwise, it will use the `top` and `left` properties
*/
gpuAcceleration: undefined
}
};
/**
* The `dataObject` is an object containing all the information used by Popper.js.
* This object is passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
* @name dataObject
* @property {Object} data.instance The Popper.js instance
* @property {String} data.placement Placement applied to popper
* @property {String} data.originalPlacement Placement originally defined on init
* @property {Boolean} data.flipped True if popper has been flipped by flip modifier
* @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper
* @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
* @property {Object} data.styles Any CSS property defined here will be applied to the popper. It expects the JavaScript nomenclature (eg. `marginBottom`)
* @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow. It expects the JavaScript nomenclature (eg. `marginBottom`)
* @property {Object} data.boundaries Offsets of the popper boundaries
* @property {Object} data.offsets The measurements of popper, reference and arrow elements
* @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
* @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
* @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0
*/
/**
* Default options provided to Popper.js constructor.<br />
* These can be overridden using the `options` argument of Popper.js.<br />
* To override an option, simply pass an object with the same
* structure of the `options` object, as the 3rd argument. For example:
* ```
* new Popper(ref, pop, {
* modifiers: {
* preventOverflow: { enabled: false }
* }
* })
* ```
* @type {Object}
* @static
* @memberof Popper
*/
var Defaults = {
/**
* Popper's placement.
* @prop {Popper.placements} placement='bottom'
*/
placement: 'bottom',
/**
* Set this to true if you want popper to position it self in 'fixed' mode
* @prop {Boolean} positionFixed=false
*/
positionFixed: false,
/**
* Whether events (resize, scroll) are initially enabled.
* @prop {Boolean} eventsEnabled=true
*/
eventsEnabled: true,
/**
* Set to true if you want to automatically remove the popper when
* you call the `destroy` method.
* @prop {Boolean} removeOnDestroy=false
*/
removeOnDestroy: false,
/**
* Callback called when the popper is created.<br />
* By default, it is set to no-op.<br />
* Access Popper.js instance with `data.instance`.
* @prop {onCreate}
*/
onCreate: function onCreate() {},
/**
* Callback called when the popper is updated. This callback is not called
* on the initialization/creation of the popper, but only on subsequent
* updates.<br />
* By default, it is set to no-op.<br />
* Access Popper.js instance with `data.instance`.
* @prop {onUpdate}
*/
onUpdate: function onUpdate() {},
/**
* List of modifiers used to modify the offsets before they are applied to the popper.
* They provide most of the functionalities of Popper.js.
* @prop {modifiers}
*/
modifiers: modifiers
};
/**
* @callback onCreate
* @param {dataObject} data
*/
/**
* @callback onUpdate
* @param {dataObject} data
*/
// Utils
// Methods
var Popper = function () {
/**
* Creates a new Popper.js instance.
* @class Popper
* @param {Element|referenceObject} reference - The reference element used to position the popper
* @param {Element} popper - The HTML / XML element used as the popper
* @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)
* @return {Object} instance - The generated Popper.js instance
*/
function Popper(reference, popper) {
var _this = this;
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
classCallCheck(this, Popper);
this.scheduleUpdate = function () {
return requestAnimationFrame(_this.update);
}; // make update() debounced, so that it only runs at most once-per-tick
this.update = debounce(this.update.bind(this)); // with {} we create a new object with the options inside it
this.options = _extends({}, Popper.Defaults, options); // init state
this.state = {
isDestroyed: false,
isCreated: false,
scrollParents: []
}; // get reference and popper elements (allow jQuery wrappers)
this.reference = reference && reference.jquery ? reference[0] : reference;
this.popper = popper && popper.jquery ? popper[0] : popper; // Deep merge modifiers options
this.options.modifiers = {};
Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {
_this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});
}); // Refactoring modifiers' list (Object => Array)
this.modifiers = Object.keys(this.options.modifiers).map(function (name) {
return _extends({
name: name
}, _this.options.modifiers[name]);
}) // sort the modifiers by order
.sort(function (a, b) {
return a.order - b.order;
}); // modifiers have the ability to execute arbitrary code when Popper.js get inited
// such code is executed in the same order of its modifier
// they could add new properties to their options configuration
// BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!
this.modifiers.forEach(function (modifierOptions) {
if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {
modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);
}
}); // fire the first update to position the popper in the right place
this.update();
var eventsEnabled = this.options.eventsEnabled;
if (eventsEnabled) {
// setup event listeners, they will take care of update the position in specific situations
this.enableEventListeners();
}
this.state.eventsEnabled = eventsEnabled;
} // We can't use class properties because they don't get listed in the
// class prototype and break stuff like Sinon stubs
createClass(Popper, [{
key: 'update',
value: function update$$1() {
return update.call(this);
}
}, {
key: 'destroy',
value: function destroy$$1() {
return destroy.call(this);
}
}, {
key: 'enableEventListeners',
value: function enableEventListeners$$1() {
return enableEventListeners.call(this);
}
}, {
key: 'disableEventListeners',
value: function disableEventListeners$$1() {
return disableEventListeners.call(this);
}
/**
* Schedules an update. It will run on the next UI update available.
* @method scheduleUpdate
* @memberof Popper
*/
/**
* Collection of utilities useful when writing custom modifiers.
* Starting from version 1.7, this method is available only if you
* include `popper-utils.js` before `popper.js`.
*
* **DEPRECATION**: This way to access PopperUtils is deprecated
* and will be removed in v2! Use the PopperUtils module directly instead.
* Due to the high instability of the methods contained in Utils, we can't
* guarantee them to follow semver. Use them at your own risk!
* @static
* @private
* @type {Object}
* @deprecated since version 1.8
* @member Utils
* @memberof Popper
*/
}]);
return Popper;
}();
/**
* The `referenceObject` is an object that provides an interface compatible with Popper.js
* and lets you use it as replacement of a real DOM node.<br />
* You can use this method to position a popper relatively to a set of coordinates
* in case you don't have a DOM node to use as reference.
*
* ```
* new Popper(referenceObject, popperNode);
* ```
*
* NB: This feature isn't supported in Internet Explorer 10.
* @name referenceObject
* @property {Function} data.getBoundingClientRect
* A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.
* @property {number} data.clientWidth
* An ES6 getter that will return the width of the virtual reference element.
* @property {number} data.clientHeight
* An ES6 getter that will return the height of the virtual reference element.
*/
Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;
Popper.placements = placements;
Popper.Defaults = Defaults;
function _typeof$m(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$m = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$m = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$m(obj);
}
function _classCallCheck$k(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$k(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$k(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$k(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$k(Constructor, staticProps);
return Constructor;
}
function _inherits$i(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$i(subClass, superClass);
}
function _setPrototypeOf$i(o, p) {
_setPrototypeOf$i = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$i(o, p);
}
function _createSuper$i(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$i();
return function _createSuperInternal() {
var Super = _getPrototypeOf$i(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$i(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$i(this, result);
};
}
function _possibleConstructorReturn$i(self, call) {
if (call && (_typeof$m(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$i(self);
}
function _assertThisInitialized$i(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$i() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$i(o) {
_getPrototypeOf$i = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$i(o);
}
/**
@class Tooltip
@extends BaseClass
@desc Creates HTML tooltips in the body of a webpage.
*/
var Tooltip = /*#__PURE__*/function (_BaseClass) {
_inherits$i(Tooltip, _BaseClass);
var _super = _createSuper$i(Tooltip);
/**
@memberof Tooltip
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function Tooltip() {
var _this;
_classCallCheck$k(this, Tooltip);
_this = _super.call(this);
_this._arrow = accessor("arrow", "");
_this._arrowStyle = {
"content": "",
"background": "inherit",
"border": "inherit",
"border-width": "0 1px 1px 0",
"height": "10px",
"position": "absolute",
"transform": "rotate(45deg)",
"width": "10px",
"z-index": "-1"
};
_this._background = constant$1("rgba(255, 255, 255, 1)");
_this._body = accessor("body", "");
_this._bodyStyle = {
"font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
"font-size": "12px",
"font-weight": "400",
"z-index": "1"
};
_this._border = constant$1("1px solid rgba(0, 0, 0, 0.1)");
_this._borderRadius = constant$1("2px");
_this._className = "d3plus-tooltip";
_this._data = [];
_this._footer = accessor("footer", "");
_this._footerStyle = {
"font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
"font-size": "12px",
"font-weight": "400",
"z-index": "1"
};
_this._height = constant$1("auto");
_this._id = function (d, i) {
return "".concat(i);
};
_this._offset = constant$1(5);
_this._padding = constant$1("5px");
_this._pointerEvents = constant$1("auto");
_this._popperClasses = {};
_this._position = function (d) {
return [d.x, d.y];
};
_this._prefix = prefix$1();
_this._tableStyle = {
"border-collapse": "collapse",
"border-spacing": "0",
"width": "100%"
};
_this._tbody = [];
_this._tbodyStyle = {
"font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
"font-size": "12px",
"text-align": "center"
};
_this._thead = [];
_this._theadStyle = {
"font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
"font-size": "12px",
"font-weight": "600",
"text-align": "center"
};
_this._title = accessor("title", "");
_this._titleStyle = {
"font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
"font-size": "14px",
"font-weight": "600"
};
_this._trStyle = {
"border-top": "1px solid rgba(0, 0, 0, 0.1)"
};
_this._tdStyle = {};
_this._width = constant$1("auto");
return _this;
}
/**
The inner return object and draw function that gets assigned the public methods.
@private
*/
_createClass$k(Tooltip, [{
key: "render",
value: function render(callback) {
var _this2 = this;
var that = this;
var tooltips = _select("body").selectAll(".".concat(this._className)).data(this._data, this._id);
var enter = tooltips.enter().append("div").attr("class", this._className);
var update = tooltips.merge(enter);
/**
Creates DIV elements with a unique class and styles.
@private
*/
function divElement(cat) {
enter.append("div").attr("class", "d3plus-tooltip-".concat(cat)).attr("id", function (d, i) {
return "d3plus-tooltip-".concat(cat, "-").concat(d ? that._id(d, i) : "");
});
var div = update.select(".d3plus-tooltip-".concat(cat)).html(function (d, i) {
return that["_".concat(cat)](d, i);
}).style("display", function (d, i) {
var val = that["_".concat(cat)](d, i);
var visible = val !== false && val !== undefined && val !== null;
return visible ? "block" : "none";
});
stylize(div, that["_".concat(cat, "Style")]);
}
/**
Fetches table contents given functions or values.
@private
*/
function cellContent(d) {
if (typeof d === "function") {
var datum = _select(this.parentNode.parentNode).datum();
return d(datum, that._data.indexOf(datum));
} else return d;
}
/**
Sets styles for both enter and update.
@private
*/
function boxStyles(box) {
box.style("background", that._background).style("".concat(that._prefix, "border-radius"), that._borderRadius).style("pointer-events", that._pointerEvents).style("padding", that._padding).style("width", that._width).style("height", that._height).style("border", function (d, i) {
var b = _select(this).style("border");
return b !== "0px none rgb(0, 0, 0)" ? b : that._border(d, i);
});
}
divElement("title");
divElement("body");
var tableEnter = enter.append("table").attr("class", "d3plus-tooltip-table");
var table = update.select(".d3plus-tooltip-table");
stylize(table, this._tableStyle);
tableEnter.append("thead").attr("class", "d3plus-tooltip-thead");
var tableHead = update.select(".d3plus-tooltip-thead");
stylize(tableHead, this._theadStyle);
var th = tableHead.selectAll("th").data(this._thead);
th.enter().append("th").merge(th).html(cellContent);
th.exit().remove();
tableEnter.append("tbody").attr("class", "d3plus-tooltip-tbody");
var tableBody = update.select(".d3plus-tooltip-tbody");
stylize(tableBody, this._tbodyStyle);
var tr = tableBody.selectAll("tr").data(this._tbody);
var trEnter = tr.enter().append("tr");
tr.exit().remove();
var trUpdate = tr.merge(trEnter);
stylize(trUpdate, this._trStyle);
var td = trUpdate.selectAll("td").data(function (d) {
return d;
});
td.enter().append("td").merge(td).html(cellContent);
stylize(td, this._tdStyle);
divElement("footer");
divElement("arrow");
enter.attr("id", function (d, i) {
return "d3plus-tooltip-".concat(d ? _this2._id(d, i) : "");
}).call(boxStyles).each(function (d, i) {
var id = that._id(d, i);
var tooltip = document.getElementById("d3plus-tooltip-".concat(id));
var arrow = document.getElementById("d3plus-tooltip-arrow-".concat(id));
var arrowHeight = arrow.offsetHeight;
var arrowDistance = arrow.getBoundingClientRect().height / 2;
arrow.style.bottom = "-".concat(arrowHeight / 2, "px");
var position = that._position(d, i);
var referenceObject = Array.isArray(position) ? {
clientWidth: 0,
clientHeight: 0,
getBoundingClientRect: function getBoundingClientRect() {
return {
top: position[1],
right: position[0],
bottom: position[1],
left: position[0],
width: 0,
height: 0
};
}
} : position;
_this2._popperClasses[id] = new Popper(referenceObject, tooltip, {
placement: "top",
placements: ["top", "bottom", "left", "right"],
modifiers: {
arrow: {
element: arrow
},
offset: {
offset: "0,".concat(that._offset(d, i) + arrowDistance)
},
preventOverflow: {
boundariesElement: "scrollParent"
},
flip: {
behavior: "flip",
boundariesElement: "viewport"
}
},
onUpdate: function onUpdate(_ref) {
var arrowElement = _ref.arrowElement,
flipped = _ref.flipped;
if (flipped) {
arrowElement.style.transform = "rotate(225deg)";
arrowElement.style.top = "-".concat(arrowHeight / 2, "px");
} else {
arrowElement.style.transform = "rotate(45deg)";
arrowElement.style.bottom = "-".concat(arrowHeight / 2, "px");
}
},
removeOnDestroy: true
});
});
update.each(function (d, i) {
var id = that._id(d, i);
var position = that._position(d, i);
var instance = _this2._popperClasses[id];
if (instance) {
var referenceObject = Array.isArray(position) ? {
clientWidth: 0,
clientHeight: 0,
getBoundingClientRect: function getBoundingClientRect() {
return {
top: position[1],
right: position[0],
bottom: position[1],
left: position[0],
width: 0,
height: 0
};
}
} : position;
instance.reference = referenceObject;
instance.scheduleUpdate();
}
}).call(boxStyles);
tooltips.exit().each(function (d, i) {
var id = that._id(d, i);
var instance = _this2._popperClasses[id];
if (instance) {
instance.destroy();
delete _this2._popperClasses[id];
}
}).remove();
if (callback) setTimeout(callback, 100);
return this;
}
/**
@memberof Tooltip
@desc Sets the inner HTML content of the arrow element, which by default is empty.
@param {Function|String} [*value*]
@example <caption>default accessor</caption>
function value(d) {
return d.arrow || "";
}
*/
}, {
key: "arrow",
value: function arrow(_) {
return arguments.length ? (this._arrow = typeof _ === "function" ? _ : constant$1(_), this) : this._arrow;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the arrow styles to the specified values and returns this generator. If *value* is not specified, returns the current arrow styles.
@param {Object} [*value*]
@example <caption>default styles</caption>
{
"content": "",
"border-width": "10px",
"border-style": "solid",
"border-color": "rgba(255, 255, 255, 0.75) transparent transparent transparent",
"position": "absolute"
}
*/
}, {
key: "arrowStyle",
value: function arrowStyle(_) {
return arguments.length ? (this._arrowStyle = Object.assign(this._arrowStyle, _), this) : this._arrowStyle;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the background accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current background accessor.
@param {Function|String} [*value* = "rgba(255, 255, 255, 0.75)"]
*/
}, {
key: "background",
value: function background(_) {
return arguments.length ? (this._background = typeof _ === "function" ? _ : constant$1(_), this) : this._background;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the body accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current body accessor.
@param {Function|String} [*value*]
@example <caption>default accessor</caption>
function value(d) {
return d.body || "";
}
*/
}, {
key: "body",
value: function body(_) {
return arguments.length ? (this._body = typeof _ === "function" ? _ : constant$1(_), this) : this._body;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the body styles to the specified values and returns this generator. If *value* is not specified, returns the current body styles.
@param {Object} [*value*]
@example <caption>default styles</caption>
{
"font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
"font-size": "12px",
"font-weight": "400"
}
*/
}, {
key: "bodyStyle",
value: function bodyStyle(_) {
return arguments.length ? (this._bodyStyle = Object.assign(this._bodyStyle, _), this) : this._bodyStyle;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the border accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current border accessor.
@param {Function|String} [*value* = "1px solid rgba(0, 0, 0, 0.1)"]
*/
}, {
key: "border",
value: function border(_) {
return arguments.length ? (this._border = typeof _ === "function" ? _ : constant$1(_), this) : this._border;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the border-radius accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current border-radius accessor.
@param {Function|String} [*value* = "2px"]
*/
}, {
key: "borderRadius",
value: function borderRadius(_) {
return arguments.length ? (this._borderRadius = typeof _ === "function" ? _ : constant$1(_), this) : this._borderRadius;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the class name to the specified string and returns this generator. If *value* is not specified, returns the current class name.
@param {String} [*value* = "d3plus-tooltip"]
*/
}, {
key: "className",
value: function className(_) {
return arguments.length ? (this._className = _, this) : this._className;
}
/**
@memberof Tooltip
@desc If *data* is specified, sets the data array to the specified array and returns this generator. If *data* is not specified, returns the current data array.
@param {Array} [*data* = []]
*/
}, {
key: "data",
value: function data(_) {
return arguments.length ? (this._data = _, this) : this._data;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the footer accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current footer accessor.
@param {Function|String} [*value*]
@example <caption>default accessor</caption>
function value(d) {
return d.footer || "";
}
*/
}, {
key: "footer",
value: function footer(_) {
return arguments.length ? (this._footer = typeof _ === "function" ? _ : constant$1(_), this) : this._footer;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the footer styles to the specified values and returns this generator. If *value* is not specified, returns the current footer styles.
@param {Object} [*value*]
@example <caption>default styles</caption>
{
"font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
"font-size": "12px",
"font-weight": "400"
}
*/
}, {
key: "footerStyle",
value: function footerStyle(_) {
return arguments.length ? (this._footerStyle = Object.assign(this._footerStyle, _), this) : this._footerStyle;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the height accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current height accessor.
@param {Function|String} [*value* = "auto"]
*/
}, {
key: "height",
value: function height(_) {
return arguments.length ? (this._height = typeof _ === "function" ? _ : constant$1(_), this) : this._height;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the id accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current id accessor.
@param {Function|String} [*value*]
@example <caption>default accessor</caption>
function value(d, i) {
return d.id || "" + i;
}
*/
}, {
key: "id",
value: function id(_) {
return arguments.length ? (this._id = typeof _ === "function" ? _ : constant$1(_), this) : this._id;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the offset accessor to the specified function or number and returns this generator. If *value* is not specified, returns the current offset accessor.
@param {Function|Number} [*value* = 10]
*/
}, {
key: "offset",
value: function offset(_) {
return arguments.length ? (this._offset = typeof _ === "function" ? _ : constant$1(_), this) : this._offset;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the padding accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current padding accessor.
@param {Function|String} [*value* = "5px"]
*/
}, {
key: "padding",
value: function padding(_) {
return arguments.length ? (this._padding = typeof _ === "function" ? _ : constant$1(_), this) : this._padding;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the pointer-events accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current pointer-events accessor.
@param {Function|String} [*value* = "auto"]
*/
}, {
key: "pointerEvents",
value: function pointerEvents(_) {
return arguments.length ? (this._pointerEvents = typeof _ === "function" ? _ : constant$1(_), this) : this._pointerEvents;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the position accessor to the specified function or array and returns this generator. If *value* is not specified, returns the current position accessor. If *value* is an HTMLElement, anchors the Tooltip to that HTMLElement. If *value* is a selection string, anchors the Tooltip to the HTMLElement selected by that string. Otherwise, coordinate points must be in reference to the client viewport, not the overall page.
@param {Function|Array|HTMLElement|String} [*value*]
@example <caption>default accessor</caption>
function value(d) {
return [d.x, d.y];
}
*/
}, {
key: "position",
value: function position(_) {
return arguments.length ? (this._position = typeof _ === "string" ? constant$1(_select(_).node() || [0, 0]) : typeof _ === "function" ? _ : constant$1(_), this) : this._position;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the table styles to the specified values and returns this generator. If *value* is not specified, returns the current table styles.
@param {Object} [*value*]
@example <caption>default styles</caption>
{
"border-collapse": "collapse",
"border-spacing": "0",
"width": "100%"
}
*/
}, {
key: "tableStyle",
value: function tableStyle(_) {
return arguments.length ? (this._tableStyle = Object.assign(this._tableStyle, _), this) : this._tableStyle;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the contents of the table body to the specified array of functions or strings and returns this generator. If *value* is not specified, returns the current table body data.
@param {Array} [*value* = []]
*/
}, {
key: "tbody",
value: function tbody(_) {
return arguments.length ? (this._tbody = _, this) : this._tbody;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the table body styles to the specified values and returns this generator. If *value* is not specified, returns the current table body styles.
@param {Object} [*value*]
@example <caption>default styles</caption>
{
"font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
"font-size": "12px",
"font-weight": "600",
"text-align": "center"
}
*/
}, {
key: "tbodyStyle",
value: function tbodyStyle(_) {
return arguments.length ? (this._tbodyStyle = Object.assign(this._tbodyStyle, _), this) : this._tbodyStyle;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the contents of the table head to the specified array of functions or strings and returns this generator. If *value* is not specified, returns the current table head data.
@param {Array} [*value* = []]
*/
}, {
key: "thead",
value: function thead(_) {
return arguments.length ? (this._thead = _, this) : this._thead;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the table head styles to the specified values and returns this generator. If *value* is not specified, returns the current table head styles.
@param {Object} [*value*]
@example <caption>default styles</caption>
{
"font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
"font-size": "12px",
"font-weight": "600",
"text-align": "center"
}
*/
}, {
key: "theadStyle",
value: function theadStyle(_) {
return arguments.length ? (this._theadStyle = Object.assign(this._theadStyle, _), this) : this._theadStyle;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the title accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current title accessor.
@param {Function|String} [*value*]
@example <caption>default accessor</caption>
function value(d) {
return d.title || "";
}
*/
}, {
key: "title",
value: function title(_) {
return arguments.length ? (this._title = typeof _ === "function" ? _ : constant$1(_), this) : this._title;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the title styles to the specified values and returns this generator. If *value* is not specified, returns the current title styles.
@param {Object} [*value*]
@example <caption>default styles</caption>
{
"font-family": "'Roboto', 'Helvetica Neue', 'HelveticaNeue', 'Helvetica', 'Arial', sans-serif",
"font-size": "14px",
"font-weight": "600",
"padding-bottom": "5px"
}
*/
}, {
key: "titleStyle",
value: function titleStyle(_) {
return arguments.length ? (this._titleStyle = Object.assign(this._titleStyle, _), this) : this._titleStyle;
}
/**
@memberof Tooltip
@desc An object with CSS keys and values to be applied to all <tr> elements inside of each <tbody>.
@param {Object} [*value*]
@example <caption>default styles</caption>
{
"border-top": "1px solid rgba(0, 0, 0, 0.1)"
}
*/
}, {
key: "trStyle",
value: function trStyle(_) {
return arguments.length ? (this._trStyle = Object.assign(this._trStyle, _), this) : this._trStyle;
}
/**
@memberof Tooltip
@desc An object with CSS keys and values to be applied to all <td> elements inside of each <tr>.
@param {Object} [*value*]
*/
}, {
key: "tdStyle",
value: function tdStyle(_) {
return arguments.length ? (this._tdStyle = Object.assign(this._tdStyle, _), this) : this._tdStyle;
}
/**
@memberof Tooltip
@desc If *value* is specified, sets the width accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current width accessor.
@param {Function|String} [*value* = "auto"]
*/
}, {
key: "width",
value: function width(_) {
return arguments.length ? (this._width = typeof _ === "function" ? _ : constant$1(_), this) : this._width;
}
}]);
return Tooltip;
}(BaseClass);
function _classCallCheck$l(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$l(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$l(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$l(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$l(Constructor, staticProps);
return Constructor;
}
/**
@class Message
@desc Displays a message using plain HTML.
@private
*/
var Message = /*#__PURE__*/function () {
/**
@memberof Message
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function Message() {
_classCallCheck$l(this, Message);
this._isVisible = false;
}
/**
@memberof Message
@desc Removes the message from the page.
@chainable
*/
_createClass$l(Message, [{
key: "exit",
value: function exit(elem, duration) {
elem.transition().duration(duration).style("opacity", 0).transition().remove();
this._isVisible = false;
}
/**
@memberof Message
@desc Removes the message from the page.
@chainable
*/
}, {
key: "hide",
value: function hide() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
_ref$duration = _ref.duration,
duration = _ref$duration === void 0 ? 600 : _ref$duration,
callback = _ref.callback;
this.mask.call(this.exit.bind(this), duration);
this.elem.call(this.exit.bind(this), duration);
if (callback) setTimeout(callback, duration + 100);
this._isVisible = false;
return this;
}
/**
@memberof Message
@desc Draws the message given the specified configuration.
@param {Object} [*config*]
@chainable
*/
}, {
key: "render",
value: function render() {
var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
callback = _ref2.callback,
_ref2$container = _ref2.container,
container = _ref2$container === void 0 ? "body" : _ref2$container,
_ref2$duration = _ref2.duration,
duration = _ref2$duration === void 0 ? 600 : _ref2$duration,
_ref2$html = _ref2.html,
html = _ref2$html === void 0 ? "Please Wait" : _ref2$html,
_ref2$mask = _ref2.mask,
mask = _ref2$mask === void 0 ? "rgba(0, 0, 0, 0.05)" : _ref2$mask,
_ref2$style = _ref2.style,
style = _ref2$style === void 0 ? {} : _ref2$style;
var parent = _select(container);
this.mask = parent.selectAll("div.d3plus-Mask").data(mask ? [mask] : []);
this.mask = this.mask.enter().append("div").attr("class", "d3plus-Mask").style("opacity", 1).merge(this.mask);
this.mask.exit().call(this.exit.bind(this), duration);
stylize(this.mask, {
"background-color": String,
"bottom": "0px",
"left": "0px",
"position": "absolute",
"right": "0px",
"top": "0px"
});
this.elem = parent.selectAll("div.d3plus-Message").data([html]);
this.elem = this.elem.enter().append("div").attr("class", "d3plus-Message").style("opacity", 1).merge(this.elem).html(String);
stylize(this.elem, style);
if (callback) setTimeout(callback, 100);
this._isVisible = true;
return this;
}
}]);
return Message;
}();
/**
@function _drawBack
@desc Draws a back button if there are states in this._history.
@private
*/
function drawBack () {
var visible = this._history.length;
var backGroup = elem("g.d3plus-viz-back", {
parent: this._select,
transition: this._transition,
update: {
transform: "translate(".concat(this._margin.left, ", ").concat(this._margin.top, ")")
}
}).node();
this._backClass.data(visible ? [{
text: "\u2190 ".concat(this._translate("Back")),
x: 0,
y: 0
}] : []).select(backGroup).config(this._backConfig).render();
this._margin.top += visible ? this._backClass.fontSize()() + this._backClass.padding()() * 2 : 0;
}
/**
@function _drawColorScale
@desc Renders the color scale if this._colorScale is not falsey.
@private
*/
function drawColorScale () {
var _this = this;
var data = this._data;
var position = this._colorScalePosition || "bottom";
var wide = ["top", "bottom"].includes(position);
var padding = this._colorScalePadding() ? this._padding : {
top: 0,
right: 0,
bottom: 0,
left: 0
};
var availableWidth = this._width - (this._margin.left + this._margin.right + padding.left + padding.right);
var width = wide ? min([this._colorScaleMaxSize, availableWidth]) : this._width - (this._margin.left + this._margin.right);
var availableHeight = this._height - (this._margin.bottom + this._margin.top + padding.bottom + padding.top);
var height = !wide ? min([this._colorScaleMaxSize, availableHeight]) : this._height - (this._margin.bottom + this._margin.top);
var transform = {
opacity: this._colorScalePosition ? 1 : 0,
transform: "translate(".concat(wide ? this._margin.left + padding.left + (availableWidth - width) / 2 : this._margin.left, ", ").concat(wide ? this._margin.top : this._margin.top + padding.top + (availableHeight - height) / 2, ")")
};
var showColorScale = this._colorScale && data && data.length > 1;
var scaleGroup = elem("g.d3plus-viz-colorScale", {
condition: showColorScale && !this._colorScaleConfig.select,
enter: transform,
parent: this._select,
transition: this._transition,
update: transform
}).node();
if (showColorScale) {
var scaleData = data.filter(function (d, i) {
var c = _this._colorScale(d, i);
return c !== undefined && c !== null;
});
this._colorScaleClass.align({
bottom: "end",
left: "start",
right: "end",
top: "start"
}[position] || "bottom").duration(this._duration).data(scaleData).height(height).locale(this._locale).orient(position).select(scaleGroup).value(this._colorScale).width(width).config(this._colorScaleConfig).render();
var scaleBounds = this._colorScaleClass.outerBounds();
if (this._colorScalePosition && !this._colorScaleConfig.select && scaleBounds.height) {
if (wide) this._margin[position] += scaleBounds.height + this._legendClass.padding() * 2;else this._margin[position] += scaleBounds.width + this._legendClass.padding() * 2;
}
} else {
this._colorScaleClass.config(this._colorScaleConfig);
}
}
var html2canvas = createCommonjsModule(function (module, exports) {
/*
html2canvas 0.5.0-beta4 <http://html2canvas.hertzen.com>
Copyright (c) 2016 Niklas von Hertzen
Released under License
*/
(function (f) {
{
module.exports = f();
}
})(function () {
return function e(t, n, r) {
function s(o, u) {
if (!n[o]) {
if (!t[o]) {
var a = typeof commonjsRequire == "function" && commonjsRequire;
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 commonjsRequire == "function" && commonjsRequire;
for (var o = 0; o < r.length; o++) {
s(r[o]);
}
return s;
}({
1: [function (_dereq_, module, exports) {
(function (global) {
(function (root) {
/** Detect free variables */
var freeExports = _typeof(exports) == 'object' && exports && !exports.nodeType && exports;
var freeModule = _typeof(module) == 'object' && module && !module.nodeType && module;
var freeGlobal = _typeof(global) == 'object' && global;
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal) {
root = freeGlobal;
}
/**
* The `punycode` object.
* @name punycode
* @type Object
*/
var punycode,
/** Highest positive signed 32-bit float value */
maxInt = 2147483647,
// aka. 0x7FFFFFFF or 2^31-1
/** Bootstring parameters */
base = 36,
tMin = 1,
tMax = 26,
skew = 38,
damp = 700,
initialBias = 72,
initialN = 128,
// 0x80
delimiter = '-',
// '\x2D'
/** Regular expressions */
regexPunycode = /^xn--/,
regexNonASCII = /[^\x20-\x7E]/,
// unprintable ASCII chars + non-ASCII chars
regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g,
// RFC 3490 separators
/** Error messages */
errors = {
'overflow': 'Overflow: input needs wider integers to process',
'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
'invalid-input': 'Invalid input'
},
/** Convenience shortcuts */
baseMinusTMin = base - tMin,
floor = Math.floor,
stringFromCharCode = String.fromCharCode,
/** Temporary variable */
key;
/*--------------------------------------------------------------------------*/
/**
* A generic error utility function.
* @private
* @param {String} type The error type.
* @returns {Error} Throws a `RangeError` with the applicable error message.
*/
function error(type) {
throw new RangeError(errors[type]);
}
/**
* A generic `Array#map` utility function.
* @private
* @param {Array} array The array to iterate over.
* @param {Function} callback The function that gets called for every array
* item.
* @returns {Array} A new array of values returned by the callback function.
*/
function map(array, fn) {
var length = array.length;
var result = [];
while (length--) {
result[length] = fn(array[length]);
}
return result;
}
/**
* A simple `Array#map`-like wrapper to work with domain name strings or email
* addresses.
* @private
* @param {String} domain The domain name or email address.
* @param {Function} callback The function that gets called for every
* character.
* @returns {Array} A new string of characters returned by the callback
* function.
*/
function mapDomain(string, fn) {
var parts = string.split('@');
var result = '';
if (parts.length > 1) {
// In email addresses, only the domain name should be punycoded. Leave
// the local part (i.e. everything up to `@`) intact.
result = parts[0] + '@';
string = parts[1];
} // Avoid `split(regex)` for IE8 compatibility. See #17.
string = string.replace(regexSeparators, '\x2E');
var labels = string.split('.');
var encoded = map(labels, fn).join('.');
return result + encoded;
}
/**
* Creates an array containing the numeric code points of each Unicode
* character in the string. While JavaScript uses UCS-2 internally,
* this function will convert a pair of surrogate halves (each of which
* UCS-2 exposes as separate characters) into a single code point,
* matching UTF-16.
* @see `punycode.ucs2.encode`
* @see <https://mathiasbynens.be/notes/javascript-encoding>
* @memberOf punycode.ucs2
* @name decode
* @param {String} string The Unicode input string (UCS-2).
* @returns {Array} The new array of code points.
*/
function ucs2decode(string) {
var output = [],
counter = 0,
length = string.length,
value,
extra;
while (counter < length) {
value = string.charCodeAt(counter++);
if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
// high surrogate, and there is a next character
extra = string.charCodeAt(counter++);
if ((extra & 0xFC00) == 0xDC00) {
// low surrogate
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
} else {
// unmatched surrogate; only append this code unit, in case the next
// code unit is the high surrogate of a surrogate pair
output.push(value);
counter--;
}
} else {
output.push(value);
}
}
return output;
}
/**
* Creates a string based on an array of numeric code points.
* @see `punycode.ucs2.decode`
* @memberOf punycode.ucs2
* @name encode
* @param {Array} codePoints The array of numeric code points.
* @returns {String} The new Unicode string (UCS-2).
*/
function ucs2encode(array) {
return map(array, function (value) {
var output = '';
if (value > 0xFFFF) {
value -= 0x10000;
output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
value = 0xDC00 | value & 0x3FF;
}
output += stringFromCharCode(value);
return output;
}).join('');
}
/**
* Converts a basic code point into a digit/integer.
* @see `digitToBasic()`
* @private
* @param {Number} codePoint The basic numeric code point value.
* @returns {Number} The numeric value of a basic code point (for use in
* representing integers) in the range `0` to `base - 1`, or `base` if
* the code point does not represent a value.
*/
function basicToDigit(codePoint) {
if (codePoint - 48 < 10) {
return codePoint - 22;
}
if (codePoint - 65 < 26) {
return codePoint - 65;
}
if (codePoint - 97 < 26) {
return codePoint - 97;
}
return base;
}
/**
* Converts a digit/integer into a basic code point.
* @see `basicToDigit()`
* @private
* @param {Number} digit The numeric value of a basic code point.
* @returns {Number} The basic code point whose value (when used for
* representing integers) is `digit`, which needs to be in the range
* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
* used; else, the lowercase form is used. The behavior is undefined
* if `flag` is non-zero and `digit` has no uppercase form.
*/
function digitToBasic(digit, flag) {
// 0..25 map to ASCII a..z or A..Z
// 26..35 map to ASCII 0..9
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
}
/**
* Bias adaptation function as per section 3.4 of RFC 3492.
* https://tools.ietf.org/html/rfc3492#section-3.4
* @private
*/
function adapt(delta, numPoints, firstTime) {
var k = 0;
delta = firstTime ? floor(delta / damp) : delta >> 1;
delta += floor(delta / numPoints);
for (;
/* no initialization */
delta > baseMinusTMin * tMax >> 1; k += base) {
delta = floor(delta / baseMinusTMin);
}
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
}
/**
* Converts a Punycode string of ASCII-only symbols to a string of Unicode
* symbols.
* @memberOf punycode
* @param {String} input The Punycode string of ASCII-only symbols.
* @returns {String} The resulting string of Unicode symbols.
*/
function decode(input) {
// Don't use UCS-2
var output = [],
inputLength = input.length,
out,
i = 0,
n = initialN,
bias = initialBias,
basic,
j,
index,
oldi,
w,
k,
digit,
t,
/** Cached calculation results */
baseMinusT; // Handle the basic code points: let `basic` be the number of input code
// points before the last delimiter, or `0` if there is none, then copy
// the first basic code points to the output.
basic = input.lastIndexOf(delimiter);
if (basic < 0) {
basic = 0;
}
for (j = 0; j < basic; ++j) {
// if it's not a basic code point
if (input.charCodeAt(j) >= 0x80) {
error('not-basic');
}
output.push(input.charCodeAt(j));
} // Main decoding loop: start just after the last delimiter if any basic code
// points were copied; start at the beginning otherwise.
for (index = basic > 0 ? basic + 1 : 0; index < inputLength;)
/* no final expression */
{
// `index` is the index of the next character to be consumed.
// Decode a generalized variable-length integer into `delta`,
// which gets added to `i`. The overflow checking is easier
// if we increase `i` as we go, then subtract off its starting
// value at the end to obtain `delta`.
for (oldi = i, w = 1, k = base;;
/* no condition */
k += base) {
if (index >= inputLength) {
error('invalid-input');
}
digit = basicToDigit(input.charCodeAt(index++));
if (digit >= base || digit > floor((maxInt - i) / w)) {
error('overflow');
}
i += digit * w;
t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;
if (digit < t) {
break;
}
baseMinusT = base - t;
if (w > floor(maxInt / baseMinusT)) {
error('overflow');
}
w *= baseMinusT;
}
out = output.length + 1;
bias = adapt(i - oldi, out, oldi == 0); // `i` was supposed to wrap around from `out` to `0`,
// incrementing `n` each time, so we'll fix that now:
if (floor(i / out) > maxInt - n) {
error('overflow');
}
n += floor(i / out);
i %= out; // Insert `n` at position `i` of the output
output.splice(i++, 0, n);
}
return ucs2encode(output);
}
/**
* Converts a string of Unicode symbols (e.g. a domain name label) to a
* Punycode string of ASCII-only symbols.
* @memberOf punycode
* @param {String} input The string of Unicode symbols.
* @returns {String} The resulting Punycode string of ASCII-only symbols.
*/
function encode(input) {
var n,
delta,
handledCPCount,
basicLength,
bias,
j,
m,
q,
k,
t,
currentValue,
output = [],
/** `inputLength` will hold the number of code points in `input`. */
inputLength,
/** Cached calculation results */
handledCPCountPlusOne,
baseMinusT,
qMinusT; // Convert the input in UCS-2 to Unicode
input = ucs2decode(input); // Cache the length
inputLength = input.length; // Initialize the state
n = initialN;
delta = 0;
bias = initialBias; // Handle the basic code points
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < 0x80) {
output.push(stringFromCharCode(currentValue));
}
}
handledCPCount = basicLength = output.length; // `handledCPCount` is the number of code points that have been handled;
// `basicLength` is the number of basic code points.
// Finish the basic string - if it is not empty - with a delimiter
if (basicLength) {
output.push(delimiter);
} // Main encoding loop:
while (handledCPCount < inputLength) {
// All non-basic code points < n have been handled already. Find the next
// larger one:
for (m = maxInt, j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue >= n && currentValue < m) {
m = currentValue;
}
} // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
// but guard against overflow
handledCPCountPlusOne = handledCPCount + 1;
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
error('overflow');
}
delta += (m - n) * handledCPCountPlusOne;
n = m;
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < n && ++delta > maxInt) {
error('overflow');
}
if (currentValue == n) {
// Represent delta as a generalized variable-length integer
for (q = delta, k = base;;
/* no condition */
k += base) {
t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;
if (q < t) {
break;
}
qMinusT = q - t;
baseMinusT = base - t;
output.push(stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)));
q = floor(qMinusT / baseMinusT);
}
output.push(stringFromCharCode(digitToBasic(q, 0)));
bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
delta = 0;
++handledCPCount;
}
}
++delta;
++n;
}
return output.join('');
}
/**
* Converts a Punycode string representing a domain name or an email address
* to Unicode. Only the Punycoded parts of the input will be converted, i.e.
* it doesn't matter if you call it on a string that has already been
* converted to Unicode.
* @memberOf punycode
* @param {String} input The Punycoded domain name or email address to
* convert to Unicode.
* @returns {String} The Unicode representation of the given Punycode
* string.
*/
function toUnicode(input) {
return mapDomain(input, function (string) {
return regexPunycode.test(string) ? decode(string.slice(4).toLowerCase()) : string;
});
}
/**
* Converts a Unicode string representing a domain name or an email address to
* Punycode. Only the non-ASCII parts of the domain name will be converted,
* i.e. it doesn't matter if you call it with a domain that's already in
* ASCII.
* @memberOf punycode
* @param {String} input The domain name or email address to convert, as a
* Unicode string.
* @returns {String} The Punycode representation of the given domain name or
* email address.
*/
function toASCII(input) {
return mapDomain(input, function (string) {
return regexNonASCII.test(string) ? 'xn--' + encode(string) : string;
});
}
/*--------------------------------------------------------------------------*/
/** Define the public API */
punycode = {
/**
* A string representing the current Punycode.js version number.
* @memberOf punycode
* @type String
*/
'version': '1.3.2',
/**
* An object of methods to convert from JavaScript's internal character
* representation (UCS-2) to Unicode code points, and back.
* @see <https://mathiasbynens.be/notes/javascript-encoding>
* @memberOf punycode
* @type Object
*/
'ucs2': {
'decode': ucs2decode,
'encode': ucs2encode
},
'decode': decode,
'encode': encode,
'toASCII': toASCII,
'toUnicode': toUnicode
};
/** Expose `punycode` */
// Some AMD build optimizers, like r.js, check for specific condition patterns
// like the following:
if (freeExports && freeModule) {
if (module.exports == freeExports) {
// in Node.js, io.js, or RingoJS v0.8.0+
freeModule.exports = punycode;
} else {
// in Narwhal or RingoJS v0.7.0-
for (key in punycode) {
punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
}
}
} else {
// in Rhino or a web browser
root.punycode = punycode;
}
})(this);
}).call(this, typeof commonjsGlobal !== "undefined" ? commonjsGlobal : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {});
}, {}],
2: [function (_dereq_, module, exports) {
var log = _dereq_('./log');
function restoreOwnerScroll(ownerDocument, x, y) {
if (ownerDocument.defaultView && (x !== ownerDocument.defaultView.pageXOffset || y !== ownerDocument.defaultView.pageYOffset)) {
ownerDocument.defaultView.scrollTo(x, y);
}
}
function cloneCanvasContents(canvas, clonedCanvas) {
try {
if (clonedCanvas) {
clonedCanvas.width = canvas.width;
clonedCanvas.height = canvas.height;
clonedCanvas.getContext("2d").putImageData(canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height), 0, 0);
}
} catch (e) {
log("Unable to copy canvas content from", canvas, e);
}
}
function cloneNode(node, javascriptEnabled) {
var clone = node.nodeType === 3 ? document.createTextNode(node.nodeValue) : node.cloneNode(false);
var child = node.firstChild;
while (child) {
if (javascriptEnabled === true || child.nodeType !== 1 || child.nodeName !== 'SCRIPT') {
clone.appendChild(cloneNode(child, javascriptEnabled));
}
child = child.nextSibling;
}
if (node.nodeType === 1) {
clone._scrollTop = node.scrollTop;
clone._scrollLeft = node.scrollLeft;
if (node.nodeName === "CANVAS") {
cloneCanvasContents(node, clone);
} else if (node.nodeName === "TEXTAREA" || node.nodeName === "SELECT") {
clone.value = node.value;
}
}
return clone;
}
function initNode(node) {
if (node.nodeType === 1) {
node.scrollTop = node._scrollTop;
node.scrollLeft = node._scrollLeft;
var child = node.firstChild;
while (child) {
initNode(child);
child = child.nextSibling;
}
}
}
module.exports = function (ownerDocument, containerDocument, width, height, options, x, y) {
var documentElement = cloneNode(ownerDocument.documentElement, options.javascriptEnabled);
var container = containerDocument.createElement("iframe");
container.className = "html2canvas-container";
container.style.visibility = "hidden";
container.style.position = "fixed";
container.style.left = "-10000px";
container.style.top = "0px";
container.style.border = "0";
container.width = width;
container.height = height;
container.scrolling = "no"; // ios won't scroll without it
containerDocument.body.appendChild(container);
return new Promise(function (resolve) {
var documentClone = container.contentWindow.document;
/* Chrome doesn't detect relative background-images assigned in inline <style> sheets when fetched through getComputedStyle
if window url is about:blank, we can assign the url to current by writing onto the document
*/
container.contentWindow.onload = container.onload = function () {
var interval = setInterval(function () {
if (documentClone.body.childNodes.length > 0) {
initNode(documentClone.documentElement);
clearInterval(interval);
if (options.type === "view") {
container.contentWindow.scrollTo(x, y);
if (/(iPad|iPhone|iPod)/g.test(navigator.userAgent) && (container.contentWindow.scrollY !== y || container.contentWindow.scrollX !== x)) {
documentClone.documentElement.style.top = -y + "px";
documentClone.documentElement.style.left = -x + "px";
documentClone.documentElement.style.position = 'absolute';
}
}
resolve(container);
}
}, 50);
};
documentClone.open();
documentClone.write("<!DOCTYPE html><html></html>"); // Chrome scrolls the parent document for some reason after the write to the cloned window???
restoreOwnerScroll(ownerDocument, x, y);
documentClone.replaceChild(documentClone.adoptNode(documentElement), documentClone.documentElement);
documentClone.close();
});
};
}, {
"./log": 13
}],
3: [function (_dereq_, module, exports) {
// http://dev.w3.org/csswg/css-color/
function Color(value) {
this.r = 0;
this.g = 0;
this.b = 0;
this.a = null;
var result = this.fromArray(value) || this.namedColor(value) || this.rgb(value) || this.rgba(value) || this.hex6(value) || this.hex3(value);
}
Color.prototype.darken = function (amount) {
var a = 1 - amount;
return new Color([Math.round(this.r * a), Math.round(this.g * a), Math.round(this.b * a), this.a]);
};
Color.prototype.isTransparent = function () {
return this.a === 0;
};
Color.prototype.isBlack = function () {
return this.r === 0 && this.g === 0 && this.b === 0;
};
Color.prototype.fromArray = function (array) {
if (Array.isArray(array)) {
this.r = Math.min(array[0], 255);
this.g = Math.min(array[1], 255);
this.b = Math.min(array[2], 255);
if (array.length > 3) {
this.a = array[3];
}
}
return Array.isArray(array);
};
var _hex3 = /^#([a-f0-9]{3})$/i;
Color.prototype.hex3 = function (value) {
var match = null;
if ((match = value.match(_hex3)) !== null) {
this.r = parseInt(match[1][0] + match[1][0], 16);
this.g = parseInt(match[1][1] + match[1][1], 16);
this.b = parseInt(match[1][2] + match[1][2], 16);
}
return match !== null;
};
var _hex6 = /^#([a-f0-9]{6})$/i;
Color.prototype.hex6 = function (value) {
var match = null;
if ((match = value.match(_hex6)) !== null) {
this.r = parseInt(match[1].substring(0, 2), 16);
this.g = parseInt(match[1].substring(2, 4), 16);
this.b = parseInt(match[1].substring(4, 6), 16);
}
return match !== null;
};
var _rgb = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/;
Color.prototype.rgb = function (value) {
var match = null;
if ((match = value.match(_rgb)) !== null) {
this.r = Number(match[1]);
this.g = Number(match[2]);
this.b = Number(match[3]);
}
return match !== null;
};
var _rgba = /^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d?\.?\d+)\s*\)$/;
Color.prototype.rgba = function (value) {
var match = null;
if ((match = value.match(_rgba)) !== null) {
this.r = Number(match[1]);
this.g = Number(match[2]);
this.b = Number(match[3]);
this.a = Number(match[4]);
}
return match !== null;
};
Color.prototype.toString = function () {
return this.a !== null && this.a !== 1 ? "rgba(" + [this.r, this.g, this.b, this.a].join(",") + ")" : "rgb(" + [this.r, this.g, this.b].join(",") + ")";
};
Color.prototype.namedColor = function (value) {
value = value.toLowerCase();
var color = colors[value];
if (color) {
this.r = color[0];
this.g = color[1];
this.b = color[2];
} else if (value === "transparent") {
this.r = this.g = this.b = this.a = 0;
return true;
}
return !!color;
};
Color.prototype.isColor = true; // JSON.stringify([].slice.call($$('.named-color-table tr'), 1).map(function(row) { return [row.childNodes[3].textContent, row.childNodes[5].textContent.trim().split(",").map(Number)] }).reduce(function(data, row) {data[row[0]] = row[1]; return data}, {}))
var colors = {
"aliceblue": [240, 248, 255],
"antiquewhite": [250, 235, 215],
"aqua": [0, 255, 255],
"aquamarine": [127, 255, 212],
"azure": [240, 255, 255],
"beige": [245, 245, 220],
"bisque": [255, 228, 196],
"black": [0, 0, 0],
"blanchedalmond": [255, 235, 205],
"blue": [0, 0, 255],
"blueviolet": [138, 43, 226],
"brown": [165, 42, 42],
"burlywood": [222, 184, 135],
"cadetblue": [95, 158, 160],
"chartreuse": [127, 255, 0],
"chocolate": [210, 105, 30],
"coral": [255, 127, 80],
"cornflowerblue": [100, 149, 237],
"cornsilk": [255, 248, 220],
"crimson": [220, 20, 60],
"cyan": [0, 255, 255],
"darkblue": [0, 0, 139],
"darkcyan": [0, 139, 139],
"darkgoldenrod": [184, 134, 11],
"darkgray": [169, 169, 169],
"darkgreen": [0, 100, 0],
"darkgrey": [169, 169, 169],
"darkkhaki": [189, 183, 107],
"darkmagenta": [139, 0, 139],
"darkolivegreen": [85, 107, 47],
"darkorange": [255, 140, 0],
"darkorchid": [153, 50, 204],
"darkred": [139, 0, 0],
"darksalmon": [233, 150, 122],
"darkseagreen": [143, 188, 143],
"darkslateblue": [72, 61, 139],
"darkslategray": [47, 79, 79],
"darkslategrey": [47, 79, 79],
"darkturquoise": [0, 206, 209],
"darkviolet": [148, 0, 211],
"deeppink": [255, 20, 147],
"deepskyblue": [0, 191, 255],
"dimgray": [105, 105, 105],
"dimgrey": [105, 105, 105],
"dodgerblue": [30, 144, 255],
"firebrick": [178, 34, 34],
"floralwhite": [255, 250, 240],
"forestgreen": [34, 139, 34],
"fuchsia": [255, 0, 255],
"gainsboro": [220, 220, 220],
"ghostwhite": [248, 248, 255],
"gold": [255, 215, 0],
"goldenrod": [218, 165, 32],
"gray": [128, 128, 128],
"green": [0, 128, 0],
"greenyellow": [173, 255, 47],
"grey": [128, 128, 128],
"honeydew": [240, 255, 240],
"hotpink": [255, 105, 180],
"indianred": [205, 92, 92],
"indigo": [75, 0, 130],
"ivory": [255, 255, 240],
"khaki": [240, 230, 140],
"lavender": [230, 230, 250],
"lavenderblush": [255, 240, 245],
"lawngreen": [124, 252, 0],
"lemonchiffon": [255, 250, 205],
"lightblue": [173, 216, 230],
"lightcoral": [240, 128, 128],
"lightcyan": [224, 255, 255],
"lightgoldenrodyellow": [250, 250, 210],
"lightgray": [211, 211, 211],
"lightgreen": [144, 238, 144],
"lightgrey": [211, 211, 211],
"lightpink": [255, 182, 193],
"lightsalmon": [255, 160, 122],
"lightseagreen": [32, 178, 170],
"lightskyblue": [135, 206, 250],
"lightslategray": [119, 136, 153],
"lightslategrey": [119, 136, 153],
"lightsteelblue": [176, 196, 222],
"lightyellow": [255, 255, 224],
"lime": [0, 255, 0],
"limegreen": [50, 205, 50],
"linen": [250, 240, 230],
"magenta": [255, 0, 255],
"maroon": [128, 0, 0],
"mediumaquamarine": [102, 205, 170],
"mediumblue": [0, 0, 205],
"mediumorchid": [186, 85, 211],
"mediumpurple": [147, 112, 219],
"mediumseagreen": [60, 179, 113],
"mediumslateblue": [123, 104, 238],
"mediumspringgreen": [0, 250, 154],
"mediumturquoise": [72, 209, 204],
"mediumvioletred": [199, 21, 133],
"midnightblue": [25, 25, 112],
"mintcream": [245, 255, 250],
"mistyrose": [255, 228, 225],
"moccasin": [255, 228, 181],
"navajowhite": [255, 222, 173],
"navy": [0, 0, 128],
"oldlace": [253, 245, 230],
"olive": [128, 128, 0],
"olivedrab": [107, 142, 35],
"orange": [255, 165, 0],
"orangered": [255, 69, 0],
"orchid": [218, 112, 214],
"palegoldenrod": [238, 232, 170],
"palegreen": [152, 251, 152],
"paleturquoise": [175, 238, 238],
"palevioletred": [219, 112, 147],
"papayawhip": [255, 239, 213],
"peachpuff": [255, 218, 185],
"peru": [205, 133, 63],
"pink": [255, 192, 203],
"plum": [221, 160, 221],
"powderblue": [176, 224, 230],
"purple": [128, 0, 128],
"rebeccapurple": [102, 51, 153],
"red": [255, 0, 0],
"rosybrown": [188, 143, 143],
"royalblue": [65, 105, 225],
"saddlebrown": [139, 69, 19],
"salmon": [250, 128, 114],
"sandybrown": [244, 164, 96],
"seagreen": [46, 139, 87],
"seashell": [255, 245, 238],
"sienna": [160, 82, 45],
"silver": [192, 192, 192],
"skyblue": [135, 206, 235],
"slateblue": [106, 90, 205],
"slategray": [112, 128, 144],
"slategrey": [112, 128, 144],
"snow": [255, 250, 250],
"springgreen": [0, 255, 127],
"steelblue": [70, 130, 180],
"tan": [210, 180, 140],
"teal": [0, 128, 128],
"thistle": [216, 191, 216],
"tomato": [255, 99, 71],
"turquoise": [64, 224, 208],
"violet": [238, 130, 238],
"wheat": [245, 222, 179],
"white": [255, 255, 255],
"whitesmoke": [245, 245, 245],
"yellow": [255, 255, 0],
"yellowgreen": [154, 205, 50]
};
module.exports = Color;
}, {}],
4: [function (_dereq_, module, exports) {
var Support = _dereq_('./support');
var CanvasRenderer = _dereq_('./renderers/canvas');
var ImageLoader = _dereq_('./imageloader');
var NodeParser = _dereq_('./nodeparser');
var NodeContainer = _dereq_('./nodecontainer');
var log = _dereq_('./log');
var utils = _dereq_('./utils');
var createWindowClone = _dereq_('./clone');
var loadUrlDocument = _dereq_('./proxy').loadUrlDocument;
var getBounds = utils.getBounds;
var html2canvasNodeAttribute = "data-html2canvas-node";
var html2canvasCloneIndex = 0;
function html2canvas(nodeList, options) {
var index = html2canvasCloneIndex++;
options = options || {};
if (options.logging) {
log.options.logging = true;
log.options.start = Date.now();
}
options.async = typeof options.async === "undefined" ? true : options.async;
options.allowTaint = typeof options.allowTaint === "undefined" ? false : options.allowTaint;
options.removeContainer = typeof options.removeContainer === "undefined" ? true : options.removeContainer;
options.javascriptEnabled = typeof options.javascriptEnabled === "undefined" ? false : options.javascriptEnabled;
options.imageTimeout = typeof options.imageTimeout === "undefined" ? 10000 : options.imageTimeout;
options.renderer = typeof options.renderer === "function" ? options.renderer : CanvasRenderer;
options.strict = !!options.strict;
if (typeof nodeList === "string") {
if (typeof options.proxy !== "string") {
return Promise.reject("Proxy must be used when rendering url");
}
var width = options.width != null ? options.width : window.innerWidth;
var height = options.height != null ? options.height : window.innerHeight;
return loadUrlDocument(absoluteUrl(nodeList), options.proxy, document, width, height, options).then(function (container) {
return renderWindow(container.contentWindow.document.documentElement, container, options, width, height);
});
}
var node = (nodeList === undefined ? [document.documentElement] : nodeList.length ? nodeList : [nodeList])[0];
node.setAttribute(html2canvasNodeAttribute + index, index);
return renderDocument(node.ownerDocument, options, node.ownerDocument.defaultView.innerWidth, node.ownerDocument.defaultView.innerHeight, index).then(function (canvas) {
if (typeof options.onrendered === "function") {
log("options.onrendered is deprecated, html2canvas returns a Promise containing the canvas");
options.onrendered(canvas);
}
return canvas;
});
}
html2canvas.CanvasRenderer = CanvasRenderer;
html2canvas.NodeContainer = NodeContainer;
html2canvas.log = log;
html2canvas.utils = utils;
var html2canvasExport = typeof document === "undefined" || typeof Object.create !== "function" || typeof document.createElement("canvas").getContext !== "function" ? function () {
return Promise.reject("No canvas support");
} : html2canvas;
module.exports = html2canvasExport;
function renderDocument(document, options, windowWidth, windowHeight, html2canvasIndex) {
return createWindowClone(document, document, windowWidth, windowHeight, options, document.defaultView.pageXOffset, document.defaultView.pageYOffset).then(function (container) {
log("Document cloned");
var attributeName = html2canvasNodeAttribute + html2canvasIndex;
var selector = "[" + attributeName + "='" + html2canvasIndex + "']";
document.querySelector(selector).removeAttribute(attributeName);
var clonedWindow = container.contentWindow;
var node = clonedWindow.document.querySelector(selector);
var oncloneHandler = typeof options.onclone === "function" ? Promise.resolve(options.onclone(clonedWindow.document)) : Promise.resolve(true);
return oncloneHandler.then(function () {
return renderWindow(node, container, options, windowWidth, windowHeight);
});
});
}
function renderWindow(node, container, options, windowWidth, windowHeight) {
var clonedWindow = container.contentWindow;
var support = new Support(clonedWindow.document);
var imageLoader = new ImageLoader(options, support);
var bounds = getBounds(node);
var width = options.type === "view" ? windowWidth : documentWidth(clonedWindow.document);
var height = options.type === "view" ? windowHeight : documentHeight(clonedWindow.document);
var renderer = new options.renderer(width, height, imageLoader, options, document);
var parser = new NodeParser(node, renderer, support, imageLoader, options);
return parser.ready.then(function () {
log("Finished rendering");
var canvas;
if (options.type === "view") {
canvas = crop(renderer.canvas, {
width: renderer.canvas.width,
height: renderer.canvas.height,
top: 0,
left: 0,
x: 0,
y: 0
});
} else if (node === clonedWindow.document.body || node === clonedWindow.document.documentElement || options.canvas != null) {
canvas = renderer.canvas;
} else {
canvas = crop(renderer.canvas, {
width: options.width != null ? options.width : bounds.width,
height: options.height != null ? options.height : bounds.height,
top: bounds.top,
left: bounds.left,
x: 0,
y: 0
});
}
cleanupContainer(container, options);
return canvas;
});
}
function cleanupContainer(container, options) {
if (options.removeContainer) {
container.parentNode.removeChild(container);
log("Cleaned up container");
}
}
function crop(canvas, bounds) {
var croppedCanvas = document.createElement("canvas");
var x1 = Math.min(canvas.width - 1, Math.max(0, bounds.left));
var x2 = Math.min(canvas.width, Math.max(1, bounds.left + bounds.width));
var y1 = Math.min(canvas.height - 1, Math.max(0, bounds.top));
var y2 = Math.min(canvas.height, Math.max(1, bounds.top + bounds.height));
croppedCanvas.width = bounds.width;
croppedCanvas.height = bounds.height;
var width = x2 - x1;
var height = y2 - y1;
log("Cropping canvas at:", "left:", bounds.left, "top:", bounds.top, "width:", width, "height:", height);
log("Resulting crop with width", bounds.width, "and height", bounds.height, "with x", x1, "and y", y1);
croppedCanvas.getContext("2d").drawImage(canvas, x1, y1, width, height, bounds.x, bounds.y, width, height);
return croppedCanvas;
}
function documentWidth(doc) {
return Math.max(Math.max(doc.body.scrollWidth, doc.documentElement.scrollWidth), Math.max(doc.body.offsetWidth, doc.documentElement.offsetWidth), Math.max(doc.body.clientWidth, doc.documentElement.clientWidth));
}
function documentHeight(doc) {
return Math.max(Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight), Math.max(doc.body.offsetHeight, doc.documentElement.offsetHeight), Math.max(doc.body.clientHeight, doc.documentElement.clientHeight));
}
function absoluteUrl(url) {
var link = document.createElement("a");
link.href = url;
link.href = link.href;
return link;
}
}, {
"./clone": 2,
"./imageloader": 11,
"./log": 13,
"./nodecontainer": 14,
"./nodeparser": 15,
"./proxy": 16,
"./renderers/canvas": 20,
"./support": 22,
"./utils": 26
}],
5: [function (_dereq_, module, exports) {
var log = _dereq_('./log');
var smallImage = _dereq_('./utils').smallImage;
function DummyImageContainer(src) {
this.src = src;
log("DummyImageContainer for", src);
if (!this.promise || !this.image) {
log("Initiating DummyImageContainer");
DummyImageContainer.prototype.image = new Image();
var image = this.image;
DummyImageContainer.prototype.promise = new Promise(function (resolve, reject) {
image.onload = resolve;
image.onerror = reject;
image.src = smallImage();
if (image.complete === true) {
resolve(image);
}
});
}
}
module.exports = DummyImageContainer;
}, {
"./log": 13,
"./utils": 26
}],
6: [function (_dereq_, module, exports) {
var smallImage = _dereq_('./utils').smallImage;
function Font(family, size) {
var container = document.createElement('div'),
img = document.createElement('img'),
span = document.createElement('span'),
sampleText = 'Hidden Text',
baseline,
middle;
container.style.visibility = "hidden";
container.style.fontFamily = family;
container.style.fontSize = size;
container.style.margin = 0;
container.style.padding = 0;
document.body.appendChild(container);
img.src = smallImage();
img.width = 1;
img.height = 1;
img.style.margin = 0;
img.style.padding = 0;
img.style.verticalAlign = "baseline";
span.style.fontFamily = family;
span.style.fontSize = size;
span.style.margin = 0;
span.style.padding = 0;
span.appendChild(document.createTextNode(sampleText));
container.appendChild(span);
container.appendChild(img);
baseline = img.offsetTop - span.offsetTop + 1;
container.removeChild(span);
container.appendChild(document.createTextNode(sampleText));
container.style.lineHeight = "normal";
img.style.verticalAlign = "super";
middle = img.offsetTop - container.offsetTop + 1;
document.body.removeChild(container);
this.baseline = baseline;
this.lineWidth = 1;
this.middle = middle;
}
module.exports = Font;
}, {
"./utils": 26
}],
7: [function (_dereq_, module, exports) {
var Font = _dereq_('./font');
function FontMetrics() {
this.data = {};
}
FontMetrics.prototype.getMetrics = function (family, size) {
if (this.data[family + "-" + size] === undefined) {
this.data[family + "-" + size] = new Font(family, size);
}
return this.data[family + "-" + size];
};
module.exports = FontMetrics;
}, {
"./font": 6
}],
8: [function (_dereq_, module, exports) {
var utils = _dereq_('./utils');
var getBounds = utils.getBounds;
var loadUrlDocument = _dereq_('./proxy').loadUrlDocument;
function FrameContainer(container, sameOrigin, options) {
this.image = null;
this.src = container;
var self = this;
var bounds = getBounds(container);
this.promise = (!sameOrigin ? this.proxyLoad(options.proxy, bounds, options) : new Promise(function (resolve) {
if (container.contentWindow.document.URL === "about:blank" || container.contentWindow.document.documentElement == null) {
container.contentWindow.onload = container.onload = function () {
resolve(container);
};
} else {
resolve(container);
}
})).then(function (container) {
var html2canvas = _dereq_('./core');
return html2canvas(container.contentWindow.document.documentElement, {
type: 'view',
width: container.width,
height: container.height,
proxy: options.proxy,
javascriptEnabled: options.javascriptEnabled,
removeContainer: options.removeContainer,
allowTaint: options.allowTaint,
imageTimeout: options.imageTimeout / 2
});
}).then(function (canvas) {
return self.image = canvas;
});
}
FrameContainer.prototype.proxyLoad = function (proxy, bounds, options) {
var container = this.src;
return loadUrlDocument(container.src, proxy, container.ownerDocument, bounds.width, bounds.height, options);
};
module.exports = FrameContainer;
}, {
"./core": 4,
"./proxy": 16,
"./utils": 26
}],
9: [function (_dereq_, module, exports) {
function GradientContainer(imageData) {
this.src = imageData.value;
this.colorStops = [];
this.type = null;
this.x0 = 0.5;
this.y0 = 0.5;
this.x1 = 0.5;
this.y1 = 0.5;
this.promise = Promise.resolve(true);
}
GradientContainer.TYPES = {
LINEAR: 1,
RADIAL: 2
}; // TODO: support hsl[a], negative %/length values
// TODO: support <angle> (e.g. -?\d{1,3}(?:\.\d+)deg, etc. : https://developer.mozilla.org/docs/Web/CSS/angle )
GradientContainer.REGEXP_COLORSTOP = /^\s*(rgba?\(\s*\d{1,3},\s*\d{1,3},\s*\d{1,3}(?:,\s*[0-9\.]+)?\s*\)|[a-z]{3,20}|#[a-f0-9]{3,6})(?:\s+(\d{1,3}(?:\.\d+)?)(%|px)?)?(?:\s|$)/i;
module.exports = GradientContainer;
}, {}],
10: [function (_dereq_, module, exports) {
function ImageContainer(src, cors) {
this.src = src;
this.image = new Image();
var self = this;
this.tainted = null;
this.promise = new Promise(function (resolve, reject) {
self.image.onload = resolve;
self.image.onerror = reject;
if (cors) {
self.image.crossOrigin = "anonymous";
}
self.image.src = src;
if (self.image.complete === true) {
resolve(self.image);
}
});
}
module.exports = ImageContainer;
}, {}],
11: [function (_dereq_, module, exports) {
var log = _dereq_('./log');
var ImageContainer = _dereq_('./imagecontainer');
var DummyImageContainer = _dereq_('./dummyimagecontainer');
var ProxyImageContainer = _dereq_('./proxyimagecontainer');
var FrameContainer = _dereq_('./framecontainer');
var SVGContainer = _dereq_('./svgcontainer');
var SVGNodeContainer = _dereq_('./svgnodecontainer');
var LinearGradientContainer = _dereq_('./lineargradientcontainer');
var WebkitGradientContainer = _dereq_('./webkitgradientcontainer');
var bind = _dereq_('./utils').bind;
function ImageLoader(options, support) {
this.link = null;
this.options = options;
this.support = support;
this.origin = this.getOrigin(window.location.href);
}
ImageLoader.prototype.findImages = function (nodes) {
var images = [];
nodes.reduce(function (imageNodes, container) {
switch (container.node.nodeName) {
case "IMG":
return imageNodes.concat([{
args: [container.node.src],
method: "url"
}]);
case "svg":
case "IFRAME":
return imageNodes.concat([{
args: [container.node],
method: container.node.nodeName
}]);
}
return imageNodes;
}, []).forEach(this.addImage(images, this.loadImage), this);
return images;
};
ImageLoader.prototype.findBackgroundImage = function (images, container) {
container.parseBackgroundImages().filter(this.hasImageBackground).forEach(this.addImage(images, this.loadImage), this);
return images;
};
ImageLoader.prototype.addImage = function (images, callback) {
return function (newImage) {
newImage.args.forEach(function (image) {
if (!this.imageExists(images, image)) {
images.splice(0, 0, callback.call(this, newImage));
log('Added image #' + images.length, typeof image === "string" ? image.substring(0, 100) : image);
}
}, this);
};
};
ImageLoader.prototype.hasImageBackground = function (imageData) {
return imageData.method !== "none";
};
ImageLoader.prototype.loadImage = function (imageData) {
if (imageData.method === "url") {
var src = imageData.args[0];
if (this.isSVG(src) && !this.support.svg && !this.options.allowTaint) {
return new SVGContainer(src);
} else if (src.match(/data:image\/.*;base64,/i)) {
return new ImageContainer(src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, ''), false);
} else if (this.isSameOrigin(src) || this.options.allowTaint === true || this.isSVG(src)) {
return new ImageContainer(src, false);
} else if (this.support.cors && !this.options.allowTaint && this.options.useCORS) {
return new ImageContainer(src, true);
} else if (this.options.proxy) {
return new ProxyImageContainer(src, this.options.proxy);
} else {
return new DummyImageContainer(src);
}
} else if (imageData.method === "linear-gradient") {
return new LinearGradientContainer(imageData);
} else if (imageData.method === "gradient") {
return new WebkitGradientContainer(imageData);
} else if (imageData.method === "svg") {
return new SVGNodeContainer(imageData.args[0], this.support.svg);
} else if (imageData.method === "IFRAME") {
return new FrameContainer(imageData.args[0], this.isSameOrigin(imageData.args[0].src), this.options);
} else {
return new DummyImageContainer(imageData);
}
};
ImageLoader.prototype.isSVG = function (src) {
return src.substring(src.length - 3).toLowerCase() === "svg" || SVGContainer.prototype.isInline(src);
};
ImageLoader.prototype.imageExists = function (images, src) {
return images.some(function (image) {
return image.src === src;
});
};
ImageLoader.prototype.isSameOrigin = function (url) {
return this.getOrigin(url) === this.origin;
};
ImageLoader.prototype.getOrigin = function (url) {
var link = this.link || (this.link = document.createElement("a"));
link.href = url;
link.href = link.href; // IE9, LOL! - http://jsfiddle.net/niklasvh/2e48b/
return link.protocol + link.hostname + link.port;
};
ImageLoader.prototype.getPromise = function (container) {
return this.timeout(container, this.options.imageTimeout)['catch'](function () {
var dummy = new DummyImageContainer(container.src);
return dummy.promise.then(function (image) {
container.image = image;
});
});
};
ImageLoader.prototype.get = function (src) {
var found = null;
return this.images.some(function (img) {
return (found = img).src === src;
}) ? found : null;
};
ImageLoader.prototype.fetch = function (nodes) {
this.images = nodes.reduce(bind(this.findBackgroundImage, this), this.findImages(nodes));
this.images.forEach(function (image, index) {
image.promise.then(function () {
log("Succesfully loaded image #" + (index + 1), image);
}, function (e) {
log("Failed loading image #" + (index + 1), image, e);
});
});
this.ready = Promise.all(this.images.map(this.getPromise, this));
log("Finished searching images");
return this;
};
ImageLoader.prototype.timeout = function (container, timeout) {
var timer;
var promise = Promise.race([container.promise, new Promise(function (res, reject) {
timer = setTimeout(function () {
log("Timed out loading image", container);
reject(container);
}, timeout);
})]).then(function (container) {
clearTimeout(timer);
return container;
});
promise['catch'](function () {
clearTimeout(timer);
});
return promise;
};
module.exports = ImageLoader;
}, {
"./dummyimagecontainer": 5,
"./framecontainer": 8,
"./imagecontainer": 10,
"./lineargradientcontainer": 12,
"./log": 13,
"./proxyimagecontainer": 17,
"./svgcontainer": 23,
"./svgnodecontainer": 24,
"./utils": 26,
"./webkitgradientcontainer": 27
}],
12: [function (_dereq_, module, exports) {
var GradientContainer = _dereq_('./gradientcontainer');
var Color = _dereq_('./color');
function LinearGradientContainer(imageData) {
GradientContainer.apply(this, arguments);
this.type = GradientContainer.TYPES.LINEAR;
var hasDirection = LinearGradientContainer.REGEXP_DIRECTION.test(imageData.args[0]) || !GradientContainer.REGEXP_COLORSTOP.test(imageData.args[0]);
if (hasDirection) {
imageData.args[0].split(/\s+/).reverse().forEach(function (position, index) {
switch (position) {
case "left":
this.x0 = 0;
this.x1 = 1;
break;
case "top":
this.y0 = 0;
this.y1 = 1;
break;
case "right":
this.x0 = 1;
this.x1 = 0;
break;
case "bottom":
this.y0 = 1;
this.y1 = 0;
break;
case "to":
var y0 = this.y0;
var x0 = this.x0;
this.y0 = this.y1;
this.x0 = this.x1;
this.x1 = x0;
this.y1 = y0;
break;
case "center":
break;
// centered by default
// Firefox internally converts position keywords to percentages:
// http://www.w3.org/TR/2010/WD-CSS2-20101207/colors.html#propdef-background-position
default:
// percentage or absolute length
// TODO: support absolute start point positions (e.g., use bounds to convert px to a ratio)
var ratio = parseFloat(position, 10) * 1e-2;
if (isNaN(ratio)) {
// invalid or unhandled value
break;
}
if (index === 0) {
this.y0 = ratio;
this.y1 = 1 - this.y0;
} else {
this.x0 = ratio;
this.x1 = 1 - this.x0;
}
break;
}
}, this);
} else {
this.y0 = 0;
this.y1 = 1;
}
this.colorStops = imageData.args.slice(hasDirection ? 1 : 0).map(function (colorStop) {
var colorStopMatch = colorStop.match(GradientContainer.REGEXP_COLORSTOP);
var value = +colorStopMatch[2];
var unit = value === 0 ? "%" : colorStopMatch[3]; // treat "0" as "0%"
return {
color: new Color(colorStopMatch[1]),
// TODO: support absolute stop positions (e.g., compute gradient line length & convert px to ratio)
stop: unit === "%" ? value / 100 : null
};
});
if (this.colorStops[0].stop === null) {
this.colorStops[0].stop = 0;
}
if (this.colorStops[this.colorStops.length - 1].stop === null) {
this.colorStops[this.colorStops.length - 1].stop = 1;
} // calculates and fills-in explicit stop positions when omitted from rule
this.colorStops.forEach(function (colorStop, index) {
if (colorStop.stop === null) {
this.colorStops.slice(index).some(function (find, count) {
if (find.stop !== null) {
colorStop.stop = (find.stop - this.colorStops[index - 1].stop) / (count + 1) + this.colorStops[index - 1].stop;
return true;
} else {
return false;
}
}, this);
}
}, this);
}
LinearGradientContainer.prototype = Object.create(GradientContainer.prototype); // TODO: support <angle> (e.g. -?\d{1,3}(?:\.\d+)deg, etc. : https://developer.mozilla.org/docs/Web/CSS/angle )
LinearGradientContainer.REGEXP_DIRECTION = /^\s*(?:to|left|right|top|bottom|center|\d{1,3}(?:\.\d+)?%?)(?:\s|$)/i;
module.exports = LinearGradientContainer;
}, {
"./color": 3,
"./gradientcontainer": 9
}],
13: [function (_dereq_, module, exports) {
var logger = function logger() {
if (logger.options.logging && window.console && window.console.log) {
Function.prototype.bind.call(window.console.log, window.console).apply(window.console, [Date.now() - logger.options.start + "ms", "html2canvas:"].concat([].slice.call(arguments, 0)));
}
};
logger.options = {
logging: false
};
module.exports = logger;
}, {}],
14: [function (_dereq_, module, exports) {
var Color = _dereq_('./color');
var utils = _dereq_('./utils');
var getBounds = utils.getBounds;
var parseBackgrounds = utils.parseBackgrounds;
var offsetBounds = utils.offsetBounds;
function NodeContainer(node, parent) {
this.node = node;
this.parent = parent;
this.stack = null;
this.bounds = null;
this.borders = null;
this.clip = [];
this.backgroundClip = [];
this.offsetBounds = null;
this.visible = null;
this.computedStyles = null;
this.colors = {};
this.styles = {};
this.backgroundImages = null;
this.transformData = null;
this.transformMatrix = null;
this.isPseudoElement = false;
this.opacity = null;
}
NodeContainer.prototype.cloneTo = function (stack) {
stack.visible = this.visible;
stack.borders = this.borders;
stack.bounds = this.bounds;
stack.clip = this.clip;
stack.backgroundClip = this.backgroundClip;
stack.computedStyles = this.computedStyles;
stack.styles = this.styles;
stack.backgroundImages = this.backgroundImages;
stack.opacity = this.opacity;
};
NodeContainer.prototype.getOpacity = function () {
return this.opacity === null ? this.opacity = this.cssFloat('opacity') : this.opacity;
};
NodeContainer.prototype.assignStack = function (stack) {
this.stack = stack;
stack.children.push(this);
};
NodeContainer.prototype.isElementVisible = function () {
return this.node.nodeType === Node.TEXT_NODE ? this.parent.visible : this.css('display') !== "none" && this.css('visibility') !== "hidden" && !this.node.hasAttribute("data-html2canvas-ignore") && (this.node.nodeName !== "INPUT" || this.node.getAttribute("type") !== "hidden");
};
NodeContainer.prototype.css = function (attribute) {
if (!this.computedStyles) {
this.computedStyles = this.isPseudoElement ? this.parent.computedStyle(this.before ? ":before" : ":after") : this.computedStyle(null);
}
return this.styles[attribute] || (this.styles[attribute] = this.computedStyles[attribute]);
};
NodeContainer.prototype.prefixedCss = function (attribute) {
var prefixes = ["webkit", "moz", "ms", "o"];
var value = this.css(attribute);
if (value === undefined) {
prefixes.some(function (prefix) {
value = this.css(prefix + attribute.substr(0, 1).toUpperCase() + attribute.substr(1));
return value !== undefined;
}, this);
}
return value === undefined ? null : value;
};
NodeContainer.prototype.computedStyle = function (type) {
return this.node.ownerDocument.defaultView.getComputedStyle(this.node, type);
};
NodeContainer.prototype.cssInt = function (attribute) {
var value = parseInt(this.css(attribute), 10);
return isNaN(value) ? 0 : value; // borders in old IE are throwing 'medium' for demo.html
};
NodeContainer.prototype.color = function (attribute) {
return this.colors[attribute] || (this.colors[attribute] = new Color(this.css(attribute)));
};
NodeContainer.prototype.cssFloat = function (attribute) {
var value = parseFloat(this.css(attribute));
return isNaN(value) ? 0 : value;
};
NodeContainer.prototype.fontWeight = function () {
var weight = this.css("fontWeight");
switch (parseInt(weight, 10)) {
case 401:
weight = "bold";
break;
case 400:
weight = "normal";
break;
}
return weight;
};
NodeContainer.prototype.parseClip = function () {
var matches = this.css('clip').match(this.CLIP);
if (matches) {
return {
top: parseInt(matches[1], 10),
right: parseInt(matches[2], 10),
bottom: parseInt(matches[3], 10),
left: parseInt(matches[4], 10)
};
}
return null;
};
NodeContainer.prototype.parseBackgroundImages = function () {
return this.backgroundImages || (this.backgroundImages = parseBackgrounds(this.css("backgroundImage")));
};
NodeContainer.prototype.cssList = function (property, index) {
var value = (this.css(property) || '').split(',');
value = value[index || 0] || value[0] || 'auto';
value = value.trim().split(' ');
if (value.length === 1) {
value = [value[0], isPercentage(value[0]) ? 'auto' : value[0]];
}
return value;
};
NodeContainer.prototype.parseBackgroundSize = function (bounds, image, index) {
var size = this.cssList("backgroundSize", index);
var width, height;
if (isPercentage(size[0])) {
width = bounds.width * parseFloat(size[0]) / 100;
} else if (/contain|cover/.test(size[0])) {
var targetRatio = bounds.width / bounds.height,
currentRatio = image.width / image.height;
return targetRatio < currentRatio ^ size[0] === 'contain' ? {
width: bounds.height * currentRatio,
height: bounds.height
} : {
width: bounds.width,
height: bounds.width / currentRatio
};
} else {
width = parseInt(size[0], 10);
}
if (size[0] === 'auto' && size[1] === 'auto') {
height = image.height;
} else if (size[1] === 'auto') {
height = width / image.width * image.height;
} else if (isPercentage(size[1])) {
height = bounds.height * parseFloat(size[1]) / 100;
} else {
height = parseInt(size[1], 10);
}
if (size[0] === 'auto') {
width = height / image.height * image.width;
}
return {
width: width,
height: height
};
};
NodeContainer.prototype.parseBackgroundPosition = function (bounds, image, index, backgroundSize) {
var position = this.cssList('backgroundPosition', index);
var left, top;
if (isPercentage(position[0])) {
left = (bounds.width - (backgroundSize || image).width) * (parseFloat(position[0]) / 100);
} else {
left = parseInt(position[0], 10);
}
if (position[1] === 'auto') {
top = left / image.width * image.height;
} else if (isPercentage(position[1])) {
top = (bounds.height - (backgroundSize || image).height) * parseFloat(position[1]) / 100;
} else {
top = parseInt(position[1], 10);
}
if (position[0] === 'auto') {
left = top / image.height * image.width;
}
return {
left: left,
top: top
};
};
NodeContainer.prototype.parseBackgroundRepeat = function (index) {
return this.cssList("backgroundRepeat", index)[0];
};
NodeContainer.prototype.parseTextShadows = function () {
var textShadow = this.css("textShadow");
var results = [];
if (textShadow && textShadow !== 'none') {
var shadows = textShadow.match(this.TEXT_SHADOW_PROPERTY);
for (var i = 0; shadows && i < shadows.length; i++) {
var s = shadows[i].match(this.TEXT_SHADOW_VALUES);
results.push({
color: new Color(s[0]),
offsetX: s[1] ? parseFloat(s[1].replace('px', '')) : 0,
offsetY: s[2] ? parseFloat(s[2].replace('px', '')) : 0,
blur: s[3] ? s[3].replace('px', '') : 0
});
}
}
return results;
};
NodeContainer.prototype.parseTransform = function () {
if (!this.transformData) {
if (this.hasTransform()) {
var offset = this.parseBounds();
var origin = this.prefixedCss("transformOrigin").split(" ").map(removePx).map(asFloat);
origin[0] += offset.left;
origin[1] += offset.top;
this.transformData = {
origin: origin,
matrix: this.parseTransformMatrix()
};
} else {
this.transformData = {
origin: [0, 0],
matrix: [1, 0, 0, 1, 0, 0]
};
}
}
return this.transformData;
};
NodeContainer.prototype.parseTransformMatrix = function () {
if (!this.transformMatrix) {
var transform = this.prefixedCss("transform");
var matrix = transform ? parseMatrix(transform.match(this.MATRIX_PROPERTY)) : null;
this.transformMatrix = matrix ? matrix : [1, 0, 0, 1, 0, 0];
}
return this.transformMatrix;
};
NodeContainer.prototype.parseBounds = function () {
return this.bounds || (this.bounds = this.hasTransform() ? offsetBounds(this.node) : getBounds(this.node));
};
NodeContainer.prototype.hasTransform = function () {
return this.parseTransformMatrix().join(",") !== "1,0,0,1,0,0" || this.parent && this.parent.hasTransform();
};
NodeContainer.prototype.getValue = function () {
var value = this.node.value || "";
if (this.node.tagName === "SELECT") {
value = selectionValue(this.node);
} else if (this.node.type === "password") {
value = Array(value.length + 1).join("\u2022"); // jshint ignore:line
}
return value.length === 0 ? this.node.placeholder || "" : value;
};
NodeContainer.prototype.MATRIX_PROPERTY = /(matrix|matrix3d)\((.+)\)/;
NodeContainer.prototype.TEXT_SHADOW_PROPERTY = /((rgba|rgb)\([^\)]+\)(\s-?\d+px){0,})/g;
NodeContainer.prototype.TEXT_SHADOW_VALUES = /(-?\d+px)|(#.+)|(rgb\(.+\))|(rgba\(.+\))/g;
NodeContainer.prototype.CLIP = /^rect\((\d+)px,? (\d+)px,? (\d+)px,? (\d+)px\)$/;
function selectionValue(node) {
var option = node.options[node.selectedIndex || 0];
return option ? option.text || "" : "";
}
function parseMatrix(match) {
if (match && match[1] === "matrix") {
return match[2].split(",").map(function (s) {
return parseFloat(s.trim());
});
} else if (match && match[1] === "matrix3d") {
var matrix3d = match[2].split(",").map(function (s) {
return parseFloat(s.trim());
});
return [matrix3d[0], matrix3d[1], matrix3d[4], matrix3d[5], matrix3d[12], matrix3d[13]];
}
}
function isPercentage(value) {
return value.toString().indexOf("%") !== -1;
}
function removePx(str) {
return str.replace("px", "");
}
function asFloat(str) {
return parseFloat(str);
}
module.exports = NodeContainer;
}, {
"./color": 3,
"./utils": 26
}],
15: [function (_dereq_, module, exports) {
var log = _dereq_('./log');
var punycode = _dereq_('punycode');
var NodeContainer = _dereq_('./nodecontainer');
var TextContainer = _dereq_('./textcontainer');
var PseudoElementContainer = _dereq_('./pseudoelementcontainer');
var FontMetrics = _dereq_('./fontmetrics');
var Color = _dereq_('./color');
var StackingContext = _dereq_('./stackingcontext');
var utils = _dereq_('./utils');
var bind = utils.bind;
var getBounds = utils.getBounds;
var parseBackgrounds = utils.parseBackgrounds;
var offsetBounds = utils.offsetBounds;
function NodeParser(element, renderer, support, imageLoader, options) {
log("Starting NodeParser");
this.renderer = renderer;
this.options = options;
this.range = null;
this.support = support;
this.renderQueue = [];
this.stack = new StackingContext(true, 1, element.ownerDocument, null);
var parent = new NodeContainer(element, null);
if (options.background) {
renderer.rectangle(0, 0, renderer.width, renderer.height, new Color(options.background));
}
if (element === element.ownerDocument.documentElement) {
// http://www.w3.org/TR/css3-background/#special-backgrounds
var canvasBackground = new NodeContainer(parent.color('backgroundColor').isTransparent() ? element.ownerDocument.body : element.ownerDocument.documentElement, null);
renderer.rectangle(0, 0, renderer.width, renderer.height, canvasBackground.color('backgroundColor'));
}
parent.visibile = parent.isElementVisible();
this.createPseudoHideStyles(element.ownerDocument);
this.disableAnimations(element.ownerDocument);
this.nodes = flatten([parent].concat(this.getChildren(parent)).filter(function (container) {
return container.visible = container.isElementVisible();
}).map(this.getPseudoElements, this));
this.fontMetrics = new FontMetrics();
log("Fetched nodes, total:", this.nodes.length);
log("Calculate overflow clips");
this.calculateOverflowClips();
log("Start fetching images");
this.images = imageLoader.fetch(this.nodes.filter(isElement));
this.ready = this.images.ready.then(bind(function () {
log("Images loaded, starting parsing");
log("Creating stacking contexts");
this.createStackingContexts();
log("Sorting stacking contexts");
this.sortStackingContexts(this.stack);
this.parse(this.stack);
log("Render queue created with " + this.renderQueue.length + " items");
return new Promise(bind(function (resolve) {
if (!options.async) {
this.renderQueue.forEach(this.paint, this);
resolve();
} else if (typeof options.async === "function") {
options.async.call(this, this.renderQueue, resolve);
} else if (this.renderQueue.length > 0) {
this.renderIndex = 0;
this.asyncRenderer(this.renderQueue, resolve);
} else {
resolve();
}
}, this));
}, this));
}
NodeParser.prototype.calculateOverflowClips = function () {
this.nodes.forEach(function (container) {
if (isElement(container)) {
if (isPseudoElement(container)) {
container.appendToDOM();
}
container.borders = this.parseBorders(container);
var clip = container.css('overflow') === "hidden" ? [container.borders.clip] : [];
var cssClip = container.parseClip();
if (cssClip && ["absolute", "fixed"].indexOf(container.css('position')) !== -1) {
clip.push([["rect", container.bounds.left + cssClip.left, container.bounds.top + cssClip.top, cssClip.right - cssClip.left, cssClip.bottom - cssClip.top]]);
}
container.clip = hasParentClip(container) ? container.parent.clip.concat(clip) : clip;
container.backgroundClip = container.css('overflow') !== "hidden" ? container.clip.concat([container.borders.clip]) : container.clip;
if (isPseudoElement(container)) {
container.cleanDOM();
}
} else if (isTextNode(container)) {
container.clip = hasParentClip(container) ? container.parent.clip : [];
}
if (!isPseudoElement(container)) {
container.bounds = null;
}
}, this);
};
function hasParentClip(container) {
return container.parent && container.parent.clip.length;
}
NodeParser.prototype.asyncRenderer = function (queue, resolve, asyncTimer) {
asyncTimer = asyncTimer || Date.now();
this.paint(queue[this.renderIndex++]);
if (queue.length === this.renderIndex) {
resolve();
} else if (asyncTimer + 20 > Date.now()) {
this.asyncRenderer(queue, resolve, asyncTimer);
} else {
setTimeout(bind(function () {
this.asyncRenderer(queue, resolve);
}, this), 0);
}
};
NodeParser.prototype.createPseudoHideStyles = function (document) {
this.createStyles(document, '.' + PseudoElementContainer.prototype.PSEUDO_HIDE_ELEMENT_CLASS_BEFORE + ':before { content: "" !important; display: none !important; }' + '.' + PseudoElementContainer.prototype.PSEUDO_HIDE_ELEMENT_CLASS_AFTER + ':after { content: "" !important; display: none !important; }');
};
NodeParser.prototype.disableAnimations = function (document) {
this.createStyles(document, '* { -webkit-animation: none !important; -moz-animation: none !important; -o-animation: none !important; animation: none !important; ' + '-webkit-transition: none !important; -moz-transition: none !important; -o-transition: none !important; transition: none !important;}');
};
NodeParser.prototype.createStyles = function (document, styles) {
var hidePseudoElements = document.createElement('style');
hidePseudoElements.innerHTML = styles;
document.body.appendChild(hidePseudoElements);
};
NodeParser.prototype.getPseudoElements = function (container) {
var nodes = [[container]];
if (container.node.nodeType === Node.ELEMENT_NODE) {
var before = this.getPseudoElement(container, ":before");
var after = this.getPseudoElement(container, ":after");
if (before) {
nodes.push(before);
}
if (after) {
nodes.push(after);
}
}
return flatten(nodes);
};
function toCamelCase(str) {
return str.replace(/(\-[a-z])/g, function (match) {
return match.toUpperCase().replace('-', '');
});
}
NodeParser.prototype.getPseudoElement = function (container, type) {
var style = container.computedStyle(type);
if (!style || !style.content || style.content === "none" || style.content === "-moz-alt-content" || style.display === "none") {
return null;
}
var content = stripQuotes(style.content);
var isImage = content.substr(0, 3) === 'url';
var pseudoNode = document.createElement(isImage ? 'img' : 'html2canvaspseudoelement');
var pseudoContainer = new PseudoElementContainer(pseudoNode, container, type);
for (var i = style.length - 1; i >= 0; i--) {
var property = toCamelCase(style.item(i));
pseudoNode.style[property] = style[property];
}
pseudoNode.className = PseudoElementContainer.prototype.PSEUDO_HIDE_ELEMENT_CLASS_BEFORE + " " + PseudoElementContainer.prototype.PSEUDO_HIDE_ELEMENT_CLASS_AFTER;
if (isImage) {
pseudoNode.src = parseBackgrounds(content)[0].args[0];
return [pseudoContainer];
} else {
var text = document.createTextNode(content);
pseudoNode.appendChild(text);
return [pseudoContainer, new TextContainer(text, pseudoContainer)];
}
};
NodeParser.prototype.getChildren = function (parentContainer) {
return flatten([].filter.call(parentContainer.node.childNodes, renderableNode).map(function (node) {
var container = [node.nodeType === Node.TEXT_NODE ? new TextContainer(node, parentContainer) : new NodeContainer(node, parentContainer)].filter(nonIgnoredElement);
return node.nodeType === Node.ELEMENT_NODE && container.length && node.tagName !== "TEXTAREA" ? container[0].isElementVisible() ? container.concat(this.getChildren(container[0])) : [] : container;
}, this));
};
NodeParser.prototype.newStackingContext = function (container, hasOwnStacking) {
var stack = new StackingContext(hasOwnStacking, container.getOpacity(), container.node, container.parent);
container.cloneTo(stack);
var parentStack = hasOwnStacking ? stack.getParentStack(this) : stack.parent.stack;
parentStack.contexts.push(stack);
container.stack = stack;
};
NodeParser.prototype.createStackingContexts = function () {
this.nodes.forEach(function (container) {
if (isElement(container) && (this.isRootElement(container) || hasOpacity(container) || isPositionedForStacking(container) || this.isBodyWithTransparentRoot(container) || container.hasTransform())) {
this.newStackingContext(container, true);
} else if (isElement(container) && (isPositioned(container) && zIndex0(container) || isInlineBlock(container) || isFloating(container))) {
this.newStackingContext(container, false);
} else {
container.assignStack(container.parent.stack);
}
}, this);
};
NodeParser.prototype.isBodyWithTransparentRoot = function (container) {
return container.node.nodeName === "BODY" && container.parent.color('backgroundColor').isTransparent();
};
NodeParser.prototype.isRootElement = function (container) {
return container.parent === null;
};
NodeParser.prototype.sortStackingContexts = function (stack) {
stack.contexts.sort(zIndexSort(stack.contexts.slice(0)));
stack.contexts.forEach(this.sortStackingContexts, this);
};
NodeParser.prototype.parseTextBounds = function (container) {
return function (text, index, textList) {
if (container.parent.css("textDecoration").substr(0, 4) !== "none" || text.trim().length !== 0) {
if (this.support.rangeBounds && !container.parent.hasTransform()) {
var offset = textList.slice(0, index).join("").length;
return this.getRangeBounds(container.node, offset, text.length);
} else if (container.node && typeof container.node.data === "string") {
var replacementNode = container.node.splitText(text.length);
var bounds = this.getWrapperBounds(container.node, container.parent.hasTransform());
container.node = replacementNode;
return bounds;
}
} else if (!this.support.rangeBounds || container.parent.hasTransform()) {
container.node = container.node.splitText(text.length);
}
return {};
};
};
NodeParser.prototype.getWrapperBounds = function (node, transform) {
var wrapper = node.ownerDocument.createElement('html2canvaswrapper');
var parent = node.parentNode,
backupText = node.cloneNode(true);
wrapper.appendChild(node.cloneNode(true));
parent.replaceChild(wrapper, node);
var bounds = transform ? offsetBounds(wrapper) : getBounds(wrapper);
parent.replaceChild(backupText, wrapper);
return bounds;
};
NodeParser.prototype.getRangeBounds = function (node, offset, length) {
var range = this.range || (this.range = node.ownerDocument.createRange());
range.setStart(node, offset);
range.setEnd(node, offset + length);
return range.getBoundingClientRect();
};
function ClearTransform() {}
NodeParser.prototype.parse = function (stack) {
// http://www.w3.org/TR/CSS21/visuren.html#z-index
var negativeZindex = stack.contexts.filter(negativeZIndex); // 2. the child stacking contexts with negative stack levels (most negative first).
var descendantElements = stack.children.filter(isElement);
var descendantNonFloats = descendantElements.filter(not(isFloating));
var nonInlineNonPositionedDescendants = descendantNonFloats.filter(not(isPositioned)).filter(not(inlineLevel)); // 3 the in-flow, non-inline-level, non-positioned descendants.
var nonPositionedFloats = descendantElements.filter(not(isPositioned)).filter(isFloating); // 4. the non-positioned floats.
var inFlow = descendantNonFloats.filter(not(isPositioned)).filter(inlineLevel); // 5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
var stackLevel0 = stack.contexts.concat(descendantNonFloats.filter(isPositioned)).filter(zIndex0); // 6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
var text = stack.children.filter(isTextNode).filter(hasText);
var positiveZindex = stack.contexts.filter(positiveZIndex); // 7. the child stacking contexts with positive stack levels (least positive first).
negativeZindex.concat(nonInlineNonPositionedDescendants).concat(nonPositionedFloats).concat(inFlow).concat(stackLevel0).concat(text).concat(positiveZindex).forEach(function (container) {
this.renderQueue.push(container);
if (isStackingContext(container)) {
this.parse(container);
this.renderQueue.push(new ClearTransform());
}
}, this);
};
NodeParser.prototype.paint = function (container) {
try {
if (container instanceof ClearTransform) {
this.renderer.ctx.restore();
} else if (isTextNode(container)) {
if (isPseudoElement(container.parent)) {
container.parent.appendToDOM();
}
this.paintText(container);
if (isPseudoElement(container.parent)) {
container.parent.cleanDOM();
}
} else {
this.paintNode(container);
}
} catch (e) {
log(e);
if (this.options.strict) {
throw e;
}
}
};
NodeParser.prototype.paintNode = function (container) {
if (isStackingContext(container)) {
this.renderer.setOpacity(container.opacity);
this.renderer.ctx.save();
if (container.hasTransform()) {
this.renderer.setTransform(container.parseTransform());
}
}
if (container.node.nodeName === "INPUT" && container.node.type === "checkbox") {
this.paintCheckbox(container);
} else if (container.node.nodeName === "INPUT" && container.node.type === "radio") {
this.paintRadio(container);
} else {
this.paintElement(container);
}
};
NodeParser.prototype.paintElement = function (container) {
var bounds = container.parseBounds();
this.renderer.clip(container.backgroundClip, function () {
this.renderer.renderBackground(container, bounds, container.borders.borders.map(getWidth));
}, this);
this.renderer.clip(container.clip, function () {
this.renderer.renderBorders(container.borders.borders);
}, this);
this.renderer.clip(container.backgroundClip, function () {
switch (container.node.nodeName) {
case "svg":
case "IFRAME":
var imgContainer = this.images.get(container.node);
if (imgContainer) {
this.renderer.renderImage(container, bounds, container.borders, imgContainer);
} else {
log("Error loading <" + container.node.nodeName + ">", container.node);
}
break;
case "IMG":
var imageContainer = this.images.get(container.node.src);
if (imageContainer) {
this.renderer.renderImage(container, bounds, container.borders, imageContainer);
} else {
log("Error loading <img>", container.node.src);
}
break;
case "CANVAS":
this.renderer.renderImage(container, bounds, container.borders, {
image: container.node
});
break;
case "SELECT":
case "INPUT":
case "TEXTAREA":
this.paintFormValue(container);
break;
}
}, this);
};
NodeParser.prototype.paintCheckbox = function (container) {
var b = container.parseBounds();
var size = Math.min(b.width, b.height);
var bounds = {
width: size - 1,
height: size - 1,
top: b.top,
left: b.left
};
var r = [3, 3];
var radius = [r, r, r, r];
var borders = [1, 1, 1, 1].map(function (w) {
return {
color: new Color('#A5A5A5'),
width: w
};
});
var borderPoints = calculateCurvePoints(bounds, radius, borders);
this.renderer.clip(container.backgroundClip, function () {
this.renderer.rectangle(bounds.left + 1, bounds.top + 1, bounds.width - 2, bounds.height - 2, new Color("#DEDEDE"));
this.renderer.renderBorders(calculateBorders(borders, bounds, borderPoints, radius));
if (container.node.checked) {
this.renderer.font(new Color('#424242'), 'normal', 'normal', 'bold', size - 3 + "px", 'arial');
this.renderer.text("\u2714", bounds.left + size / 6, bounds.top + size - 1);
}
}, this);
};
NodeParser.prototype.paintRadio = function (container) {
var bounds = container.parseBounds();
var size = Math.min(bounds.width, bounds.height) - 2;
this.renderer.clip(container.backgroundClip, function () {
this.renderer.circleStroke(bounds.left + 1, bounds.top + 1, size, new Color('#DEDEDE'), 1, new Color('#A5A5A5'));
if (container.node.checked) {
this.renderer.circle(Math.ceil(bounds.left + size / 4) + 1, Math.ceil(bounds.top + size / 4) + 1, Math.floor(size / 2), new Color('#424242'));
}
}, this);
};
NodeParser.prototype.paintFormValue = function (container) {
var value = container.getValue();
if (value.length > 0) {
var document = container.node.ownerDocument;
var wrapper = document.createElement('html2canvaswrapper');
var properties = ['lineHeight', 'textAlign', 'fontFamily', 'fontWeight', 'fontSize', 'color', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'width', 'height', 'borderLeftStyle', 'borderTopStyle', 'borderLeftWidth', 'borderTopWidth', 'boxSizing', 'whiteSpace', 'wordWrap'];
properties.forEach(function (property) {
try {
wrapper.style[property] = container.css(property);
} catch (e) {
// Older IE has issues with "border"
log("html2canvas: Parse: Exception caught in renderFormValue: " + e.message);
}
});
var bounds = container.parseBounds();
wrapper.style.position = "fixed";
wrapper.style.left = bounds.left + "px";
wrapper.style.top = bounds.top + "px";
wrapper.textContent = value;
document.body.appendChild(wrapper);
this.paintText(new TextContainer(wrapper.firstChild, container));
document.body.removeChild(wrapper);
}
};
NodeParser.prototype.paintText = function (container) {
container.applyTextTransform();
var characters = punycode.ucs2.decode(container.node.data);
var textList = (!this.options.letterRendering || noLetterSpacing(container)) && !hasUnicode(container.node.data) ? getWords(characters) : characters.map(function (character) {
return punycode.ucs2.encode([character]);
});
var weight = container.parent.fontWeight();
var size = container.parent.css('fontSize');
var family = container.parent.css('fontFamily');
var shadows = container.parent.parseTextShadows();
this.renderer.font(container.parent.color('color'), container.parent.css('fontStyle'), container.parent.css('fontVariant'), weight, size, family);
if (shadows.length) {
// TODO: support multiple text shadows
this.renderer.fontShadow(shadows[0].color, shadows[0].offsetX, shadows[0].offsetY, shadows[0].blur);
} else {
this.renderer.clearShadow();
}
this.renderer.clip(container.parent.clip, function () {
textList.map(this.parseTextBounds(container), this).forEach(function (bounds, index) {
if (bounds) {
this.renderer.text(textList[index], bounds.left, bounds.bottom);
this.renderTextDecoration(container.parent, bounds, this.fontMetrics.getMetrics(family, size));
}
}, this);
}, this);
};
NodeParser.prototype.renderTextDecoration = function (container, bounds, metrics) {
switch (container.css("textDecoration").split(" ")[0]) {
case "underline":
// Draws a line at the baseline of the font
// TODO As some browsers display the line as more than 1px if the font-size is big, need to take that into account both in position and size
this.renderer.rectangle(bounds.left, Math.round(bounds.top + metrics.baseline + metrics.lineWidth), bounds.width, 1, container.color("color"));
break;
case "overline":
this.renderer.rectangle(bounds.left, Math.round(bounds.top), bounds.width, 1, container.color("color"));
break;
case "line-through":
// TODO try and find exact position for line-through
this.renderer.rectangle(bounds.left, Math.ceil(bounds.top + metrics.middle + metrics.lineWidth), bounds.width, 1, container.color("color"));
break;
}
};
var borderColorTransforms = {
inset: [["darken", 0.60], ["darken", 0.10], ["darken", 0.10], ["darken", 0.60]]
};
NodeParser.prototype.parseBorders = function (container) {
var nodeBounds = container.parseBounds();
var radius = getBorderRadiusData(container);
var borders = ["Top", "Right", "Bottom", "Left"].map(function (side, index) {
var style = container.css('border' + side + 'Style');
var color = container.color('border' + side + 'Color');
if (style === "inset" && color.isBlack()) {
color = new Color([255, 255, 255, color.a]); // this is wrong, but
}
var colorTransform = borderColorTransforms[style] ? borderColorTransforms[style][index] : null;
return {
width: container.cssInt('border' + side + 'Width'),
color: colorTransform ? color[colorTransform[0]](colorTransform[1]) : color,
args: null
};
});
var borderPoints = calculateCurvePoints(nodeBounds, radius, borders);
return {
clip: this.parseBackgroundClip(container, borderPoints, borders, radius, nodeBounds),
borders: calculateBorders(borders, nodeBounds, borderPoints, radius)
};
};
function calculateBorders(borders, nodeBounds, borderPoints, radius) {
return borders.map(function (border, borderSide) {
if (border.width > 0) {
var bx = nodeBounds.left;
var by = nodeBounds.top;
var bw = nodeBounds.width;
var bh = nodeBounds.height - borders[2].width;
switch (borderSide) {
case 0:
// top border
bh = borders[0].width;
border.args = drawSide({
c1: [bx, by],
c2: [bx + bw, by],
c3: [bx + bw - borders[1].width, by + bh],
c4: [bx + borders[3].width, by + bh]
}, radius[0], radius[1], borderPoints.topLeftOuter, borderPoints.topLeftInner, borderPoints.topRightOuter, borderPoints.topRightInner);
break;
case 1:
// right border
bx = nodeBounds.left + nodeBounds.width - borders[1].width;
bw = borders[1].width;
border.args = drawSide({
c1: [bx + bw, by],
c2: [bx + bw, by + bh + borders[2].width],
c3: [bx, by + bh],
c4: [bx, by + borders[0].width]
}, radius[1], radius[2], borderPoints.topRightOuter, borderPoints.topRightInner, borderPoints.bottomRightOuter, borderPoints.bottomRightInner);
break;
case 2:
// bottom border
by = by + nodeBounds.height - borders[2].width;
bh = borders[2].width;
border.args = drawSide({
c1: [bx + bw, by + bh],
c2: [bx, by + bh],
c3: [bx + borders[3].width, by],
c4: [bx + bw - borders[3].width, by]
}, radius[2], radius[3], borderPoints.bottomRightOuter, borderPoints.bottomRightInner, borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner);
break;
case 3:
// left border
bw = borders[3].width;
border.args = drawSide({
c1: [bx, by + bh + borders[2].width],
c2: [bx, by],
c3: [bx + bw, by + borders[0].width],
c4: [bx + bw, by + bh]
}, radius[3], radius[0], borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner, borderPoints.topLeftOuter, borderPoints.topLeftInner);
break;
}
}
return border;
});
}
NodeParser.prototype.parseBackgroundClip = function (container, borderPoints, borders, radius, bounds) {
var backgroundClip = container.css('backgroundClip'),
borderArgs = [];
switch (backgroundClip) {
case "content-box":
case "padding-box":
parseCorner(borderArgs, radius[0], radius[1], borderPoints.topLeftInner, borderPoints.topRightInner, bounds.left + borders[3].width, bounds.top + borders[0].width);
parseCorner(borderArgs, radius[1], radius[2], borderPoints.topRightInner, borderPoints.bottomRightInner, bounds.left + bounds.width - borders[1].width, bounds.top + borders[0].width);
parseCorner(borderArgs, radius[2], radius[3], borderPoints.bottomRightInner, borderPoints.bottomLeftInner, bounds.left + bounds.width - borders[1].width, bounds.top + bounds.height - borders[2].width);
parseCorner(borderArgs, radius[3], radius[0], borderPoints.bottomLeftInner, borderPoints.topLeftInner, bounds.left + borders[3].width, bounds.top + bounds.height - borders[2].width);
break;
default:
parseCorner(borderArgs, radius[0], radius[1], borderPoints.topLeftOuter, borderPoints.topRightOuter, bounds.left, bounds.top);
parseCorner(borderArgs, radius[1], radius[2], borderPoints.topRightOuter, borderPoints.bottomRightOuter, bounds.left + bounds.width, bounds.top);
parseCorner(borderArgs, radius[2], radius[3], borderPoints.bottomRightOuter, borderPoints.bottomLeftOuter, bounds.left + bounds.width, bounds.top + bounds.height);
parseCorner(borderArgs, radius[3], radius[0], borderPoints.bottomLeftOuter, borderPoints.topLeftOuter, bounds.left, bounds.top + bounds.height);
break;
}
return borderArgs;
};
function getCurvePoints(x, y, r1, r2) {
var kappa = 4 * ((Math.sqrt(2) - 1) / 3);
var ox = r1 * kappa,
// control point offset horizontal
oy = r2 * kappa,
// control point offset vertical
xm = x + r1,
// x-middle
ym = y + r2; // y-middle
return {
topLeft: bezierCurve({
x: x,
y: ym
}, {
x: x,
y: ym - oy
}, {
x: xm - ox,
y: y
}, {
x: xm,
y: y
}),
topRight: bezierCurve({
x: x,
y: y
}, {
x: x + ox,
y: y
}, {
x: xm,
y: ym - oy
}, {
x: xm,
y: ym
}),
bottomRight: bezierCurve({
x: xm,
y: y
}, {
x: xm,
y: y + oy
}, {
x: x + ox,
y: ym
}, {
x: x,
y: ym
}),
bottomLeft: bezierCurve({
x: xm,
y: ym
}, {
x: xm - ox,
y: ym
}, {
x: x,
y: y + oy
}, {
x: x,
y: y
})
};
}
function calculateCurvePoints(bounds, borderRadius, borders) {
var x = bounds.left,
y = bounds.top,
width = bounds.width,
height = bounds.height,
tlh = borderRadius[0][0] < width / 2 ? borderRadius[0][0] : width / 2,
tlv = borderRadius[0][1] < height / 2 ? borderRadius[0][1] : height / 2,
trh = borderRadius[1][0] < width / 2 ? borderRadius[1][0] : width / 2,
trv = borderRadius[1][1] < height / 2 ? borderRadius[1][1] : height / 2,
brh = borderRadius[2][0] < width / 2 ? borderRadius[2][0] : width / 2,
brv = borderRadius[2][1] < height / 2 ? borderRadius[2][1] : height / 2,
blh = borderRadius[3][0] < width / 2 ? borderRadius[3][0] : width / 2,
blv = borderRadius[3][1] < height / 2 ? borderRadius[3][1] : height / 2;
var topWidth = width - trh,
rightHeight = height - brv,
bottomWidth = width - brh,
leftHeight = height - blv;
return {
topLeftOuter: getCurvePoints(x, y, tlh, tlv).topLeft.subdivide(0.5),
topLeftInner: getCurvePoints(x + borders[3].width, y + borders[0].width, Math.max(0, tlh - borders[3].width), Math.max(0, tlv - borders[0].width)).topLeft.subdivide(0.5),
topRightOuter: getCurvePoints(x + topWidth, y, trh, trv).topRight.subdivide(0.5),
topRightInner: getCurvePoints(x + Math.min(topWidth, width + borders[3].width), y + borders[0].width, topWidth > width + borders[3].width ? 0 : trh - borders[3].width, trv - borders[0].width).topRight.subdivide(0.5),
bottomRightOuter: getCurvePoints(x + bottomWidth, y + rightHeight, brh, brv).bottomRight.subdivide(0.5),
bottomRightInner: getCurvePoints(x + Math.min(bottomWidth, width - borders[3].width), y + Math.min(rightHeight, height + borders[0].width), Math.max(0, brh - borders[1].width), brv - borders[2].width).bottomRight.subdivide(0.5),
bottomLeftOuter: getCurvePoints(x, y + leftHeight, blh, blv).bottomLeft.subdivide(0.5),
bottomLeftInner: getCurvePoints(x + borders[3].width, y + leftHeight, Math.max(0, blh - borders[3].width), blv - borders[2].width).bottomLeft.subdivide(0.5)
};
}
function bezierCurve(start, startControl, endControl, end) {
var lerp = function lerp(a, b, t) {
return {
x: a.x + (b.x - a.x) * t,
y: a.y + (b.y - a.y) * t
};
};
return {
start: start,
startControl: startControl,
endControl: endControl,
end: end,
subdivide: function subdivide(t) {
var ab = lerp(start, startControl, t),
bc = lerp(startControl, endControl, t),
cd = lerp(endControl, end, t),
abbc = lerp(ab, bc, t),
bccd = lerp(bc, cd, t),
dest = lerp(abbc, bccd, t);
return [bezierCurve(start, ab, abbc, dest), bezierCurve(dest, bccd, cd, end)];
},
curveTo: function curveTo(borderArgs) {
borderArgs.push(["bezierCurve", startControl.x, startControl.y, endControl.x, endControl.y, end.x, end.y]);
},
curveToReversed: function curveToReversed(borderArgs) {
borderArgs.push(["bezierCurve", endControl.x, endControl.y, startControl.x, startControl.y, start.x, start.y]);
}
};
}
function drawSide(borderData, radius1, radius2, outer1, inner1, outer2, inner2) {
var borderArgs = [];
if (radius1[0] > 0 || radius1[1] > 0) {
borderArgs.push(["line", outer1[1].start.x, outer1[1].start.y]);
outer1[1].curveTo(borderArgs);
} else {
borderArgs.push(["line", borderData.c1[0], borderData.c1[1]]);
}
if (radius2[0] > 0 || radius2[1] > 0) {
borderArgs.push(["line", outer2[0].start.x, outer2[0].start.y]);
outer2[0].curveTo(borderArgs);
borderArgs.push(["line", inner2[0].end.x, inner2[0].end.y]);
inner2[0].curveToReversed(borderArgs);
} else {
borderArgs.push(["line", borderData.c2[0], borderData.c2[1]]);
borderArgs.push(["line", borderData.c3[0], borderData.c3[1]]);
}
if (radius1[0] > 0 || radius1[1] > 0) {
borderArgs.push(["line", inner1[1].end.x, inner1[1].end.y]);
inner1[1].curveToReversed(borderArgs);
} else {
borderArgs.push(["line", borderData.c4[0], borderData.c4[1]]);
}
return borderArgs;
}
function parseCorner(borderArgs, radius1, radius2, corner1, corner2, x, y) {
if (radius1[0] > 0 || radius1[1] > 0) {
borderArgs.push(["line", corner1[0].start.x, corner1[0].start.y]);
corner1[0].curveTo(borderArgs);
corner1[1].curveTo(borderArgs);
} else {
borderArgs.push(["line", x, y]);
}
if (radius2[0] > 0 || radius2[1] > 0) {
borderArgs.push(["line", corner2[0].start.x, corner2[0].start.y]);
}
}
function negativeZIndex(container) {
return container.cssInt("zIndex") < 0;
}
function positiveZIndex(container) {
return container.cssInt("zIndex") > 0;
}
function zIndex0(container) {
return container.cssInt("zIndex") === 0;
}
function inlineLevel(container) {
return ["inline", "inline-block", "inline-table"].indexOf(container.css("display")) !== -1;
}
function isStackingContext(container) {
return container instanceof StackingContext;
}
function hasText(container) {
return container.node.data.trim().length > 0;
}
function noLetterSpacing(container) {
return /^(normal|none|0px)$/.test(container.parent.css("letterSpacing"));
}
function getBorderRadiusData(container) {
return ["TopLeft", "TopRight", "BottomRight", "BottomLeft"].map(function (side) {
var value = container.css('border' + side + 'Radius');
var arr = value.split(" ");
if (arr.length <= 1) {
arr[1] = arr[0];
}
return arr.map(asInt);
});
}
function renderableNode(node) {
return node.nodeType === Node.TEXT_NODE || node.nodeType === Node.ELEMENT_NODE;
}
function isPositionedForStacking(container) {
var position = container.css("position");
var zIndex = ["absolute", "relative", "fixed"].indexOf(position) !== -1 ? container.css("zIndex") : "auto";
return zIndex !== "auto";
}
function isPositioned(container) {
return container.css("position") !== "static";
}
function isFloating(container) {
return container.css("float") !== "none";
}
function isInlineBlock(container) {
return ["inline-block", "inline-table"].indexOf(container.css("display")) !== -1;
}
function not(callback) {
var context = this;
return function () {
return !callback.apply(context, arguments);
};
}
function isElement(container) {
return container.node.nodeType === Node.ELEMENT_NODE;
}
function isPseudoElement(container) {
return container.isPseudoElement === true;
}
function isTextNode(container) {
return container.node.nodeType === Node.TEXT_NODE;
}
function zIndexSort(contexts) {
return function (a, b) {
return a.cssInt("zIndex") + contexts.indexOf(a) / contexts.length - (b.cssInt("zIndex") + contexts.indexOf(b) / contexts.length);
};
}
function hasOpacity(container) {
return container.getOpacity() < 1;
}
function asInt(value) {
return parseInt(value, 10);
}
function getWidth(border) {
return border.width;
}
function nonIgnoredElement(nodeContainer) {
return nodeContainer.node.nodeType !== Node.ELEMENT_NODE || ["SCRIPT", "HEAD", "TITLE", "OBJECT", "BR", "OPTION"].indexOf(nodeContainer.node.nodeName) === -1;
}
function flatten(arrays) {
return [].concat.apply([], arrays);
}
function stripQuotes(content) {
var first = content.substr(0, 1);
return first === content.substr(content.length - 1) && first.match(/'|"/) ? content.substr(1, content.length - 2) : content;
}
function getWords(characters) {
var words = [],
i = 0,
onWordBoundary = false,
word;
while (characters.length) {
if (isWordBoundary(characters[i]) === onWordBoundary) {
word = characters.splice(0, i);
if (word.length) {
words.push(punycode.ucs2.encode(word));
}
onWordBoundary = !onWordBoundary;
i = 0;
} else {
i++;
}
if (i >= characters.length) {
word = characters.splice(0, i);
if (word.length) {
words.push(punycode.ucs2.encode(word));
}
}
}
return words;
}
function isWordBoundary(characterCode) {
return [32, // <space>
13, // \r
10, // \n
9, // \t
45 // -
].indexOf(characterCode) !== -1;
}
function hasUnicode(string) {
return /[^\u0000-\u00ff]/.test(string);
}
module.exports = NodeParser;
}, {
"./color": 3,
"./fontmetrics": 7,
"./log": 13,
"./nodecontainer": 14,
"./pseudoelementcontainer": 18,
"./stackingcontext": 21,
"./textcontainer": 25,
"./utils": 26,
"punycode": 1
}],
16: [function (_dereq_, module, exports) {
var XHR = _dereq_('./xhr');
var utils = _dereq_('./utils');
var log = _dereq_('./log');
var createWindowClone = _dereq_('./clone');
var decode64 = utils.decode64;
function Proxy(src, proxyUrl, document) {
var supportsCORS = ('withCredentials' in new XMLHttpRequest());
if (!proxyUrl) {
return Promise.reject("No proxy configured");
}
var callback = createCallback(supportsCORS);
var url = createProxyUrl(proxyUrl, src, callback);
return supportsCORS ? XHR(url) : jsonp(document, url, callback).then(function (response) {
return decode64(response.content);
});
}
var proxyCount = 0;
function ProxyURL(src, proxyUrl, document) {
var supportsCORSImage = ('crossOrigin' in new Image());
var callback = createCallback(supportsCORSImage);
var url = createProxyUrl(proxyUrl, src, callback);
return supportsCORSImage ? Promise.resolve(url) : jsonp(document, url, callback).then(function (response) {
return "data:" + response.type + ";base64," + response.content;
});
}
function jsonp(document, url, callback) {
return new Promise(function (resolve, reject) {
var s = document.createElement("script");
var cleanup = function cleanup() {
delete window.html2canvas.proxy[callback];
document.body.removeChild(s);
};
window.html2canvas.proxy[callback] = function (response) {
cleanup();
resolve(response);
};
s.src = url;
s.onerror = function (e) {
cleanup();
reject(e);
};
document.body.appendChild(s);
});
}
function createCallback(useCORS) {
return !useCORS ? "html2canvas_" + Date.now() + "_" + ++proxyCount + "_" + Math.round(Math.random() * 100000) : "";
}
function createProxyUrl(proxyUrl, src, callback) {
return proxyUrl + "?url=" + encodeURIComponent(src) + (callback.length ? "&callback=html2canvas.proxy." + callback : "");
}
function documentFromHTML(src) {
return function (html) {
var parser = new DOMParser(),
doc;
try {
doc = parser.parseFromString(html, "text/html");
} catch (e) {
log("DOMParser not supported, falling back to createHTMLDocument");
doc = document.implementation.createHTMLDocument("");
try {
doc.open();
doc.write(html);
doc.close();
} catch (ee) {
log("createHTMLDocument write not supported, falling back to document.body.innerHTML");
doc.body.innerHTML = html; // ie9 doesnt support writing to documentElement
}
}
var b = doc.querySelector("base");
if (!b || !b.href.host) {
var base = doc.createElement("base");
base.href = src;
doc.head.insertBefore(base, doc.head.firstChild);
}
return doc;
};
}
function loadUrlDocument(src, proxy, document, width, height, options) {
return new Proxy(src, proxy, window.document).then(documentFromHTML(src)).then(function (doc) {
return createWindowClone(doc, document, width, height, options, 0, 0);
});
}
exports.Proxy = Proxy;
exports.ProxyURL = ProxyURL;
exports.loadUrlDocument = loadUrlDocument;
}, {
"./clone": 2,
"./log": 13,
"./utils": 26,
"./xhr": 28
}],
17: [function (_dereq_, module, exports) {
var ProxyURL = _dereq_('./proxy').ProxyURL;
function ProxyImageContainer(src, proxy) {
var link = document.createElement("a");
link.href = src;
src = link.href;
this.src = src;
this.image = new Image();
var self = this;
this.promise = new Promise(function (resolve, reject) {
self.image.crossOrigin = "Anonymous";
self.image.onload = resolve;
self.image.onerror = reject;
new ProxyURL(src, proxy, document).then(function (url) {
self.image.src = url;
})['catch'](reject);
});
}
module.exports = ProxyImageContainer;
}, {
"./proxy": 16
}],
18: [function (_dereq_, module, exports) {
var NodeContainer = _dereq_('./nodecontainer');
function PseudoElementContainer(node, parent, type) {
NodeContainer.call(this, node, parent);
this.isPseudoElement = true;
this.before = type === ":before";
}
PseudoElementContainer.prototype.cloneTo = function (stack) {
PseudoElementContainer.prototype.cloneTo.call(this, stack);
stack.isPseudoElement = true;
stack.before = this.before;
};
PseudoElementContainer.prototype = Object.create(NodeContainer.prototype);
PseudoElementContainer.prototype.appendToDOM = function () {
if (this.before) {
this.parent.node.insertBefore(this.node, this.parent.node.firstChild);
} else {
this.parent.node.appendChild(this.node);
}
this.parent.node.className += " " + this.getHideClass();
};
PseudoElementContainer.prototype.cleanDOM = function () {
this.node.parentNode.removeChild(this.node);
this.parent.node.className = this.parent.node.className.replace(this.getHideClass(), "");
};
PseudoElementContainer.prototype.getHideClass = function () {
return this["PSEUDO_HIDE_ELEMENT_CLASS_" + (this.before ? "BEFORE" : "AFTER")];
};
PseudoElementContainer.prototype.PSEUDO_HIDE_ELEMENT_CLASS_BEFORE = "___html2canvas___pseudoelement_before";
PseudoElementContainer.prototype.PSEUDO_HIDE_ELEMENT_CLASS_AFTER = "___html2canvas___pseudoelement_after";
module.exports = PseudoElementContainer;
}, {
"./nodecontainer": 14
}],
19: [function (_dereq_, module, exports) {
var log = _dereq_('./log');
function Renderer(width, height, images, options, document) {
this.width = width;
this.height = height;
this.images = images;
this.options = options;
this.document = document;
}
Renderer.prototype.renderImage = function (container, bounds, borderData, imageContainer) {
var paddingLeft = container.cssInt('paddingLeft'),
paddingTop = container.cssInt('paddingTop'),
paddingRight = container.cssInt('paddingRight'),
paddingBottom = container.cssInt('paddingBottom'),
borders = borderData.borders;
var width = bounds.width - (borders[1].width + borders[3].width + paddingLeft + paddingRight);
var height = bounds.height - (borders[0].width + borders[2].width + paddingTop + paddingBottom);
this.drawImage(imageContainer, 0, 0, imageContainer.image.width || width, imageContainer.image.height || height, bounds.left + paddingLeft + borders[3].width, bounds.top + paddingTop + borders[0].width, width, height);
};
Renderer.prototype.renderBackground = function (container, bounds, borderData) {
if (bounds.height > 0 && bounds.width > 0) {
this.renderBackgroundColor(container, bounds);
this.renderBackgroundImage(container, bounds, borderData);
}
};
Renderer.prototype.renderBackgroundColor = function (container, bounds) {
var color = container.color("backgroundColor");
if (!color.isTransparent()) {
this.rectangle(bounds.left, bounds.top, bounds.width, bounds.height, color);
}
};
Renderer.prototype.renderBorders = function (borders) {
borders.forEach(this.renderBorder, this);
};
Renderer.prototype.renderBorder = function (data) {
if (!data.color.isTransparent() && data.args !== null) {
this.drawShape(data.args, data.color);
}
};
Renderer.prototype.renderBackgroundImage = function (container, bounds, borderData) {
var backgroundImages = container.parseBackgroundImages();
backgroundImages.reverse().forEach(function (backgroundImage, index, arr) {
switch (backgroundImage.method) {
case "url":
var image = this.images.get(backgroundImage.args[0]);
if (image) {
this.renderBackgroundRepeating(container, bounds, image, arr.length - (index + 1), borderData);
} else {
log("Error loading background-image", backgroundImage.args[0]);
}
break;
case "linear-gradient":
case "gradient":
var gradientImage = this.images.get(backgroundImage.value);
if (gradientImage) {
this.renderBackgroundGradient(gradientImage, bounds, borderData);
} else {
log("Error loading background-image", backgroundImage.args[0]);
}
break;
case "none":
break;
default:
log("Unknown background-image type", backgroundImage.args[0]);
}
}, this);
};
Renderer.prototype.renderBackgroundRepeating = function (container, bounds, imageContainer, index, borderData) {
var size = container.parseBackgroundSize(bounds, imageContainer.image, index);
var position = container.parseBackgroundPosition(bounds, imageContainer.image, index, size);
var repeat = container.parseBackgroundRepeat(index);
switch (repeat) {
case "repeat-x":
case "repeat no-repeat":
this.backgroundRepeatShape(imageContainer, position, size, bounds, bounds.left + borderData[3], bounds.top + position.top + borderData[0], 99999, size.height, borderData);
break;
case "repeat-y":
case "no-repeat repeat":
this.backgroundRepeatShape(imageContainer, position, size, bounds, bounds.left + position.left + borderData[3], bounds.top + borderData[0], size.width, 99999, borderData);
break;
case "no-repeat":
this.backgroundRepeatShape(imageContainer, position, size, bounds, bounds.left + position.left + borderData[3], bounds.top + position.top + borderData[0], size.width, size.height, borderData);
break;
default:
this.renderBackgroundRepeat(imageContainer, position, size, {
top: bounds.top,
left: bounds.left
}, borderData[3], borderData[0]);
break;
}
};
module.exports = Renderer;
}, {
"./log": 13
}],
20: [function (_dereq_, module, exports) {
var Renderer = _dereq_('../renderer');
var LinearGradientContainer = _dereq_('../lineargradientcontainer');
var log = _dereq_('../log');
function CanvasRenderer(width, height) {
Renderer.apply(this, arguments);
this.canvas = this.options.canvas || this.document.createElement("canvas");
if (!this.options.canvas) {
this.canvas.width = width;
this.canvas.height = height;
}
this.ctx = this.canvas.getContext("2d");
this.taintCtx = this.document.createElement("canvas").getContext("2d");
this.ctx.textBaseline = "bottom";
this.variables = {};
log("Initialized CanvasRenderer with size", width, "x", height);
}
CanvasRenderer.prototype = Object.create(Renderer.prototype);
CanvasRenderer.prototype.setFillStyle = function (fillStyle) {
this.ctx.fillStyle = _typeof(fillStyle) === "object" && !!fillStyle.isColor ? fillStyle.toString() : fillStyle;
return this.ctx;
};
CanvasRenderer.prototype.rectangle = function (left, top, width, height, color) {
this.setFillStyle(color).fillRect(left, top, width, height);
};
CanvasRenderer.prototype.circle = function (left, top, size, color) {
this.setFillStyle(color);
this.ctx.beginPath();
this.ctx.arc(left + size / 2, top + size / 2, size / 2, 0, Math.PI * 2, true);
this.ctx.closePath();
this.ctx.fill();
};
CanvasRenderer.prototype.circleStroke = function (left, top, size, color, stroke, strokeColor) {
this.circle(left, top, size, color);
this.ctx.strokeStyle = strokeColor.toString();
this.ctx.stroke();
};
CanvasRenderer.prototype.drawShape = function (shape, color) {
this.shape(shape);
this.setFillStyle(color).fill();
};
CanvasRenderer.prototype.taints = function (imageContainer) {
if (imageContainer.tainted === null) {
this.taintCtx.drawImage(imageContainer.image, 0, 0);
try {
this.taintCtx.getImageData(0, 0, 1, 1);
imageContainer.tainted = false;
} catch (e) {
this.taintCtx = document.createElement("canvas").getContext("2d");
imageContainer.tainted = true;
}
}
return imageContainer.tainted;
};
CanvasRenderer.prototype.drawImage = function (imageContainer, sx, sy, sw, sh, dx, dy, dw, dh) {
if (!this.taints(imageContainer) || this.options.allowTaint) {
this.ctx.drawImage(imageContainer.image, sx, sy, sw, sh, dx, dy, dw, dh);
}
};
CanvasRenderer.prototype.clip = function (shapes, callback, context) {
this.ctx.save();
shapes.filter(hasEntries).forEach(function (shape) {
this.shape(shape).clip();
}, this);
callback.call(context);
this.ctx.restore();
};
CanvasRenderer.prototype.shape = function (shape) {
this.ctx.beginPath();
shape.forEach(function (point, index) {
if (point[0] === "rect") {
this.ctx.rect.apply(this.ctx, point.slice(1));
} else {
this.ctx[index === 0 ? "moveTo" : point[0] + "To"].apply(this.ctx, point.slice(1));
}
}, this);
this.ctx.closePath();
return this.ctx;
};
CanvasRenderer.prototype.font = function (color, style, variant, weight, size, family) {
this.setFillStyle(color).font = [style, variant, weight, size, family].join(" ").split(",")[0];
};
CanvasRenderer.prototype.fontShadow = function (color, offsetX, offsetY, blur) {
this.setVariable("shadowColor", color.toString()).setVariable("shadowOffsetY", offsetX).setVariable("shadowOffsetX", offsetY).setVariable("shadowBlur", blur);
};
CanvasRenderer.prototype.clearShadow = function () {
this.setVariable("shadowColor", "rgba(0,0,0,0)");
};
CanvasRenderer.prototype.setOpacity = function (opacity) {
this.ctx.globalAlpha = opacity;
};
CanvasRenderer.prototype.setTransform = function (transform) {
this.ctx.translate(transform.origin[0], transform.origin[1]);
this.ctx.transform.apply(this.ctx, transform.matrix);
this.ctx.translate(-transform.origin[0], -transform.origin[1]);
};
CanvasRenderer.prototype.setVariable = function (property, value) {
if (this.variables[property] !== value) {
this.variables[property] = this.ctx[property] = value;
}
return this;
};
CanvasRenderer.prototype.text = function (text, left, bottom) {
this.ctx.fillText(text, left, bottom);
};
CanvasRenderer.prototype.backgroundRepeatShape = function (imageContainer, backgroundPosition, size, bounds, left, top, width, height, borderData) {
var shape = [["line", Math.round(left), Math.round(top)], ["line", Math.round(left + width), Math.round(top)], ["line", Math.round(left + width), Math.round(height + top)], ["line", Math.round(left), Math.round(height + top)]];
this.clip([shape], function () {
this.renderBackgroundRepeat(imageContainer, backgroundPosition, size, bounds, borderData[3], borderData[0]);
}, this);
};
CanvasRenderer.prototype.renderBackgroundRepeat = function (imageContainer, backgroundPosition, size, bounds, borderLeft, borderTop) {
var offsetX = Math.round(bounds.left + backgroundPosition.left + borderLeft),
offsetY = Math.round(bounds.top + backgroundPosition.top + borderTop);
this.setFillStyle(this.ctx.createPattern(this.resizeImage(imageContainer, size), "repeat"));
this.ctx.translate(offsetX, offsetY);
this.ctx.fill();
this.ctx.translate(-offsetX, -offsetY);
};
CanvasRenderer.prototype.renderBackgroundGradient = function (gradientImage, bounds) {
if (gradientImage instanceof LinearGradientContainer) {
var gradient = this.ctx.createLinearGradient(bounds.left + bounds.width * gradientImage.x0, bounds.top + bounds.height * gradientImage.y0, bounds.left + bounds.width * gradientImage.x1, bounds.top + bounds.height * gradientImage.y1);
gradientImage.colorStops.forEach(function (colorStop) {
gradient.addColorStop(colorStop.stop, colorStop.color.toString());
});
this.rectangle(bounds.left, bounds.top, bounds.width, bounds.height, gradient);
}
};
CanvasRenderer.prototype.resizeImage = function (imageContainer, size) {
var image = imageContainer.image;
if (image.width === size.width && image.height === size.height) {
return image;
}
var ctx,
canvas = document.createElement('canvas');
canvas.width = size.width;
canvas.height = size.height;
ctx = canvas.getContext("2d");
ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, size.width, size.height);
return canvas;
};
function hasEntries(array) {
return array.length > 0;
}
module.exports = CanvasRenderer;
}, {
"../lineargradientcontainer": 12,
"../log": 13,
"../renderer": 19
}],
21: [function (_dereq_, module, exports) {
var NodeContainer = _dereq_('./nodecontainer');
function StackingContext(hasOwnStacking, opacity, element, parent) {
NodeContainer.call(this, element, parent);
this.ownStacking = hasOwnStacking;
this.contexts = [];
this.children = [];
this.opacity = (this.parent ? this.parent.stack.opacity : 1) * opacity;
}
StackingContext.prototype = Object.create(NodeContainer.prototype);
StackingContext.prototype.getParentStack = function (context) {
var parentStack = this.parent ? this.parent.stack : null;
return parentStack ? parentStack.ownStacking ? parentStack : parentStack.getParentStack(context) : context.stack;
};
module.exports = StackingContext;
}, {
"./nodecontainer": 14
}],
22: [function (_dereq_, module, exports) {
function Support(document) {
this.rangeBounds = this.testRangeBounds(document);
this.cors = this.testCORS();
this.svg = this.testSVG();
}
Support.prototype.testRangeBounds = function (document) {
var range,
testElement,
rangeBounds,
rangeHeight,
support = false;
if (document.createRange) {
range = document.createRange();
if (range.getBoundingClientRect) {
testElement = document.createElement('boundtest');
testElement.style.height = "123px";
testElement.style.display = "block";
document.body.appendChild(testElement);
range.selectNode(testElement);
rangeBounds = range.getBoundingClientRect();
rangeHeight = rangeBounds.height;
if (rangeHeight === 123) {
support = true;
}
document.body.removeChild(testElement);
}
}
return support;
};
Support.prototype.testCORS = function () {
return typeof new Image().crossOrigin !== "undefined";
};
Support.prototype.testSVG = function () {
var img = new Image();
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
img.src = "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>";
try {
ctx.drawImage(img, 0, 0);
canvas.toDataURL();
} catch (e) {
return false;
}
return true;
};
module.exports = Support;
}, {}],
23: [function (_dereq_, module, exports) {
var XHR = _dereq_('./xhr');
var decode64 = _dereq_('./utils').decode64;
function SVGContainer(src) {
this.src = src;
this.image = null;
var self = this;
this.promise = this.hasFabric().then(function () {
return self.isInline(src) ? Promise.resolve(self.inlineFormatting(src)) : XHR(src);
}).then(function (svg) {
return new Promise(function (resolve) {
window.html2canvas.svg.fabric.loadSVGFromString(svg, self.createCanvas.call(self, resolve));
});
});
}
SVGContainer.prototype.hasFabric = function () {
return !window.html2canvas.svg || !window.html2canvas.svg.fabric ? Promise.reject(new Error("html2canvas.svg.js is not loaded, cannot render svg")) : Promise.resolve();
};
SVGContainer.prototype.inlineFormatting = function (src) {
return /^data:image\/svg\+xml;base64,/.test(src) ? this.decode64(this.removeContentType(src)) : this.removeContentType(src);
};
SVGContainer.prototype.removeContentType = function (src) {
return src.replace(/^data:image\/svg\+xml(;base64)?,/, '');
};
SVGContainer.prototype.isInline = function (src) {
return /^data:image\/svg\+xml/i.test(src);
};
SVGContainer.prototype.createCanvas = function (resolve) {
var self = this;
return function (objects, options) {
var canvas = new window.html2canvas.svg.fabric.StaticCanvas('c');
self.image = canvas.lowerCanvasEl;
canvas.setWidth(options.width).setHeight(options.height).add(window.html2canvas.svg.fabric.util.groupSVGElements(objects, options)).renderAll();
resolve(canvas.lowerCanvasEl);
};
};
SVGContainer.prototype.decode64 = function (str) {
return typeof window.atob === "function" ? window.atob(str) : decode64(str);
};
module.exports = SVGContainer;
}, {
"./utils": 26,
"./xhr": 28
}],
24: [function (_dereq_, module, exports) {
var SVGContainer = _dereq_('./svgcontainer');
function SVGNodeContainer(node, _native) {
this.src = node;
this.image = null;
var self = this;
this.promise = _native ? new Promise(function (resolve, reject) {
self.image = new Image();
self.image.onload = resolve;
self.image.onerror = reject;
self.image.src = "data:image/svg+xml," + new XMLSerializer().serializeToString(node);
if (self.image.complete === true) {
resolve(self.image);
}
}) : this.hasFabric().then(function () {
return new Promise(function (resolve) {
window.html2canvas.svg.fabric.parseSVGDocument(node, self.createCanvas.call(self, resolve));
});
});
}
SVGNodeContainer.prototype = Object.create(SVGContainer.prototype);
module.exports = SVGNodeContainer;
}, {
"./svgcontainer": 23
}],
25: [function (_dereq_, module, exports) {
var NodeContainer = _dereq_('./nodecontainer');
function TextContainer(node, parent) {
NodeContainer.call(this, node, parent);
}
TextContainer.prototype = Object.create(NodeContainer.prototype);
TextContainer.prototype.applyTextTransform = function () {
this.node.data = this.transform(this.parent.css("textTransform"));
};
TextContainer.prototype.transform = function (transform) {
var text = this.node.data;
switch (transform) {
case "lowercase":
return text.toLowerCase();
case "capitalize":
return text.replace(/(^|\s|:|-|\(|\))([a-z])/g, capitalize);
case "uppercase":
return text.toUpperCase();
default:
return text;
}
};
function capitalize(m, p1, p2) {
if (m.length > 0) {
return p1 + p2.toUpperCase();
}
}
module.exports = TextContainer;
}, {
"./nodecontainer": 14
}],
26: [function (_dereq_, module, exports) {
exports.smallImage = function smallImage() {
return "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
};
exports.bind = function (callback, context) {
return function () {
return callback.apply(context, arguments);
};
};
/*
* base64-arraybuffer
* https://github.com/niklasvh/base64-arraybuffer
*
* Copyright (c) 2012 Niklas von Hertzen
* Licensed under the MIT license.
*/
exports.decode64 = function (base64) {
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var len = base64.length,
i,
encoded1,
encoded2,
encoded3,
encoded4,
byte1,
byte2,
byte3;
var output = "";
for (i = 0; i < len; i += 4) {
encoded1 = chars.indexOf(base64[i]);
encoded2 = chars.indexOf(base64[i + 1]);
encoded3 = chars.indexOf(base64[i + 2]);
encoded4 = chars.indexOf(base64[i + 3]);
byte1 = encoded1 << 2 | encoded2 >> 4;
byte2 = (encoded2 & 15) << 4 | encoded3 >> 2;
byte3 = (encoded3 & 3) << 6 | encoded4;
if (encoded3 === 64) {
output += String.fromCharCode(byte1);
} else if (encoded4 === 64 || encoded4 === -1) {
output += String.fromCharCode(byte1, byte2);
} else {
output += String.fromCharCode(byte1, byte2, byte3);
}
}
return output;
};
exports.getBounds = function (node) {
if (node.getBoundingClientRect) {
var clientRect = node.getBoundingClientRect();
var width = node.offsetWidth == null ? clientRect.width : node.offsetWidth;
return {
top: clientRect.top,
bottom: clientRect.bottom || clientRect.top + clientRect.height,
right: clientRect.left + width,
left: clientRect.left,
width: width,
height: node.offsetHeight == null ? clientRect.height : node.offsetHeight
};
}
return {};
};
exports.offsetBounds = function (node) {
var parent = node.offsetParent ? exports.offsetBounds(node.offsetParent) : {
top: 0,
left: 0
};
return {
top: node.offsetTop + parent.top,
bottom: node.offsetTop + node.offsetHeight + parent.top,
right: node.offsetLeft + parent.left + node.offsetWidth,
left: node.offsetLeft + parent.left,
width: node.offsetWidth,
height: node.offsetHeight
};
};
exports.parseBackgrounds = function (backgroundImage) {
var whitespace = ' \r\n\t',
method,
definition,
prefix,
prefix_i,
block,
results = [],
mode = 0,
numParen = 0,
quote,
args;
var appendResult = function appendResult() {
if (method) {
if (definition.substr(0, 1) === '"') {
definition = definition.substr(1, definition.length - 2);
}
if (definition) {
args.push(definition);
}
if (method.substr(0, 1) === '-' && (prefix_i = method.indexOf('-', 1) + 1) > 0) {
prefix = method.substr(0, prefix_i);
method = method.substr(prefix_i);
}
results.push({
prefix: prefix,
method: method.toLowerCase(),
value: block,
args: args,
image: null
});
}
args = [];
method = prefix = definition = block = '';
};
args = [];
method = prefix = definition = block = '';
backgroundImage.split("").forEach(function (c) {
if (mode === 0 && whitespace.indexOf(c) > -1) {
return;
}
switch (c) {
case '"':
if (!quote) {
quote = c;
} else if (quote === c) {
quote = null;
}
break;
case '(':
if (quote) {
break;
} else if (mode === 0) {
mode = 1;
block += c;
return;
} else {
numParen++;
}
break;
case ')':
if (quote) {
break;
} else if (mode === 1) {
if (numParen === 0) {
mode = 0;
block += c;
appendResult();
return;
} else {
numParen--;
}
}
break;
case ',':
if (quote) {
break;
} else if (mode === 0) {
appendResult();
return;
} else if (mode === 1) {
if (numParen === 0 && !method.match(/^url$/i)) {
args.push(definition);
definition = '';
block += c;
return;
}
}
break;
}
block += c;
if (mode === 0) {
method += c;
} else {
definition += c;
}
});
appendResult();
return results;
};
}, {}],
27: [function (_dereq_, module, exports) {
var GradientContainer = _dereq_('./gradientcontainer');
function WebkitGradientContainer(imageData) {
GradientContainer.apply(this, arguments);
this.type = imageData.args[0] === "linear" ? GradientContainer.TYPES.LINEAR : GradientContainer.TYPES.RADIAL;
}
WebkitGradientContainer.prototype = Object.create(GradientContainer.prototype);
module.exports = WebkitGradientContainer;
}, {
"./gradientcontainer": 9
}],
28: [function (_dereq_, module, exports) {
function XHR(url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = function () {
if (xhr.status === 200) {
resolve(xhr.responseText);
} else {
reject(new Error(xhr.statusText));
}
};
xhr.onerror = function () {
reject(new Error("Network Error"));
};
xhr.send();
});
}
module.exports = XHR;
}, {}]
}, {}, [4])(4);
});
});
/*
Based on rgbcolor.js by Stoyan Stefanov <sstoo@gmail.com>
http://www.phpied.com/rgb-color-parser-in-javascript/
*/
var rgbcolor = function rgbcolor(color_string) {
this.ok = false;
this.alpha = 1.0; // strip any leading #
if (color_string.charAt(0) == '#') {
// remove # if any
color_string = color_string.substr(1, 6);
}
color_string = color_string.replace(/ /g, '');
color_string = color_string.toLowerCase(); // before getting into regexps, try simple matches
// and overwrite the input
var simple_colors = {
aliceblue: 'f0f8ff',
antiquewhite: 'faebd7',
aqua: '00ffff',
aquamarine: '7fffd4',
azure: 'f0ffff',
beige: 'f5f5dc',
bisque: 'ffe4c4',
black: '000000',
blanchedalmond: 'ffebcd',
blue: '0000ff',
blueviolet: '8a2be2',
brown: 'a52a2a',
burlywood: 'deb887',
cadetblue: '5f9ea0',
chartreuse: '7fff00',
chocolate: 'd2691e',
coral: 'ff7f50',
cornflowerblue: '6495ed',
cornsilk: 'fff8dc',
crimson: 'dc143c',
cyan: '00ffff',
darkblue: '00008b',
darkcyan: '008b8b',
darkgoldenrod: 'b8860b',
darkgray: 'a9a9a9',
darkgreen: '006400',
darkkhaki: 'bdb76b',
darkmagenta: '8b008b',
darkolivegreen: '556b2f',
darkorange: 'ff8c00',
darkorchid: '9932cc',
darkred: '8b0000',
darksalmon: 'e9967a',
darkseagreen: '8fbc8f',
darkslateblue: '483d8b',
darkslategray: '2f4f4f',
darkturquoise: '00ced1',
darkviolet: '9400d3',
deeppink: 'ff1493',
deepskyblue: '00bfff',
dimgray: '696969',
dodgerblue: '1e90ff',
feldspar: 'd19275',
firebrick: 'b22222',
floralwhite: 'fffaf0',
forestgreen: '228b22',
fuchsia: 'ff00ff',
gainsboro: 'dcdcdc',
ghostwhite: 'f8f8ff',
gold: 'ffd700',
goldenrod: 'daa520',
gray: '808080',
green: '008000',
greenyellow: 'adff2f',
honeydew: 'f0fff0',
hotpink: 'ff69b4',
indianred: 'cd5c5c',
indigo: '4b0082',
ivory: 'fffff0',
khaki: 'f0e68c',
lavender: 'e6e6fa',
lavenderblush: 'fff0f5',
lawngreen: '7cfc00',
lemonchiffon: 'fffacd',
lightblue: 'add8e6',
lightcoral: 'f08080',
lightcyan: 'e0ffff',
lightgoldenrodyellow: 'fafad2',
lightgrey: 'd3d3d3',
lightgreen: '90ee90',
lightpink: 'ffb6c1',
lightsalmon: 'ffa07a',
lightseagreen: '20b2aa',
lightskyblue: '87cefa',
lightslateblue: '8470ff',
lightslategray: '778899',
lightsteelblue: 'b0c4de',
lightyellow: 'ffffe0',
lime: '00ff00',
limegreen: '32cd32',
linen: 'faf0e6',
magenta: 'ff00ff',
maroon: '800000',
mediumaquamarine: '66cdaa',
mediumblue: '0000cd',
mediumorchid: 'ba55d3',
mediumpurple: '9370d8',
mediumseagreen: '3cb371',
mediumslateblue: '7b68ee',
mediumspringgreen: '00fa9a',
mediumturquoise: '48d1cc',
mediumvioletred: 'c71585',
midnightblue: '191970',
mintcream: 'f5fffa',
mistyrose: 'ffe4e1',
moccasin: 'ffe4b5',
navajowhite: 'ffdead',
navy: '000080',
oldlace: 'fdf5e6',
olive: '808000',
olivedrab: '6b8e23',
orange: 'ffa500',
orangered: 'ff4500',
orchid: 'da70d6',
palegoldenrod: 'eee8aa',
palegreen: '98fb98',
paleturquoise: 'afeeee',
palevioletred: 'd87093',
papayawhip: 'ffefd5',
peachpuff: 'ffdab9',
peru: 'cd853f',
pink: 'ffc0cb',
plum: 'dda0dd',
powderblue: 'b0e0e6',
purple: '800080',
red: 'ff0000',
rosybrown: 'bc8f8f',
royalblue: '4169e1',
saddlebrown: '8b4513',
salmon: 'fa8072',
sandybrown: 'f4a460',
seagreen: '2e8b57',
seashell: 'fff5ee',
sienna: 'a0522d',
silver: 'c0c0c0',
skyblue: '87ceeb',
slateblue: '6a5acd',
slategray: '708090',
snow: 'fffafa',
springgreen: '00ff7f',
steelblue: '4682b4',
tan: 'd2b48c',
teal: '008080',
thistle: 'd8bfd8',
tomato: 'ff6347',
turquoise: '40e0d0',
violet: 'ee82ee',
violetred: 'd02090',
wheat: 'f5deb3',
white: 'ffffff',
whitesmoke: 'f5f5f5',
yellow: 'ffff00',
yellowgreen: '9acd32'
};
color_string = simple_colors[color_string] || color_string; // emd of simple type-in colors
// array of color definition objects
var color_defs = [{
re: /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*((?:\d?\.)?\d)\)$/,
example: ['rgba(123, 234, 45, 0.8)', 'rgba(255,234,245,1.0)'],
process: function process(bits) {
return [parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3]), parseFloat(bits[4])];
}
}, {
re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
process: function process(bits) {
return [parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3])];
}
}, {
re: /^(\w{2})(\w{2})(\w{2})$/,
example: ['#00ff00', '336699'],
process: function process(bits) {
return [parseInt(bits[1], 16), parseInt(bits[2], 16), parseInt(bits[3], 16)];
}
}, {
re: /^(\w{1})(\w{1})(\w{1})$/,
example: ['#fb0', 'f0f'],
process: function process(bits) {
return [parseInt(bits[1] + bits[1], 16), parseInt(bits[2] + bits[2], 16), parseInt(bits[3] + bits[3], 16)];
}
}]; // search through the definitions to find a match
for (var i = 0; i < color_defs.length; i++) {
var re = color_defs[i].re;
var processor = color_defs[i].process;
var bits = re.exec(color_string);
if (bits) {
var channels = processor(bits);
this.r = channels[0];
this.g = channels[1];
this.b = channels[2];
if (channels.length > 3) {
this.alpha = channels[3];
}
this.ok = true;
}
} // validate/cleanup values
this.r = this.r < 0 || isNaN(this.r) ? 0 : this.r > 255 ? 255 : this.r;
this.g = this.g < 0 || isNaN(this.g) ? 0 : this.g > 255 ? 255 : this.g;
this.b = this.b < 0 || isNaN(this.b) ? 0 : this.b > 255 ? 255 : this.b;
this.alpha = this.alpha < 0 ? 0 : this.alpha > 1.0 || isNaN(this.alpha) ? 1.0 : this.alpha; // some getters
this.toRGB = function () {
return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
};
this.toRGBA = function () {
return 'rgba(' + this.r + ', ' + this.g + ', ' + this.b + ', ' + this.alpha + ')';
};
this.toHex = function () {
var r = this.r.toString(16);
var g = this.g.toString(16);
var b = this.b.toString(16);
if (r.length == 1) r = '0' + r;
if (g.length == 1) g = '0' + g;
if (b.length == 1) b = '0' + b;
return '#' + r + g + b;
}; // help
this.getHelpXML = function () {
var examples = new Array(); // add regexps
for (var i = 0; i < color_defs.length; i++) {
var example = color_defs[i].example;
for (var j = 0; j < example.length; j++) {
examples[examples.length] = example[j];
}
} // add type-in colors
for (var sc in simple_colors) {
examples[examples.length] = sc;
}
var xml = document.createElement('ul');
xml.setAttribute('id', 'rgbcolor-examples');
for (var i = 0; i < examples.length; i++) {
try {
var list_item = document.createElement('li');
var list_color = new RGBColor(examples[i]);
var example_div = document.createElement('div');
example_div.style.cssText = 'margin: 3px; ' + 'border: 1px solid black; ' + 'background:' + list_color.toHex() + '; ' + 'color:' + list_color.toHex();
example_div.appendChild(document.createTextNode('test'));
var list_item_value = document.createTextNode(' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex());
list_item.appendChild(example_div);
list_item.appendChild(list_item_value);
xml.appendChild(list_item);
} catch (e) {}
}
return xml;
};
};
/*
StackBlur - a fast almost Gaussian Blur For Canvas
Version: 0.5
Author: Mario Klingemann
Contact: mario@quasimondo.com
Website: http://www.quasimondo.com/StackBlurForCanvas
Twitter: @quasimondo
In case you find this class useful - especially in commercial projects -
I am not totally unhappy for a small donation to my PayPal account
mario@quasimondo.de
Or support me on flattr:
https://flattr.com/thing/72791/StackBlur-a-fast-almost-Gaussian-Blur-Effect-for-CanvasJavascript
Copyright (c) 2010 Mario Klingemann
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
var mul_table = [512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259];
var shg_table = [9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24];
function blur(pixels, width, height, radius) {
if (isNaN(radius) || radius < 1) return;
radius |= 0;
var x, y, i, p, yp, yi, yw, r_sum, g_sum, b_sum, a_sum, r_out_sum, g_out_sum, b_out_sum, a_out_sum, r_in_sum, g_in_sum, b_in_sum, a_in_sum, pr, pg, pb, pa, rbs;
var div = radius + radius + 1;
var widthMinus1 = width - 1;
var heightMinus1 = height - 1;
var radiusPlus1 = radius + 1;
var sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2;
var stackStart = new BlurStack();
var stack = stackStart;
for (i = 1; i < div; i++) {
stack = stack.next = new BlurStack();
if (i == radiusPlus1) var stackEnd = stack;
}
stack.next = stackStart;
var stackIn = null;
var stackOut = null;
yw = yi = 0;
var mul_sum = mul_table[radius];
var shg_sum = shg_table[radius];
for (y = 0; y < height; y++) {
r_in_sum = g_in_sum = b_in_sum = a_in_sum = r_sum = g_sum = b_sum = a_sum = 0;
r_out_sum = radiusPlus1 * (pr = pixels[yi]);
g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]);
b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]);
a_out_sum = radiusPlus1 * (pa = pixels[yi + 3]);
r_sum += sumFactor * pr;
g_sum += sumFactor * pg;
b_sum += sumFactor * pb;
a_sum += sumFactor * pa;
stack = stackStart;
for (i = 0; i < radiusPlus1; i++) {
stack.r = pr;
stack.g = pg;
stack.b = pb;
stack.a = pa;
stack = stack.next;
}
for (i = 1; i < radiusPlus1; i++) {
p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2);
r_sum += (stack.r = pr = pixels[p]) * (rbs = radiusPlus1 - i);
g_sum += (stack.g = pg = pixels[p + 1]) * rbs;
b_sum += (stack.b = pb = pixels[p + 2]) * rbs;
a_sum += (stack.a = pa = pixels[p + 3]) * rbs;
r_in_sum += pr;
g_in_sum += pg;
b_in_sum += pb;
a_in_sum += pa;
stack = stack.next;
}
stackIn = stackStart;
stackOut = stackEnd;
for (x = 0; x < width; x++) {
pixels[yi + 3] = pa = a_sum * mul_sum >> shg_sum;
if (pa != 0) {
pa = 255 / pa;
pixels[yi] = (r_sum * mul_sum >> shg_sum) * pa;
pixels[yi + 1] = (g_sum * mul_sum >> shg_sum) * pa;
pixels[yi + 2] = (b_sum * mul_sum >> shg_sum) * pa;
} else {
pixels[yi] = pixels[yi + 1] = pixels[yi + 2] = 0;
}
r_sum -= r_out_sum;
g_sum -= g_out_sum;
b_sum -= b_out_sum;
a_sum -= a_out_sum;
r_out_sum -= stackIn.r;
g_out_sum -= stackIn.g;
b_out_sum -= stackIn.b;
a_out_sum -= stackIn.a;
p = yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1) << 2;
r_in_sum += stackIn.r = pixels[p];
g_in_sum += stackIn.g = pixels[p + 1];
b_in_sum += stackIn.b = pixels[p + 2];
a_in_sum += stackIn.a = pixels[p + 3];
r_sum += r_in_sum;
g_sum += g_in_sum;
b_sum += b_in_sum;
a_sum += a_in_sum;
stackIn = stackIn.next;
r_out_sum += pr = stackOut.r;
g_out_sum += pg = stackOut.g;
b_out_sum += pb = stackOut.b;
a_out_sum += pa = stackOut.a;
r_in_sum -= pr;
g_in_sum -= pg;
b_in_sum -= pb;
a_in_sum -= pa;
stackOut = stackOut.next;
yi += 4;
}
yw += width;
}
for (x = 0; x < width; x++) {
g_in_sum = b_in_sum = a_in_sum = r_in_sum = g_sum = b_sum = a_sum = r_sum = 0;
yi = x << 2;
r_out_sum = radiusPlus1 * (pr = pixels[yi]);
g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]);
b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]);
a_out_sum = radiusPlus1 * (pa = pixels[yi + 3]);
r_sum += sumFactor * pr;
g_sum += sumFactor * pg;
b_sum += sumFactor * pb;
a_sum += sumFactor * pa;
stack = stackStart;
for (i = 0; i < radiusPlus1; i++) {
stack.r = pr;
stack.g = pg;
stack.b = pb;
stack.a = pa;
stack = stack.next;
}
yp = width;
for (i = 1; i <= radius; i++) {
yi = yp + x << 2;
r_sum += (stack.r = pr = pixels[yi]) * (rbs = radiusPlus1 - i);
g_sum += (stack.g = pg = pixels[yi + 1]) * rbs;
b_sum += (stack.b = pb = pixels[yi + 2]) * rbs;
a_sum += (stack.a = pa = pixels[yi + 3]) * rbs;
r_in_sum += pr;
g_in_sum += pg;
b_in_sum += pb;
a_in_sum += pa;
stack = stack.next;
if (i < heightMinus1) {
yp += width;
}
}
yi = x;
stackIn = stackStart;
stackOut = stackEnd;
for (y = 0; y < height; y++) {
p = yi << 2;
pixels[p + 3] = pa = a_sum * mul_sum >> shg_sum;
if (pa > 0) {
pa = 255 / pa;
pixels[p] = (r_sum * mul_sum >> shg_sum) * pa;
pixels[p + 1] = (g_sum * mul_sum >> shg_sum) * pa;
pixels[p + 2] = (b_sum * mul_sum >> shg_sum) * pa;
} else {
pixels[p] = pixels[p + 1] = pixels[p + 2] = 0;
}
r_sum -= r_out_sum;
g_sum -= g_out_sum;
b_sum -= b_out_sum;
a_sum -= a_out_sum;
r_out_sum -= stackIn.r;
g_out_sum -= stackIn.g;
b_out_sum -= stackIn.b;
a_out_sum -= stackIn.a;
p = x + ((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width << 2;
r_sum += r_in_sum += stackIn.r = pixels[p];
g_sum += g_in_sum += stackIn.g = pixels[p + 1];
b_sum += b_in_sum += stackIn.b = pixels[p + 2];
a_sum += a_in_sum += stackIn.a = pixels[p + 3];
stackIn = stackIn.next;
r_out_sum += pr = stackOut.r;
g_out_sum += pg = stackOut.g;
b_out_sum += pb = stackOut.b;
a_out_sum += pa = stackOut.a;
r_in_sum -= pr;
g_in_sum -= pg;
b_in_sum -= pb;
a_in_sum -= pa;
stackOut = stackOut.next;
yi += width;
}
}
}
function BlurStack() {
this.r = 0;
this.g = 0;
this.b = 0;
this.a = 0;
this.next = null;
}
var stackblur = blur;
//[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
//[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
//[5] Name ::= NameStartChar (NameChar)*
var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/; //\u10000-\uEFFFF
var nameChar = new RegExp("[\\-\\.0-9" + nameStartChar.source.slice(1, -1) + "\\u00B7\\u0300-\\u036F\\u203F-\\u2040]");
var tagNamePattern = new RegExp('^' + nameStartChar.source + nameChar.source + '*(?:\:' + nameStartChar.source + nameChar.source + '*)?$'); //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
//var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',')
//S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
//S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
var S_TAG = 0; //tag name offerring
var S_ATTR = 1; //attr name offerring
var S_ATTR_SPACE = 2; //attr name end and space offer
var S_EQ = 3; //=space?
var S_ATTR_NOQUOT_VALUE = 4; //attr value(no quot value only)
var S_ATTR_END = 5; //attr value end and no space(quot end)
var S_TAG_SPACE = 6; //(attr value end || tag end ) && (space offer)
var S_TAG_CLOSE = 7; //closed el<el />
function XMLReader() {}
XMLReader.prototype = {
parse: function parse(source, defaultNSMap, entityMap) {
var domBuilder = this.domBuilder;
domBuilder.startDocument();
_copy(defaultNSMap, defaultNSMap = {});
_parse(source, defaultNSMap, entityMap, domBuilder, this.errorHandler);
domBuilder.endDocument();
}
};
function _parse(source, defaultNSMapCopy, entityMap, domBuilder, errorHandler) {
function fixedFromCharCode(code) {
// String.prototype.fromCharCode does not supports
// > 2 bytes unicode chars directly
if (code > 0xffff) {
code -= 0x10000;
var surrogate1 = 0xd800 + (code >> 10),
surrogate2 = 0xdc00 + (code & 0x3ff);
return String.fromCharCode(surrogate1, surrogate2);
} else {
return String.fromCharCode(code);
}
}
function entityReplacer(a) {
var k = a.slice(1, -1);
if (k in entityMap) {
return entityMap[k];
} else if (k.charAt(0) === '#') {
return fixedFromCharCode(parseInt(k.substr(1).replace('x', '0x')));
} else {
errorHandler.error('entity not found:' + a);
return a;
}
}
function appendText(end) {
//has some bugs
if (end > start) {
var xt = source.substring(start, end).replace(/&#?\w+;/g, entityReplacer);
locator && position(start);
domBuilder.characters(xt, 0, end - start);
start = end;
}
}
function position(p, m) {
while (p >= lineEnd && (m = linePattern.exec(source))) {
lineStart = m.index;
lineEnd = lineStart + m[0].length;
locator.lineNumber++; //console.log('line++:',locator,startPos,endPos)
}
locator.columnNumber = p - lineStart + 1;
}
var lineStart = 0;
var lineEnd = 0;
var linePattern = /.*(?:\r\n?|\n)|.*$/g;
var locator = domBuilder.locator;
var parseStack = [{
currentNSMap: defaultNSMapCopy
}];
var closeMap = {};
var start = 0;
while (true) {
try {
var tagStart = source.indexOf('<', start);
if (tagStart < 0) {
if (!source.substr(start).match(/^\s*$/)) {
var doc = domBuilder.doc;
var text = doc.createTextNode(source.substr(start));
doc.appendChild(text);
domBuilder.currentElement = text;
}
return;
}
if (tagStart > start) {
appendText(tagStart);
}
switch (source.charAt(tagStart + 1)) {
case '/':
var end = source.indexOf('>', tagStart + 3);
var tagName = source.substring(tagStart + 2, end);
var config = parseStack.pop();
if (end < 0) {
tagName = source.substring(tagStart + 2).replace(/[\s<].*/, ''); //console.error('#@@@@@@'+tagName)
errorHandler.error("end tag name: " + tagName + ' is not complete:' + config.tagName);
end = tagStart + 1 + tagName.length;
} else if (tagName.match(/\s</)) {
tagName = tagName.replace(/[\s<].*/, '');
errorHandler.error("end tag name: " + tagName + ' maybe not complete');
end = tagStart + 1 + tagName.length;
} //console.error(parseStack.length,parseStack)
//console.error(config);
var localNSMap = config.localNSMap;
var endMatch = config.tagName == tagName;
var endIgnoreCaseMach = endMatch || config.tagName && config.tagName.toLowerCase() == tagName.toLowerCase();
if (endIgnoreCaseMach) {
domBuilder.endElement(config.uri, config.localName, tagName);
if (localNSMap) {
for (var prefix in localNSMap) {
domBuilder.endPrefixMapping(prefix);
}
}
if (!endMatch) {
errorHandler.fatalError("end tag name: " + tagName + ' is not match the current start tagName:' + config.tagName);
}
} else {
parseStack.push(config);
}
end++;
break;
// end elment
case '?':
// <?...?>
locator && position(tagStart);
end = parseInstruction(source, tagStart, domBuilder);
break;
case '!':
// <!doctype,<![CDATA,<!--
locator && position(tagStart);
end = parseDCC(source, tagStart, domBuilder, errorHandler);
break;
default:
locator && position(tagStart);
var el = new ElementAttributes();
var currentNSMap = parseStack[parseStack.length - 1].currentNSMap; //elStartEnd
var end = parseElementStartPart(source, tagStart, el, currentNSMap, entityReplacer, errorHandler);
var len = el.length;
if (!el.closed && fixSelfClosed(source, end, el.tagName, closeMap)) {
el.closed = true;
if (!entityMap.nbsp) {
errorHandler.warning('unclosed xml attribute');
}
}
if (locator && len) {
var locator2 = copyLocator(locator, {}); //try{//attribute position fixed
for (var i = 0; i < len; i++) {
var a = el[i];
position(a.offset);
a.locator = copyLocator(locator, {});
} //}catch(e){console.error('@@@@@'+e)}
domBuilder.locator = locator2;
if (appendElement(el, domBuilder, currentNSMap)) {
parseStack.push(el);
}
domBuilder.locator = locator;
} else {
if (appendElement(el, domBuilder, currentNSMap)) {
parseStack.push(el);
}
}
if (el.uri === 'http://www.w3.org/1999/xhtml' && !el.closed) {
end = parseHtmlSpecialContent(source, end, el.tagName, entityReplacer, domBuilder);
} else {
end++;
}
}
} catch (e) {
errorHandler.error('element parse error: ' + e); //errorHandler.error('element parse error: '+e);
end = -1; //throw e;
}
if (end > start) {
start = end;
} else {
//TODO: 这里有可能sax回退有位置错误风险
appendText(Math.max(tagStart, start) + 1);
}
}
}
function copyLocator(f, t) {
t.lineNumber = f.lineNumber;
t.columnNumber = f.columnNumber;
return t;
}
/**
* @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
* @return end of the elementStartPart(end of elementEndPart for selfClosed el)
*/
function parseElementStartPart(source, start, el, currentNSMap, entityReplacer, errorHandler) {
var attrName;
var value;
var p = ++start;
var s = S_TAG; //status
while (true) {
var c = source.charAt(p);
switch (c) {
case '=':
if (s === S_ATTR) {
//attrName
attrName = source.slice(start, p);
s = S_EQ;
} else if (s === S_ATTR_SPACE) {
s = S_EQ;
} else {
//fatalError: equal must after attrName or space after attrName
throw new Error('attribute equal must after attrName');
}
break;
case '\'':
case '"':
if (s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE
) {
//equal
if (s === S_ATTR) {
errorHandler.warning('attribute value must after "="');
attrName = source.slice(start, p);
}
start = p + 1;
p = source.indexOf(c, start);
if (p > 0) {
value = source.slice(start, p).replace(/&#?\w+;/g, entityReplacer);
el.add(attrName, value, start - 1);
s = S_ATTR_END;
} else {
//fatalError: no end quot match
throw new Error('attribute value no end \'' + c + '\' match');
}
} else if (s == S_ATTR_NOQUOT_VALUE) {
value = source.slice(start, p).replace(/&#?\w+;/g, entityReplacer); //console.log(attrName,value,start,p)
el.add(attrName, value, start); //console.dir(el)
errorHandler.warning('attribute "' + attrName + '" missed start quot(' + c + ')!!');
start = p + 1;
s = S_ATTR_END;
} else {
//fatalError: no equal before
throw new Error('attribute value must after "="');
}
break;
case '/':
switch (s) {
case S_TAG:
el.setTagName(source.slice(start, p));
case S_ATTR_END:
case S_TAG_SPACE:
case S_TAG_CLOSE:
s = S_TAG_CLOSE;
el.closed = true;
case S_ATTR_NOQUOT_VALUE:
case S_ATTR:
case S_ATTR_SPACE:
break;
//case S_EQ:
default:
throw new Error("attribute invalid close char('/')");
}
break;
case '':
//end document
//throw new Error('unexpected end of input')
errorHandler.error('unexpected end of input');
if (s == S_TAG) {
el.setTagName(source.slice(start, p));
}
return p;
case '>':
switch (s) {
case S_TAG:
el.setTagName(source.slice(start, p));
case S_ATTR_END:
case S_TAG_SPACE:
case S_TAG_CLOSE:
break;
//normal
case S_ATTR_NOQUOT_VALUE: //Compatible state
case S_ATTR:
value = source.slice(start, p);
if (value.slice(-1) === '/') {
el.closed = true;
value = value.slice(0, -1);
}
case S_ATTR_SPACE:
if (s === S_ATTR_SPACE) {
value = attrName;
}
if (s == S_ATTR_NOQUOT_VALUE) {
errorHandler.warning('attribute "' + value + '" missed quot(")!!');
el.add(attrName, value.replace(/&#?\w+;/g, entityReplacer), start);
} else {
if (currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !value.match(/^(?:disabled|checked|selected)$/i)) {
errorHandler.warning('attribute "' + value + '" missed value!! "' + value + '" instead!!');
}
el.add(value, value, start);
}
break;
case S_EQ:
throw new Error('attribute value missed!!');
} // console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
return p;
/*xml space '\x20' | #x9 | #xD | #xA; */
case "\x80":
c = ' ';
default:
if (c <= ' ') {
//space
switch (s) {
case S_TAG:
el.setTagName(source.slice(start, p)); //tagName
s = S_TAG_SPACE;
break;
case S_ATTR:
attrName = source.slice(start, p);
s = S_ATTR_SPACE;
break;
case S_ATTR_NOQUOT_VALUE:
var value = source.slice(start, p).replace(/&#?\w+;/g, entityReplacer);
errorHandler.warning('attribute "' + value + '" missed quot(")!!');
el.add(attrName, value, start);
case S_ATTR_END:
s = S_TAG_SPACE;
break;
//case S_TAG_SPACE:
//case S_EQ:
//case S_ATTR_SPACE:
// void();break;
//case S_TAG_CLOSE:
//ignore warning
}
} else {
//not space
//S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
//S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
switch (s) {
//case S_TAG:void();break;
//case S_ATTR:void();break;
//case S_ATTR_NOQUOT_VALUE:void();break;
case S_ATTR_SPACE:
var tagName = el.tagName;
if (currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !attrName.match(/^(?:disabled|checked|selected)$/i)) {
errorHandler.warning('attribute "' + attrName + '" missed value!! "' + attrName + '" instead2!!');
}
el.add(attrName, attrName, start);
start = p;
s = S_ATTR;
break;
case S_ATTR_END:
errorHandler.warning('attribute space is required"' + attrName + '"!!');
case S_TAG_SPACE:
s = S_ATTR;
start = p;
break;
case S_EQ:
s = S_ATTR_NOQUOT_VALUE;
start = p;
break;
case S_TAG_CLOSE:
throw new Error("elements closed character '/' and '>' must be connected to");
}
}
} //end outer switch
//console.log('p++',p)
p++;
}
}
/**
* @return true if has new namespace define
*/
function appendElement(el, domBuilder, currentNSMap) {
var tagName = el.tagName;
var localNSMap = null; //var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
var i = el.length;
while (i--) {
var a = el[i];
var qName = a.qName;
var value = a.value;
var nsp = qName.indexOf(':');
if (nsp > 0) {
var prefix = a.prefix = qName.slice(0, nsp);
var localName = qName.slice(nsp + 1);
var nsPrefix = prefix === 'xmlns' && localName;
} else {
localName = qName;
prefix = null;
nsPrefix = qName === 'xmlns' && '';
} //can not set prefix,because prefix !== ''
a.localName = localName; //prefix == null for no ns prefix attribute
if (nsPrefix !== false) {
//hack!!
if (localNSMap == null) {
localNSMap = {}; //console.log(currentNSMap,0)
_copy(currentNSMap, currentNSMap = {}); //console.log(currentNSMap,1)
}
currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
a.uri = 'http://www.w3.org/2000/xmlns/';
domBuilder.startPrefixMapping(nsPrefix, value);
}
}
var i = el.length;
while (i--) {
a = el[i];
var prefix = a.prefix;
if (prefix) {
//no prefix attribute has no namespace
if (prefix === 'xml') {
a.uri = 'http://www.w3.org/XML/1998/namespace';
}
if (prefix !== 'xmlns') {
a.uri = currentNSMap[prefix || '']; //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
}
}
}
var nsp = tagName.indexOf(':');
if (nsp > 0) {
prefix = el.prefix = tagName.slice(0, nsp);
localName = el.localName = tagName.slice(nsp + 1);
} else {
prefix = null; //important!!
localName = el.localName = tagName;
} //no prefix element has default namespace
var ns = el.uri = currentNSMap[prefix || ''];
domBuilder.startElement(ns, localName, tagName, el); //endPrefixMapping and startPrefixMapping have not any help for dom builder
//localNSMap = null
if (el.closed) {
domBuilder.endElement(ns, localName, tagName);
if (localNSMap) {
for (prefix in localNSMap) {
domBuilder.endPrefixMapping(prefix);
}
}
} else {
el.currentNSMap = currentNSMap;
el.localNSMap = localNSMap; //parseStack.push(el);
return true;
}
}
function parseHtmlSpecialContent(source, elStartEnd, tagName, entityReplacer, domBuilder) {
if (/^(?:script|textarea)$/i.test(tagName)) {
var elEndStart = source.indexOf('</' + tagName + '>', elStartEnd);
var text = source.substring(elStartEnd + 1, elEndStart);
if (/[&<]/.test(text)) {
if (/^script$/i.test(tagName)) {
//if(!/\]\]>/.test(text)){
//lexHandler.startCDATA();
domBuilder.characters(text, 0, text.length); //lexHandler.endCDATA();
return elEndStart; //}
} //}else{//text area
text = text.replace(/&#?\w+;/g, entityReplacer);
domBuilder.characters(text, 0, text.length);
return elEndStart; //}
}
}
return elStartEnd + 1;
}
function fixSelfClosed(source, elStartEnd, tagName, closeMap) {
//if(tagName in closeMap){
var pos = closeMap[tagName];
if (pos == null) {
//console.log(tagName)
pos = source.lastIndexOf('</' + tagName + '>');
if (pos < elStartEnd) {
//忘记闭合
pos = source.lastIndexOf('</' + tagName);
}
closeMap[tagName] = pos;
}
return pos < elStartEnd; //}
}
function _copy(source, target) {
for (var n in source) {
target[n] = source[n];
}
}
function parseDCC(source, start, domBuilder, errorHandler) {
//sure start with '<!'
var next = source.charAt(start + 2);
switch (next) {
case '-':
if (source.charAt(start + 3) === '-') {
var end = source.indexOf('-->', start + 4); //append comment source.substring(4,end)//<!--
if (end > start) {
domBuilder.comment(source, start + 4, end - start - 4);
return end + 3;
} else {
errorHandler.error("Unclosed comment");
return -1;
}
} else {
//error
return -1;
}
default:
if (source.substr(start + 3, 6) == 'CDATA[') {
var end = source.indexOf(']]>', start + 9);
domBuilder.startCDATA();
domBuilder.characters(source, start + 9, end - start - 9);
domBuilder.endCDATA();
return end + 3;
} //<!DOCTYPE
//startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId)
var matchs = split(source, start);
var len = matchs.length;
if (len > 1 && /!doctype/i.test(matchs[0][0])) {
var name = matchs[1][0];
var pubid = len > 3 && /^public$/i.test(matchs[2][0]) && matchs[3][0];
var sysid = len > 4 && matchs[4][0];
var lastMatch = matchs[len - 1];
domBuilder.startDTD(name, pubid && pubid.replace(/^(['"])(.*?)\1$/, '$2'), sysid && sysid.replace(/^(['"])(.*?)\1$/, '$2'));
domBuilder.endDTD();
return lastMatch.index + lastMatch[0].length;
}
}
return -1;
}
function parseInstruction(source, start, domBuilder) {
var end = source.indexOf('?>', start);
if (end) {
var match = source.substring(start, end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
if (match) {
var len = match[0].length;
domBuilder.processingInstruction(match[1], match[2]);
return end + 2;
} else {
//error
return -1;
}
}
return -1;
}
/**
* @param source
*/
function ElementAttributes(source) {}
ElementAttributes.prototype = {
setTagName: function setTagName(tagName) {
if (!tagNamePattern.test(tagName)) {
throw new Error('invalid tagName:' + tagName);
}
this.tagName = tagName;
},
add: function add(qName, value, offset) {
if (!tagNamePattern.test(qName)) {
throw new Error('invalid attribute:' + qName);
}
this[this.length++] = {
qName: qName,
value: value,
offset: offset
};
},
length: 0,
getLocalName: function getLocalName(i) {
return this[i].localName;
},
getLocator: function getLocator(i) {
return this[i].locator;
},
getQName: function getQName(i) {
return this[i].qName;
},
getURI: function getURI(i) {
return this[i].uri;
},
getValue: function getValue(i) {
return this[i].value;
} // ,getIndex:function(uri, localName)){
// if(localName){
//
// }else{
// var qName = uri
// }
// },
// getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
// getType:function(uri,localName){}
// getType:function(i){},
};
function _set_proto_(thiz, parent) {
thiz.__proto__ = parent;
return thiz;
}
if (!(_set_proto_({}, _set_proto_.prototype) instanceof _set_proto_)) {
_set_proto_ = function _set_proto_(thiz, parent) {
function p() {}
p.prototype = parent;
p = new p();
for (parent in thiz) {
p[parent] = thiz[parent];
}
return p;
};
}
function split(source, start) {
var match;
var buf = [];
var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
reg.lastIndex = start;
reg.exec(source); //skip <
while (match = reg.exec(source)) {
buf.push(match);
if (match[1]) return buf;
}
}
var XMLReader_1 = XMLReader;
var sax = {
XMLReader: XMLReader_1
};
/*
* DOM Level 2
* Object DOMException
* @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
* @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
*/
function copy$2(src, dest) {
for (var p in src) {
dest[p] = src[p];
}
}
/**
^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));?
^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));?
*/
function _extends$1(Class, Super) {
var pt = Class.prototype;
if (Object.create) {
var ppt = Object.create(Super.prototype);
pt.__proto__ = ppt;
}
if (!(pt instanceof Super)) {
var t = function t() {};
t.prototype = Super.prototype;
t = new t();
copy$2(pt, t);
Class.prototype = pt = t;
}
if (pt.constructor != Class) {
if (typeof Class != 'function') {
console.error("unknow Class:" + Class);
}
pt.constructor = Class;
}
}
var htmlns = 'http://www.w3.org/1999/xhtml'; // Node Types
var NodeType = {};
var ELEMENT_NODE = NodeType.ELEMENT_NODE = 1;
var ATTRIBUTE_NODE = NodeType.ATTRIBUTE_NODE = 2;
var TEXT_NODE = NodeType.TEXT_NODE = 3;
var CDATA_SECTION_NODE = NodeType.CDATA_SECTION_NODE = 4;
var ENTITY_REFERENCE_NODE = NodeType.ENTITY_REFERENCE_NODE = 5;
var ENTITY_NODE = NodeType.ENTITY_NODE = 6;
var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7;
var COMMENT_NODE = NodeType.COMMENT_NODE = 8;
var DOCUMENT_NODE = NodeType.DOCUMENT_NODE = 9;
var DOCUMENT_TYPE_NODE = NodeType.DOCUMENT_TYPE_NODE = 10;
var DOCUMENT_FRAGMENT_NODE = NodeType.DOCUMENT_FRAGMENT_NODE = 11;
var NOTATION_NODE = NodeType.NOTATION_NODE = 12; // ExceptionCode
var ExceptionCode = {};
var ExceptionMessage = {};
var INDEX_SIZE_ERR = ExceptionCode.INDEX_SIZE_ERR = (ExceptionMessage[1] = "Index size error", 1);
var DOMSTRING_SIZE_ERR = ExceptionCode.DOMSTRING_SIZE_ERR = (ExceptionMessage[2] = "DOMString size error", 2);
var HIERARCHY_REQUEST_ERR = ExceptionCode.HIERARCHY_REQUEST_ERR = (ExceptionMessage[3] = "Hierarchy request error", 3);
var WRONG_DOCUMENT_ERR = ExceptionCode.WRONG_DOCUMENT_ERR = (ExceptionMessage[4] = "Wrong document", 4);
var INVALID_CHARACTER_ERR = ExceptionCode.INVALID_CHARACTER_ERR = (ExceptionMessage[5] = "Invalid character", 5);
var NO_DATA_ALLOWED_ERR = ExceptionCode.NO_DATA_ALLOWED_ERR = (ExceptionMessage[6] = "No data allowed", 6);
var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = (ExceptionMessage[7] = "No modification allowed", 7);
var NOT_FOUND_ERR = ExceptionCode.NOT_FOUND_ERR = (ExceptionMessage[8] = "Not found", 8);
var NOT_SUPPORTED_ERR = ExceptionCode.NOT_SUPPORTED_ERR = (ExceptionMessage[9] = "Not supported", 9);
var INUSE_ATTRIBUTE_ERR = ExceptionCode.INUSE_ATTRIBUTE_ERR = (ExceptionMessage[10] = "Attribute in use", 10); //level2
var INVALID_STATE_ERR = ExceptionCode.INVALID_STATE_ERR = (ExceptionMessage[11] = "Invalid state", 11);
var SYNTAX_ERR = ExceptionCode.SYNTAX_ERR = (ExceptionMessage[12] = "Syntax error", 12);
var INVALID_MODIFICATION_ERR = ExceptionCode.INVALID_MODIFICATION_ERR = (ExceptionMessage[13] = "Invalid modification", 13);
var NAMESPACE_ERR = ExceptionCode.NAMESPACE_ERR = (ExceptionMessage[14] = "Invalid namespace", 14);
var INVALID_ACCESS_ERR = ExceptionCode.INVALID_ACCESS_ERR = (ExceptionMessage[15] = "Invalid access", 15);
function DOMException(code, message) {
if (message instanceof Error) {
var error = message;
} else {
error = this;
Error.call(this, ExceptionMessage[code]);
this.message = ExceptionMessage[code];
if (Error.captureStackTrace) Error.captureStackTrace(this, DOMException);
}
error.code = code;
if (message) this.message = this.message + ": " + message;
return error;
}
DOMException.prototype = Error.prototype;
copy$2(ExceptionCode, DOMException);
/**
* @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
* The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live.
* The items in the NodeList are accessible via an integral index, starting from 0.
*/
function NodeList() {}
NodeList.prototype = {
/**
* The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
* @standard level1
*/
length: 0,
/**
* Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null.
* @standard level1
* @param index unsigned long
* Index into the collection.
* @return Node
* The node at the indexth position in the NodeList, or null if that is not a valid index.
*/
item: function item(index) {
return this[index] || null;
},
toString: function toString(isHTML, nodeFilter) {
for (var buf = [], i = 0; i < this.length; i++) {
serializeToString(this[i], buf, isHTML, nodeFilter);
}
return buf.join('');
}
};
function LiveNodeList(node, refresh) {
this._node = node;
this._refresh = refresh;
_updateLiveList(this);
}
function _updateLiveList(list) {
var inc = list._node._inc || list._node.ownerDocument._inc;
if (list._inc != inc) {
var ls = list._refresh(list._node); //console.log(ls.length)
__set__(list, 'length', ls.length);
copy$2(ls, list);
list._inc = inc;
}
}
LiveNodeList.prototype.item = function (i) {
_updateLiveList(this);
return this[i];
};
_extends$1(LiveNodeList, NodeList);
/**
*
* Objects implementing the NamedNodeMap interface are used to represent collections of nodes that can be accessed by name. Note that NamedNodeMap does not inherit from NodeList; NamedNodeMaps are not maintained in any particular order. Objects contained in an object implementing NamedNodeMap may also be accessed by an ordinal index, but this is simply to allow convenient enumeration of the contents of a NamedNodeMap, and does not imply that the DOM specifies an order to these Nodes.
* NamedNodeMap objects in the DOM are live.
* used for attributes or DocumentType entities
*/
function NamedNodeMap() {}
function _findNodeIndex(list, node) {
var i = list.length;
while (i--) {
if (list[i] === node) {
return i;
}
}
}
function _addNamedNode(el, list, newAttr, oldAttr) {
if (oldAttr) {
list[_findNodeIndex(list, oldAttr)] = newAttr;
} else {
list[list.length++] = newAttr;
}
if (el) {
newAttr.ownerElement = el;
var doc = el.ownerDocument;
if (doc) {
oldAttr && _onRemoveAttribute(doc, el, oldAttr);
_onAddAttribute(doc, el, newAttr);
}
}
}
function _removeNamedNode(el, list, attr) {
//console.log('remove attr:'+attr)
var i = _findNodeIndex(list, attr);
if (i >= 0) {
var lastIndex = list.length - 1;
while (i < lastIndex) {
list[i] = list[++i];
}
list.length = lastIndex;
if (el) {
var doc = el.ownerDocument;
if (doc) {
_onRemoveAttribute(doc, el, attr);
attr.ownerElement = null;
}
}
} else {
throw DOMException(NOT_FOUND_ERR, new Error(el.tagName + '@' + attr));
}
}
NamedNodeMap.prototype = {
length: 0,
item: NodeList.prototype.item,
getNamedItem: function getNamedItem(key) {
// if(key.indexOf(':')>0 || key == 'xmlns'){
// return null;
// }
//console.log()
var i = this.length;
while (i--) {
var attr = this[i]; //console.log(attr.nodeName,key)
if (attr.nodeName == key) {
return attr;
}
}
},
setNamedItem: function setNamedItem(attr) {
var el = attr.ownerElement;
if (el && el != this._ownerElement) {
throw new DOMException(INUSE_ATTRIBUTE_ERR);
}
var oldAttr = this.getNamedItem(attr.nodeName);
_addNamedNode(this._ownerElement, this, attr, oldAttr);
return oldAttr;
},
/* returns Node */
setNamedItemNS: function setNamedItemNS(attr) {
// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR
var el = attr.ownerElement,
oldAttr;
if (el && el != this._ownerElement) {
throw new DOMException(INUSE_ATTRIBUTE_ERR);
}
oldAttr = this.getNamedItemNS(attr.namespaceURI, attr.localName);
_addNamedNode(this._ownerElement, this, attr, oldAttr);
return oldAttr;
},
/* returns Node */
removeNamedItem: function removeNamedItem(key) {
var attr = this.getNamedItem(key);
_removeNamedNode(this._ownerElement, this, attr);
return attr;
},
// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR
//for level2
removeNamedItemNS: function removeNamedItemNS(namespaceURI, localName) {
var attr = this.getNamedItemNS(namespaceURI, localName);
_removeNamedNode(this._ownerElement, this, attr);
return attr;
},
getNamedItemNS: function getNamedItemNS(namespaceURI, localName) {
var i = this.length;
while (i--) {
var node = this[i];
if (node.localName == localName && node.namespaceURI == namespaceURI) {
return node;
}
}
return null;
}
};
/**
* @see http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490
*/
function DOMImplementation(
/* Object */
features) {
this._features = {};
if (features) {
for (var feature in features) {
this._features = features[feature];
}
}
}
DOMImplementation.prototype = {
hasFeature: function hasFeature(
/* string */
feature,
/* string */
version) {
var versions = this._features[feature.toLowerCase()];
if (versions && (!version || version in versions)) {
return true;
} else {
return false;
}
},
// Introduced in DOM Level 2:
createDocument: function createDocument(namespaceURI, qualifiedName, doctype) {
// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR,WRONG_DOCUMENT_ERR
var doc = new Document();
doc.implementation = this;
doc.childNodes = new NodeList();
doc.doctype = doctype;
if (doctype) {
doc.appendChild(doctype);
}
if (qualifiedName) {
var root = doc.createElementNS(namespaceURI, qualifiedName);
doc.appendChild(root);
}
return doc;
},
// Introduced in DOM Level 2:
createDocumentType: function createDocumentType(qualifiedName, publicId, systemId) {
// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR
var node = new DocumentType();
node.name = qualifiedName;
node.nodeName = qualifiedName;
node.publicId = publicId;
node.systemId = systemId; // Introduced in DOM Level 2:
//readonly attribute DOMString internalSubset;
//TODO:..
// readonly attribute NamedNodeMap entities;
// readonly attribute NamedNodeMap notations;
return node;
}
};
/**
* @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247
*/
function Node$1() {}
Node$1.prototype = {
firstChild: null,
lastChild: null,
previousSibling: null,
nextSibling: null,
attributes: null,
parentNode: null,
childNodes: null,
ownerDocument: null,
nodeValue: null,
namespaceURI: null,
prefix: null,
localName: null,
// Modified in DOM Level 2:
insertBefore: function insertBefore(newChild, refChild) {
//raises
return _insertBefore(this, newChild, refChild);
},
replaceChild: function replaceChild(newChild, oldChild) {
//raises
this.insertBefore(newChild, oldChild);
if (oldChild) {
this.removeChild(oldChild);
}
},
removeChild: function removeChild(oldChild) {
return _removeChild(this, oldChild);
},
appendChild: function appendChild(newChild) {
return this.insertBefore(newChild, null);
},
hasChildNodes: function hasChildNodes() {
return this.firstChild != null;
},
cloneNode: function cloneNode(deep) {
return _cloneNode(this.ownerDocument || this, this, deep);
},
// Modified in DOM Level 2:
normalize: function normalize() {
var child = this.firstChild;
while (child) {
var next = child.nextSibling;
if (next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE) {
this.removeChild(next);
child.appendData(next.data);
} else {
child.normalize();
child = next;
}
}
},
// Introduced in DOM Level 2:
isSupported: function isSupported(feature, version) {
return this.ownerDocument.implementation.hasFeature(feature, version);
},
// Introduced in DOM Level 2:
hasAttributes: function hasAttributes() {
return this.attributes.length > 0;
},
lookupPrefix: function lookupPrefix(namespaceURI) {
var el = this;
while (el) {
var map = el._nsMap; //console.dir(map)
if (map) {
for (var n in map) {
if (map[n] == namespaceURI) {
return n;
}
}
}
el = el.nodeType == ATTRIBUTE_NODE ? el.ownerDocument : el.parentNode;
}
return null;
},
// Introduced in DOM Level 3:
lookupNamespaceURI: function lookupNamespaceURI(prefix) {
var el = this;
while (el) {
var map = el._nsMap; //console.dir(map)
if (map) {
if (prefix in map) {
return map[prefix];
}
}
el = el.nodeType == ATTRIBUTE_NODE ? el.ownerDocument : el.parentNode;
}
return null;
},
// Introduced in DOM Level 3:
isDefaultNamespace: function isDefaultNamespace(namespaceURI) {
var prefix = this.lookupPrefix(namespaceURI);
return prefix == null;
}
};
function _xmlEncoder(c) {
return c == '<' && '&lt;' || c == '>' && '&gt;' || c == '&' && '&amp;' || c == '"' && '&quot;' || '&#' + c.charCodeAt() + ';';
}
copy$2(NodeType, Node$1);
copy$2(NodeType, Node$1.prototype);
/**
* @param callback return true for continue,false for break
* @return boolean true: break visit;
*/
function _visitNode(node, callback) {
if (callback(node)) {
return true;
}
if (node = node.firstChild) {
do {
if (_visitNode(node, callback)) {
return true;
}
} while (node = node.nextSibling);
}
}
function Document() {}
function _onAddAttribute(doc, el, newAttr) {
doc && doc._inc++;
var ns = newAttr.namespaceURI;
if (ns == 'http://www.w3.org/2000/xmlns/') {
//update namespace
el._nsMap[newAttr.prefix ? newAttr.localName : ''] = newAttr.value;
}
}
function _onRemoveAttribute(doc, el, newAttr, remove) {
doc && doc._inc++;
var ns = newAttr.namespaceURI;
if (ns == 'http://www.w3.org/2000/xmlns/') {
//update namespace
delete el._nsMap[newAttr.prefix ? newAttr.localName : ''];
}
}
function _onUpdateChild(doc, el, newChild) {
if (doc && doc._inc) {
doc._inc++; //update childNodes
var cs = el.childNodes;
if (newChild) {
cs[cs.length++] = newChild;
} else {
//console.log(1)
var child = el.firstChild;
var i = 0;
while (child) {
cs[i++] = child;
child = child.nextSibling;
}
cs.length = i;
}
}
}
/**
* attributes;
* children;
*
* writeable properties:
* nodeValue,Attr:value,CharacterData:data
* prefix
*/
function _removeChild(parentNode, child) {
var previous = child.previousSibling;
var next = child.nextSibling;
if (previous) {
previous.nextSibling = next;
} else {
parentNode.firstChild = next;
}
if (next) {
next.previousSibling = previous;
} else {
parentNode.lastChild = previous;
}
_onUpdateChild(parentNode.ownerDocument, parentNode);
return child;
}
/**
* preformance key(refChild == null)
*/
function _insertBefore(parentNode, newChild, nextChild) {
var cp = newChild.parentNode;
if (cp) {
cp.removeChild(newChild); //remove and update
}
if (newChild.nodeType === DOCUMENT_FRAGMENT_NODE) {
var newFirst = newChild.firstChild;
if (newFirst == null) {
return newChild;
}
var newLast = newChild.lastChild;
} else {
newFirst = newLast = newChild;
}
var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild;
newFirst.previousSibling = pre;
newLast.nextSibling = nextChild;
if (pre) {
pre.nextSibling = newFirst;
} else {
parentNode.firstChild = newFirst;
}
if (nextChild == null) {
parentNode.lastChild = newLast;
} else {
nextChild.previousSibling = newLast;
}
do {
newFirst.parentNode = parentNode;
} while (newFirst !== newLast && (newFirst = newFirst.nextSibling));
_onUpdateChild(parentNode.ownerDocument || parentNode, parentNode); //console.log(parentNode.lastChild.nextSibling == null)
if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {
newChild.firstChild = newChild.lastChild = null;
}
return newChild;
}
function _appendSingleChild(parentNode, newChild) {
var cp = newChild.parentNode;
if (cp) {
var pre = parentNode.lastChild;
cp.removeChild(newChild); //remove and update
var pre = parentNode.lastChild;
}
var pre = parentNode.lastChild;
newChild.parentNode = parentNode;
newChild.previousSibling = pre;
newChild.nextSibling = null;
if (pre) {
pre.nextSibling = newChild;
} else {
parentNode.firstChild = newChild;
}
parentNode.lastChild = newChild;
_onUpdateChild(parentNode.ownerDocument, parentNode, newChild);
return newChild; //console.log("__aa",parentNode.lastChild.nextSibling == null)
}
Document.prototype = {
//implementation : null,
nodeName: '#document',
nodeType: DOCUMENT_NODE,
doctype: null,
documentElement: null,
_inc: 1,
insertBefore: function insertBefore(newChild, refChild) {
//raises
if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {
var child = newChild.firstChild;
while (child) {
var next = child.nextSibling;
this.insertBefore(child, refChild);
child = next;
}
return newChild;
}
if (this.documentElement == null && newChild.nodeType == ELEMENT_NODE) {
this.documentElement = newChild;
}
return _insertBefore(this, newChild, refChild), newChild.ownerDocument = this, newChild;
},
removeChild: function removeChild(oldChild) {
if (this.documentElement == oldChild) {
this.documentElement = null;
}
return _removeChild(this, oldChild);
},
// Introduced in DOM Level 2:
importNode: function importNode(importedNode, deep) {
return _importNode(this, importedNode, deep);
},
// Introduced in DOM Level 2:
getElementById: function getElementById(id) {
var rtv = null;
_visitNode(this.documentElement, function (node) {
if (node.nodeType == ELEMENT_NODE) {
if (node.getAttribute('id') == id) {
rtv = node;
return true;
}
}
});
return rtv;
},
//document factory method:
createElement: function createElement(tagName) {
var node = new Element$1();
node.ownerDocument = this;
node.nodeName = tagName;
node.tagName = tagName;
node.childNodes = new NodeList();
var attrs = node.attributes = new NamedNodeMap();
attrs._ownerElement = node;
return node;
},
createDocumentFragment: function createDocumentFragment() {
var node = new DocumentFragment();
node.ownerDocument = this;
node.childNodes = new NodeList();
return node;
},
createTextNode: function createTextNode(data) {
var node = new Text();
node.ownerDocument = this;
node.appendData(data);
return node;
},
createComment: function createComment(data) {
var node = new Comment();
node.ownerDocument = this;
node.appendData(data);
return node;
},
createCDATASection: function createCDATASection(data) {
var node = new CDATASection();
node.ownerDocument = this;
node.appendData(data);
return node;
},
createProcessingInstruction: function createProcessingInstruction(target, data) {
var node = new ProcessingInstruction();
node.ownerDocument = this;
node.tagName = node.target = target;
node.nodeValue = node.data = data;
return node;
},
createAttribute: function createAttribute(name) {
var node = new Attr();
node.ownerDocument = this;
node.name = name;
node.nodeName = name;
node.localName = name;
node.specified = true;
return node;
},
createEntityReference: function createEntityReference(name) {
var node = new EntityReference();
node.ownerDocument = this;
node.nodeName = name;
return node;
},
// Introduced in DOM Level 2:
createElementNS: function createElementNS(namespaceURI, qualifiedName) {
var node = new Element$1();
var pl = qualifiedName.split(':');
var attrs = node.attributes = new NamedNodeMap();
node.childNodes = new NodeList();
node.ownerDocument = this;
node.nodeName = qualifiedName;
node.tagName = qualifiedName;
node.namespaceURI = namespaceURI;
if (pl.length == 2) {
node.prefix = pl[0];
node.localName = pl[1];
} else {
//el.prefix = null;
node.localName = qualifiedName;
}
attrs._ownerElement = node;
return node;
},
// Introduced in DOM Level 2:
createAttributeNS: function createAttributeNS(namespaceURI, qualifiedName) {
var node = new Attr();
var pl = qualifiedName.split(':');
node.ownerDocument = this;
node.nodeName = qualifiedName;
node.name = qualifiedName;
node.namespaceURI = namespaceURI;
node.specified = true;
if (pl.length == 2) {
node.prefix = pl[0];
node.localName = pl[1];
} else {
//el.prefix = null;
node.localName = qualifiedName;
}
return node;
}
};
_extends$1(Document, Node$1);
function Element$1() {
this._nsMap = {};
}
Element$1.prototype = {
nodeType: ELEMENT_NODE,
hasAttribute: function hasAttribute(name) {
return this.getAttributeNode(name) != null;
},
getAttribute: function getAttribute(name) {
var attr = this.getAttributeNode(name);
return attr && attr.value || '';
},
getAttributeNode: function getAttributeNode(name) {
return this.attributes.getNamedItem(name);
},
setAttribute: function setAttribute(name, value) {
var attr = this.ownerDocument.createAttribute(name);
attr.value = attr.nodeValue = "" + value;
this.setAttributeNode(attr);
},
removeAttribute: function removeAttribute(name) {
var attr = this.getAttributeNode(name);
attr && this.removeAttributeNode(attr);
},
//four real opeartion method
appendChild: function appendChild(newChild) {
if (newChild.nodeType === DOCUMENT_FRAGMENT_NODE) {
return this.insertBefore(newChild, null);
} else {
return _appendSingleChild(this, newChild);
}
},
setAttributeNode: function setAttributeNode(newAttr) {
return this.attributes.setNamedItem(newAttr);
},
setAttributeNodeNS: function setAttributeNodeNS(newAttr) {
return this.attributes.setNamedItemNS(newAttr);
},
removeAttributeNode: function removeAttributeNode(oldAttr) {
//console.log(this == oldAttr.ownerElement)
return this.attributes.removeNamedItem(oldAttr.nodeName);
},
//get real attribute name,and remove it by removeAttributeNode
removeAttributeNS: function removeAttributeNS(namespaceURI, localName) {
var old = this.getAttributeNodeNS(namespaceURI, localName);
old && this.removeAttributeNode(old);
},
hasAttributeNS: function hasAttributeNS(namespaceURI, localName) {
return this.getAttributeNodeNS(namespaceURI, localName) != null;
},
getAttributeNS: function getAttributeNS(namespaceURI, localName) {
var attr = this.getAttributeNodeNS(namespaceURI, localName);
return attr && attr.value || '';
},
setAttributeNS: function setAttributeNS(namespaceURI, qualifiedName, value) {
var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);
attr.value = attr.nodeValue = "" + value;
this.setAttributeNode(attr);
},
getAttributeNodeNS: function getAttributeNodeNS(namespaceURI, localName) {
return this.attributes.getNamedItemNS(namespaceURI, localName);
},
getElementsByTagName: function getElementsByTagName(tagName) {
return new LiveNodeList(this, function (base) {
var ls = [];
_visitNode(base, function (node) {
if (node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)) {
ls.push(node);
}
});
return ls;
});
},
getElementsByTagNameNS: function getElementsByTagNameNS(namespaceURI, localName) {
return new LiveNodeList(this, function (base) {
var ls = [];
_visitNode(base, function (node) {
if (node !== base && node.nodeType === ELEMENT_NODE && (namespaceURI === '*' || node.namespaceURI === namespaceURI) && (localName === '*' || node.localName == localName)) {
ls.push(node);
}
});
return ls;
});
}
};
Document.prototype.getElementsByTagName = Element$1.prototype.getElementsByTagName;
Document.prototype.getElementsByTagNameNS = Element$1.prototype.getElementsByTagNameNS;
_extends$1(Element$1, Node$1);
function Attr() {}
Attr.prototype.nodeType = ATTRIBUTE_NODE;
_extends$1(Attr, Node$1);
function CharacterData() {}
CharacterData.prototype = {
data: '',
substringData: function substringData(offset, count) {
return this.data.substring(offset, offset + count);
},
appendData: function appendData(text) {
text = this.data + text;
this.nodeValue = this.data = text;
this.length = text.length;
},
insertData: function insertData(offset, text) {
this.replaceData(offset, 0, text);
},
appendChild: function appendChild(newChild) {
throw new Error(ExceptionMessage[HIERARCHY_REQUEST_ERR]);
},
deleteData: function deleteData(offset, count) {
this.replaceData(offset, count, "");
},
replaceData: function replaceData(offset, count, text) {
var start = this.data.substring(0, offset);
var end = this.data.substring(offset + count);
text = start + text + end;
this.nodeValue = this.data = text;
this.length = text.length;
}
};
_extends$1(CharacterData, Node$1);
function Text() {}
Text.prototype = {
nodeName: "#text",
nodeType: TEXT_NODE,
splitText: function splitText(offset) {
var text = this.data;
var newText = text.substring(offset);
text = text.substring(0, offset);
this.data = this.nodeValue = text;
this.length = text.length;
var newNode = this.ownerDocument.createTextNode(newText);
if (this.parentNode) {
this.parentNode.insertBefore(newNode, this.nextSibling);
}
return newNode;
}
};
_extends$1(Text, CharacterData);
function Comment() {}
Comment.prototype = {
nodeName: "#comment",
nodeType: COMMENT_NODE
};
_extends$1(Comment, CharacterData);
function CDATASection() {}
CDATASection.prototype = {
nodeName: "#cdata-section",
nodeType: CDATA_SECTION_NODE
};
_extends$1(CDATASection, CharacterData);
function DocumentType() {}
DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;
_extends$1(DocumentType, Node$1);
function Notation() {}
Notation.prototype.nodeType = NOTATION_NODE;
_extends$1(Notation, Node$1);
function Entity() {}
Entity.prototype.nodeType = ENTITY_NODE;
_extends$1(Entity, Node$1);
function EntityReference() {}
EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
_extends$1(EntityReference, Node$1);
function DocumentFragment() {}
DocumentFragment.prototype.nodeName = "#document-fragment";
DocumentFragment.prototype.nodeType = DOCUMENT_FRAGMENT_NODE;
_extends$1(DocumentFragment, Node$1);
function ProcessingInstruction() {}
ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
_extends$1(ProcessingInstruction, Node$1);
function XMLSerializer$1() {}
XMLSerializer$1.prototype.serializeToString = function (node, isHtml, nodeFilter) {
return nodeSerializeToString.call(node, isHtml, nodeFilter);
};
Node$1.prototype.toString = nodeSerializeToString;
function nodeSerializeToString(isHtml, nodeFilter) {
var buf = [];
var refNode = this.nodeType == 9 ? this.documentElement : this;
var prefix = refNode.prefix;
var uri = refNode.namespaceURI;
if (uri && prefix == null) {
//console.log(prefix)
var prefix = refNode.lookupPrefix(uri);
if (prefix == null) {
//isHTML = true;
var visibleNamespaces = [{
namespace: uri,
prefix: null
} //{namespace:uri,prefix:''}
];
}
}
serializeToString(this, buf, isHtml, nodeFilter, visibleNamespaces); //console.log('###',this.nodeType,uri,prefix,buf.join(''))
return buf.join('');
}
function needNamespaceDefine(node, isHTML, visibleNamespaces) {
var prefix = node.prefix || '';
var uri = node.namespaceURI;
if (!prefix && !uri) {
return false;
}
if (prefix === "xml" && uri === "http://www.w3.org/XML/1998/namespace" || uri == 'http://www.w3.org/2000/xmlns/') {
return false;
}
var i = visibleNamespaces.length; //console.log('@@@@',node.tagName,prefix,uri,visibleNamespaces)
while (i--) {
var ns = visibleNamespaces[i]; // get namespace prefix
//console.log(node.nodeType,node.tagName,ns.prefix,prefix)
if (ns.prefix == prefix) {
return ns.namespace != uri;
}
} //console.log(isHTML,uri,prefix=='')
//if(isHTML && prefix ==null && uri == 'http://www.w3.org/1999/xhtml'){
// return false;
//}
//node.flag = '11111'
//console.error(3,true,node.flag,node.prefix,node.namespaceURI)
return true;
}
function serializeToString(node, buf, isHTML, nodeFilter, visibleNamespaces) {
if (nodeFilter) {
node = nodeFilter(node);
if (node) {
if (typeof node == 'string') {
buf.push(node);
return;
}
} else {
return;
} //buf.sort.apply(attrs, attributeSorter);
}
switch (node.nodeType) {
case ELEMENT_NODE:
if (!visibleNamespaces) visibleNamespaces = [];
var startVisibleNamespaces = visibleNamespaces.length;
var attrs = node.attributes;
var len = attrs.length;
var child = node.firstChild;
var nodeName = node.tagName;
isHTML = htmlns === node.namespaceURI || isHTML;
buf.push('<', nodeName);
for (var i = 0; i < len; i++) {
// add namespaces for attributes
var attr = attrs.item(i);
if (attr.prefix == 'xmlns') {
visibleNamespaces.push({
prefix: attr.localName,
namespace: attr.value
});
} else if (attr.nodeName == 'xmlns') {
visibleNamespaces.push({
prefix: '',
namespace: attr.value
});
}
}
for (var i = 0; i < len; i++) {
var attr = attrs.item(i);
if (needNamespaceDefine(attr, isHTML, visibleNamespaces)) {
var prefix = attr.prefix || '';
var uri = attr.namespaceURI;
var ns = prefix ? ' xmlns:' + prefix : " xmlns";
buf.push(ns, '="', uri, '"');
visibleNamespaces.push({
prefix: prefix,
namespace: uri
});
}
serializeToString(attr, buf, isHTML, nodeFilter, visibleNamespaces);
} // add namespace for current node
if (needNamespaceDefine(node, isHTML, visibleNamespaces)) {
var prefix = node.prefix || '';
var uri = node.namespaceURI;
var ns = prefix ? ' xmlns:' + prefix : " xmlns";
buf.push(ns, '="', uri, '"');
visibleNamespaces.push({
prefix: prefix,
namespace: uri
});
}
if (child || isHTML && !/^(?:meta|link|img|br|hr|input)$/i.test(nodeName)) {
buf.push('>'); //if is cdata child node
if (isHTML && /^script$/i.test(nodeName)) {
while (child) {
if (child.data) {
buf.push(child.data);
} else {
serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces);
}
child = child.nextSibling;
}
} else {
while (child) {
serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces);
child = child.nextSibling;
}
}
buf.push('</', nodeName, '>');
} else {
buf.push('/>');
} // remove added visible namespaces
//visibleNamespaces.length = startVisibleNamespaces;
return;
case DOCUMENT_NODE:
case DOCUMENT_FRAGMENT_NODE:
var child = node.firstChild;
while (child) {
serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces);
child = child.nextSibling;
}
return;
case ATTRIBUTE_NODE:
return buf.push(' ', node.name, '="', node.value.replace(/[<&"]/g, _xmlEncoder), '"');
case TEXT_NODE:
return buf.push(node.data.replace(/[<&]/g, _xmlEncoder));
case CDATA_SECTION_NODE:
return buf.push('<![CDATA[', node.data, ']]>');
case COMMENT_NODE:
return buf.push("<!--", node.data, "-->");
case DOCUMENT_TYPE_NODE:
var pubid = node.publicId;
var sysid = node.systemId;
buf.push('<!DOCTYPE ', node.name);
if (pubid) {
buf.push(' PUBLIC "', pubid);
if (sysid && sysid != '.') {
buf.push('" "', sysid);
}
buf.push('">');
} else if (sysid && sysid != '.') {
buf.push(' SYSTEM "', sysid, '">');
} else {
var sub = node.internalSubset;
if (sub) {
buf.push(" [", sub, "]");
}
buf.push(">");
}
return;
case PROCESSING_INSTRUCTION_NODE:
return buf.push("<?", node.target, " ", node.data, "?>");
case ENTITY_REFERENCE_NODE:
return buf.push('&', node.nodeName, ';');
//case ENTITY_NODE:
//case NOTATION_NODE:
default:
buf.push('??', node.nodeName);
}
}
function _importNode(doc, node, deep) {
var node2;
switch (node.nodeType) {
case ELEMENT_NODE:
node2 = node.cloneNode(false);
node2.ownerDocument = doc;
//var attrs = node2.attributes;
//var len = attrs.length;
//for(var i=0;i<len;i++){
//node2.setAttributeNodeNS(importNode(doc,attrs.item(i),deep));
//}
case DOCUMENT_FRAGMENT_NODE:
break;
case ATTRIBUTE_NODE:
deep = true;
break;
//case ENTITY_REFERENCE_NODE:
//case PROCESSING_INSTRUCTION_NODE:
////case TEXT_NODE:
//case CDATA_SECTION_NODE:
//case COMMENT_NODE:
// deep = false;
// break;
//case DOCUMENT_NODE:
//case DOCUMENT_TYPE_NODE:
//cannot be imported.
//case ENTITY_NODE:
//case NOTATION_NODE
//can not hit in level3
//default:throw e;
}
if (!node2) {
node2 = node.cloneNode(false); //false
}
node2.ownerDocument = doc;
node2.parentNode = null;
if (deep) {
var child = node.firstChild;
while (child) {
node2.appendChild(_importNode(doc, child, deep));
child = child.nextSibling;
}
}
return node2;
} //
//var _relationMap = {firstChild:1,lastChild:1,previousSibling:1,nextSibling:1,
// attributes:1,childNodes:1,parentNode:1,documentElement:1,doctype,};
function _cloneNode(doc, node, deep) {
var node2 = new node.constructor();
for (var n in node) {
var v = node[n];
if (_typeof(v) != 'object') {
if (v != node2[n]) {
node2[n] = v;
}
}
}
if (node.childNodes) {
node2.childNodes = new NodeList();
}
node2.ownerDocument = doc;
switch (node2.nodeType) {
case ELEMENT_NODE:
var attrs = node.attributes;
var attrs2 = node2.attributes = new NamedNodeMap();
var len = attrs.length;
attrs2._ownerElement = node2;
for (var i = 0; i < len; i++) {
node2.setAttributeNode(_cloneNode(doc, attrs.item(i), true));
}
break;
case ATTRIBUTE_NODE:
deep = true;
}
if (deep) {
var child = node.firstChild;
while (child) {
node2.appendChild(_cloneNode(doc, child, deep));
child = child.nextSibling;
}
}
return node2;
}
function __set__(object, key, value) {
object[key] = value;
} //do dynamic
try {
if (Object.defineProperty) {
var getTextContent = function getTextContent(node) {
switch (node.nodeType) {
case ELEMENT_NODE:
case DOCUMENT_FRAGMENT_NODE:
var buf = [];
node = node.firstChild;
while (node) {
if (node.nodeType !== 7 && node.nodeType !== 8) {
buf.push(getTextContent(node));
}
node = node.nextSibling;
}
return buf.join('');
default:
return node.nodeValue;
}
};
Object.defineProperty(LiveNodeList.prototype, 'length', {
get: function get() {
_updateLiveList(this);
return this.$$length;
}
});
Object.defineProperty(Node$1.prototype, 'textContent', {
get: function get() {
return getTextContent(this);
},
set: function set(data) {
switch (this.nodeType) {
case ELEMENT_NODE:
case DOCUMENT_FRAGMENT_NODE:
while (this.firstChild) {
this.removeChild(this.firstChild);
}
if (data || String(data)) {
this.appendChild(this.ownerDocument.createTextNode(data));
}
break;
default:
//TODO:
this.data = data;
this.value = data;
this.nodeValue = data;
}
}
});
__set__ = function __set__(object, key, value) {
//console.log(value)
object['$$' + key] = value;
};
}
} catch (e) {//ie8
} //if(typeof require == 'function'){
var DOMImplementation_1 = DOMImplementation;
var XMLSerializer_1 = XMLSerializer$1; //}
var dom = {
DOMImplementation: DOMImplementation_1,
XMLSerializer: XMLSerializer_1
};
var domParser = createCommonjsModule(function (module, exports) {
function DOMParser(options) {
this.options = options || {
locator: {}
};
}
DOMParser.prototype.parseFromString = function (source, mimeType) {
var options = this.options;
var sax = new XMLReader();
var domBuilder = options.domBuilder || new DOMHandler(); //contentHandler and LexicalHandler
var errorHandler = options.errorHandler;
var locator = options.locator;
var defaultNSMap = options.xmlns || {};
var entityMap = {
'lt': '<',
'gt': '>',
'amp': '&',
'quot': '"',
'apos': "'"
};
if (locator) {
domBuilder.setDocumentLocator(locator);
}
sax.errorHandler = buildErrorHandler(errorHandler, domBuilder, locator);
sax.domBuilder = options.domBuilder || domBuilder;
if (/\/x?html?$/.test(mimeType)) {
entityMap.nbsp = '\xa0';
entityMap.copy = '\xa9';
defaultNSMap[''] = 'http://www.w3.org/1999/xhtml';
}
defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace';
if (source) {
sax.parse(source, defaultNSMap, entityMap);
} else {
sax.errorHandler.error("invalid doc source");
}
return domBuilder.doc;
};
function buildErrorHandler(errorImpl, domBuilder, locator) {
if (!errorImpl) {
if (domBuilder instanceof DOMHandler) {
return domBuilder;
}
errorImpl = domBuilder;
}
var errorHandler = {};
var isCallback = errorImpl instanceof Function;
locator = locator || {};
function build(key) {
var fn = errorImpl[key];
if (!fn && isCallback) {
fn = errorImpl.length == 2 ? function (msg) {
errorImpl(key, msg);
} : errorImpl;
}
errorHandler[key] = fn && function (msg) {
fn('[xmldom ' + key + ']\t' + msg + _locator(locator));
} || function () {};
}
build('warning');
build('error');
build('fatalError');
return errorHandler;
} //console.log('#\n\n\n\n\n\n\n####')
/**
* +ContentHandler+ErrorHandler
* +LexicalHandler+EntityResolver2
* -DeclHandler-DTDHandler
*
* DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler
* DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2
* @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html
*/
function DOMHandler() {
this.cdata = false;
}
function position(locator, node) {
node.lineNumber = locator.lineNumber;
node.columnNumber = locator.columnNumber;
}
/**
* @see org.xml.sax.ContentHandler#startDocument
* @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
*/
DOMHandler.prototype = {
startDocument: function startDocument() {
this.doc = new DOMImplementation().createDocument(null, null, null);
if (this.locator) {
this.doc.documentURI = this.locator.systemId;
}
},
startElement: function startElement(namespaceURI, localName, qName, attrs) {
var doc = this.doc;
var el = doc.createElementNS(namespaceURI, qName || localName);
var len = attrs.length;
appendElement(this, el);
this.currentElement = el;
this.locator && position(this.locator, el);
for (var i = 0; i < len; i++) {
var namespaceURI = attrs.getURI(i);
var value = attrs.getValue(i);
var qName = attrs.getQName(i);
var attr = doc.createAttributeNS(namespaceURI, qName);
this.locator && position(attrs.getLocator(i), attr);
attr.value = attr.nodeValue = value;
el.setAttributeNode(attr);
}
},
endElement: function endElement(namespaceURI, localName, qName) {
var current = this.currentElement;
var tagName = current.tagName;
this.currentElement = current.parentNode;
},
startPrefixMapping: function startPrefixMapping(prefix, uri) {},
endPrefixMapping: function endPrefixMapping(prefix) {},
processingInstruction: function processingInstruction(target, data) {
var ins = this.doc.createProcessingInstruction(target, data);
this.locator && position(this.locator, ins);
appendElement(this, ins);
},
ignorableWhitespace: function ignorableWhitespace(ch, start, length) {},
characters: function characters(chars, start, length) {
chars = _toString.apply(this, arguments); //console.log(chars)
if (chars) {
if (this.cdata) {
var charNode = this.doc.createCDATASection(chars);
} else {
var charNode = this.doc.createTextNode(chars);
}
if (this.currentElement) {
this.currentElement.appendChild(charNode);
} else if (/^\s*$/.test(chars)) {
this.doc.appendChild(charNode); //process xml
}
this.locator && position(this.locator, charNode);
}
},
skippedEntity: function skippedEntity(name) {},
endDocument: function endDocument() {
this.doc.normalize();
},
setDocumentLocator: function setDocumentLocator(locator) {
if (this.locator = locator) {
// && !('lineNumber' in locator)){
locator.lineNumber = 0;
}
},
//LexicalHandler
comment: function comment(chars, start, length) {
chars = _toString.apply(this, arguments);
var comm = this.doc.createComment(chars);
this.locator && position(this.locator, comm);
appendElement(this, comm);
},
startCDATA: function startCDATA() {
//used in characters() methods
this.cdata = true;
},
endCDATA: function endCDATA() {
this.cdata = false;
},
startDTD: function startDTD(name, publicId, systemId) {
var impl = this.doc.implementation;
if (impl && impl.createDocumentType) {
var dt = impl.createDocumentType(name, publicId, systemId);
this.locator && position(this.locator, dt);
appendElement(this, dt);
}
},
/**
* @see org.xml.sax.ErrorHandler
* @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
*/
warning: function warning(error) {
console.warn('[xmldom warning]\t' + error, _locator(this.locator));
},
error: function error(_error) {
console.error('[xmldom error]\t' + _error, _locator(this.locator));
},
fatalError: function fatalError(error) {
console.error('[xmldom fatalError]\t' + error, _locator(this.locator));
throw error;
}
};
function _locator(l) {
if (l) {
return '\n@' + (l.systemId || '') + '#[line:' + l.lineNumber + ',col:' + l.columnNumber + ']';
}
}
function _toString(chars, start, length) {
if (typeof chars == 'string') {
return chars.substr(start, length);
} else {
//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
if (chars.length >= start + length || start) {
return new java.lang.String(chars, start, length) + '';
}
return chars;
}
}
/*
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
* used method of org.xml.sax.ext.LexicalHandler:
* #comment(chars, start, length)
* #startCDATA()
* #endCDATA()
* #startDTD(name, publicId, systemId)
*
*
* IGNORED method of org.xml.sax.ext.LexicalHandler:
* #endDTD()
* #startEntity(name)
* #endEntity(name)
*
*
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
* IGNORED method of org.xml.sax.ext.DeclHandler
* #attributeDecl(eName, aName, type, mode, value)
* #elementDecl(name, model)
* #externalEntityDecl(name, publicId, systemId)
* #internalEntityDecl(name, value)
* @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
* IGNORED method of org.xml.sax.EntityResolver2
* #resolveEntity(String name,String publicId,String baseURI,String systemId)
* #resolveEntity(publicId, systemId)
* #getExternalSubset(name, baseURI)
* @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
* IGNORED method of org.xml.sax.DTDHandler
* #notationDecl(name, publicId, systemId) {};
* #unparsedEntityDecl(name, publicId, systemId, notationName) {};
*/
"endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g, function (key) {
DOMHandler.prototype[key] = function () {
return null;
};
});
/* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */
function appendElement(hander, node) {
if (!hander.currentElement) {
hander.doc.appendChild(node);
} else {
hander.currentElement.appendChild(node);
}
} //appendChild and setAttributeNS are preformance key
//if(typeof require == 'function'){
var XMLReader = sax.XMLReader;
var DOMImplementation = exports.DOMImplementation = dom.DOMImplementation;
exports.XMLSerializer = dom.XMLSerializer;
exports.DOMParser = DOMParser; //}
});
var domParser_1 = domParser.DOMImplementation;
var domParser_2 = domParser.XMLSerializer;
var domParser_3 = domParser.DOMParser;
/*
* canvg.js - Javascript SVG parser and renderer on Canvas
* MIT Licensed
* Gabe Lerner (gabelerner@gmail.com)
* http://code.google.com/p/canvg/
*
* Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/
*/
/*
canvg(target, s)
empty parameters: replace all 'svg' elements on page with 'canvas' elements
target: canvas element or the id of a canvas element
s: svg string, url to svg file, or xml document
opts: optional hash of options
ignoreMouse: true => ignore mouse events
ignoreAnimation: true => ignore animations
ignoreDimensions: true => does not try to resize canvas
ignoreClear: true => does not clear canvas
offsetX: int => draws at a x offset
offsetY: int => draws at a y offset
scaleWidth: int => scales horizontally to width
scaleHeight: int => scales vertically to height
renderCallback: function => will call the function after the first render is completed
forceRedraw: function => will call the function on every frame, if it returns true, will redraw
*/
function canvg(target, s, opts) {
// no parameters
if (target == null && s == null && opts == null) {
var svgTags = document.querySelectorAll('svg');
for (var i = 0; i < svgTags.length; i++) {
var svgTag = svgTags[i];
var c = document.createElement('canvas');
c.width = svgTag.clientWidth;
c.height = svgTag.clientHeight;
svgTag.parentNode.insertBefore(c, svgTag);
svgTag.parentNode.removeChild(svgTag);
var div = document.createElement('div');
div.appendChild(svgTag);
canvg(c, div.innerHTML);
}
return;
}
if (typeof target == 'string') {
target = document.getElementById(target);
} // store class on canvas
if (target.svg != null) target.svg.stop();
var svg = build(opts || {}); // on i.e. 8 for flash canvas, we can't assign the property so check for it
if (!(target.childNodes.length == 1 && target.childNodes[0].nodeName == 'OBJECT')) target.svg = svg;
var ctx = target.getContext('2d');
if (typeof s.documentElement != 'undefined') {
// load from xml doc
svg.loadXmlDoc(ctx, s);
} else if (s.substr(0, 1) == '<') {
// load from xml string
svg.loadXml(ctx, s);
} else {
// load from url
svg.load(ctx, s);
}
}
function getMatchesSelector() {
// see https://developer.mozilla.org/en-US/docs/Web/API/Element.matches
var matchesSelector;
if (typeof Element.prototype.matches != 'undefined') {
matchesSelector = function matchesSelector(node, selector) {
return node.matches(selector);
};
} else if (typeof Element.prototype.webkitMatchesSelector != 'undefined') {
matchesSelector = function matchesSelector(node, selector) {
return node.webkitMatchesSelector(selector);
};
} else if (typeof Element.prototype.mozMatchesSelector != 'undefined') {
matchesSelector = function matchesSelector(node, selector) {
return node.mozMatchesSelector(selector);
};
} else if (typeof Element.prototype.msMatchesSelector != 'undefined') {
matchesSelector = function matchesSelector(node, selector) {
return node.msMatchesSelector(selector);
};
} else if (typeof Element.prototype.oMatchesSelector != 'undefined') {
matchesSelector = function matchesSelector(node, selector) {
return node.oMatchesSelector(selector);
};
} else {
// requires Sizzle: https://github.com/jquery/sizzle/wiki/Sizzle-Documentation
// or jQuery: http://jquery.com/download/
// or Zepto: http://zeptojs.com/#
// without it, this is a ReferenceError
if (typeof jQuery == 'function' || typeof Zepto == 'function') {
matchesSelector = function matchesSelector(node, selector) {
return $(node).is(selector);
};
}
if (typeof matchesSelector == 'undefined') {
matchesSelector = Sizzle.matchesSelector;
}
}
return matchesSelector;
}
function getSelectorSpecificity(selector) {
var typeCount = [0, 0, 0]; // slightly modified version of https://github.com/keeganstreet/specificity/blob/master/specificity.js
var attributeRegex = /(\[[^\]]+\])/g;
var idRegex = /(#[^\s\+>~\.\[:]+)/g;
var classRegex = /(\.[^\s\+>~\.\[:]+)/g;
var pseudoElementRegex = /(::[^\s\+>~\.\[:]+|:first-line|:first-letter|:before|:after)/gi;
var pseudoClassWithBracketsRegex = /(:[\w-]+\([^\)]*\))/gi;
var pseudoClassRegex = /(:[^\s\+>~\.\[:]+)/g;
var elementRegex = /([^\s\+>~\.\[:]+)/g;
var findMatch = function findMatch(regex, type) {
var matches = selector.match(regex);
if (matches == null) {
return;
}
typeCount[type] += matches.length;
selector = selector.replace(regex, ' ');
};
selector = selector.replace(/:not\(([^\)]*)\)/g, ' $1 ');
selector = selector.replace(/{[^]*/gm, ' ');
findMatch(attributeRegex, 1);
findMatch(idRegex, 0);
findMatch(classRegex, 1);
findMatch(pseudoElementRegex, 2);
findMatch(pseudoClassWithBracketsRegex, 1);
findMatch(pseudoClassRegex, 1);
selector = selector.replace(/[\*\s\+>~]/g, ' ');
selector = selector.replace(/[#\.]/g, ' ');
findMatch(elementRegex, 2);
return typeCount.join('');
}
function build(opts) {
var svg = {
opts: opts
};
var matchesSelector = getMatchesSelector();
if (typeof CanvasRenderingContext2D != 'undefined') {
CanvasRenderingContext2D.prototype.drawSvg = function (s, dx, dy, dw, dh, opts) {
var cOpts = {
ignoreMouse: true,
ignoreAnimation: true,
ignoreDimensions: true,
ignoreClear: true,
offsetX: dx,
offsetY: dy,
scaleWidth: dw,
scaleHeight: dh
};
for (var prop in opts) {
if (opts.hasOwnProperty(prop)) {
cOpts[prop] = opts[prop];
}
}
canvg(this.canvas, s, cOpts);
};
}
svg.FRAMERATE = 30;
svg.MAX_VIRTUAL_PIXELS = 30000;
svg.log = function (msg) {};
if (svg.opts.log == true && typeof console != 'undefined') {
svg.log = function (msg) {
console.log(msg);
};
} // globals
svg.init = function (ctx) {
var uniqueId = 0;
svg.UniqueId = function () {
uniqueId++;
return 'canvg' + uniqueId;
};
svg.Definitions = {};
svg.Styles = {};
svg.StylesSpecificity = {};
svg.Animations = [];
svg.Images = [];
svg.ctx = ctx;
svg.ViewPort = new function () {
this.viewPorts = [];
this.Clear = function () {
this.viewPorts = [];
};
this.SetCurrent = function (width, height) {
this.viewPorts.push({
width: width,
height: height
});
};
this.RemoveCurrent = function () {
this.viewPorts.pop();
};
this.Current = function () {
return this.viewPorts[this.viewPorts.length - 1];
};
this.width = function () {
return this.Current().width;
};
this.height = function () {
return this.Current().height;
};
this.ComputeSize = function (d) {
if (d != null && typeof d == 'number') return d;
if (d == 'x') return this.width();
if (d == 'y') return this.height();
return Math.sqrt(Math.pow(this.width(), 2) + Math.pow(this.height(), 2)) / Math.sqrt(2);
};
}();
};
svg.init(); // images loaded
svg.ImagesLoaded = function () {
for (var i = 0; i < svg.Images.length; i++) {
if (!svg.Images[i].loaded) return false;
}
return true;
}; // trim
svg.trim = function (s) {
return s.replace(/^\s+|\s+$/g, '');
}; // compress spaces
svg.compressSpaces = function (s) {
return s.replace(/[\s\r\t\n]+/gm, ' ');
}; // ajax
svg.ajax = function (url) {
var AJAX;
if (window.XMLHttpRequest) {
AJAX = new XMLHttpRequest();
} else {
AJAX = new ActiveXObject('Microsoft.XMLHTTP');
}
if (AJAX) {
AJAX.open('GET', url, false);
AJAX.send(null);
return AJAX.responseText;
}
return null;
}; // parse xml
svg.parseXml = function (xml) {
if (typeof Windows != 'undefined' && typeof Windows.Data != 'undefined' && typeof Windows.Data.Xml != 'undefined') {
var xmlDoc = new Windows.Data.Xml.Dom.XmlDocument();
var settings = new Windows.Data.Xml.Dom.XmlLoadSettings();
settings.prohibitDtd = false;
xmlDoc.loadXml(xml, settings);
return xmlDoc;
} else if (window.DOMParser) {
var parser = new DOMParser();
return parser.parseFromString(xml, 'text/xml');
} else {
xml = xml.replace(/<!DOCTYPE svg[^>]*>/, '');
var xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
xmlDoc.async = 'false';
xmlDoc.loadXML(xml);
return xmlDoc;
}
};
svg.Property = function (name, value) {
this.name = name;
this.value = value;
};
svg.Property.prototype.getValue = function () {
return this.value;
};
svg.Property.prototype.hasValue = function () {
return this.value != null && this.value != '';
}; // return the numerical value of the property
svg.Property.prototype.numValue = function () {
if (!this.hasValue()) return 0;
var n = parseFloat(this.value);
if ((this.value + '').match(/%$/)) {
n = n / 100.0;
}
return n;
};
svg.Property.prototype.valueOrDefault = function (def) {
if (this.hasValue()) return this.value;
return def;
};
svg.Property.prototype.numValueOrDefault = function (def) {
if (this.hasValue()) return this.numValue();
return def;
}; // color extensions
// augment the current color value with the opacity
svg.Property.prototype.addOpacity = function (opacityProp) {
var newValue = this.value;
if (opacityProp.value != null && opacityProp.value != '' && typeof this.value == 'string') {
// can only add opacity to colors, not patterns
var color = new rgbcolor(this.value);
if (color.ok) {
newValue = 'rgba(' + color.r + ', ' + color.g + ', ' + color.b + ', ' + opacityProp.numValue() + ')';
}
}
return new svg.Property(this.name, newValue);
}; // definition extensions
// get the definition from the definitions table
svg.Property.prototype.getDefinition = function () {
var name = this.value.match(/#([^\)'"]+)/);
if (name) {
name = name[1];
}
if (!name) {
name = this.value;
}
return svg.Definitions[name];
};
svg.Property.prototype.isUrlDefinition = function () {
return this.value.indexOf('url(') == 0;
};
svg.Property.prototype.getFillStyleDefinition = function (e, opacityProp) {
var def = this.getDefinition(); // gradient
if (def != null && def.createGradient) {
return def.createGradient(svg.ctx, e, opacityProp);
} // pattern
if (def != null && def.createPattern) {
if (def.getHrefAttribute().hasValue()) {
var pt = def.attribute('patternTransform');
def = def.getHrefAttribute().getDefinition();
if (pt.hasValue()) {
def.attribute('patternTransform', true).value = pt.value;
}
}
return def.createPattern(svg.ctx, e);
}
return null;
}; // length extensions
svg.Property.prototype.getDPI = function (viewPort) {
return 96.0; // TODO: compute?
};
svg.Property.prototype.getEM = function (viewPort) {
var em = 12;
var fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize);
if (fontSize.hasValue()) em = fontSize.toPixels(viewPort);
return em;
};
svg.Property.prototype.getUnits = function () {
var s = this.value + '';
return s.replace(/[0-9\.\-]/g, '');
}; // get the length as pixels
svg.Property.prototype.toPixels = function (viewPort, processPercent) {
if (!this.hasValue()) return 0;
var s = this.value + '';
if (s.match(/em$/)) return this.numValue() * this.getEM(viewPort);
if (s.match(/ex$/)) return this.numValue() * this.getEM(viewPort) / 2.0;
if (s.match(/px$/)) return this.numValue();
if (s.match(/pt$/)) return this.numValue() * this.getDPI(viewPort) * (1.0 / 72.0);
if (s.match(/pc$/)) return this.numValue() * 15;
if (s.match(/cm$/)) return this.numValue() * this.getDPI(viewPort) / 2.54;
if (s.match(/mm$/)) return this.numValue() * this.getDPI(viewPort) / 25.4;
if (s.match(/in$/)) return this.numValue() * this.getDPI(viewPort);
if (s.match(/%$/)) return this.numValue() * svg.ViewPort.ComputeSize(viewPort);
var n = this.numValue();
if (processPercent && n < 1.0) return n * svg.ViewPort.ComputeSize(viewPort);
return n;
}; // time extensions
// get the time as milliseconds
svg.Property.prototype.toMilliseconds = function () {
if (!this.hasValue()) return 0;
var s = this.value + '';
if (s.match(/s$/)) return this.numValue() * 1000;
if (s.match(/ms$/)) return this.numValue();
return this.numValue();
}; // angle extensions
// get the angle as radians
svg.Property.prototype.toRadians = function () {
if (!this.hasValue()) return 0;
var s = this.value + '';
if (s.match(/deg$/)) return this.numValue() * (Math.PI / 180.0);
if (s.match(/grad$/)) return this.numValue() * (Math.PI / 200.0);
if (s.match(/rad$/)) return this.numValue();
return this.numValue() * (Math.PI / 180.0);
}; // text extensions
// get the text baseline
var textBaselineMapping = {
'baseline': 'alphabetic',
'before-edge': 'top',
'text-before-edge': 'top',
'middle': 'middle',
'central': 'middle',
'after-edge': 'bottom',
'text-after-edge': 'bottom',
'ideographic': 'ideographic',
'alphabetic': 'alphabetic',
'hanging': 'hanging',
'mathematical': 'alphabetic'
};
svg.Property.prototype.toTextBaseline = function () {
if (!this.hasValue()) return null;
return textBaselineMapping[this.value];
}; // fonts
svg.Font = new function () {
this.Styles = 'normal|italic|oblique|inherit';
this.Variants = 'normal|small-caps|inherit';
this.Weights = 'normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900|inherit';
this.CreateFont = function (fontStyle, fontVariant, fontWeight, fontSize, fontFamily, inherit) {
var f = inherit != null ? this.Parse(inherit) : this.CreateFont('', '', '', '', '', svg.ctx.font);
return {
fontFamily: fontFamily || f.fontFamily,
fontSize: fontSize || f.fontSize,
fontStyle: fontStyle || f.fontStyle,
fontWeight: fontWeight || f.fontWeight,
fontVariant: fontVariant || f.fontVariant,
toString: function toString() {
return [this.fontStyle, this.fontVariant, this.fontWeight, this.fontSize, this.fontFamily].join(' ');
}
};
};
var that = this;
this.Parse = function (s) {
var f = {};
var d = svg.trim(svg.compressSpaces(s || '')).split(' ');
var set = {
fontSize: false,
fontStyle: false,
fontWeight: false,
fontVariant: false
};
var ff = '';
for (var i = 0; i < d.length; i++) {
if (!set.fontStyle && that.Styles.indexOf(d[i]) != -1) {
if (d[i] != 'inherit') f.fontStyle = d[i];
set.fontStyle = true;
} else if (!set.fontVariant && that.Variants.indexOf(d[i]) != -1) {
if (d[i] != 'inherit') f.fontVariant = d[i];
set.fontStyle = set.fontVariant = true;
} else if (!set.fontWeight && that.Weights.indexOf(d[i]) != -1) {
if (d[i] != 'inherit') f.fontWeight = d[i];
set.fontStyle = set.fontVariant = set.fontWeight = true;
} else if (!set.fontSize) {
if (d[i] != 'inherit') f.fontSize = d[i].split('/')[0];
set.fontStyle = set.fontVariant = set.fontWeight = set.fontSize = true;
} else {
if (d[i] != 'inherit') ff += d[i];
}
}
if (ff != '') f.fontFamily = ff;
return f;
};
}(); // points and paths
svg.ToNumberArray = function (s) {
var a = svg.trim(svg.compressSpaces((s || '').replace(/,/g, ' '))).split(' ');
for (var i = 0; i < a.length; i++) {
a[i] = parseFloat(a[i]);
}
return a;
};
svg.Point = function (x, y) {
this.x = x;
this.y = y;
};
svg.Point.prototype.angleTo = function (p) {
return Math.atan2(p.y - this.y, p.x - this.x);
};
svg.Point.prototype.applyTransform = function (v) {
var xp = this.x * v[0] + this.y * v[2] + v[4];
var yp = this.x * v[1] + this.y * v[3] + v[5];
this.x = xp;
this.y = yp;
};
svg.CreatePoint = function (s) {
var a = svg.ToNumberArray(s);
return new svg.Point(a[0], a[1]);
};
svg.CreatePath = function (s) {
var a = svg.ToNumberArray(s);
var path = [];
for (var i = 0; i < a.length; i += 2) {
path.push(new svg.Point(a[i], a[i + 1]));
}
return path;
}; // bounding box
svg.BoundingBox = function (x1, y1, x2, y2) {
// pass in initial points if you want
this.x1 = Number.NaN;
this.y1 = Number.NaN;
this.x2 = Number.NaN;
this.y2 = Number.NaN;
this.x = function () {
return this.x1;
};
this.y = function () {
return this.y1;
};
this.width = function () {
return this.x2 - this.x1;
};
this.height = function () {
return this.y2 - this.y1;
};
this.addPoint = function (x, y) {
if (x != null) {
if (isNaN(this.x1) || isNaN(this.x2)) {
this.x1 = x;
this.x2 = x;
}
if (x < this.x1) this.x1 = x;
if (x > this.x2) this.x2 = x;
}
if (y != null) {
if (isNaN(this.y1) || isNaN(this.y2)) {
this.y1 = y;
this.y2 = y;
}
if (y < this.y1) this.y1 = y;
if (y > this.y2) this.y2 = y;
}
};
this.addX = function (x) {
this.addPoint(x, null);
};
this.addY = function (y) {
this.addPoint(null, y);
};
this.addBoundingBox = function (bb) {
this.addPoint(bb.x1, bb.y1);
this.addPoint(bb.x2, bb.y2);
};
this.addQuadraticCurve = function (p0x, p0y, p1x, p1y, p2x, p2y) {
var cp1x = p0x + 2 / 3 * (p1x - p0x); // CP1 = QP0 + 2/3 *(QP1-QP0)
var cp1y = p0y + 2 / 3 * (p1y - p0y); // CP1 = QP0 + 2/3 *(QP1-QP0)
var cp2x = cp1x + 1 / 3 * (p2x - p0x); // CP2 = CP1 + 1/3 *(QP2-QP0)
var cp2y = cp1y + 1 / 3 * (p2y - p0y); // CP2 = CP1 + 1/3 *(QP2-QP0)
this.addBezierCurve(p0x, p0y, cp1x, cp2x, cp1y, cp2y, p2x, p2y);
};
this.addBezierCurve = function (p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) {
// from http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
var p0 = [p0x, p0y],
p1 = [p1x, p1y],
p2 = [p2x, p2y],
p3 = [p3x, p3y];
this.addPoint(p0[0], p0[1]);
this.addPoint(p3[0], p3[1]);
for (var i = 0; i <= 1; i++) {
var f = function f(t) {
return Math.pow(1 - t, 3) * p0[i] + 3 * Math.pow(1 - t, 2) * t * p1[i] + 3 * (1 - t) * Math.pow(t, 2) * p2[i] + Math.pow(t, 3) * p3[i];
};
var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i];
var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i];
var c = 3 * p1[i] - 3 * p0[i];
if (a == 0) {
if (b == 0) continue;
var t = -c / b;
if (0 < t && t < 1) {
if (i == 0) this.addX(f(t));
if (i == 1) this.addY(f(t));
}
continue;
}
var b2ac = Math.pow(b, 2) - 4 * c * a;
if (b2ac < 0) continue;
var t1 = (-b + Math.sqrt(b2ac)) / (2 * a);
if (0 < t1 && t1 < 1) {
if (i == 0) this.addX(f(t1));
if (i == 1) this.addY(f(t1));
}
var t2 = (-b - Math.sqrt(b2ac)) / (2 * a);
if (0 < t2 && t2 < 1) {
if (i == 0) this.addX(f(t2));
if (i == 1) this.addY(f(t2));
}
}
};
this.isPointInBox = function (x, y) {
return this.x1 <= x && x <= this.x2 && this.y1 <= y && y <= this.y2;
};
this.addPoint(x1, y1);
this.addPoint(x2, y2);
}; // transforms
svg.Transform = function (v) {
var that = this;
this.Type = {}; // translate
this.Type.translate = function (s) {
this.p = svg.CreatePoint(s);
this.apply = function (ctx) {
ctx.translate(this.p.x || 0.0, this.p.y || 0.0);
};
this.unapply = function (ctx) {
ctx.translate(-1.0 * this.p.x || 0.0, -1.0 * this.p.y || 0.0);
};
this.applyToPoint = function (p) {
p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]);
};
}; // rotate
this.Type.rotate = function (s) {
var a = svg.ToNumberArray(s);
this.angle = new svg.Property('angle', a[0]);
this.cx = a[1] || 0;
this.cy = a[2] || 0;
this.apply = function (ctx) {
ctx.translate(this.cx, this.cy);
ctx.rotate(this.angle.toRadians());
ctx.translate(-this.cx, -this.cy);
};
this.unapply = function (ctx) {
ctx.translate(this.cx, this.cy);
ctx.rotate(-1.0 * this.angle.toRadians());
ctx.translate(-this.cx, -this.cy);
};
this.applyToPoint = function (p) {
var a = this.angle.toRadians();
p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]);
p.applyTransform([Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0]);
p.applyTransform([1, 0, 0, 1, -this.p.x || 0.0, -this.p.y || 0.0]);
};
};
this.Type.scale = function (s) {
this.p = svg.CreatePoint(s);
this.apply = function (ctx) {
ctx.scale(this.p.x || 1.0, this.p.y || this.p.x || 1.0);
};
this.unapply = function (ctx) {
ctx.scale(1.0 / this.p.x || 1.0, 1.0 / this.p.y || this.p.x || 1.0);
};
this.applyToPoint = function (p) {
p.applyTransform([this.p.x || 0.0, 0, 0, this.p.y || 0.0, 0, 0]);
};
};
this.Type.matrix = function (s) {
this.m = svg.ToNumberArray(s);
this.apply = function (ctx) {
ctx.transform(this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5]);
};
this.unapply = function (ctx) {
var a = this.m[0];
var b = this.m[2];
var c = this.m[4];
var d = this.m[1];
var e = this.m[3];
var f = this.m[5];
var g = 0.0;
var h = 0.0;
var i = 1.0;
var det = 1 / (a * (e * i - f * h) - b * (d * i - f * g) + c * (d * h - e * g));
ctx.transform(det * (e * i - f * h), det * (f * g - d * i), det * (c * h - b * i), det * (a * i - c * g), det * (b * f - c * e), det * (c * d - a * f));
};
this.applyToPoint = function (p) {
p.applyTransform(this.m);
};
};
this.Type.SkewBase = function (s) {
this.base = that.Type.matrix;
this.base(s);
this.angle = new svg.Property('angle', s);
};
this.Type.SkewBase.prototype = new this.Type.matrix();
this.Type.skewX = function (s) {
this.base = that.Type.SkewBase;
this.base(s);
this.m = [1, 0, Math.tan(this.angle.toRadians()), 1, 0, 0];
};
this.Type.skewX.prototype = new this.Type.SkewBase();
this.Type.skewY = function (s) {
this.base = that.Type.SkewBase;
this.base(s);
this.m = [1, Math.tan(this.angle.toRadians()), 0, 1, 0, 0];
};
this.Type.skewY.prototype = new this.Type.SkewBase();
this.transforms = [];
this.apply = function (ctx) {
for (var i = 0; i < this.transforms.length; i++) {
this.transforms[i].apply(ctx);
}
};
this.unapply = function (ctx) {
for (var i = this.transforms.length - 1; i >= 0; i--) {
this.transforms[i].unapply(ctx);
}
};
this.applyToPoint = function (p) {
for (var i = 0; i < this.transforms.length; i++) {
this.transforms[i].applyToPoint(p);
}
};
var data = svg.trim(svg.compressSpaces(v)).replace(/\)([a-zA-Z])/g, ') $1').replace(/\)(\s?,\s?)/g, ') ').split(/\s(?=[a-z])/);
for (var i = 0; i < data.length; i++) {
var type = svg.trim(data[i].split('(')[0]);
var s = data[i].split('(')[1].replace(')', '');
var transformType = this.Type[type];
if (typeof transformType != 'undefined') {
var transform = new transformType(s);
transform.type = type;
this.transforms.push(transform);
}
}
}; // aspect ratio
svg.AspectRatio = function (ctx, aspectRatio, width, desiredWidth, height, desiredHeight, minX, minY, refX, refY) {
// aspect ratio - http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
aspectRatio = svg.compressSpaces(aspectRatio);
aspectRatio = aspectRatio.replace(/^defer\s/, ''); // ignore defer
var align = aspectRatio.split(' ')[0] || 'xMidYMid';
var meetOrSlice = aspectRatio.split(' ')[1] || 'meet'; // calculate scale
var scaleX = width / desiredWidth;
var scaleY = height / desiredHeight;
var scaleMin = Math.min(scaleX, scaleY);
var scaleMax = Math.max(scaleX, scaleY);
if (meetOrSlice == 'meet') {
desiredWidth *= scaleMin;
desiredHeight *= scaleMin;
}
if (meetOrSlice == 'slice') {
desiredWidth *= scaleMax;
desiredHeight *= scaleMax;
}
refX = new svg.Property('refX', refX);
refY = new svg.Property('refY', refY);
if (refX.hasValue() && refY.hasValue()) {
ctx.translate(-scaleMin * refX.toPixels('x'), -scaleMin * refY.toPixels('y'));
} else {
// align
if (align.match(/^xMid/) && (meetOrSlice == 'meet' && scaleMin == scaleY || meetOrSlice == 'slice' && scaleMax == scaleY)) ctx.translate(width / 2.0 - desiredWidth / 2.0, 0);
if (align.match(/YMid$/) && (meetOrSlice == 'meet' && scaleMin == scaleX || meetOrSlice == 'slice' && scaleMax == scaleX)) ctx.translate(0, height / 2.0 - desiredHeight / 2.0);
if (align.match(/^xMax/) && (meetOrSlice == 'meet' && scaleMin == scaleY || meetOrSlice == 'slice' && scaleMax == scaleY)) ctx.translate(width - desiredWidth, 0);
if (align.match(/YMax$/) && (meetOrSlice == 'meet' && scaleMin == scaleX || meetOrSlice == 'slice' && scaleMax == scaleX)) ctx.translate(0, height - desiredHeight);
} // scale
if (align == 'none') ctx.scale(scaleX, scaleY);else if (meetOrSlice == 'meet') ctx.scale(scaleMin, scaleMin);else if (meetOrSlice == 'slice') ctx.scale(scaleMax, scaleMax); // translate
ctx.translate(minX == null ? 0 : -minX, minY == null ? 0 : -minY);
}; // elements
svg.Element = {};
svg.EmptyProperty = new svg.Property('EMPTY', '');
svg.Element.ElementBase = function (node) {
this.attributes = {};
this.styles = {};
this.stylesSpecificity = {};
this.children = []; // get or create attribute
this.attribute = function (name, createIfNotExists) {
var a = this.attributes[name];
if (a != null) return a;
if (createIfNotExists == true) {
a = new svg.Property(name, '');
this.attributes[name] = a;
}
return a || svg.EmptyProperty;
};
this.getHrefAttribute = function () {
for (var a in this.attributes) {
if (a == 'href' || a.match(/:href$/)) {
return this.attributes[a];
}
}
return svg.EmptyProperty;
}; // get or create style, crawls up node tree
this.style = function (name, createIfNotExists, skipAncestors) {
var s = this.styles[name];
if (s != null) return s;
var a = this.attribute(name);
if (a != null && a.hasValue()) {
this.styles[name] = a; // move up to me to cache
return a;
}
if (skipAncestors != true) {
var p = this.parent;
if (p != null) {
var ps = p.style(name);
if (ps != null && ps.hasValue()) {
return ps;
}
}
}
if (createIfNotExists == true) {
s = new svg.Property(name, '');
this.styles[name] = s;
}
return s || svg.EmptyProperty;
}; // base render
this.render = function (ctx) {
// don't render display=none
if (this.style('display').value == 'none') return; // don't render visibility=hidden
if (this.style('visibility').value == 'hidden') return;
ctx.save();
if (this.style('mask').hasValue()) {
// mask
var mask = this.style('mask').getDefinition();
if (mask != null) mask.apply(ctx, this);
} else if (this.style('filter').hasValue()) {
// filter
var filter = this.style('filter').getDefinition();
if (filter != null) filter.apply(ctx, this);
} else {
this.setContext(ctx);
this.renderChildren(ctx);
this.clearContext(ctx);
}
ctx.restore();
}; // base set context
this.setContext = function (ctx) {// OVERRIDE ME!
}; // base clear context
this.clearContext = function (ctx) {// OVERRIDE ME!
}; // base render children
this.renderChildren = function (ctx) {
for (var i = 0; i < this.children.length; i++) {
this.children[i].render(ctx);
}
};
this.addChild = function (childNode, create) {
var child = childNode;
if (create) child = svg.CreateElement(childNode);
child.parent = this;
if (child.type != 'title') {
this.children.push(child);
}
};
this.addStylesFromStyleDefinition = function () {
// add styles
for (var selector in svg.Styles) {
if (selector[0] != '@' && matchesSelector(node, selector)) {
var styles = svg.Styles[selector];
var specificity = svg.StylesSpecificity[selector];
if (styles != null) {
for (var name in styles) {
var existingSpecificity = this.stylesSpecificity[name];
if (typeof existingSpecificity == 'undefined') {
existingSpecificity = '000';
}
if (specificity > existingSpecificity) {
this.styles[name] = styles[name];
this.stylesSpecificity[name] = specificity;
}
}
}
}
}
};
if (node != null && node.nodeType == 1) {
//ELEMENT_NODE
// add attributes
for (var i = 0; i < node.attributes.length; i++) {
var attribute = node.attributes[i];
this.attributes[attribute.nodeName] = new svg.Property(attribute.nodeName, attribute.value);
}
this.addStylesFromStyleDefinition(); // add inline styles
if (this.attribute('style').hasValue()) {
var styles = this.attribute('style').value.split(';');
for (var i = 0; i < styles.length; i++) {
if (svg.trim(styles[i]) != '') {
var style = styles[i].split(':');
var name = svg.trim(style[0]);
var value = svg.trim(style[1]);
this.styles[name] = new svg.Property(name, value);
}
}
} // add id
if (this.attribute('id').hasValue()) {
if (svg.Definitions[this.attribute('id').value] == null) {
svg.Definitions[this.attribute('id').value] = this;
}
} // add children
for (var i = 0; i < node.childNodes.length; i++) {
var childNode = node.childNodes[i];
if (childNode.nodeType == 1) this.addChild(childNode, true); //ELEMENT_NODE
if (this.captureTextNodes && (childNode.nodeType == 3 || childNode.nodeType == 4)) {
var text = childNode.value || childNode.text || childNode.textContent || '';
if (svg.compressSpaces(text) != '') {
this.addChild(new svg.Element.tspan(childNode), false); // TEXT_NODE
}
}
}
}
};
svg.Element.RenderedElementBase = function (node) {
this.base = svg.Element.ElementBase;
this.base(node);
this.setContext = function (ctx) {
// fill
if (this.style('fill').isUrlDefinition()) {
var fs = this.style('fill').getFillStyleDefinition(this, this.style('fill-opacity'));
if (fs != null) ctx.fillStyle = fs;
} else if (this.style('fill').hasValue()) {
var fillStyle = this.style('fill');
if (fillStyle.value == 'currentColor') fillStyle.value = this.style('color').value;
if (fillStyle.value != 'inherit') ctx.fillStyle = fillStyle.value == 'none' ? 'rgba(0,0,0,0)' : fillStyle.value;
}
if (this.style('fill-opacity').hasValue()) {
var fillStyle = new svg.Property('fill', ctx.fillStyle);
fillStyle = fillStyle.addOpacity(this.style('fill-opacity'));
ctx.fillStyle = fillStyle.value;
} // stroke
if (this.style('stroke').isUrlDefinition()) {
var fs = this.style('stroke').getFillStyleDefinition(this, this.style('stroke-opacity'));
if (fs != null) ctx.strokeStyle = fs;
} else if (this.style('stroke').hasValue()) {
var strokeStyle = this.style('stroke');
if (strokeStyle.value == 'currentColor') strokeStyle.value = this.style('color').value;
if (strokeStyle.value != 'inherit') ctx.strokeStyle = strokeStyle.value == 'none' ? 'rgba(0,0,0,0)' : strokeStyle.value;
}
if (this.style('stroke-opacity').hasValue()) {
var strokeStyle = new svg.Property('stroke', ctx.strokeStyle);
strokeStyle = strokeStyle.addOpacity(this.style('stroke-opacity'));
ctx.strokeStyle = strokeStyle.value;
}
if (this.style('stroke-width').hasValue()) {
var newLineWidth = this.style('stroke-width').toPixels();
ctx.lineWidth = newLineWidth == 0 ? 0.001 : newLineWidth; // browsers don't respect 0
}
if (this.style('stroke-linecap').hasValue()) ctx.lineCap = this.style('stroke-linecap').value;
if (this.style('stroke-linejoin').hasValue()) ctx.lineJoin = this.style('stroke-linejoin').value;
if (this.style('stroke-miterlimit').hasValue()) ctx.miterLimit = this.style('stroke-miterlimit').value;
if (this.style('stroke-dasharray').hasValue() && this.style('stroke-dasharray').value != 'none') {
var gaps = svg.ToNumberArray(this.style('stroke-dasharray').value);
if (typeof ctx.setLineDash != 'undefined') {
ctx.setLineDash(gaps);
} else if (typeof ctx.webkitLineDash != 'undefined') {
ctx.webkitLineDash = gaps;
} else if (typeof ctx.mozDash != 'undefined' && !(gaps.length == 1 && gaps[0] == 0)) {
ctx.mozDash = gaps;
}
var offset = this.style('stroke-dashoffset').numValueOrDefault(1);
if (typeof ctx.lineDashOffset != 'undefined') {
ctx.lineDashOffset = offset;
} else if (typeof ctx.webkitLineDashOffset != 'undefined') {
ctx.webkitLineDashOffset = offset;
} else if (typeof ctx.mozDashOffset != 'undefined') {
ctx.mozDashOffset = offset;
}
} // font
if (typeof ctx.font != 'undefined') {
ctx.font = svg.Font.CreateFont(this.style('font-style').value, this.style('font-variant').value, this.style('font-weight').value, this.style('font-size').hasValue() ? this.style('font-size').toPixels() + 'px' : '', this.style('font-family').value).toString();
} // transform
if (this.style('transform', false, true).hasValue()) {
var transform = new svg.Transform(this.style('transform', false, true).value);
transform.apply(ctx);
} // clip
if (this.style('clip-path', false, true).hasValue()) {
var clip = this.style('clip-path', false, true).getDefinition();
if (clip != null) clip.apply(ctx);
} // opacity
if (this.style('opacity').hasValue()) {
ctx.globalAlpha = this.style('opacity').numValue();
}
};
};
svg.Element.RenderedElementBase.prototype = new svg.Element.ElementBase();
svg.Element.PathElementBase = function (node) {
this.base = svg.Element.RenderedElementBase;
this.base(node);
this.path = function (ctx) {
if (ctx != null) ctx.beginPath();
return new svg.BoundingBox();
};
this.renderChildren = function (ctx) {
this.path(ctx);
svg.Mouse.checkPath(this, ctx);
if (ctx.fillStyle != '') {
if (this.style('fill-rule').valueOrDefault('inherit') != 'inherit') {
ctx.fill(this.style('fill-rule').value);
} else {
ctx.fill();
}
}
if (ctx.strokeStyle != '') ctx.stroke();
var markers = this.getMarkers();
if (markers != null) {
if (this.style('marker-start').isUrlDefinition()) {
var marker = this.style('marker-start').getDefinition();
marker.render(ctx, markers[0][0], markers[0][1]);
}
if (this.style('marker-mid').isUrlDefinition()) {
var marker = this.style('marker-mid').getDefinition();
for (var i = 1; i < markers.length - 1; i++) {
marker.render(ctx, markers[i][0], markers[i][1]);
}
}
if (this.style('marker-end').isUrlDefinition()) {
var marker = this.style('marker-end').getDefinition();
marker.render(ctx, markers[markers.length - 1][0], markers[markers.length - 1][1]);
}
}
};
this.getBoundingBox = function () {
return this.path();
};
this.getMarkers = function () {
return null;
};
};
svg.Element.PathElementBase.prototype = new svg.Element.RenderedElementBase(); // svg element
svg.Element.svg = function (node) {
this.base = svg.Element.RenderedElementBase;
this.base(node);
this.baseClearContext = this.clearContext;
this.clearContext = function (ctx) {
this.baseClearContext(ctx);
svg.ViewPort.RemoveCurrent();
};
this.baseSetContext = this.setContext;
this.setContext = function (ctx) {
// initial values and defaults
ctx.strokeStyle = 'rgba(0,0,0,0)';
ctx.lineCap = 'butt';
ctx.lineJoin = 'miter';
ctx.miterLimit = 4;
if (typeof ctx.font != 'undefined' && typeof window.getComputedStyle != 'undefined') {
ctx.font = window.getComputedStyle(ctx.canvas).getPropertyValue('font');
}
this.baseSetContext(ctx); // create new view port
if (!this.attribute('x').hasValue()) this.attribute('x', true).value = 0;
if (!this.attribute('y').hasValue()) this.attribute('y', true).value = 0;
ctx.translate(this.attribute('x').toPixels('x'), this.attribute('y').toPixels('y'));
var width = svg.ViewPort.width();
var height = svg.ViewPort.height();
if (!this.attribute('width').hasValue()) this.attribute('width', true).value = '100%';
if (!this.attribute('height').hasValue()) this.attribute('height', true).value = '100%';
if (typeof this.root == 'undefined') {
width = this.attribute('width').toPixels('x');
height = this.attribute('height').toPixels('y');
var x = 0;
var y = 0;
if (this.attribute('refX').hasValue() && this.attribute('refY').hasValue()) {
x = -this.attribute('refX').toPixels('x');
y = -this.attribute('refY').toPixels('y');
}
if (this.attribute('overflow').valueOrDefault('hidden') != 'visible') {
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(width, y);
ctx.lineTo(width, height);
ctx.lineTo(x, height);
ctx.closePath();
ctx.clip();
}
}
svg.ViewPort.SetCurrent(width, height); // viewbox
if (this.attribute('viewBox').hasValue()) {
var viewBox = svg.ToNumberArray(this.attribute('viewBox').value);
var minX = viewBox[0];
var minY = viewBox[1];
width = viewBox[2];
height = viewBox[3];
svg.AspectRatio(ctx, this.attribute('preserveAspectRatio').value, svg.ViewPort.width(), width, svg.ViewPort.height(), height, minX, minY, this.attribute('refX').value, this.attribute('refY').value);
svg.ViewPort.RemoveCurrent();
svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]);
}
};
};
svg.Element.svg.prototype = new svg.Element.RenderedElementBase(); // rect element
svg.Element.rect = function (node) {
this.base = svg.Element.PathElementBase;
this.base(node);
this.path = function (ctx) {
var x = this.attribute('x').toPixels('x');
var y = this.attribute('y').toPixels('y');
var width = this.attribute('width').toPixels('x');
var height = this.attribute('height').toPixels('y');
var rx = this.attribute('rx').toPixels('x');
var ry = this.attribute('ry').toPixels('y');
if (this.attribute('rx').hasValue() && !this.attribute('ry').hasValue()) ry = rx;
if (this.attribute('ry').hasValue() && !this.attribute('rx').hasValue()) rx = ry;
rx = Math.min(rx, width / 2.0);
ry = Math.min(ry, height / 2.0);
if (ctx != null) {
ctx.beginPath();
ctx.moveTo(x + rx, y);
ctx.lineTo(x + width - rx, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + ry);
ctx.lineTo(x + width, y + height - ry);
ctx.quadraticCurveTo(x + width, y + height, x + width - rx, y + height);
ctx.lineTo(x + rx, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - ry);
ctx.lineTo(x, y + ry);
ctx.quadraticCurveTo(x, y, x + rx, y);
ctx.closePath();
}
return new svg.BoundingBox(x, y, x + width, y + height);
};
};
svg.Element.rect.prototype = new svg.Element.PathElementBase(); // circle element
svg.Element.circle = function (node) {
this.base = svg.Element.PathElementBase;
this.base(node);
this.path = function (ctx) {
var cx = this.attribute('cx').toPixels('x');
var cy = this.attribute('cy').toPixels('y');
var r = this.attribute('r').toPixels();
if (ctx != null) {
ctx.beginPath();
ctx.arc(cx, cy, r, 0, Math.PI * 2, true);
ctx.closePath();
}
return new svg.BoundingBox(cx - r, cy - r, cx + r, cy + r);
};
};
svg.Element.circle.prototype = new svg.Element.PathElementBase(); // ellipse element
svg.Element.ellipse = function (node) {
this.base = svg.Element.PathElementBase;
this.base(node);
this.path = function (ctx) {
var KAPPA = 4 * ((Math.sqrt(2) - 1) / 3);
var rx = this.attribute('rx').toPixels('x');
var ry = this.attribute('ry').toPixels('y');
var cx = this.attribute('cx').toPixels('x');
var cy = this.attribute('cy').toPixels('y');
if (ctx != null) {
ctx.beginPath();
ctx.moveTo(cx, cy - ry);
ctx.bezierCurveTo(cx + KAPPA * rx, cy - ry, cx + rx, cy - KAPPA * ry, cx + rx, cy);
ctx.bezierCurveTo(cx + rx, cy + KAPPA * ry, cx + KAPPA * rx, cy + ry, cx, cy + ry);
ctx.bezierCurveTo(cx - KAPPA * rx, cy + ry, cx - rx, cy + KAPPA * ry, cx - rx, cy);
ctx.bezierCurveTo(cx - rx, cy - KAPPA * ry, cx - KAPPA * rx, cy - ry, cx, cy - ry);
ctx.closePath();
}
return new svg.BoundingBox(cx - rx, cy - ry, cx + rx, cy + ry);
};
};
svg.Element.ellipse.prototype = new svg.Element.PathElementBase(); // line element
svg.Element.line = function (node) {
this.base = svg.Element.PathElementBase;
this.base(node);
this.getPoints = function () {
return [new svg.Point(this.attribute('x1').toPixels('x'), this.attribute('y1').toPixels('y')), new svg.Point(this.attribute('x2').toPixels('x'), this.attribute('y2').toPixels('y'))];
};
this.path = function (ctx) {
var points = this.getPoints();
if (ctx != null) {
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
ctx.lineTo(points[1].x, points[1].y);
}
return new svg.BoundingBox(points[0].x, points[0].y, points[1].x, points[1].y);
};
this.getMarkers = function () {
var points = this.getPoints();
var a = points[0].angleTo(points[1]);
return [[points[0], a], [points[1], a]];
};
};
svg.Element.line.prototype = new svg.Element.PathElementBase(); // polyline element
svg.Element.polyline = function (node) {
this.base = svg.Element.PathElementBase;
this.base(node);
this.points = svg.CreatePath(this.attribute('points').value);
this.path = function (ctx) {
var bb = new svg.BoundingBox(this.points[0].x, this.points[0].y);
if (ctx != null) {
ctx.beginPath();
ctx.moveTo(this.points[0].x, this.points[0].y);
}
for (var i = 1; i < this.points.length; i++) {
bb.addPoint(this.points[i].x, this.points[i].y);
if (ctx != null) ctx.lineTo(this.points[i].x, this.points[i].y);
}
return bb;
};
this.getMarkers = function () {
var markers = [];
for (var i = 0; i < this.points.length - 1; i++) {
markers.push([this.points[i], this.points[i].angleTo(this.points[i + 1])]);
}
if (markers.length > 0) {
markers.push([this.points[this.points.length - 1], markers[markers.length - 1][1]]);
}
return markers;
};
};
svg.Element.polyline.prototype = new svg.Element.PathElementBase(); // polygon element
svg.Element.polygon = function (node) {
this.base = svg.Element.polyline;
this.base(node);
this.basePath = this.path;
this.path = function (ctx) {
var bb = this.basePath(ctx);
if (ctx != null) {
ctx.lineTo(this.points[0].x, this.points[0].y);
ctx.closePath();
}
return bb;
};
};
svg.Element.polygon.prototype = new svg.Element.polyline(); // path element
svg.Element.path = function (node) {
this.base = svg.Element.PathElementBase;
this.base(node);
var d = this.attribute('d').value; // TODO: convert to real lexer based on http://www.w3.org/TR/SVG11/paths.html#PathDataBNF
d = d.replace(/,/gm, ' '); // get rid of all commas
// As the end of a match can also be the start of the next match, we need to run this replace twice.
for (var i = 0; i < 2; i++) {
d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\s])/gm, '$1 $2');
} // suffix commands with spaces
d = d.replace(/([^\s])([MmZzLlHhVvCcSsQqTtAa])/gm, '$1 $2'); // prefix commands with spaces
d = d.replace(/([0-9])([+\-])/gm, '$1 $2'); // separate digits on +- signs
// Again, we need to run this twice to find all occurances
for (var i = 0; i < 2; i++) {
d = d.replace(/(\.[0-9]*)(\.)/gm, '$1 $2');
} // separate digits when they start with a comma
d = d.replace(/([Aa](\s+[0-9]+){3})\s+([01])\s*([01])/gm, '$1 $3 $4 '); // shorthand elliptical arc path syntax
d = svg.compressSpaces(d); // compress multiple spaces
d = svg.trim(d);
this.PathParser = new function (d) {
this.tokens = d.split(' ');
this.reset = function () {
this.i = -1;
this.command = '';
this.previousCommand = '';
this.start = new svg.Point(0, 0);
this.control = new svg.Point(0, 0);
this.current = new svg.Point(0, 0);
this.points = [];
this.angles = [];
};
this.isEnd = function () {
return this.i >= this.tokens.length - 1;
};
this.isCommandOrEnd = function () {
if (this.isEnd()) return true;
return this.tokens[this.i + 1].match(/^[A-Za-z]$/) != null;
};
this.isRelativeCommand = function () {
switch (this.command) {
case 'm':
case 'l':
case 'h':
case 'v':
case 'c':
case 's':
case 'q':
case 't':
case 'a':
case 'z':
return true;
}
return false;
};
this.getToken = function () {
this.i++;
return this.tokens[this.i];
};
this.getScalar = function () {
return parseFloat(this.getToken());
};
this.nextCommand = function () {
this.previousCommand = this.command;
this.command = this.getToken();
};
this.getPoint = function () {
var p = new svg.Point(this.getScalar(), this.getScalar());
return this.makeAbsolute(p);
};
this.getAsControlPoint = function () {
var p = this.getPoint();
this.control = p;
return p;
};
this.getAsCurrentPoint = function () {
var p = this.getPoint();
this.current = p;
return p;
};
this.getReflectedControlPoint = function () {
if (this.previousCommand.toLowerCase() != 'c' && this.previousCommand.toLowerCase() != 's' && this.previousCommand.toLowerCase() != 'q' && this.previousCommand.toLowerCase() != 't') {
return this.current;
} // reflect point
var p = new svg.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y);
return p;
};
this.makeAbsolute = function (p) {
if (this.isRelativeCommand()) {
p.x += this.current.x;
p.y += this.current.y;
}
return p;
};
this.addMarker = function (p, from, priorTo) {
// if the last angle isn't filled in because we didn't have this point yet ...
if (priorTo != null && this.angles.length > 0 && this.angles[this.angles.length - 1] == null) {
this.angles[this.angles.length - 1] = this.points[this.points.length - 1].angleTo(priorTo);
}
this.addMarkerAngle(p, from == null ? null : from.angleTo(p));
};
this.addMarkerAngle = function (p, a) {
this.points.push(p);
this.angles.push(a);
};
this.getMarkerPoints = function () {
return this.points;
};
this.getMarkerAngles = function () {
for (var i = 0; i < this.angles.length; i++) {
if (this.angles[i] == null) {
for (var j = i + 1; j < this.angles.length; j++) {
if (this.angles[j] != null) {
this.angles[i] = this.angles[j];
break;
}
}
}
}
return this.angles;
};
}(d);
this.path = function (ctx) {
var pp = this.PathParser;
pp.reset();
var bb = new svg.BoundingBox();
if (ctx != null) ctx.beginPath();
while (!pp.isEnd()) {
pp.nextCommand();
switch (pp.command) {
case 'M':
case 'm':
var p = pp.getAsCurrentPoint();
pp.addMarker(p);
bb.addPoint(p.x, p.y);
if (ctx != null) ctx.moveTo(p.x, p.y);
pp.start = pp.current;
while (!pp.isCommandOrEnd()) {
var p = pp.getAsCurrentPoint();
pp.addMarker(p, pp.start);
bb.addPoint(p.x, p.y);
if (ctx != null) ctx.lineTo(p.x, p.y);
}
break;
case 'L':
case 'l':
while (!pp.isCommandOrEnd()) {
var c = pp.current;
var p = pp.getAsCurrentPoint();
pp.addMarker(p, c);
bb.addPoint(p.x, p.y);
if (ctx != null) ctx.lineTo(p.x, p.y);
}
break;
case 'H':
case 'h':
while (!pp.isCommandOrEnd()) {
var newP = new svg.Point((pp.isRelativeCommand() ? pp.current.x : 0) + pp.getScalar(), pp.current.y);
pp.addMarker(newP, pp.current);
pp.current = newP;
bb.addPoint(pp.current.x, pp.current.y);
if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
}
break;
case 'V':
case 'v':
while (!pp.isCommandOrEnd()) {
var newP = new svg.Point(pp.current.x, (pp.isRelativeCommand() ? pp.current.y : 0) + pp.getScalar());
pp.addMarker(newP, pp.current);
pp.current = newP;
bb.addPoint(pp.current.x, pp.current.y);
if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
}
break;
case 'C':
case 'c':
while (!pp.isCommandOrEnd()) {
var curr = pp.current;
var p1 = pp.getPoint();
var cntrl = pp.getAsControlPoint();
var cp = pp.getAsCurrentPoint();
pp.addMarker(cp, cntrl, p1);
bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
}
break;
case 'S':
case 's':
while (!pp.isCommandOrEnd()) {
var curr = pp.current;
var p1 = pp.getReflectedControlPoint();
var cntrl = pp.getAsControlPoint();
var cp = pp.getAsCurrentPoint();
pp.addMarker(cp, cntrl, p1);
bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
}
break;
case 'Q':
case 'q':
while (!pp.isCommandOrEnd()) {
var curr = pp.current;
var cntrl = pp.getAsControlPoint();
var cp = pp.getAsCurrentPoint();
pp.addMarker(cp, cntrl, cntrl);
bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
}
break;
case 'T':
case 't':
while (!pp.isCommandOrEnd()) {
var curr = pp.current;
var cntrl = pp.getReflectedControlPoint();
pp.control = cntrl;
var cp = pp.getAsCurrentPoint();
pp.addMarker(cp, cntrl, cntrl);
bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
}
break;
case 'A':
case 'a':
while (!pp.isCommandOrEnd()) {
var curr = pp.current;
var rx = pp.getScalar();
var ry = pp.getScalar();
var xAxisRotation = pp.getScalar() * (Math.PI / 180.0);
var largeArcFlag = pp.getScalar();
var sweepFlag = pp.getScalar();
var cp = pp.getAsCurrentPoint(); // Conversion from endpoint to center parameterization
// http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
// x1', y1'
var currp = new svg.Point(Math.cos(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.sin(xAxisRotation) * (curr.y - cp.y) / 2.0, -Math.sin(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.cos(xAxisRotation) * (curr.y - cp.y) / 2.0); // adjust radii
var l = Math.pow(currp.x, 2) / Math.pow(rx, 2) + Math.pow(currp.y, 2) / Math.pow(ry, 2);
if (l > 1) {
rx *= Math.sqrt(l);
ry *= Math.sqrt(l);
} // cx', cy'
var s = (largeArcFlag == sweepFlag ? -1 : 1) * Math.sqrt((Math.pow(rx, 2) * Math.pow(ry, 2) - Math.pow(rx, 2) * Math.pow(currp.y, 2) - Math.pow(ry, 2) * Math.pow(currp.x, 2)) / (Math.pow(rx, 2) * Math.pow(currp.y, 2) + Math.pow(ry, 2) * Math.pow(currp.x, 2)));
if (isNaN(s)) s = 0;
var cpp = new svg.Point(s * rx * currp.y / ry, s * -ry * currp.x / rx); // cx, cy
var centp = new svg.Point((curr.x + cp.x) / 2.0 + Math.cos(xAxisRotation) * cpp.x - Math.sin(xAxisRotation) * cpp.y, (curr.y + cp.y) / 2.0 + Math.sin(xAxisRotation) * cpp.x + Math.cos(xAxisRotation) * cpp.y); // vector magnitude
var m = function m(v) {
return Math.sqrt(Math.pow(v[0], 2) + Math.pow(v[1], 2));
}; // ratio between two vectors
var r = function r(u, v) {
return (u[0] * v[0] + u[1] * v[1]) / (m(u) * m(v));
}; // angle between two vectors
var a = function a(u, v) {
return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) * Math.acos(r(u, v));
}; // initial angle
var a1 = a([1, 0], [(currp.x - cpp.x) / rx, (currp.y - cpp.y) / ry]); // angle delta
var u = [(currp.x - cpp.x) / rx, (currp.y - cpp.y) / ry];
var v = [(-currp.x - cpp.x) / rx, (-currp.y - cpp.y) / ry];
var ad = a(u, v);
if (r(u, v) <= -1) ad = Math.PI;
if (r(u, v) >= 1) ad = 0; // for markers
var dir = 1 - sweepFlag ? 1.0 : -1.0;
var ah = a1 + dir * (ad / 2.0);
var halfWay = new svg.Point(centp.x + rx * Math.cos(ah), centp.y + ry * Math.sin(ah));
pp.addMarkerAngle(halfWay, ah - dir * Math.PI / 2);
pp.addMarkerAngle(cp, ah - dir * Math.PI);
bb.addPoint(cp.x, cp.y); // TODO: this is too naive, make it better
if (ctx != null) {
var r = rx > ry ? rx : ry;
var sx = rx > ry ? 1 : rx / ry;
var sy = rx > ry ? ry / rx : 1;
ctx.translate(centp.x, centp.y);
ctx.rotate(xAxisRotation);
ctx.scale(sx, sy);
ctx.arc(0, 0, r, a1, a1 + ad, 1 - sweepFlag);
ctx.scale(1 / sx, 1 / sy);
ctx.rotate(-xAxisRotation);
ctx.translate(-centp.x, -centp.y);
}
}
break;
case 'Z':
case 'z':
if (ctx != null) ctx.closePath();
pp.current = pp.start;
}
}
return bb;
};
this.getMarkers = function () {
var points = this.PathParser.getMarkerPoints();
var angles = this.PathParser.getMarkerAngles();
var markers = [];
for (var i = 0; i < points.length; i++) {
markers.push([points[i], angles[i]]);
}
return markers;
};
};
svg.Element.path.prototype = new svg.Element.PathElementBase(); // pattern element
svg.Element.pattern = function (node) {
this.base = svg.Element.ElementBase;
this.base(node);
this.createPattern = function (ctx, element) {
var width = this.attribute('width').toPixels('x', true);
var height = this.attribute('height').toPixels('y', true); // render me using a temporary svg element
var tempSvg = new svg.Element.svg();
tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value);
tempSvg.attributes['width'] = new svg.Property('width', width + 'px');
tempSvg.attributes['height'] = new svg.Property('height', height + 'px');
tempSvg.attributes['transform'] = new svg.Property('transform', this.attribute('patternTransform').value);
tempSvg.children = this.children;
var c = document.createElement('canvas');
c.width = width;
c.height = height;
var cctx = c.getContext('2d');
if (this.attribute('x').hasValue() && this.attribute('y').hasValue()) {
cctx.translate(this.attribute('x').toPixels('x', true), this.attribute('y').toPixels('y', true));
} // render 3x3 grid so when we transform there's no white space on edges
for (var x = -1; x <= 1; x++) {
for (var y = -1; y <= 1; y++) {
cctx.save();
tempSvg.attributes['x'] = new svg.Property('x', x * c.width);
tempSvg.attributes['y'] = new svg.Property('y', y * c.height);
tempSvg.render(cctx);
cctx.restore();
}
}
var pattern = ctx.createPattern(c, 'repeat');
return pattern;
};
};
svg.Element.pattern.prototype = new svg.Element.ElementBase(); // marker element
svg.Element.marker = function (node) {
this.base = svg.Element.ElementBase;
this.base(node);
this.baseRender = this.render;
this.render = function (ctx, point, angle) {
ctx.translate(point.x, point.y);
if (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(angle);
if (this.attribute('markerUnits').valueOrDefault('strokeWidth') == 'strokeWidth') ctx.scale(ctx.lineWidth, ctx.lineWidth);
ctx.save(); // render me using a temporary svg element
var tempSvg = new svg.Element.svg();
tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value);
tempSvg.attributes['refX'] = new svg.Property('refX', this.attribute('refX').value);
tempSvg.attributes['refY'] = new svg.Property('refY', this.attribute('refY').value);
tempSvg.attributes['width'] = new svg.Property('width', this.attribute('markerWidth').value);
tempSvg.attributes['height'] = new svg.Property('height', this.attribute('markerHeight').value);
tempSvg.attributes['fill'] = new svg.Property('fill', this.attribute('fill').valueOrDefault('black'));
tempSvg.attributes['stroke'] = new svg.Property('stroke', this.attribute('stroke').valueOrDefault('none'));
tempSvg.children = this.children;
tempSvg.render(ctx);
ctx.restore();
if (this.attribute('markerUnits').valueOrDefault('strokeWidth') == 'strokeWidth') ctx.scale(1 / ctx.lineWidth, 1 / ctx.lineWidth);
if (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(-angle);
ctx.translate(-point.x, -point.y);
};
};
svg.Element.marker.prototype = new svg.Element.ElementBase(); // definitions element
svg.Element.defs = function (node) {
this.base = svg.Element.ElementBase;
this.base(node);
this.render = function (ctx) {// NOOP
};
};
svg.Element.defs.prototype = new svg.Element.ElementBase(); // base for gradients
svg.Element.GradientBase = function (node) {
this.base = svg.Element.ElementBase;
this.base(node);
this.stops = [];
for (var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if (child.type == 'stop') this.stops.push(child);
}
this.getGradient = function () {// OVERRIDE ME!
};
this.gradientUnits = function () {
return this.attribute('gradientUnits').valueOrDefault('objectBoundingBox');
};
this.attributesToInherit = ['gradientUnits'];
this.inheritStopContainer = function (stopsContainer) {
for (var i = 0; i < this.attributesToInherit.length; i++) {
var attributeToInherit = this.attributesToInherit[i];
if (!this.attribute(attributeToInherit).hasValue() && stopsContainer.attribute(attributeToInherit).hasValue()) {
this.attribute(attributeToInherit, true).value = stopsContainer.attribute(attributeToInherit).value;
}
}
};
this.createGradient = function (ctx, element, parentOpacityProp) {
var stopsContainer = this;
if (this.getHrefAttribute().hasValue()) {
stopsContainer = this.getHrefAttribute().getDefinition();
this.inheritStopContainer(stopsContainer);
}
var addParentOpacity = function addParentOpacity(color) {
if (parentOpacityProp.hasValue()) {
var p = new svg.Property('color', color);
return p.addOpacity(parentOpacityProp).value;
}
return color;
};
var g = this.getGradient(ctx, element);
if (g == null) return addParentOpacity(stopsContainer.stops[stopsContainer.stops.length - 1].color);
for (var i = 0; i < stopsContainer.stops.length; i++) {
g.addColorStop(stopsContainer.stops[i].offset, addParentOpacity(stopsContainer.stops[i].color));
}
if (this.attribute('gradientTransform').hasValue()) {
// render as transformed pattern on temporary canvas
var rootView = svg.ViewPort.viewPorts[0];
var rect = new svg.Element.rect();
rect.attributes['x'] = new svg.Property('x', -svg.MAX_VIRTUAL_PIXELS / 3.0);
rect.attributes['y'] = new svg.Property('y', -svg.MAX_VIRTUAL_PIXELS / 3.0);
rect.attributes['width'] = new svg.Property('width', svg.MAX_VIRTUAL_PIXELS);
rect.attributes['height'] = new svg.Property('height', svg.MAX_VIRTUAL_PIXELS);
var group = new svg.Element.g();
group.attributes['transform'] = new svg.Property('transform', this.attribute('gradientTransform').value);
group.children = [rect];
var tempSvg = new svg.Element.svg();
tempSvg.attributes['x'] = new svg.Property('x', 0);
tempSvg.attributes['y'] = new svg.Property('y', 0);
tempSvg.attributes['width'] = new svg.Property('width', rootView.width);
tempSvg.attributes['height'] = new svg.Property('height', rootView.height);
tempSvg.children = [group];
var c = document.createElement('canvas');
c.width = rootView.width;
c.height = rootView.height;
var tempCtx = c.getContext('2d');
tempCtx.fillStyle = g;
tempSvg.render(tempCtx);
return tempCtx.createPattern(c, 'no-repeat');
}
return g;
};
};
svg.Element.GradientBase.prototype = new svg.Element.ElementBase(); // linear gradient element
svg.Element.linearGradient = function (node) {
this.base = svg.Element.GradientBase;
this.base(node);
this.attributesToInherit.push('x1');
this.attributesToInherit.push('y1');
this.attributesToInherit.push('x2');
this.attributesToInherit.push('y2');
this.getGradient = function (ctx, element) {
var bb = this.gradientUnits() == 'objectBoundingBox' ? element.getBoundingBox() : null;
if (!this.attribute('x1').hasValue() && !this.attribute('y1').hasValue() && !this.attribute('x2').hasValue() && !this.attribute('y2').hasValue()) {
this.attribute('x1', true).value = 0;
this.attribute('y1', true).value = 0;
this.attribute('x2', true).value = 1;
this.attribute('y2', true).value = 0;
}
var x1 = this.gradientUnits() == 'objectBoundingBox' ? bb.x() + bb.width() * this.attribute('x1').numValue() : this.attribute('x1').toPixels('x');
var y1 = this.gradientUnits() == 'objectBoundingBox' ? bb.y() + bb.height() * this.attribute('y1').numValue() : this.attribute('y1').toPixels('y');
var x2 = this.gradientUnits() == 'objectBoundingBox' ? bb.x() + bb.width() * this.attribute('x2').numValue() : this.attribute('x2').toPixels('x');
var y2 = this.gradientUnits() == 'objectBoundingBox' ? bb.y() + bb.height() * this.attribute('y2').numValue() : this.attribute('y2').toPixels('y');
if (x1 == x2 && y1 == y2) return null;
return ctx.createLinearGradient(x1, y1, x2, y2);
};
};
svg.Element.linearGradient.prototype = new svg.Element.GradientBase(); // radial gradient element
svg.Element.radialGradient = function (node) {
this.base = svg.Element.GradientBase;
this.base(node);
this.attributesToInherit.push('cx');
this.attributesToInherit.push('cy');
this.attributesToInherit.push('r');
this.attributesToInherit.push('fx');
this.attributesToInherit.push('fy');
this.getGradient = function (ctx, element) {
var bb = element.getBoundingBox();
if (!this.attribute('cx').hasValue()) this.attribute('cx', true).value = '50%';
if (!this.attribute('cy').hasValue()) this.attribute('cy', true).value = '50%';
if (!this.attribute('r').hasValue()) this.attribute('r', true).value = '50%';
var cx = this.gradientUnits() == 'objectBoundingBox' ? bb.x() + bb.width() * this.attribute('cx').numValue() : this.attribute('cx').toPixels('x');
var cy = this.gradientUnits() == 'objectBoundingBox' ? bb.y() + bb.height() * this.attribute('cy').numValue() : this.attribute('cy').toPixels('y');
var fx = cx;
var fy = cy;
if (this.attribute('fx').hasValue()) {
fx = this.gradientUnits() == 'objectBoundingBox' ? bb.x() + bb.width() * this.attribute('fx').numValue() : this.attribute('fx').toPixels('x');
}
if (this.attribute('fy').hasValue()) {
fy = this.gradientUnits() == 'objectBoundingBox' ? bb.y() + bb.height() * this.attribute('fy').numValue() : this.attribute('fy').toPixels('y');
}
var r = this.gradientUnits() == 'objectBoundingBox' ? (bb.width() + bb.height()) / 2.0 * this.attribute('r').numValue() : this.attribute('r').toPixels();
return ctx.createRadialGradient(fx, fy, 0, cx, cy, r);
};
};
svg.Element.radialGradient.prototype = new svg.Element.GradientBase(); // gradient stop element
svg.Element.stop = function (node) {
this.base = svg.Element.ElementBase;
this.base(node);
this.offset = this.attribute('offset').numValue();
if (this.offset < 0) this.offset = 0;
if (this.offset > 1) this.offset = 1;
var stopColor = this.style('stop-color', true);
if (stopColor.value == '') stopColor.value = '#000';
if (this.style('stop-opacity').hasValue()) stopColor = stopColor.addOpacity(this.style('stop-opacity'));
this.color = stopColor.value;
};
svg.Element.stop.prototype = new svg.Element.ElementBase(); // animation base element
svg.Element.AnimateBase = function (node) {
this.base = svg.Element.ElementBase;
this.base(node);
svg.Animations.push(this);
this.duration = 0.0;
this.begin = this.attribute('begin').toMilliseconds();
this.maxDuration = this.begin + this.attribute('dur').toMilliseconds();
this.getProperty = function () {
var attributeType = this.attribute('attributeType').value;
var attributeName = this.attribute('attributeName').value;
if (attributeType == 'CSS') {
return this.parent.style(attributeName, true);
}
return this.parent.attribute(attributeName, true);
};
this.initialValue = null;
this.initialUnits = '';
this.removed = false;
this.calcValue = function () {
// OVERRIDE ME!
return '';
};
this.update = function (delta) {
// set initial value
if (this.initialValue == null) {
this.initialValue = this.getProperty().value;
this.initialUnits = this.getProperty().getUnits();
} // if we're past the end time
if (this.duration > this.maxDuration) {
// loop for indefinitely repeating animations
if (this.attribute('repeatCount').value == 'indefinite' || this.attribute('repeatDur').value == 'indefinite') {
this.duration = 0.0;
} else if (this.attribute('fill').valueOrDefault('remove') == 'freeze' && !this.frozen) {
this.frozen = true;
this.parent.animationFrozen = true;
this.parent.animationFrozenValue = this.getProperty().value;
} else if (this.attribute('fill').valueOrDefault('remove') == 'remove' && !this.removed) {
this.removed = true;
this.getProperty().value = this.parent.animationFrozen ? this.parent.animationFrozenValue : this.initialValue;
return true;
}
return false;
}
this.duration = this.duration + delta; // if we're past the begin time
var updated = false;
if (this.begin < this.duration) {
var newValue = this.calcValue(); // tween
if (this.attribute('type').hasValue()) {
// for transform, etc.
var type = this.attribute('type').value;
newValue = type + '(' + newValue + ')';
}
this.getProperty().value = newValue;
updated = true;
}
return updated;
};
this.from = this.attribute('from');
this.to = this.attribute('to');
this.values = this.attribute('values');
if (this.values.hasValue()) this.values.value = this.values.value.split(';'); // fraction of duration we've covered
this.progress = function () {
var ret = {
progress: (this.duration - this.begin) / (this.maxDuration - this.begin)
};
if (this.values.hasValue()) {
var p = ret.progress * (this.values.value.length - 1);
var lb = Math.floor(p),
ub = Math.ceil(p);
ret.from = new svg.Property('from', parseFloat(this.values.value[lb]));
ret.to = new svg.Property('to', parseFloat(this.values.value[ub]));
ret.progress = (p - lb) / (ub - lb);
} else {
ret.from = this.from;
ret.to = this.to;
}
return ret;
};
};
svg.Element.AnimateBase.prototype = new svg.Element.ElementBase(); // animate element
svg.Element.animate = function (node) {
this.base = svg.Element.AnimateBase;
this.base(node);
this.calcValue = function () {
var p = this.progress(); // tween value linearly
var newValue = p.from.numValue() + (p.to.numValue() - p.from.numValue()) * p.progress;
return newValue + this.initialUnits;
};
};
svg.Element.animate.prototype = new svg.Element.AnimateBase(); // animate color element
svg.Element.animateColor = function (node) {
this.base = svg.Element.AnimateBase;
this.base(node);
this.calcValue = function () {
var p = this.progress();
var from = new rgbcolor(p.from.value);
var to = new rgbcolor(p.to.value);
if (from.ok && to.ok) {
// tween color linearly
var r = from.r + (to.r - from.r) * p.progress;
var g = from.g + (to.g - from.g) * p.progress;
var b = from.b + (to.b - from.b) * p.progress;
return 'rgb(' + parseInt(r, 10) + ',' + parseInt(g, 10) + ',' + parseInt(b, 10) + ')';
}
return this.attribute('from').value;
};
};
svg.Element.animateColor.prototype = new svg.Element.AnimateBase(); // animate transform element
svg.Element.animateTransform = function (node) {
this.base = svg.Element.AnimateBase;
this.base(node);
this.calcValue = function () {
var p = this.progress(); // tween value linearly
var from = svg.ToNumberArray(p.from.value);
var to = svg.ToNumberArray(p.to.value);
var newValue = '';
for (var i = 0; i < from.length; i++) {
newValue += from[i] + (to[i] - from[i]) * p.progress + ' ';
}
return newValue;
};
};
svg.Element.animateTransform.prototype = new svg.Element.animate(); // font element
svg.Element.font = function (node) {
this.base = svg.Element.ElementBase;
this.base(node);
this.horizAdvX = this.attribute('horiz-adv-x').numValue();
this.isRTL = false;
this.isArabic = false;
this.fontFace = null;
this.missingGlyph = null;
this.glyphs = [];
for (var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if (child.type == 'font-face') {
this.fontFace = child;
if (child.style('font-family').hasValue()) {
svg.Definitions[child.style('font-family').value] = this;
}
} else if (child.type == 'missing-glyph') this.missingGlyph = child;else if (child.type == 'glyph') {
if (child.arabicForm != '') {
this.isRTL = true;
this.isArabic = true;
if (typeof this.glyphs[child.unicode] == 'undefined') this.glyphs[child.unicode] = [];
this.glyphs[child.unicode][child.arabicForm] = child;
} else {
this.glyphs[child.unicode] = child;
}
}
}
};
svg.Element.font.prototype = new svg.Element.ElementBase(); // font-face element
svg.Element.fontface = function (node) {
this.base = svg.Element.ElementBase;
this.base(node);
this.ascent = this.attribute('ascent').value;
this.descent = this.attribute('descent').value;
this.unitsPerEm = this.attribute('units-per-em').numValue();
};
svg.Element.fontface.prototype = new svg.Element.ElementBase(); // missing-glyph element
svg.Element.missingglyph = function (node) {
this.base = svg.Element.path;
this.base(node);
this.horizAdvX = 0;
};
svg.Element.missingglyph.prototype = new svg.Element.path(); // glyph element
svg.Element.glyph = function (node) {
this.base = svg.Element.path;
this.base(node);
this.horizAdvX = this.attribute('horiz-adv-x').numValue();
this.unicode = this.attribute('unicode').value;
this.arabicForm = this.attribute('arabic-form').value;
};
svg.Element.glyph.prototype = new svg.Element.path(); // text element
svg.Element.text = function (node) {
this.captureTextNodes = true;
this.base = svg.Element.RenderedElementBase;
this.base(node);
this.baseSetContext = this.setContext;
this.setContext = function (ctx) {
this.baseSetContext(ctx);
var textBaseline = this.style('dominant-baseline').toTextBaseline();
if (textBaseline == null) textBaseline = this.style('alignment-baseline').toTextBaseline();
if (textBaseline != null) ctx.textBaseline = textBaseline;
};
this.getBoundingBox = function () {
var x = this.attribute('x').toPixels('x');
var y = this.attribute('y').toPixels('y');
var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
return new svg.BoundingBox(x, y - fontSize, x + Math.floor(fontSize * 2.0 / 3.0) * this.children[0].getText().length, y);
};
this.renderChildren = function (ctx) {
this.x = this.attribute('x').toPixels('x');
this.y = this.attribute('y').toPixels('y');
if (this.attribute('dx').hasValue()) this.x += this.attribute('dx').toPixels('x');
if (this.attribute('dy').hasValue()) this.y += this.attribute('dy').toPixels('y');
this.x += this.getAnchorDelta(ctx, this, 0);
for (var i = 0; i < this.children.length; i++) {
this.renderChild(ctx, this, this, i);
}
};
this.getAnchorDelta = function (ctx, parent, startI) {
var textAnchor = this.style('text-anchor').valueOrDefault('start');
if (textAnchor != 'start') {
var width = 0;
for (var i = startI; i < parent.children.length; i++) {
var child = parent.children[i];
if (i > startI && child.attribute('x').hasValue()) break; // new group
width += child.measureTextRecursive(ctx);
}
return -1 * (textAnchor == 'end' ? width : width / 2.0);
}
return 0;
};
this.renderChild = function (ctx, textParent, parent, i) {
var child = parent.children[i];
if (child.attribute('x').hasValue()) {
child.x = child.attribute('x').toPixels('x') + textParent.getAnchorDelta(ctx, parent, i);
if (child.attribute('dx').hasValue()) child.x += child.attribute('dx').toPixels('x');
} else {
if (child.attribute('dx').hasValue()) textParent.x += child.attribute('dx').toPixels('x');
child.x = textParent.x;
}
textParent.x = child.x + child.measureText(ctx);
if (child.attribute('y').hasValue()) {
child.y = child.attribute('y').toPixels('y');
if (child.attribute('dy').hasValue()) child.y += child.attribute('dy').toPixels('y');
} else {
if (child.attribute('dy').hasValue()) textParent.y += child.attribute('dy').toPixels('y');
child.y = textParent.y;
}
textParent.y = child.y;
child.render(ctx);
for (var i = 0; i < child.children.length; i++) {
textParent.renderChild(ctx, textParent, child, i);
}
};
};
svg.Element.text.prototype = new svg.Element.RenderedElementBase(); // text base
svg.Element.TextElementBase = function (node) {
this.base = svg.Element.RenderedElementBase;
this.base(node);
this.getGlyph = function (font, text, i) {
var c = text[i];
var glyph = null;
if (font.isArabic) {
var arabicForm = 'isolated';
if ((i == 0 || text[i - 1] == ' ') && i < text.length - 2 && text[i + 1] != ' ') arabicForm = 'terminal';
if (i > 0 && text[i - 1] != ' ' && i < text.length - 2 && text[i + 1] != ' ') arabicForm = 'medial';
if (i > 0 && text[i - 1] != ' ' && (i == text.length - 1 || text[i + 1] == ' ')) arabicForm = 'initial';
if (typeof font.glyphs[c] != 'undefined') {
glyph = font.glyphs[c][arabicForm];
if (glyph == null && font.glyphs[c].type == 'glyph') glyph = font.glyphs[c];
}
} else {
glyph = font.glyphs[c];
}
if (glyph == null) glyph = font.missingGlyph;
return glyph;
};
this.renderChildren = function (ctx) {
var customFont = this.parent.style('font-family').getDefinition();
if (customFont != null) {
var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
var fontStyle = this.parent.style('font-style').valueOrDefault(svg.Font.Parse(svg.ctx.font).fontStyle);
var text = this.getText();
if (customFont.isRTL) text = text.split("").reverse().join("");
var dx = svg.ToNumberArray(this.parent.attribute('dx').value);
for (var i = 0; i < text.length; i++) {
var glyph = this.getGlyph(customFont, text, i);
var scale = fontSize / customFont.fontFace.unitsPerEm;
ctx.translate(this.x, this.y);
ctx.scale(scale, -scale);
var lw = ctx.lineWidth;
ctx.lineWidth = ctx.lineWidth * customFont.fontFace.unitsPerEm / fontSize;
if (fontStyle == 'italic') ctx.transform(1, 0, .4, 1, 0, 0);
glyph.render(ctx);
if (fontStyle == 'italic') ctx.transform(1, 0, -.4, 1, 0, 0);
ctx.lineWidth = lw;
ctx.scale(1 / scale, -1 / scale);
ctx.translate(-this.x, -this.y);
this.x += fontSize * (glyph.horizAdvX || customFont.horizAdvX) / customFont.fontFace.unitsPerEm;
if (typeof dx[i] != 'undefined' && !isNaN(dx[i])) {
this.x += dx[i];
}
}
return;
}
if (ctx.fillStyle != '') ctx.fillText(svg.compressSpaces(this.getText()), this.x, this.y);
if (ctx.strokeStyle != '') ctx.strokeText(svg.compressSpaces(this.getText()), this.x, this.y);
};
this.getText = function () {// OVERRIDE ME
};
this.measureTextRecursive = function (ctx) {
var width = this.measureText(ctx);
for (var i = 0; i < this.children.length; i++) {
width += this.children[i].measureTextRecursive(ctx);
}
return width;
};
this.measureText = function (ctx) {
var customFont = this.parent.style('font-family').getDefinition();
if (customFont != null) {
var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
var measure = 0;
var text = this.getText();
if (customFont.isRTL) text = text.split("").reverse().join("");
var dx = svg.ToNumberArray(this.parent.attribute('dx').value);
for (var i = 0; i < text.length; i++) {
var glyph = this.getGlyph(customFont, text, i);
measure += (glyph.horizAdvX || customFont.horizAdvX) * fontSize / customFont.fontFace.unitsPerEm;
if (typeof dx[i] != 'undefined' && !isNaN(dx[i])) {
measure += dx[i];
}
}
return measure;
}
var textToMeasure = svg.compressSpaces(this.getText());
if (!ctx.measureText) return textToMeasure.length * 10;
ctx.save();
this.setContext(ctx);
var width = ctx.measureText(textToMeasure).width;
ctx.restore();
return width;
};
};
svg.Element.TextElementBase.prototype = new svg.Element.RenderedElementBase(); // tspan
svg.Element.tspan = function (node) {
this.captureTextNodes = true;
this.base = svg.Element.TextElementBase;
this.base(node);
this.text = svg.compressSpaces(node.value || node.text || node.textContent || '');
this.getText = function () {
// if this node has children, then they own the text
if (this.children.length > 0) {
return '';
}
return this.text;
};
};
svg.Element.tspan.prototype = new svg.Element.TextElementBase(); // tref
svg.Element.tref = function (node) {
this.base = svg.Element.TextElementBase;
this.base(node);
this.getText = function () {
var element = this.getHrefAttribute().getDefinition();
if (element != null) return element.children[0].getText();
};
};
svg.Element.tref.prototype = new svg.Element.TextElementBase(); // a element
svg.Element.a = function (node) {
this.base = svg.Element.TextElementBase;
this.base(node);
this.hasText = node.childNodes.length > 0;
for (var i = 0; i < node.childNodes.length; i++) {
if (node.childNodes[i].nodeType != 3) this.hasText = false;
} // this might contain text
this.text = this.hasText ? node.childNodes[0].value : '';
this.getText = function () {
return this.text;
};
this.baseRenderChildren = this.renderChildren;
this.renderChildren = function (ctx) {
if (this.hasText) {
// render as text element
this.baseRenderChildren(ctx);
var fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize);
svg.Mouse.checkBoundingBox(this, new svg.BoundingBox(this.x, this.y - fontSize.toPixels('y'), this.x + this.measureText(ctx), this.y));
} else if (this.children.length > 0) {
// render as temporary group
var g = new svg.Element.g();
g.children = this.children;
g.parent = this;
g.render(ctx);
}
};
this.onclick = function () {
window.open(this.getHrefAttribute().value);
};
this.onmousemove = function () {
svg.ctx.canvas.style.cursor = 'pointer';
};
};
svg.Element.a.prototype = new svg.Element.TextElementBase(); // image element
svg.Element.image = function (node) {
this.base = svg.Element.RenderedElementBase;
this.base(node);
var href = this.getHrefAttribute().value;
if (href == '') {
return;
}
var isSvg = href.match(/\.svg$/);
svg.Images.push(this);
this.loaded = false;
if (!isSvg) {
this.img = document.createElement('img');
if (svg.opts['useCORS'] == true) {
this.img.crossOrigin = 'Anonymous';
}
var self = this;
this.img.onload = function () {
self.loaded = true;
};
this.img.onerror = function () {
svg.log('ERROR: image "' + href + '" not found');
self.loaded = true;
};
this.img.src = href;
} else {
this.img = svg.ajax(href);
this.loaded = true;
}
this.renderChildren = function (ctx) {
var x = this.attribute('x').toPixels('x');
var y = this.attribute('y').toPixels('y');
var width = this.attribute('width').toPixels('x');
var height = this.attribute('height').toPixels('y');
if (width == 0 || height == 0) return;
ctx.save();
if (isSvg) {
ctx.drawSvg(this.img, x, y, width, height);
} else {
ctx.translate(x, y);
svg.AspectRatio(ctx, this.attribute('preserveAspectRatio').value, width, this.img.width, height, this.img.height, 0, 0);
ctx.drawImage(this.img, 0, 0);
}
ctx.restore();
};
this.getBoundingBox = function () {
var x = this.attribute('x').toPixels('x');
var y = this.attribute('y').toPixels('y');
var width = this.attribute('width').toPixels('x');
var height = this.attribute('height').toPixels('y');
return new svg.BoundingBox(x, y, x + width, y + height);
};
};
svg.Element.image.prototype = new svg.Element.RenderedElementBase(); // group element
svg.Element.g = function (node) {
this.base = svg.Element.RenderedElementBase;
this.base(node);
this.getBoundingBox = function () {
var bb = new svg.BoundingBox();
for (var i = 0; i < this.children.length; i++) {
bb.addBoundingBox(this.children[i].getBoundingBox());
}
return bb;
};
};
svg.Element.g.prototype = new svg.Element.RenderedElementBase(); // symbol element
svg.Element.symbol = function (node) {
this.base = svg.Element.RenderedElementBase;
this.base(node);
this.render = function (ctx) {// NO RENDER
};
};
svg.Element.symbol.prototype = new svg.Element.RenderedElementBase(); // style element
svg.Element.style = function (node) {
this.base = svg.Element.ElementBase;
this.base(node); // text, or spaces then CDATA
var css = '';
for (var i = 0; i < node.childNodes.length; i++) {
css += node.childNodes[i].data;
}
css = css.replace(/(\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)|(^[\s]*\/\/.*)/gm, ''); // remove comments
css = svg.compressSpaces(css); // replace whitespace
var cssDefs = css.split('}');
for (var i = 0; i < cssDefs.length; i++) {
if (svg.trim(cssDefs[i]) != '') {
var cssDef = cssDefs[i].split('{');
var cssClasses = cssDef[0].split(',');
var cssProps = cssDef[1].split(';');
for (var j = 0; j < cssClasses.length; j++) {
var cssClass = svg.trim(cssClasses[j]);
if (cssClass != '') {
var props = svg.Styles[cssClass] || {};
for (var k = 0; k < cssProps.length; k++) {
var prop = cssProps[k].indexOf(':');
var name = cssProps[k].substr(0, prop);
var value = cssProps[k].substr(prop + 1, cssProps[k].length - prop);
if (name != null && value != null) {
props[svg.trim(name)] = new svg.Property(svg.trim(name), svg.trim(value));
}
}
svg.Styles[cssClass] = props;
svg.StylesSpecificity[cssClass] = getSelectorSpecificity(cssClass);
if (cssClass == '@font-face') {
var fontFamily = props['font-family'].value.replace(/"/g, '');
var srcs = props['src'].value.split(',');
for (var s = 0; s < srcs.length; s++) {
if (srcs[s].indexOf('format("svg")') > 0) {
var urlStart = srcs[s].indexOf('url');
var urlEnd = srcs[s].indexOf(')', urlStart);
var url = srcs[s].substr(urlStart + 5, urlEnd - urlStart - 6);
var doc = svg.parseXml(svg.ajax(url));
var fonts = doc.getElementsByTagName('font');
for (var f = 0; f < fonts.length; f++) {
var font = svg.CreateElement(fonts[f]);
svg.Definitions[fontFamily] = font;
}
}
}
}
}
}
}
}
};
svg.Element.style.prototype = new svg.Element.ElementBase(); // use element
svg.Element.use = function (node) {
this.base = svg.Element.RenderedElementBase;
this.base(node);
this.baseSetContext = this.setContext;
this.setContext = function (ctx) {
this.baseSetContext(ctx);
if (this.attribute('x').hasValue()) ctx.translate(this.attribute('x').toPixels('x'), 0);
if (this.attribute('y').hasValue()) ctx.translate(0, this.attribute('y').toPixels('y'));
};
var element = this.getHrefAttribute().getDefinition();
this.path = function (ctx) {
if (element != null) element.path(ctx);
};
this.getBoundingBox = function () {
if (element != null) return element.getBoundingBox();
};
this.renderChildren = function (ctx) {
if (element != null) {
var tempSvg = element;
if (element.type == 'symbol') {
// render me using a temporary svg element in symbol cases (http://www.w3.org/TR/SVG/struct.html#UseElement)
tempSvg = new svg.Element.svg();
tempSvg.type = 'svg';
tempSvg.attributes['viewBox'] = new svg.Property('viewBox', element.attribute('viewBox').value);
tempSvg.attributes['preserveAspectRatio'] = new svg.Property('preserveAspectRatio', element.attribute('preserveAspectRatio').value);
tempSvg.attributes['overflow'] = new svg.Property('overflow', element.attribute('overflow').value);
tempSvg.children = element.children;
}
if (tempSvg.type == 'svg') {
// if symbol or svg, inherit width/height from me
if (this.attribute('width').hasValue()) tempSvg.attributes['width'] = new svg.Property('width', this.attribute('width').value);
if (this.attribute('height').hasValue()) tempSvg.attributes['height'] = new svg.Property('height', this.attribute('height').value);
}
var oldParent = tempSvg.parent;
tempSvg.parent = null;
tempSvg.render(ctx);
tempSvg.parent = oldParent;
}
};
};
svg.Element.use.prototype = new svg.Element.RenderedElementBase(); // mask element
svg.Element.mask = function (node) {
this.base = svg.Element.ElementBase;
this.base(node);
this.apply = function (ctx, element) {
// render as temp svg
var x = this.attribute('x').toPixels('x');
var y = this.attribute('y').toPixels('y');
var width = this.attribute('width').toPixels('x');
var height = this.attribute('height').toPixels('y');
if (width == 0 && height == 0) {
var bb = new svg.BoundingBox();
for (var i = 0; i < this.children.length; i++) {
bb.addBoundingBox(this.children[i].getBoundingBox());
}
var x = Math.floor(bb.x1);
var y = Math.floor(bb.y1);
var width = Math.floor(bb.width());
var height = Math.floor(bb.height());
} // temporarily remove mask to avoid recursion
var mask = element.attribute('mask').value;
element.attribute('mask').value = '';
var cMask = document.createElement('canvas');
cMask.width = x + width;
cMask.height = y + height;
var maskCtx = cMask.getContext('2d');
this.renderChildren(maskCtx);
var c = document.createElement('canvas');
c.width = x + width;
c.height = y + height;
var tempCtx = c.getContext('2d');
element.render(tempCtx);
tempCtx.globalCompositeOperation = 'destination-in';
tempCtx.fillStyle = maskCtx.createPattern(cMask, 'no-repeat');
tempCtx.fillRect(0, 0, x + width, y + height);
ctx.fillStyle = tempCtx.createPattern(c, 'no-repeat');
ctx.fillRect(0, 0, x + width, y + height); // reassign mask
element.attribute('mask').value = mask;
};
this.render = function (ctx) {// NO RENDER
};
};
svg.Element.mask.prototype = new svg.Element.ElementBase(); // clip element
svg.Element.clipPath = function (node) {
this.base = svg.Element.ElementBase;
this.base(node);
this.apply = function (ctx) {
var oldBeginPath = CanvasRenderingContext2D.prototype.beginPath;
CanvasRenderingContext2D.prototype.beginPath = function () {};
var oldClosePath = CanvasRenderingContext2D.prototype.closePath;
CanvasRenderingContext2D.prototype.closePath = function () {};
oldBeginPath.call(ctx);
for (var i = 0; i < this.children.length; i++) {
var child = this.children[i];
if (typeof child.path != 'undefined') {
var transform = null;
if (child.style('transform', false, true).hasValue()) {
transform = new svg.Transform(child.style('transform', false, true).value);
transform.apply(ctx);
}
child.path(ctx);
CanvasRenderingContext2D.prototype.closePath = oldClosePath;
if (transform) {
transform.unapply(ctx);
}
}
}
oldClosePath.call(ctx);
ctx.clip();
CanvasRenderingContext2D.prototype.beginPath = oldBeginPath;
CanvasRenderingContext2D.prototype.closePath = oldClosePath;
};
this.render = function (ctx) {// NO RENDER
};
};
svg.Element.clipPath.prototype = new svg.Element.ElementBase(); // filters
svg.Element.filter = function (node) {
this.base = svg.Element.ElementBase;
this.base(node);
this.apply = function (ctx, element) {
// render as temp svg
var bb = element.getBoundingBox();
var x = Math.floor(bb.x1);
var y = Math.floor(bb.y1);
var width = Math.floor(bb.width());
var height = Math.floor(bb.height()); // temporarily remove filter to avoid recursion
var filter = element.style('filter').value;
element.style('filter').value = '';
var px = 0,
py = 0;
for (var i = 0; i < this.children.length; i++) {
var efd = this.children[i].extraFilterDistance || 0;
px = Math.max(px, efd);
py = Math.max(py, efd);
}
var c = document.createElement('canvas');
c.width = width + 2 * px;
c.height = height + 2 * py;
var tempCtx = c.getContext('2d');
tempCtx.translate(-x + px, -y + py);
element.render(tempCtx); // apply filters
for (var i = 0; i < this.children.length; i++) {
if (typeof this.children[i].apply == 'function') {
this.children[i].apply(tempCtx, 0, 0, width + 2 * px, height + 2 * py);
}
} // render on me
ctx.drawImage(c, 0, 0, width + 2 * px, height + 2 * py, x - px, y - py, width + 2 * px, height + 2 * py); // reassign filter
element.style('filter', true).value = filter;
};
this.render = function (ctx) {// NO RENDER
};
};
svg.Element.filter.prototype = new svg.Element.ElementBase();
svg.Element.feMorphology = function (node) {
this.base = svg.Element.ElementBase;
this.base(node);
this.apply = function (ctx, x, y, width, height) {// TODO: implement
};
};
svg.Element.feMorphology.prototype = new svg.Element.ElementBase();
svg.Element.feComposite = function (node) {
this.base = svg.Element.ElementBase;
this.base(node);
this.apply = function (ctx, x, y, width, height) {// TODO: implement
};
};
svg.Element.feComposite.prototype = new svg.Element.ElementBase();
svg.Element.feColorMatrix = function (node) {
this.base = svg.Element.ElementBase;
this.base(node);
var matrix = svg.ToNumberArray(this.attribute('values').value);
switch (this.attribute('type').valueOrDefault('matrix')) {
// http://www.w3.org/TR/SVG/filters.html#feColorMatrixElement
case 'saturate':
var s = matrix[0];
matrix = [0.213 + 0.787 * s, 0.715 - 0.715 * s, 0.072 - 0.072 * s, 0, 0, 0.213 - 0.213 * s, 0.715 + 0.285 * s, 0.072 - 0.072 * s, 0, 0, 0.213 - 0.213 * s, 0.715 - 0.715 * s, 0.072 + 0.928 * s, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1];
break;
case 'hueRotate':
var a = matrix[0] * Math.PI / 180.0;
var c = function c(m1, m2, m3) {
return m1 + Math.cos(a) * m2 + Math.sin(a) * m3;
};
matrix = [c(0.213, 0.787, -0.213), c(0.715, -0.715, -0.715), c(0.072, -0.072, 0.928), 0, 0, c(0.213, -0.213, 0.143), c(0.715, 0.285, 0.140), c(0.072, -0.072, -0.283), 0, 0, c(0.213, -0.213, -0.787), c(0.715, -0.715, 0.715), c(0.072, 0.928, 0.072), 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1];
break;
case 'luminanceToAlpha':
matrix = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2125, 0.7154, 0.0721, 0, 0, 0, 0, 0, 0, 1];
break;
}
function imGet(img, x, y, width, height, rgba) {
return img[y * width * 4 + x * 4 + rgba];
}
function imSet(img, x, y, width, height, rgba, val) {
img[y * width * 4 + x * 4 + rgba] = val;
}
function m(i, v) {
var mi = matrix[i];
return mi * (mi < 0 ? v - 255 : v);
}
this.apply = function (ctx, x, y, width, height) {
// assuming x==0 && y==0 for now
var srcData = ctx.getImageData(0, 0, width, height);
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var r = imGet(srcData.data, x, y, width, height, 0);
var g = imGet(srcData.data, x, y, width, height, 1);
var b = imGet(srcData.data, x, y, width, height, 2);
var a = imGet(srcData.data, x, y, width, height, 3);
imSet(srcData.data, x, y, width, height, 0, m(0, r) + m(1, g) + m(2, b) + m(3, a) + m(4, 1));
imSet(srcData.data, x, y, width, height, 1, m(5, r) + m(6, g) + m(7, b) + m(8, a) + m(9, 1));
imSet(srcData.data, x, y, width, height, 2, m(10, r) + m(11, g) + m(12, b) + m(13, a) + m(14, 1));
imSet(srcData.data, x, y, width, height, 3, m(15, r) + m(16, g) + m(17, b) + m(18, a) + m(19, 1));
}
}
ctx.clearRect(0, 0, width, height);
ctx.putImageData(srcData, 0, 0);
};
};
svg.Element.feColorMatrix.prototype = new svg.Element.ElementBase();
svg.Element.feGaussianBlur = function (node) {
this.base = svg.Element.ElementBase;
this.base(node);
this.blurRadius = Math.floor(this.attribute('stdDeviation').numValue());
this.extraFilterDistance = this.blurRadius;
this.apply = function (ctx, x, y, width, height) {
if (typeof stackblur.canvasRGBA == 'undefined') {
svg.log('ERROR: StackBlur.js must be included for blur to work');
return;
} // StackBlur requires canvas be on document
ctx.canvas.id = svg.UniqueId();
ctx.canvas.style.display = 'none';
document.body.appendChild(ctx.canvas);
stackblur.canvasRGBA(ctx.canvas.id, x, y, width, height, this.blurRadius);
document.body.removeChild(ctx.canvas);
};
};
svg.Element.feGaussianBlur.prototype = new svg.Element.ElementBase(); // title element, do nothing
svg.Element.title = function (node) {};
svg.Element.title.prototype = new svg.Element.ElementBase(); // desc element, do nothing
svg.Element.desc = function (node) {};
svg.Element.desc.prototype = new svg.Element.ElementBase();
svg.Element.MISSING = function (node) {
svg.log('ERROR: Element \'' + node.nodeName + '\' not yet implemented.');
};
svg.Element.MISSING.prototype = new svg.Element.ElementBase(); // element factory
svg.CreateElement = function (node) {
var className = node.nodeName.replace(/^[^:]+:/, ''); // remove namespace
className = className.replace(/\-/g, ''); // remove dashes
var e = null;
if (typeof svg.Element[className] != 'undefined') {
e = new svg.Element[className](node);
} else {
e = new svg.Element.MISSING(node);
}
e.type = node.nodeName;
return e;
}; // load from url
svg.load = function (ctx, url) {
svg.loadXml(ctx, svg.ajax(url));
}; // load from xml
svg.loadXml = function (ctx, xml) {
svg.loadXmlDoc(ctx, svg.parseXml(xml));
};
svg.loadXmlDoc = function (ctx, dom) {
svg.init(ctx);
var mapXY = function mapXY(p) {
var e = ctx.canvas;
while (e) {
p.x -= e.offsetLeft;
p.y -= e.offsetTop;
e = e.offsetParent;
}
if (window.scrollX) p.x += window.scrollX;
if (window.scrollY) p.y += window.scrollY;
return p;
}; // bind mouse
if (svg.opts['ignoreMouse'] != true) {
ctx.canvas.onclick = function (e) {
var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));
svg.Mouse.onclick(p.x, p.y);
};
ctx.canvas.onmousemove = function (e) {
var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));
svg.Mouse.onmousemove(p.x, p.y);
};
}
var e = svg.CreateElement(dom.documentElement);
e.root = true;
e.addStylesFromStyleDefinition(); // render loop
var isFirstRender = true;
var draw = function draw() {
svg.ViewPort.Clear();
if (ctx.canvas.parentNode) svg.ViewPort.SetCurrent(ctx.canvas.parentNode.clientWidth, ctx.canvas.parentNode.clientHeight);
if (svg.opts['ignoreDimensions'] != true) {
// set canvas size
if (e.style('width').hasValue()) {
ctx.canvas.width = e.style('width').toPixels('x');
ctx.canvas.style.width = ctx.canvas.width + 'px';
}
if (e.style('height').hasValue()) {
ctx.canvas.height = e.style('height').toPixels('y');
ctx.canvas.style.height = ctx.canvas.height + 'px';
}
}
var cWidth = ctx.canvas.clientWidth || ctx.canvas.width;
var cHeight = ctx.canvas.clientHeight || ctx.canvas.height;
if (svg.opts['ignoreDimensions'] == true && e.style('width').hasValue() && e.style('height').hasValue()) {
cWidth = e.style('width').toPixels('x');
cHeight = e.style('height').toPixels('y');
}
svg.ViewPort.SetCurrent(cWidth, cHeight);
if (svg.opts['offsetX'] != null) e.attribute('x', true).value = svg.opts['offsetX'];
if (svg.opts['offsetY'] != null) e.attribute('y', true).value = svg.opts['offsetY'];
if (svg.opts['scaleWidth'] != null || svg.opts['scaleHeight'] != null) {
var xRatio = null,
yRatio = null,
viewBox = svg.ToNumberArray(e.attribute('viewBox').value);
if (svg.opts['scaleWidth'] != null) {
if (e.attribute('width').hasValue()) xRatio = e.attribute('width').toPixels('x') / svg.opts['scaleWidth'];else if (!isNaN(viewBox[2])) xRatio = viewBox[2] / svg.opts['scaleWidth'];
}
if (svg.opts['scaleHeight'] != null) {
if (e.attribute('height').hasValue()) yRatio = e.attribute('height').toPixels('y') / svg.opts['scaleHeight'];else if (!isNaN(viewBox[3])) yRatio = viewBox[3] / svg.opts['scaleHeight'];
}
if (xRatio == null) {
xRatio = yRatio;
}
if (yRatio == null) {
yRatio = xRatio;
}
e.attribute('width', true).value = svg.opts['scaleWidth'];
e.attribute('height', true).value = svg.opts['scaleHeight'];
e.style('transform', true, true).value += ' scale(' + 1.0 / xRatio + ',' + 1.0 / yRatio + ')';
} // clear and render
if (svg.opts['ignoreClear'] != true) {
ctx.clearRect(0, 0, cWidth, cHeight);
}
e.render(ctx);
if (isFirstRender) {
isFirstRender = false;
if (typeof svg.opts['renderCallback'] == 'function') svg.opts['renderCallback'](dom);
}
};
var waitingForImages = true;
if (svg.ImagesLoaded()) {
waitingForImages = false;
draw();
}
svg.intervalID = setInterval(function () {
var needUpdate = false;
if (waitingForImages && svg.ImagesLoaded()) {
waitingForImages = false;
needUpdate = true;
} // need update from mouse events?
if (svg.opts['ignoreMouse'] != true) {
needUpdate = needUpdate | svg.Mouse.hasEvents();
} // need update from animations?
if (svg.opts['ignoreAnimation'] != true) {
for (var i = 0; i < svg.Animations.length; i++) {
needUpdate = needUpdate | svg.Animations[i].update(1000 / svg.FRAMERATE);
}
} // need update from redraw?
if (typeof svg.opts['forceRedraw'] == 'function') {
if (svg.opts['forceRedraw']() == true) needUpdate = true;
} // render if needed
if (needUpdate) {
draw();
svg.Mouse.runEvents(); // run and clear our events
}
}, 1000 / svg.FRAMERATE);
};
svg.stop = function () {
if (svg.intervalID) {
clearInterval(svg.intervalID);
}
};
svg.Mouse = new function () {
this.events = [];
this.hasEvents = function () {
return this.events.length != 0;
};
this.onclick = function (x, y) {
this.events.push({
type: 'onclick',
x: x,
y: y,
run: function run(e) {
if (e.onclick) e.onclick();
}
});
};
this.onmousemove = function (x, y) {
this.events.push({
type: 'onmousemove',
x: x,
y: y,
run: function run(e) {
if (e.onmousemove) e.onmousemove();
}
});
};
this.eventElements = [];
this.checkPath = function (element, ctx) {
for (var i = 0; i < this.events.length; i++) {
var e = this.events[i];
if (ctx.isPointInPath && ctx.isPointInPath(e.x, e.y)) this.eventElements[i] = element;
}
};
this.checkBoundingBox = function (element, bb) {
for (var i = 0; i < this.events.length; i++) {
var e = this.events[i];
if (bb.isPointInBox(e.x, e.y)) this.eventElements[i] = element;
}
};
this.runEvents = function () {
svg.ctx.canvas.style.cursor = '';
for (var i = 0; i < this.events.length; i++) {
var e = this.events[i];
var element = this.eventElements[i];
while (element) {
e.run(element);
element = element.parent;
}
} // done running, clear
this.events = [];
this.eventElements = [];
};
}();
return svg;
}
var canvgBrowser = canvg;
/**
@function svgPresets
@desc Adds SVG default attributes to a d3 selection in order to render it properly.
@param {Selection} selection
*/
function svgPresets (selection) {
// sets "stroke-width" attribute to `0` if not defined
var strokeWidth = selection.attr("stroke-width");
selection.attr("stroke-width", !strokeWidth ? 0 : strokeWidth); // if there is no stroke, set the stroke color to "transparent" (fixes weird text rendering)
if (!strokeWidth) selection.attr("stroke", "transparent"); // sets "fill-opacity" attribute to `0` if fill is "transparent" or "none"
var transparent = ["none", "transparent"].includes(selection.attr("fill"));
var fillOpacity = selection.attr("fill-opacity");
selection.attr("fill-opacity", transparent ? 0 : fillOpacity); // "aria-label" properties interfere with text labels ¯\_(ツ)_/¯
selection.attr("aria-label", null);
}
/**
@function htmlPresets
@desc Adds HTML default styles to a d3 selection in order to render it properly.
@param {Selection} selection
*/
function htmlPresets (selection) {
selection.selectAll("*").each(function () {
var tag = this.tagName.toLowerCase();
if (!["option"].includes(tag)) {
var elem = _select(this);
/* forces minor unnoticible letter-spacing on any element where it is not defined to fix IE */
var letterSpacing = elem.style("letter-spacing");
elem.style("letter-spacing", letterSpacing === "normal" ? "0.1px" : letterSpacing);
}
});
}
function _slicedToArray$3(arr, i) {
return _arrayWithHoles$3(arr) || _iterableToArrayLimit$3(arr, i) || _unsupportedIterableToArray$5(arr, i) || _nonIterableRest$3();
}
function _nonIterableRest$3() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _unsupportedIterableToArray$5(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray$5(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$5(o, minLen);
}
function _arrayLikeToArray$5(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) {
arr2[i] = arr[i];
}
return arr2;
}
function _iterableToArrayLimit$3(arr, i) {
if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _arrayWithHoles$3(arr) {
if (Array.isArray(arr)) return arr;
}
var defaultOptions = {
background: false,
callback: function callback() {},
exclude: [],
padding: 0,
scale: 1
};
var canvgOptions = {
ignoreMouse: true,
ignoreAnimation: true,
ignoreDimensions: true,
ignoreClear: true
};
/**
@function parseTransform
@desc Extracts scale, x, and y position from an elements "transform" attribute, respecting cross-browser render differences.
@param {HTMLElement} elem The element to be analyzed.
@private
*/
function parseTransform(elem) {
var property = _select(elem).attr("transform");
var scale = 1,
x = 0,
y = 0;
if (property) {
scale = property.match(/scale\(([^a-z]+)\)/i);
if (scale) scale = parseFloat(scale[1]);else scale = 1;
var translate = property.match(/translate\(([^a-z]+)\)/i);
if (translate) {
var _translate$1$replace$ = translate[1].replace(", ", ",").replace(/([^a-z]),*\s([^a-z])/gi, "$1,$2").split(",").map(function (d) {
return parseFloat(d) * scale;
});
var _translate$1$replace$2 = _slicedToArray$3(_translate$1$replace$, 2);
x = _translate$1$replace$2[0];
y = _translate$1$replace$2[1];
}
}
return [scale, x, y];
}
/**
@function dom2canvas
@desc Renders HTML/SVG elements to a shared canvas.
@param {HTMLElement|Object|Array} elem The element or array of elements to be rendered to a single canvas. Additionally, a complex object can be passed as an element which can contain specific other properties.
@param {Number} [elem.x] The x offset of the element within the rendered canvas.
@param {Number} [elem.y] The y offset of the element within the rendered canvas.
@param {Object} [options] Additional options to specify.
@param {String} [options.background] Background color of the rendered canvas.
@param {Function} [options.callback] Callback function to be passed the canvas element after rendering.
@param {HTMLElement} [options.canvas] A canvas DOM element to draw onto. If no element is supplied, a canvas element will be created in memory and passed to the callback function when drawing is complete.
@param {Array} [options.excludes] An array of HTMLElement objects to be excluded from the render.
@param {Number} [options.height] Pixel height for the final output. If a height value has not been passed, it will be inferred from the sizing of the first DOM element passed.
@param {Number} [options.padding = 0] Outer padding for the final file.
@param {Number} [options.scale = 1] Scale for the final file.
@param {Number} [options.width] Pixel width for the final output. If a width value has not been passed, it will be inferred from the sizing of the first DOM element passed.
*/
function dom2canvas (elem, options) {
if (!elem) return;
if (!(elem instanceof Array)) elem = [elem];
options = Object.assign({}, defaultOptions, options);
var IE = new RegExp(/(MSIE|Trident\/|Edge\/)/i).test(navigator.userAgent);
var ratio = window ? window.devicePixelRatio || 1 : 1;
var reference = elem[0];
if (reference.constructor === Object) reference = reference.element;
var height = options.height || parseFloat(_select(reference).style("height")) + parseFloat(_select(reference).style("padding-top")) + parseFloat(_select(reference).style("padding-bottom")),
width = options.width || parseFloat(_select(reference).style("width")) + parseFloat(_select(reference).style("padding-left")) + parseFloat(_select(reference).style("padding-right"));
var layerX,
layerY,
offsetX = 0,
offsetY = 0;
if (reference.getBoundingClientRect) {
var bounds = reference.getBoundingClientRect();
offsetX = bounds.left;
offsetY = bounds.top;
} else {
offsetX = reference.offsetLeft;
offsetY = reference.offsetTop;
}
var canvas = options.canvas || document.createElement("canvas");
canvas.width = (width + options.padding * 2) * options.scale * ratio;
canvas.height = (height + options.padding * 2) * options.scale * ratio;
canvas.style.width = (width + options.padding * 2) * options.scale;
canvas.style.height = (height + options.padding * 2) * options.scale;
var context = canvas.getContext("2d");
context.scale(options.scale * ratio, options.scale * ratio);
context.clearRect(0, 0, canvas.width / ratio, canvas.height / ratio);
if (options.background) {
context.beginPath();
context.rect(0, 0, canvas.width / ratio, canvas.height / ratio);
context.fillStyle = options.background;
context.fill();
}
var layers = [];
/**
* Determines how a given DOM element should be rendered.
* @param {Object} trans ancestral transform properties
* @private
*/
function checkRender(trans) {
var tag = (this.tagName || "").toLowerCase();
if (options.exclude.includes(this) || tag === "foreignobject") return;
var transform = Object.assign({}, trans); // strips translate and scale from transform property
if (this.tagName) {
var opacity = _select(this).attr("opacity") || _select(this).style("opacity");
var display = _select(this).style("display");
var visibility = _select(this).style("visibility");
if (display === "none" || visibility === "hidden" || opacity && parseFloat(opacity) === 0) return;
var _tag = this.tagName.toLowerCase();
if (_tag.length && ["defs", "title", "desc"].includes(_tag)) return;
if (_tag === "svg") {
// do not perform this transform for SVGs nested within other SVGs
if (!transform.svg) {
var _this$getBoundingClie = this.getBoundingClientRect(),
left = _this$getBoundingClie.left,
top = _this$getBoundingClie.top;
transform.x += left - offsetX;
transform.y += top - offsetY;
transform.svg = true;
}
var x = _select(this).attr("x");
x = x ? parseFloat(x) * transform.scale : 0;
transform.x += x;
var y = _select(this).attr("y");
y = y ? parseFloat(y) * transform.scale : 0;
transform.y += y;
transform.clip = {
height: parseFloat(_select(this).attr("height") || _select(this).style("height")),
width: parseFloat(_select(this).attr("width") || _select(this).style("width")),
x: x,
y: y
};
} else {
var _x = _select(this).attr("x");
if (_x) transform.x += parseFloat(_x) * transform.scale;
var _y = _select(this).attr("y");
if (_y) transform.y += parseFloat(_y) * transform.scale;
}
}
if (!tag.length) {
var test = (this.wholeText || "").replace(/\s/g, "");
if (test.length) {
var text = this.nodeValue.replace(/^\s*/, "").replace(/^\n/, "").replace(/^\s*/, "").replace(/\n$/, "").replace(/\s*$/, "").replace(/\n$/, "");
layers.push({
type: "text",
style: this.parentNode,
value: text,
x: transform.x,
y: transform.y
});
}
} else if (tag === "text") {
var _elem = this.cloneNode(true);
_select(_elem).call(svgPresets);
layers.push(Object.assign({}, transform, {
type: "svg",
value: _elem
}));
} else if (["image", "img"].includes(tag)) {
var url = _select(this).attr("href") || _select(this).attr("xlink:href");
if (url.length) {
var h = parseFloat(_select(this).attr("height")) * transform.scale,
w = parseFloat(_select(this).attr("width")) * transform.scale;
var data = {
clip: transform.clip,
height: h,
loaded: false,
type: "img",
width: w,
x: transform.x,
y: transform.y
};
layers.push(data);
var img = new Image();
img.crossOrigin = "Anonymous";
img.onload = function () {
var canvas2 = document.createElement("canvas");
var ctx2 = canvas2.getContext("2d");
canvas2.height = h * ratio;
canvas2.width = w * ratio;
ctx2.drawImage(this, 0, 0, w * ratio, h * ratio);
var himg = document.createElement("img");
himg.src = canvas2.toDataURL("image/png");
data.value = himg;
data.loaded = true;
};
img.onerror = function () {
data.loaded = true;
data.value = false;
};
img.src = url;
}
} else if (!["svg", "g", "text"].includes(tag) && !_select(this).selectAll("svg").size()) {
var s = options.scale * ratio;
var _data = {
height: Math.floor(height + options.padding * 2 + offsetY),
loaded: false,
type: "html",
width: Math.floor(width + options.padding * 2 + offsetX),
x: Math.floor(layerX - offsetX),
y: Math.floor(layerY - offsetY)
};
var tempCanvas = document.createElement("canvas");
tempCanvas.width = _data.width * s;
tempCanvas.height = _data.height * s;
tempCanvas.style.width = "".concat(_data.width * s, "px");
tempCanvas.style.height = "".concat(_data.height * s, "px");
var tempContext = tempCanvas.getContext("2d");
tempContext.scale(s, s);
layers.push(_data);
htmlPresets(_select(this));
html2canvas(this, {
allowTaint: true,
canvas: tempCanvas,
letterRendering: true
}).then(function (c) {
_data.value = c;
_data.loaded = true;
});
} else if (tag !== "svg" && this.childNodes.length > 0 && !_select(this).selectAll("image, img, svg").size()) {
var _elem2 = this.cloneNode(true);
_select(_elem2).selectAll("*").each(function () {
_select(this).call(svgPresets);
if (_select(this).attr("opacity") === "0") this.parentNode.removeChild(this);
});
layers.push(Object.assign({}, transform, {
type: "svg",
value: _elem2,
tag: tag
}));
} else if (this.childNodes.length > 0) {
var _parseTransform = parseTransform(this),
_parseTransform2 = _slicedToArray$3(_parseTransform, 3),
scale = _parseTransform2[0],
_x2 = _parseTransform2[1],
_y2 = _parseTransform2[2];
transform.scale *= scale;
transform.x += _x2;
transform.y += _y2;
checkChildren(this, transform);
} else {
// catches all SVG shapes
var _elem3 = this.cloneNode(true);
_select(_elem3).selectAll("*").each(function () {
if (_select(this).attr("opacity") === "0") this.parentNode.removeChild(this);
});
if (tag === "line") {
_select(_elem3).attr("x1", parseFloat(_select(_elem3).attr("x1")) + transform.x);
_select(_elem3).attr("x2", parseFloat(_select(_elem3).attr("x2")) + transform.x);
_select(_elem3).attr("y1", parseFloat(_select(_elem3).attr("y1")) + transform.y);
_select(_elem3).attr("y2", parseFloat(_select(_elem3).attr("y2")) + transform.y);
} else if (tag === "path") {
var _parseTransform3 = parseTransform(_elem3),
_parseTransform4 = _slicedToArray$3(_parseTransform3, 3),
_scale = _parseTransform4[0],
_x3 = _parseTransform4[1],
_y3 = _parseTransform4[2];
if (_select(_elem3).attr("transform")) _select(_elem3).attr("transform", "scale(".concat(_scale, ")translate(").concat(_x3 + transform.x, ",").concat(_y3 + transform.y, ")"));
}
_select(_elem3).call(svgPresets);
var fill = _select(_elem3).attr("fill");
var defFill = fill && fill.indexOf("url") === 0; // if (defFill) select(elem).attr("fill-opacity", 0);
layers.push(Object.assign({}, transform, {
type: "svg",
value: _elem3,
tag: tag
}));
if (defFill) {
var def = _select(fill.slice(4, -1)).node().cloneNode(true);
var defTag = (def.tagName || "").toLowerCase();
if (defTag === "pattern") {
var _parseTransform5 = parseTransform(_elem3),
_parseTransform6 = _slicedToArray$3(_parseTransform5, 3),
_scale2 = _parseTransform6[0],
_x4 = _parseTransform6[1],
_y4 = _parseTransform6[2];
transform.scale *= _scale2;
transform.x += _x4;
transform.y += _y4;
checkChildren(def, transform);
}
}
}
}
/**
* Performs "checkRender" on all childNodes of a DOM element (used recursively by checkRender)
* @param {HTMLElement} e DOM node to traverse
* @param {Object} trans ancestral transform properties
* @private
*/
function checkChildren(e, trans) {
selectAll(e.childNodes).each(function () {
checkRender.bind(this)(trans);
});
}
for (var i = 0; i < elem.length; i++) {
var e = elem[i],
_options = {
scale: 1,
x: 0,
y: 0,
svg: false
};
if (e.constructor === Object) {
_options = Object.assign(_options, e);
e = e.element;
}
layerX = _options.x;
layerY = _options.y;
checkRender.bind(e)(_options);
}
/**
* Checks the status of each render layer every 500ms, and finishes render once all are complete.
* @private
*/
function checkStatus() {
var allDone = true;
for (var _i2 = 0; _i2 < layers.length; _i2++) {
if (layers[_i2].loaded === false) {
allDone = false;
break;
}
}
if (allDone) finish();else setTimeout(checkStatus, 500);
}
checkStatus();
/**
* Finishes the render after all layers have been rendered to canvas.
* @private
*/
function finish() {
for (var _i3 = 0; _i3 < layers.length; _i3++) {
var layer = layers[_i3];
var clip = layer.clip || {
height: height,
width: width,
x: 0,
y: 0
};
switch (layer.type) {
case "img":
if (layer.value) {
context.save();
context.beginPath();
context.translate(options.padding + clip.x, options.padding + clip.y);
context.rect(0, 0, clip.width, clip.height);
context.clip();
context.drawImage(layer.value, layer.x + clip.x, layer.y + clip.y, layer.width, layer.height);
context.restore();
}
break;
case "html":
context.save();
context.beginPath();
context.translate(options.padding, options.padding);
context.drawImage(layer.value, layer.x, layer.y, layer.width, layer.height);
context.restore();
break;
case "text":
var parent = _select(layer.style);
var title = layer.value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
var fC = parent.style("color"),
fS = parent.style("font-size");
var fF = parent.style("font-family").split(",")[0];
if (fF.indexOf("'") !== 0) fF = "'".concat(fF, "'");
var text = "<text stroke='none' dy='".concat(fS, "' fill='").concat(fC, "' font-family=").concat(fF, " font-size='").concat(fS, "'>").concat(title, "</text>");
context.save();
context.translate(options.padding, options.padding);
canvgBrowser(canvas, text, Object.assign({}, canvgOptions, {
offsetX: layer.x,
offsetY: layer.y
}));
context.restore();
break;
case "svg":
var outer = IE ? new XMLSerializer().serializeToString(layer.value) : layer.value.outerHTML;
context.save();
context.translate(options.padding + clip.x + layer.x, options.padding + clip.y + layer.y);
context.rect(0, 0, clip.width, clip.height);
context.clip();
canvgBrowser(canvas, outer, Object.assign({}, canvgOptions, {
offsetX: layer.x + clip.x,
offsetY: layer.y + clip.y
}));
context.restore();
break;
default:
console.warn("uncaught", layer);
break;
}
}
options.callback(canvas);
}
}
/* canvas-toBlob.js
* A canvas.toBlob() implementation.
* 2016-05-26
*
* By Eli Grey, http://eligrey.com and Devin Samarin, https://github.com/eboyjr
* License: MIT
* See https://github.com/eligrey/canvas-toBlob.js/blob/master/LICENSE.md
*/
/*global self */
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
plusplus: true */
/*! @source http://purl.eligrey.com/github/canvas-toBlob.js/blob/master/canvas-toBlob.js */
(function (view) {
var Uint8Array = view.Uint8Array,
HTMLCanvasElement = view.HTMLCanvasElement,
canvas_proto = HTMLCanvasElement && HTMLCanvasElement.prototype,
is_base64_regex = /\s*;\s*base64\s*(?:;|$)/i,
to_data_url = "toDataURL",
base64_ranks,
decode_base64 = function decode_base64(base64) {
var len = base64.length,
buffer = new Uint8Array(len / 4 * 3 | 0),
i = 0,
outptr = 0,
last = [0, 0],
state = 0,
save = 0,
rank,
code,
undef;
while (len--) {
code = base64.charCodeAt(i++);
rank = base64_ranks[code - 43];
if (rank !== 255 && rank !== undef) {
last[1] = last[0];
last[0] = code;
save = save << 6 | rank;
state++;
if (state === 4) {
buffer[outptr++] = save >>> 16;
if (last[1] !== 61
/* padding character */
) {
buffer[outptr++] = save >>> 8;
}
if (last[0] !== 61
/* padding character */
) {
buffer[outptr++] = save;
}
state = 0;
}
}
} // 2/3 chance there's going to be some null bytes at the end, but that
// doesn't really matter with most image formats.
// If it somehow matters for you, truncate the buffer up outptr.
return buffer;
};
if (Uint8Array) {
base64_ranks = new Uint8Array([62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51]);
}
if (HTMLCanvasElement && (!canvas_proto.toBlob || !canvas_proto.toBlobHD)) {
if (!canvas_proto.toBlob) canvas_proto.toBlob = function (callback, type
/*, ...args*/
) {
if (!type) {
type = "image/png";
}
if (this.mozGetAsFile) {
callback(this.mozGetAsFile("canvas", type));
return;
}
if (this.msToBlob && /^\s*image\/png\s*(?:$|;)/i.test(type)) {
callback(this.msToBlob());
return;
}
var args = Array.prototype.slice.call(arguments, 1),
dataURI = this[to_data_url].apply(this, args),
header_end = dataURI.indexOf(","),
data = dataURI.substring(header_end + 1),
is_base64 = is_base64_regex.test(dataURI.substring(0, header_end)),
blob;
if (Blob.fake) {
// no reason to decode a data: URI that's just going to become a data URI again
blob = new Blob();
if (is_base64) {
blob.encoding = "base64";
} else {
blob.encoding = "URI";
}
blob.data = data;
blob.size = data.length;
} else if (Uint8Array) {
if (is_base64) {
blob = new Blob([decode_base64(data)], {
type: type
});
} else {
blob = new Blob([decodeURIComponent(data)], {
type: type
});
}
}
callback(blob);
};
if (!canvas_proto.toBlobHD && canvas_proto.toDataURLHD) {
canvas_proto.toBlobHD = function () {
to_data_url = "toDataURLHD";
var blob = this.toBlob();
to_data_url = "toDataURL";
return blob;
};
} else {
canvas_proto.toBlobHD = canvas_proto.toBlob;
}
}
})(typeof self !== "undefined" && self || typeof window !== "undefined" && window || commonjsGlobal.content || commonjsGlobal);
var FileSaver = createCommonjsModule(function (module) {
/* FileSaver.js
* A saveAs() FileSaver implementation.
* 1.3.2
* 2016-06-16 18:25:19
*
* By Eli Grey, http://eligrey.com
* License: MIT
* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
*/
/*global self */
/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
var saveAs = saveAs || function (view) {
if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
return;
}
var doc = view.document // only get URL when necessary in case Blob.js hasn't overridden it yet
,
get_URL = function get_URL() {
return view.URL || view.webkitURL || view;
},
save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"),
can_use_save_link = ("download" in save_link),
click = function click(node) {
var event = new MouseEvent("click");
node.dispatchEvent(event);
},
is_safari = /constructor/i.test(view.HTMLElement) || view.safari,
is_chrome_ios = /CriOS\/[\d]+/.test(navigator.userAgent),
throw_outside = function throw_outside(ex) {
(view.setImmediate || view.setTimeout)(function () {
throw ex;
}, 0);
},
force_saveable_type = "application/octet-stream" // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
,
arbitrary_revoke_timeout = 1000 * 40 // in ms
,
revoke = function revoke(file) {
var revoker = function revoker() {
if (typeof file === "string") {
// file is an object URL
get_URL().revokeObjectURL(file);
} else {
// file is a File
file.remove();
}
};
setTimeout(revoker, arbitrary_revoke_timeout);
},
dispatch = function dispatch(filesaver, event_types, event) {
event_types = [].concat(event_types);
var i = event_types.length;
while (i--) {
var listener = filesaver["on" + event_types[i]];
if (typeof listener === "function") {
try {
listener.call(filesaver, event || filesaver);
} catch (ex) {
throw_outside(ex);
}
}
}
},
auto_bom = function auto_bom(blob) {
// prepend BOM for UTF-8 XML and text/* types (including HTML)
// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
return new Blob([String.fromCharCode(0xFEFF), blob], {
type: blob.type
});
}
return blob;
},
FileSaver = function FileSaver(blob, name, no_auto_bom) {
if (!no_auto_bom) {
blob = auto_bom(blob);
} // First try a.download, then web filesystem, then object URLs
var filesaver = this,
type = blob.type,
force = type === force_saveable_type,
object_url,
dispatch_all = function dispatch_all() {
dispatch(filesaver, "writestart progress write writeend".split(" "));
} // on any filesys errors revert to saving with object URLs
,
fs_error = function fs_error() {
if ((is_chrome_ios || force && is_safari) && view.FileReader) {
// Safari doesn't allow downloading of blob urls
var reader = new FileReader();
reader.onloadend = function () {
var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');
var popup = view.open(url, '_blank');
if (!popup) view.location.href = url;
url = undefined; // release reference before dispatching
filesaver.readyState = filesaver.DONE;
dispatch_all();
};
reader.readAsDataURL(blob);
filesaver.readyState = filesaver.INIT;
return;
} // don't create more object URLs than needed
if (!object_url) {
object_url = get_URL().createObjectURL(blob);
}
if (force) {
view.location.href = object_url;
} else {
var opened = view.open(object_url, "_blank");
if (!opened) {
// Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
view.location.href = object_url;
}
}
filesaver.readyState = filesaver.DONE;
dispatch_all();
revoke(object_url);
};
filesaver.readyState = filesaver.INIT;
if (can_use_save_link) {
object_url = get_URL().createObjectURL(blob);
setTimeout(function () {
save_link.href = object_url;
save_link.download = name;
click(save_link);
dispatch_all();
revoke(object_url);
filesaver.readyState = filesaver.DONE;
});
return;
}
fs_error();
},
FS_proto = FileSaver.prototype,
saveAs = function saveAs(blob, name, no_auto_bom) {
return new FileSaver(blob, name || blob.name || "download", no_auto_bom);
}; // IE 10+ (native saveAs)
if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
return function (blob, name, no_auto_bom) {
name = name || blob.name || "download";
if (!no_auto_bom) {
blob = auto_bom(blob);
}
return navigator.msSaveOrOpenBlob(blob, name);
};
}
FS_proto.abort = function () {};
FS_proto.readyState = FS_proto.INIT = 0;
FS_proto.WRITING = 1;
FS_proto.DONE = 2;
FS_proto.error = FS_proto.onwritestart = FS_proto.onprogress = FS_proto.onwrite = FS_proto.onabort = FS_proto.onerror = FS_proto.onwriteend = null;
return saveAs;
}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || commonjsGlobal.content); // `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the window
if ( module.exports) {
module.exports.saveAs = saveAs;
}
});
var FileSaver_1 = FileSaver.saveAs;
var defaultOptions$1 = {
filename: "download",
type: "png"
};
/**
@function saveElement
@desc Downloads an HTML Element as a bitmap PNG image.
@param {HTMLElement|Array} elem A single element or array of elements to be saved to one file.
@param {Object} [options] Additional options to specify.
@param {String} [options.filename = "download"] Filename for the downloaded file, without the extension.
@param {String} [options.type = "png"] File type of the saved document. Accepted values are `"png"` and `"jpg"`.
@param {Object} [renderOptions] Custom options to be passed to the dom2canvas function.
*/
function saveElement (elem) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var renderOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
if (!elem) return;
options = Object.assign({}, defaultOptions$1, options);
var IE = new RegExp(/(MSIE|Trident\/|Edge\/)/i).test(navigator.userAgent);
if (!(elem instanceof Array) && options.type === "svg") {
var outer = IE ? new XMLSerializer().serializeToString(elem) : elem.outerHTML;
FileSaver_1(new Blob([outer], {
type: "application/svg+xml"
}), "".concat(options.filename, ".svg"));
}
dom2canvas(elem, Object.assign({}, renderOptions, {
callback: function callback(canvas) {
if (renderOptions.callback) renderOptions.callback(canvas);
if (["jpg", "png"].includes(options.type)) {
canvas.toBlob(function (blob) {
return FileSaver_1(blob, "".concat(options.filename, ".").concat(options.type));
});
} // else if (options.type === "pdf") {
// const outputHeight = 11,
// outputWidth = 8.5;
// const aspect = canvas.width / canvas.height,
// orientation = aspect > 1 ? "landscape" : "portrait";
// const pdf = new JsPDF({
// orientation,
// unit: "in",
// format: [outputWidth, outputHeight]
// });
// let h = orientation === "landscape" ? outputWidth : outputHeight,
// left,
// top,
// w = orientation === "landscape" ? outputHeight : outputWidth;
// const margin = 0.5;
// if (aspect < w / h) {
// h -= margin * 2;
// const tempWidth = h * aspect;
// top = margin;
// left = (w - tempWidth) / 2;
// w = tempWidth;
// }
// else {
// w -= margin * 2;
// const tempHeight = w / aspect;
// left = margin;
// top = (h - tempHeight) / 2;
// h = tempHeight;
// }
// pdf.addImage(canvas, "canvas", left, top, w, h);
// pdf.save(options.filename);
// }
}
}));
}
var formTypes = {
Button: Button,
Radio: Radio,
Select: Select
};
/**
@function _drawLegend
@desc Renders the legend if this._legend is not falsy.
@param {Array} dara The filtered data array to be displayed.
@private
*/
function drawControls () {
var _this = this;
var that = this;
var padding = this._controlPadding() ? this._padding : {
top: 0,
right: 0,
bottom: 0,
left: 0
};
var areas = ["left", "right", "top", "bottom"];
var _loop = function _loop(a) {
var area = areas[a];
var controls = (_this._controls || []).filter(function (c) {
return !c.position && area === "bottom" || c.position === area;
});
if (_this._downloadButton && _this._downloadPosition === area) {
controls.push({
data: [{
text: _this._translate("Download"),
value: 1
}],
label: "downloadButton",
on: {
click: function click() {
var resize = _this._detectResize;
if (resize) _this.detectResize(false).render();
saveElement(_this._select.node(), Object.assign({
title: _this._title || undefined
}, _this._downloadConfig), {
callback: function callback() {
setTimeout(function () {
if (resize) _this.detectResize(resize).render();
}, 5000);
}
});
}
},
type: "Button"
});
}
var wide = area === "top" || area === "bottom";
var transform = {
height: wide ? _this._height - (_this._margin.top + _this._margin.bottom) : _this._height - (_this._margin.top + _this._margin.bottom + padding.top + padding.bottom),
width: wide ? _this._width - (_this._margin.left + _this._margin.right + padding.left + padding.right) : _this._width - (_this._margin.left + _this._margin.right)
};
transform.x = (wide ? _this._margin.left + padding.left : _this._margin.left) + (area === "right" ? _this._width - _this._margin.bottom : 0);
transform.y = (wide ? _this._margin.top : _this._margin.top + padding.top) + (area === "bottom" ? _this._height - _this._margin.bottom : 0);
var foreign = elem("foreignObject.d3plus-viz-controls-".concat(area), {
condition: controls.length,
enter: Object.assign({
opacity: 0
}, transform),
exit: Object.assign({
opacity: 0
}, transform),
parent: _this._select,
transition: _this._transition,
update: {
height: transform.height,
opacity: 1,
width: transform.width
}
});
var container = foreign.selectAll("div.d3plus-viz-controls-container").data([null]);
container = container.enter().append("xhtml:div").attr("class", "d3plus-viz-controls-container").merge(container);
if (controls.length) {
var _loop2 = function _loop2(i) {
var control = Object.assign({}, controls[i]);
var on = {};
if (control.on) {
var _loop3 = function _loop3(event) {
if ({}.hasOwnProperty.call(control.on, event)) {
on[event] = function () {
control.on[event].bind(that)(this.value);
};
}
};
for (var event in control.on) {
_loop3(event);
}
}
var id = control.label || "".concat(area, "-").concat(i);
if (!_this._controlCache[id]) {
var type = control.type && formTypes[control.type] ? control.type : "Select";
_this._controlCache[id] = new formTypes[type]().container(container.node());
if (control.checked) _this._controlCache[id].checked(control.checked);
if (control.selected) _this._controlCache[id].selected(control.selected);
}
delete control.checked;
delete control.selected;
_this._controlCache[id].config(control).config({
on: on
}).config(_this._controlConfig).render();
};
for (var i = 0; i < controls.length; i++) {
_loop2(i);
}
container.style("display", ["top", "bottom"].includes(area) ? "block" : "inline-block").style("text-align", ["top", "bottom"].includes(area) ? "center" : area);
var bounds = container.node().getBoundingClientRect();
foreign.transition(_this._transition).attr("x", transform.x - (area === "right" ? bounds.width : 0)).attr("y", transform.y - (area === "bottom" ? bounds.height : 0)).attr("height", wide ? bounds.height : transform.height).attr("width", wide ? transform.width : bounds.width);
_this._margin[area] += ["top", "bottom"].includes(area) ? bounds.height : bounds.width;
}
};
for (var a = 0; a < areas.length; a++) {
_loop(a);
}
}
/**
@function legendLabel
@desc Default label function for the legend.
@private
*/
function legendLabel(d, i) {
return this._drawLabel(d, i, this._legendDepth);
}
/**
@function _drawLegend
@desc Renders the legend if this._legend is not falsy.
@param {Array} data The filtered data array to be displayed.
@private
*/
function drawLegend () {
var _this = this;
var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var legendBounds = this._legendClass.outerBounds();
var position = this._legendPosition;
var wide = ["top", "bottom"].includes(position);
var padding = this._legendPadding() ? this._padding : {
top: 0,
right: 0,
bottom: 0,
left: 0
};
var transform = {
transform: "translate(".concat(wide ? this._margin.left + padding.left : this._margin.left, ", ").concat(wide ? this._margin.top : this._margin.top + padding.top, ")")
};
var legendGroup = elem("g.d3plus-viz-legend", {
condition: this._legend && !this._legendConfig.select,
enter: transform,
parent: this._select,
transition: this._transition,
update: transform
}).node();
var legendData = [];
var color = function color(d, i) {
var shape = _this._shape(d, i);
var attr = shape === "Line" ? "stroke" : "fill";
var value = _this._shapeConfig[shape] && _this._shapeConfig[shape][attr] ? _this._shapeConfig[shape][attr] : _this._shapeConfig[attr];
return typeof value === "function" ? value.bind(_this)(d, i) : value;
};
var opacity = function opacity(d, i) {
var shape = _this._shape(d, i);
var value = _this._shapeConfig[shape] && _this._shapeConfig[shape].opacity ? _this._shapeConfig[shape].opacity : _this._shapeConfig.opacity;
return typeof value === "function" ? value.bind(_this)(d, i) : value;
};
var fill = function fill(d, i) {
return "".concat(color(d, i), "_").concat(opacity(d, i));
};
if (this._legend) {
nest().key(fill).rollup(function (leaves) {
return legendData.push(objectMerge(leaves, _this._aggs));
}).entries(this._colorScale ? data.filter(function (d, i) {
return _this._colorScale(d, i) === undefined;
}) : data);
}
legendData.sort(this._legendSort);
var labels = legendData.map(function (d, i) {
return _this._ids(d, i).slice(0, _this._drawDepth + 1);
});
this._legendDepth = 0;
var _loop = function _loop(x) {
var values = labels.map(function (l) {
return l[x];
});
if (!values.some(function (v) {
return v instanceof Array;
}) && Array.from(new Set(values)).length === legendData.length) {
_this._legendDepth = x;
return "break";
}
};
for (var x = 0; x <= this._drawDepth; x++) {
var _ret = _loop(x);
if (_ret === "break") break;
}
var hidden = function hidden(d, i) {
var id = _this._id(d, i);
if (id instanceof Array) id = id[0];
return _this._hidden.includes(id) || _this._solo.length && !_this._solo.includes(id);
};
this._legendClass.id(fill).align(wide ? "center" : position).direction(wide ? "row" : "column").duration(this._duration).data(legendData.length > this._legendCutoff || this._colorScale ? legendData : []).height(wide ? this._height - (this._margin.bottom + this._margin.top) : this._height - (this._margin.bottom + this._margin.top + padding.bottom + padding.top)).locale(this._locale).parent(this).select(legendGroup).verticalAlign(!wide ? "middle" : position).width(wide ? this._width - (this._margin.left + this._margin.right + padding.left + padding.right) : this._width - (this._margin.left + this._margin.right)).shapeConfig(configPrep.bind(this)(this._shapeConfig, "legend")).shapeConfig({
fill: function fill(d, i) {
return hidden(d, i) ? _this._hiddenColor(d, i) : color(d, i);
},
labelConfig: {
fontOpacity: function fontOpacity(d, i) {
return hidden(d, i) ? _this._hiddenOpacity(d, i) : 1;
}
},
opacity: opacity
}).config(this._legendConfig).render();
if (!this._legendConfig.select && legendBounds.height) {
if (wide) this._margin[position] += legendBounds.height + this._legendClass.padding() * 2;else this._margin[position] += legendBounds.width + this._legendClass.padding() * 2;
}
}
/**
@function setTimeFilter
@desc Determines whether or not to update the timeFilter method of the Viz.
@param {Array|Date} The timeline selection given from the d3 brush.
@private
*/
function setTimeFilter(s) {
var _this = this;
if (!(s instanceof Array)) s = [s, s];
if (JSON.stringify(s) !== JSON.stringify(this._timelineSelection)) {
this._timelineSelection = s;
s = s.map(Number);
this.timeFilter(function (d) {
var ms = date$2(_this._time(d)).getTime();
return ms >= s[0] && ms <= s[1];
}).render();
}
}
/**
@function _drawTimeline
@desc Renders the timeline if this._time and this._timeline are not falsy and there are more than 1 tick available.
@param {Array} data The filtered data array to be displayed.
@private
*/
function drawTimeline () {
var _this2 = this;
var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var timelinePossible = this._time && this._timeline;
var ticks = timelinePossible ? unique(this._data.map(this._time)).map(date$2) : [];
timelinePossible = timelinePossible && ticks.length > 1;
var padding = this._timelinePadding() ? this._padding : {
top: 0,
right: 0,
bottom: 0,
left: 0
};
var transform = {
transform: "translate(".concat(this._margin.left + padding.left, ", 0)")
};
var timelineGroup = elem("g.d3plus-viz-timeline", {
condition: timelinePossible,
enter: transform,
parent: this._select,
transition: this._transition,
update: transform
}).node();
if (timelinePossible) {
var timeline = this._timelineClass.domain(extent(ticks)).duration(this._duration).height(this._height - this._margin.bottom).locale(this._locale).select(timelineGroup).ticks(ticks.sort(function (a, b) {
return +a - +b;
})).width(this._width - (this._margin.left + this._margin.right + padding.left + padding.right));
if (timeline.selection() === undefined) {
this._timelineSelection = extent(data, this._time).map(date$2);
timeline.selection(this._timelineSelection);
}
var config = this._timelineConfig;
timeline.config(config) // .on("brush", s => {
// setTimeFilter.bind(this)(s);
// if (config.on && config.on.brush) config.on.brush(s);
// })
.on("end", function (s) {
setTimeFilter.bind(_this2)(s);
if (config.on && config.on.end) config.on.end(s);
}).render();
this._margin.bottom += timeline.outerBounds().height + timeline.padding() * 2;
}
}
/**
@function _drawTitle
@desc Draws a title if this._title is defined.
@param {Array} [*data*] The currently filtered dataset.
@private
*/
function drawTitle () {
var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var text = this._title ? this._title(data) : false;
var padding = this._titlePadding() ? this._padding : {
top: 0,
right: 0,
bottom: 0,
left: 0
};
var transform = {
transform: "translate(".concat(this._margin.left + padding.left, ", ").concat(this._margin.top, ")")
};
var group = elem("g.d3plus-viz-title", {
enter: transform,
parent: this._select,
transition: this._transition,
update: transform
}).node();
this._titleClass.data(text ? [{
text: text
}] : []).locale(this._locale).select(group).width(this._width - (this._margin.left + this._margin.right + padding.left + padding.right)).config(this._titleConfig).render();
this._margin.top += text ? group.getBBox().height : 0;
}
/**
@function _drawTotal
@desc Draws a total title if this._total is defined.
@param {Array} [*data*] The currently filtered dataset.
@private
*/
function drawTotal () {
var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var total = typeof this._total === "function" ? sum(data.map(this._total)) : this._total === true && this._size ? sum(data.map(this._size)) : false;
var padding = this._totalPadding() ? this._padding : {
top: 0,
right: 0,
bottom: 0,
left: 0
};
var transform = {
transform: "translate(".concat(this._margin.left + padding.left, ", ").concat(this._margin.top, ")")
};
var group = elem("g.d3plus-viz-total", {
enter: transform,
parent: this._select,
transition: this._transition,
update: transform
}).node();
var visible = typeof total === "number";
this._totalClass.data(visible ? [{
text: this._totalFormat(total)
}] : []).locale(this._locale).select(group).width(this._width - (this._margin.left + this._margin.right + padding.left + padding.right)).config(this._totalConfig).render();
this._margin.top += visible ? group.getBBox().height + this._totalConfig.padding * 2 : 0;
}
/**
@desc Given an HTMLElement and a "width" or "height" string, this function returns the current calculated size for the DOM element.
@private
*/
function _elementSize(element, s) {
if (!element) return undefined;
if (element.tagName === undefined || ["BODY", "HTML"].indexOf(element.tagName) >= 0) {
var val = window["inner".concat(s.charAt(0).toUpperCase() + s.slice(1))];
var elem = _select(element);
if (s === "width") {
val -= parseFloat(elem.style("margin-left"), 10);
val -= parseFloat(elem.style("margin-right"), 10);
val -= parseFloat(elem.style("padding-left"), 10);
val -= parseFloat(elem.style("padding-right"), 10);
} else {
val -= parseFloat(elem.style("margin-top"), 10);
val -= parseFloat(elem.style("margin-bottom"), 10);
val -= parseFloat(elem.style("padding-top"), 10);
val -= parseFloat(elem.style("padding-bottom"), 10);
}
return val;
} else {
var _val = parseFloat(_select(element).style(s), 10);
if (typeof _val === "number" && _val > 0) return _val;else return _elementSize(element.parentNode, s);
}
}
/**
@function getSize
@desc Finds the available width and height for a specified HTMLElement, traversing it's parents until it finds something with constrained dimensions. Falls back to the inner dimensions of the browser window if none is found.
@param {HTMLElement} elem The HTMLElement to find dimensions for.
@private
*/
function getSize$1 (elem) {
return [_elementSize(elem, "width"), _elementSize(elem, "height")];
}
/**
@desc Returns a *Boolean* denoting whether or not a given DOM element is visible in the current window.
@param {DOMElement} elem The DOM element to analyze.
@param {Number} [buffer = 0] A pixel offset from the edge of the top and bottom of the screen. If a positive value, the element will be deemed visible when it is that many pixels away from entering the viewport. If negative, the element will have to enter the viewport by that many pixels before being deemed visible.
@private
*/
function inViewport (elem) {
var buffer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var pageX = window.pageXOffset !== undefined ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft;
var pageY = window.pageYOffset !== undefined ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
var bounds = elem.getBoundingClientRect();
var height = bounds.height,
left = bounds.left + pageX,
top = bounds.top + pageY,
width = bounds.width;
return pageY + window.innerHeight > top + buffer && pageY + buffer < top + height && pageX + window.innerWidth > left + buffer && pageX + buffer < left + width;
}
/**
@desc On click event for all shapes in a Viz.
@param {Object} *d* The data object being interacted with.
@param {Number} *i* The index of the data object being interacted with.
@private
*/
function clickShape (d, i) {
this._select.style("cursor", "auto");
if (this._drawDepth < this._groupBy.length - 1) {
var filterGroup = this._groupBy[this._drawDepth],
filterId = filterGroup(d, i);
this.hover(false);
if (this._tooltip(d, i)) this._tooltipClass.data([]).render();
var oldFilter = this._filter;
this._history.push({
depth: this._depth,
filter: oldFilter
});
this.config({
depth: this._drawDepth + 1,
filter: function filter(f, x) {
return (!oldFilter || oldFilter(f, x)) && filterGroup(f, x) === filterId;
}
}).render();
}
}
/**
@desc On click event for all legend shapes in a Viz.
@param {Object} *d* The data object being interacted with.
@param {Number} *i* The index of the data object being interacted with.
@private
*/
function clickLegend (d, i) {
var _this = this;
this._select.style("cursor", "auto");
if (this._tooltip(d, i)) this._tooltipClass.data([]).render();
var id = this._id(d, i);
if (!(id instanceof Array)) id = [id];
var hiddenIndex = this._hidden.indexOf(id[0]);
var soloIndex = this._solo.indexOf(id[0]);
var dataLength = arrayMerge(this._legendClass.data().map(function (d, i) {
var id = _this._id(d, i);
if (!(id instanceof Array)) id = [id];
return id;
})).length;
if (event$1.shiftKey) {
if (hiddenIndex < 0 && !this._solo.length) {
this._hidden = this._hidden.concat(id);
if (this._solo.length === dataLength) this._solo = [];
if (this._hidden.length === dataLength) this._hidden = [];
this.render();
} else if (soloIndex >= 0) {
this._solo = [];
this._hidden = [];
this.render();
}
} else {
if (soloIndex < 0 && this._hidden.length < dataLength - 1) {
this._solo = id;
this._hidden = [];
} else {
this._solo = [];
this._hidden = [];
}
this.render();
}
}
var flattenIds = function flattenIds(levels) {
return levels.reduce(function (arr, level) {
if (level instanceof Array) {
if (arr.length) {
var oldArray = arr.slice();
arr = [];
level.forEach(function (id) {
return arr = arr.concat(oldArray.map(function (a) {
return "".concat(a, "_").concat(id);
}));
});
} else {
arr = level.slice();
}
} else if (arr.length) {
arr = arr.map(function (a) {
return "".concat(a, "_").concat(level);
});
} else {
arr.push(level);
}
return arr;
}, []);
};
/**
@desc On mouseenter event for all shapes in a Viz.
@param {Object} *d* The data object being interacted with.
@param {Number} *i* The index of the data object being interacted with.
@private
*/
function mouseenter (d, i) {
var _this = this;
if (this._shapeConfig.hoverOpacity !== 1) {
var filterIds = flattenIds(this._ids(d, i));
this.hover(function (h, x) {
var ids = flattenIds(_this._ids(h, x));
return filterIds.some(function (id) {
return ids.includes(id);
});
});
}
}
/**
@desc On mouseleave event for all shapes in a Viz.
@param {Object} *d* The data object being interacted with.
@param {Number} *i* The index of the data object being interacted with.
@private
*/
function mouseleave (d, i) {
var _this = this;
setTimeout(function () {
if (_this._shapeConfig.hoverOpacity !== 1 && _this._hover ? _this._hover(d, i) : true) {
_this.hover(false);
}
var tooltipData = _this._tooltipClass.data();
if (tooltipData.length && _this._tooltip(d, i)) {
var tooltipDatum = tooltipData[0];
while (tooltipDatum.__d3plus__ && tooltipDatum.data) {
tooltipDatum = tooltipDatum.data;
}
if (_this._id(tooltipDatum) === _this._id(d)) _this._tooltipClass.data([]).render();
}
}, 50);
this._select.style("cursor", "auto");
}
/**
@desc Tooltip logic for a specified data point.
@param {Object} *d* The data object being interacted with.
@param {Number} *i* The index of the data object being interacted with.
@param {Object} [*config*] Optional configuration methods for the Tooltip class.
@private
*/
function mousemoveLegend (d, i, x) {
var _this = this;
var position = event$1.touches ? [event$1.touches[0].clientX, event$1.touches[0].clientY] : [event$1.clientX, event$1.clientY];
var dataLength = arrayMerge(this._legendClass.data().map(function (d, i) {
var id = _this._id(d, i);
if (!(id instanceof Array)) id = [id];
return id;
})).length;
if (d && this._tooltip(d, i)) {
var id = this._id(d, i);
if (id instanceof Array) id = id[0];
var t = this._translate;
this._select.style("cursor", "pointer");
this._tooltipClass.data([x || d]).footer(this._solo.length && !this._solo.includes(id) ? t("Click to Highlight") : this._solo.length === 1 && this._solo.includes(id) || this._hidden.length === dataLength - 1 ? t("Click to Reset") : this._solo.includes(id) ? t("Click to Hide") : this._hidden.includes(id) ? t("Click to Highlight") : "".concat(t("Click to Highlight"), "<br />").concat(t("Shift+Click to Hide"))).title(this._legendConfig.label ? this._legendClass.label() : legendLabel.bind(this)).position(position).config(configPrep.bind(this)(this._tooltipConfig)).config(configPrep.bind(this)(this._legendTooltip)).render();
}
}
/**
@desc Tooltip logic for a specified data point.
@param {Object} *d* The data object being interacted with.
@param {Number} *i* The index of the data object being interacted with.
@param {Object} [*config*] Optional configuration methods for the Tooltip class.
@private
*/
function mousemoveShape (d, i, x) {
if (d && this._tooltip(d, i)) {
this._select.style("cursor", "pointer");
var position = event$1.touches ? [event$1.touches[0].clientX, event$1.touches[0].clientY] : [event$1.clientX, event$1.clientY];
this._tooltipClass.data([x || d]).footer(this._drawDepth < this._groupBy.length - 1 ? this._translate("Click to Expand") : false).title(this._drawLabel).position(position).config(configPrep.bind(this)(this._tooltipConfig)).render();
}
}
/**
@desc On touchstart event for the Body element.
@private
*/
function touchstartBody (d) {
event$1.preventDefault();
event$1.stopPropagation();
if (!d) this._tooltipClass.data([]).render();
}
function _slicedToArray$4(arr, i) {
return _arrayWithHoles$4(arr) || _iterableToArrayLimit$4(arr, i) || _unsupportedIterableToArray$6(arr, i) || _nonIterableRest$4();
}
function _nonIterableRest$4() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _unsupportedIterableToArray$6(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray$6(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$6(o, minLen);
}
function _arrayLikeToArray$6(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) {
arr2[i] = arr[i];
}
return arr2;
}
function _iterableToArrayLimit$4(arr, i) {
if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _arrayWithHoles$4(arr) {
if (Array.isArray(arr)) return arr;
}
var brushing = false;
/**
@name zoomControls
@desc Sets up initial zoom events and controls.
@private
*/
function zoomControls () {
if (!this._container || !this._zoomGroup) return;
var height = this._zoomHeight || this._height - this._margin.top - this._margin.bottom,
that = this,
width = this._zoomWidth || this._width - this._margin.left - this._margin.right;
this._zoomBehavior.extent([[0, 0], [width, height]]).scaleExtent([1, this._zoomMax]).translateExtent([[0, 0], [width, height]]).on("zoom", zoomed.bind(this));
this._zoomToBounds = zoomToBounds.bind(this);
var control = _select(this._select.node().parentNode).selectAll("div.d3plus-zoom-control").data(this._zoom ? [0] : []);
var controlEnter = control.enter().append("div").attr("class", "d3plus-zoom-control");
control.exit().remove();
control = control.merge(controlEnter).style("position", "absolute").style("top", "".concat(this._margin.top, "px")).style("left", "".concat(this._margin.left, "px"));
controlEnter.append("div").attr("class", "zoom-control zoom-in");
control.select(".zoom-in").on("click", zoomMath.bind(this, this._zoomFactor)).html("&#65291;");
controlEnter.append("div").attr("class", "zoom-control zoom-out");
control.select(".zoom-out").on("click", zoomMath.bind(this, 1 / this._zoomFactor)).html("&#65293;");
controlEnter.append("div").attr("class", "zoom-control zoom-reset");
control.select(".zoom-reset").on("click", zoomMath.bind(this, 0)).html("&#8634");
controlEnter.append("div").attr("class", "zoom-control zoom-brush");
control.select(".zoom-brush").on("click", function () {
_select(this).classed("active", !brushing).call(stylize, brushing ? that._zoomControlStyle || {} : that._zoomControlStyleActive || {});
zoomEvents.bind(that)(!brushing);
}).html("&#164");
control.selectAll(".zoom-control").call(stylize, that._zoomControlStyle).on("mouseenter", function () {
_select(this).call(stylize, that._zoomControlStyleHover || {});
}).on("mouseleave", function () {
_select(this).call(stylize, _select(this).classed("active") ? that._zoomControlStyleActive || {} : that._zoomControlStyle || {});
});
this._zoomBrush.extent([[0, 0], [width, height]]).filter(function () {
return !event$1.button && event$1.detail < 2;
}).handleSize(this._zoomBrushHandleSize).on("start", brushStart.bind(this)).on("brush", brushBrush.bind(this)).on("end", brushEnd.bind(this));
var brushGroup = this._container.selectAll("g.brush").data([0]);
this._brushGroup = brushGroup.enter().append("g").attr("class", "brush").merge(brushGroup).call(this._zoomBrush);
zoomEvents.bind(this)();
if (this._renderTiles) this._renderTiles(transform(this._container.node()), 0);
}
/**
@name zoomEvents
@desc Handles adding/removing zoom event listeners.
@private
*/
function zoomEvents() {
var brush = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
brushing = brush;
if (brushing) this._brushGroup.style("display", "inline");else this._brushGroup.style("display", "none");
if (!brushing && this._zoom) {
this._container.call(this._zoomBehavior);
if (!this._zoomScroll) {
this._container.on("wheel.zoom", null);
}
if (!this._zoomPan) {
this._container.on("mousedown.zoom mousemove.zoom", null).on("touchstart.zoom touchmove.zoom touchend.zoom touchcancel.zoom", null);
}
} else {
this._container.on(".zoom", null);
}
}
/**
@name zoomed
@desc Handles events dispatched from this._zoomBehavior
@param {Object} [*transform* = event.transform]
@param {Number} [*duration* = 0]
@private
*/
function zoomed() {
var transform$1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; // console.log(transform || event.transform);
if (this._zoomGroup) {
if (!duration) this._zoomGroup.attr("transform", transform$1 || event$1.transform);else this._zoomGroup.transition().duration(duration).attr("transform", transform$1 || event$1.transform);
}
if (this._renderTiles) this._renderTiles(transform(this._container.node()), duration);
}
/**
@name zoomMath
@desc Zooms in or out based on the provided multiplier.
@param {Number} [*factor* = 0]
@private
*/
function zoomMath() {
var factor = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
if (!this._container) return;
var center = this._zoomBehavior.extent().bind(document)()[1].map(function (d) {
return d / 2;
}),
scaleExtent = this._zoomBehavior.scaleExtent(),
t = transform(this._container.node());
if (!factor) {
t.k = scaleExtent[0];
t.x = 0;
t.y = 0;
} else {
var translate0 = [(center[0] - t.x) / t.k, (center[1] - t.y) / t.k];
t.k = Math.min(scaleExtent[1], t.k * factor);
if (t.k <= scaleExtent[0]) {
t.k = scaleExtent[0];
t.x = 0;
t.y = 0;
} else {
t.x += center[0] - (translate0[0] * t.k + t.x);
t.y += center[1] - (translate0[1] * t.k + t.y);
}
}
zoomed.bind(this)(t, this._duration);
}
/**
@name zoomToBounds
@desc Zooms to given bounds.
@param {Array} *bounds*
@param {Number} [*duration* = 0]
@private
*/
function zoomToBounds(bounds) {
var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this._duration;
var scaleExtent = this._zoomBehavior.scaleExtent(),
t = transform(this._container.node());
if (bounds) {
var _this$_zoomBehavior$t = _slicedToArray$4(this._zoomBehavior.translateExtent()[1], 2),
width = _this$_zoomBehavior$t[0],
height = _this$_zoomBehavior$t[1],
dx = bounds[1][0] - bounds[0][0],
dy = bounds[1][1] - bounds[0][1];
var k = Math.min(scaleExtent[1], 1 / Math.max(dx / width, dy / height));
var xMod, yMod;
if (dx / dy < width / height) {
k *= (height - this._zoomPadding * 2) / height;
xMod = (width - dx * k) / 2 / k;
yMod = this._zoomPadding / k;
} else {
k *= (width - this._zoomPadding * 2) / width;
yMod = (height - dy * k) / 2 / k;
xMod = this._zoomPadding / k;
}
t.x = (t.x - bounds[0][0] + xMod) * (t.k * k / t.k);
t.y = (t.y - bounds[0][1] + yMod) * (t.k * k / t.k);
t.k *= k;
if (t.x > 0) t.x = 0;else if (t.x < width * -t.k + width) t.x = width * -t.k + width;
if (t.y > 0) t.y = 0;else if (t.y < height * -t.k + height) t.y = height * -t.k + height;
} else {
t.k = scaleExtent[0];
t.x = 0;
t.y = 0;
}
zoomed.bind(this)(t, duration);
}
/**
@desc Triggered on brush "brush".
@private
*/
function brushBrush() {
brushStyle.bind(this)();
}
/**
@desc Triggered on brush "end".
@private
*/
function brushEnd() {
if (!event$1.selection) return; // Only transition after input.
this._brushGroup.call(this._zoomBrush.move, null);
zoomToBounds.bind(this)(event$1.selection);
}
/**
@desc Triggered on brush "start".
@private
*/
function brushStart() {
brushStyle.bind(this)();
}
/**
@desc Overrides the default brush styles.
@private
*/
function brushStyle() {
this._brushGroup.selectAll(".selection").call(attrize, this._zoomBrushSelectionStyle || {});
this._brushGroup.selectAll(".handle").call(attrize, this._zoomBrushHandleStyle || {});
}
/**
@name _drawAttribution
@desc Draws absolute positioned attribution text.
@private
*/
function drawAttribution () {
var attr = _select(this._select.node().parentNode).selectAll("div.d3plus-attribution").data(this._attribution ? [0] : []);
var attrEnter = attr.enter().append("div").attr("class", "d3plus-attribution");
attr.exit().remove();
attr = attr.merge(attrEnter).style("position", "absolute").html(this._attribution).style("right", "".concat(this._margin.right, "px")).style("bottom", "".concat(this._margin.bottom, "px")).call(stylize, this._attributionStyle);
}
function _toConsumableArray$2(arr) {
return _arrayWithoutHoles$2(arr) || _iterableToArray$2(arr) || _unsupportedIterableToArray$7(arr) || _nonIterableSpread$2();
}
function _nonIterableSpread$2() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _iterableToArray$2(iter) {
if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
}
function _arrayWithoutHoles$2(arr) {
if (Array.isArray(arr)) return _arrayLikeToArray$7(arr);
}
function _slicedToArray$5(arr, i) {
return _arrayWithHoles$5(arr) || _iterableToArrayLimit$5(arr, i) || _unsupportedIterableToArray$7(arr, i) || _nonIterableRest$5();
}
function _nonIterableRest$5() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _unsupportedIterableToArray$7(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray$7(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$7(o, minLen);
}
function _arrayLikeToArray$7(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) {
arr2[i] = arr[i];
}
return arr2;
}
function _iterableToArrayLimit$5(arr, i) {
if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _arrayWithHoles$5(arr) {
if (Array.isArray(arr)) return arr;
}
function _typeof$n(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof$n = function _typeof(obj) {
return typeof obj;
};
} else {
_typeof$n = function _typeof(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof$n(obj);
}
function _classCallCheck$m(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties$m(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass$m(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$m(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$m(Constructor, staticProps);
return Constructor;
}
function _inherits$j(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf$j(subClass, superClass);
}
function _setPrototypeOf$j(o, p) {
_setPrototypeOf$j = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf$j(o, p);
}
function _createSuper$j(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct$j();
return function _createSuperInternal() {
var Super = _getPrototypeOf$j(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf$j(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn$j(this, result);
};
}
function _possibleConstructorReturn$j(self, call) {
if (call && (_typeof$n(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized$j(self);
}
function _assertThisInitialized$j(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _isNativeReflectConstruct$j() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _getPrototypeOf$j(o) {
_getPrototypeOf$j = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf$j(o);
}
/**
* Default padding logic that will return false if the screen is less than 600 pixels wide.
*/
function defaultPadding() {
return typeof window !== "undefined" ? window.innerWidth > 600 : true;
}
/**
* Turns an array of values into a list string.
*/
function listify(n) {
return n.reduce(function (str, item, i) {
if (!i) str += item;else if (i === n.length - 1 && i === 1) str += " and ".concat(item);else if (i === n.length - 1) str += ", and ".concat(item);else str += ", ".concat(item);
return str;
}, "");
}
/**
@class Viz
@extends external:BaseClass
@desc Creates an x/y plot based on an array of data. If *data* is specified, immediately draws the tree map based on the specified array and returns the current class instance. If *data* is not specified on instantiation, it can be passed/updated after instantiation using the [data](#treemap.data) method. See [this example](https://d3plus.org/examples/d3plus-treemap/getting-started/) for help getting started using the treemap generator.
*/
var Viz = /*#__PURE__*/function (_BaseClass) {
_inherits$j(Viz, _BaseClass);
var _super = _createSuper$j(Viz);
/**
@memberof Viz
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function Viz() {
var _this;
_classCallCheck$m(this, Viz);
_this = _super.call(this);
_this._aggs = {};
_this._ariaHidden = true;
_this._attribution = false;
_this._attributionStyle = {
background: "rgba(255, 255, 255, 0.75)",
border: "1px solid rgba(0, 0, 0, 0.25)",
color: "rgba(0, 0, 0, 0.75)",
display: "block",
font: "400 11px/11px 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
margin: "5px",
opacity: 0.75,
padding: "4px 6px 3px"
};
_this._backClass = new TextBox().on("click", function () {
if (_this._history.length) _this.config(_this._history.pop()).render();else _this.depth(_this._drawDepth - 1).filter(false).render();
}).on("mousemove", function () {
return _this._backClass.select().style("cursor", "pointer");
});
_this._backConfig = {
fontSize: 10,
padding: 5,
resize: false
};
_this._cache = true;
_this._color = function (d, i) {
return _this._groupBy[0](d, i);
};
_this._colorScaleClass = new ColorScale();
_this._colorScaleConfig = {};
_this._colorScalePadding = defaultPadding;
_this._colorScalePosition = "bottom";
_this._colorScaleMaxSize = 600;
var controlTest = new Select();
_this._controlCache = {};
_this._controlConfig = {
selectStyle: Object.assign({
margin: "5px"
}, controlTest.selectStyle())
};
_this._controlPadding = defaultPadding;
_this._data = [];
_this._dataCutoff = 100;
_this._detectResize = true;
_this._detectResizeDelay = 400;
_this._detectVisible = true;
_this._detectVisibleInterval = 1000;
_this._downloadButton = false;
_this._downloadConfig = {
type: "png"
};
_this._downloadPosition = "top";
_this._duration = 600;
_this._hidden = [];
_this._hiddenColor = constant$1("#aaa");
_this._hiddenOpacity = constant$1(0.5);
_this._history = [];
_this._groupBy = [accessor("id")];
_this._legend = true;
_this._legendClass = new Legend();
_this._legendConfig = {
label: legendLabel.bind(_assertThisInitialized$j(_this)),
shapeConfig: {
ariaLabel: legendLabel.bind(_assertThisInitialized$j(_this)),
labelConfig: {
fontColor: undefined,
fontResize: false,
padding: 0
}
}
};
_this._legendCutoff = 1;
_this._legendPadding = defaultPadding;
_this._legendPosition = "bottom";
_this._legendSort = function (a, b) {
return _this._drawLabel(a).localeCompare(_this._drawLabel(b));
};
_this._legendTooltip = {};
_this._loadingHTML = function () {
return "\n <div style=\"left: 50%; top: 50%; position: absolute; transform: translate(-50%, -50%); font-family: 'Roboto', 'Helvetica Neue', Helvetica, Arial, sans-serif;\">\n <strong>".concat(_this._translate("Loading Visualization"), "</strong>\n <sub style=\"bottom: 0; display: block; line-height: 1; margin-top: 5px;\"><a href=\"https://d3plus.org\" target=\"_blank\">").concat(_this._translate("Powered by D3plus"), "</a></sub>\n </div>");
};
_this._loadingMessage = true;
_this._lrucache = lrucache(10);
_this._messageClass = new Message();
_this._messageMask = "rgba(0, 0, 0, 0.05)";
_this._messageStyle = {
"bottom": "0",
"left": "0",
"position": "absolute",
"right": "0",
"text-align": "center",
"top": "0"
};
_this._noDataHTML = function () {
return "\n <div style=\"left: 50%; top: 50%; position: absolute; transform: translate(-50%, -50%); font-family: 'Roboto', 'Helvetica Neue', Helvetica, Arial, sans-serif;\">\n <strong>".concat(_this._translate("No Data Available"), "</strong>\n </div>");
};
_this._noDataMessage = true;
_this._on = {
"click.shape": clickShape.bind(_assertThisInitialized$j(_this)),
"click.legend": clickLegend.bind(_assertThisInitialized$j(_this)),
"mouseenter": mouseenter.bind(_assertThisInitialized$j(_this)),
"mouseleave": mouseleave.bind(_assertThisInitialized$j(_this)),
"mousemove.shape": mousemoveShape.bind(_assertThisInitialized$j(_this)),
"mousemove.legend": mousemoveLegend.bind(_assertThisInitialized$j(_this))
};
_this._queue = [];
_this._scrollContainer = (typeof window === "undefined" ? "undefined" : _typeof$n(window)) === undefined ? "" : window;
_this._shape = constant$1("Rect");
_this._shapes = [];
_this._shapeConfig = {
ariaLabel: function ariaLabel(d, i) {
return _this._drawLabel(d, i);
},
fill: function fill(d, i) {
while (d.__d3plus__ && d.data) {
d = d.data;
i = d.i;
}
if (_this._colorScale) {
var _c = _this._colorScale(d, i);
if (_c !== undefined && _c !== null) {
var scale = _this._colorScaleClass._colorScale;
var colors = _this._colorScaleClass.color();
if (!scale) return colors instanceof Array ? colors[colors.length - 1] : colors;else if (!scale.domain().length) return scale.range()[scale.range().length - 1];
return scale(_c);
}
}
var c = _this._color(d, i);
if (color$3(c)) return c;
return colorAssign(c);
},
labelConfig: {
fontColor: function fontColor(d, i) {
var c = typeof _this._shapeConfig.fill === "function" ? _this._shapeConfig.fill(d, i) : _this._shapeConfig.fill;
return colorContrast(c);
}
},
opacity: constant$1(1),
stroke: function stroke(d, i) {
var c = typeof _this._shapeConfig.fill === "function" ? _this._shapeConfig.fill(d, i) : _this._shapeConfig.fill;
return color$3(c).darker();
},
role: "presentation",
strokeWidth: constant$1(0)
};
_this._solo = [];
_this._svgDesc = "";
_this._svgTitle = "";
_this._timeline = true;
_this._timelineClass = new Timeline().align("end");
_this._timelineConfig = {
brushing: false,
padding: 5
};
_this._timelinePadding = defaultPadding;
_this._threshold = constant$1(0.0001);
_this._thresholdKey = undefined;
_this._thresholdName = function () {
return _this._translate("Values");
};
_this._titleClass = new TextBox();
_this._titleConfig = {
ariaHidden: true,
fontSize: 12,
padding: 5,
resize: false,
textAnchor: "middle"
};
_this._titlePadding = defaultPadding;
_this._tooltip = constant$1(true);
_this._tooltipClass = new Tooltip();
_this._tooltipConfig = {
pointerEvents: "none",
titleStyle: {
"max-width": "200px"
}
};
_this._totalClass = new TextBox();
_this._totalConfig = {
fontSize: 10,
padding: 5,
resize: false,
textAnchor: "middle"
};
_this._totalFormat = function (d) {
return "".concat(_this._translate("Total"), ": ").concat(formatAbbreviate(d, _this._locale));
};
_this._totalPadding = defaultPadding;
_this._zoom = false;
_this._zoomBehavior = zoom();
_this._zoomBrush = brush();
_this._zoomBrushHandleSize = 1;
_this._zoomBrushHandleStyle = {
fill: "#444"
};
_this._zoomBrushSelectionStyle = {
"fill": "#777",
"stroke-width": 0
};
_this._zoomControlStyle = {
"background": "rgba(255, 255, 255, 0.75)",
"border": "1px solid rgba(0, 0, 0, 0.75)",
"color": "rgba(0, 0, 0, 0.75)",
"display": "block",
"font": "900 15px/21px 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
"height": "20px",
"margin": "5px",
"opacity": 0.75,
"padding": 0,
"text-align": "center",
"width": "20px"
};
_this._zoomControlStyleActive = {
background: "rgba(0, 0, 0, 0.75)",
color: "rgba(255, 255, 255, 0.75)",
opacity: 1
};
_this._zoomControlStyleHover = {
cursor: "pointer",
opacity: 1
};
_this._zoomFactor = 2;
_this._zoomMax = 16;
_this._zoomPadding = 20;
_this._zoomPan = true;
_this._zoomScroll = true;
return _this;
}
/**
@memberof Viz
@desc Called by draw before anything is drawn. Formats the data and performs preparations for draw.
@private
*/
_createClass$m(Viz, [{
key: "_preDraw",
value: function _preDraw() {
var _this2 = this;
var that = this; // based on the groupBy, determine the draw depth and current depth id
this._drawDepth = this._depth !== void 0 ? this._depth : this._groupBy.length - 1;
this._id = this._groupBy[this._drawDepth];
this._ids = function (d, i) {
return _this2._groupBy.map(function (g) {
return !d || d.__d3plus__ && !d.data ? undefined : g(d.__d3plus__ ? d.data : d, d.__d3plus__ ? d.i : i);
}).filter(function (g) {
return g !== undefined && g !== null;
});
};
this._drawLabel = function (d, i) {
var depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _this2._drawDepth;
if (!d) return "";
while (d.__d3plus__ && d.data) {
d = d.data;
i = d.i;
}
if (d._isAggregation) {
return "".concat(_this2._thresholdName(d, i), " < ").concat(formatAbbreviate(d._threshold * 100, _this2._locale), "%");
}
if (_this2._label) return "".concat(_this2._label(d, i));
var l = that._ids(d, i).slice(0, depth + 1);
var n = l.reverse().find(function (ll) {
return !(ll instanceof Array);
}) || l[l.length - 1];
return n instanceof Array ? listify(n) : "".concat(n);
}; // set the default timeFilter if it has not been specified
if (this._time && !this._timeFilter && this._data.length) {
var dates = this._data.map(this._time).map(date$2);
var d = this._data[0],
i = 0;
if (this._discrete && "_".concat(this._discrete) in this && this["_".concat(this._discrete)](d, i) === this._time(d, i)) {
this._timeFilter = function () {
return true;
};
} else {
var latestTime = +max(dates);
this._timeFilter = function (d, i) {
return +date$2(_this2._time(d, i)) === latestTime;
};
}
}
this._filteredData = [];
this._legendData = [];
var flatData = [];
if (this._data.length) {
flatData = this._timeFilter ? this._data.filter(this._timeFilter) : this._data;
if (this._filter) flatData = flatData.filter(this._filter);
var dataNest = nest();
for (var _i = 0; _i <= this._drawDepth; _i++) {
dataNest.key(this._groupBy[_i]);
}
if (this._discrete && "_".concat(this._discrete) in this) dataNest.key(this["_".concat(this._discrete)]);
if (this._discrete && "_".concat(this._discrete, "2") in this) dataNest.key(this["_".concat(this._discrete, "2")]);
var tree = dataNest.rollup(function (leaves) {
var index = _this2._data.indexOf(leaves[0]);
var shape = _this2._shape(leaves[0], index);
var id = _this2._id(leaves[0], index);
var d = objectMerge(leaves, _this2._aggs);
if (!_this2._hidden.includes(id) && (!_this2._solo.length || _this2._solo.includes(id))) {
if (!_this2._discrete && shape === "Line") _this2._filteredData = _this2._filteredData.concat(leaves);else _this2._filteredData.push(d);
}
_this2._legendData.push(d);
}).entries(flatData);
this._filteredData = this._thresholdFunction(this._filteredData, tree);
} // overrides the hoverOpacity of shapes if data is larger than cutoff
var uniqueIds = nest().key(this._id).entries(this._filteredData).length;
if (uniqueIds > this._dataCutoff) {
if (this._userHover === undefined) this._userHover = this._shapeConfig.hoverOpacity || 0.5;
if (this._userDuration === undefined) this._userDuration = this._shapeConfig.duration || 600;
this._shapeConfig.hoverOpacity = 1;
this._shapeConfig.duration = 0;
} else if (this._userHover !== undefined) {
this._shapeConfig.hoverOpacity = this._userHover;
this._shapeConfig.duration = this._userDuration;
}
if (this._noDataMessage && !this._filteredData.length) {
this._messageClass.render({
container: this._select.node().parentNode,
html: this._noDataHTML(this),
mask: false,
style: this._messageStyle
});
}
}
/**
@memberof Viz
@desc Called by render once all checks are passed.
@private
*/
}, {
key: "_draw",
value: function _draw() {
if (this._legendPosition === "left" || this._legendPosition === "right") drawLegend.bind(this)(this._filteredData);
if (this._colorScalePosition === "left" || this._colorScalePosition === "right" || this._colorScalePosition === false) drawColorScale.bind(this)(this._filteredData);
drawBack.bind(this)();
drawTitle.bind(this)(this._filteredData);
drawTotal.bind(this)(this._filteredData);
drawTimeline.bind(this)(this._filteredData);
drawControls.bind(this)(this._filteredData);
if (this._legendPosition === "top" || this._legendPosition === "bottom") drawLegend.bind(this)(this._legendData);
if (this._colorScalePosition === "top" || this._colorScalePosition === "bottom") drawColorScale.bind(this)(this._filteredData);
this._shapes = []; // Draws a container and zoomGroup to test functionality.
// this._testGroup = this._select.selectAll("g.d3plus-viz-testGroup").data([0]);
// const enterTest = this._testGroup.enter().append("g").attr("class", "d3plus-viz-testGroup")
// .merge(this._testGroup);
// this._testGroup = enterTest.merge(this._testGroup);
// const bgHeight = this._height - this._margin.top - this._margin.bottom;
// const bgWidth = this._width - this._margin.left - this._margin.right;
// new Rect()
// .data([{id: "background"}])
// .select(this._testGroup.node())
// .x(bgWidth / 2 + this._margin.left)
// .y(bgHeight / 2 + this._margin.top)
// .width(bgWidth)
// .height(bgHeight)
// .fill("#ccc")
// .render();
// this._zoomGroup = this._select.selectAll("g.d3plus-viz-zoomGroup").data([0]);
// const enter = this._zoomGroup.enter().append("g").attr("class", "d3plus-viz-zoomGroup")
// .merge(this._zoomGroup);
// this._zoomGroup = enter.merge(this._zoomGroup);
// const testConfig = {
// on: {
// click: this._on["click.shape"],
// mouseenter: this._on.mouseenter,
// mouseleave: this._on.mouseleave,
// mousemove: this._on["mousemove.shape"]
// }
// };
// const testWidth = 10;
// this._shapes.push(new Rect()
// .config(this._shapeConfig)
// .config(configPrep.bind(this)(testConfig))
// .data(this._filteredData)
// .label("Test Label")
// .select(this._zoomGroup.node())
// .id(this._id)
// .x(() => Math.random() * bgWidth)
// .y(() => Math.random() * bgHeight)
// .width(testWidth)
// .height(testWidth)
// .render());
}
/**
* Applies the threshold algorithm according to the type of chart used.
* @param {Array} data The data to process.
*/
}, {
key: "_thresholdFunction",
value: function _thresholdFunction(data) {
return data;
}
/**
@memberof Viz
@desc Draws the visualization given the specified configuration.
@param {Function} [*callback*] An optional callback function that, if passed, will be called after animation is complete.
@chainable
*/
}, {
key: "render",
value: function render(callback) {
var _this3 = this; // Resets margins and padding
this._margin = {
bottom: 0,
left: 0,
right: 0,
top: 0
};
this._padding = {
bottom: 0,
left: 0,
right: 0,
top: 0
};
this._transition = transition().duration(this._duration); // Appends a fullscreen SVG to the BODY if a container has not been provided through .select().
if (this._select === void 0 || this._select.node().tagName.toLowerCase() !== "svg") {
var _parent = this._select === void 0 ? _select("body").append("div") : this._select;
var svg = _parent.append("svg");
this.select(svg.node());
}
/** detects width and height and sets SVG properties */
function setSVGSize() {
var display = this._select.style("display");
this._select.style("display", "none");
var _getSize = getSize$1(this._select.node().parentNode),
_getSize2 = _slicedToArray$5(_getSize, 2),
w = _getSize2[0],
h = _getSize2[1];
w -= parseFloat(this._select.style("border-left-width"), 10);
w -= parseFloat(this._select.style("border-right-width"), 10);
h -= parseFloat(this._select.style("border-top-width"), 10);
h -= parseFloat(this._select.style("border-bottom-width"), 10);
this._select.style("display", display);
if (this._autoWidth) {
this.width(w);
this._select.style("width", "".concat(this._width, "px")).attr("width", "".concat(this._width, "px"));
}
if (this._autoHeight) {
this.height(h);
this._select.style("height", "".concat(this._height, "px")).attr("height", "".concat(this._height, "px"));
}
} // Calculates the width and/or height of the Viz based on the this._select, if either has not been defined.
if ((!this._width || !this._height) && (!this._detectVisible || inViewport(this._select.node()))) {
this._autoWidth = this._width === undefined;
this._autoHeight = this._height === undefined;
setSVGSize.bind(this)();
}
this._select.attr("class", "d3plus-viz").attr("aria-hidden", this._ariaHidden).attr("aria-labelledby", "".concat(this._uuid, "-title ").concat(this._uuid, "-desc")).attr("role", "img").attr("xmlns", "http://www.w3.org/2000/svg").attr("xmlns:xlink", "http://www.w3.org/1999/xlink").transition(transition).style("width", this._width !== undefined ? "".concat(this._width, "px") : undefined).style("height", this._height !== undefined ? "".concat(this._height, "px") : undefined).attr("width", this._width !== undefined ? "".concat(this._width, "px") : undefined).attr("height", this._height !== undefined ? "".concat(this._height, "px") : undefined); // sets "position: relative" on the SVG parent if currently undefined
var parent = _select(this._select.node().parentNode);
var position = parent.style("position");
if (position === "static") parent.style("position", "relative"); // Updates the <title> tag if already exists else creates a new <title> tag on this.select.
var svgTitle = this._select.selectAll("title").data([0]);
var svgTitleEnter = svgTitle.enter().append("title").attr("id", "".concat(this._uuid, "-title"));
svgTitle.merge(svgTitleEnter).text(this._svgTitle); // Updates the <desc> tag if already exists else creates a new <desc> tag on this.select.
var svgDesc = this._select.selectAll("desc").data([0]);
var svgDescEnter = svgDesc.enter().append("desc").attr("id", "".concat(this._uuid, "-desc"));
svgDesc.merge(svgDescEnter).text(this._svgDesc);
this._visiblePoll = clearInterval(this._visiblePoll);
this._resizePoll = clearTimeout(this._resizePoll);
this._scrollPoll = clearTimeout(this._scrollPoll);
_select(this._scrollContainer).on("scroll.".concat(this._uuid), null);
_select(this._scrollContainer).on("resize.".concat(this._uuid), null);
if (this._detectVisible && this._select.style("visibility") === "hidden") {
this._visiblePoll = setInterval(function () {
if (_this3._select.style("visibility") !== "hidden") {
_this3._visiblePoll = clearInterval(_this3._visiblePoll);
_this3.render(callback);
}
}, this._detectVisibleInterval);
} else if (this._detectVisible && this._select.style("display") === "none") {
this._visiblePoll = setInterval(function () {
if (_this3._select.style("display") !== "none") {
_this3._visiblePoll = clearInterval(_this3._visiblePoll);
_this3.render(callback);
}
}, this._detectVisibleInterval);
} else if (this._detectVisible && !inViewport(this._select.node())) {
_select(this._scrollContainer).on("scroll.".concat(this._uuid), function () {
if (!_this3._scrollPoll) {
_this3._scrollPoll = setTimeout(function () {
if (inViewport(_this3._select.node())) {
_select(_this3._scrollContainer).on("scroll.".concat(_this3._uuid), null);
_this3.render(callback);
}
_this3._scrollPoll = clearTimeout(_this3._scrollPoll);
}, _this3._detectVisibleInterval);
}
});
} else {
var q = queue();
this._queue.forEach(function (p) {
var cache = _this3._cache ? _this3._lrucache.get("".concat(p[3], "_").concat(p[1])) : undefined;
if (!cache) q.defer.apply(q, _toConsumableArray$2(p));else _this3["_".concat(p[3])] = p[2] ? p[2](cache) : cache;
});
this._queue = [];
if (this._loadingMessage && q._tasks.length) {
this._messageClass.render({
container: this._select.node().parentNode,
html: this._loadingHTML(this),
mask: this._filteredData ? this._messageMask : false,
style: this._messageStyle
});
}
q.awaitAll(function () {
var columns = _this3._data instanceof Array && _this3._data.length > 0 ? Object.keys(_this3._data[0]) : [];
var svgTable = _this3._select.selectAll("g.data-table").data(!_this3._ariaHidden && _this3._data instanceof Array && _this3._data.length ? [0] : []);
var svgTableEnter = svgTable.enter().append("g").attr("class", "data-table").attr("role", "table");
svgTable.exit().remove();
var rows = svgTable.merge(svgTableEnter).selectAll("text").data(_this3._data instanceof Array ? range(0, _this3._data.length + 1) : []);
rows.exit().remove();
var cells = rows.merge(rows.enter().append("text").attr("role", "row")).selectAll("tspan").data(function (d, i) {
return columns.map(function (c) {
return {
role: i ? "cell" : "columnheader",
text: i ? _this3._data[i - 1][c] : c
};
});
});
cells.exit().remove();
cells.merge(cells.enter().append("tspan")).attr("role", function (d) {
return d.role;
}).attr("dy", "-1000px").html(function (d) {
return d.text;
});
_this3._preDraw();
_this3._draw(callback);
zoomControls.bind(_this3)();
drawAttribution.bind(_this3)();
if (_this3._messageClass._isVisible && (!_this3._noDataMessage || _this3._filteredData.length)) _this3._messageClass.hide();
if (_this3._detectResize && (_this3._autoWidth || _this3._autoHeight)) {
_select(_this3._scrollContainer).on("resize.".concat(_this3._uuid), function () {
_this3._resizePoll = clearTimeout(_this3._resizePoll);
_this3._resizePoll = setTimeout(function () {
_this3._resizePoll = clearTimeout(_this3._resizePoll);
setSVGSize.bind(_this3)();
_this3.render(callback);
}, _this3._detectResizeDelay);
});
}
if (callback) setTimeout(callback, _this3._duration + 100);
});
} // Attaches touchstart event listener to the BODY to hide the tooltip when the user touches any element without data
_select("body").on("touchstart.".concat(this._uuid), touchstartBody.bind(this));
return this;
}
/**
@memberof Viz
@desc If *value* is specified, sets the active method to the specified function and returns the current class instance.
@param {Function} [*value*]
@chainable
*/
}, {
key: "active",
value: function active(_) {
this._active = _;
if (this._shapeConfig.activeOpacity !== 1) {
this._shapes.forEach(function (s) {
return s.active(_);
});
if (this._legend) this._legendClass.active(_);
}
return this;
}
/**
@memberof Viz
@desc If *value* is specified, sets the aggregation method for each key in the object and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "aggs",
value: function aggs(_) {
return arguments.length ? (this._aggs = assign(this._aggs, _), this) : this._aggs;
}
/**
@memberof Viz
@desc Sets the "aria-hidden" attribute of the containing SVG element. The default value is "false", but it you need to hide the SVG from screen readers set this property to "true".
@param {Boolean} [*value* = true]
@chainable
*/
}, {
key: "ariaHidden",
value: function ariaHidden(_) {
return arguments.length ? (this._ariaHidden = _, this) : this._ariaHidden;
}
/**
@memberof Viz
@desc Sets text to be shown positioned absolute on top of the visualization in the bottom-right corner. This is most often used in Geomaps to display the copyright of map tiles. The text is rendered as HTML, so any valid HTML string will render as expected (eg. anchor links work).
@param {HTMLString|Boolean} *value* = false
@chainable
*/
}, {
key: "attribution",
value: function attribution(_) {
return arguments.length ? (this._attribution = _, this) : this._attribution;
}
/**
@memberof Viz
@desc If *value* is specified, sets the config method for the back button and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "attributionStyle",
value: function attributionStyle(_) {
return arguments.length ? (this._attributionStyle = assign(this._attributionStyle, _), this) : this._attributionStyle;
}
/**
@memberof Viz
@desc If *value* is specified, sets the config method for the back button and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "backConfig",
value: function backConfig(_) {
return arguments.length ? (this._backConfig = assign(this._backConfig, _), this) : this._backConfig;
}
/**
@memberof Viz
@desc Enables a lru cache that stores up to 5 previously loaded files/URLs. Helpful when constantly writing over the data array with a URL in the render function of a react component.
@param {Boolean} [*value* = false]
@chainable
*/
}, {
key: "cache",
value: function cache(_) {
return arguments.length ? (this._cache = _, this) : this._cache;
}
/**
@memberof Viz
@desc Defines the main color to be used for each data point in a visualization. Can be either an accessor function or a string key to reference in each data point. If a color value is returned, it will be used as is. If a string is returned, a unique color will be assigned based on the string.
@param {Function|String|False} [*value*]
@chainable
*/
}, {
key: "color",
value: function color(_) {
return arguments.length ? (this._color = !_ || typeof _ === "function" ? _ : accessor(_), this) : this._color;
}
/**
@memberof Viz
@desc Defines the value to be used for a color scale. Can be either an accessor function or a string key to reference in each data point.
@param {Function|String|False} [*value*]
@chainable
*/
}, {
key: "colorScale",
value: function colorScale(_) {
return arguments.length ? (this._colorScale = !_ || typeof _ === "function" ? _ : accessor(_), this) : this._colorScale;
}
/**
@memberof Viz
@desc A pass-through to the config method of ColorScale.
@param {Object} [*value*]
@chainable
*/
}, {
key: "colorScaleConfig",
value: function colorScaleConfig(_) {
return arguments.length ? (this._colorScaleConfig = assign(this._colorScaleConfig, _), this) : this._colorScaleConfig;
}
/**
@memberof Viz
@desc Tells the colorScale whether or not to use the internal padding defined by the visualization in it's positioning. For example, d3plus-plot will add padding on the left so that the colorScale appears centered above the x-axis. By default, this padding is only applied on screens larger than 600 pixels wide.
@param {Boolean|Function} [*value*]
@chainable
*/
}, {
key: "colorScalePadding",
value: function colorScalePadding(_) {
return arguments.length ? (this._colorScalePadding = typeof _ === "function" ? _ : constant$1(_), this) : this._colorScalePadding;
}
/**
@memberof Viz
@desc Defines which side of the visualization to anchor the color scale. Acceptable values are `"top"`, `"bottom"`, `"left"`, `"right"`, and `false`. A `false` value will cause the color scale to not be displayed, but will still color shapes based on the scale.
@param {String|Boolean} [*value* = "bottom"]
@chainable
*/
}, {
key: "colorScalePosition",
value: function colorScalePosition(_) {
return arguments.length ? (this._colorScalePosition = _, this) : this._colorScalePosition;
}
/**
@memberof Viz
@desc Sets the maximum pixel size for drawing the color scale: width for horizontal scales and height for vertical scales.
@param {Number} [*value* = 600]
@chainable
*/
}, {
key: "colorScaleMaxSize",
value: function colorScaleMaxSize(_) {
return arguments.length ? (this._colorScaleMaxSize = _, this) : this._colorScaleMaxSize;
}
/**
@memberof Viz
@desc Defines a list of controls to be rendered at the bottom of the visualization.
@param {Array} [*value*]
@chainable
*/
}, {
key: "controls",
value: function controls(_) {
return arguments.length ? (this._controls = _, this) : this._controls;
}
/**
@memberof Viz
@desc If *value* is specified, sets the config method for the controls and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "controlConfig",
value: function controlConfig(_) {
return arguments.length ? (this._controlConfig = assign(this._controlConfig, _), this) : this._controlConfig;
}
/**
@memberof Viz
@desc Tells the controls whether or not to use the internal padding defined by the visualization in it's positioning. For example, d3plus-plot will add padding on the left so that the controls appears centered above the x-axis. By default, this padding is only applied on screens larger than 600 pixels wide.
@param {Boolean|Function} [*value*]
@chainable
*/
}, {
key: "controlPadding",
value: function controlPadding(_) {
return arguments.length ? (this._controlPadding = typeof _ === "function" ? _ : constant$1(_), this) : this._controlPadding;
}
/**
@memberof Viz
@desc Sets the primary data array to be used when drawing the visualization. The value passed should be an *Array* of objects or a *String* representing a filepath or URL to be loaded. The following filetypes are supported: `csv`, `tsv`, `txt`, and `json`.
If your data URL needs specific headers to be set, an Object with "url" and "headers" keys may also be passed.
Additionally, a custom formatting function can be passed as a second argument to this method. This custom function will be passed the data that has been loaded, as long as there are no errors. This function should return the final array of obejcts to be used as the primary data array. For example, some JSON APIs return the headers split from the data values to save bandwidth. These would need be joined using a custom formatter.
If *data* is not specified, this method returns the current primary data array, which defaults to an empty array (`[]`);
@param {Array|String} *data* = []
@param {Function} [*formatter*]
@chainable
*/
}, {
key: "data",
value: function data(_, f) {
if (arguments.length) {
var prev = this._queue.find(function (q) {
return q[3] === "data";
});
var d = [load.bind(this), _, f, "data"];
if (prev) this._queue[this._queue.indexOf(prev)] = d;else this._queue.push(d);
this._hidden = [];
this._solo = [];
return this;
}
return this._data;
}
/**
@memberof Viz
@desc If the number of visible data points exceeds this number, the default hover behavior will be disabled (helpful for very large visualizations bogging down the DOM with opacity updates).
@param {Number} [*value* = 100]
@chainable
*/
}, {
key: "dataCutoff",
value: function dataCutoff(_) {
return arguments.length ? (this._dataCutoff = _, this) : this._dataCutoff;
}
/**
@memberof Viz
@desc If *value* is specified, sets the depth to the specified number and returns the current class instance. The *value* should correspond with an index in the [groupBy](#groupBy) array.
@param {Number} [*value*]
@chainable
*/
}, {
key: "depth",
value: function depth(_) {
return arguments.length ? (this._depth = _, this) : this._depth;
}
/**
@memberof Viz
@desc If the width and/or height of a Viz is not user-defined, it is determined by the size of it's parent element. When this method is set to `true`, the Viz will listen for the `window.onresize` event and adjust it's dimensions accordingly.
@param {Boolean} *value* = true
@chainable
*/
}, {
key: "detectResize",
value: function detectResize(_) {
return arguments.length ? (this._detectResize = _, this) : this._detectResize;
}
/**
@memberof Viz
@desc When resizing the browser window, this is the millisecond delay to trigger the resize event.
@param {Number} *value* = 400
@chainable
*/
}, {
key: "detectResizeDelay",
value: function detectResizeDelay(_) {
return arguments.length ? (this._detectResizeDelay = _, this) : this._detectResizeDelay;
}
/**
@memberof Viz
@desc Toggles whether or not the Viz should try to detect if it visible in the current viewport. When this method is set to `true`, the Viz will only be rendered when it has entered the viewport either through scrolling or if it's display or visibility is changed.
@param {Boolean} *value* = true
@chainable
*/
}, {
key: "detectVisible",
value: function detectVisible(_) {
return arguments.length ? (this._detectVisible = _, this) : this._detectVisible;
}
/**
@memberof Viz
@desc The interval, in milliseconds, for checking if the visualization is visible on the page.
@param {Number} *value* = 1000
@chainable
*/
}, {
key: "detectVisibleInterval",
value: function detectVisibleInterval(_) {
return arguments.length ? (this._detectVisibleInterval = _, this) : this._detectVisibleInterval;
}
/**
@memberof Viz
@desc If *value* is specified, sets the discrete accessor to the specified method name (usually an axis) and returns the current class instance.
@param {String} [*value*]
@chainable
*/
}, {
key: "discrete",
value: function discrete(_) {
return arguments.length ? (this._discrete = _, this) : this._discrete;
}
/**
@memberof Viz
@desc Shows a button that allows for downloading the current visualization.
@param {Boolean} [*value* = false]
@chainable
*/
}, {
key: "downloadButton",
value: function downloadButton(_) {
return arguments.length ? (this._downloadButton = _, this) : this._downloadButton;
}
/**
@memberof Viz
@desc Sets specific options of the saveElement function used when downloading the visualization.
@param {Object} [*value* = {type: "png"}]
@chainable
*/
}, {
key: "downloadConfig",
value: function downloadConfig(_) {
return arguments.length ? (this._downloadConfig = assign(this._downloadConfig, _), this) : this._downloadConfig;
}
/**
@memberof Viz
@desc Defines which control group to add the download button into.
@param {String} [*value* = "top"]
@chainable
*/
}, {
key: "downloadPosition",
value: function downloadPosition(_) {
return arguments.length ? (this._downloadPosition = _, this) : this._downloadPosition;
}
/**
@memberof Viz
@desc If *ms* is specified, sets the animation duration to the specified number and returns the current class instance. If *ms* is not specified, returns the current animation duration.
@param {Number} [*ms* = 600]
@chainable
*/
}, {
key: "duration",
value: function duration(_) {
return arguments.length ? (this._duration = _, this) : this._duration;
}
/**
@memberof Viz
@desc If *value* is specified, sets the filter to the specified function and returns the current class instance.
@param {Function} [*value*]
@chainable
*/
}, {
key: "filter",
value: function filter(_) {
return arguments.length ? (this._filter = _, this) : this._filter;
}
/**
@memberof Viz
@desc If *value* is specified, sets the group accessor(s) to the specified string, function, or array of values and returns the current class instance.
@param {String|Function|Array} [*value*]
@chainable
@example
function value(d) {
return d.id;
}
*/
}, {
key: "groupBy",
value: function groupBy(_) {
var _this4 = this;
if (!arguments.length) return this._groupBy;
if (!(_ instanceof Array)) _ = [_];
return this._groupBy = _.map(function (k) {
if (typeof k === "function") return k;else {
if (!_this4._aggs[k]) {
_this4._aggs[k] = function (a, c) {
var v = unique(a.map(c));
return v.length === 1 ? v[0] : v;
};
}
return accessor(k);
}
}), this;
}
/**
@memberof Viz
@desc If *value* is specified, sets the overall height to the specified number and returns the current class instance.
@param {Number} [*value* = window.innerHeight]
@chainable
*/
}, {
key: "height",
value: function height(_) {
return arguments.length ? (this._height = _, this) : this._height;
}
/**
@memberof Viz
@desc Defines the color used for legend shapes when the corresponding grouping is hidden from display (by clicking on the legend).
@param {Function|String} [*value* = "#aaa"]
@chainable
*/
}, {
key: "hiddenColor",
value: function hiddenColor(_) {
return arguments.length ? (this._hiddenColor = typeof _ === "function" ? _ : constant$1(_), this) : this._hiddenColor;
}
/**
@memberof Viz
@desc Defines the opacity used for legend labels when the corresponding grouping is hidden from display (by clicking on the legend).
@param {Function|Number} [*value* = 0.5]
@chainable
*/
}, {
key: "hiddenOpacity",
value: function hiddenOpacity(_) {
return arguments.length ? (this._hiddenOpacity = typeof _ === "function" ? _ : constant$1(_), this) : this._hiddenOpacity;
}
/**
@memberof Viz
@desc If *value* is specified, sets the hover method to the specified function and returns the current class instance.
@param {Function} [*value*]
@chainable
*/
}, {
key: "hover",
value: function hover(_) {
var _this5 = this;
var hoverFunction = this._hover = _;
if (this._shapeConfig.hoverOpacity !== 1) {
if (typeof _ === "function") {
var shapeData = arrayMerge(this._shapes.map(function (s) {
return s.data();
}));
shapeData = shapeData.concat(this._legendClass.data());
var activeData = _ ? shapeData.filter(_) : [];
var activeIds = [];
activeData.map(this._ids).forEach(function (ids) {
for (var x = 1; x <= ids.length; x++) {
activeIds.push(JSON.stringify(ids.slice(0, x)));
}
});
activeIds = activeIds.filter(function (id, i) {
return activeIds.indexOf(id) === i;
});
if (activeIds.length) hoverFunction = function hoverFunction(d, i) {
return activeIds.includes(JSON.stringify(_this5._ids(d, i)));
};
}
this._shapes.forEach(function (s) {
return s.hover(hoverFunction);
});
if (this._legend) this._legendClass.hover(hoverFunction);
}
return this;
}
/**
@memberof Viz
@desc If *value* is specified, sets the label accessor to the specified function or string and returns the current class instance.
@param {Function|String} [*value*]
@chainable
*/
}, {
key: "label",
value: function label(_) {
return arguments.length ? (this._label = typeof _ === "function" ? _ : constant$1(_), this) : this._label;
}
/**
@memberof Viz
@desc If *value* is specified, toggles the legend based on the specified boolean and returns the current class instance.
@param {Boolean} [*value* = true]
@chainable
*/
}, {
key: "legend",
value: function legend(_) {
return arguments.length ? (this._legend = _, this) : this._legend;
}
/**
@memberof Viz
@desc If *value* is specified, the object is passed to the legend's config method.
@param {Object} [*value*]
@chainable
*/
}, {
key: "legendConfig",
value: function legendConfig(_) {
return arguments.length ? (this._legendConfig = assign(this._legendConfig, _), this) : this._legendConfig;
}
/**
* @memberof Viz
* @desc If *value* is specified, sets the cutoff for the amount of categories in the legend.
* @param {Number} [*value* = 1]
* @chainable
*/
}, {
key: "legendCutoff",
value: function legendCutoff(_) {
return arguments.length ? (this._legendCutoff = _, this) : this._legendCutoff;
}
/**
@memberof Viz
@desc If *value* is specified, sets the config method for the legend tooltip and returns the current class instance.
@param {Object} [*value* = {}]
@chainable
*/
}, {
key: "legendTooltip",
value: function legendTooltip(_) {
return arguments.length ? (this._legendTooltip = assign(this._legendTooltip, _), this) : this._legendTooltip;
}
/**
@memberof Viz
@desc Tells the legend whether or not to use the internal padding defined by the visualization in it's positioning. For example, d3plus-plot will add padding on the left so that the legend appears centered underneath the x-axis. By default, this padding is only applied on screens larger than 600 pixels wide.
@param {Boolean|Function} [*value*]
@chainable
*/
}, {
key: "legendPadding",
value: function legendPadding(_) {
return arguments.length ? (this._legendPadding = typeof _ === "function" ? _ : constant$1(_), this) : this._legendPadding;
}
/**
@memberof Viz
@desc Defines which side of the visualization to anchor the legend. Expected values are `"top"`, `"bottom"`, `"left"`, and `"right"`.
@param {String} [*value* = "bottom"]
@chainable
*/
}, {
key: "legendPosition",
value: function legendPosition(_) {
return arguments.length ? (this._legendPosition = _, this) : this._legendPosition;
}
/**
@memberof Viz
@desc A JavaScript [sort comparator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) used to sort the legend.
@param {Function} *value*
@chainable
*/
}, {
key: "legendSort",
value: function legendSort(_) {
return arguments.length ? (this._legendSort = _, this) : this._legendSort;
}
/**
@memberof Viz
@desc Sets the inner HTML of the status message that is displayed when loading AJAX requests and displaying errors. Must be a valid HTML string or a function that, when passed this Viz instance, returns a valid HTML string.
@param {Function|String} [*value*]
@chainable
*/
}, {
key: "loadingHTML",
value: function loadingHTML(_) {
return arguments.length ? (this._loadingHTML = typeof _ === "function" ? _ : constant$1(_), this) : this._loadingHTML;
}
/**
@memberof Viz
@desc Toggles the visibility of the status message that is displayed when loading AJAX requests and displaying errors.
@param {Boolean} [*value* = true]
@chainable
*/
}, {
key: "loadingMessage",
value: function loadingMessage(_) {
return arguments.length ? (this._loadingMessage = _, this) : this._loadingMessage;
}
/**
@memberof Viz
@desc Sets the color of the mask used underneath the status message that is displayed when loading AJAX requests and displaying errors. Additionally, `false` will turn off the mask completely.
@param {Boolean|String} [*value* = "rgba(0, 0, 0, 0.1)"]
@chainable
*/
}, {
key: "messageMask",
value: function messageMask(_) {
return arguments.length ? (this._messageMask = _, this) : this._messageMask;
}
/**
@memberof Viz
@desc Defines the CSS style properties for the status message that is displayed when loading AJAX requests and displaying errors.
@param {Object} [*value*]
@chainable
*/
}, {
key: "messageStyle",
value: function messageStyle(_) {
return arguments.length ? (this._messageStyle = assign(this._messageStyle, _), this) : this._messageStyle;
}
/**
@memberof Viz
@desc Sets the inner HTML of the status message that is displayed when no data is supplied to the visualization. Must be a valid HTML string or a function that, when passed this Viz instance, returns a valid HTML string.
@param {Function|String} [*value*]
@chainable
*/
}, {
key: "noDataHTML",
value: function noDataHTML(_) {
return arguments.length ? (this._noDataHTML = typeof _ === "function" ? _ : constant$1(_), this) : this._noDataHTML;
}
/**
@memberof Viz
@desc Toggles the visibility of the status message that is displayed when no data is supplied to the visualization.
@param {Boolean} [*value* = true]
@chainable
*/
}, {
key: "noDataMessage",
value: function noDataMessage(_) {
return arguments.length ? (this._noDataMessage = _, this) : this._noDataMessage;
}
/**
@memberof Viz
@desc If using scroll or visibility detection, this method allow a custom override of the element to which the scroll detection function gets attached.
@param {String|HTMLElement} *selector*
@chainable
*/
}, {
key: "scrollContainer",
value: function scrollContainer(_) {
return arguments.length ? (this._scrollContainer = _, this) : this._scrollContainer;
}
/**
@memberof Viz
@desc If *selector* is specified, sets the SVG container element to the specified d3 selector or DOM element and returns the current class instance. If *selector* is not specified, returns the current SVG container element, which is `undefined` by default.
@param {String|HTMLElement} [*selector*]
@chainable
*/
}, {
key: "select",
value: function select(_) {
return arguments.length ? (this._select = _select(_), this) : this._select;
}
/**
@memberof Viz
@desc If *value* is specified, sets the shape accessor to the specified function or number and returns the current class instance.
@param {Function|String} [*value*]
@chainable
*/
}, {
key: "shape",
value: function shape(_) {
return arguments.length ? (this._shape = typeof _ === "function" ? _ : constant$1(_), this) : this._shape;
}
/**
@memberof Viz
@desc If *value* is specified, sets the config method for each shape and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "shapeConfig",
value: function shapeConfig(_) {
return arguments.length ? (this._shapeConfig = assign(this._shapeConfig, _), this) : this._shapeConfig;
}
/**
@memberof Viz
@desc If *value* is specified, sets the description accessor to the specified string and returns the current class instance.
@param {String} [*value*]
@chainable
*/
}, {
key: "svgDesc",
value: function svgDesc(_) {
return arguments.length ? (this._svgDesc = _, this) : this._svgDesc;
}
/**
@memberof Viz
@desc If *value* is specified, sets the title accessor to the specified string and returns the current class instance.
@param {String} [*value*]
@chainable
*/
}, {
key: "svgTitle",
value: function svgTitle(_) {
return arguments.length ? (this._svgTitle = _, this) : this._svgTitle;
}
/**
@memberof Viz
@desc If *value* is specified, sets the threshold for buckets to the specified function or string, and returns the current class instance.
@param {Function|Number} [value]
@chainable
*/
}, {
key: "threshold",
value: function threshold(_) {
if (arguments.length) {
if (typeof _ === "function") {
this._threshold = _;
} else if (isFinite(_) && !isNaN(_)) {
this._threshold = constant$1(_ * 1);
}
return this;
} else return this._threshold;
}
/**
@memberof Viz
@desc If *value* is specified, sets the accesor for the value used in the threshold algorithm, and returns the current class instance.
@param {Function|Number} [value]
@chainable
*/
}, {
key: "thresholdKey",
value: function thresholdKey(key) {
if (arguments.length) {
if (typeof key === "function") {
this._thresholdKey = key;
} else {
this._thresholdKey = accessor(key);
}
return this;
} else return this._thresholdKey;
}
/**
@memberof Viz
@desc If *value* is specified, sets the label for the bucket item, and returns the current class instance.
@param {Function|String} [value]
@chainable
*/
}, {
key: "thresholdName",
value: function thresholdName(_) {
return arguments.length ? (this._thresholdName = typeof _ === "function" ? _ : constant$1(_), this) : this._thresholdName;
}
/**
@memberof Viz
@desc If *value* is specified, sets the time accessor to the specified function or string and returns the current class instance.
@param {Function|String} [*value*]
@chainable
*/
}, {
key: "time",
value: function time(_) {
if (arguments.length) {
if (typeof _ === "function") {
this._time = _;
} else {
this._time = accessor(_);
if (!this._aggs[_]) {
this._aggs[_] = function (a, c) {
var v = unique(a.map(c));
return v.length === 1 ? v[0] : v;
};
}
}
this._timeFilter = false;
return this;
} else return this._time;
}
/**
@memberof Viz
@desc If *value* is specified, sets the time filter to the specified function and returns the current class instance.
@param {Function} [*value*]
@chainable
*/
}, {
key: "timeFilter",
value: function timeFilter(_) {
return arguments.length ? (this._timeFilter = _, this) : this._timeFilter;
}
/**
@memberof Viz
@desc If *value* is specified, toggles the timeline based on the specified boolean and returns the current class instance.
@param {Boolean} [*value* = true]
@chainable
*/
}, {
key: "timeline",
value: function timeline(_) {
return arguments.length ? (this._timeline = _, this) : this._timeline;
}
/**
@memberof Viz
@desc If *value* is specified, sets the config method for the timeline and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "timelineConfig",
value: function timelineConfig(_) {
return arguments.length ? (this._timelineConfig = assign(this._timelineConfig, _), this) : this._timelineConfig;
}
/**
@memberof Viz
@desc Tells the timeline whether or not to use the internal padding defined by the visualization in it's positioning. For example, d3plus-plot will add padding on the left so that the timeline appears centered underneath the x-axis. By default, this padding is only applied on screens larger than 600 pixels wide.
@param {Boolean|Function} [*value*]
@chainable
*/
}, {
key: "timelinePadding",
value: function timelinePadding(_) {
return arguments.length ? (this._timelinePadding = typeof _ === "function" ? _ : constant$1(_), this) : this._timelinePadding;
}
/**
@memberof Viz
@desc If *value* is specified, sets the title accessor to the specified function or string and returns the current class instance.
@param {Function|String} [*value*]
@chainable
*/
}, {
key: "title",
value: function title(_) {
return arguments.length ? (this._title = typeof _ === "function" ? _ : constant$1(_), this) : this._title;
}
/**
@memberof Viz
@desc If *value* is specified, sets the config method for the title and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "titleConfig",
value: function titleConfig(_) {
return arguments.length ? (this._titleConfig = assign(this._titleConfig, _), this) : this._titleConfig;
}
/**
@memberof Viz
@desc Tells the title whether or not to use the internal padding defined by the visualization in it's positioning. For example, d3plus-plot will add padding on the left so that the title appears centered above the x-axis. By default, this padding is only applied on screens larger than 600 pixels wide.
@param {Boolean|Function} [*value*]
@chainable
*/
}, {
key: "titlePadding",
value: function titlePadding(_) {
return arguments.length ? (this._titlePadding = typeof _ === "function" ? _ : constant$1(_), this) : this._titlePadding;
}
/**
@memberof Viz
@desc If *value* is specified, toggles the tooltip based on the specified boolean and returns the current class instance.
@param {Boolean|Function} [*value* = true]
@chainable
*/
}, {
key: "tooltip",
value: function tooltip(_) {
return arguments.length ? (this._tooltip = typeof _ === "function" ? _ : constant$1(_), this) : this._tooltip;
}
/**
@memberof Viz
@desc If *value* is specified, sets the config method for the tooltip and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "tooltipConfig",
value: function tooltipConfig(_) {
return arguments.length ? (this._tooltipConfig = assign(this._tooltipConfig, _), this) : this._tooltipConfig;
}
/**
@memberof Viz
@desc If *value* is specified, sets the total accessor to the specified function or string and returns the current class instance.
@param {Boolean|Function|String} [*value*]
@chainable
*/
}, {
key: "total",
value: function total(_) {
if (arguments.length) {
if (typeof _ === "function") this._total = _;else if (_) this._total = accessor(_);else this._total = false;
return this;
} else return this._total;
}
/**
@memberof Viz
@desc If *value* is specified, sets the config method for the total and returns the current class instance.
@param {Object} [*value*]
@chainable
*/
}, {
key: "totalConfig",
value: function totalConfig(_) {
return arguments.length ? (this._totalConfig = assign(this._totalConfig, _), this) : this._totalConfig;
}
/**
@memberof Viz
@desc Formatter function for the value in the total bar.
@param {Function} *value*
@chainable
*/
}, {
key: "totalFormat",
value: function totalFormat(_) {
return arguments.length ? (this._totalFormat = _, this) : this._totalFormat;
}
/**
@memberof Viz
@desc Tells the total whether or not to use the internal padding defined by the visualization in it's positioning. For example, d3plus-plot will add padding on the left so that the total appears centered above the x-axis. By default, this padding is only applied on screens larger than 600 pixels wide.
@param {Boolean|Function} [*value*]
@chainable
*/
}, {
key: "totalPadding",
value: function totalPadding(_) {
return arguments.length ? (this._totalPadding = typeof _ === "function" ? _ : constant$1(_), this) : this._totalPadding;
}
/**
@memberof Viz
@desc If *value* is specified, sets the overallwidth to the specified number and returns the current class instance.
@param {Number} [*value* = window.innerWidth]
@chainable
*/
}, {
key: "width",
value: function width(_) {
return arguments.length ? (this._width = _, this) : this._width;
}
/**
@memberof Viz
@desc Toggles the ability to zoom/pan the visualization. Certain parameters for zooming are required to be hooked up on a visualization by visualization basis.
@param {Boolean} *value* = false
@chainable
*/
}, {
key: "zoom",
value: function zoom(_) {
return arguments.length ? (this._zoom = _, this) : this._zoom;
}
/**
@memberof Viz
@desc The pixel stroke-width of the zoom brush area.
@param {Number} *value* = 1
@chainable
*/
}, {
key: "zoomBrushHandleSize",
value: function zoomBrushHandleSize(_) {
return arguments.length ? (this._zoomBrushHandleSize = _, this) : this._zoomBrushHandleSize;
}
/**
@memberof Viz
@desc An object containing CSS key/value pairs that is used to style the outer handle area of the zoom brush. Passing `false` will remove all default styling.
@param {Object|Boolean} *value*
@chainable
*/
}, {
key: "zoomBrushHandleStyle",
value: function zoomBrushHandleStyle(_) {
return arguments.length ? (this._zoomBrushHandleStyle = _, this) : this._zoomBrushHandleStyle;
}
/**
@memberof Viz
@desc An object containing CSS key/value pairs that is used to style the inner selection area of the zoom brush. Passing `false` will remove all default styling.
@param {Object|Boolean} *value*
@chainable
*/
}, {
key: "zoomBrushSelectionStyle",
value: function zoomBrushSelectionStyle(_) {
return arguments.length ? (this._zoomBrushSelectionStyle = _, this) : this._zoomBrushSelectionStyle;
}
/**
@memberof Viz
@desc An object containing CSS key/value pairs that is used to style each zoom control button (`.zoom-in`, `.zoom-out`, `.zoom-reset`, and `.zoom-brush`). Passing `false` will remove all default styling.
@param {Object|Boolean} *value*
@chainable
*/
}, {
key: "zoomControlStyle",
value: function zoomControlStyle(_) {
return arguments.length ? (this._zoomControlStyle = _, this) : this._zoomControlStyle;
}
/**
@memberof Viz
@desc An object containing CSS key/value pairs that is used to style each zoom control button when active (`.zoom-in`, `.zoom-out`, `.zoom-reset`, and `.zoom-brush`). Passing `false` will remove all default styling.
@param {Object|Boolean} *value*
@chainable
*/
}, {
key: "zoomControlStyleActive",
value: function zoomControlStyleActive(_) {
return arguments.length ? (this._zoomControlStyleActive = _, this) : this._zoomControlStyleActive;
}
/**
@memberof Viz
@desc An object containing CSS key/value pairs that is used to style each zoom control button on hover (`.zoom-in`, `.zoom-out`, `.zoom-reset`, and `.zoom-brush`). Passing `false` will remove all default styling.
@param {Object|Boolean} *value*
@chainable
*/
}, {
key: "zoomControlStyleHover",
value: function zoomControlStyleHover(_) {
return arguments.length ? (this._zoomControlStyleHover = _, this) : this._zoomControlStyleHover;
}
/**
@memberof Viz
@desc The multiplier that is used in with the control buttons when zooming in and out.
@param {Number} *value* = 2
@chainable
*/
}, {
key: "zoomFactor",
value: function zoomFactor(_) {
return arguments.length ? (this._zoomFactor = _, this) : this._zoomFactor;
}
/**
@memberof Viz
@desc If *value* is specified, sets the max zoom scale to the specified number and returns the current class instance. If *value* is not specified, returns the current max zoom scale.
@param {Number} *value* = 16
@chainable
*/
}, {
key: "zoomMax",
value: function zoomMax(_) {
return arguments.length ? (this._zoomMax = _, this) : this._zoomMax;
}
/**
@memberof Viz
@desc If *value* is specified, toggles panning to the specified boolean and returns the current class instance. If *value* is not specified, returns the current panning value.
@param {Boolean} *value* = true
@chainable
*/
}, {
key: "zoomPan",
value: function zoomPan(_) {
return arguments.length ? (this._zoomPan = _, this) : this._zoomPan;
}
/**
@memberof Viz
@desc A pixel value to be used to pad all sides of a zoomed area.
@param {Number} *value* = 20
@chainable
*/
}, {
key: "zoomPadding",
value: function zoomPadding(_) {
return arguments.length ? (this._zoomPadding = _, this) : this._zoomPadding;
}
/**
@memberof Viz
@desc If *value* is specified, toggles scroll zooming to the specified boolean and returns the current class instance. If *value* is not specified, returns the current scroll zooming value.
@param {Boolean} [*value* = true]
@chainable
*/
}, {
key: "zoomScroll",
value: function zoomScroll(_) {
return arguments.length ? (this._zoomScroll = _, this) : this._zoomScroll;
}
}]);
return Viz;
}(BaseClass);
/**
@class Pie
@extends Viz
@desc Uses the [d3 pie layout](https://github.com/d3/d3-shape#pies) to creates SVG arcs based on an array of data.
*/
var Pie = /*#__PURE__*/function (_Viz) {
_inherits(Pie, _Viz);
var _super = _createSuper(Pie);
/**
@memberof Pie
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function Pie() {
var _this;
_classCallCheck(this, Pie);
_this = _super.call(this);
_this._shapeConfig = assign(_this._shapeConfig, {
ariaLabel: function ariaLabel(d, i) {
return _this._pieData ? "".concat(++_this._pieData[i].index, ". ").concat(_this._drawLabel(d, i), ", ").concat(_this._value(d, i), ".") : "";
},
Path: {
labelConfig: {
fontResize: true
}
}
});
_this._innerRadius = 0;
_this._legendSort = function (a, b) {
return _this._value(b) - _this._value(a);
};
_this._padPixel = 0;
_this._pie = pie();
_this._sort = function (a, b) {
return _this._value(b) - _this._value(a);
};
_this._value = accessor("value");
return _this;
}
/**
Extends the draw behavior of the abstract Viz class.
@private
*/
_createClass(Pie, [{
key: "_draw",
value: function _draw(callback) {
var _this2 = this;
_get(_getPrototypeOf(Pie.prototype), "_draw", this).call(this, callback);
var height = this._height - this._margin.top - this._margin.bottom,
width = this._width - this._margin.left - this._margin.right;
var outerRadius = min([width, height]) / 2;
var pieData = this._pieData = this._pie.padAngle(this._padAngle || this._padPixel / outerRadius).sort(this._sort).value(this._value)(this._filteredData);
pieData.forEach(function (d, i) {
d.__d3plus__ = true;
d.i = i;
});
var arcData = arc().innerRadius(this._innerRadius).outerRadius(outerRadius);
var transform = "translate(".concat(width / 2 + this._margin.left, ", ").concat(height / 2 + this._margin.top, ")");
this._shapes.push(new Path$1().data(pieData).d(arcData).select(elem("g.d3plus-Pie", {
parent: this._select,
enter: {
transform: transform
},
update: {
transform: transform
}
}).node()).config({
id: function id(d) {
return _this2._ids(d).join("-");
},
x: 0,
y: 0
}).label(this._drawLabel).config(configPrep.bind(this)(this._shapeConfig, "shape", "Path")).render());
return this;
}
/**
@memberof Pie
@desc If *value* is specified, sets the inner radius accessor to the specified function or number and returns the current class instance. If *value* is not specified, returns the current inner radius accessor.
@param {Function|Number} [*value*]
*/
}, {
key: "innerRadius",
value: function innerRadius(_) {
return arguments.length ? (this._innerRadius = _, this) : this._innerRadius;
}
/**
@memberof Pie
@desc If *value* is specified, sets the arc padding to the specified radian value and returns the current class instance. If *value* is not specified, returns the current radian padding.
@param {Number} [*value*]
*/
}, {
key: "padAngle",
value: function padAngle(_) {
return arguments.length ? (this._padAngle = _, this) : this._padAngle;
}
/**
@memberof Pie
@desc If *value* is specified, sets the arc padding to the specified pixel value and returns the current class instance. If *value* is not specified, returns the current pixel padding.
@param {Number} [*value*]
*/
}, {
key: "padPixel",
value: function padPixel(_) {
return arguments.length ? (this._padPixel = _, this) : this._padPixel;
}
/**
@memberof Pie
@desc If *comparator* is specified, sets the sort order for the pie slices using the specified comparator function. If *comparator* is not specified, returns the current sort order, which defaults to descending order by the associated input data's numeric value attribute.
@param {Array} [*comparator*]
@example
function comparator(a, b) {
return b.value - a.value;
}
*/
}, {
key: "sort",
value: function sort(_) {
return arguments.length ? (this._sort = _, this) : this._sort;
}
/**
@memberof Pie
@desc If *value* is specified, sets the value accessor to the specified function or number and returns the current class instance. If *value* is not specified, returns the current value accessor.
@param {Function|String} *value*
@example
function value(d) {
return d.value;
}
*/
}, {
key: "value",
value: function value(_) {
return arguments.length ? (this._value = typeof _ === "function" ? _ : accessor(_), this) : this._value;
}
}]);
return Pie;
}(Viz);
/**
@class Donut
@extends Pie
@desc Extends the Pie visualization to create a donut chart.
*/
var Donut = /*#__PURE__*/function (_Pie) {
_inherits(Donut, _Pie);
var _super = _createSuper(Donut);
/**
@memberof Donut
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function Donut() {
var _this;
_classCallCheck(this, Donut);
_this = _super.call(this);
_this._innerRadius = function () {
return min([_this._width - _this._margin.left - _this._margin.right, _this._height - _this._margin.top - _this._margin.bottom]) / 4;
};
_this._padPixel = 2;
return _this;
}
return Donut;
}(Pie);
function count(node) {
var sum = 0,
children = node.children,
i = children && children.length;
if (!i) sum = 1;else while (--i >= 0) {
sum += children[i].value;
}
node.value = sum;
}
function node_count () {
return this.eachAfter(count);
}
function node_each (callback) {
var node = this,
current,
next = [node],
children,
i,
n;
do {
current = next.reverse(), next = [];
while (node = current.pop()) {
callback(node), children = node.children;
if (children) for (i = 0, n = children.length; i < n; ++i) {
next.push(children[i]);
}
}
} while (next.length);
return this;
}
function node_eachBefore (callback) {
var node = this,
nodes = [node],
children,
i;
while (node = nodes.pop()) {
callback(node), children = node.children;
if (children) for (i = children.length - 1; i >= 0; --i) {
nodes.push(children[i]);
}
}
return this;
}
function node_eachAfter (callback) {
var node = this,
nodes = [node],
next = [],
children,
i,
n;
while (node = nodes.pop()) {
next.push(node), children = node.children;
if (children) for (i = 0, n = children.length; i < n; ++i) {
nodes.push(children[i]);
}
}
while (node = next.pop()) {
callback(node);
}
return this;
}
function node_sum (value) {
return this.eachAfter(function (node) {
var sum = +value(node.data) || 0,
children = node.children,
i = children && children.length;
while (--i >= 0) {
sum += children[i].value;
}
node.value = sum;
});
}
function node_sort (compare) {
return this.eachBefore(function (node) {
if (node.children) {
node.children.sort(compare);
}
});
}
function node_path (end) {
var start = this,
ancestor = leastCommonAncestor(start, end),
nodes = [start];
while (start !== ancestor) {
start = start.parent;
nodes.push(start);
}
var k = nodes.length;
while (end !== ancestor) {
nodes.splice(k, 0, end);
end = end.parent;
}
return nodes;
}
function leastCommonAncestor(a, b) {
if (a === b) return a;
var aNodes = a.ancestors(),
bNodes = b.ancestors(),
c = null;
a = aNodes.pop();
b = bNodes.pop();
while (a === b) {
c = a;
a = aNodes.pop();
b = bNodes.pop();
}
return c;
}
function node_ancestors () {
var node = this,
nodes = [node];
while (node = node.parent) {
nodes.push(node);
}
return nodes;
}
function node_descendants () {
var nodes = [];
this.each(function (node) {
nodes.push(node);
});
return nodes;
}
function node_leaves () {
var leaves = [];
this.eachBefore(function (node) {
if (!node.children) {
leaves.push(node);
}
});
return leaves;
}
function node_links () {
var root = this,
links = [];
root.each(function (node) {
if (node !== root) {
// Dont include the roots parent, if any.
links.push({
source: node.parent,
target: node
});
}
});
return links;
}
function hierarchy(data, children) {
var root = new Node$2(data),
valued = +data.value && (root.value = data.value),
node,
nodes = [root],
child,
childs,
i,
n;
if (children == null) children = defaultChildren;
while (node = nodes.pop()) {
if (valued) node.value = +node.data.value;
if ((childs = children(node.data)) && (n = childs.length)) {
node.children = new Array(n);
for (i = n - 1; i >= 0; --i) {
nodes.push(child = node.children[i] = new Node$2(childs[i]));
child.parent = node;
child.depth = node.depth + 1;
}
}
}
return root.eachBefore(computeHeight);
}
function node_copy() {
return hierarchy(this).eachBefore(copyData);
}
function defaultChildren(d) {
return d.children;
}
function copyData(node) {
node.data = node.data.data;
}
function computeHeight(node) {
var height = 0;
do {
node.height = height;
} while ((node = node.parent) && node.height < ++height);
}
function Node$2(data) {
this.data = data;
this.depth = this.height = 0;
this.parent = null;
}
Node$2.prototype = hierarchy.prototype = {
constructor: Node$2,
count: node_count,
each: node_each,
eachAfter: node_eachAfter,
eachBefore: node_eachBefore,
sum: node_sum,
sort: node_sort,
path: node_path,
ancestors: node_ancestors,
descendants: node_descendants,
leaves: node_leaves,
links: node_links,
copy: node_copy
};
var slice$3 = Array.prototype.slice;
function shuffle(array) {
var m = array.length,
t,
i;
while (m) {
i = Math.random() * m-- | 0;
t = array[m];
array[m] = array[i];
array[i] = t;
}
return array;
}
function enclose (circles) {
var i = 0,
n = (circles = shuffle(slice$3.call(circles))).length,
B = [],
p,
e;
while (i < n) {
p = circles[i];
if (e && enclosesWeak(e, p)) ++i;else e = encloseBasis(B = extendBasis(B, p)), i = 0;
}
return e;
}
function extendBasis(B, p) {
var i, j;
if (enclosesWeakAll(p, B)) return [p]; // If we get here then B must have at least one element.
for (i = 0; i < B.length; ++i) {
if (enclosesNot(p, B[i]) && enclosesWeakAll(encloseBasis2(B[i], p), B)) {
return [B[i], p];
}
} // If we get here then B must have at least two elements.
for (i = 0; i < B.length - 1; ++i) {
for (j = i + 1; j < B.length; ++j) {
if (enclosesNot(encloseBasis2(B[i], B[j]), p) && enclosesNot(encloseBasis2(B[i], p), B[j]) && enclosesNot(encloseBasis2(B[j], p), B[i]) && enclosesWeakAll(encloseBasis3(B[i], B[j], p), B)) {
return [B[i], B[j], p];
}
}
} // If we get here then something is very wrong.
throw new Error();
}
function enclosesNot(a, b) {
var dr = a.r - b.r,
dx = b.x - a.x,
dy = b.y - a.y;
return dr < 0 || dr * dr < dx * dx + dy * dy;
}
function enclosesWeak(a, b) {
var dr = a.r - b.r + 1e-6,
dx = b.x - a.x,
dy = b.y - a.y;
return dr > 0 && dr * dr > dx * dx + dy * dy;
}
function enclosesWeakAll(a, B) {
for (var i = 0; i < B.length; ++i) {
if (!enclosesWeak(a, B[i])) {
return false;
}
}
return true;
}
function encloseBasis(B) {
switch (B.length) {
case 1:
return encloseBasis1(B[0]);
case 2:
return encloseBasis2(B[0], B[1]);
case 3:
return encloseBasis3(B[0], B[1], B[2]);
}
}
function encloseBasis1(a) {
return {
x: a.x,
y: a.y,
r: a.r
};
}
function encloseBasis2(a, b) {
var x1 = a.x,
y1 = a.y,
r1 = a.r,
x2 = b.x,
y2 = b.y,
r2 = b.r,
x21 = x2 - x1,
y21 = y2 - y1,
r21 = r2 - r1,
l = Math.sqrt(x21 * x21 + y21 * y21);
return {
x: (x1 + x2 + x21 / l * r21) / 2,
y: (y1 + y2 + y21 / l * r21) / 2,
r: (l + r1 + r2) / 2
};
}
function encloseBasis3(a, b, c) {
var x1 = a.x,
y1 = a.y,
r1 = a.r,
x2 = b.x,
y2 = b.y,
r2 = b.r,
x3 = c.x,
y3 = c.y,
r3 = c.r,
a2 = x1 - x2,
a3 = x1 - x3,
b2 = y1 - y2,
b3 = y1 - y3,
c2 = r2 - r1,
c3 = r3 - r1,
d1 = x1 * x1 + y1 * y1 - r1 * r1,
d2 = d1 - x2 * x2 - y2 * y2 + r2 * r2,
d3 = d1 - x3 * x3 - y3 * y3 + r3 * r3,
ab = a3 * b2 - a2 * b3,
xa = (b2 * d3 - b3 * d2) / (ab * 2) - x1,
xb = (b3 * c2 - b2 * c3) / ab,
ya = (a3 * d2 - a2 * d3) / (ab * 2) - y1,
yb = (a2 * c3 - a3 * c2) / ab,
A = xb * xb + yb * yb - 1,
B = 2 * (r1 + xa * xb + ya * yb),
C = xa * xa + ya * ya - r1 * r1,
r = -(A ? (B + Math.sqrt(B * B - 4 * A * C)) / (2 * A) : C / B);
return {
x: x1 + xa + xb * r,
y: y1 + ya + yb * r,
r: r
};
}
function place(b, a, c) {
var dx = b.x - a.x,
x,
a2,
dy = b.y - a.y,
y,
b2,
d2 = dx * dx + dy * dy;
if (d2) {
a2 = a.r + c.r, a2 *= a2;
b2 = b.r + c.r, b2 *= b2;
if (a2 > b2) {
x = (d2 + b2 - a2) / (2 * d2);
y = Math.sqrt(Math.max(0, b2 / d2 - x * x));
c.x = b.x - x * dx - y * dy;
c.y = b.y - x * dy + y * dx;
} else {
x = (d2 + a2 - b2) / (2 * d2);
y = Math.sqrt(Math.max(0, a2 / d2 - x * x));
c.x = a.x + x * dx - y * dy;
c.y = a.y + x * dy + y * dx;
}
} else {
c.x = a.x + c.r;
c.y = a.y;
}
}
function intersects(a, b) {
var dr = a.r + b.r - 1e-6,
dx = b.x - a.x,
dy = b.y - a.y;
return dr > 0 && dr * dr > dx * dx + dy * dy;
}
function score(node) {
var a = node._,
b = node.next._,
ab = a.r + b.r,
dx = (a.x * b.r + b.x * a.r) / ab,
dy = (a.y * b.r + b.y * a.r) / ab;
return dx * dx + dy * dy;
}
function Node$3(circle) {
this._ = circle;
this.next = null;
this.previous = null;
}
function packEnclose(circles) {
if (!(n = circles.length)) return 0;
var a, b, c, n, aa, ca, i, j, k, sj, sk; // Place the first circle.
a = circles[0], a.x = 0, a.y = 0;
if (!(n > 1)) return a.r; // Place the second circle.
b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0;
if (!(n > 2)) return a.r + b.r; // Place the third circle.
place(b, a, c = circles[2]); // Initialize the front-chain using the first three circles a, b and c.
a = new Node$3(a), b = new Node$3(b), c = new Node$3(c);
a.next = c.previous = b;
b.next = a.previous = c;
c.next = b.previous = a; // Attempt to place each remaining circle…
pack: for (i = 3; i < n; ++i) {
place(a._, b._, c = circles[i]), c = new Node$3(c); // Find the closest intersecting circle on the front-chain, if any.
// “Closeness” is determined by linear distance along the front-chain.
// “Ahead” or “behind” is likewise determined by linear distance.
j = b.next, k = a.previous, sj = b._.r, sk = a._.r;
do {
if (sj <= sk) {
if (intersects(j._, c._)) {
b = j, a.next = b, b.previous = a, --i;
continue pack;
}
sj += j._.r, j = j.next;
} else {
if (intersects(k._, c._)) {
a = k, a.next = b, b.previous = a, --i;
continue pack;
}
sk += k._.r, k = k.previous;
}
} while (j !== k.next); // Success! Insert the new circle c between a and b.
c.previous = a, c.next = b, a.next = b.previous = b = c; // Compute the new closest circle pair to the centroid.
aa = score(a);
while ((c = c.next) !== b) {
if ((ca = score(c)) < aa) {
a = c, aa = ca;
}
}
b = a.next;
} // Compute the enclosing circle of the front chain.
a = [b._], c = b;
while ((c = c.next) !== b) {
a.push(c._);
}
c = enclose(a); // Translate the circles to put the enclosing circle around the origin.
for (i = 0; i < n; ++i) {
a = circles[i], a.x -= c.x, a.y -= c.y;
}
return c.r;
}
function optional(f) {
return f == null ? null : required(f);
}
function required(f) {
if (typeof f !== "function") throw new Error();
return f;
}
function constantZero() {
return 0;
}
function constant$7 (x) {
return function () {
return x;
};
}
function defaultRadius(d) {
return Math.sqrt(d.value);
}
function pack () {
var radius = null,
dx = 1,
dy = 1,
padding = constantZero;
function pack(root) {
root.x = dx / 2, root.y = dy / 2;
if (radius) {
root.eachBefore(radiusLeaf(radius)).eachAfter(packChildren(padding, 0.5)).eachBefore(translateChild(1));
} else {
root.eachBefore(radiusLeaf(defaultRadius)).eachAfter(packChildren(constantZero, 1)).eachAfter(packChildren(padding, root.r / Math.min(dx, dy))).eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r)));
}
return root;
}
pack.radius = function (x) {
return arguments.length ? (radius = optional(x), pack) : radius;
};
pack.size = function (x) {
return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy];
};
pack.padding = function (x) {
return arguments.length ? (padding = typeof x === "function" ? x : constant$7(+x), pack) : padding;
};
return pack;
}
function radiusLeaf(radius) {
return function (node) {
if (!node.children) {
node.r = Math.max(0, +radius(node) || 0);
}
};
}
function packChildren(padding, k) {
return function (node) {
if (children = node.children) {
var children,
i,
n = children.length,
r = padding(node) * k || 0,
e;
if (r) for (i = 0; i < n; ++i) {
children[i].r += r;
}
e = packEnclose(children);
if (r) for (i = 0; i < n; ++i) {
children[i].r -= r;
}
node.r = e + r;
}
};
}
function translateChild(k) {
return function (node) {
var parent = node.parent;
node.r *= k;
if (parent) {
node.x = parent.x + k * node.x;
node.y = parent.y + k * node.y;
}
};
}
function roundNode (node) {
node.x0 = Math.round(node.x0);
node.y0 = Math.round(node.y0);
node.x1 = Math.round(node.x1);
node.y1 = Math.round(node.y1);
}
function treemapDice (parent, x0, y0, x1, y1) {
var nodes = parent.children,
node,
i = -1,
n = nodes.length,
k = parent.value && (x1 - x0) / parent.value;
while (++i < n) {
node = nodes[i], node.y0 = y0, node.y1 = y1;
node.x0 = x0, node.x1 = x0 += node.value * k;
}
}
function defaultSeparation(a, b) {
return a.parent === b.parent ? 1 : 2;
} // function radialSeparation(a, b) {
// return (a.parent === b.parent ? 1 : 2) / a.depth;
// }
// This function is used to traverse the left contour of a subtree (or
// subforest). It returns the successor of v on this contour. This successor is
// either given by the leftmost child of v or by the thread of v. The function
// returns null if and only if v is on the highest level of its subtree.
function nextLeft(v) {
var children = v.children;
return children ? children[0] : v.t;
} // This function works analogously to nextLeft.
function nextRight(v) {
var children = v.children;
return children ? children[children.length - 1] : v.t;
} // Shifts the current subtree rooted at w+. This is done by increasing
// prelim(w+) and mod(w+) by shift.
function moveSubtree(wm, wp, shift) {
var change = shift / (wp.i - wm.i);
wp.c -= change;
wp.s += shift;
wm.c += change;
wp.z += shift;
wp.m += shift;
} // All other shifts, applied to the smaller subtrees between w- and w+, are
// performed by this function. To prepare the shifts, we have to adjust
// change(w+), shift(w+), and change(w-).
function executeShifts(v) {
var shift = 0,
change = 0,
children = v.children,
i = children.length,
w;
while (--i >= 0) {
w = children[i];
w.z += shift;
w.m += shift;
shift += w.s + (change += w.c);
}
} // If vi-s ancestor is a sibling of v, returns vi-s ancestor. Otherwise,
// returns the specified (default) ancestor.
function nextAncestor(vim, v, ancestor) {
return vim.a.parent === v.parent ? vim.a : ancestor;
}
function TreeNode(node, i) {
this._ = node;
this.parent = null;
this.children = null;
this.A = null; // default ancestor
this.a = this; // ancestor
this.z = 0; // prelim
this.m = 0; // mod
this.c = 0; // change
this.s = 0; // shift
this.t = null; // thread
this.i = i; // number
}
TreeNode.prototype = Object.create(Node$2.prototype);
function treeRoot(root) {
var tree = new TreeNode(root, 0),
node,
nodes = [tree],
child,
children,
i,
n;
while (node = nodes.pop()) {
if (children = node._.children) {
node.children = new Array(n = children.length);
for (i = n - 1; i >= 0; --i) {
nodes.push(child = node.children[i] = new TreeNode(children[i], i));
child.parent = node;
}
}
}
(tree.parent = new TreeNode(null, 0)).children = [tree];
return tree;
} // Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
function tree () {
var separation = defaultSeparation,
dx = 1,
dy = 1,
nodeSize = null;
function tree(root) {
var t = treeRoot(root); // Compute the layout using Buchheim et al.s algorithm.
t.eachAfter(firstWalk), t.parent.m = -t.z;
t.eachBefore(secondWalk); // If a fixed node size is specified, scale x and y.
if (nodeSize) root.eachBefore(sizeNode); // If a fixed tree size is specified, scale x and y based on the extent.
// Compute the left-most, right-most, and depth-most nodes for extents.
else {
var left = root,
right = root,
bottom = root;
root.eachBefore(function (node) {
if (node.x < left.x) left = node;
if (node.x > right.x) right = node;
if (node.depth > bottom.depth) bottom = node;
});
var s = left === right ? 1 : separation(left, right) / 2,
tx = s - left.x,
kx = dx / (right.x + s + tx),
ky = dy / (bottom.depth || 1);
root.eachBefore(function (node) {
node.x = (node.x + tx) * kx;
node.y = node.depth * ky;
});
}
return root;
} // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is
// applied recursively to the children of v, as well as the function
// APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the
// node v is placed to the midpoint of its outermost children.
function firstWalk(v) {
var children = v.children,
siblings = v.parent.children,
w = v.i ? siblings[v.i - 1] : null;
if (children) {
executeShifts(v);
var midpoint = (children[0].z + children[children.length - 1].z) / 2;
if (w) {
v.z = w.z + separation(v._, w._);
v.m = v.z - midpoint;
} else {
v.z = midpoint;
}
} else if (w) {
v.z = w.z + separation(v._, w._);
}
v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
} // Computes all real x-coordinates by summing up the modifiers recursively.
function secondWalk(v) {
v._.x = v.z + v.parent.m;
v.m += v.parent.m;
} // The core of the algorithm. Here, a new subtree is combined with the
// previous subtrees. Threads are used to traverse the inside and outside
// contours of the left and right subtree up to the highest common level. The
// vertices used for the traversals are vi+, vi-, vo-, and vo+, where the
// superscript o means outside and i means inside, the subscript - means left
// subtree and + means right subtree. For summing up the modifiers along the
// contour, we use respective variables si+, si-, so-, and so+. Whenever two
// nodes of the inside contours conflict, we compute the left one of the
// greatest uncommon ancestors using the function ANCESTOR and call MOVE
// SUBTREE to shift the subtree and prepare the shifts of smaller subtrees.
// Finally, we add a new thread (if necessary).
function apportion(v, w, ancestor) {
if (w) {
var vip = v,
vop = v,
vim = w,
vom = vip.parent.children[0],
sip = vip.m,
sop = vop.m,
sim = vim.m,
som = vom.m,
shift;
while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) {
vom = nextLeft(vom);
vop = nextRight(vop);
vop.a = v;
shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
if (shift > 0) {
moveSubtree(nextAncestor(vim, v, ancestor), v, shift);
sip += shift;
sop += shift;
}
sim += vim.m;
sip += vip.m;
som += vom.m;
sop += vop.m;
}
if (vim && !nextRight(vop)) {
vop.t = vim;
vop.m += sim - sop;
}
if (vip && !nextLeft(vom)) {
vom.t = vip;
vom.m += sip - som;
ancestor = v;
}
}
return ancestor;
}
function sizeNode(node) {
node.x *= dx;
node.y = node.depth * dy;
}
tree.separation = function (x) {
return arguments.length ? (separation = x, tree) : separation;
};
tree.size = function (x) {
return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : nodeSize ? null : [dx, dy];
};
tree.nodeSize = function (x) {
return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : nodeSize ? [dx, dy] : null;
};
return tree;
}
function treemapSlice (parent, x0, y0, x1, y1) {
var nodes = parent.children,
node,
i = -1,
n = nodes.length,
k = parent.value && (y1 - y0) / parent.value;
while (++i < n) {
node = nodes[i], node.x0 = x0, node.x1 = x1;
node.y0 = y0, node.y1 = y0 += node.value * k;
}
}
var phi = (1 + Math.sqrt(5)) / 2;
function squarifyRatio(ratio, parent, x0, y0, x1, y1) {
var rows = [],
nodes = parent.children,
row,
nodeValue,
i0 = 0,
i1 = 0,
n = nodes.length,
dx,
dy,
value = parent.value,
sumValue,
minValue,
maxValue,
newRatio,
minRatio,
alpha,
beta;
while (i0 < n) {
dx = x1 - x0, dy = y1 - y0; // Find the next non-empty node.
do {
sumValue = nodes[i1++].value;
} while (!sumValue && i1 < n);
minValue = maxValue = sumValue;
alpha = Math.max(dy / dx, dx / dy) / (value * ratio);
beta = sumValue * sumValue * alpha;
minRatio = Math.max(maxValue / beta, beta / minValue); // Keep adding nodes while the aspect ratio maintains or improves.
for (; i1 < n; ++i1) {
sumValue += nodeValue = nodes[i1].value;
if (nodeValue < minValue) minValue = nodeValue;
if (nodeValue > maxValue) maxValue = nodeValue;
beta = sumValue * sumValue * alpha;
newRatio = Math.max(maxValue / beta, beta / minValue);
if (newRatio > minRatio) {
sumValue -= nodeValue;
break;
}
minRatio = newRatio;
} // Position and record the row orientation.
rows.push(row = {
value: sumValue,
dice: dx < dy,
children: nodes.slice(i0, i1)
});
if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1);else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1);
value -= sumValue, i0 = i1;
}
return rows;
}
var treemapSquarify = (function custom(ratio) {
function squarify(parent, x0, y0, x1, y1) {
squarifyRatio(ratio, parent, x0, y0, x1, y1);
}
squarify.ratio = function (x) {
return custom((x = +x) > 1 ? x : 1);
};
return squarify;
})(phi);
function treemap () {
var tile = treemapSquarify,
round = false,
dx = 1,
dy = 1,
paddingStack = [0],
paddingInner = constantZero,
paddingTop = constantZero,
paddingRight = constantZero,
paddingBottom = constantZero,
paddingLeft = constantZero;
function treemap(root) {
root.x0 = root.y0 = 0;
root.x1 = dx;
root.y1 = dy;
root.eachBefore(positionNode);
paddingStack = [0];
if (round) root.eachBefore(roundNode);
return root;
}
function positionNode(node) {
var p = paddingStack[node.depth],
x0 = node.x0 + p,
y0 = node.y0 + p,
x1 = node.x1 - p,
y1 = node.y1 - p;
if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
node.x0 = x0;
node.y0 = y0;
node.x1 = x1;
node.y1 = y1;
if (node.children) {
p = paddingStack[node.depth + 1] = paddingInner(node) / 2;
x0 += paddingLeft(node) - p;
y0 += paddingTop(node) - p;
x1 -= paddingRight(node) - p;
y1 -= paddingBottom(node) - p;
if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
tile(node, x0, y0, x1, y1);
}
}
treemap.round = function (x) {
return arguments.length ? (round = !!x, treemap) : round;
};
treemap.size = function (x) {
return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy];
};
treemap.tile = function (x) {
return arguments.length ? (tile = required(x), treemap) : tile;
};
treemap.padding = function (x) {
return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner();
};
treemap.paddingInner = function (x) {
return arguments.length ? (paddingInner = typeof x === "function" ? x : constant$7(+x), treemap) : paddingInner;
};
treemap.paddingOuter = function (x) {
return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop();
};
treemap.paddingTop = function (x) {
return arguments.length ? (paddingTop = typeof x === "function" ? x : constant$7(+x), treemap) : paddingTop;
};
treemap.paddingRight = function (x) {
return arguments.length ? (paddingRight = typeof x === "function" ? x : constant$7(+x), treemap) : paddingRight;
};
treemap.paddingBottom = function (x) {
return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant$7(+x), treemap) : paddingBottom;
};
treemap.paddingLeft = function (x) {
return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant$7(+x), treemap) : paddingLeft;
};
return treemap;
}
var recursionCircles = function recursionCircles(d) {
var arr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
if (d.values) {
d.values.forEach(function (h) {
arr.push(h);
recursionCircles(h, arr);
});
} else {
arr.push(d);
}
return arr;
};
/**
@class Pack
@extends Viz
@desc Uses the [d3 pack layout](https://github.com/d3/d3-hierarchy#pack) to creates Circle Packing chart based on an array of data.
*/
var Pack = /*#__PURE__*/function (_Viz) {
_inherits(Pack, _Viz);
var _super = _createSuper(Pack);
/**
@memberof Pack
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function Pack() {
var _this;
_classCallCheck(this, Pack);
_this = _super.call(this);
_this._layoutPadding = 1;
_this._on.mouseenter = function () {};
var defaultMouseMoveLegend = _this._on["mousemove.legend"];
_this._on["mousemove.legend"] = function (d, i) {
defaultMouseMoveLegend(d, i);
var ids = _this._ids(d, i);
var hoverData = recursionCircles(d);
_this.hover(function (h) {
var hover = Object.keys(h).filter(function (key) {
return key !== "value";
}).every(function (key) {
return d[key] && d[key].includes(h[key]);
});
if (hover) hoverData.push(h);else if (ids.includes(h.key)) hoverData.push.apply(hoverData, _toConsumableArray(recursionCircles(h, [h])));
return hoverData.includes(h);
});
};
var defaultMouseMoveShape = _this._on["mousemove.shape"];
_this._on["mousemove.shape"] = function (d, i) {
if (d.__d3plusTooltip__) defaultMouseMoveShape(d, i);
_this.hover(function (h) {
return recursionCircles(d, [d]).includes(h);
});
};
_this._pack = pack();
_this._packOpacity = constant$1(0.25);
_this._shape = constant$1("Circle");
_this._shapeConfig = assign(_this._shapeConfig, {
Circle: {
label: function label(d) {
return d.parent && !d.children ? d.id : false;
},
labelConfig: {
fontResize: true
},
opacity: function opacity(d) {
return d.__d3plusOpacity__;
}
}
});
_this._sort = function (a, b) {
return b.value - a.value;
};
_this._sum = accessor("value");
return _this;
}
/**
Extends the draw behavior of the abstract Viz class.
@private
*/
_createClass(Pack, [{
key: "_draw",
value: function _draw(callback) {
var _this2 = this;
_get(_getPrototypeOf(Pack.prototype), "_draw", this).call(this, callback);
var height = this._height - this._margin.top - this._margin.bottom,
width = this._width - this._margin.left - this._margin.right;
var diameter = Math.min(height, width);
var transform = "translate(".concat((width - diameter) / 2, ", ").concat((height - diameter) / 2, ")");
var nestedData = nest();
for (var i = 0; i <= this._drawDepth; i++) {
nestedData.key(this._groupBy[i]);
}
nestedData = nestedData.entries(this._filteredData);
var packData = this._pack.padding(this._layoutPadding).size([diameter, diameter])(hierarchy({
key: nestedData.key,
values: nestedData
}, function (d) {
return d.values;
}).sum(this._sum).sort(this._sort)).descendants();
packData.forEach(function (d, i) {
d.__d3plus__ = true;
d.i = i;
d.id = d.parent ? d.parent.data.key : null;
d.data.__d3plusOpacity__ = d.height ? _this2._packOpacity(d.data, i) : 1;
d.data.__d3plusTooltip__ = !d.height ? true : false;
});
this._shapes.push(new Circle().data(packData).select(elem("g.d3plus-Pack", {
parent: this._select,
enter: {
transform: transform
},
update: {
transform: transform
}
}).node()).config(configPrep.bind(this)(this._shapeConfig, "shape", "Circle")).render());
return this;
}
/**
@memberof Pack
@desc If *value* is specified, sets the hover method to the specified function and returns the current class instance.
@param {Function} [*value*]
@chainable
*/
}, {
key: "hover",
value: function hover(_) {
this._hover = _;
this._shapes.forEach(function (s) {
return s.hover(_);
});
if (this._legend) this._legendClass.hover(_);
return this;
}
/**
@memberof Pack
@desc If *value* is specified, sets the opacity accessor to the specified function or number and returns the current class instance. If *value* is not specified, returns the current pack opacity accessor.
@param {Function|Number} [*value*]
*/
}, {
key: "layoutPadding",
value: function layoutPadding(_) {
return arguments.length ? (this._layoutPadding = _, this) : this._layoutPadding;
}
/**
@memberof Pack
@desc If *value* is specified, sets the padding accessor to the specified function or number and returns the current class instance. If *value* is not specified, returns the current pack opacity accessor.
@param {Function|Number} [*value*]
*/
}, {
key: "packOpacity",
value: function packOpacity(_) {
return arguments.length ? (this._packOpacity = typeof _ === "function" ? _ : constant$1(_), this) : this._packOpacity;
}
/**
@memberof Pack
@desc If *comparator* is specified, sets the sort order for the pack using the specified comparator function. If *comparator* is not specified, returns the current group sort order, which defaults to descending order by the associated input data's numeric value attribute.
@param {Array} [*comparator*]
@example
function comparator(a, b) {
return b.value - a.value;
}
*/
}, {
key: "sort",
value: function sort(_) {
return arguments.length ? (this._sort = _, this) : this._sort;
}
/**
@memberof Pack
@desc If *value* is specified, sets the sum accessor to the specified function or number and returns the current class instance. If *value* is not specified, returns the current sum accessor.
@param {Function|Number} [*value*]
@example
function sum(d) {
return d.sum;
}
*/
}, {
key: "sum",
value: function sum(_) {
return arguments.length ? (this._sum = typeof _ === "function" ? _ : accessor(_), this) : this._sum;
}
}]);
return Pack;
}(Viz);
/**
@function nest
@summary Extends the base behavior of d3.nest to allow for multiple depth levels.
@param {Array} *data* The data array to be nested.
@param {Array} *keys* An array of key accessors that signify each nest level.
*/
function nest$1 (data, keys) {
if (!(keys instanceof Array)) keys = [keys];
var dataNest = nest();
for (var i = 0; i < keys.length; i++) {
dataNest.key(keys[i]);
}
var nestedData = dataNest.entries(data);
return bubble(nestedData);
}
/**
Bubbles up values that do not nest to the furthest key.
@param {Array} *values* The "values" of a nest object.
@private
*/
function bubble(values) {
return values.map(function (d) {
if (d.key && d.values) {
if (d.values[0].key === "undefined") return d.values[0].values[0];else d.values = bubble(d.values);
}
return d;
});
}
/**
@class Tree
@extends Viz
@desc Uses d3's [tree layout](https://github.com/d3/d3-hierarchy#tree) to create a tidy tree chart based on an array of data.
*/
var Tree = /*#__PURE__*/function (_Viz) {
_inherits(Tree, _Viz);
var _super = _createSuper(Tree);
/**
@memberof Tree
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function Tree() {
var _this;
_classCallCheck(this, Tree);
_this = _super.call(this);
_this._orient = "vertical";
_this._separation = function (a, b) {
return a.parent === b.parent ? 1 : 2;
};
_this._shape = constant$1("Circle");
_this._shapeConfig = assign(_this._shapeConfig, {
ariaLabel: function ariaLabel(d, i) {
return _this._treeData ? "".concat(_this._treeData[i].depth, ". ").concat(_this._drawLabel(d, i), ".") : "";
},
labelConfig: {
fontColor: "#444"
},
Path: {
fill: "none",
stroke: "#ccc",
strokeWidth: 1
},
r: constant$1(5),
width: constant$1(10),
height: constant$1(10)
});
_this._tree = tree();
return _this;
}
/**
Extends the draw behavior of the abstract Viz class.
@private
*/
_createClass(Tree, [{
key: "_draw",
value: function _draw(callback) {
var _this2 = this;
_get(_getPrototypeOf(Tree.prototype), "_draw", this).call(this, callback);
var height = this._orient === "vertical" ? this._height - this._margin.top - this._margin.bottom : this._width - this._margin.left - this._margin.right,
left = this._orient === "vertical" ? "left" : "top",
that = this,
transform = "translate(".concat(this._margin.left, ", ").concat(this._margin.top, ")"),
width = this._orient === "horizontal" ? this._height - this._margin.top - this._margin.bottom : this._width - this._margin.left - this._margin.right;
var treeData = this._treeData = this._tree.separation(this._separation).size([width, height])(hierarchy({
key: "root",
values: nest$1(this._filteredData, this._groupBy.slice(0, this._drawDepth + 1))
}, function (d) {
return d.key && d.values ? d.values : null;
}).sort(this._sort)).descendants().filter(function (d) {
return d.depth <= _this2._groupBy.length && d.parent;
});
/**
Merges the values of a given nest branch.
@private
*/
function flattenBranchData(branch) {
return objectMerge(branch.values.map(function (l) {
return l.key && l.values ? flattenBranchData(l) : l;
}), that._aggs);
}
treeData.forEach(function (d, i) {
if (d.data.key && d.data.values) d.data = flattenBranchData(d.data);
d.__d3plus__ = true;
d.i = i;
});
var r = this._shapeConfig.r;
if (typeof r !== "function") r = constant$1(r);
var rBufferRoot = max(treeData, function (d) {
return d.depth === 1 ? r(d.data, d.i) : 0;
});
var rBufferEnd = max(treeData, function (d) {
return d.children ? 0 : r(d.data, d.i);
});
var yExtent = extent(treeData, function (d) {
return d.y;
});
this._labelHeight = min([this._orient === "vertical" ? 50 : 100, (yExtent[1] - rBufferRoot - rBufferEnd) / (this._groupBy.length + 1)]);
this._labelWidths = nest$1(treeData, function (d) {
return d.depth;
}).map(function (d) {
return d.values.reduce(function (num, v, i) {
var next = i < d.values.length - 1 ? d.values[i + 1].x : width + _this2._margin[left],
prev = i ? d.values[i - 1].x : _this2._margin[left];
return min([num, next - v.x, v.x - prev]);
}, width);
});
var yScale = linear$1().domain(yExtent).range([rBufferRoot + this._labelHeight, height - rBufferEnd - this._labelHeight]);
treeData.forEach(function (d) {
var val = yScale(d.y);
if (_this2._orient === "horizontal") {
d.y = d.x;
d.x = val;
} else d.y = val;
});
var elemObject = {
parent: this._select,
enter: {
transform: transform
},
update: {
transform: transform
}
};
this._shapes.push(new Path$1().data(treeData.filter(function (d) {
return d.depth > 1;
})).select(elem("g.d3plus-Tree-Links", elemObject).node()).config(configPrep.bind(this)(this._shapeConfig, "shape", "Path")).config({
d: function d(_d) {
var r = _this2._shapeConfig.r;
if (typeof r === "function") r = r(_d.data, _d.i);
var px = _d.parent.x - _d.x + (_this2._orient === "vertical" ? 0 : r),
py = _d.parent.y - _d.y + (_this2._orient === "vertical" ? r : 0),
x = _this2._orient === "vertical" ? 0 : -r,
y = _this2._orient === "vertical" ? -r : 0;
return _this2._orient === "vertical" ? "M".concat(x, ",").concat(y, "C").concat(x, ",").concat((y + py) / 2, " ").concat(px, ",").concat((y + py) / 2, " ").concat(px, ",").concat(py) : "M".concat(x, ",").concat(y, "C").concat((x + px) / 2, ",").concat(y, " ").concat((x + px) / 2, ",").concat(py, " ").concat(px, ",").concat(py);
},
id: function id(d, i) {
return _this2._ids(d, i).join("-");
}
}).render());
this._shapes.push(new Circle().data(treeData).select(elem("g.d3plus-Tree-Shapes", elemObject).node()).config(configPrep.bind(this)(this._shapeConfig, "shape", "Circle")).config({
id: function id(d, i) {
return _this2._ids(d, i).join("-");
},
label: function label(d, i) {
if (_this2._label) return _this2._label(d.data, i);
var ids = _this2._ids(d, i).slice(0, d.depth);
return ids[ids.length - 1];
},
labelConfig: {
textAnchor: function textAnchor(d) {
return _this2._orient === "vertical" ? "middle" : d.data.children && d.data.depth !== _this2._groupBy.length ? "end" : "start";
},
verticalAlign: function verticalAlign(d) {
return _this2._orient === "vertical" ? d.data.depth === 1 ? "bottom" : "top" : "middle";
}
},
hitArea: function hitArea(d, i, s) {
var h = _this2._labelHeight,
w = _this2._labelWidths[d.depth - 1];
return {
width: _this2._orient === "vertical" ? w : s.r * 2 + w,
height: _this2._orient === "horizontal" ? h : s.r * 2 + h,
x: _this2._orient === "vertical" ? -w / 2 : d.children && d.depth !== _this2._groupBy.length ? -(s.r + w) : -s.r,
y: _this2._orient === "horizontal" ? -h / 2 : d.children && d.depth !== _this2._groupBy.length ? -(s.r + _this2._labelHeight) : -s.r
};
},
labelBounds: function labelBounds(d, i, s) {
var _ref;
var h = _this2._labelHeight,
height = _this2._orient === "vertical" ? "height" : "width",
w = _this2._labelWidths[d.depth - 1],
width = _this2._orient === "vertical" ? "width" : "height",
x = _this2._orient === "vertical" ? "x" : "y",
y = _this2._orient === "vertical" ? "y" : "x";
return _ref = {}, _defineProperty(_ref, width, w), _defineProperty(_ref, height, h), _defineProperty(_ref, x, -w / 2), _defineProperty(_ref, y, d.children && d.depth !== _this2._groupBy.length ? -(s.r + h) : s.r), _ref;
}
}).render());
return this;
}
/**
@memberof Tree
@desc If *value* is specified, sets the orientation to the specified value. If *value* is not specified, returns the current orientation.
@param {String} [*value* = "vertical"] Accepts either "vertical" or "horizontal".
*/
}, {
key: "orient",
value: function orient(_) {
return arguments.length ? (this._orient = _, this) : this._orient;
}
/**
@memberof Tree
@desc If *value* is specified, sets the separation accessor to the specified function. If *value* is not specified, returns the current separation accessor.
From the [d3-hierarchy documentation](https://github.com/d3/d3-hierarchy#tree_separation):
> The separation accessor is used to separate neighboring nodes. The separation function is passed two nodes a and b, and must return the desired separation. The nodes are typically siblings, though the nodes may be more distantly related if the layout decides to place such nodes adjacent.
@param {Function} [*value*]
@example
function separation(a, b) {
return a.parent === b.parent ? 1 : 2;
}
*/
}, {
key: "separation",
value: function separation(_) {
return arguments.length ? (this._separation = _, this) : this._separation;
}
}]);
return Tree;
}(Viz);
/**
@class Treemap
@extends Viz
@desc Uses the [d3 treemap layout](https://github.com/mbostock/d3/wiki/Treemap-Layout) to creates SVG rectangles based on an array of data. See [this example](https://d3plus.org/examples/d3plus-hierarchy/getting-started/) for help getting started using the treemap generator.
*/
var Treemap = /*#__PURE__*/function (_Viz) {
_inherits(Treemap, _Viz);
var _super = _createSuper(Treemap);
/**
@memberof Treemap
@desc Invoked when creating a new class instance, and sets any default parameters.
@private
*/
function Treemap() {
var _this;
_classCallCheck(this, Treemap);
_this = _super.call(this);
_this._layoutPadding = 1;
_this._legendSort = function (a, b) {
return _this._sum(b) - _this._sum(a);
};
_this._legendTooltip = assign({}, _this._legendTooltip, {
tbody: []
});
_this._shapeConfig = assign({}, _this._shapeConfig, {
ariaLabel: function ariaLabel(d, i) {
var rank = _this._rankData ? "".concat(_this._rankData.indexOf(d) + 1, ". ") : "";
return "".concat(rank).concat(_this._drawLabel(d, i), ", ").concat(_this._sum(d, i), ".");
},
labelConfig: {
fontMax: 20,
fontMin: 8,
fontResize: true,
padding: 5
}
});
_this._sort = function (a, b) {
var aggA = isAggregated(a);
var aggB = isAggregated(b);
return aggA && !aggB ? 1 : !aggA && aggB ? -1 : b.value - a.value;
};
_this._sum = accessor("value");
_this._thresholdKey = _this._sum;
_this._tile = treemapSquarify;
_this._tooltipConfig = assign({}, _this._tooltipConfig, {
tbody: [[function () {
return _this._translate("Share");
}, function (d, i, x) {
return "".concat(formatAbbreviate(x.share * 100, _this._locale), "%");
}]]
});
_this._treemap = treemap().round(true);
var isAggregated = function isAggregated(leaf) {
return leaf.children && leaf.children.length === 1 && leaf.children[0].data._isAggregation;
};
return _this;
}
/**
@memberof Treemap
@desc Extends the draw behavior of the abstract Viz class.
@private
*/
_createClass(Treemap, [{
key: "_draw",
value: function _draw(callback) {
var _this2 = this;
_get(_getPrototypeOf(Treemap.prototype), "_draw", this).call(this, callback);
var nestedData = nest();
for (var i = 0; i <= this._drawDepth; i++) {
nestedData.key(this._groupBy[i]);
}
nestedData = nestedData.entries(this._filteredData);
var tmapData = this._treemap.padding(this._layoutPadding).size([this._width - this._margin.left - this._margin.right, this._height - this._margin.top - this._margin.bottom]).tile(this._tile)(hierarchy({
values: nestedData
}, function (d) {
return d.values;
}).sum(this._sum).sort(this._sort));
var shapeData = [],
that = this;
/**
@memberof Treemap
@desc Flattens and merges treemap data.
@private
*/
function extractLayout(children) {
for (var _i = 0; _i < children.length; _i++) {
var node = children[_i];
if (node.depth <= that._drawDepth) extractLayout(node.children);else {
var index = node.data.values.length === 1 ? that._filteredData.indexOf(node.data.values[0]) : undefined;
node.__d3plus__ = true;
node.id = node.data.key;
node.i = index > -1 ? index : undefined;
node.data = objectMerge(node.data.values, that._aggs);
node.x = node.x0 + (node.x1 - node.x0) / 2;
node.y = node.y0 + (node.y1 - node.y0) / 2;
shapeData.push(node);
}
}
}
if (tmapData.children) extractLayout(tmapData.children);
this._rankData = shapeData.sort(this._sort).map(function (d) {
return d.data;
});
var total = tmapData.value;
shapeData.forEach(function (d) {
d.share = _this2._sum(d.data, d.i) / total;
});
var transform = "translate(".concat(this._margin.left, ", ").concat(this._margin.top, ")");
var rectConfig = configPrep.bind(this)(this._shapeConfig, "shape", "Rect");
var fontMin = rectConfig.labelConfig.fontMin;
var padding = rectConfig.labelConfig.padding;
this._shapes.push(new Rect().data(shapeData).label(function (d) {
return [_this2._drawLabel(d.data, d.i), "".concat(formatAbbreviate(d.share * 100, _this2._locale), "%")];
}).select(elem("g.d3plus-Treemap", {
parent: this._select,
enter: {
transform: transform
},
update: {
transform: transform
}
}).node()).config({
height: function height(d) {
return d.y1 - d.y0;
},
labelBounds: function labelBounds(d, i, s) {
var h = s.height;
var sh = Math.min(50, (h - padding * 2) * 0.5);
if (sh < fontMin) sh = 0;
return [{
width: s.width,
height: h - sh,
x: -s.width / 2,
y: -h / 2
}, {
width: s.width,
height: sh + padding * 2,
x: -s.width / 2,
y: h / 2 - sh - padding * 2
}];
},
labelConfig: {
textAnchor: function textAnchor(d, i, x) {
var line,
parent = x;
while (typeof line === "undefined" && parent) {
if (typeof parent.l !== "undefined") line = parent.l;
parent = parent.__d3plusParent__;
}
return line ? "middle" : "start";
},
verticalAlign: function verticalAlign(d, i, x) {
var line,
parent = x;
while (typeof line === "undefined" && parent) {
if (typeof parent.l !== "undefined") line = parent.l;
parent = parent.__d3plusParent__;
}
return line ? "bottom" : "top";
}
},
width: function width(d) {
return d.x1 - d.x0;
}
}).config(rectConfig).render());
return this;
}
/**
* Applies the threshold algorithm for Treemaps.
* @param {Array} data The data to process.
*/
}, {
key: "_thresholdFunction",
value: function _thresholdFunction(data) {
var aggs = this._aggs;
var drawDepth = this._drawDepth;
var groupBy = this._groupBy;
var threshold = this._threshold;
var thresholdKey = this._thresholdKey;
var totalSum = sum(data, thresholdKey);
if (threshold && thresholdKey) {
return thresholdByDepth(data, 0);
}
/**
* @memberof Treemap
* @desc Explores the data tree recursively and merges elements under the indicated threshold.
* @param {object[]} branchData The current subset of the dataset to work on.
* @param {number} depth The depth of the current branch.
* @private
*/
function thresholdByDepth(branchData, depth) {
if (depth < drawDepth) {
return nest().key(groupBy[depth]).entries(branchData).reduce(function (bulk, leaf) {
var subBranchData = thresholdByDepth(leaf.values, depth + 1);
return bulk.concat(subBranchData);
}, []);
}
if (depth === drawDepth) {
var thresholdPercent = Math.min(1, Math.max(0, threshold(branchData)));
if (!isFinite(thresholdPercent) || isNaN(thresholdPercent)) return null;
var removedItems = [];
var branchDataCopy = branchData.slice();
var thresholdValue = thresholdPercent * totalSum;
var n = branchDataCopy.length;
while (n--) {
var datum = branchDataCopy[n];
if (thresholdKey(datum) < thresholdValue) {
var index = branchDataCopy.indexOf(datum);
branchDataCopy.splice(index, 1);
removedItems.push(datum);
}
}
if (removedItems.length > 0) {
var mergedItem = objectMerge(removedItems, aggs);
mergedItem._isAggregation = true;
mergedItem._threshold = thresholdPercent;
branchDataCopy.push(mergedItem);
}
return branchDataCopy;
}
throw new Error("Depth is higher than the amount of grouping levels.");
}
return data;
}
/**
@memberof Treemap
@desc If *value* is specified, sets the inner and outer padding accessor to the specified function or number and returns the current class instance. If *value* is not specified, returns the current padding accessor.
@param {Function|Number} [*value*]
*/
}, {
key: "layoutPadding",
value: function layoutPadding(_) {
return arguments.length ? (this._layoutPadding = typeof _ === "function" ? _ : constant$1(_), this) : this._layoutPadding;
}
/**
@memberof Treemap
@desc If *comparator* is specified, sets the sort order for the treemap using the specified comparator function. If *comparator* is not specified, returns the current group sort order, which defaults to descending order by the associated input data's numeric value attribute.
@param {Array} [*comparator*]
@example
function comparator(a, b) {
return b.value - a.value;
}
*/
}, {
key: "sort",
value: function sort(_) {
return arguments.length ? (this._sort = _, this) : this._sort;
}
/**
@memberof Treemap
@desc If *value* is specified, sets the sum accessor to the specified function or number and returns the current class instance. If *value* is not specified, returns the current sum accessor.
@param {Function|Number} [*value*]
@example
function sum(d) {
return d.sum;
}
*/
}, {
key: "sum",
value: function sum(_) {
if (arguments.length) {
this._sum = typeof _ === "function" ? _ : accessor(_);
this._thresholdKey = this._sum;
return this;
} else return this._sum;
}
/**
@memberof Treemap
@desc If *value* is specified, sets the [tiling method](https://github.com/d3/d3-hierarchy#treemap-tiling) to the specified function and returns the current class instance. If *value* is not specified, returns the current [tiling method](https://github.com/d3/d3-hierarchy#treemap-tiling).
@param {Function} [*value*]
*/
}, {
key: "tile",
value: function tile(_) {
return arguments.length ? (this._tile = _, this) : this._tile;
}
}]);
return Treemap;
}(Viz);
exports.Donut = Donut;
exports.Pack = Pack;
exports.Pie = Pie;
exports.Tree = Tree;
exports.Treemap = Treemap;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=d3plus-hierarchy.full.js.map