mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-07 14:24:13 +01:00
40176 lines
1.3 MiB
40176 lines
1.3 MiB
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.mermaidAPI=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||
|
||
},{}],2:[function(require,module,exports){
|
||
(function (process){
|
||
// Copyright Joyent, Inc. and other Node 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.
|
||
|
||
// resolves . and .. elements in a path array with directory names there
|
||
// must be no slashes, empty elements, or device names (c:\) in the array
|
||
// (so also no leading and trailing slashes - it does not distinguish
|
||
// relative and absolute paths)
|
||
function normalizeArray(parts, allowAboveRoot) {
|
||
// if the path tries to go above the root, `up` ends up > 0
|
||
var up = 0;
|
||
for (var i = parts.length - 1; i >= 0; i--) {
|
||
var last = parts[i];
|
||
if (last === '.') {
|
||
parts.splice(i, 1);
|
||
} else if (last === '..') {
|
||
parts.splice(i, 1);
|
||
up++;
|
||
} else if (up) {
|
||
parts.splice(i, 1);
|
||
up--;
|
||
}
|
||
}
|
||
|
||
// if the path is allowed to go above the root, restore leading ..s
|
||
if (allowAboveRoot) {
|
||
for (; up--; up) {
|
||
parts.unshift('..');
|
||
}
|
||
}
|
||
|
||
return parts;
|
||
}
|
||
|
||
// Split a filename into [root, dir, basename, ext], unix version
|
||
// 'root' is just a slash, or nothing.
|
||
var splitPathRe =
|
||
/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
|
||
var splitPath = function(filename) {
|
||
return splitPathRe.exec(filename).slice(1);
|
||
};
|
||
|
||
// path.resolve([from ...], to)
|
||
// posix version
|
||
exports.resolve = function() {
|
||
var resolvedPath = '',
|
||
resolvedAbsolute = false;
|
||
|
||
for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
|
||
var path = (i >= 0) ? arguments[i] : process.cwd();
|
||
|
||
// Skip empty and invalid entries
|
||
if (typeof path !== 'string') {
|
||
throw new TypeError('Arguments to path.resolve must be strings');
|
||
} else if (!path) {
|
||
continue;
|
||
}
|
||
|
||
resolvedPath = path + '/' + resolvedPath;
|
||
resolvedAbsolute = path.charAt(0) === '/';
|
||
}
|
||
|
||
// At this point the path should be resolved to a full absolute path, but
|
||
// handle relative paths to be safe (might happen when process.cwd() fails)
|
||
|
||
// Normalize the path
|
||
resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
|
||
return !!p;
|
||
}), !resolvedAbsolute).join('/');
|
||
|
||
return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
|
||
};
|
||
|
||
// path.normalize(path)
|
||
// posix version
|
||
exports.normalize = function(path) {
|
||
var isAbsolute = exports.isAbsolute(path),
|
||
trailingSlash = substr(path, -1) === '/';
|
||
|
||
// Normalize the path
|
||
path = normalizeArray(filter(path.split('/'), function(p) {
|
||
return !!p;
|
||
}), !isAbsolute).join('/');
|
||
|
||
if (!path && !isAbsolute) {
|
||
path = '.';
|
||
}
|
||
if (path && trailingSlash) {
|
||
path += '/';
|
||
}
|
||
|
||
return (isAbsolute ? '/' : '') + path;
|
||
};
|
||
|
||
// posix version
|
||
exports.isAbsolute = function(path) {
|
||
return path.charAt(0) === '/';
|
||
};
|
||
|
||
// posix version
|
||
exports.join = function() {
|
||
var paths = Array.prototype.slice.call(arguments, 0);
|
||
return exports.normalize(filter(paths, function(p, index) {
|
||
if (typeof p !== 'string') {
|
||
throw new TypeError('Arguments to path.join must be strings');
|
||
}
|
||
return p;
|
||
}).join('/'));
|
||
};
|
||
|
||
|
||
// path.relative(from, to)
|
||
// posix version
|
||
exports.relative = function(from, to) {
|
||
from = exports.resolve(from).substr(1);
|
||
to = exports.resolve(to).substr(1);
|
||
|
||
function trim(arr) {
|
||
var start = 0;
|
||
for (; start < arr.length; start++) {
|
||
if (arr[start] !== '') break;
|
||
}
|
||
|
||
var end = arr.length - 1;
|
||
for (; end >= 0; end--) {
|
||
if (arr[end] !== '') break;
|
||
}
|
||
|
||
if (start > end) return [];
|
||
return arr.slice(start, end - start + 1);
|
||
}
|
||
|
||
var fromParts = trim(from.split('/'));
|
||
var toParts = trim(to.split('/'));
|
||
|
||
var length = Math.min(fromParts.length, toParts.length);
|
||
var samePartsLength = length;
|
||
for (var i = 0; i < length; i++) {
|
||
if (fromParts[i] !== toParts[i]) {
|
||
samePartsLength = i;
|
||
break;
|
||
}
|
||
}
|
||
|
||
var outputParts = [];
|
||
for (var i = samePartsLength; i < fromParts.length; i++) {
|
||
outputParts.push('..');
|
||
}
|
||
|
||
outputParts = outputParts.concat(toParts.slice(samePartsLength));
|
||
|
||
return outputParts.join('/');
|
||
};
|
||
|
||
exports.sep = '/';
|
||
exports.delimiter = ':';
|
||
|
||
exports.dirname = function(path) {
|
||
var result = splitPath(path),
|
||
root = result[0],
|
||
dir = result[1];
|
||
|
||
if (!root && !dir) {
|
||
// No dirname whatsoever
|
||
return '.';
|
||
}
|
||
|
||
if (dir) {
|
||
// It has a dirname, strip trailing slash
|
||
dir = dir.substr(0, dir.length - 1);
|
||
}
|
||
|
||
return root + dir;
|
||
};
|
||
|
||
|
||
exports.basename = function(path, ext) {
|
||
var f = splitPath(path)[2];
|
||
// TODO: make this comparison case-insensitive on windows?
|
||
if (ext && f.substr(-1 * ext.length) === ext) {
|
||
f = f.substr(0, f.length - ext.length);
|
||
}
|
||
return f;
|
||
};
|
||
|
||
|
||
exports.extname = function(path) {
|
||
return splitPath(path)[3];
|
||
};
|
||
|
||
function filter (xs, f) {
|
||
if (xs.filter) return xs.filter(f);
|
||
var res = [];
|
||
for (var i = 0; i < xs.length; i++) {
|
||
if (f(xs[i], i, xs)) res.push(xs[i]);
|
||
}
|
||
return res;
|
||
}
|
||
|
||
// String.prototype.substr - negative index don't work in IE8
|
||
var substr = 'ab'.substr(-1) === 'b'
|
||
? function (str, start, len) { return str.substr(start, len) }
|
||
: function (str, start, len) {
|
||
if (start < 0) start = str.length + start;
|
||
return str.substr(start, len);
|
||
}
|
||
;
|
||
|
||
}).call(this,require('_process'))
|
||
},{"_process":3}],3:[function(require,module,exports){
|
||
// shim for using process in browser
|
||
|
||
var process = module.exports = {};
|
||
|
||
process.nextTick = (function () {
|
||
var canSetImmediate = typeof window !== 'undefined'
|
||
&& window.setImmediate;
|
||
var canMutationObserver = typeof window !== 'undefined'
|
||
&& window.MutationObserver;
|
||
var canPost = typeof window !== 'undefined'
|
||
&& window.postMessage && window.addEventListener
|
||
;
|
||
|
||
if (canSetImmediate) {
|
||
return function (f) { return window.setImmediate(f) };
|
||
}
|
||
|
||
var queue = [];
|
||
|
||
if (canMutationObserver) {
|
||
var hiddenDiv = document.createElement("div");
|
||
var observer = new MutationObserver(function () {
|
||
var queueList = queue.slice();
|
||
queue.length = 0;
|
||
queueList.forEach(function (fn) {
|
||
fn();
|
||
});
|
||
});
|
||
|
||
observer.observe(hiddenDiv, { attributes: true });
|
||
|
||
return function nextTick(fn) {
|
||
if (!queue.length) {
|
||
hiddenDiv.setAttribute('yes', 'no');
|
||
}
|
||
queue.push(fn);
|
||
};
|
||
}
|
||
|
||
if (canPost) {
|
||
window.addEventListener('message', function (ev) {
|
||
var source = ev.source;
|
||
if ((source === window || source === null) && ev.data === 'process-tick') {
|
||
ev.stopPropagation();
|
||
if (queue.length > 0) {
|
||
var fn = queue.shift();
|
||
fn();
|
||
}
|
||
}
|
||
}, true);
|
||
|
||
return function nextTick(fn) {
|
||
queue.push(fn);
|
||
window.postMessage('process-tick', '*');
|
||
};
|
||
}
|
||
|
||
return function nextTick(fn) {
|
||
setTimeout(fn, 0);
|
||
};
|
||
})();
|
||
|
||
process.title = 'browser';
|
||
process.browser = true;
|
||
process.env = {};
|
||
process.argv = [];
|
||
|
||
function noop() {}
|
||
|
||
process.on = noop;
|
||
process.addListener = noop;
|
||
process.once = noop;
|
||
process.off = noop;
|
||
process.removeListener = noop;
|
||
process.removeAllListeners = noop;
|
||
process.emit = noop;
|
||
|
||
process.binding = function (name) {
|
||
throw new Error('process.binding is not supported');
|
||
};
|
||
|
||
// TODO(shtylman)
|
||
process.cwd = function () { return '/' };
|
||
process.chdir = function (dir) {
|
||
throw new Error('process.chdir is not supported');
|
||
};
|
||
|
||
},{}],4:[function(require,module,exports){
|
||
!function() {
|
||
var d3 = {
|
||
version: "3.5.6"
|
||
};
|
||
var d3_arraySlice = [].slice, d3_array = function(list) {
|
||
return d3_arraySlice.call(list);
|
||
};
|
||
var d3_document = this.document;
|
||
function d3_documentElement(node) {
|
||
return node && (node.ownerDocument || node.document || node).documentElement;
|
||
}
|
||
function d3_window(node) {
|
||
return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView);
|
||
}
|
||
if (d3_document) {
|
||
try {
|
||
d3_array(d3_document.documentElement.childNodes)[0].nodeType;
|
||
} catch (e) {
|
||
d3_array = function(list) {
|
||
var i = list.length, array = new Array(i);
|
||
while (i--) array[i] = list[i];
|
||
return array;
|
||
};
|
||
}
|
||
}
|
||
if (!Date.now) Date.now = function() {
|
||
return +new Date();
|
||
};
|
||
if (d3_document) {
|
||
try {
|
||
d3_document.createElement("DIV").style.setProperty("opacity", 0, "");
|
||
} catch (error) {
|
||
var d3_element_prototype = this.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = this.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty;
|
||
d3_element_prototype.setAttribute = function(name, value) {
|
||
d3_element_setAttribute.call(this, name, value + "");
|
||
};
|
||
d3_element_prototype.setAttributeNS = function(space, local, value) {
|
||
d3_element_setAttributeNS.call(this, space, local, value + "");
|
||
};
|
||
d3_style_prototype.setProperty = function(name, value, priority) {
|
||
d3_style_setProperty.call(this, name, value + "", priority);
|
||
};
|
||
}
|
||
}
|
||
d3.ascending = d3_ascending;
|
||
function d3_ascending(a, b) {
|
||
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
|
||
}
|
||
d3.descending = function(a, b) {
|
||
return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
|
||
};
|
||
d3.min = function(array, f) {
|
||
var i = -1, n = array.length, a, b;
|
||
if (arguments.length === 1) {
|
||
while (++i < n) if ((b = array[i]) != null && b >= b) {
|
||
a = b;
|
||
break;
|
||
}
|
||
while (++i < n) if ((b = array[i]) != null && a > b) a = b;
|
||
} else {
|
||
while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
|
||
a = b;
|
||
break;
|
||
}
|
||
while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
|
||
}
|
||
return a;
|
||
};
|
||
d3.max = function(array, f) {
|
||
var i = -1, n = array.length, a, b;
|
||
if (arguments.length === 1) {
|
||
while (++i < n) if ((b = array[i]) != null && b >= b) {
|
||
a = b;
|
||
break;
|
||
}
|
||
while (++i < n) if ((b = array[i]) != null && b > a) a = b;
|
||
} else {
|
||
while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
|
||
a = b;
|
||
break;
|
||
}
|
||
while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
|
||
}
|
||
return a;
|
||
};
|
||
d3.extent = function(array, f) {
|
||
var i = -1, n = array.length, a, b, c;
|
||
if (arguments.length === 1) {
|
||
while (++i < n) if ((b = array[i]) != null && b >= b) {
|
||
a = c = b;
|
||
break;
|
||
}
|
||
while (++i < n) if ((b = array[i]) != null) {
|
||
if (a > b) a = b;
|
||
if (c < b) c = b;
|
||
}
|
||
} else {
|
||
while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
|
||
a = c = b;
|
||
break;
|
||
}
|
||
while (++i < n) if ((b = f.call(array, array[i], i)) != null) {
|
||
if (a > b) a = b;
|
||
if (c < b) c = b;
|
||
}
|
||
}
|
||
return [ a, c ];
|
||
};
|
||
function d3_number(x) {
|
||
return x === null ? NaN : +x;
|
||
}
|
||
function d3_numeric(x) {
|
||
return !isNaN(x);
|
||
}
|
||
d3.sum = function(array, f) {
|
||
var s = 0, n = array.length, a, i = -1;
|
||
if (arguments.length === 1) {
|
||
while (++i < n) if (d3_numeric(a = +array[i])) s += a;
|
||
} else {
|
||
while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a;
|
||
}
|
||
return s;
|
||
};
|
||
d3.mean = function(array, f) {
|
||
var s = 0, n = array.length, a, i = -1, j = n;
|
||
if (arguments.length === 1) {
|
||
while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j;
|
||
} else {
|
||
while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j;
|
||
}
|
||
if (j) return s / j;
|
||
};
|
||
d3.quantile = function(values, p) {
|
||
var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h;
|
||
return e ? v + e * (values[h] - v) : v;
|
||
};
|
||
d3.median = function(array, f) {
|
||
var numbers = [], n = array.length, a, i = -1;
|
||
if (arguments.length === 1) {
|
||
while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a);
|
||
} else {
|
||
while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a);
|
||
}
|
||
if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5);
|
||
};
|
||
d3.variance = function(array, f) {
|
||
var n = array.length, m = 0, a, d, s = 0, i = -1, j = 0;
|
||
if (arguments.length === 1) {
|
||
while (++i < n) {
|
||
if (d3_numeric(a = d3_number(array[i]))) {
|
||
d = a - m;
|
||
m += d / ++j;
|
||
s += d * (a - m);
|
||
}
|
||
}
|
||
} else {
|
||
while (++i < n) {
|
||
if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) {
|
||
d = a - m;
|
||
m += d / ++j;
|
||
s += d * (a - m);
|
||
}
|
||
}
|
||
}
|
||
if (j > 1) return s / (j - 1);
|
||
};
|
||
d3.deviation = function() {
|
||
var v = d3.variance.apply(this, arguments);
|
||
return v ? Math.sqrt(v) : v;
|
||
};
|
||
function d3_bisector(compare) {
|
||
return {
|
||
left: function(a, x, lo, hi) {
|
||
if (arguments.length < 3) lo = 0;
|
||
if (arguments.length < 4) 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(a, x, lo, hi) {
|
||
if (arguments.length < 3) lo = 0;
|
||
if (arguments.length < 4) 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;
|
||
}
|
||
};
|
||
}
|
||
var d3_bisect = d3_bisector(d3_ascending);
|
||
d3.bisectLeft = d3_bisect.left;
|
||
d3.bisect = d3.bisectRight = d3_bisect.right;
|
||
d3.bisector = function(f) {
|
||
return d3_bisector(f.length === 1 ? function(d, x) {
|
||
return d3_ascending(f(d), x);
|
||
} : f);
|
||
};
|
||
d3.shuffle = function(array, i0, i1) {
|
||
if ((m = arguments.length) < 3) {
|
||
i1 = array.length;
|
||
if (m < 2) i0 = 0;
|
||
}
|
||
var m = i1 - i0, t, i;
|
||
while (m) {
|
||
i = Math.random() * m-- | 0;
|
||
t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t;
|
||
}
|
||
return array;
|
||
};
|
||
d3.permute = function(array, indexes) {
|
||
var i = indexes.length, permutes = new Array(i);
|
||
while (i--) permutes[i] = array[indexes[i]];
|
||
return permutes;
|
||
};
|
||
d3.pairs = function(array) {
|
||
var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n);
|
||
while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ];
|
||
return pairs;
|
||
};
|
||
d3.zip = function() {
|
||
if (!(n = arguments.length)) return [];
|
||
for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) {
|
||
for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) {
|
||
zip[j] = arguments[j][i];
|
||
}
|
||
}
|
||
return zips;
|
||
};
|
||
function d3_zipLength(d) {
|
||
return d.length;
|
||
}
|
||
d3.transpose = function(matrix) {
|
||
return d3.zip.apply(d3, matrix);
|
||
};
|
||
d3.keys = function(map) {
|
||
var keys = [];
|
||
for (var key in map) keys.push(key);
|
||
return keys;
|
||
};
|
||
d3.values = function(map) {
|
||
var values = [];
|
||
for (var key in map) values.push(map[key]);
|
||
return values;
|
||
};
|
||
d3.entries = function(map) {
|
||
var entries = [];
|
||
for (var key in map) entries.push({
|
||
key: key,
|
||
value: map[key]
|
||
});
|
||
return entries;
|
||
};
|
||
d3.merge = function(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;
|
||
};
|
||
var abs = Math.abs;
|
||
d3.range = function(start, stop, step) {
|
||
if (arguments.length < 3) {
|
||
step = 1;
|
||
if (arguments.length < 2) {
|
||
stop = start;
|
||
start = 0;
|
||
}
|
||
}
|
||
if ((stop - start) / step === Infinity) throw new Error("infinite range");
|
||
var range = [], k = d3_range_integerScale(abs(step)), i = -1, j;
|
||
start *= k, stop *= k, step *= k;
|
||
if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k);
|
||
return range;
|
||
};
|
||
function d3_range_integerScale(x) {
|
||
var k = 1;
|
||
while (x * k % 1) k *= 10;
|
||
return k;
|
||
}
|
||
function d3_class(ctor, properties) {
|
||
for (var key in properties) {
|
||
Object.defineProperty(ctor.prototype, key, {
|
||
value: properties[key],
|
||
enumerable: false
|
||
});
|
||
}
|
||
}
|
||
d3.map = function(object, f) {
|
||
var map = new d3_Map();
|
||
if (object instanceof d3_Map) {
|
||
object.forEach(function(key, value) {
|
||
map.set(key, value);
|
||
});
|
||
} else if (Array.isArray(object)) {
|
||
var i = -1, n = object.length, o;
|
||
if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o);
|
||
} else {
|
||
for (var key in object) map.set(key, object[key]);
|
||
}
|
||
return map;
|
||
};
|
||
function d3_Map() {
|
||
this._ = Object.create(null);
|
||
}
|
||
var d3_map_proto = "__proto__", d3_map_zero = "\x00";
|
||
d3_class(d3_Map, {
|
||
has: d3_map_has,
|
||
get: function(key) {
|
||
return this._[d3_map_escape(key)];
|
||
},
|
||
set: function(key, value) {
|
||
return this._[d3_map_escape(key)] = value;
|
||
},
|
||
remove: d3_map_remove,
|
||
keys: d3_map_keys,
|
||
values: function() {
|
||
var values = [];
|
||
for (var key in this._) values.push(this._[key]);
|
||
return values;
|
||
},
|
||
entries: function() {
|
||
var entries = [];
|
||
for (var key in this._) entries.push({
|
||
key: d3_map_unescape(key),
|
||
value: this._[key]
|
||
});
|
||
return entries;
|
||
},
|
||
size: d3_map_size,
|
||
empty: d3_map_empty,
|
||
forEach: function(f) {
|
||
for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]);
|
||
}
|
||
});
|
||
function d3_map_escape(key) {
|
||
return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key;
|
||
}
|
||
function d3_map_unescape(key) {
|
||
return (key += "")[0] === d3_map_zero ? key.slice(1) : key;
|
||
}
|
||
function d3_map_has(key) {
|
||
return d3_map_escape(key) in this._;
|
||
}
|
||
function d3_map_remove(key) {
|
||
return (key = d3_map_escape(key)) in this._ && delete this._[key];
|
||
}
|
||
function d3_map_keys() {
|
||
var keys = [];
|
||
for (var key in this._) keys.push(d3_map_unescape(key));
|
||
return keys;
|
||
}
|
||
function d3_map_size() {
|
||
var size = 0;
|
||
for (var key in this._) ++size;
|
||
return size;
|
||
}
|
||
function d3_map_empty() {
|
||
for (var key in this._) return false;
|
||
return true;
|
||
}
|
||
d3.nest = function() {
|
||
var nest = {}, keys = [], sortKeys = [], sortValues, rollup;
|
||
function map(mapType, array, depth) {
|
||
if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array;
|
||
var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values;
|
||
while (++i < n) {
|
||
if (values = valuesByKey.get(keyValue = key(object = array[i]))) {
|
||
values.push(object);
|
||
} else {
|
||
valuesByKey.set(keyValue, [ object ]);
|
||
}
|
||
}
|
||
if (mapType) {
|
||
object = mapType();
|
||
setter = function(keyValue, values) {
|
||
object.set(keyValue, map(mapType, values, depth));
|
||
};
|
||
} else {
|
||
object = {};
|
||
setter = function(keyValue, values) {
|
||
object[keyValue] = map(mapType, values, depth);
|
||
};
|
||
}
|
||
valuesByKey.forEach(setter);
|
||
return object;
|
||
}
|
||
function entries(map, depth) {
|
||
if (depth >= keys.length) return map;
|
||
var array = [], sortKey = sortKeys[depth++];
|
||
map.forEach(function(key, keyMap) {
|
||
array.push({
|
||
key: key,
|
||
values: entries(keyMap, depth)
|
||
});
|
||
});
|
||
return sortKey ? array.sort(function(a, b) {
|
||
return sortKey(a.key, b.key);
|
||
}) : array;
|
||
}
|
||
nest.map = function(array, mapType) {
|
||
return map(mapType, array, 0);
|
||
};
|
||
nest.entries = function(array) {
|
||
return entries(map(d3.map, array, 0), 0);
|
||
};
|
||
nest.key = function(d) {
|
||
keys.push(d);
|
||
return nest;
|
||
};
|
||
nest.sortKeys = function(order) {
|
||
sortKeys[keys.length - 1] = order;
|
||
return nest;
|
||
};
|
||
nest.sortValues = function(order) {
|
||
sortValues = order;
|
||
return nest;
|
||
};
|
||
nest.rollup = function(f) {
|
||
rollup = f;
|
||
return nest;
|
||
};
|
||
return nest;
|
||
};
|
||
d3.set = function(array) {
|
||
var set = new d3_Set();
|
||
if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]);
|
||
return set;
|
||
};
|
||
function d3_Set() {
|
||
this._ = Object.create(null);
|
||
}
|
||
d3_class(d3_Set, {
|
||
has: d3_map_has,
|
||
add: function(key) {
|
||
this._[d3_map_escape(key += "")] = true;
|
||
return key;
|
||
},
|
||
remove: d3_map_remove,
|
||
values: d3_map_keys,
|
||
size: d3_map_size,
|
||
empty: d3_map_empty,
|
||
forEach: function(f) {
|
||
for (var key in this._) f.call(this, d3_map_unescape(key));
|
||
}
|
||
});
|
||
d3.behavior = {};
|
||
function d3_identity(d) {
|
||
return d;
|
||
}
|
||
d3.rebind = function(target, source) {
|
||
var i = 1, n = arguments.length, method;
|
||
while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
|
||
return target;
|
||
};
|
||
function d3_rebind(target, source, method) {
|
||
return function() {
|
||
var value = method.apply(source, arguments);
|
||
return value === source ? target : value;
|
||
};
|
||
}
|
||
function d3_vendorSymbol(object, name) {
|
||
if (name in object) return name;
|
||
name = name.charAt(0).toUpperCase() + name.slice(1);
|
||
for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) {
|
||
var prefixName = d3_vendorPrefixes[i] + name;
|
||
if (prefixName in object) return prefixName;
|
||
}
|
||
}
|
||
var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ];
|
||
function d3_noop() {}
|
||
d3.dispatch = function() {
|
||
var dispatch = new d3_dispatch(), i = -1, n = arguments.length;
|
||
while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
|
||
return dispatch;
|
||
};
|
||
function d3_dispatch() {}
|
||
d3_dispatch.prototype.on = function(type, listener) {
|
||
var i = type.indexOf("."), name = "";
|
||
if (i >= 0) {
|
||
name = type.slice(i + 1);
|
||
type = type.slice(0, i);
|
||
}
|
||
if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);
|
||
if (arguments.length === 2) {
|
||
if (listener == null) for (type in this) {
|
||
if (this.hasOwnProperty(type)) this[type].on(name, null);
|
||
}
|
||
return this;
|
||
}
|
||
};
|
||
function d3_dispatch_event(dispatch) {
|
||
var listeners = [], listenerByName = new d3_Map();
|
||
function event() {
|
||
var z = listeners, i = -1, n = z.length, l;
|
||
while (++i < n) if (l = z[i].on) l.apply(this, arguments);
|
||
return dispatch;
|
||
}
|
||
event.on = function(name, listener) {
|
||
var l = listenerByName.get(name), i;
|
||
if (arguments.length < 2) return l && l.on;
|
||
if (l) {
|
||
l.on = null;
|
||
listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));
|
||
listenerByName.remove(name);
|
||
}
|
||
if (listener) listeners.push(listenerByName.set(name, {
|
||
on: listener
|
||
}));
|
||
return dispatch;
|
||
};
|
||
return event;
|
||
}
|
||
d3.event = null;
|
||
function d3_eventPreventDefault() {
|
||
d3.event.preventDefault();
|
||
}
|
||
function d3_eventSource() {
|
||
var e = d3.event, s;
|
||
while (s = e.sourceEvent) e = s;
|
||
return e;
|
||
}
|
||
function d3_eventDispatch(target) {
|
||
var dispatch = new d3_dispatch(), i = 0, n = arguments.length;
|
||
while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
|
||
dispatch.of = function(thiz, argumentz) {
|
||
return function(e1) {
|
||
try {
|
||
var e0 = e1.sourceEvent = d3.event;
|
||
e1.target = target;
|
||
d3.event = e1;
|
||
dispatch[e1.type].apply(thiz, argumentz);
|
||
} finally {
|
||
d3.event = e0;
|
||
}
|
||
};
|
||
};
|
||
return dispatch;
|
||
}
|
||
d3.requote = function(s) {
|
||
return s.replace(d3_requote_re, "\\$&");
|
||
};
|
||
var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
|
||
var d3_subclass = {}.__proto__ ? function(object, prototype) {
|
||
object.__proto__ = prototype;
|
||
} : function(object, prototype) {
|
||
for (var property in prototype) object[property] = prototype[property];
|
||
};
|
||
function d3_selection(groups) {
|
||
d3_subclass(groups, d3_selectionPrototype);
|
||
return groups;
|
||
}
|
||
var d3_select = function(s, n) {
|
||
return n.querySelector(s);
|
||
}, d3_selectAll = function(s, n) {
|
||
return n.querySelectorAll(s);
|
||
}, d3_selectMatches = function(n, s) {
|
||
var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")];
|
||
d3_selectMatches = function(n, s) {
|
||
return d3_selectMatcher.call(n, s);
|
||
};
|
||
return d3_selectMatches(n, s);
|
||
};
|
||
if (typeof Sizzle === "function") {
|
||
d3_select = function(s, n) {
|
||
return Sizzle(s, n)[0] || null;
|
||
};
|
||
d3_selectAll = Sizzle;
|
||
d3_selectMatches = Sizzle.matchesSelector;
|
||
}
|
||
d3.selection = function() {
|
||
return d3.select(d3_document.documentElement);
|
||
};
|
||
var d3_selectionPrototype = d3.selection.prototype = [];
|
||
d3_selectionPrototype.select = function(selector) {
|
||
var subgroups = [], subgroup, subnode, group, node;
|
||
selector = d3_selection_selector(selector);
|
||
for (var j = -1, m = this.length; ++j < m; ) {
|
||
subgroups.push(subgroup = []);
|
||
subgroup.parentNode = (group = this[j]).parentNode;
|
||
for (var i = -1, n = group.length; ++i < n; ) {
|
||
if (node = group[i]) {
|
||
subgroup.push(subnode = selector.call(node, node.__data__, i, j));
|
||
if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
|
||
} else {
|
||
subgroup.push(null);
|
||
}
|
||
}
|
||
}
|
||
return d3_selection(subgroups);
|
||
};
|
||
function d3_selection_selector(selector) {
|
||
return typeof selector === "function" ? selector : function() {
|
||
return d3_select(selector, this);
|
||
};
|
||
}
|
||
d3_selectionPrototype.selectAll = function(selector) {
|
||
var subgroups = [], subgroup, node;
|
||
selector = d3_selection_selectorAll(selector);
|
||
for (var j = -1, m = this.length; ++j < m; ) {
|
||
for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
|
||
if (node = group[i]) {
|
||
subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j)));
|
||
subgroup.parentNode = node;
|
||
}
|
||
}
|
||
}
|
||
return d3_selection(subgroups);
|
||
};
|
||
function d3_selection_selectorAll(selector) {
|
||
return typeof selector === "function" ? selector : function() {
|
||
return d3_selectAll(selector, this);
|
||
};
|
||
}
|
||
var d3_nsPrefix = {
|
||
svg: "http://www.w3.org/2000/svg",
|
||
xhtml: "http://www.w3.org/1999/xhtml",
|
||
xlink: "http://www.w3.org/1999/xlink",
|
||
xml: "http://www.w3.org/XML/1998/namespace",
|
||
xmlns: "http://www.w3.org/2000/xmlns/"
|
||
};
|
||
d3.ns = {
|
||
prefix: d3_nsPrefix,
|
||
qualify: function(name) {
|
||
var i = name.indexOf(":"), prefix = name;
|
||
if (i >= 0) {
|
||
prefix = name.slice(0, i);
|
||
name = name.slice(i + 1);
|
||
}
|
||
return d3_nsPrefix.hasOwnProperty(prefix) ? {
|
||
space: d3_nsPrefix[prefix],
|
||
local: name
|
||
} : name;
|
||
}
|
||
};
|
||
d3_selectionPrototype.attr = function(name, value) {
|
||
if (arguments.length < 2) {
|
||
if (typeof name === "string") {
|
||
var node = this.node();
|
||
name = d3.ns.qualify(name);
|
||
return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);
|
||
}
|
||
for (value in name) this.each(d3_selection_attr(value, name[value]));
|
||
return this;
|
||
}
|
||
return this.each(d3_selection_attr(name, value));
|
||
};
|
||
function d3_selection_attr(name, value) {
|
||
name = d3.ns.qualify(name);
|
||
function attrNull() {
|
||
this.removeAttribute(name);
|
||
}
|
||
function attrNullNS() {
|
||
this.removeAttributeNS(name.space, name.local);
|
||
}
|
||
function attrConstant() {
|
||
this.setAttribute(name, value);
|
||
}
|
||
function attrConstantNS() {
|
||
this.setAttributeNS(name.space, name.local, value);
|
||
}
|
||
function attrFunction() {
|
||
var x = value.apply(this, arguments);
|
||
if (x == null) this.removeAttribute(name); else this.setAttribute(name, x);
|
||
}
|
||
function attrFunctionNS() {
|
||
var x = value.apply(this, arguments);
|
||
if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);
|
||
}
|
||
return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;
|
||
}
|
||
function d3_collapse(s) {
|
||
return s.trim().replace(/\s+/g, " ");
|
||
}
|
||
d3_selectionPrototype.classed = function(name, value) {
|
||
if (arguments.length < 2) {
|
||
if (typeof name === "string") {
|
||
var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1;
|
||
if (value = node.classList) {
|
||
while (++i < n) if (!value.contains(name[i])) return false;
|
||
} else {
|
||
value = node.getAttribute("class");
|
||
while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
|
||
}
|
||
return true;
|
||
}
|
||
for (value in name) this.each(d3_selection_classed(value, name[value]));
|
||
return this;
|
||
}
|
||
return this.each(d3_selection_classed(name, value));
|
||
};
|
||
function d3_selection_classedRe(name) {
|
||
return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
|
||
}
|
||
function d3_selection_classes(name) {
|
||
return (name + "").trim().split(/^|\s+/);
|
||
}
|
||
function d3_selection_classed(name, value) {
|
||
name = d3_selection_classes(name).map(d3_selection_classedName);
|
||
var n = name.length;
|
||
function classedConstant() {
|
||
var i = -1;
|
||
while (++i < n) name[i](this, value);
|
||
}
|
||
function classedFunction() {
|
||
var i = -1, x = value.apply(this, arguments);
|
||
while (++i < n) name[i](this, x);
|
||
}
|
||
return typeof value === "function" ? classedFunction : classedConstant;
|
||
}
|
||
function d3_selection_classedName(name) {
|
||
var re = d3_selection_classedRe(name);
|
||
return function(node, value) {
|
||
if (c = node.classList) return value ? c.add(name) : c.remove(name);
|
||
var c = node.getAttribute("class") || "";
|
||
if (value) {
|
||
re.lastIndex = 0;
|
||
if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name));
|
||
} else {
|
||
node.setAttribute("class", d3_collapse(c.replace(re, " ")));
|
||
}
|
||
};
|
||
}
|
||
d3_selectionPrototype.style = function(name, value, priority) {
|
||
var n = arguments.length;
|
||
if (n < 3) {
|
||
if (typeof name !== "string") {
|
||
if (n < 2) value = "";
|
||
for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
|
||
return this;
|
||
}
|
||
if (n < 2) {
|
||
var node = this.node();
|
||
return d3_window(node).getComputedStyle(node, null).getPropertyValue(name);
|
||
}
|
||
priority = "";
|
||
}
|
||
return this.each(d3_selection_style(name, value, priority));
|
||
};
|
||
function d3_selection_style(name, value, priority) {
|
||
function styleNull() {
|
||
this.style.removeProperty(name);
|
||
}
|
||
function styleConstant() {
|
||
this.style.setProperty(name, value, priority);
|
||
}
|
||
function styleFunction() {
|
||
var x = value.apply(this, arguments);
|
||
if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);
|
||
}
|
||
return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant;
|
||
}
|
||
d3_selectionPrototype.property = function(name, value) {
|
||
if (arguments.length < 2) {
|
||
if (typeof name === "string") return this.node()[name];
|
||
for (value in name) this.each(d3_selection_property(value, name[value]));
|
||
return this;
|
||
}
|
||
return this.each(d3_selection_property(name, value));
|
||
};
|
||
function d3_selection_property(name, value) {
|
||
function propertyNull() {
|
||
delete this[name];
|
||
}
|
||
function propertyConstant() {
|
||
this[name] = value;
|
||
}
|
||
function propertyFunction() {
|
||
var x = value.apply(this, arguments);
|
||
if (x == null) delete this[name]; else this[name] = x;
|
||
}
|
||
return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant;
|
||
}
|
||
d3_selectionPrototype.text = function(value) {
|
||
return arguments.length ? this.each(typeof value === "function" ? function() {
|
||
var v = value.apply(this, arguments);
|
||
this.textContent = v == null ? "" : v;
|
||
} : value == null ? function() {
|
||
this.textContent = "";
|
||
} : function() {
|
||
this.textContent = value;
|
||
}) : this.node().textContent;
|
||
};
|
||
d3_selectionPrototype.html = function(value) {
|
||
return arguments.length ? this.each(typeof value === "function" ? function() {
|
||
var v = value.apply(this, arguments);
|
||
this.innerHTML = v == null ? "" : v;
|
||
} : value == null ? function() {
|
||
this.innerHTML = "";
|
||
} : function() {
|
||
this.innerHTML = value;
|
||
}) : this.node().innerHTML;
|
||
};
|
||
d3_selectionPrototype.append = function(name) {
|
||
name = d3_selection_creator(name);
|
||
return this.select(function() {
|
||
return this.appendChild(name.apply(this, arguments));
|
||
});
|
||
};
|
||
function d3_selection_creator(name) {
|
||
function create() {
|
||
var document = this.ownerDocument, namespace = this.namespaceURI;
|
||
return namespace ? document.createElementNS(namespace, name) : document.createElement(name);
|
||
}
|
||
function createNS() {
|
||
return this.ownerDocument.createElementNS(name.space, name.local);
|
||
}
|
||
return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? createNS : create;
|
||
}
|
||
d3_selectionPrototype.insert = function(name, before) {
|
||
name = d3_selection_creator(name);
|
||
before = d3_selection_selector(before);
|
||
return this.select(function() {
|
||
return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null);
|
||
});
|
||
};
|
||
d3_selectionPrototype.remove = function() {
|
||
return this.each(d3_selectionRemove);
|
||
};
|
||
function d3_selectionRemove() {
|
||
var parent = this.parentNode;
|
||
if (parent) parent.removeChild(this);
|
||
}
|
||
d3_selectionPrototype.data = function(value, key) {
|
||
var i = -1, n = this.length, group, node;
|
||
if (!arguments.length) {
|
||
value = new Array(n = (group = this[0]).length);
|
||
while (++i < n) {
|
||
if (node = group[i]) {
|
||
value[i] = node.__data__;
|
||
}
|
||
}
|
||
return value;
|
||
}
|
||
function bind(group, groupData) {
|
||
var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData;
|
||
if (key) {
|
||
var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue;
|
||
for (i = -1; ++i < n; ) {
|
||
if (nodeByKeyValue.has(keyValue = key.call(node = group[i], node.__data__, i))) {
|
||
exitNodes[i] = node;
|
||
} else {
|
||
nodeByKeyValue.set(keyValue, node);
|
||
}
|
||
keyValues[i] = keyValue;
|
||
}
|
||
for (i = -1; ++i < m; ) {
|
||
if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) {
|
||
enterNodes[i] = d3_selection_dataNode(nodeData);
|
||
} else if (node !== true) {
|
||
updateNodes[i] = node;
|
||
node.__data__ = nodeData;
|
||
}
|
||
nodeByKeyValue.set(keyValue, true);
|
||
}
|
||
for (i = -1; ++i < n; ) {
|
||
if (nodeByKeyValue.get(keyValues[i]) !== true) {
|
||
exitNodes[i] = group[i];
|
||
}
|
||
}
|
||
} else {
|
||
for (i = -1; ++i < n0; ) {
|
||
node = group[i];
|
||
nodeData = groupData[i];
|
||
if (node) {
|
||
node.__data__ = nodeData;
|
||
updateNodes[i] = node;
|
||
} else {
|
||
enterNodes[i] = d3_selection_dataNode(nodeData);
|
||
}
|
||
}
|
||
for (;i < m; ++i) {
|
||
enterNodes[i] = d3_selection_dataNode(groupData[i]);
|
||
}
|
||
for (;i < n; ++i) {
|
||
exitNodes[i] = group[i];
|
||
}
|
||
}
|
||
enterNodes.update = updateNodes;
|
||
enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode;
|
||
enter.push(enterNodes);
|
||
update.push(updateNodes);
|
||
exit.push(exitNodes);
|
||
}
|
||
var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]);
|
||
if (typeof value === "function") {
|
||
while (++i < n) {
|
||
bind(group = this[i], value.call(group, group.parentNode.__data__, i));
|
||
}
|
||
} else {
|
||
while (++i < n) {
|
||
bind(group = this[i], value);
|
||
}
|
||
}
|
||
update.enter = function() {
|
||
return enter;
|
||
};
|
||
update.exit = function() {
|
||
return exit;
|
||
};
|
||
return update;
|
||
};
|
||
function d3_selection_dataNode(data) {
|
||
return {
|
||
__data__: data
|
||
};
|
||
}
|
||
d3_selectionPrototype.datum = function(value) {
|
||
return arguments.length ? this.property("__data__", value) : this.property("__data__");
|
||
};
|
||
d3_selectionPrototype.filter = function(filter) {
|
||
var subgroups = [], subgroup, group, node;
|
||
if (typeof filter !== "function") filter = d3_selection_filter(filter);
|
||
for (var j = 0, m = this.length; j < m; j++) {
|
||
subgroups.push(subgroup = []);
|
||
subgroup.parentNode = (group = this[j]).parentNode;
|
||
for (var i = 0, n = group.length; i < n; i++) {
|
||
if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
|
||
subgroup.push(node);
|
||
}
|
||
}
|
||
}
|
||
return d3_selection(subgroups);
|
||
};
|
||
function d3_selection_filter(selector) {
|
||
return function() {
|
||
return d3_selectMatches(this, selector);
|
||
};
|
||
}
|
||
d3_selectionPrototype.order = function() {
|
||
for (var j = -1, m = this.length; ++j < m; ) {
|
||
for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) {
|
||
if (node = group[i]) {
|
||
if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
|
||
next = node;
|
||
}
|
||
}
|
||
}
|
||
return this;
|
||
};
|
||
d3_selectionPrototype.sort = function(comparator) {
|
||
comparator = d3_selection_sortComparator.apply(this, arguments);
|
||
for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator);
|
||
return this.order();
|
||
};
|
||
function d3_selection_sortComparator(comparator) {
|
||
if (!arguments.length) comparator = d3_ascending;
|
||
return function(a, b) {
|
||
return a && b ? comparator(a.__data__, b.__data__) : !a - !b;
|
||
};
|
||
}
|
||
d3_selectionPrototype.each = function(callback) {
|
||
return d3_selection_each(this, function(node, i, j) {
|
||
callback.call(node, node.__data__, i, j);
|
||
});
|
||
};
|
||
function d3_selection_each(groups, callback) {
|
||
for (var 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(node, i, j);
|
||
}
|
||
}
|
||
return groups;
|
||
}
|
||
d3_selectionPrototype.call = function(callback) {
|
||
var args = d3_array(arguments);
|
||
callback.apply(args[0] = this, args);
|
||
return this;
|
||
};
|
||
d3_selectionPrototype.empty = function() {
|
||
return !this.node();
|
||
};
|
||
d3_selectionPrototype.node = function() {
|
||
for (var j = 0, m = this.length; j < m; j++) {
|
||
for (var group = this[j], i = 0, n = group.length; i < n; i++) {
|
||
var node = group[i];
|
||
if (node) return node;
|
||
}
|
||
}
|
||
return null;
|
||
};
|
||
d3_selectionPrototype.size = function() {
|
||
var n = 0;
|
||
d3_selection_each(this, function() {
|
||
++n;
|
||
});
|
||
return n;
|
||
};
|
||
function d3_selection_enter(selection) {
|
||
d3_subclass(selection, d3_selection_enterPrototype);
|
||
return selection;
|
||
}
|
||
var d3_selection_enterPrototype = [];
|
||
d3.selection.enter = d3_selection_enter;
|
||
d3.selection.enter.prototype = d3_selection_enterPrototype;
|
||
d3_selection_enterPrototype.append = d3_selectionPrototype.append;
|
||
d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
|
||
d3_selection_enterPrototype.node = d3_selectionPrototype.node;
|
||
d3_selection_enterPrototype.call = d3_selectionPrototype.call;
|
||
d3_selection_enterPrototype.size = d3_selectionPrototype.size;
|
||
d3_selection_enterPrototype.select = function(selector) {
|
||
var subgroups = [], subgroup, subnode, upgroup, group, node;
|
||
for (var j = -1, m = this.length; ++j < m; ) {
|
||
upgroup = (group = this[j]).update;
|
||
subgroups.push(subgroup = []);
|
||
subgroup.parentNode = group.parentNode;
|
||
for (var i = -1, n = group.length; ++i < n; ) {
|
||
if (node = group[i]) {
|
||
subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j));
|
||
subnode.__data__ = node.__data__;
|
||
} else {
|
||
subgroup.push(null);
|
||
}
|
||
}
|
||
}
|
||
return d3_selection(subgroups);
|
||
};
|
||
d3_selection_enterPrototype.insert = function(name, before) {
|
||
if (arguments.length < 2) before = d3_selection_enterInsertBefore(this);
|
||
return d3_selectionPrototype.insert.call(this, name, before);
|
||
};
|
||
function d3_selection_enterInsertBefore(enter) {
|
||
var i0, j0;
|
||
return function(d, i, j) {
|
||
var group = enter[j].update, n = group.length, node;
|
||
if (j != j0) j0 = j, i0 = 0;
|
||
if (i >= i0) i0 = i + 1;
|
||
while (!(node = group[i0]) && ++i0 < n) ;
|
||
return node;
|
||
};
|
||
}
|
||
d3.select = function(node) {
|
||
var group;
|
||
if (typeof node === "string") {
|
||
group = [ d3_select(node, d3_document) ];
|
||
group.parentNode = d3_document.documentElement;
|
||
} else {
|
||
group = [ node ];
|
||
group.parentNode = d3_documentElement(node);
|
||
}
|
||
return d3_selection([ group ]);
|
||
};
|
||
d3.selectAll = function(nodes) {
|
||
var group;
|
||
if (typeof nodes === "string") {
|
||
group = d3_array(d3_selectAll(nodes, d3_document));
|
||
group.parentNode = d3_document.documentElement;
|
||
} else {
|
||
group = nodes;
|
||
group.parentNode = null;
|
||
}
|
||
return d3_selection([ group ]);
|
||
};
|
||
d3_selectionPrototype.on = function(type, listener, capture) {
|
||
var n = arguments.length;
|
||
if (n < 3) {
|
||
if (typeof type !== "string") {
|
||
if (n < 2) listener = false;
|
||
for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
|
||
return this;
|
||
}
|
||
if (n < 2) return (n = this.node()["__on" + type]) && n._;
|
||
capture = false;
|
||
}
|
||
return this.each(d3_selection_on(type, listener, capture));
|
||
};
|
||
function d3_selection_on(type, listener, capture) {
|
||
var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener;
|
||
if (i > 0) type = type.slice(0, i);
|
||
var filter = d3_selection_onFilters.get(type);
|
||
if (filter) type = filter, wrap = d3_selection_onFilter;
|
||
function onRemove() {
|
||
var l = this[name];
|
||
if (l) {
|
||
this.removeEventListener(type, l, l.$);
|
||
delete this[name];
|
||
}
|
||
}
|
||
function onAdd() {
|
||
var l = wrap(listener, d3_array(arguments));
|
||
onRemove.call(this);
|
||
this.addEventListener(type, this[name] = l, l.$ = capture);
|
||
l._ = listener;
|
||
}
|
||
function removeAll() {
|
||
var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match;
|
||
for (var name in this) {
|
||
if (match = name.match(re)) {
|
||
var l = this[name];
|
||
this.removeEventListener(match[1], l, l.$);
|
||
delete this[name];
|
||
}
|
||
}
|
||
}
|
||
return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll;
|
||
}
|
||
var d3_selection_onFilters = d3.map({
|
||
mouseenter: "mouseover",
|
||
mouseleave: "mouseout"
|
||
});
|
||
if (d3_document) {
|
||
d3_selection_onFilters.forEach(function(k) {
|
||
if ("on" + k in d3_document) d3_selection_onFilters.remove(k);
|
||
});
|
||
}
|
||
function d3_selection_onListener(listener, argumentz) {
|
||
return function(e) {
|
||
var o = d3.event;
|
||
d3.event = e;
|
||
argumentz[0] = this.__data__;
|
||
try {
|
||
listener.apply(this, argumentz);
|
||
} finally {
|
||
d3.event = o;
|
||
}
|
||
};
|
||
}
|
||
function d3_selection_onFilter(listener, argumentz) {
|
||
var l = d3_selection_onListener(listener, argumentz);
|
||
return function(e) {
|
||
var target = this, related = e.relatedTarget;
|
||
if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) {
|
||
l.call(target, e);
|
||
}
|
||
};
|
||
}
|
||
var d3_event_dragSelect, d3_event_dragId = 0;
|
||
function d3_event_dragSuppress(node) {
|
||
var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window(node)).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault);
|
||
if (d3_event_dragSelect == null) {
|
||
d3_event_dragSelect = "onselectstart" in node ? false : d3_vendorSymbol(node.style, "userSelect");
|
||
}
|
||
if (d3_event_dragSelect) {
|
||
var style = d3_documentElement(node).style, select = style[d3_event_dragSelect];
|
||
style[d3_event_dragSelect] = "none";
|
||
}
|
||
return function(suppressClick) {
|
||
w.on(name, null);
|
||
if (d3_event_dragSelect) style[d3_event_dragSelect] = select;
|
||
if (suppressClick) {
|
||
var off = function() {
|
||
w.on(click, null);
|
||
};
|
||
w.on(click, function() {
|
||
d3_eventPreventDefault();
|
||
off();
|
||
}, true);
|
||
setTimeout(off, 0);
|
||
}
|
||
};
|
||
}
|
||
d3.mouse = function(container) {
|
||
return d3_mousePoint(container, d3_eventSource());
|
||
};
|
||
var d3_mouse_bug44083 = this.navigator && /WebKit/.test(this.navigator.userAgent) ? -1 : 0;
|
||
function d3_mousePoint(container, e) {
|
||
if (e.changedTouches) e = e.changedTouches[0];
|
||
var svg = container.ownerSVGElement || container;
|
||
if (svg.createSVGPoint) {
|
||
var point = svg.createSVGPoint();
|
||
if (d3_mouse_bug44083 < 0) {
|
||
var window = d3_window(container);
|
||
if (window.scrollX || window.scrollY) {
|
||
svg = d3.select("body").append("svg").style({
|
||
position: "absolute",
|
||
top: 0,
|
||
left: 0,
|
||
margin: 0,
|
||
padding: 0,
|
||
border: "none"
|
||
}, "important");
|
||
var ctm = svg[0][0].getScreenCTM();
|
||
d3_mouse_bug44083 = !(ctm.f || ctm.e);
|
||
svg.remove();
|
||
}
|
||
}
|
||
if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX,
|
||
point.y = e.clientY;
|
||
point = point.matrixTransform(container.getScreenCTM().inverse());
|
||
return [ point.x, point.y ];
|
||
}
|
||
var rect = container.getBoundingClientRect();
|
||
return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];
|
||
}
|
||
d3.touch = function(container, touches, identifier) {
|
||
if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches;
|
||
if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) {
|
||
if ((touch = touches[i]).identifier === identifier) {
|
||
return d3_mousePoint(container, touch);
|
||
}
|
||
}
|
||
};
|
||
d3.behavior.drag = function() {
|
||
var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_window, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_identity, "touchmove", "touchend");
|
||
function drag() {
|
||
this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart);
|
||
}
|
||
function dragstart(id, position, subject, move, end) {
|
||
return function() {
|
||
var that = this, target = d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject(target)).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(target), position0 = position(parent, dragId);
|
||
if (origin) {
|
||
dragOffset = origin.apply(that, arguments);
|
||
dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ];
|
||
} else {
|
||
dragOffset = [ 0, 0 ];
|
||
}
|
||
dispatch({
|
||
type: "dragstart"
|
||
});
|
||
function moved() {
|
||
var position1 = position(parent, dragId), dx, dy;
|
||
if (!position1) return;
|
||
dx = position1[0] - position0[0];
|
||
dy = position1[1] - position0[1];
|
||
dragged |= dx | dy;
|
||
position0 = position1;
|
||
dispatch({
|
||
type: "drag",
|
||
x: position1[0] + dragOffset[0],
|
||
y: position1[1] + dragOffset[1],
|
||
dx: dx,
|
||
dy: dy
|
||
});
|
||
}
|
||
function ended() {
|
||
if (!position(parent, dragId)) return;
|
||
dragSubject.on(move + dragName, null).on(end + dragName, null);
|
||
dragRestore(dragged && d3.event.target === target);
|
||
dispatch({
|
||
type: "dragend"
|
||
});
|
||
}
|
||
};
|
||
}
|
||
drag.origin = function(x) {
|
||
if (!arguments.length) return origin;
|
||
origin = x;
|
||
return drag;
|
||
};
|
||
return d3.rebind(drag, event, "on");
|
||
};
|
||
function d3_behavior_dragTouchId() {
|
||
return d3.event.changedTouches[0].identifier;
|
||
}
|
||
d3.touches = function(container, touches) {
|
||
if (arguments.length < 2) touches = d3_eventSource().touches;
|
||
return touches ? d3_array(touches).map(function(touch) {
|
||
var point = d3_mousePoint(container, touch);
|
||
point.identifier = touch.identifier;
|
||
return point;
|
||
}) : [];
|
||
};
|
||
var ε = 1e-6, ε2 = ε * ε, π = Math.PI, τ = 2 * π, τε = τ - ε, halfπ = π / 2, d3_radians = π / 180, d3_degrees = 180 / π;
|
||
function d3_sgn(x) {
|
||
return x > 0 ? 1 : x < 0 ? -1 : 0;
|
||
}
|
||
function d3_cross2d(a, b, c) {
|
||
return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
|
||
}
|
||
function d3_acos(x) {
|
||
return x > 1 ? 0 : x < -1 ? π : Math.acos(x);
|
||
}
|
||
function d3_asin(x) {
|
||
return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x);
|
||
}
|
||
function d3_sinh(x) {
|
||
return ((x = Math.exp(x)) - 1 / x) / 2;
|
||
}
|
||
function d3_cosh(x) {
|
||
return ((x = Math.exp(x)) + 1 / x) / 2;
|
||
}
|
||
function d3_tanh(x) {
|
||
return ((x = Math.exp(2 * x)) - 1) / (x + 1);
|
||
}
|
||
function d3_haversin(x) {
|
||
return (x = Math.sin(x / 2)) * x;
|
||
}
|
||
var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4;
|
||
d3.interpolateZoom = function(p0, p1) {
|
||
var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2];
|
||
var dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1), dr = r1 - r0, S = (dr || Math.log(w1 / w0)) / ρ;
|
||
function interpolate(t) {
|
||
var s = t * S;
|
||
if (dr) {
|
||
var coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0));
|
||
return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ];
|
||
}
|
||
return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * s) ];
|
||
}
|
||
interpolate.duration = S * 1e3;
|
||
return interpolate;
|
||
};
|
||
d3.behavior.zoom = function() {
|
||
var view = {
|
||
x: 0,
|
||
y: 0,
|
||
k: 1
|
||
}, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, duration = 250, zooming = 0, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1;
|
||
if (!d3_behavior_zoomWheel) {
|
||
d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() {
|
||
return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1);
|
||
}, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() {
|
||
return d3.event.wheelDelta;
|
||
}, "mousewheel") : (d3_behavior_zoomDelta = function() {
|
||
return -d3.event.detail;
|
||
}, "MozMousePixelScroll");
|
||
}
|
||
function zoom(g) {
|
||
g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted);
|
||
}
|
||
zoom.event = function(g) {
|
||
g.each(function() {
|
||
var dispatch = event.of(this, arguments), view1 = view;
|
||
if (d3_transitionInheritId) {
|
||
d3.select(this).transition().each("start.zoom", function() {
|
||
view = this.__chart__ || {
|
||
x: 0,
|
||
y: 0,
|
||
k: 1
|
||
};
|
||
zoomstarted(dispatch);
|
||
}).tween("zoom:zoom", function() {
|
||
var dx = size[0], dy = size[1], cx = center0 ? center0[0] : dx / 2, cy = center0 ? center0[1] : dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]);
|
||
return function(t) {
|
||
var l = i(t), k = dx / l[2];
|
||
this.__chart__ = view = {
|
||
x: cx - l[0] * k,
|
||
y: cy - l[1] * k,
|
||
k: k
|
||
};
|
||
zoomed(dispatch);
|
||
};
|
||
}).each("interrupt.zoom", function() {
|
||
zoomended(dispatch);
|
||
}).each("end.zoom", function() {
|
||
zoomended(dispatch);
|
||
});
|
||
} else {
|
||
this.__chart__ = view;
|
||
zoomstarted(dispatch);
|
||
zoomed(dispatch);
|
||
zoomended(dispatch);
|
||
}
|
||
});
|
||
};
|
||
zoom.translate = function(_) {
|
||
if (!arguments.length) return [ view.x, view.y ];
|
||
view = {
|
||
x: +_[0],
|
||
y: +_[1],
|
||
k: view.k
|
||
};
|
||
rescale();
|
||
return zoom;
|
||
};
|
||
zoom.scale = function(_) {
|
||
if (!arguments.length) return view.k;
|
||
view = {
|
||
x: view.x,
|
||
y: view.y,
|
||
k: +_
|
||
};
|
||
rescale();
|
||
return zoom;
|
||
};
|
||
zoom.scaleExtent = function(_) {
|
||
if (!arguments.length) return scaleExtent;
|
||
scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ];
|
||
return zoom;
|
||
};
|
||
zoom.center = function(_) {
|
||
if (!arguments.length) return center;
|
||
center = _ && [ +_[0], +_[1] ];
|
||
return zoom;
|
||
};
|
||
zoom.size = function(_) {
|
||
if (!arguments.length) return size;
|
||
size = _ && [ +_[0], +_[1] ];
|
||
return zoom;
|
||
};
|
||
zoom.duration = function(_) {
|
||
if (!arguments.length) return duration;
|
||
duration = +_;
|
||
return zoom;
|
||
};
|
||
zoom.x = function(z) {
|
||
if (!arguments.length) return x1;
|
||
x1 = z;
|
||
x0 = z.copy();
|
||
view = {
|
||
x: 0,
|
||
y: 0,
|
||
k: 1
|
||
};
|
||
return zoom;
|
||
};
|
||
zoom.y = function(z) {
|
||
if (!arguments.length) return y1;
|
||
y1 = z;
|
||
y0 = z.copy();
|
||
view = {
|
||
x: 0,
|
||
y: 0,
|
||
k: 1
|
||
};
|
||
return zoom;
|
||
};
|
||
function location(p) {
|
||
return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ];
|
||
}
|
||
function point(l) {
|
||
return [ l[0] * view.k + view.x, l[1] * view.k + view.y ];
|
||
}
|
||
function scaleTo(s) {
|
||
view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
|
||
}
|
||
function translateTo(p, l) {
|
||
l = point(l);
|
||
view.x += p[0] - l[0];
|
||
view.y += p[1] - l[1];
|
||
}
|
||
function zoomTo(that, p, l, k) {
|
||
that.__chart__ = {
|
||
x: view.x,
|
||
y: view.y,
|
||
k: view.k
|
||
};
|
||
scaleTo(Math.pow(2, k));
|
||
translateTo(center0 = p, l);
|
||
that = d3.select(that);
|
||
if (duration > 0) that = that.transition().duration(duration);
|
||
that.call(zoom.event);
|
||
}
|
||
function rescale() {
|
||
if (x1) x1.domain(x0.range().map(function(x) {
|
||
return (x - view.x) / view.k;
|
||
}).map(x0.invert));
|
||
if (y1) y1.domain(y0.range().map(function(y) {
|
||
return (y - view.y) / view.k;
|
||
}).map(y0.invert));
|
||
}
|
||
function zoomstarted(dispatch) {
|
||
if (!zooming++) dispatch({
|
||
type: "zoomstart"
|
||
});
|
||
}
|
||
function zoomed(dispatch) {
|
||
rescale();
|
||
dispatch({
|
||
type: "zoom",
|
||
scale: view.k,
|
||
translate: [ view.x, view.y ]
|
||
});
|
||
}
|
||
function zoomended(dispatch) {
|
||
if (!--zooming) dispatch({
|
||
type: "zoomend"
|
||
}), center0 = null;
|
||
}
|
||
function mousedowned() {
|
||
var that = this, target = d3.event.target, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(that);
|
||
d3_selection_interrupt.call(that);
|
||
zoomstarted(dispatch);
|
||
function moved() {
|
||
dragged = 1;
|
||
translateTo(d3.mouse(that), location0);
|
||
zoomed(dispatch);
|
||
}
|
||
function ended() {
|
||
subject.on(mousemove, null).on(mouseup, null);
|
||
dragRestore(dragged && d3.event.target === target);
|
||
zoomended(dispatch);
|
||
}
|
||
}
|
||
function touchstarted() {
|
||
var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(that);
|
||
started();
|
||
zoomstarted(dispatch);
|
||
subject.on(mousedown, null).on(touchstart, started);
|
||
function relocate() {
|
||
var touches = d3.touches(that);
|
||
scale0 = view.k;
|
||
touches.forEach(function(t) {
|
||
if (t.identifier in locations0) locations0[t.identifier] = location(t);
|
||
});
|
||
return touches;
|
||
}
|
||
function started() {
|
||
var target = d3.event.target;
|
||
d3.select(target).on(touchmove, moved).on(touchend, ended);
|
||
targets.push(target);
|
||
var changed = d3.event.changedTouches;
|
||
for (var i = 0, n = changed.length; i < n; ++i) {
|
||
locations0[changed[i].identifier] = null;
|
||
}
|
||
var touches = relocate(), now = Date.now();
|
||
if (touches.length === 1) {
|
||
if (now - touchtime < 500) {
|
||
var p = touches[0];
|
||
zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1);
|
||
d3_eventPreventDefault();
|
||
}
|
||
touchtime = now;
|
||
} else if (touches.length > 1) {
|
||
var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1];
|
||
distance0 = dx * dx + dy * dy;
|
||
}
|
||
}
|
||
function moved() {
|
||
var touches = d3.touches(that), p0, l0, p1, l1;
|
||
d3_selection_interrupt.call(that);
|
||
for (var i = 0, n = touches.length; i < n; ++i, l1 = null) {
|
||
p1 = touches[i];
|
||
if (l1 = locations0[p1.identifier]) {
|
||
if (l0) break;
|
||
p0 = p1, l0 = l1;
|
||
}
|
||
}
|
||
if (l1) {
|
||
var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0);
|
||
p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];
|
||
l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];
|
||
scaleTo(scale1 * scale0);
|
||
}
|
||
touchtime = null;
|
||
translateTo(p0, l0);
|
||
zoomed(dispatch);
|
||
}
|
||
function ended() {
|
||
if (d3.event.touches.length) {
|
||
var changed = d3.event.changedTouches;
|
||
for (var i = 0, n = changed.length; i < n; ++i) {
|
||
delete locations0[changed[i].identifier];
|
||
}
|
||
for (var identifier in locations0) {
|
||
return void relocate();
|
||
}
|
||
}
|
||
d3.selectAll(targets).on(zoomName, null);
|
||
subject.on(mousedown, mousedowned).on(touchstart, touchstarted);
|
||
dragRestore();
|
||
zoomended(dispatch);
|
||
}
|
||
}
|
||
function mousewheeled() {
|
||
var dispatch = event.of(this, arguments);
|
||
if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this),
|
||
translate0 = location(center0 = center || d3.mouse(this)), zoomstarted(dispatch);
|
||
mousewheelTimer = setTimeout(function() {
|
||
mousewheelTimer = null;
|
||
zoomended(dispatch);
|
||
}, 50);
|
||
d3_eventPreventDefault();
|
||
scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k);
|
||
translateTo(center0, translate0);
|
||
zoomed(dispatch);
|
||
}
|
||
function dblclicked() {
|
||
var p = d3.mouse(this), k = Math.log(view.k) / Math.LN2;
|
||
zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1);
|
||
}
|
||
return d3.rebind(zoom, event, "on");
|
||
};
|
||
var d3_behavior_zoomInfinity = [ 0, Infinity ], d3_behavior_zoomDelta, d3_behavior_zoomWheel;
|
||
d3.color = d3_color;
|
||
function d3_color() {}
|
||
d3_color.prototype.toString = function() {
|
||
return this.rgb() + "";
|
||
};
|
||
d3.hsl = d3_hsl;
|
||
function d3_hsl(h, s, l) {
|
||
return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l);
|
||
}
|
||
var d3_hslPrototype = d3_hsl.prototype = new d3_color();
|
||
d3_hslPrototype.brighter = function(k) {
|
||
k = Math.pow(.7, arguments.length ? k : 1);
|
||
return new d3_hsl(this.h, this.s, this.l / k);
|
||
};
|
||
d3_hslPrototype.darker = function(k) {
|
||
k = Math.pow(.7, arguments.length ? k : 1);
|
||
return new d3_hsl(this.h, this.s, k * this.l);
|
||
};
|
||
d3_hslPrototype.rgb = function() {
|
||
return d3_hsl_rgb(this.h, this.s, this.l);
|
||
};
|
||
function d3_hsl_rgb(h, s, l) {
|
||
var m1, m2;
|
||
h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h;
|
||
s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s;
|
||
l = l < 0 ? 0 : l > 1 ? 1 : l;
|
||
m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
|
||
m1 = 2 * l - m2;
|
||
function v(h) {
|
||
if (h > 360) h -= 360; else if (h < 0) h += 360;
|
||
if (h < 60) return m1 + (m2 - m1) * h / 60;
|
||
if (h < 180) return m2;
|
||
if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
|
||
return m1;
|
||
}
|
||
function vv(h) {
|
||
return Math.round(v(h) * 255);
|
||
}
|
||
return new d3_rgb(vv(h + 120), vv(h), vv(h - 120));
|
||
}
|
||
d3.hcl = d3_hcl;
|
||
function d3_hcl(h, c, l) {
|
||
return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l);
|
||
}
|
||
var d3_hclPrototype = d3_hcl.prototype = new d3_color();
|
||
d3_hclPrototype.brighter = function(k) {
|
||
return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
|
||
};
|
||
d3_hclPrototype.darker = function(k) {
|
||
return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
|
||
};
|
||
d3_hclPrototype.rgb = function() {
|
||
return d3_hcl_lab(this.h, this.c, this.l).rgb();
|
||
};
|
||
function d3_hcl_lab(h, c, l) {
|
||
if (isNaN(h)) h = 0;
|
||
if (isNaN(c)) c = 0;
|
||
return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
|
||
}
|
||
d3.lab = d3_lab;
|
||
function d3_lab(l, a, b) {
|
||
return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b);
|
||
}
|
||
var d3_lab_K = 18;
|
||
var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;
|
||
var d3_labPrototype = d3_lab.prototype = new d3_color();
|
||
d3_labPrototype.brighter = function(k) {
|
||
return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
|
||
};
|
||
d3_labPrototype.darker = function(k) {
|
||
return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
|
||
};
|
||
d3_labPrototype.rgb = function() {
|
||
return d3_lab_rgb(this.l, this.a, this.b);
|
||
};
|
||
function d3_lab_rgb(l, a, b) {
|
||
var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200;
|
||
x = d3_lab_xyz(x) * d3_lab_X;
|
||
y = d3_lab_xyz(y) * d3_lab_Y;
|
||
z = d3_lab_xyz(z) * d3_lab_Z;
|
||
return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));
|
||
}
|
||
function d3_lab_hcl(l, a, b) {
|
||
return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l);
|
||
}
|
||
function d3_lab_xyz(x) {
|
||
return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
|
||
}
|
||
function d3_xyz_lab(x) {
|
||
return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
|
||
}
|
||
function d3_xyz_rgb(r) {
|
||
return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));
|
||
}
|
||
d3.rgb = d3_rgb;
|
||
function d3_rgb(r, g, b) {
|
||
return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b);
|
||
}
|
||
function d3_rgbNumber(value) {
|
||
return new d3_rgb(value >> 16, value >> 8 & 255, value & 255);
|
||
}
|
||
function d3_rgbString(value) {
|
||
return d3_rgbNumber(value) + "";
|
||
}
|
||
var d3_rgbPrototype = d3_rgb.prototype = new d3_color();
|
||
d3_rgbPrototype.brighter = function(k) {
|
||
k = Math.pow(.7, arguments.length ? k : 1);
|
||
var r = this.r, g = this.g, b = this.b, i = 30;
|
||
if (!r && !g && !b) return new d3_rgb(i, i, i);
|
||
if (r && r < i) r = i;
|
||
if (g && g < i) g = i;
|
||
if (b && b < i) b = i;
|
||
return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k));
|
||
};
|
||
d3_rgbPrototype.darker = function(k) {
|
||
k = Math.pow(.7, arguments.length ? k : 1);
|
||
return new d3_rgb(k * this.r, k * this.g, k * this.b);
|
||
};
|
||
d3_rgbPrototype.hsl = function() {
|
||
return d3_rgb_hsl(this.r, this.g, this.b);
|
||
};
|
||
d3_rgbPrototype.toString = function() {
|
||
return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
|
||
};
|
||
function d3_rgb_hex(v) {
|
||
return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);
|
||
}
|
||
function d3_rgb_parse(format, rgb, hsl) {
|
||
format = format.toLowerCase();
|
||
var r = 0, g = 0, b = 0, m1, m2, color;
|
||
m1 = /([a-z]+)\((.*)\)/.exec(format);
|
||
if (m1) {
|
||
m2 = m1[2].split(",");
|
||
switch (m1[1]) {
|
||
case "hsl":
|
||
{
|
||
return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100);
|
||
}
|
||
|
||
case "rgb":
|
||
{
|
||
return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2]));
|
||
}
|
||
}
|
||
}
|
||
if (color = d3_rgb_names.get(format)) {
|
||
return rgb(color.r, color.g, color.b);
|
||
}
|
||
if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) {
|
||
if (format.length === 4) {
|
||
r = (color & 3840) >> 4;
|
||
r = r >> 4 | r;
|
||
g = color & 240;
|
||
g = g >> 4 | g;
|
||
b = color & 15;
|
||
b = b << 4 | b;
|
||
} else if (format.length === 7) {
|
||
r = (color & 16711680) >> 16;
|
||
g = (color & 65280) >> 8;
|
||
b = color & 255;
|
||
}
|
||
}
|
||
return rgb(r, g, b);
|
||
}
|
||
function d3_rgb_hsl(r, g, b) {
|
||
var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2;
|
||
if (d) {
|
||
s = l < .5 ? d / (max + min) : d / (2 - max - min);
|
||
if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4;
|
||
h *= 60;
|
||
} else {
|
||
h = NaN;
|
||
s = l > 0 && l < 1 ? 0 : h;
|
||
}
|
||
return new d3_hsl(h, s, l);
|
||
}
|
||
function d3_rgb_lab(r, g, b) {
|
||
r = d3_rgb_xyz(r);
|
||
g = d3_rgb_xyz(g);
|
||
b = d3_rgb_xyz(b);
|
||
var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z);
|
||
return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));
|
||
}
|
||
function d3_rgb_xyz(r) {
|
||
return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);
|
||
}
|
||
function d3_rgb_parseNumber(c) {
|
||
var f = parseFloat(c);
|
||
return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
|
||
}
|
||
var d3_rgb_names = d3.map({
|
||
aliceblue: 15792383,
|
||
antiquewhite: 16444375,
|
||
aqua: 65535,
|
||
aquamarine: 8388564,
|
||
azure: 15794175,
|
||
beige: 16119260,
|
||
bisque: 16770244,
|
||
black: 0,
|
||
blanchedalmond: 16772045,
|
||
blue: 255,
|
||
blueviolet: 9055202,
|
||
brown: 10824234,
|
||
burlywood: 14596231,
|
||
cadetblue: 6266528,
|
||
chartreuse: 8388352,
|
||
chocolate: 13789470,
|
||
coral: 16744272,
|
||
cornflowerblue: 6591981,
|
||
cornsilk: 16775388,
|
||
crimson: 14423100,
|
||
cyan: 65535,
|
||
darkblue: 139,
|
||
darkcyan: 35723,
|
||
darkgoldenrod: 12092939,
|
||
darkgray: 11119017,
|
||
darkgreen: 25600,
|
||
darkgrey: 11119017,
|
||
darkkhaki: 12433259,
|
||
darkmagenta: 9109643,
|
||
darkolivegreen: 5597999,
|
||
darkorange: 16747520,
|
||
darkorchid: 10040012,
|
||
darkred: 9109504,
|
||
darksalmon: 15308410,
|
||
darkseagreen: 9419919,
|
||
darkslateblue: 4734347,
|
||
darkslategray: 3100495,
|
||
darkslategrey: 3100495,
|
||
darkturquoise: 52945,
|
||
darkviolet: 9699539,
|
||
deeppink: 16716947,
|
||
deepskyblue: 49151,
|
||
dimgray: 6908265,
|
||
dimgrey: 6908265,
|
||
dodgerblue: 2003199,
|
||
firebrick: 11674146,
|
||
floralwhite: 16775920,
|
||
forestgreen: 2263842,
|
||
fuchsia: 16711935,
|
||
gainsboro: 14474460,
|
||
ghostwhite: 16316671,
|
||
gold: 16766720,
|
||
goldenrod: 14329120,
|
||
gray: 8421504,
|
||
green: 32768,
|
||
greenyellow: 11403055,
|
||
grey: 8421504,
|
||
honeydew: 15794160,
|
||
hotpink: 16738740,
|
||
indianred: 13458524,
|
||
indigo: 4915330,
|
||
ivory: 16777200,
|
||
khaki: 15787660,
|
||
lavender: 15132410,
|
||
lavenderblush: 16773365,
|
||
lawngreen: 8190976,
|
||
lemonchiffon: 16775885,
|
||
lightblue: 11393254,
|
||
lightcoral: 15761536,
|
||
lightcyan: 14745599,
|
||
lightgoldenrodyellow: 16448210,
|
||
lightgray: 13882323,
|
||
lightgreen: 9498256,
|
||
lightgrey: 13882323,
|
||
lightpink: 16758465,
|
||
lightsalmon: 16752762,
|
||
lightseagreen: 2142890,
|
||
lightskyblue: 8900346,
|
||
lightslategray: 7833753,
|
||
lightslategrey: 7833753,
|
||
lightsteelblue: 11584734,
|
||
lightyellow: 16777184,
|
||
lime: 65280,
|
||
limegreen: 3329330,
|
||
linen: 16445670,
|
||
magenta: 16711935,
|
||
maroon: 8388608,
|
||
mediumaquamarine: 6737322,
|
||
mediumblue: 205,
|
||
mediumorchid: 12211667,
|
||
mediumpurple: 9662683,
|
||
mediumseagreen: 3978097,
|
||
mediumslateblue: 8087790,
|
||
mediumspringgreen: 64154,
|
||
mediumturquoise: 4772300,
|
||
mediumvioletred: 13047173,
|
||
midnightblue: 1644912,
|
||
mintcream: 16121850,
|
||
mistyrose: 16770273,
|
||
moccasin: 16770229,
|
||
navajowhite: 16768685,
|
||
navy: 128,
|
||
oldlace: 16643558,
|
||
olive: 8421376,
|
||
olivedrab: 7048739,
|
||
orange: 16753920,
|
||
orangered: 16729344,
|
||
orchid: 14315734,
|
||
palegoldenrod: 15657130,
|
||
palegreen: 10025880,
|
||
paleturquoise: 11529966,
|
||
palevioletred: 14381203,
|
||
papayawhip: 16773077,
|
||
peachpuff: 16767673,
|
||
peru: 13468991,
|
||
pink: 16761035,
|
||
plum: 14524637,
|
||
powderblue: 11591910,
|
||
purple: 8388736,
|
||
rebeccapurple: 6697881,
|
||
red: 16711680,
|
||
rosybrown: 12357519,
|
||
royalblue: 4286945,
|
||
saddlebrown: 9127187,
|
||
salmon: 16416882,
|
||
sandybrown: 16032864,
|
||
seagreen: 3050327,
|
||
seashell: 16774638,
|
||
sienna: 10506797,
|
||
silver: 12632256,
|
||
skyblue: 8900331,
|
||
slateblue: 6970061,
|
||
slategray: 7372944,
|
||
slategrey: 7372944,
|
||
snow: 16775930,
|
||
springgreen: 65407,
|
||
steelblue: 4620980,
|
||
tan: 13808780,
|
||
teal: 32896,
|
||
thistle: 14204888,
|
||
tomato: 16737095,
|
||
turquoise: 4251856,
|
||
violet: 15631086,
|
||
wheat: 16113331,
|
||
white: 16777215,
|
||
whitesmoke: 16119285,
|
||
yellow: 16776960,
|
||
yellowgreen: 10145074
|
||
});
|
||
d3_rgb_names.forEach(function(key, value) {
|
||
d3_rgb_names.set(key, d3_rgbNumber(value));
|
||
});
|
||
function d3_functor(v) {
|
||
return typeof v === "function" ? v : function() {
|
||
return v;
|
||
};
|
||
}
|
||
d3.functor = d3_functor;
|
||
d3.xhr = d3_xhrType(d3_identity);
|
||
function d3_xhrType(response) {
|
||
return function(url, mimeType, callback) {
|
||
if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType,
|
||
mimeType = null;
|
||
return d3_xhr(url, mimeType, response, callback);
|
||
};
|
||
}
|
||
function d3_xhr(url, mimeType, response, callback) {
|
||
var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null;
|
||
if (this.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest();
|
||
"onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() {
|
||
request.readyState > 3 && respond();
|
||
};
|
||
function respond() {
|
||
var status = request.status, result;
|
||
if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) {
|
||
try {
|
||
result = response.call(xhr, request);
|
||
} catch (e) {
|
||
dispatch.error.call(xhr, e);
|
||
return;
|
||
}
|
||
dispatch.load.call(xhr, result);
|
||
} else {
|
||
dispatch.error.call(xhr, request);
|
||
}
|
||
}
|
||
request.onprogress = function(event) {
|
||
var o = d3.event;
|
||
d3.event = event;
|
||
try {
|
||
dispatch.progress.call(xhr, request);
|
||
} finally {
|
||
d3.event = o;
|
||
}
|
||
};
|
||
xhr.header = function(name, value) {
|
||
name = (name + "").toLowerCase();
|
||
if (arguments.length < 2) return headers[name];
|
||
if (value == null) delete headers[name]; else headers[name] = value + "";
|
||
return xhr;
|
||
};
|
||
xhr.mimeType = function(value) {
|
||
if (!arguments.length) return mimeType;
|
||
mimeType = value == null ? null : value + "";
|
||
return xhr;
|
||
};
|
||
xhr.responseType = function(value) {
|
||
if (!arguments.length) return responseType;
|
||
responseType = value;
|
||
return xhr;
|
||
};
|
||
xhr.response = function(value) {
|
||
response = value;
|
||
return xhr;
|
||
};
|
||
[ "get", "post" ].forEach(function(method) {
|
||
xhr[method] = function() {
|
||
return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments)));
|
||
};
|
||
});
|
||
xhr.send = function(method, data, callback) {
|
||
if (arguments.length === 2 && typeof data === "function") callback = data, data = null;
|
||
request.open(method, url, true);
|
||
if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*";
|
||
if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]);
|
||
if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType);
|
||
if (responseType != null) request.responseType = responseType;
|
||
if (callback != null) xhr.on("error", callback).on("load", function(request) {
|
||
callback(null, request);
|
||
});
|
||
dispatch.beforesend.call(xhr, request);
|
||
request.send(data == null ? null : data);
|
||
return xhr;
|
||
};
|
||
xhr.abort = function() {
|
||
request.abort();
|
||
return xhr;
|
||
};
|
||
d3.rebind(xhr, dispatch, "on");
|
||
return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback));
|
||
}
|
||
function d3_xhr_fixCallback(callback) {
|
||
return callback.length === 1 ? function(error, request) {
|
||
callback(error == null ? request : null);
|
||
} : callback;
|
||
}
|
||
function d3_xhrHasResponse(request) {
|
||
var type = request.responseType;
|
||
return type && type !== "text" ? request.response : request.responseText;
|
||
}
|
||
d3.dsv = function(delimiter, mimeType) {
|
||
var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0);
|
||
function dsv(url, row, callback) {
|
||
if (arguments.length < 3) callback = row, row = null;
|
||
var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback);
|
||
xhr.row = function(_) {
|
||
return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row;
|
||
};
|
||
return xhr;
|
||
}
|
||
function response(request) {
|
||
return dsv.parse(request.responseText);
|
||
}
|
||
function typedResponse(f) {
|
||
return function(request) {
|
||
return dsv.parse(request.responseText, f);
|
||
};
|
||
}
|
||
dsv.parse = function(text, f) {
|
||
var o;
|
||
return dsv.parseRows(text, function(row, i) {
|
||
if (o) return o(row, i - 1);
|
||
var a = new Function("d", "return {" + row.map(function(name, i) {
|
||
return JSON.stringify(name) + ": d[" + i + "]";
|
||
}).join(",") + "}");
|
||
o = f ? function(row, i) {
|
||
return f(a(row), i);
|
||
} : a;
|
||
});
|
||
};
|
||
dsv.parseRows = function(text, f) {
|
||
var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol;
|
||
function token() {
|
||
if (I >= N) return EOF;
|
||
if (eol) return eol = false, EOL;
|
||
var j = I;
|
||
if (text.charCodeAt(j) === 34) {
|
||
var i = j;
|
||
while (i++ < N) {
|
||
if (text.charCodeAt(i) === 34) {
|
||
if (text.charCodeAt(i + 1) !== 34) break;
|
||
++i;
|
||
}
|
||
}
|
||
I = i + 2;
|
||
var c = text.charCodeAt(i + 1);
|
||
if (c === 13) {
|
||
eol = true;
|
||
if (text.charCodeAt(i + 2) === 10) ++I;
|
||
} else if (c === 10) {
|
||
eol = true;
|
||
}
|
||
return text.slice(j + 1, i).replace(/""/g, '"');
|
||
}
|
||
while (I < N) {
|
||
var c = text.charCodeAt(I++), k = 1;
|
||
if (c === 10) eol = true; else if (c === 13) {
|
||
eol = true;
|
||
if (text.charCodeAt(I) === 10) ++I, ++k;
|
||
} else if (c !== delimiterCode) continue;
|
||
return text.slice(j, I - k);
|
||
}
|
||
return text.slice(j);
|
||
}
|
||
while ((t = token()) !== EOF) {
|
||
var a = [];
|
||
while (t !== EOL && t !== EOF) {
|
||
a.push(t);
|
||
t = token();
|
||
}
|
||
if (f && (a = f(a, n++)) == null) continue;
|
||
rows.push(a);
|
||
}
|
||
return rows;
|
||
};
|
||
dsv.format = function(rows) {
|
||
if (Array.isArray(rows[0])) return dsv.formatRows(rows);
|
||
var fieldSet = new d3_Set(), fields = [];
|
||
rows.forEach(function(row) {
|
||
for (var field in row) {
|
||
if (!fieldSet.has(field)) {
|
||
fields.push(fieldSet.add(field));
|
||
}
|
||
}
|
||
});
|
||
return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) {
|
||
return fields.map(function(field) {
|
||
return formatValue(row[field]);
|
||
}).join(delimiter);
|
||
})).join("\n");
|
||
};
|
||
dsv.formatRows = function(rows) {
|
||
return rows.map(formatRow).join("\n");
|
||
};
|
||
function formatRow(row) {
|
||
return row.map(formatValue).join(delimiter);
|
||
}
|
||
function formatValue(text) {
|
||
return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text;
|
||
}
|
||
return dsv;
|
||
};
|
||
d3.csv = d3.dsv(",", "text/csv");
|
||
d3.tsv = d3.dsv(" ", "text/tab-separated-values");
|
||
var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_active, d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) {
|
||
setTimeout(callback, 17);
|
||
};
|
||
d3.timer = function(callback, delay, then) {
|
||
var n = arguments.length;
|
||
if (n < 2) delay = 0;
|
||
if (n < 3) then = Date.now();
|
||
var time = then + delay, timer = {
|
||
c: callback,
|
||
t: time,
|
||
f: false,
|
||
n: null
|
||
};
|
||
if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer;
|
||
d3_timer_queueTail = timer;
|
||
if (!d3_timer_interval) {
|
||
d3_timer_timeout = clearTimeout(d3_timer_timeout);
|
||
d3_timer_interval = 1;
|
||
d3_timer_frame(d3_timer_step);
|
||
}
|
||
};
|
||
function d3_timer_step() {
|
||
var now = d3_timer_mark(), delay = d3_timer_sweep() - now;
|
||
if (delay > 24) {
|
||
if (isFinite(delay)) {
|
||
clearTimeout(d3_timer_timeout);
|
||
d3_timer_timeout = setTimeout(d3_timer_step, delay);
|
||
}
|
||
d3_timer_interval = 0;
|
||
} else {
|
||
d3_timer_interval = 1;
|
||
d3_timer_frame(d3_timer_step);
|
||
}
|
||
}
|
||
d3.timer.flush = function() {
|
||
d3_timer_mark();
|
||
d3_timer_sweep();
|
||
};
|
||
function d3_timer_mark() {
|
||
var now = Date.now();
|
||
d3_timer_active = d3_timer_queueHead;
|
||
while (d3_timer_active) {
|
||
if (now >= d3_timer_active.t) d3_timer_active.f = d3_timer_active.c(now - d3_timer_active.t);
|
||
d3_timer_active = d3_timer_active.n;
|
||
}
|
||
return now;
|
||
}
|
||
function d3_timer_sweep() {
|
||
var t0, t1 = d3_timer_queueHead, time = Infinity;
|
||
while (t1) {
|
||
if (t1.f) {
|
||
t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n;
|
||
} else {
|
||
if (t1.t < time) time = t1.t;
|
||
t1 = (t0 = t1).n;
|
||
}
|
||
}
|
||
d3_timer_queueTail = t0;
|
||
return time;
|
||
}
|
||
function d3_format_precision(x, p) {
|
||
return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);
|
||
}
|
||
d3.round = function(x, n) {
|
||
return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);
|
||
};
|
||
var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix);
|
||
d3.formatPrefix = function(value, precision) {
|
||
var i = 0;
|
||
if (value) {
|
||
if (value < 0) value *= -1;
|
||
if (precision) value = d3.round(value, d3_format_precision(value, precision));
|
||
i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
|
||
i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3));
|
||
}
|
||
return d3_formatPrefixes[8 + i / 3];
|
||
};
|
||
function d3_formatPrefix(d, i) {
|
||
var k = Math.pow(10, abs(8 - i) * 3);
|
||
return {
|
||
scale: i > 8 ? function(d) {
|
||
return d / k;
|
||
} : function(d) {
|
||
return d * k;
|
||
},
|
||
symbol: d
|
||
};
|
||
}
|
||
function d3_locale_numberFormat(locale) {
|
||
var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) {
|
||
var i = value.length, t = [], j = 0, g = locale_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 = locale_grouping[j = (j + 1) % locale_grouping.length];
|
||
}
|
||
return t.reverse().join(locale_thousands);
|
||
} : d3_identity;
|
||
return function(specifier) {
|
||
var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true;
|
||
if (precision) precision = +precision.substring(1);
|
||
if (zfill || fill === "0" && align === "=") {
|
||
zfill = fill = "0";
|
||
align = "=";
|
||
}
|
||
switch (type) {
|
||
case "n":
|
||
comma = true;
|
||
type = "g";
|
||
break;
|
||
|
||
case "%":
|
||
scale = 100;
|
||
suffix = "%";
|
||
type = "f";
|
||
break;
|
||
|
||
case "p":
|
||
scale = 100;
|
||
suffix = "%";
|
||
type = "r";
|
||
break;
|
||
|
||
case "b":
|
||
case "o":
|
||
case "x":
|
||
case "X":
|
||
if (symbol === "#") prefix = "0" + type.toLowerCase();
|
||
|
||
case "c":
|
||
exponent = false;
|
||
|
||
case "d":
|
||
integer = true;
|
||
precision = 0;
|
||
break;
|
||
|
||
case "s":
|
||
scale = -1;
|
||
type = "r";
|
||
break;
|
||
}
|
||
if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1];
|
||
if (type == "r" && !precision) type = "g";
|
||
if (precision != null) {
|
||
if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision));
|
||
}
|
||
type = d3_format_types.get(type) || d3_format_typeDefault;
|
||
var zcomma = zfill && comma;
|
||
return function(value) {
|
||
var fullSuffix = suffix;
|
||
if (integer && value % 1) return "";
|
||
var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign;
|
||
if (scale < 0) {
|
||
var unit = d3.formatPrefix(value, precision);
|
||
value = unit.scale(value);
|
||
fullSuffix = unit.symbol + suffix;
|
||
} else {
|
||
value *= scale;
|
||
}
|
||
value = type(value, precision);
|
||
var i = value.lastIndexOf("."), before, after;
|
||
if (i < 0) {
|
||
var j = exponent ? value.lastIndexOf("e") : -1;
|
||
if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j);
|
||
} else {
|
||
before = value.substring(0, i);
|
||
after = locale_decimal + value.substring(i + 1);
|
||
}
|
||
if (!zfill && comma) before = formatGroup(before, Infinity);
|
||
var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : "";
|
||
if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity);
|
||
negative += prefix;
|
||
value = before + after;
|
||
return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix;
|
||
};
|
||
};
|
||
}
|
||
var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i;
|
||
var d3_format_types = d3.map({
|
||
b: function(x) {
|
||
return x.toString(2);
|
||
},
|
||
c: function(x) {
|
||
return String.fromCharCode(x);
|
||
},
|
||
o: function(x) {
|
||
return x.toString(8);
|
||
},
|
||
x: function(x) {
|
||
return x.toString(16);
|
||
},
|
||
X: function(x) {
|
||
return x.toString(16).toUpperCase();
|
||
},
|
||
g: function(x, p) {
|
||
return x.toPrecision(p);
|
||
},
|
||
e: function(x, p) {
|
||
return x.toExponential(p);
|
||
},
|
||
f: function(x, p) {
|
||
return x.toFixed(p);
|
||
},
|
||
r: function(x, p) {
|
||
return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p))));
|
||
}
|
||
});
|
||
function d3_format_typeDefault(x) {
|
||
return x + "";
|
||
}
|
||
var d3_time = d3.time = {}, d3_date = Date;
|
||
function d3_date_utc() {
|
||
this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]);
|
||
}
|
||
d3_date_utc.prototype = {
|
||
getDate: function() {
|
||
return this._.getUTCDate();
|
||
},
|
||
getDay: function() {
|
||
return this._.getUTCDay();
|
||
},
|
||
getFullYear: function() {
|
||
return this._.getUTCFullYear();
|
||
},
|
||
getHours: function() {
|
||
return this._.getUTCHours();
|
||
},
|
||
getMilliseconds: function() {
|
||
return this._.getUTCMilliseconds();
|
||
},
|
||
getMinutes: function() {
|
||
return this._.getUTCMinutes();
|
||
},
|
||
getMonth: function() {
|
||
return this._.getUTCMonth();
|
||
},
|
||
getSeconds: function() {
|
||
return this._.getUTCSeconds();
|
||
},
|
||
getTime: function() {
|
||
return this._.getTime();
|
||
},
|
||
getTimezoneOffset: function() {
|
||
return 0;
|
||
},
|
||
valueOf: function() {
|
||
return this._.valueOf();
|
||
},
|
||
setDate: function() {
|
||
d3_time_prototype.setUTCDate.apply(this._, arguments);
|
||
},
|
||
setDay: function() {
|
||
d3_time_prototype.setUTCDay.apply(this._, arguments);
|
||
},
|
||
setFullYear: function() {
|
||
d3_time_prototype.setUTCFullYear.apply(this._, arguments);
|
||
},
|
||
setHours: function() {
|
||
d3_time_prototype.setUTCHours.apply(this._, arguments);
|
||
},
|
||
setMilliseconds: function() {
|
||
d3_time_prototype.setUTCMilliseconds.apply(this._, arguments);
|
||
},
|
||
setMinutes: function() {
|
||
d3_time_prototype.setUTCMinutes.apply(this._, arguments);
|
||
},
|
||
setMonth: function() {
|
||
d3_time_prototype.setUTCMonth.apply(this._, arguments);
|
||
},
|
||
setSeconds: function() {
|
||
d3_time_prototype.setUTCSeconds.apply(this._, arguments);
|
||
},
|
||
setTime: function() {
|
||
d3_time_prototype.setTime.apply(this._, arguments);
|
||
}
|
||
};
|
||
var d3_time_prototype = Date.prototype;
|
||
function d3_time_interval(local, step, number) {
|
||
function round(date) {
|
||
var d0 = local(date), d1 = offset(d0, 1);
|
||
return date - d0 < d1 - date ? d0 : d1;
|
||
}
|
||
function ceil(date) {
|
||
step(date = local(new d3_date(date - 1)), 1);
|
||
return date;
|
||
}
|
||
function offset(date, k) {
|
||
step(date = new d3_date(+date), k);
|
||
return date;
|
||
}
|
||
function range(t0, t1, dt) {
|
||
var time = ceil(t0), times = [];
|
||
if (dt > 1) {
|
||
while (time < t1) {
|
||
if (!(number(time) % dt)) times.push(new Date(+time));
|
||
step(time, 1);
|
||
}
|
||
} else {
|
||
while (time < t1) times.push(new Date(+time)), step(time, 1);
|
||
}
|
||
return times;
|
||
}
|
||
function range_utc(t0, t1, dt) {
|
||
try {
|
||
d3_date = d3_date_utc;
|
||
var utc = new d3_date_utc();
|
||
utc._ = t0;
|
||
return range(utc, t1, dt);
|
||
} finally {
|
||
d3_date = Date;
|
||
}
|
||
}
|
||
local.floor = local;
|
||
local.round = round;
|
||
local.ceil = ceil;
|
||
local.offset = offset;
|
||
local.range = range;
|
||
var utc = local.utc = d3_time_interval_utc(local);
|
||
utc.floor = utc;
|
||
utc.round = d3_time_interval_utc(round);
|
||
utc.ceil = d3_time_interval_utc(ceil);
|
||
utc.offset = d3_time_interval_utc(offset);
|
||
utc.range = range_utc;
|
||
return local;
|
||
}
|
||
function d3_time_interval_utc(method) {
|
||
return function(date, k) {
|
||
try {
|
||
d3_date = d3_date_utc;
|
||
var utc = new d3_date_utc();
|
||
utc._ = date;
|
||
return method(utc, k)._;
|
||
} finally {
|
||
d3_date = Date;
|
||
}
|
||
};
|
||
}
|
||
d3_time.year = d3_time_interval(function(date) {
|
||
date = d3_time.day(date);
|
||
date.setMonth(0, 1);
|
||
return date;
|
||
}, function(date, offset) {
|
||
date.setFullYear(date.getFullYear() + offset);
|
||
}, function(date) {
|
||
return date.getFullYear();
|
||
});
|
||
d3_time.years = d3_time.year.range;
|
||
d3_time.years.utc = d3_time.year.utc.range;
|
||
d3_time.day = d3_time_interval(function(date) {
|
||
var day = new d3_date(2e3, 0);
|
||
day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
|
||
return day;
|
||
}, function(date, offset) {
|
||
date.setDate(date.getDate() + offset);
|
||
}, function(date) {
|
||
return date.getDate() - 1;
|
||
});
|
||
d3_time.days = d3_time.day.range;
|
||
d3_time.days.utc = d3_time.day.utc.range;
|
||
d3_time.dayOfYear = function(date) {
|
||
var year = d3_time.year(date);
|
||
return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);
|
||
};
|
||
[ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) {
|
||
i = 7 - i;
|
||
var interval = d3_time[day] = d3_time_interval(function(date) {
|
||
(date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);
|
||
return date;
|
||
}, function(date, offset) {
|
||
date.setDate(date.getDate() + Math.floor(offset) * 7);
|
||
}, function(date) {
|
||
var day = d3_time.year(date).getDay();
|
||
return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);
|
||
});
|
||
d3_time[day + "s"] = interval.range;
|
||
d3_time[day + "s"].utc = interval.utc.range;
|
||
d3_time[day + "OfYear"] = function(date) {
|
||
var day = d3_time.year(date).getDay();
|
||
return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7);
|
||
};
|
||
});
|
||
d3_time.week = d3_time.sunday;
|
||
d3_time.weeks = d3_time.sunday.range;
|
||
d3_time.weeks.utc = d3_time.sunday.utc.range;
|
||
d3_time.weekOfYear = d3_time.sundayOfYear;
|
||
function d3_locale_timeFormat(locale) {
|
||
var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths;
|
||
function d3_time_format(template) {
|
||
var n = template.length;
|
||
function format(date) {
|
||
var string = [], i = -1, j = 0, c, p, f;
|
||
while (++i < n) {
|
||
if (template.charCodeAt(i) === 37) {
|
||
string.push(template.slice(j, i));
|
||
if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i);
|
||
if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p);
|
||
string.push(c);
|
||
j = i + 1;
|
||
}
|
||
}
|
||
string.push(template.slice(j, i));
|
||
return string.join("");
|
||
}
|
||
format.parse = function(string) {
|
||
var d = {
|
||
y: 1900,
|
||
m: 0,
|
||
d: 1,
|
||
H: 0,
|
||
M: 0,
|
||
S: 0,
|
||
L: 0,
|
||
Z: null
|
||
}, i = d3_time_parse(d, template, string, 0);
|
||
if (i != string.length) return null;
|
||
if ("p" in d) d.H = d.H % 12 + d.p * 12;
|
||
var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)();
|
||
if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("w" in d && ("W" in d || "U" in d)) {
|
||
date.setFullYear(d.y, 0, 1);
|
||
date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7);
|
||
} else date.setFullYear(d.y, d.m, d.d);
|
||
date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L);
|
||
return localZ ? date._ : date;
|
||
};
|
||
format.toString = function() {
|
||
return template;
|
||
};
|
||
return format;
|
||
}
|
||
function d3_time_parse(date, template, string, j) {
|
||
var c, p, t, i = 0, n = template.length, m = string.length;
|
||
while (i < n) {
|
||
if (j >= m) return -1;
|
||
c = template.charCodeAt(i++);
|
||
if (c === 37) {
|
||
t = template.charAt(i++);
|
||
p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t];
|
||
if (!p || (j = p(date, string, j)) < 0) return -1;
|
||
} else if (c != string.charCodeAt(j++)) {
|
||
return -1;
|
||
}
|
||
}
|
||
return j;
|
||
}
|
||
d3_time_format.utc = function(template) {
|
||
var local = d3_time_format(template);
|
||
function format(date) {
|
||
try {
|
||
d3_date = d3_date_utc;
|
||
var utc = new d3_date();
|
||
utc._ = date;
|
||
return local(utc);
|
||
} finally {
|
||
d3_date = Date;
|
||
}
|
||
}
|
||
format.parse = function(string) {
|
||
try {
|
||
d3_date = d3_date_utc;
|
||
var date = local.parse(string);
|
||
return date && date._;
|
||
} finally {
|
||
d3_date = Date;
|
||
}
|
||
};
|
||
format.toString = local.toString;
|
||
return format;
|
||
};
|
||
d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti;
|
||
var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths);
|
||
locale_periods.forEach(function(p, i) {
|
||
d3_time_periodLookup.set(p.toLowerCase(), i);
|
||
});
|
||
var d3_time_formats = {
|
||
a: function(d) {
|
||
return locale_shortDays[d.getDay()];
|
||
},
|
||
A: function(d) {
|
||
return locale_days[d.getDay()];
|
||
},
|
||
b: function(d) {
|
||
return locale_shortMonths[d.getMonth()];
|
||
},
|
||
B: function(d) {
|
||
return locale_months[d.getMonth()];
|
||
},
|
||
c: d3_time_format(locale_dateTime),
|
||
d: function(d, p) {
|
||
return d3_time_formatPad(d.getDate(), p, 2);
|
||
},
|
||
e: function(d, p) {
|
||
return d3_time_formatPad(d.getDate(), p, 2);
|
||
},
|
||
H: function(d, p) {
|
||
return d3_time_formatPad(d.getHours(), p, 2);
|
||
},
|
||
I: function(d, p) {
|
||
return d3_time_formatPad(d.getHours() % 12 || 12, p, 2);
|
||
},
|
||
j: function(d, p) {
|
||
return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3);
|
||
},
|
||
L: function(d, p) {
|
||
return d3_time_formatPad(d.getMilliseconds(), p, 3);
|
||
},
|
||
m: function(d, p) {
|
||
return d3_time_formatPad(d.getMonth() + 1, p, 2);
|
||
},
|
||
M: function(d, p) {
|
||
return d3_time_formatPad(d.getMinutes(), p, 2);
|
||
},
|
||
p: function(d) {
|
||
return locale_periods[+(d.getHours() >= 12)];
|
||
},
|
||
S: function(d, p) {
|
||
return d3_time_formatPad(d.getSeconds(), p, 2);
|
||
},
|
||
U: function(d, p) {
|
||
return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2);
|
||
},
|
||
w: function(d) {
|
||
return d.getDay();
|
||
},
|
||
W: function(d, p) {
|
||
return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2);
|
||
},
|
||
x: d3_time_format(locale_date),
|
||
X: d3_time_format(locale_time),
|
||
y: function(d, p) {
|
||
return d3_time_formatPad(d.getFullYear() % 100, p, 2);
|
||
},
|
||
Y: function(d, p) {
|
||
return d3_time_formatPad(d.getFullYear() % 1e4, p, 4);
|
||
},
|
||
Z: d3_time_zone,
|
||
"%": function() {
|
||
return "%";
|
||
}
|
||
};
|
||
var d3_time_parsers = {
|
||
a: d3_time_parseWeekdayAbbrev,
|
||
A: d3_time_parseWeekday,
|
||
b: d3_time_parseMonthAbbrev,
|
||
B: d3_time_parseMonth,
|
||
c: d3_time_parseLocaleFull,
|
||
d: d3_time_parseDay,
|
||
e: d3_time_parseDay,
|
||
H: d3_time_parseHour24,
|
||
I: d3_time_parseHour24,
|
||
j: d3_time_parseDayOfYear,
|
||
L: d3_time_parseMilliseconds,
|
||
m: d3_time_parseMonthNumber,
|
||
M: d3_time_parseMinutes,
|
||
p: d3_time_parseAmPm,
|
||
S: d3_time_parseSeconds,
|
||
U: d3_time_parseWeekNumberSunday,
|
||
w: d3_time_parseWeekdayNumber,
|
||
W: d3_time_parseWeekNumberMonday,
|
||
x: d3_time_parseLocaleDate,
|
||
X: d3_time_parseLocaleTime,
|
||
y: d3_time_parseYear,
|
||
Y: d3_time_parseFullYear,
|
||
Z: d3_time_parseZone,
|
||
"%": d3_time_parseLiteralPercent
|
||
};
|
||
function d3_time_parseWeekdayAbbrev(date, string, i) {
|
||
d3_time_dayAbbrevRe.lastIndex = 0;
|
||
var n = d3_time_dayAbbrevRe.exec(string.slice(i));
|
||
return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
|
||
}
|
||
function d3_time_parseWeekday(date, string, i) {
|
||
d3_time_dayRe.lastIndex = 0;
|
||
var n = d3_time_dayRe.exec(string.slice(i));
|
||
return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
|
||
}
|
||
function d3_time_parseMonthAbbrev(date, string, i) {
|
||
d3_time_monthAbbrevRe.lastIndex = 0;
|
||
var n = d3_time_monthAbbrevRe.exec(string.slice(i));
|
||
return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
|
||
}
|
||
function d3_time_parseMonth(date, string, i) {
|
||
d3_time_monthRe.lastIndex = 0;
|
||
var n = d3_time_monthRe.exec(string.slice(i));
|
||
return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
|
||
}
|
||
function d3_time_parseLocaleFull(date, string, i) {
|
||
return d3_time_parse(date, d3_time_formats.c.toString(), string, i);
|
||
}
|
||
function d3_time_parseLocaleDate(date, string, i) {
|
||
return d3_time_parse(date, d3_time_formats.x.toString(), string, i);
|
||
}
|
||
function d3_time_parseLocaleTime(date, string, i) {
|
||
return d3_time_parse(date, d3_time_formats.X.toString(), string, i);
|
||
}
|
||
function d3_time_parseAmPm(date, string, i) {
|
||
var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase());
|
||
return n == null ? -1 : (date.p = n, i);
|
||
}
|
||
return d3_time_format;
|
||
}
|
||
var d3_time_formatPads = {
|
||
"-": "",
|
||
_: " ",
|
||
"0": "0"
|
||
}, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/;
|
||
function d3_time_formatPad(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 d3_time_formatRe(names) {
|
||
return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i");
|
||
}
|
||
function d3_time_formatLookup(names) {
|
||
var map = new d3_Map(), i = -1, n = names.length;
|
||
while (++i < n) map.set(names[i].toLowerCase(), i);
|
||
return map;
|
||
}
|
||
function d3_time_parseWeekdayNumber(date, string, i) {
|
||
d3_time_numberRe.lastIndex = 0;
|
||
var n = d3_time_numberRe.exec(string.slice(i, i + 1));
|
||
return n ? (date.w = +n[0], i + n[0].length) : -1;
|
||
}
|
||
function d3_time_parseWeekNumberSunday(date, string, i) {
|
||
d3_time_numberRe.lastIndex = 0;
|
||
var n = d3_time_numberRe.exec(string.slice(i));
|
||
return n ? (date.U = +n[0], i + n[0].length) : -1;
|
||
}
|
||
function d3_time_parseWeekNumberMonday(date, string, i) {
|
||
d3_time_numberRe.lastIndex = 0;
|
||
var n = d3_time_numberRe.exec(string.slice(i));
|
||
return n ? (date.W = +n[0], i + n[0].length) : -1;
|
||
}
|
||
function d3_time_parseFullYear(date, string, i) {
|
||
d3_time_numberRe.lastIndex = 0;
|
||
var n = d3_time_numberRe.exec(string.slice(i, i + 4));
|
||
return n ? (date.y = +n[0], i + n[0].length) : -1;
|
||
}
|
||
function d3_time_parseYear(date, string, i) {
|
||
d3_time_numberRe.lastIndex = 0;
|
||
var n = d3_time_numberRe.exec(string.slice(i, i + 2));
|
||
return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1;
|
||
}
|
||
function d3_time_parseZone(date, string, i) {
|
||
return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string,
|
||
i + 5) : -1;
|
||
}
|
||
function d3_time_expandYear(d) {
|
||
return d + (d > 68 ? 1900 : 2e3);
|
||
}
|
||
function d3_time_parseMonthNumber(date, string, i) {
|
||
d3_time_numberRe.lastIndex = 0;
|
||
var n = d3_time_numberRe.exec(string.slice(i, i + 2));
|
||
return n ? (date.m = n[0] - 1, i + n[0].length) : -1;
|
||
}
|
||
function d3_time_parseDay(date, string, i) {
|
||
d3_time_numberRe.lastIndex = 0;
|
||
var n = d3_time_numberRe.exec(string.slice(i, i + 2));
|
||
return n ? (date.d = +n[0], i + n[0].length) : -1;
|
||
}
|
||
function d3_time_parseDayOfYear(date, string, i) {
|
||
d3_time_numberRe.lastIndex = 0;
|
||
var n = d3_time_numberRe.exec(string.slice(i, i + 3));
|
||
return n ? (date.j = +n[0], i + n[0].length) : -1;
|
||
}
|
||
function d3_time_parseHour24(date, string, i) {
|
||
d3_time_numberRe.lastIndex = 0;
|
||
var n = d3_time_numberRe.exec(string.slice(i, i + 2));
|
||
return n ? (date.H = +n[0], i + n[0].length) : -1;
|
||
}
|
||
function d3_time_parseMinutes(date, string, i) {
|
||
d3_time_numberRe.lastIndex = 0;
|
||
var n = d3_time_numberRe.exec(string.slice(i, i + 2));
|
||
return n ? (date.M = +n[0], i + n[0].length) : -1;
|
||
}
|
||
function d3_time_parseSeconds(date, string, i) {
|
||
d3_time_numberRe.lastIndex = 0;
|
||
var n = d3_time_numberRe.exec(string.slice(i, i + 2));
|
||
return n ? (date.S = +n[0], i + n[0].length) : -1;
|
||
}
|
||
function d3_time_parseMilliseconds(date, string, i) {
|
||
d3_time_numberRe.lastIndex = 0;
|
||
var n = d3_time_numberRe.exec(string.slice(i, i + 3));
|
||
return n ? (date.L = +n[0], i + n[0].length) : -1;
|
||
}
|
||
function d3_time_zone(d) {
|
||
var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60;
|
||
return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2);
|
||
}
|
||
function d3_time_parseLiteralPercent(date, string, i) {
|
||
d3_time_percentRe.lastIndex = 0;
|
||
var n = d3_time_percentRe.exec(string.slice(i, i + 1));
|
||
return n ? i + n[0].length : -1;
|
||
}
|
||
function d3_time_formatMulti(formats) {
|
||
var n = formats.length, i = -1;
|
||
while (++i < n) formats[i][0] = this(formats[i][0]);
|
||
return function(date) {
|
||
var i = 0, f = formats[i];
|
||
while (!f[1](date)) f = formats[++i];
|
||
return f[0](date);
|
||
};
|
||
}
|
||
d3.locale = function(locale) {
|
||
return {
|
||
numberFormat: d3_locale_numberFormat(locale),
|
||
timeFormat: d3_locale_timeFormat(locale)
|
||
};
|
||
};
|
||
var d3_locale_enUS = d3.locale({
|
||
decimal: ".",
|
||
thousands: ",",
|
||
grouping: [ 3 ],
|
||
currency: [ "$", "" ],
|
||
dateTime: "%a %b %e %X %Y",
|
||
date: "%m/%d/%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" ]
|
||
});
|
||
d3.format = d3_locale_enUS.numberFormat;
|
||
d3.geo = {};
|
||
function d3_adder() {}
|
||
d3_adder.prototype = {
|
||
s: 0,
|
||
t: 0,
|
||
add: function(y) {
|
||
d3_adderSum(y, this.t, d3_adderTemp);
|
||
d3_adderSum(d3_adderTemp.s, this.s, this);
|
||
if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t;
|
||
},
|
||
reset: function() {
|
||
this.s = this.t = 0;
|
||
},
|
||
valueOf: function() {
|
||
return this.s;
|
||
}
|
||
};
|
||
var d3_adderTemp = new d3_adder();
|
||
function d3_adderSum(a, b, o) {
|
||
var x = o.s = a + b, bv = x - a, av = x - bv;
|
||
o.t = a - av + (b - bv);
|
||
}
|
||
d3.geo.stream = function(object, listener) {
|
||
if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) {
|
||
d3_geo_streamObjectType[object.type](object, listener);
|
||
} else {
|
||
d3_geo_streamGeometry(object, listener);
|
||
}
|
||
};
|
||
function d3_geo_streamGeometry(geometry, listener) {
|
||
if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {
|
||
d3_geo_streamGeometryType[geometry.type](geometry, listener);
|
||
}
|
||
}
|
||
var d3_geo_streamObjectType = {
|
||
Feature: function(feature, listener) {
|
||
d3_geo_streamGeometry(feature.geometry, listener);
|
||
},
|
||
FeatureCollection: function(object, listener) {
|
||
var features = object.features, i = -1, n = features.length;
|
||
while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener);
|
||
}
|
||
};
|
||
var d3_geo_streamGeometryType = {
|
||
Sphere: function(object, listener) {
|
||
listener.sphere();
|
||
},
|
||
Point: function(object, listener) {
|
||
object = object.coordinates;
|
||
listener.point(object[0], object[1], object[2]);
|
||
},
|
||
MultiPoint: function(object, listener) {
|
||
var coordinates = object.coordinates, i = -1, n = coordinates.length;
|
||
while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]);
|
||
},
|
||
LineString: function(object, listener) {
|
||
d3_geo_streamLine(object.coordinates, listener, 0);
|
||
},
|
||
MultiLineString: function(object, listener) {
|
||
var coordinates = object.coordinates, i = -1, n = coordinates.length;
|
||
while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0);
|
||
},
|
||
Polygon: function(object, listener) {
|
||
d3_geo_streamPolygon(object.coordinates, listener);
|
||
},
|
||
MultiPolygon: function(object, listener) {
|
||
var coordinates = object.coordinates, i = -1, n = coordinates.length;
|
||
while (++i < n) d3_geo_streamPolygon(coordinates[i], listener);
|
||
},
|
||
GeometryCollection: function(object, listener) {
|
||
var geometries = object.geometries, i = -1, n = geometries.length;
|
||
while (++i < n) d3_geo_streamGeometry(geometries[i], listener);
|
||
}
|
||
};
|
||
function d3_geo_streamLine(coordinates, listener, closed) {
|
||
var i = -1, n = coordinates.length - closed, coordinate;
|
||
listener.lineStart();
|
||
while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]);
|
||
listener.lineEnd();
|
||
}
|
||
function d3_geo_streamPolygon(coordinates, listener) {
|
||
var i = -1, n = coordinates.length;
|
||
listener.polygonStart();
|
||
while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1);
|
||
listener.polygonEnd();
|
||
}
|
||
d3.geo.area = function(object) {
|
||
d3_geo_areaSum = 0;
|
||
d3.geo.stream(object, d3_geo_area);
|
||
return d3_geo_areaSum;
|
||
};
|
||
var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder();
|
||
var d3_geo_area = {
|
||
sphere: function() {
|
||
d3_geo_areaSum += 4 * π;
|
||
},
|
||
point: d3_noop,
|
||
lineStart: d3_noop,
|
||
lineEnd: d3_noop,
|
||
polygonStart: function() {
|
||
d3_geo_areaRingSum.reset();
|
||
d3_geo_area.lineStart = d3_geo_areaRingStart;
|
||
},
|
||
polygonEnd: function() {
|
||
var area = 2 * d3_geo_areaRingSum;
|
||
d3_geo_areaSum += area < 0 ? 4 * π + area : area;
|
||
d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;
|
||
}
|
||
};
|
||
function d3_geo_areaRingStart() {
|
||
var λ00, φ00, λ0, cosφ0, sinφ0;
|
||
d3_geo_area.point = function(λ, φ) {
|
||
d3_geo_area.point = nextPoint;
|
||
λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4),
|
||
sinφ0 = Math.sin(φ);
|
||
};
|
||
function nextPoint(λ, φ) {
|
||
λ *= d3_radians;
|
||
φ = φ * d3_radians / 2 + π / 4;
|
||
var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ);
|
||
d3_geo_areaRingSum.add(Math.atan2(v, u));
|
||
λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;
|
||
}
|
||
d3_geo_area.lineEnd = function() {
|
||
nextPoint(λ00, φ00);
|
||
};
|
||
}
|
||
function d3_geo_cartesian(spherical) {
|
||
var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ);
|
||
return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ];
|
||
}
|
||
function d3_geo_cartesianDot(a, b) {
|
||
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
||
}
|
||
function d3_geo_cartesianCross(a, b) {
|
||
return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ];
|
||
}
|
||
function d3_geo_cartesianAdd(a, b) {
|
||
a[0] += b[0];
|
||
a[1] += b[1];
|
||
a[2] += b[2];
|
||
}
|
||
function d3_geo_cartesianScale(vector, k) {
|
||
return [ vector[0] * k, vector[1] * k, vector[2] * k ];
|
||
}
|
||
function d3_geo_cartesianNormalize(d) {
|
||
var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
|
||
d[0] /= l;
|
||
d[1] /= l;
|
||
d[2] /= l;
|
||
}
|
||
function d3_geo_spherical(cartesian) {
|
||
return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ];
|
||
}
|
||
function d3_geo_sphericalEqual(a, b) {
|
||
return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε;
|
||
}
|
||
d3.geo.bounds = function() {
|
||
var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range;
|
||
var bound = {
|
||
point: point,
|
||
lineStart: lineStart,
|
||
lineEnd: lineEnd,
|
||
polygonStart: function() {
|
||
bound.point = ringPoint;
|
||
bound.lineStart = ringStart;
|
||
bound.lineEnd = ringEnd;
|
||
dλSum = 0;
|
||
d3_geo_area.polygonStart();
|
||
},
|
||
polygonEnd: function() {
|
||
d3_geo_area.polygonEnd();
|
||
bound.point = point;
|
||
bound.lineStart = lineStart;
|
||
bound.lineEnd = lineEnd;
|
||
if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90;
|
||
range[0] = λ0, range[1] = λ1;
|
||
}
|
||
};
|
||
function point(λ, φ) {
|
||
ranges.push(range = [ λ0 = λ, λ1 = λ ]);
|
||
if (φ < φ0) φ0 = φ;
|
||
if (φ > φ1) φ1 = φ;
|
||
}
|
||
function linePoint(λ, φ) {
|
||
var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]);
|
||
if (p0) {
|
||
var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal);
|
||
d3_geo_cartesianNormalize(inflection);
|
||
inflection = d3_geo_spherical(inflection);
|
||
var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180;
|
||
if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
|
||
var φi = inflection[1] * d3_degrees;
|
||
if (φi > φ1) φ1 = φi;
|
||
} else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
|
||
var φi = -inflection[1] * d3_degrees;
|
||
if (φi < φ0) φ0 = φi;
|
||
} else {
|
||
if (φ < φ0) φ0 = φ;
|
||
if (φ > φ1) φ1 = φ;
|
||
}
|
||
if (antimeridian) {
|
||
if (λ < λ_) {
|
||
if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
|
||
} else {
|
||
if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
|
||
}
|
||
} else {
|
||
if (λ1 >= λ0) {
|
||
if (λ < λ0) λ0 = λ;
|
||
if (λ > λ1) λ1 = λ;
|
||
} else {
|
||
if (λ > λ_) {
|
||
if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
|
||
} else {
|
||
if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
point(λ, φ);
|
||
}
|
||
p0 = p, λ_ = λ;
|
||
}
|
||
function lineStart() {
|
||
bound.point = linePoint;
|
||
}
|
||
function lineEnd() {
|
||
range[0] = λ0, range[1] = λ1;
|
||
bound.point = point;
|
||
p0 = null;
|
||
}
|
||
function ringPoint(λ, φ) {
|
||
if (p0) {
|
||
var dλ = λ - λ_;
|
||
dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ;
|
||
} else λ__ = λ, φ__ = φ;
|
||
d3_geo_area.point(λ, φ);
|
||
linePoint(λ, φ);
|
||
}
|
||
function ringStart() {
|
||
d3_geo_area.lineStart();
|
||
}
|
||
function ringEnd() {
|
||
ringPoint(λ__, φ__);
|
||
d3_geo_area.lineEnd();
|
||
if (abs(dλSum) > ε) λ0 = -(λ1 = 180);
|
||
range[0] = λ0, range[1] = λ1;
|
||
p0 = null;
|
||
}
|
||
function angle(λ0, λ1) {
|
||
return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1;
|
||
}
|
||
function compareRanges(a, b) {
|
||
return a[0] - b[0];
|
||
}
|
||
function withinRange(x, range) {
|
||
return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
|
||
}
|
||
return function(feature) {
|
||
φ1 = λ1 = -(λ0 = φ0 = Infinity);
|
||
ranges = [];
|
||
d3.geo.stream(feature, bound);
|
||
var n = ranges.length;
|
||
if (n) {
|
||
ranges.sort(compareRanges);
|
||
for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) {
|
||
b = ranges[i];
|
||
if (withinRange(b[0], a) || withinRange(b[1], a)) {
|
||
if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
|
||
if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
|
||
} else {
|
||
merged.push(a = b);
|
||
}
|
||
}
|
||
var best = -Infinity, dλ;
|
||
for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) {
|
||
b = merged[i];
|
||
if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1];
|
||
}
|
||
}
|
||
ranges = range = null;
|
||
return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ];
|
||
};
|
||
}();
|
||
d3.geo.centroid = function(object) {
|
||
d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
|
||
d3.geo.stream(object, d3_geo_centroid);
|
||
var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z;
|
||
if (m < ε2) {
|
||
x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1;
|
||
if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0;
|
||
m = x * x + y * y + z * z;
|
||
if (m < ε2) return [ NaN, NaN ];
|
||
}
|
||
return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ];
|
||
};
|
||
var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2;
|
||
var d3_geo_centroid = {
|
||
sphere: d3_noop,
|
||
point: d3_geo_centroidPoint,
|
||
lineStart: d3_geo_centroidLineStart,
|
||
lineEnd: d3_geo_centroidLineEnd,
|
||
polygonStart: function() {
|
||
d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
|
||
},
|
||
polygonEnd: function() {
|
||
d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
|
||
}
|
||
};
|
||
function d3_geo_centroidPoint(λ, φ) {
|
||
λ *= d3_radians;
|
||
var cosφ = Math.cos(φ *= d3_radians);
|
||
d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ));
|
||
}
|
||
function d3_geo_centroidPointXYZ(x, y, z) {
|
||
++d3_geo_centroidW0;
|
||
d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0;
|
||
d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0;
|
||
d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0;
|
||
}
|
||
function d3_geo_centroidLineStart() {
|
||
var x0, y0, z0;
|
||
d3_geo_centroid.point = function(λ, φ) {
|
||
λ *= d3_radians;
|
||
var cosφ = Math.cos(φ *= d3_radians);
|
||
x0 = cosφ * Math.cos(λ);
|
||
y0 = cosφ * Math.sin(λ);
|
||
z0 = Math.sin(φ);
|
||
d3_geo_centroid.point = nextPoint;
|
||
d3_geo_centroidPointXYZ(x0, y0, z0);
|
||
};
|
||
function nextPoint(λ, φ) {
|
||
λ *= d3_radians;
|
||
var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);
|
||
d3_geo_centroidW1 += w;
|
||
d3_geo_centroidX1 += w * (x0 + (x0 = x));
|
||
d3_geo_centroidY1 += w * (y0 + (y0 = y));
|
||
d3_geo_centroidZ1 += w * (z0 + (z0 = z));
|
||
d3_geo_centroidPointXYZ(x0, y0, z0);
|
||
}
|
||
}
|
||
function d3_geo_centroidLineEnd() {
|
||
d3_geo_centroid.point = d3_geo_centroidPoint;
|
||
}
|
||
function d3_geo_centroidRingStart() {
|
||
var λ00, φ00, x0, y0, z0;
|
||
d3_geo_centroid.point = function(λ, φ) {
|
||
λ00 = λ, φ00 = φ;
|
||
d3_geo_centroid.point = nextPoint;
|
||
λ *= d3_radians;
|
||
var cosφ = Math.cos(φ *= d3_radians);
|
||
x0 = cosφ * Math.cos(λ);
|
||
y0 = cosφ * Math.sin(λ);
|
||
z0 = Math.sin(φ);
|
||
d3_geo_centroidPointXYZ(x0, y0, z0);
|
||
};
|
||
d3_geo_centroid.lineEnd = function() {
|
||
nextPoint(λ00, φ00);
|
||
d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
|
||
d3_geo_centroid.point = d3_geo_centroidPoint;
|
||
};
|
||
function nextPoint(λ, φ) {
|
||
λ *= d3_radians;
|
||
var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u);
|
||
d3_geo_centroidX2 += v * cx;
|
||
d3_geo_centroidY2 += v * cy;
|
||
d3_geo_centroidZ2 += v * cz;
|
||
d3_geo_centroidW1 += w;
|
||
d3_geo_centroidX1 += w * (x0 + (x0 = x));
|
||
d3_geo_centroidY1 += w * (y0 + (y0 = y));
|
||
d3_geo_centroidZ1 += w * (z0 + (z0 = z));
|
||
d3_geo_centroidPointXYZ(x0, y0, z0);
|
||
}
|
||
}
|
||
function d3_geo_compose(a, b) {
|
||
function compose(x, y) {
|
||
return x = a(x, y), b(x[0], x[1]);
|
||
}
|
||
if (a.invert && b.invert) compose.invert = function(x, y) {
|
||
return x = b.invert(x, y), x && a.invert(x[0], x[1]);
|
||
};
|
||
return compose;
|
||
}
|
||
function d3_true() {
|
||
return true;
|
||
}
|
||
function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) {
|
||
var subject = [], clip = [];
|
||
segments.forEach(function(segment) {
|
||
if ((n = segment.length - 1) <= 0) return;
|
||
var n, p0 = segment[0], p1 = segment[n];
|
||
if (d3_geo_sphericalEqual(p0, p1)) {
|
||
listener.lineStart();
|
||
for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);
|
||
listener.lineEnd();
|
||
return;
|
||
}
|
||
var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false);
|
||
a.o = b;
|
||
subject.push(a);
|
||
clip.push(b);
|
||
a = new d3_geo_clipPolygonIntersection(p1, segment, null, false);
|
||
b = new d3_geo_clipPolygonIntersection(p1, null, a, true);
|
||
a.o = b;
|
||
subject.push(a);
|
||
clip.push(b);
|
||
});
|
||
clip.sort(compare);
|
||
d3_geo_clipPolygonLinkCircular(subject);
|
||
d3_geo_clipPolygonLinkCircular(clip);
|
||
if (!subject.length) return;
|
||
for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {
|
||
clip[i].e = entry = !entry;
|
||
}
|
||
var start = subject[0], points, point;
|
||
while (1) {
|
||
var current = start, isSubject = true;
|
||
while (current.v) if ((current = current.n) === start) return;
|
||
points = current.z;
|
||
listener.lineStart();
|
||
do {
|
||
current.v = current.o.v = true;
|
||
if (current.e) {
|
||
if (isSubject) {
|
||
for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]);
|
||
} else {
|
||
interpolate(current.x, current.n.x, 1, listener);
|
||
}
|
||
current = current.n;
|
||
} else {
|
||
if (isSubject) {
|
||
points = current.p.z;
|
||
for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]);
|
||
} else {
|
||
interpolate(current.x, current.p.x, -1, listener);
|
||
}
|
||
current = current.p;
|
||
}
|
||
current = current.o;
|
||
points = current.z;
|
||
isSubject = !isSubject;
|
||
} while (!current.v);
|
||
listener.lineEnd();
|
||
}
|
||
}
|
||
function d3_geo_clipPolygonLinkCircular(array) {
|
||
if (!(n = array.length)) return;
|
||
var n, i = 0, a = array[0], b;
|
||
while (++i < n) {
|
||
a.n = b = array[i];
|
||
b.p = a;
|
||
a = b;
|
||
}
|
||
a.n = b = array[0];
|
||
b.p = a;
|
||
}
|
||
function d3_geo_clipPolygonIntersection(point, points, other, entry) {
|
||
this.x = point;
|
||
this.z = points;
|
||
this.o = other;
|
||
this.e = entry;
|
||
this.v = false;
|
||
this.n = this.p = null;
|
||
}
|
||
function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
|
||
return function(rotate, listener) {
|
||
var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]);
|
||
var clip = {
|
||
point: point,
|
||
lineStart: lineStart,
|
||
lineEnd: lineEnd,
|
||
polygonStart: function() {
|
||
clip.point = pointRing;
|
||
clip.lineStart = ringStart;
|
||
clip.lineEnd = ringEnd;
|
||
segments = [];
|
||
polygon = [];
|
||
},
|
||
polygonEnd: function() {
|
||
clip.point = point;
|
||
clip.lineStart = lineStart;
|
||
clip.lineEnd = lineEnd;
|
||
segments = d3.merge(segments);
|
||
var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
|
||
if (segments.length) {
|
||
if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
|
||
d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
|
||
} else if (clipStartInside) {
|
||
if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
|
||
listener.lineStart();
|
||
interpolate(null, null, 1, listener);
|
||
listener.lineEnd();
|
||
}
|
||
if (polygonStarted) listener.polygonEnd(), polygonStarted = false;
|
||
segments = polygon = null;
|
||
},
|
||
sphere: function() {
|
||
listener.polygonStart();
|
||
listener.lineStart();
|
||
interpolate(null, null, 1, listener);
|
||
listener.lineEnd();
|
||
listener.polygonEnd();
|
||
}
|
||
};
|
||
function point(λ, φ) {
|
||
var point = rotate(λ, φ);
|
||
if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ);
|
||
}
|
||
function pointLine(λ, φ) {
|
||
var point = rotate(λ, φ);
|
||
line.point(point[0], point[1]);
|
||
}
|
||
function lineStart() {
|
||
clip.point = pointLine;
|
||
line.lineStart();
|
||
}
|
||
function lineEnd() {
|
||
clip.point = point;
|
||
line.lineEnd();
|
||
}
|
||
var segments;
|
||
var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring;
|
||
function pointRing(λ, φ) {
|
||
ring.push([ λ, φ ]);
|
||
var point = rotate(λ, φ);
|
||
ringListener.point(point[0], point[1]);
|
||
}
|
||
function ringStart() {
|
||
ringListener.lineStart();
|
||
ring = [];
|
||
}
|
||
function ringEnd() {
|
||
pointRing(ring[0][0], ring[0][1]);
|
||
ringListener.lineEnd();
|
||
var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length;
|
||
ring.pop();
|
||
polygon.push(ring);
|
||
ring = null;
|
||
if (!n) return;
|
||
if (clean & 1) {
|
||
segment = ringSegments[0];
|
||
var n = segment.length - 1, i = -1, point;
|
||
if (n > 0) {
|
||
if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
|
||
listener.lineStart();
|
||
while (++i < n) listener.point((point = segment[i])[0], point[1]);
|
||
listener.lineEnd();
|
||
}
|
||
return;
|
||
}
|
||
if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
|
||
segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
|
||
}
|
||
return clip;
|
||
};
|
||
}
|
||
function d3_geo_clipSegmentLength1(segment) {
|
||
return segment.length > 1;
|
||
}
|
||
function d3_geo_clipBufferListener() {
|
||
var lines = [], line;
|
||
return {
|
||
lineStart: function() {
|
||
lines.push(line = []);
|
||
},
|
||
point: function(λ, φ) {
|
||
line.push([ λ, φ ]);
|
||
},
|
||
lineEnd: d3_noop,
|
||
buffer: function() {
|
||
var buffer = lines;
|
||
lines = [];
|
||
line = null;
|
||
return buffer;
|
||
},
|
||
rejoin: function() {
|
||
if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
|
||
}
|
||
};
|
||
}
|
||
function d3_geo_clipSort(a, b) {
|
||
return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]);
|
||
}
|
||
var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]);
|
||
function d3_geo_clipAntimeridianLine(listener) {
|
||
var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean;
|
||
return {
|
||
lineStart: function() {
|
||
listener.lineStart();
|
||
clean = 1;
|
||
},
|
||
point: function(λ1, φ1) {
|
||
var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0);
|
||
if (abs(dλ - π) < ε) {
|
||
listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ);
|
||
listener.point(sλ0, φ0);
|
||
listener.lineEnd();
|
||
listener.lineStart();
|
||
listener.point(sλ1, φ0);
|
||
listener.point(λ1, φ0);
|
||
clean = 0;
|
||
} else if (sλ0 !== sλ1 && dλ >= π) {
|
||
if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;
|
||
if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε;
|
||
φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);
|
||
listener.point(sλ0, φ0);
|
||
listener.lineEnd();
|
||
listener.lineStart();
|
||
listener.point(sλ1, φ0);
|
||
clean = 0;
|
||
}
|
||
listener.point(λ0 = λ1, φ0 = φ1);
|
||
sλ0 = sλ1;
|
||
},
|
||
lineEnd: function() {
|
||
listener.lineEnd();
|
||
λ0 = φ0 = NaN;
|
||
},
|
||
clean: function() {
|
||
return 2 - clean;
|
||
}
|
||
};
|
||
}
|
||
function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {
|
||
var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1);
|
||
return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2;
|
||
}
|
||
function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
|
||
var φ;
|
||
if (from == null) {
|
||
φ = direction * halfπ;
|
||
listener.point(-π, φ);
|
||
listener.point(0, φ);
|
||
listener.point(π, φ);
|
||
listener.point(π, 0);
|
||
listener.point(π, -φ);
|
||
listener.point(0, -φ);
|
||
listener.point(-π, -φ);
|
||
listener.point(-π, 0);
|
||
listener.point(-π, φ);
|
||
} else if (abs(from[0] - to[0]) > ε) {
|
||
var s = from[0] < to[0] ? π : -π;
|
||
φ = direction * s / 2;
|
||
listener.point(-s, φ);
|
||
listener.point(0, φ);
|
||
listener.point(s, φ);
|
||
} else {
|
||
listener.point(to[0], to[1]);
|
||
}
|
||
}
|
||
function d3_geo_pointInPolygon(point, polygon) {
|
||
var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0;
|
||
d3_geo_areaRingSum.reset();
|
||
for (var i = 0, n = polygon.length; i < n; ++i) {
|
||
var ring = polygon[i], m = ring.length;
|
||
if (!m) continue;
|
||
var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1;
|
||
while (true) {
|
||
if (j === m) j = 0;
|
||
point = ring[j];
|
||
var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ;
|
||
d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ)));
|
||
polarAngle += antimeridian ? dλ + sdλ * τ : dλ;
|
||
if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) {
|
||
var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point));
|
||
d3_geo_cartesianNormalize(arc);
|
||
var intersection = d3_geo_cartesianCross(meridianNormal, arc);
|
||
d3_geo_cartesianNormalize(intersection);
|
||
var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]);
|
||
if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) {
|
||
winding += antimeridian ^ dλ >= 0 ? 1 : -1;
|
||
}
|
||
}
|
||
if (!j++) break;
|
||
λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point;
|
||
}
|
||
}
|
||
return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < 0) ^ winding & 1;
|
||
}
|
||
function d3_geo_clipCircle(radius) {
|
||
var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians);
|
||
return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]);
|
||
function visible(λ, φ) {
|
||
return Math.cos(λ) * Math.cos(φ) > cr;
|
||
}
|
||
function clipLine(listener) {
|
||
var point0, c0, v0, v00, clean;
|
||
return {
|
||
lineStart: function() {
|
||
v00 = v0 = false;
|
||
clean = 1;
|
||
},
|
||
point: function(λ, φ) {
|
||
var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0;
|
||
if (!point0 && (v00 = v0 = v)) listener.lineStart();
|
||
if (v !== v0) {
|
||
point2 = intersect(point0, point1);
|
||
if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) {
|
||
point1[0] += ε;
|
||
point1[1] += ε;
|
||
v = visible(point1[0], point1[1]);
|
||
}
|
||
}
|
||
if (v !== v0) {
|
||
clean = 0;
|
||
if (v) {
|
||
listener.lineStart();
|
||
point2 = intersect(point1, point0);
|
||
listener.point(point2[0], point2[1]);
|
||
} else {
|
||
point2 = intersect(point0, point1);
|
||
listener.point(point2[0], point2[1]);
|
||
listener.lineEnd();
|
||
}
|
||
point0 = point2;
|
||
} else if (notHemisphere && point0 && smallRadius ^ v) {
|
||
var t;
|
||
if (!(c & c0) && (t = intersect(point1, point0, true))) {
|
||
clean = 0;
|
||
if (smallRadius) {
|
||
listener.lineStart();
|
||
listener.point(t[0][0], t[0][1]);
|
||
listener.point(t[1][0], t[1][1]);
|
||
listener.lineEnd();
|
||
} else {
|
||
listener.point(t[1][0], t[1][1]);
|
||
listener.lineEnd();
|
||
listener.lineStart();
|
||
listener.point(t[0][0], t[0][1]);
|
||
}
|
||
}
|
||
}
|
||
if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) {
|
||
listener.point(point1[0], point1[1]);
|
||
}
|
||
point0 = point1, v0 = v, c0 = c;
|
||
},
|
||
lineEnd: function() {
|
||
if (v0) listener.lineEnd();
|
||
point0 = null;
|
||
},
|
||
clean: function() {
|
||
return clean | (v00 && v0) << 1;
|
||
}
|
||
};
|
||
}
|
||
function intersect(a, b, two) {
|
||
var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b);
|
||
var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2;
|
||
if (!determinant) return !two && a;
|
||
var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2);
|
||
d3_geo_cartesianAdd(A, B);
|
||
var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1);
|
||
if (t2 < 0) return;
|
||
var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu);
|
||
d3_geo_cartesianAdd(q, A);
|
||
q = d3_geo_spherical(q);
|
||
if (!two) return q;
|
||
var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z;
|
||
if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z;
|
||
var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε;
|
||
if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z;
|
||
if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) {
|
||
var q1 = d3_geo_cartesianScale(u, (-w + t) / uu);
|
||
d3_geo_cartesianAdd(q1, A);
|
||
return [ q, d3_geo_spherical(q1) ];
|
||
}
|
||
}
|
||
function code(λ, φ) {
|
||
var r = smallRadius ? radius : π - radius, code = 0;
|
||
if (λ < -r) code |= 1; else if (λ > r) code |= 2;
|
||
if (φ < -r) code |= 4; else if (φ > r) code |= 8;
|
||
return code;
|
||
}
|
||
}
|
||
function d3_geom_clipLine(x0, y0, x1, y1) {
|
||
return function(line) {
|
||
var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r;
|
||
r = x0 - ax;
|
||
if (!dx && r > 0) return;
|
||
r /= dx;
|
||
if (dx < 0) {
|
||
if (r < t0) return;
|
||
if (r < t1) t1 = r;
|
||
} else if (dx > 0) {
|
||
if (r > t1) return;
|
||
if (r > t0) t0 = r;
|
||
}
|
||
r = x1 - ax;
|
||
if (!dx && r < 0) return;
|
||
r /= dx;
|
||
if (dx < 0) {
|
||
if (r > t1) return;
|
||
if (r > t0) t0 = r;
|
||
} else if (dx > 0) {
|
||
if (r < t0) return;
|
||
if (r < t1) t1 = r;
|
||
}
|
||
r = y0 - ay;
|
||
if (!dy && r > 0) return;
|
||
r /= dy;
|
||
if (dy < 0) {
|
||
if (r < t0) return;
|
||
if (r < t1) t1 = r;
|
||
} else if (dy > 0) {
|
||
if (r > t1) return;
|
||
if (r > t0) t0 = r;
|
||
}
|
||
r = y1 - ay;
|
||
if (!dy && r < 0) return;
|
||
r /= dy;
|
||
if (dy < 0) {
|
||
if (r > t1) return;
|
||
if (r > t0) t0 = r;
|
||
} else if (dy > 0) {
|
||
if (r < t0) return;
|
||
if (r < t1) t1 = r;
|
||
}
|
||
if (t0 > 0) line.a = {
|
||
x: ax + t0 * dx,
|
||
y: ay + t0 * dy
|
||
};
|
||
if (t1 < 1) line.b = {
|
||
x: ax + t1 * dx,
|
||
y: ay + t1 * dy
|
||
};
|
||
return line;
|
||
};
|
||
}
|
||
var d3_geo_clipExtentMAX = 1e9;
|
||
d3.geo.clipExtent = function() {
|
||
var x0, y0, x1, y1, stream, clip, clipExtent = {
|
||
stream: function(output) {
|
||
if (stream) stream.valid = false;
|
||
stream = clip(output);
|
||
stream.valid = true;
|
||
return stream;
|
||
},
|
||
extent: function(_) {
|
||
if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
|
||
clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]);
|
||
if (stream) stream.valid = false, stream = null;
|
||
return clipExtent;
|
||
}
|
||
};
|
||
return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]);
|
||
};
|
||
function d3_geo_clipExtent(x0, y0, x1, y1) {
|
||
return function(listener) {
|
||
var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring;
|
||
var clip = {
|
||
point: point,
|
||
lineStart: lineStart,
|
||
lineEnd: lineEnd,
|
||
polygonStart: function() {
|
||
listener = bufferListener;
|
||
segments = [];
|
||
polygon = [];
|
||
clean = true;
|
||
},
|
||
polygonEnd: function() {
|
||
listener = listener_;
|
||
segments = d3.merge(segments);
|
||
var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length;
|
||
if (inside || visible) {
|
||
listener.polygonStart();
|
||
if (inside) {
|
||
listener.lineStart();
|
||
interpolate(null, null, 1, listener);
|
||
listener.lineEnd();
|
||
}
|
||
if (visible) {
|
||
d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener);
|
||
}
|
||
listener.polygonEnd();
|
||
}
|
||
segments = polygon = ring = null;
|
||
}
|
||
};
|
||
function insidePolygon(p) {
|
||
var wn = 0, n = polygon.length, y = p[1];
|
||
for (var i = 0; i < n; ++i) {
|
||
for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) {
|
||
b = v[j];
|
||
if (a[1] <= y) {
|
||
if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn;
|
||
} else {
|
||
if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn;
|
||
}
|
||
a = b;
|
||
}
|
||
}
|
||
return wn !== 0;
|
||
}
|
||
function interpolate(from, to, direction, listener) {
|
||
var a = 0, a1 = 0;
|
||
if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) {
|
||
do {
|
||
listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
|
||
} while ((a = (a + direction + 4) % 4) !== a1);
|
||
} else {
|
||
listener.point(to[0], to[1]);
|
||
}
|
||
}
|
||
function pointVisible(x, y) {
|
||
return x0 <= x && x <= x1 && y0 <= y && y <= y1;
|
||
}
|
||
function point(x, y) {
|
||
if (pointVisible(x, y)) listener.point(x, y);
|
||
}
|
||
var x__, y__, v__, x_, y_, v_, first, clean;
|
||
function lineStart() {
|
||
clip.point = linePoint;
|
||
if (polygon) polygon.push(ring = []);
|
||
first = true;
|
||
v_ = false;
|
||
x_ = y_ = NaN;
|
||
}
|
||
function lineEnd() {
|
||
if (segments) {
|
||
linePoint(x__, y__);
|
||
if (v__ && v_) bufferListener.rejoin();
|
||
segments.push(bufferListener.buffer());
|
||
}
|
||
clip.point = point;
|
||
if (v_) listener.lineEnd();
|
||
}
|
||
function linePoint(x, y) {
|
||
x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x));
|
||
y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y));
|
||
var v = pointVisible(x, y);
|
||
if (polygon) ring.push([ x, y ]);
|
||
if (first) {
|
||
x__ = x, y__ = y, v__ = v;
|
||
first = false;
|
||
if (v) {
|
||
listener.lineStart();
|
||
listener.point(x, y);
|
||
}
|
||
} else {
|
||
if (v && v_) listener.point(x, y); else {
|
||
var l = {
|
||
a: {
|
||
x: x_,
|
||
y: y_
|
||
},
|
||
b: {
|
||
x: x,
|
||
y: y
|
||
}
|
||
};
|
||
if (clipLine(l)) {
|
||
if (!v_) {
|
||
listener.lineStart();
|
||
listener.point(l.a.x, l.a.y);
|
||
}
|
||
listener.point(l.b.x, l.b.y);
|
||
if (!v) listener.lineEnd();
|
||
clean = false;
|
||
} else if (v) {
|
||
listener.lineStart();
|
||
listener.point(x, y);
|
||
clean = false;
|
||
}
|
||
}
|
||
}
|
||
x_ = x, y_ = y, v_ = v;
|
||
}
|
||
return clip;
|
||
};
|
||
function corner(p, direction) {
|
||
return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2;
|
||
}
|
||
function compare(a, b) {
|
||
return comparePoints(a.x, b.x);
|
||
}
|
||
function comparePoints(a, b) {
|
||
var ca = corner(a, 1), cb = corner(b, 1);
|
||
return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0];
|
||
}
|
||
}
|
||
function d3_geo_conic(projectAt) {
|
||
var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1);
|
||
p.parallels = function(_) {
|
||
if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ];
|
||
return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180);
|
||
};
|
||
return p;
|
||
}
|
||
function d3_geo_conicEqualArea(φ0, φ1) {
|
||
var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n;
|
||
function forward(λ, φ) {
|
||
var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;
|
||
return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ];
|
||
}
|
||
forward.invert = function(x, y) {
|
||
var ρ0_y = ρ0 - y;
|
||
return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ];
|
||
};
|
||
return forward;
|
||
}
|
||
(d3.geo.conicEqualArea = function() {
|
||
return d3_geo_conic(d3_geo_conicEqualArea);
|
||
}).raw = d3_geo_conicEqualArea;
|
||
d3.geo.albers = function() {
|
||
return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070);
|
||
};
|
||
d3.geo.albersUsa = function() {
|
||
var lower48 = d3.geo.albers();
|
||
var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]);
|
||
var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]);
|
||
var point, pointStream = {
|
||
point: function(x, y) {
|
||
point = [ x, y ];
|
||
}
|
||
}, lower48Point, alaskaPoint, hawaiiPoint;
|
||
function albersUsa(coordinates) {
|
||
var x = coordinates[0], y = coordinates[1];
|
||
point = null;
|
||
(lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y);
|
||
return point;
|
||
}
|
||
albersUsa.invert = function(coordinates) {
|
||
var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k;
|
||
return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates);
|
||
};
|
||
albersUsa.stream = function(stream) {
|
||
var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream);
|
||
return {
|
||
point: function(x, y) {
|
||
lower48Stream.point(x, y);
|
||
alaskaStream.point(x, y);
|
||
hawaiiStream.point(x, y);
|
||
},
|
||
sphere: function() {
|
||
lower48Stream.sphere();
|
||
alaskaStream.sphere();
|
||
hawaiiStream.sphere();
|
||
},
|
||
lineStart: function() {
|
||
lower48Stream.lineStart();
|
||
alaskaStream.lineStart();
|
||
hawaiiStream.lineStart();
|
||
},
|
||
lineEnd: function() {
|
||
lower48Stream.lineEnd();
|
||
alaskaStream.lineEnd();
|
||
hawaiiStream.lineEnd();
|
||
},
|
||
polygonStart: function() {
|
||
lower48Stream.polygonStart();
|
||
alaskaStream.polygonStart();
|
||
hawaiiStream.polygonStart();
|
||
},
|
||
polygonEnd: function() {
|
||
lower48Stream.polygonEnd();
|
||
alaskaStream.polygonEnd();
|
||
hawaiiStream.polygonEnd();
|
||
}
|
||
};
|
||
};
|
||
albersUsa.precision = function(_) {
|
||
if (!arguments.length) return lower48.precision();
|
||
lower48.precision(_);
|
||
alaska.precision(_);
|
||
hawaii.precision(_);
|
||
return albersUsa;
|
||
};
|
||
albersUsa.scale = function(_) {
|
||
if (!arguments.length) return lower48.scale();
|
||
lower48.scale(_);
|
||
alaska.scale(_ * .35);
|
||
hawaii.scale(_);
|
||
return albersUsa.translate(lower48.translate());
|
||
};
|
||
albersUsa.translate = function(_) {
|
||
if (!arguments.length) return lower48.translate();
|
||
var k = lower48.scale(), x = +_[0], y = +_[1];
|
||
lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point;
|
||
alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
|
||
hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
|
||
return albersUsa;
|
||
};
|
||
return albersUsa.scale(1070);
|
||
};
|
||
var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {
|
||
point: d3_noop,
|
||
lineStart: d3_noop,
|
||
lineEnd: d3_noop,
|
||
polygonStart: function() {
|
||
d3_geo_pathAreaPolygon = 0;
|
||
d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;
|
||
},
|
||
polygonEnd: function() {
|
||
d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;
|
||
d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2);
|
||
}
|
||
};
|
||
function d3_geo_pathAreaRingStart() {
|
||
var x00, y00, x0, y0;
|
||
d3_geo_pathArea.point = function(x, y) {
|
||
d3_geo_pathArea.point = nextPoint;
|
||
x00 = x0 = x, y00 = y0 = y;
|
||
};
|
||
function nextPoint(x, y) {
|
||
d3_geo_pathAreaPolygon += y0 * x - x0 * y;
|
||
x0 = x, y0 = y;
|
||
}
|
||
d3_geo_pathArea.lineEnd = function() {
|
||
nextPoint(x00, y00);
|
||
};
|
||
}
|
||
var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1;
|
||
var d3_geo_pathBounds = {
|
||
point: d3_geo_pathBoundsPoint,
|
||
lineStart: d3_noop,
|
||
lineEnd: d3_noop,
|
||
polygonStart: d3_noop,
|
||
polygonEnd: d3_noop
|
||
};
|
||
function d3_geo_pathBoundsPoint(x, y) {
|
||
if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x;
|
||
if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x;
|
||
if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y;
|
||
if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y;
|
||
}
|
||
function d3_geo_pathBuffer() {
|
||
var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = [];
|
||
var stream = {
|
||
point: point,
|
||
lineStart: function() {
|
||
stream.point = pointLineStart;
|
||
},
|
||
lineEnd: lineEnd,
|
||
polygonStart: function() {
|
||
stream.lineEnd = lineEndPolygon;
|
||
},
|
||
polygonEnd: function() {
|
||
stream.lineEnd = lineEnd;
|
||
stream.point = point;
|
||
},
|
||
pointRadius: function(_) {
|
||
pointCircle = d3_geo_pathBufferCircle(_);
|
||
return stream;
|
||
},
|
||
result: function() {
|
||
if (buffer.length) {
|
||
var result = buffer.join("");
|
||
buffer = [];
|
||
return result;
|
||
}
|
||
}
|
||
};
|
||
function point(x, y) {
|
||
buffer.push("M", x, ",", y, pointCircle);
|
||
}
|
||
function pointLineStart(x, y) {
|
||
buffer.push("M", x, ",", y);
|
||
stream.point = pointLine;
|
||
}
|
||
function pointLine(x, y) {
|
||
buffer.push("L", x, ",", y);
|
||
}
|
||
function lineEnd() {
|
||
stream.point = point;
|
||
}
|
||
function lineEndPolygon() {
|
||
buffer.push("Z");
|
||
}
|
||
return stream;
|
||
}
|
||
function d3_geo_pathBufferCircle(radius) {
|
||
return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z";
|
||
}
|
||
var d3_geo_pathCentroid = {
|
||
point: d3_geo_pathCentroidPoint,
|
||
lineStart: d3_geo_pathCentroidLineStart,
|
||
lineEnd: d3_geo_pathCentroidLineEnd,
|
||
polygonStart: function() {
|
||
d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;
|
||
},
|
||
polygonEnd: function() {
|
||
d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
|
||
d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;
|
||
d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;
|
||
}
|
||
};
|
||
function d3_geo_pathCentroidPoint(x, y) {
|
||
d3_geo_centroidX0 += x;
|
||
d3_geo_centroidY0 += y;
|
||
++d3_geo_centroidZ0;
|
||
}
|
||
function d3_geo_pathCentroidLineStart() {
|
||
var x0, y0;
|
||
d3_geo_pathCentroid.point = function(x, y) {
|
||
d3_geo_pathCentroid.point = nextPoint;
|
||
d3_geo_pathCentroidPoint(x0 = x, y0 = y);
|
||
};
|
||
function nextPoint(x, y) {
|
||
var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
|
||
d3_geo_centroidX1 += z * (x0 + x) / 2;
|
||
d3_geo_centroidY1 += z * (y0 + y) / 2;
|
||
d3_geo_centroidZ1 += z;
|
||
d3_geo_pathCentroidPoint(x0 = x, y0 = y);
|
||
}
|
||
}
|
||
function d3_geo_pathCentroidLineEnd() {
|
||
d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
|
||
}
|
||
function d3_geo_pathCentroidRingStart() {
|
||
var x00, y00, x0, y0;
|
||
d3_geo_pathCentroid.point = function(x, y) {
|
||
d3_geo_pathCentroid.point = nextPoint;
|
||
d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y);
|
||
};
|
||
function nextPoint(x, y) {
|
||
var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
|
||
d3_geo_centroidX1 += z * (x0 + x) / 2;
|
||
d3_geo_centroidY1 += z * (y0 + y) / 2;
|
||
d3_geo_centroidZ1 += z;
|
||
z = y0 * x - x0 * y;
|
||
d3_geo_centroidX2 += z * (x0 + x);
|
||
d3_geo_centroidY2 += z * (y0 + y);
|
||
d3_geo_centroidZ2 += z * 3;
|
||
d3_geo_pathCentroidPoint(x0 = x, y0 = y);
|
||
}
|
||
d3_geo_pathCentroid.lineEnd = function() {
|
||
nextPoint(x00, y00);
|
||
};
|
||
}
|
||
function d3_geo_pathContext(context) {
|
||
var pointRadius = 4.5;
|
||
var stream = {
|
||
point: point,
|
||
lineStart: function() {
|
||
stream.point = pointLineStart;
|
||
},
|
||
lineEnd: lineEnd,
|
||
polygonStart: function() {
|
||
stream.lineEnd = lineEndPolygon;
|
||
},
|
||
polygonEnd: function() {
|
||
stream.lineEnd = lineEnd;
|
||
stream.point = point;
|
||
},
|
||
pointRadius: function(_) {
|
||
pointRadius = _;
|
||
return stream;
|
||
},
|
||
result: d3_noop
|
||
};
|
||
function point(x, y) {
|
||
context.moveTo(x + pointRadius, y);
|
||
context.arc(x, y, pointRadius, 0, τ);
|
||
}
|
||
function pointLineStart(x, y) {
|
||
context.moveTo(x, y);
|
||
stream.point = pointLine;
|
||
}
|
||
function pointLine(x, y) {
|
||
context.lineTo(x, y);
|
||
}
|
||
function lineEnd() {
|
||
stream.point = point;
|
||
}
|
||
function lineEndPolygon() {
|
||
context.closePath();
|
||
}
|
||
return stream;
|
||
}
|
||
function d3_geo_resample(project) {
|
||
var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16;
|
||
function resample(stream) {
|
||
return (maxDepth ? resampleRecursive : resampleNone)(stream);
|
||
}
|
||
function resampleNone(stream) {
|
||
return d3_geo_transformPoint(stream, function(x, y) {
|
||
x = project(x, y);
|
||
stream.point(x[0], x[1]);
|
||
});
|
||
}
|
||
function resampleRecursive(stream) {
|
||
var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0;
|
||
var resample = {
|
||
point: point,
|
||
lineStart: lineStart,
|
||
lineEnd: lineEnd,
|
||
polygonStart: function() {
|
||
stream.polygonStart();
|
||
resample.lineStart = ringStart;
|
||
},
|
||
polygonEnd: function() {
|
||
stream.polygonEnd();
|
||
resample.lineStart = lineStart;
|
||
}
|
||
};
|
||
function point(x, y) {
|
||
x = project(x, y);
|
||
stream.point(x[0], x[1]);
|
||
}
|
||
function lineStart() {
|
||
x0 = NaN;
|
||
resample.point = linePoint;
|
||
stream.lineStart();
|
||
}
|
||
function linePoint(λ, φ) {
|
||
var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ);
|
||
resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
|
||
stream.point(x0, y0);
|
||
}
|
||
function lineEnd() {
|
||
resample.point = point;
|
||
stream.lineEnd();
|
||
}
|
||
function ringStart() {
|
||
lineStart();
|
||
resample.point = ringPoint;
|
||
resample.lineEnd = ringEnd;
|
||
}
|
||
function ringPoint(λ, φ) {
|
||
linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
|
||
resample.point = linePoint;
|
||
}
|
||
function ringEnd() {
|
||
resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream);
|
||
resample.lineEnd = lineEnd;
|
||
lineEnd();
|
||
}
|
||
return resample;
|
||
}
|
||
function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) {
|
||
var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy;
|
||
if (d2 > 4 * δ2 && depth--) {
|
||
var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2;
|
||
if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) {
|
||
resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream);
|
||
stream.point(x2, y2);
|
||
resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream);
|
||
}
|
||
}
|
||
}
|
||
resample.precision = function(_) {
|
||
if (!arguments.length) return Math.sqrt(δ2);
|
||
maxDepth = (δ2 = _ * _) > 0 && 16;
|
||
return resample;
|
||
};
|
||
return resample;
|
||
}
|
||
d3.geo.path = function() {
|
||
var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream;
|
||
function path(object) {
|
||
if (object) {
|
||
if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
|
||
if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream);
|
||
d3.geo.stream(object, cacheStream);
|
||
}
|
||
return contextStream.result();
|
||
}
|
||
path.area = function(object) {
|
||
d3_geo_pathAreaSum = 0;
|
||
d3.geo.stream(object, projectStream(d3_geo_pathArea));
|
||
return d3_geo_pathAreaSum;
|
||
};
|
||
path.centroid = function(object) {
|
||
d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
|
||
d3.geo.stream(object, projectStream(d3_geo_pathCentroid));
|
||
return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ];
|
||
};
|
||
path.bounds = function(object) {
|
||
d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity);
|
||
d3.geo.stream(object, projectStream(d3_geo_pathBounds));
|
||
return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ];
|
||
};
|
||
path.projection = function(_) {
|
||
if (!arguments.length) return projection;
|
||
projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;
|
||
return reset();
|
||
};
|
||
path.context = function(_) {
|
||
if (!arguments.length) return context;
|
||
contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_);
|
||
if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
|
||
return reset();
|
||
};
|
||
path.pointRadius = function(_) {
|
||
if (!arguments.length) return pointRadius;
|
||
pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
|
||
return path;
|
||
};
|
||
function reset() {
|
||
cacheStream = null;
|
||
return path;
|
||
}
|
||
return path.projection(d3.geo.albersUsa()).context(null);
|
||
};
|
||
function d3_geo_pathProjectStream(project) {
|
||
var resample = d3_geo_resample(function(x, y) {
|
||
return project([ x * d3_degrees, y * d3_degrees ]);
|
||
});
|
||
return function(stream) {
|
||
return d3_geo_projectionRadians(resample(stream));
|
||
};
|
||
}
|
||
d3.geo.transform = function(methods) {
|
||
return {
|
||
stream: function(stream) {
|
||
var transform = new d3_geo_transform(stream);
|
||
for (var k in methods) transform[k] = methods[k];
|
||
return transform;
|
||
}
|
||
};
|
||
};
|
||
function d3_geo_transform(stream) {
|
||
this.stream = stream;
|
||
}
|
||
d3_geo_transform.prototype = {
|
||
point: function(x, y) {
|
||
this.stream.point(x, y);
|
||
},
|
||
sphere: function() {
|
||
this.stream.sphere();
|
||
},
|
||
lineStart: function() {
|
||
this.stream.lineStart();
|
||
},
|
||
lineEnd: function() {
|
||
this.stream.lineEnd();
|
||
},
|
||
polygonStart: function() {
|
||
this.stream.polygonStart();
|
||
},
|
||
polygonEnd: function() {
|
||
this.stream.polygonEnd();
|
||
}
|
||
};
|
||
function d3_geo_transformPoint(stream, point) {
|
||
return {
|
||
point: point,
|
||
sphere: function() {
|
||
stream.sphere();
|
||
},
|
||
lineStart: function() {
|
||
stream.lineStart();
|
||
},
|
||
lineEnd: function() {
|
||
stream.lineEnd();
|
||
},
|
||
polygonStart: function() {
|
||
stream.polygonStart();
|
||
},
|
||
polygonEnd: function() {
|
||
stream.polygonEnd();
|
||
}
|
||
};
|
||
}
|
||
d3.geo.projection = d3_geo_projection;
|
||
d3.geo.projectionMutator = d3_geo_projectionMutator;
|
||
function d3_geo_projection(project) {
|
||
return d3_geo_projectionMutator(function() {
|
||
return project;
|
||
})();
|
||
}
|
||
function d3_geo_projectionMutator(projectAt) {
|
||
var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) {
|
||
x = project(x, y);
|
||
return [ x[0] * k + δx, δy - x[1] * k ];
|
||
}), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream;
|
||
function projection(point) {
|
||
point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
|
||
return [ point[0] * k + δx, δy - point[1] * k ];
|
||
}
|
||
function invert(point) {
|
||
point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);
|
||
return point && [ point[0] * d3_degrees, point[1] * d3_degrees ];
|
||
}
|
||
projection.stream = function(output) {
|
||
if (stream) stream.valid = false;
|
||
stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output))));
|
||
stream.valid = true;
|
||
return stream;
|
||
};
|
||
projection.clipAngle = function(_) {
|
||
if (!arguments.length) return clipAngle;
|
||
preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);
|
||
return invalidate();
|
||
};
|
||
projection.clipExtent = function(_) {
|
||
if (!arguments.length) return clipExtent;
|
||
clipExtent = _;
|
||
postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity;
|
||
return invalidate();
|
||
};
|
||
projection.scale = function(_) {
|
||
if (!arguments.length) return k;
|
||
k = +_;
|
||
return reset();
|
||
};
|
||
projection.translate = function(_) {
|
||
if (!arguments.length) return [ x, y ];
|
||
x = +_[0];
|
||
y = +_[1];
|
||
return reset();
|
||
};
|
||
projection.center = function(_) {
|
||
if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ];
|
||
λ = _[0] % 360 * d3_radians;
|
||
φ = _[1] % 360 * d3_radians;
|
||
return reset();
|
||
};
|
||
projection.rotate = function(_) {
|
||
if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ];
|
||
δλ = _[0] % 360 * d3_radians;
|
||
δφ = _[1] % 360 * d3_radians;
|
||
δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;
|
||
return reset();
|
||
};
|
||
d3.rebind(projection, projectResample, "precision");
|
||
function reset() {
|
||
projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
|
||
var center = project(λ, φ);
|
||
δx = x - center[0] * k;
|
||
δy = y + center[1] * k;
|
||
return invalidate();
|
||
}
|
||
function invalidate() {
|
||
if (stream) stream.valid = false, stream = null;
|
||
return projection;
|
||
}
|
||
return function() {
|
||
project = projectAt.apply(this, arguments);
|
||
projection.invert = project.invert && invert;
|
||
return reset();
|
||
};
|
||
}
|
||
function d3_geo_projectionRadians(stream) {
|
||
return d3_geo_transformPoint(stream, function(x, y) {
|
||
stream.point(x * d3_radians, y * d3_radians);
|
||
});
|
||
}
|
||
function d3_geo_equirectangular(λ, φ) {
|
||
return [ λ, φ ];
|
||
}
|
||
(d3.geo.equirectangular = function() {
|
||
return d3_geo_projection(d3_geo_equirectangular);
|
||
}).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;
|
||
d3.geo.rotation = function(rotate) {
|
||
rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0);
|
||
function forward(coordinates) {
|
||
coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
|
||
return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
|
||
}
|
||
forward.invert = function(coordinates) {
|
||
coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
|
||
return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
|
||
};
|
||
return forward;
|
||
};
|
||
function d3_geo_identityRotation(λ, φ) {
|
||
return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];
|
||
}
|
||
d3_geo_identityRotation.invert = d3_geo_equirectangular;
|
||
function d3_geo_rotation(δλ, δφ, δγ) {
|
||
return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation;
|
||
}
|
||
function d3_geo_forwardRotationλ(δλ) {
|
||
return function(λ, φ) {
|
||
return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];
|
||
};
|
||
}
|
||
function d3_geo_rotationλ(δλ) {
|
||
var rotation = d3_geo_forwardRotationλ(δλ);
|
||
rotation.invert = d3_geo_forwardRotationλ(-δλ);
|
||
return rotation;
|
||
}
|
||
function d3_geo_rotationφγ(δφ, δγ) {
|
||
var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ);
|
||
function rotation(λ, φ) {
|
||
var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ;
|
||
return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ];
|
||
}
|
||
rotation.invert = function(λ, φ) {
|
||
var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ;
|
||
return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ];
|
||
};
|
||
return rotation;
|
||
}
|
||
d3.geo.circle = function() {
|
||
var origin = [ 0, 0 ], angle, precision = 6, interpolate;
|
||
function circle() {
|
||
var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = [];
|
||
interpolate(null, null, 1, {
|
||
point: function(x, y) {
|
||
ring.push(x = rotate(x, y));
|
||
x[0] *= d3_degrees, x[1] *= d3_degrees;
|
||
}
|
||
});
|
||
return {
|
||
type: "Polygon",
|
||
coordinates: [ ring ]
|
||
};
|
||
}
|
||
circle.origin = function(x) {
|
||
if (!arguments.length) return origin;
|
||
origin = x;
|
||
return circle;
|
||
};
|
||
circle.angle = function(x) {
|
||
if (!arguments.length) return angle;
|
||
interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);
|
||
return circle;
|
||
};
|
||
circle.precision = function(_) {
|
||
if (!arguments.length) return precision;
|
||
interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);
|
||
return circle;
|
||
};
|
||
return circle.angle(90);
|
||
};
|
||
function d3_geo_circleInterpolate(radius, precision) {
|
||
var cr = Math.cos(radius), sr = Math.sin(radius);
|
||
return function(from, to, direction, listener) {
|
||
var step = direction * precision;
|
||
if (from != null) {
|
||
from = d3_geo_circleAngle(cr, from);
|
||
to = d3_geo_circleAngle(cr, to);
|
||
if (direction > 0 ? from < to : from > to) from += direction * τ;
|
||
} else {
|
||
from = radius + direction * τ;
|
||
to = radius - .5 * step;
|
||
}
|
||
for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) {
|
||
listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]);
|
||
}
|
||
};
|
||
}
|
||
function d3_geo_circleAngle(cr, point) {
|
||
var a = d3_geo_cartesian(point);
|
||
a[0] -= cr;
|
||
d3_geo_cartesianNormalize(a);
|
||
var angle = d3_acos(-a[1]);
|
||
return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);
|
||
}
|
||
d3.geo.distance = function(a, b) {
|
||
var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t;
|
||
return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ);
|
||
};
|
||
d3.geo.graticule = function() {
|
||
var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5;
|
||
function graticule() {
|
||
return {
|
||
type: "MultiLineString",
|
||
coordinates: lines()
|
||
};
|
||
}
|
||
function lines() {
|
||
return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) {
|
||
return abs(x % DX) > ε;
|
||
}).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) {
|
||
return abs(y % DY) > ε;
|
||
}).map(y));
|
||
}
|
||
graticule.lines = function() {
|
||
return lines().map(function(coordinates) {
|
||
return {
|
||
type: "LineString",
|
||
coordinates: coordinates
|
||
};
|
||
});
|
||
};
|
||
graticule.outline = function() {
|
||
return {
|
||
type: "Polygon",
|
||
coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ]
|
||
};
|
||
};
|
||
graticule.extent = function(_) {
|
||
if (!arguments.length) return graticule.minorExtent();
|
||
return graticule.majorExtent(_).minorExtent(_);
|
||
};
|
||
graticule.majorExtent = function(_) {
|
||
if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ];
|
||
X0 = +_[0][0], X1 = +_[1][0];
|
||
Y0 = +_[0][1], Y1 = +_[1][1];
|
||
if (X0 > X1) _ = X0, X0 = X1, X1 = _;
|
||
if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
|
||
return graticule.precision(precision);
|
||
};
|
||
graticule.minorExtent = function(_) {
|
||
if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
|
||
x0 = +_[0][0], x1 = +_[1][0];
|
||
y0 = +_[0][1], y1 = +_[1][1];
|
||
if (x0 > x1) _ = x0, x0 = x1, x1 = _;
|
||
if (y0 > y1) _ = y0, y0 = y1, y1 = _;
|
||
return graticule.precision(precision);
|
||
};
|
||
graticule.step = function(_) {
|
||
if (!arguments.length) return graticule.minorStep();
|
||
return graticule.majorStep(_).minorStep(_);
|
||
};
|
||
graticule.majorStep = function(_) {
|
||
if (!arguments.length) return [ DX, DY ];
|
||
DX = +_[0], DY = +_[1];
|
||
return graticule;
|
||
};
|
||
graticule.minorStep = function(_) {
|
||
if (!arguments.length) return [ dx, dy ];
|
||
dx = +_[0], dy = +_[1];
|
||
return graticule;
|
||
};
|
||
graticule.precision = function(_) {
|
||
if (!arguments.length) return precision;
|
||
precision = +_;
|
||
x = d3_geo_graticuleX(y0, y1, 90);
|
||
y = d3_geo_graticuleY(x0, x1, precision);
|
||
X = d3_geo_graticuleX(Y0, Y1, 90);
|
||
Y = d3_geo_graticuleY(X0, X1, precision);
|
||
return graticule;
|
||
};
|
||
return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]);
|
||
};
|
||
function d3_geo_graticuleX(y0, y1, dy) {
|
||
var y = d3.range(y0, y1 - ε, dy).concat(y1);
|
||
return function(x) {
|
||
return y.map(function(y) {
|
||
return [ x, y ];
|
||
});
|
||
};
|
||
}
|
||
function d3_geo_graticuleY(x0, x1, dx) {
|
||
var x = d3.range(x0, x1 - ε, dx).concat(x1);
|
||
return function(y) {
|
||
return x.map(function(x) {
|
||
return [ x, y ];
|
||
});
|
||
};
|
||
}
|
||
function d3_source(d) {
|
||
return d.source;
|
||
}
|
||
function d3_target(d) {
|
||
return d.target;
|
||
}
|
||
d3.geo.greatArc = function() {
|
||
var source = d3_source, source_, target = d3_target, target_;
|
||
function greatArc() {
|
||
return {
|
||
type: "LineString",
|
||
coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ]
|
||
};
|
||
}
|
||
greatArc.distance = function() {
|
||
return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments));
|
||
};
|
||
greatArc.source = function(_) {
|
||
if (!arguments.length) return source;
|
||
source = _, source_ = typeof _ === "function" ? null : _;
|
||
return greatArc;
|
||
};
|
||
greatArc.target = function(_) {
|
||
if (!arguments.length) return target;
|
||
target = _, target_ = typeof _ === "function" ? null : _;
|
||
return greatArc;
|
||
};
|
||
greatArc.precision = function() {
|
||
return arguments.length ? greatArc : 0;
|
||
};
|
||
return greatArc;
|
||
};
|
||
d3.geo.interpolate = function(source, target) {
|
||
return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians);
|
||
};
|
||
function d3_geo_interpolate(x0, y0, x1, y1) {
|
||
var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d);
|
||
var interpolate = d ? function(t) {
|
||
var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1;
|
||
return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ];
|
||
} : function() {
|
||
return [ x0 * d3_degrees, y0 * d3_degrees ];
|
||
};
|
||
interpolate.distance = d;
|
||
return interpolate;
|
||
}
|
||
d3.geo.length = function(object) {
|
||
d3_geo_lengthSum = 0;
|
||
d3.geo.stream(object, d3_geo_length);
|
||
return d3_geo_lengthSum;
|
||
};
|
||
var d3_geo_lengthSum;
|
||
var d3_geo_length = {
|
||
sphere: d3_noop,
|
||
point: d3_noop,
|
||
lineStart: d3_geo_lengthLineStart,
|
||
lineEnd: d3_noop,
|
||
polygonStart: d3_noop,
|
||
polygonEnd: d3_noop
|
||
};
|
||
function d3_geo_lengthLineStart() {
|
||
var λ0, sinφ0, cosφ0;
|
||
d3_geo_length.point = function(λ, φ) {
|
||
λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ);
|
||
d3_geo_length.point = nextPoint;
|
||
};
|
||
d3_geo_length.lineEnd = function() {
|
||
d3_geo_length.point = d3_geo_length.lineEnd = d3_noop;
|
||
};
|
||
function nextPoint(λ, φ) {
|
||
var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t);
|
||
d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ);
|
||
λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ;
|
||
}
|
||
}
|
||
function d3_geo_azimuthal(scale, angle) {
|
||
function azimuthal(λ, φ) {
|
||
var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ);
|
||
return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ];
|
||
}
|
||
azimuthal.invert = function(x, y) {
|
||
var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c);
|
||
return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ];
|
||
};
|
||
return azimuthal;
|
||
}
|
||
var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) {
|
||
return Math.sqrt(2 / (1 + cosλcosφ));
|
||
}, function(ρ) {
|
||
return 2 * Math.asin(ρ / 2);
|
||
});
|
||
(d3.geo.azimuthalEqualArea = function() {
|
||
return d3_geo_projection(d3_geo_azimuthalEqualArea);
|
||
}).raw = d3_geo_azimuthalEqualArea;
|
||
var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) {
|
||
var c = Math.acos(cosλcosφ);
|
||
return c && c / Math.sin(c);
|
||
}, d3_identity);
|
||
(d3.geo.azimuthalEquidistant = function() {
|
||
return d3_geo_projection(d3_geo_azimuthalEquidistant);
|
||
}).raw = d3_geo_azimuthalEquidistant;
|
||
function d3_geo_conicConformal(φ0, φ1) {
|
||
var cosφ0 = Math.cos(φ0), t = function(φ) {
|
||
return Math.tan(π / 4 + φ / 2);
|
||
}, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n;
|
||
if (!n) return d3_geo_mercator;
|
||
function forward(λ, φ) {
|
||
if (F > 0) {
|
||
if (φ < -halfπ + ε) φ = -halfπ + ε;
|
||
} else {
|
||
if (φ > halfπ - ε) φ = halfπ - ε;
|
||
}
|
||
var ρ = F / Math.pow(t(φ), n);
|
||
return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ];
|
||
}
|
||
forward.invert = function(x, y) {
|
||
var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y);
|
||
return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ];
|
||
};
|
||
return forward;
|
||
}
|
||
(d3.geo.conicConformal = function() {
|
||
return d3_geo_conic(d3_geo_conicConformal);
|
||
}).raw = d3_geo_conicConformal;
|
||
function d3_geo_conicEquidistant(φ0, φ1) {
|
||
var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0;
|
||
if (abs(n) < ε) return d3_geo_equirectangular;
|
||
function forward(λ, φ) {
|
||
var ρ = G - φ;
|
||
return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ];
|
||
}
|
||
forward.invert = function(x, y) {
|
||
var ρ0_y = G - y;
|
||
return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ];
|
||
};
|
||
return forward;
|
||
}
|
||
(d3.geo.conicEquidistant = function() {
|
||
return d3_geo_conic(d3_geo_conicEquidistant);
|
||
}).raw = d3_geo_conicEquidistant;
|
||
var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) {
|
||
return 1 / cosλcosφ;
|
||
}, Math.atan);
|
||
(d3.geo.gnomonic = function() {
|
||
return d3_geo_projection(d3_geo_gnomonic);
|
||
}).raw = d3_geo_gnomonic;
|
||
function d3_geo_mercator(λ, φ) {
|
||
return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ];
|
||
}
|
||
d3_geo_mercator.invert = function(x, y) {
|
||
return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ];
|
||
};
|
||
function d3_geo_mercatorProjection(project) {
|
||
var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto;
|
||
m.scale = function() {
|
||
var v = scale.apply(m, arguments);
|
||
return v === m ? clipAuto ? m.clipExtent(null) : m : v;
|
||
};
|
||
m.translate = function() {
|
||
var v = translate.apply(m, arguments);
|
||
return v === m ? clipAuto ? m.clipExtent(null) : m : v;
|
||
};
|
||
m.clipExtent = function(_) {
|
||
var v = clipExtent.apply(m, arguments);
|
||
if (v === m) {
|
||
if (clipAuto = _ == null) {
|
||
var k = π * scale(), t = translate();
|
||
clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]);
|
||
}
|
||
} else if (clipAuto) {
|
||
v = null;
|
||
}
|
||
return v;
|
||
};
|
||
return m.clipExtent(null);
|
||
}
|
||
(d3.geo.mercator = function() {
|
||
return d3_geo_mercatorProjection(d3_geo_mercator);
|
||
}).raw = d3_geo_mercator;
|
||
var d3_geo_orthographic = d3_geo_azimuthal(function() {
|
||
return 1;
|
||
}, Math.asin);
|
||
(d3.geo.orthographic = function() {
|
||
return d3_geo_projection(d3_geo_orthographic);
|
||
}).raw = d3_geo_orthographic;
|
||
var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) {
|
||
return 1 / (1 + cosλcosφ);
|
||
}, function(ρ) {
|
||
return 2 * Math.atan(ρ);
|
||
});
|
||
(d3.geo.stereographic = function() {
|
||
return d3_geo_projection(d3_geo_stereographic);
|
||
}).raw = d3_geo_stereographic;
|
||
function d3_geo_transverseMercator(λ, φ) {
|
||
return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ];
|
||
}
|
||
d3_geo_transverseMercator.invert = function(x, y) {
|
||
return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ];
|
||
};
|
||
(d3.geo.transverseMercator = function() {
|
||
var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate;
|
||
projection.center = function(_) {
|
||
return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]);
|
||
};
|
||
projection.rotate = function(_) {
|
||
return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(),
|
||
[ _[0], _[1], _[2] - 90 ]);
|
||
};
|
||
return rotate([ 0, 0, 90 ]);
|
||
}).raw = d3_geo_transverseMercator;
|
||
d3.geom = {};
|
||
function d3_geom_pointX(d) {
|
||
return d[0];
|
||
}
|
||
function d3_geom_pointY(d) {
|
||
return d[1];
|
||
}
|
||
d3.geom.hull = function(vertices) {
|
||
var x = d3_geom_pointX, y = d3_geom_pointY;
|
||
if (arguments.length) return hull(vertices);
|
||
function hull(data) {
|
||
if (data.length < 3) return [];
|
||
var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = [];
|
||
for (i = 0; i < n; i++) {
|
||
points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]);
|
||
}
|
||
points.sort(d3_geom_hullOrder);
|
||
for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]);
|
||
var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints);
|
||
var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = [];
|
||
for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]);
|
||
for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]);
|
||
return polygon;
|
||
}
|
||
hull.x = function(_) {
|
||
return arguments.length ? (x = _, hull) : x;
|
||
};
|
||
hull.y = function(_) {
|
||
return arguments.length ? (y = _, hull) : y;
|
||
};
|
||
return hull;
|
||
};
|
||
function d3_geom_hullUpper(points) {
|
||
var n = points.length, hull = [ 0, 1 ], hs = 2;
|
||
for (var i = 2; i < n; i++) {
|
||
while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs;
|
||
hull[hs++] = i;
|
||
}
|
||
return hull.slice(0, hs);
|
||
}
|
||
function d3_geom_hullOrder(a, b) {
|
||
return a[0] - b[0] || a[1] - b[1];
|
||
}
|
||
d3.geom.polygon = function(coordinates) {
|
||
d3_subclass(coordinates, d3_geom_polygonPrototype);
|
||
return coordinates;
|
||
};
|
||
var d3_geom_polygonPrototype = d3.geom.polygon.prototype = [];
|
||
d3_geom_polygonPrototype.area = function() {
|
||
var i = -1, n = this.length, a, b = this[n - 1], area = 0;
|
||
while (++i < n) {
|
||
a = b;
|
||
b = this[i];
|
||
area += a[1] * b[0] - a[0] * b[1];
|
||
}
|
||
return area * .5;
|
||
};
|
||
d3_geom_polygonPrototype.centroid = function(k) {
|
||
var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c;
|
||
if (!arguments.length) k = -1 / (6 * this.area());
|
||
while (++i < n) {
|
||
a = b;
|
||
b = this[i];
|
||
c = a[0] * b[1] - b[0] * a[1];
|
||
x += (a[0] + b[0]) * c;
|
||
y += (a[1] + b[1]) * c;
|
||
}
|
||
return [ x * k, y * k ];
|
||
};
|
||
d3_geom_polygonPrototype.clip = function(subject) {
|
||
var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d;
|
||
while (++i < n) {
|
||
input = subject.slice();
|
||
subject.length = 0;
|
||
b = this[i];
|
||
c = input[(m = input.length - closed) - 1];
|
||
j = -1;
|
||
while (++j < m) {
|
||
d = input[j];
|
||
if (d3_geom_polygonInside(d, a, b)) {
|
||
if (!d3_geom_polygonInside(c, a, b)) {
|
||
subject.push(d3_geom_polygonIntersect(c, d, a, b));
|
||
}
|
||
subject.push(d);
|
||
} else if (d3_geom_polygonInside(c, a, b)) {
|
||
subject.push(d3_geom_polygonIntersect(c, d, a, b));
|
||
}
|
||
c = d;
|
||
}
|
||
if (closed) subject.push(subject[0]);
|
||
a = b;
|
||
}
|
||
return subject;
|
||
};
|
||
function d3_geom_polygonInside(p, a, b) {
|
||
return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
|
||
}
|
||
function d3_geom_polygonIntersect(c, d, a, b) {
|
||
var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
|
||
return [ x1 + ua * x21, y1 + ua * y21 ];
|
||
}
|
||
function d3_geom_polygonClosed(coordinates) {
|
||
var a = coordinates[0], b = coordinates[coordinates.length - 1];
|
||
return !(a[0] - b[0] || a[1] - b[1]);
|
||
}
|
||
var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = [];
|
||
function d3_geom_voronoiBeach() {
|
||
d3_geom_voronoiRedBlackNode(this);
|
||
this.edge = this.site = this.circle = null;
|
||
}
|
||
function d3_geom_voronoiCreateBeach(site) {
|
||
var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach();
|
||
beach.site = site;
|
||
return beach;
|
||
}
|
||
function d3_geom_voronoiDetachBeach(beach) {
|
||
d3_geom_voronoiDetachCircle(beach);
|
||
d3_geom_voronoiBeaches.remove(beach);
|
||
d3_geom_voronoiBeachPool.push(beach);
|
||
d3_geom_voronoiRedBlackNode(beach);
|
||
}
|
||
function d3_geom_voronoiRemoveBeach(beach) {
|
||
var circle = beach.circle, x = circle.x, y = circle.cy, vertex = {
|
||
x: x,
|
||
y: y
|
||
}, previous = beach.P, next = beach.N, disappearing = [ beach ];
|
||
d3_geom_voronoiDetachBeach(beach);
|
||
var lArc = previous;
|
||
while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) {
|
||
previous = lArc.P;
|
||
disappearing.unshift(lArc);
|
||
d3_geom_voronoiDetachBeach(lArc);
|
||
lArc = previous;
|
||
}
|
||
disappearing.unshift(lArc);
|
||
d3_geom_voronoiDetachCircle(lArc);
|
||
var rArc = next;
|
||
while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) {
|
||
next = rArc.N;
|
||
disappearing.push(rArc);
|
||
d3_geom_voronoiDetachBeach(rArc);
|
||
rArc = next;
|
||
}
|
||
disappearing.push(rArc);
|
||
d3_geom_voronoiDetachCircle(rArc);
|
||
var nArcs = disappearing.length, iArc;
|
||
for (iArc = 1; iArc < nArcs; ++iArc) {
|
||
rArc = disappearing[iArc];
|
||
lArc = disappearing[iArc - 1];
|
||
d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
|
||
}
|
||
lArc = disappearing[0];
|
||
rArc = disappearing[nArcs - 1];
|
||
rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex);
|
||
d3_geom_voronoiAttachCircle(lArc);
|
||
d3_geom_voronoiAttachCircle(rArc);
|
||
}
|
||
function d3_geom_voronoiAddBeach(site) {
|
||
var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._;
|
||
while (node) {
|
||
dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x;
|
||
if (dxl > ε) node = node.L; else {
|
||
dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix);
|
||
if (dxr > ε) {
|
||
if (!node.R) {
|
||
lArc = node;
|
||
break;
|
||
}
|
||
node = node.R;
|
||
} else {
|
||
if (dxl > -ε) {
|
||
lArc = node.P;
|
||
rArc = node;
|
||
} else if (dxr > -ε) {
|
||
lArc = node;
|
||
rArc = node.N;
|
||
} else {
|
||
lArc = rArc = node;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
var newArc = d3_geom_voronoiCreateBeach(site);
|
||
d3_geom_voronoiBeaches.insert(lArc, newArc);
|
||
if (!lArc && !rArc) return;
|
||
if (lArc === rArc) {
|
||
d3_geom_voronoiDetachCircle(lArc);
|
||
rArc = d3_geom_voronoiCreateBeach(lArc.site);
|
||
d3_geom_voronoiBeaches.insert(newArc, rArc);
|
||
newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
|
||
d3_geom_voronoiAttachCircle(lArc);
|
||
d3_geom_voronoiAttachCircle(rArc);
|
||
return;
|
||
}
|
||
if (!rArc) {
|
||
newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
|
||
return;
|
||
}
|
||
d3_geom_voronoiDetachCircle(lArc);
|
||
d3_geom_voronoiDetachCircle(rArc);
|
||
var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = {
|
||
x: (cy * hb - by * hc) / d + ax,
|
||
y: (bx * hc - cx * hb) / d + ay
|
||
};
|
||
d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex);
|
||
newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex);
|
||
rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex);
|
||
d3_geom_voronoiAttachCircle(lArc);
|
||
d3_geom_voronoiAttachCircle(rArc);
|
||
}
|
||
function d3_geom_voronoiLeftBreakPoint(arc, directrix) {
|
||
var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix;
|
||
if (!pby2) return rfocx;
|
||
var lArc = arc.P;
|
||
if (!lArc) return -Infinity;
|
||
site = lArc.site;
|
||
var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix;
|
||
if (!plby2) return lfocx;
|
||
var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2;
|
||
if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
|
||
return (rfocx + lfocx) / 2;
|
||
}
|
||
function d3_geom_voronoiRightBreakPoint(arc, directrix) {
|
||
var rArc = arc.N;
|
||
if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix);
|
||
var site = arc.site;
|
||
return site.y === directrix ? site.x : Infinity;
|
||
}
|
||
function d3_geom_voronoiCell(site) {
|
||
this.site = site;
|
||
this.edges = [];
|
||
}
|
||
d3_geom_voronoiCell.prototype.prepare = function() {
|
||
var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge;
|
||
while (iHalfEdge--) {
|
||
edge = halfEdges[iHalfEdge].edge;
|
||
if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1);
|
||
}
|
||
halfEdges.sort(d3_geom_voronoiHalfEdgeOrder);
|
||
return halfEdges.length;
|
||
};
|
||
function d3_geom_voronoiCloseCells(extent) {
|
||
var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end;
|
||
while (iCell--) {
|
||
cell = cells[iCell];
|
||
if (!cell || !cell.prepare()) continue;
|
||
halfEdges = cell.edges;
|
||
nHalfEdges = halfEdges.length;
|
||
iHalfEdge = 0;
|
||
while (iHalfEdge < nHalfEdges) {
|
||
end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y;
|
||
start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y;
|
||
if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) {
|
||
halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? {
|
||
x: x0,
|
||
y: abs(x2 - x0) < ε ? y2 : y1
|
||
} : abs(y3 - y1) < ε && x1 - x3 > ε ? {
|
||
x: abs(y2 - y1) < ε ? x2 : x1,
|
||
y: y1
|
||
} : abs(x3 - x1) < ε && y3 - y0 > ε ? {
|
||
x: x1,
|
||
y: abs(x2 - x1) < ε ? y2 : y0
|
||
} : abs(y3 - y0) < ε && x3 - x0 > ε ? {
|
||
x: abs(y2 - y0) < ε ? x2 : x0,
|
||
y: y0
|
||
} : null), cell.site, null));
|
||
++nHalfEdges;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
function d3_geom_voronoiHalfEdgeOrder(a, b) {
|
||
return b.angle - a.angle;
|
||
}
|
||
function d3_geom_voronoiCircle() {
|
||
d3_geom_voronoiRedBlackNode(this);
|
||
this.x = this.y = this.arc = this.site = this.cy = null;
|
||
}
|
||
function d3_geom_voronoiAttachCircle(arc) {
|
||
var lArc = arc.P, rArc = arc.N;
|
||
if (!lArc || !rArc) return;
|
||
var lSite = lArc.site, cSite = arc.site, rSite = rArc.site;
|
||
if (lSite === rSite) return;
|
||
var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by;
|
||
var d = 2 * (ax * cy - ay * cx);
|
||
if (d >= -ε2) return;
|
||
var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by;
|
||
var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle();
|
||
circle.arc = arc;
|
||
circle.site = cSite;
|
||
circle.x = x + bx;
|
||
circle.y = cy + Math.sqrt(x * x + y * y);
|
||
circle.cy = cy;
|
||
arc.circle = circle;
|
||
var before = null, node = d3_geom_voronoiCircles._;
|
||
while (node) {
|
||
if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) {
|
||
if (node.L) node = node.L; else {
|
||
before = node.P;
|
||
break;
|
||
}
|
||
} else {
|
||
if (node.R) node = node.R; else {
|
||
before = node;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
d3_geom_voronoiCircles.insert(before, circle);
|
||
if (!before) d3_geom_voronoiFirstCircle = circle;
|
||
}
|
||
function d3_geom_voronoiDetachCircle(arc) {
|
||
var circle = arc.circle;
|
||
if (circle) {
|
||
if (!circle.P) d3_geom_voronoiFirstCircle = circle.N;
|
||
d3_geom_voronoiCircles.remove(circle);
|
||
d3_geom_voronoiCirclePool.push(circle);
|
||
d3_geom_voronoiRedBlackNode(circle);
|
||
arc.circle = null;
|
||
}
|
||
}
|
||
function d3_geom_voronoiClipEdges(extent) {
|
||
var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e;
|
||
while (i--) {
|
||
e = edges[i];
|
||
if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) {
|
||
e.a = e.b = null;
|
||
edges.splice(i, 1);
|
||
}
|
||
}
|
||
}
|
||
function d3_geom_voronoiConnectEdge(edge, extent) {
|
||
var vb = edge.b;
|
||
if (vb) return true;
|
||
var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb;
|
||
if (ry === ly) {
|
||
if (fx < x0 || fx >= x1) return;
|
||
if (lx > rx) {
|
||
if (!va) va = {
|
||
x: fx,
|
||
y: y0
|
||
}; else if (va.y >= y1) return;
|
||
vb = {
|
||
x: fx,
|
||
y: y1
|
||
};
|
||
} else {
|
||
if (!va) va = {
|
||
x: fx,
|
||
y: y1
|
||
}; else if (va.y < y0) return;
|
||
vb = {
|
||
x: fx,
|
||
y: y0
|
||
};
|
||
}
|
||
} else {
|
||
fm = (lx - rx) / (ry - ly);
|
||
fb = fy - fm * fx;
|
||
if (fm < -1 || fm > 1) {
|
||
if (lx > rx) {
|
||
if (!va) va = {
|
||
x: (y0 - fb) / fm,
|
||
y: y0
|
||
}; else if (va.y >= y1) return;
|
||
vb = {
|
||
x: (y1 - fb) / fm,
|
||
y: y1
|
||
};
|
||
} else {
|
||
if (!va) va = {
|
||
x: (y1 - fb) / fm,
|
||
y: y1
|
||
}; else if (va.y < y0) return;
|
||
vb = {
|
||
x: (y0 - fb) / fm,
|
||
y: y0
|
||
};
|
||
}
|
||
} else {
|
||
if (ly < ry) {
|
||
if (!va) va = {
|
||
x: x0,
|
||
y: fm * x0 + fb
|
||
}; else if (va.x >= x1) return;
|
||
vb = {
|
||
x: x1,
|
||
y: fm * x1 + fb
|
||
};
|
||
} else {
|
||
if (!va) va = {
|
||
x: x1,
|
||
y: fm * x1 + fb
|
||
}; else if (va.x < x0) return;
|
||
vb = {
|
||
x: x0,
|
||
y: fm * x0 + fb
|
||
};
|
||
}
|
||
}
|
||
}
|
||
edge.a = va;
|
||
edge.b = vb;
|
||
return true;
|
||
}
|
||
function d3_geom_voronoiEdge(lSite, rSite) {
|
||
this.l = lSite;
|
||
this.r = rSite;
|
||
this.a = this.b = null;
|
||
}
|
||
function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) {
|
||
var edge = new d3_geom_voronoiEdge(lSite, rSite);
|
||
d3_geom_voronoiEdges.push(edge);
|
||
if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va);
|
||
if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb);
|
||
d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite));
|
||
d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite));
|
||
return edge;
|
||
}
|
||
function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) {
|
||
var edge = new d3_geom_voronoiEdge(lSite, null);
|
||
edge.a = va;
|
||
edge.b = vb;
|
||
d3_geom_voronoiEdges.push(edge);
|
||
return edge;
|
||
}
|
||
function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) {
|
||
if (!edge.a && !edge.b) {
|
||
edge.a = vertex;
|
||
edge.l = lSite;
|
||
edge.r = rSite;
|
||
} else if (edge.l === rSite) {
|
||
edge.b = vertex;
|
||
} else {
|
||
edge.a = vertex;
|
||
}
|
||
}
|
||
function d3_geom_voronoiHalfEdge(edge, lSite, rSite) {
|
||
var va = edge.a, vb = edge.b;
|
||
this.edge = edge;
|
||
this.site = lSite;
|
||
this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y);
|
||
}
|
||
d3_geom_voronoiHalfEdge.prototype = {
|
||
start: function() {
|
||
return this.edge.l === this.site ? this.edge.a : this.edge.b;
|
||
},
|
||
end: function() {
|
||
return this.edge.l === this.site ? this.edge.b : this.edge.a;
|
||
}
|
||
};
|
||
function d3_geom_voronoiRedBlackTree() {
|
||
this._ = null;
|
||
}
|
||
function d3_geom_voronoiRedBlackNode(node) {
|
||
node.U = node.C = node.L = node.R = node.P = node.N = null;
|
||
}
|
||
d3_geom_voronoiRedBlackTree.prototype = {
|
||
insert: function(after, node) {
|
||
var parent, grandpa, uncle;
|
||
if (after) {
|
||
node.P = after;
|
||
node.N = after.N;
|
||
if (after.N) after.N.P = node;
|
||
after.N = node;
|
||
if (after.R) {
|
||
after = after.R;
|
||
while (after.L) after = after.L;
|
||
after.L = node;
|
||
} else {
|
||
after.R = node;
|
||
}
|
||
parent = after;
|
||
} else if (this._) {
|
||
after = d3_geom_voronoiRedBlackFirst(this._);
|
||
node.P = null;
|
||
node.N = after;
|
||
after.P = after.L = node;
|
||
parent = after;
|
||
} else {
|
||
node.P = node.N = null;
|
||
this._ = node;
|
||
parent = null;
|
||
}
|
||
node.L = node.R = null;
|
||
node.U = parent;
|
||
node.C = true;
|
||
after = node;
|
||
while (parent && parent.C) {
|
||
grandpa = parent.U;
|
||
if (parent === grandpa.L) {
|
||
uncle = grandpa.R;
|
||
if (uncle && uncle.C) {
|
||
parent.C = uncle.C = false;
|
||
grandpa.C = true;
|
||
after = grandpa;
|
||
} else {
|
||
if (after === parent.R) {
|
||
d3_geom_voronoiRedBlackRotateLeft(this, parent);
|
||
after = parent;
|
||
parent = after.U;
|
||
}
|
||
parent.C = false;
|
||
grandpa.C = true;
|
||
d3_geom_voronoiRedBlackRotateRight(this, grandpa);
|
||
}
|
||
} else {
|
||
uncle = grandpa.L;
|
||
if (uncle && uncle.C) {
|
||
parent.C = uncle.C = false;
|
||
grandpa.C = true;
|
||
after = grandpa;
|
||
} else {
|
||
if (after === parent.L) {
|
||
d3_geom_voronoiRedBlackRotateRight(this, parent);
|
||
after = parent;
|
||
parent = after.U;
|
||
}
|
||
parent.C = false;
|
||
grandpa.C = true;
|
||
d3_geom_voronoiRedBlackRotateLeft(this, grandpa);
|
||
}
|
||
}
|
||
parent = after.U;
|
||
}
|
||
this._.C = false;
|
||
},
|
||
remove: function(node) {
|
||
if (node.N) node.N.P = node.P;
|
||
if (node.P) node.P.N = node.N;
|
||
node.N = node.P = null;
|
||
var parent = node.U, sibling, left = node.L, right = node.R, next, red;
|
||
if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right);
|
||
if (parent) {
|
||
if (parent.L === node) parent.L = next; else parent.R = next;
|
||
} else {
|
||
this._ = next;
|
||
}
|
||
if (left && right) {
|
||
red = next.C;
|
||
next.C = node.C;
|
||
next.L = left;
|
||
left.U = next;
|
||
if (next !== right) {
|
||
parent = next.U;
|
||
next.U = node.U;
|
||
node = next.R;
|
||
parent.L = node;
|
||
next.R = right;
|
||
right.U = next;
|
||
} else {
|
||
next.U = parent;
|
||
parent = next;
|
||
node = next.R;
|
||
}
|
||
} else {
|
||
red = node.C;
|
||
node = next;
|
||
}
|
||
if (node) node.U = parent;
|
||
if (red) return;
|
||
if (node && node.C) {
|
||
node.C = false;
|
||
return;
|
||
}
|
||
do {
|
||
if (node === this._) break;
|
||
if (node === parent.L) {
|
||
sibling = parent.R;
|
||
if (sibling.C) {
|
||
sibling.C = false;
|
||
parent.C = true;
|
||
d3_geom_voronoiRedBlackRotateLeft(this, parent);
|
||
sibling = parent.R;
|
||
}
|
||
if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {
|
||
if (!sibling.R || !sibling.R.C) {
|
||
sibling.L.C = false;
|
||
sibling.C = true;
|
||
d3_geom_voronoiRedBlackRotateRight(this, sibling);
|
||
sibling = parent.R;
|
||
}
|
||
sibling.C = parent.C;
|
||
parent.C = sibling.R.C = false;
|
||
d3_geom_voronoiRedBlackRotateLeft(this, parent);
|
||
node = this._;
|
||
break;
|
||
}
|
||
} else {
|
||
sibling = parent.L;
|
||
if (sibling.C) {
|
||
sibling.C = false;
|
||
parent.C = true;
|
||
d3_geom_voronoiRedBlackRotateRight(this, parent);
|
||
sibling = parent.L;
|
||
}
|
||
if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {
|
||
if (!sibling.L || !sibling.L.C) {
|
||
sibling.R.C = false;
|
||
sibling.C = true;
|
||
d3_geom_voronoiRedBlackRotateLeft(this, sibling);
|
||
sibling = parent.L;
|
||
}
|
||
sibling.C = parent.C;
|
||
parent.C = sibling.L.C = false;
|
||
d3_geom_voronoiRedBlackRotateRight(this, parent);
|
||
node = this._;
|
||
break;
|
||
}
|
||
}
|
||
sibling.C = true;
|
||
node = parent;
|
||
parent = parent.U;
|
||
} while (!node.C);
|
||
if (node) node.C = false;
|
||
}
|
||
};
|
||
function d3_geom_voronoiRedBlackRotateLeft(tree, node) {
|
||
var p = node, q = node.R, parent = p.U;
|
||
if (parent) {
|
||
if (parent.L === p) parent.L = q; else parent.R = q;
|
||
} else {
|
||
tree._ = q;
|
||
}
|
||
q.U = parent;
|
||
p.U = q;
|
||
p.R = q.L;
|
||
if (p.R) p.R.U = p;
|
||
q.L = p;
|
||
}
|
||
function d3_geom_voronoiRedBlackRotateRight(tree, node) {
|
||
var p = node, q = node.L, parent = p.U;
|
||
if (parent) {
|
||
if (parent.L === p) parent.L = q; else parent.R = q;
|
||
} else {
|
||
tree._ = q;
|
||
}
|
||
q.U = parent;
|
||
p.U = q;
|
||
p.L = q.R;
|
||
if (p.L) p.L.U = p;
|
||
q.R = p;
|
||
}
|
||
function d3_geom_voronoiRedBlackFirst(node) {
|
||
while (node.L) node = node.L;
|
||
return node;
|
||
}
|
||
function d3_geom_voronoi(sites, bbox) {
|
||
var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle;
|
||
d3_geom_voronoiEdges = [];
|
||
d3_geom_voronoiCells = new Array(sites.length);
|
||
d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree();
|
||
d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree();
|
||
while (true) {
|
||
circle = d3_geom_voronoiFirstCircle;
|
||
if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) {
|
||
if (site.x !== x0 || site.y !== y0) {
|
||
d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site);
|
||
d3_geom_voronoiAddBeach(site);
|
||
x0 = site.x, y0 = site.y;
|
||
}
|
||
site = sites.pop();
|
||
} else if (circle) {
|
||
d3_geom_voronoiRemoveBeach(circle.arc);
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox);
|
||
var diagram = {
|
||
cells: d3_geom_voronoiCells,
|
||
edges: d3_geom_voronoiEdges
|
||
};
|
||
d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null;
|
||
return diagram;
|
||
}
|
||
function d3_geom_voronoiVertexOrder(a, b) {
|
||
return b.y - a.y || b.x - a.x;
|
||
}
|
||
d3.geom.voronoi = function(points) {
|
||
var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent;
|
||
if (points) return voronoi(points);
|
||
function voronoi(data) {
|
||
var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1];
|
||
d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) {
|
||
var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) {
|
||
var s = e.start();
|
||
return [ s.x, s.y ];
|
||
}) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : [];
|
||
polygon.point = data[i];
|
||
});
|
||
return polygons;
|
||
}
|
||
function sites(data) {
|
||
return data.map(function(d, i) {
|
||
return {
|
||
x: Math.round(fx(d, i) / ε) * ε,
|
||
y: Math.round(fy(d, i) / ε) * ε,
|
||
i: i
|
||
};
|
||
});
|
||
}
|
||
voronoi.links = function(data) {
|
||
return d3_geom_voronoi(sites(data)).edges.filter(function(edge) {
|
||
return edge.l && edge.r;
|
||
}).map(function(edge) {
|
||
return {
|
||
source: data[edge.l.i],
|
||
target: data[edge.r.i]
|
||
};
|
||
});
|
||
};
|
||
voronoi.triangles = function(data) {
|
||
var triangles = [];
|
||
d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) {
|
||
var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l;
|
||
while (++j < m) {
|
||
e0 = e1;
|
||
s0 = s1;
|
||
e1 = edges[j].edge;
|
||
s1 = e1.l === site ? e1.r : e1.l;
|
||
if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) {
|
||
triangles.push([ data[i], data[s0.i], data[s1.i] ]);
|
||
}
|
||
}
|
||
});
|
||
return triangles;
|
||
};
|
||
voronoi.x = function(_) {
|
||
return arguments.length ? (fx = d3_functor(x = _), voronoi) : x;
|
||
};
|
||
voronoi.y = function(_) {
|
||
return arguments.length ? (fy = d3_functor(y = _), voronoi) : y;
|
||
};
|
||
voronoi.clipExtent = function(_) {
|
||
if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent;
|
||
clipExtent = _ == null ? d3_geom_voronoiClipExtent : _;
|
||
return voronoi;
|
||
};
|
||
voronoi.size = function(_) {
|
||
if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1];
|
||
return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]);
|
||
};
|
||
return voronoi;
|
||
};
|
||
var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ];
|
||
function d3_geom_voronoiTriangleArea(a, b, c) {
|
||
return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y);
|
||
}
|
||
d3.geom.delaunay = function(vertices) {
|
||
return d3.geom.voronoi().triangles(vertices);
|
||
};
|
||
d3.geom.quadtree = function(points, x1, y1, x2, y2) {
|
||
var x = d3_geom_pointX, y = d3_geom_pointY, compat;
|
||
if (compat = arguments.length) {
|
||
x = d3_geom_quadtreeCompatX;
|
||
y = d3_geom_quadtreeCompatY;
|
||
if (compat === 3) {
|
||
y2 = y1;
|
||
x2 = x1;
|
||
y1 = x1 = 0;
|
||
}
|
||
return quadtree(points);
|
||
}
|
||
function quadtree(data) {
|
||
var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_;
|
||
if (x1 != null) {
|
||
x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2;
|
||
} else {
|
||
x2_ = y2_ = -(x1_ = y1_ = Infinity);
|
||
xs = [], ys = [];
|
||
n = data.length;
|
||
if (compat) for (i = 0; i < n; ++i) {
|
||
d = data[i];
|
||
if (d.x < x1_) x1_ = d.x;
|
||
if (d.y < y1_) y1_ = d.y;
|
||
if (d.x > x2_) x2_ = d.x;
|
||
if (d.y > y2_) y2_ = d.y;
|
||
xs.push(d.x);
|
||
ys.push(d.y);
|
||
} else for (i = 0; i < n; ++i) {
|
||
var x_ = +fx(d = data[i], i), y_ = +fy(d, i);
|
||
if (x_ < x1_) x1_ = x_;
|
||
if (y_ < y1_) y1_ = y_;
|
||
if (x_ > x2_) x2_ = x_;
|
||
if (y_ > y2_) y2_ = y_;
|
||
xs.push(x_);
|
||
ys.push(y_);
|
||
}
|
||
}
|
||
var dx = x2_ - x1_, dy = y2_ - y1_;
|
||
if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy;
|
||
function insert(n, d, x, y, x1, y1, x2, y2) {
|
||
if (isNaN(x) || isNaN(y)) return;
|
||
if (n.leaf) {
|
||
var nx = n.x, ny = n.y;
|
||
if (nx != null) {
|
||
if (abs(nx - x) + abs(ny - y) < .01) {
|
||
insertChild(n, d, x, y, x1, y1, x2, y2);
|
||
} else {
|
||
var nPoint = n.point;
|
||
n.x = n.y = n.point = null;
|
||
insertChild(n, nPoint, nx, ny, x1, y1, x2, y2);
|
||
insertChild(n, d, x, y, x1, y1, x2, y2);
|
||
}
|
||
} else {
|
||
n.x = x, n.y = y, n.point = d;
|
||
}
|
||
} else {
|
||
insertChild(n, d, x, y, x1, y1, x2, y2);
|
||
}
|
||
}
|
||
function insertChild(n, d, x, y, x1, y1, x2, y2) {
|
||
var xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym, i = below << 1 | right;
|
||
n.leaf = false;
|
||
n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());
|
||
if (right) x1 = xm; else x2 = xm;
|
||
if (below) y1 = ym; else y2 = ym;
|
||
insert(n, d, x, y, x1, y1, x2, y2);
|
||
}
|
||
var root = d3_geom_quadtreeNode();
|
||
root.add = function(d) {
|
||
insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_);
|
||
};
|
||
root.visit = function(f) {
|
||
d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_);
|
||
};
|
||
root.find = function(point) {
|
||
return d3_geom_quadtreeFind(root, point[0], point[1], x1_, y1_, x2_, y2_);
|
||
};
|
||
i = -1;
|
||
if (x1 == null) {
|
||
while (++i < n) {
|
||
insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_);
|
||
}
|
||
--i;
|
||
} else data.forEach(root.add);
|
||
xs = ys = data = d = null;
|
||
return root;
|
||
}
|
||
quadtree.x = function(_) {
|
||
return arguments.length ? (x = _, quadtree) : x;
|
||
};
|
||
quadtree.y = function(_) {
|
||
return arguments.length ? (y = _, quadtree) : y;
|
||
};
|
||
quadtree.extent = function(_) {
|
||
if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ];
|
||
if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0],
|
||
y2 = +_[1][1];
|
||
return quadtree;
|
||
};
|
||
quadtree.size = function(_) {
|
||
if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ];
|
||
if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1];
|
||
return quadtree;
|
||
};
|
||
return quadtree;
|
||
};
|
||
function d3_geom_quadtreeCompatX(d) {
|
||
return d.x;
|
||
}
|
||
function d3_geom_quadtreeCompatY(d) {
|
||
return d.y;
|
||
}
|
||
function d3_geom_quadtreeNode() {
|
||
return {
|
||
leaf: true,
|
||
nodes: [],
|
||
point: null,
|
||
x: null,
|
||
y: null
|
||
};
|
||
}
|
||
function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) {
|
||
if (!f(node, x1, y1, x2, y2)) {
|
||
var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes;
|
||
if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy);
|
||
if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy);
|
||
if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2);
|
||
if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2);
|
||
}
|
||
}
|
||
function d3_geom_quadtreeFind(root, x, y, x0, y0, x3, y3) {
|
||
var minDistance2 = Infinity, closestPoint;
|
||
(function find(node, x1, y1, x2, y2) {
|
||
if (x1 > x3 || y1 > y3 || x2 < x0 || y2 < y0) return;
|
||
if (point = node.point) {
|
||
var point, dx = x - node.x, dy = y - node.y, distance2 = dx * dx + dy * dy;
|
||
if (distance2 < minDistance2) {
|
||
var distance = Math.sqrt(minDistance2 = distance2);
|
||
x0 = x - distance, y0 = y - distance;
|
||
x3 = x + distance, y3 = y + distance;
|
||
closestPoint = point;
|
||
}
|
||
}
|
||
var children = node.nodes, xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym;
|
||
for (var i = below << 1 | right, j = i + 4; i < j; ++i) {
|
||
if (node = children[i & 3]) switch (i & 3) {
|
||
case 0:
|
||
find(node, x1, y1, xm, ym);
|
||
break;
|
||
|
||
case 1:
|
||
find(node, xm, y1, x2, ym);
|
||
break;
|
||
|
||
case 2:
|
||
find(node, x1, ym, xm, y2);
|
||
break;
|
||
|
||
case 3:
|
||
find(node, xm, ym, x2, y2);
|
||
break;
|
||
}
|
||
}
|
||
})(root, x0, y0, x3, y3);
|
||
return closestPoint;
|
||
}
|
||
d3.interpolateRgb = d3_interpolateRgb;
|
||
function d3_interpolateRgb(a, b) {
|
||
a = d3.rgb(a);
|
||
b = d3.rgb(b);
|
||
var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab;
|
||
return function(t) {
|
||
return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t));
|
||
};
|
||
}
|
||
d3.interpolateObject = d3_interpolateObject;
|
||
function d3_interpolateObject(a, b) {
|
||
var i = {}, c = {}, k;
|
||
for (k in a) {
|
||
if (k in b) {
|
||
i[k] = d3_interpolate(a[k], b[k]);
|
||
} else {
|
||
c[k] = a[k];
|
||
}
|
||
}
|
||
for (k in b) {
|
||
if (!(k in a)) {
|
||
c[k] = b[k];
|
||
}
|
||
}
|
||
return function(t) {
|
||
for (k in i) c[k] = i[k](t);
|
||
return c;
|
||
};
|
||
}
|
||
d3.interpolateNumber = d3_interpolateNumber;
|
||
function d3_interpolateNumber(a, b) {
|
||
a = +a, b = +b;
|
||
return function(t) {
|
||
return a * (1 - t) + b * t;
|
||
};
|
||
}
|
||
d3.interpolateString = d3_interpolateString;
|
||
function d3_interpolateString(a, b) {
|
||
var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = [];
|
||
a = a + "", b = b + "";
|
||
while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) {
|
||
if ((bs = bm.index) > bi) {
|
||
bs = b.slice(bi, bs);
|
||
if (s[i]) s[i] += bs; else s[++i] = bs;
|
||
}
|
||
if ((am = am[0]) === (bm = bm[0])) {
|
||
if (s[i]) s[i] += bm; else s[++i] = bm;
|
||
} else {
|
||
s[++i] = null;
|
||
q.push({
|
||
i: i,
|
||
x: d3_interpolateNumber(am, bm)
|
||
});
|
||
}
|
||
bi = d3_interpolate_numberB.lastIndex;
|
||
}
|
||
if (bi < b.length) {
|
||
bs = b.slice(bi);
|
||
if (s[i]) s[i] += bs; else s[++i] = bs;
|
||
}
|
||
return s.length < 2 ? q[0] ? (b = q[0].x, function(t) {
|
||
return b(t) + "";
|
||
}) : function() {
|
||
return 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("");
|
||
});
|
||
}
|
||
var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g");
|
||
d3.interpolate = d3_interpolate;
|
||
function d3_interpolate(a, b) {
|
||
var i = d3.interpolators.length, f;
|
||
while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ;
|
||
return f;
|
||
}
|
||
d3.interpolators = [ function(a, b) {
|
||
var t = typeof b;
|
||
return (t === "string" ? d3_rgb_names.has(b.toLowerCase()) || /^(#|rgb\(|hsl\()/i.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b);
|
||
} ];
|
||
d3.interpolateArray = d3_interpolateArray;
|
||
function d3_interpolateArray(a, b) {
|
||
var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i;
|
||
for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i]));
|
||
for (;i < na; ++i) c[i] = a[i];
|
||
for (;i < nb; ++i) c[i] = b[i];
|
||
return function(t) {
|
||
for (i = 0; i < n0; ++i) c[i] = x[i](t);
|
||
return c;
|
||
};
|
||
}
|
||
var d3_ease_default = function() {
|
||
return d3_identity;
|
||
};
|
||
var d3_ease = d3.map({
|
||
linear: d3_ease_default,
|
||
poly: d3_ease_poly,
|
||
quad: function() {
|
||
return d3_ease_quad;
|
||
},
|
||
cubic: function() {
|
||
return d3_ease_cubic;
|
||
},
|
||
sin: function() {
|
||
return d3_ease_sin;
|
||
},
|
||
exp: function() {
|
||
return d3_ease_exp;
|
||
},
|
||
circle: function() {
|
||
return d3_ease_circle;
|
||
},
|
||
elastic: d3_ease_elastic,
|
||
back: d3_ease_back,
|
||
bounce: function() {
|
||
return d3_ease_bounce;
|
||
}
|
||
});
|
||
var d3_ease_mode = d3.map({
|
||
"in": d3_identity,
|
||
out: d3_ease_reverse,
|
||
"in-out": d3_ease_reflect,
|
||
"out-in": function(f) {
|
||
return d3_ease_reflect(d3_ease_reverse(f));
|
||
}
|
||
});
|
||
d3.ease = function(name) {
|
||
var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in";
|
||
t = d3_ease.get(t) || d3_ease_default;
|
||
m = d3_ease_mode.get(m) || d3_identity;
|
||
return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1))));
|
||
};
|
||
function d3_ease_clamp(f) {
|
||
return function(t) {
|
||
return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
|
||
};
|
||
}
|
||
function d3_ease_reverse(f) {
|
||
return function(t) {
|
||
return 1 - f(1 - t);
|
||
};
|
||
}
|
||
function d3_ease_reflect(f) {
|
||
return function(t) {
|
||
return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t));
|
||
};
|
||
}
|
||
function d3_ease_quad(t) {
|
||
return t * t;
|
||
}
|
||
function d3_ease_cubic(t) {
|
||
return t * t * t;
|
||
}
|
||
function d3_ease_cubicInOut(t) {
|
||
if (t <= 0) return 0;
|
||
if (t >= 1) return 1;
|
||
var t2 = t * t, t3 = t2 * t;
|
||
return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75);
|
||
}
|
||
function d3_ease_poly(e) {
|
||
return function(t) {
|
||
return Math.pow(t, e);
|
||
};
|
||
}
|
||
function d3_ease_sin(t) {
|
||
return 1 - Math.cos(t * halfπ);
|
||
}
|
||
function d3_ease_exp(t) {
|
||
return Math.pow(2, 10 * (t - 1));
|
||
}
|
||
function d3_ease_circle(t) {
|
||
return 1 - Math.sqrt(1 - t * t);
|
||
}
|
||
function d3_ease_elastic(a, p) {
|
||
var s;
|
||
if (arguments.length < 2) p = .45;
|
||
if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4;
|
||
return function(t) {
|
||
return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p);
|
||
};
|
||
}
|
||
function d3_ease_back(s) {
|
||
if (!s) s = 1.70158;
|
||
return function(t) {
|
||
return t * t * ((s + 1) * t - s);
|
||
};
|
||
}
|
||
function d3_ease_bounce(t) {
|
||
return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
|
||
}
|
||
d3.interpolateHcl = d3_interpolateHcl;
|
||
function d3_interpolateHcl(a, b) {
|
||
a = d3.hcl(a);
|
||
b = d3.hcl(b);
|
||
var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al;
|
||
if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac;
|
||
if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
|
||
return function(t) {
|
||
return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + "";
|
||
};
|
||
}
|
||
d3.interpolateHsl = d3_interpolateHsl;
|
||
function d3_interpolateHsl(a, b) {
|
||
a = d3.hsl(a);
|
||
b = d3.hsl(b);
|
||
var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al;
|
||
if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as;
|
||
if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
|
||
return function(t) {
|
||
return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + "";
|
||
};
|
||
}
|
||
d3.interpolateLab = d3_interpolateLab;
|
||
function d3_interpolateLab(a, b) {
|
||
a = d3.lab(a);
|
||
b = d3.lab(b);
|
||
var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab;
|
||
return function(t) {
|
||
return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + "";
|
||
};
|
||
}
|
||
d3.interpolateRound = d3_interpolateRound;
|
||
function d3_interpolateRound(a, b) {
|
||
b -= a;
|
||
return function(t) {
|
||
return Math.round(a + b * t);
|
||
};
|
||
}
|
||
d3.transform = function(string) {
|
||
var g = d3_document.createElementNS(d3.ns.prefix.svg, "g");
|
||
return (d3.transform = function(string) {
|
||
if (string != null) {
|
||
g.setAttribute("transform", string);
|
||
var t = g.transform.baseVal.consolidate();
|
||
}
|
||
return new d3_transform(t ? t.matrix : d3_transformIdentity);
|
||
})(string);
|
||
};
|
||
function d3_transform(m) {
|
||
var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;
|
||
if (r0[0] * r1[1] < r1[0] * r0[1]) {
|
||
r0[0] *= -1;
|
||
r0[1] *= -1;
|
||
kx *= -1;
|
||
kz *= -1;
|
||
}
|
||
this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees;
|
||
this.translate = [ m.e, m.f ];
|
||
this.scale = [ kx, ky ];
|
||
this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0;
|
||
}
|
||
d3_transform.prototype.toString = function() {
|
||
return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")";
|
||
};
|
||
function d3_transformDot(a, b) {
|
||
return a[0] * b[0] + a[1] * b[1];
|
||
}
|
||
function d3_transformNormalize(a) {
|
||
var k = Math.sqrt(d3_transformDot(a, a));
|
||
if (k) {
|
||
a[0] /= k;
|
||
a[1] /= k;
|
||
}
|
||
return k;
|
||
}
|
||
function d3_transformCombine(a, b, k) {
|
||
a[0] += k * b[0];
|
||
a[1] += k * b[1];
|
||
return a;
|
||
}
|
||
var d3_transformIdentity = {
|
||
a: 1,
|
||
b: 0,
|
||
c: 0,
|
||
d: 1,
|
||
e: 0,
|
||
f: 0
|
||
};
|
||
d3.interpolateTransform = d3_interpolateTransform;
|
||
function d3_interpolateTransform(a, b) {
|
||
var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale;
|
||
if (ta[0] != tb[0] || ta[1] != tb[1]) {
|
||
s.push("translate(", null, ",", null, ")");
|
||
q.push({
|
||
i: 1,
|
||
x: d3_interpolateNumber(ta[0], tb[0])
|
||
}, {
|
||
i: 3,
|
||
x: d3_interpolateNumber(ta[1], tb[1])
|
||
});
|
||
} else if (tb[0] || tb[1]) {
|
||
s.push("translate(" + tb + ")");
|
||
} else {
|
||
s.push("");
|
||
}
|
||
if (ra != rb) {
|
||
if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360;
|
||
q.push({
|
||
i: s.push(s.pop() + "rotate(", null, ")") - 2,
|
||
x: d3_interpolateNumber(ra, rb)
|
||
});
|
||
} else if (rb) {
|
||
s.push(s.pop() + "rotate(" + rb + ")");
|
||
}
|
||
if (wa != wb) {
|
||
q.push({
|
||
i: s.push(s.pop() + "skewX(", null, ")") - 2,
|
||
x: d3_interpolateNumber(wa, wb)
|
||
});
|
||
} else if (wb) {
|
||
s.push(s.pop() + "skewX(" + wb + ")");
|
||
}
|
||
if (ka[0] != kb[0] || ka[1] != kb[1]) {
|
||
n = s.push(s.pop() + "scale(", null, ",", null, ")");
|
||
q.push({
|
||
i: n - 4,
|
||
x: d3_interpolateNumber(ka[0], kb[0])
|
||
}, {
|
||
i: n - 2,
|
||
x: d3_interpolateNumber(ka[1], kb[1])
|
||
});
|
||
} else if (kb[0] != 1 || kb[1] != 1) {
|
||
s.push(s.pop() + "scale(" + kb + ")");
|
||
}
|
||
n = q.length;
|
||
return function(t) {
|
||
var i = -1, o;
|
||
while (++i < n) s[(o = q[i]).i] = o.x(t);
|
||
return s.join("");
|
||
};
|
||
}
|
||
function d3_uninterpolateNumber(a, b) {
|
||
b = (b -= a = +a) || 1 / b;
|
||
return function(x) {
|
||
return (x - a) / b;
|
||
};
|
||
}
|
||
function d3_uninterpolateClamp(a, b) {
|
||
b = (b -= a = +a) || 1 / b;
|
||
return function(x) {
|
||
return Math.max(0, Math.min(1, (x - a) / b));
|
||
};
|
||
}
|
||
d3.layout = {};
|
||
d3.layout.bundle = function() {
|
||
return function(links) {
|
||
var paths = [], i = -1, n = links.length;
|
||
while (++i < n) paths.push(d3_layout_bundlePath(links[i]));
|
||
return paths;
|
||
};
|
||
};
|
||
function d3_layout_bundlePath(link) {
|
||
var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ];
|
||
while (start !== lca) {
|
||
start = start.parent;
|
||
points.push(start);
|
||
}
|
||
var k = points.length;
|
||
while (end !== lca) {
|
||
points.splice(k, 0, end);
|
||
end = end.parent;
|
||
}
|
||
return points;
|
||
}
|
||
function d3_layout_bundleAncestors(node) {
|
||
var ancestors = [], parent = node.parent;
|
||
while (parent != null) {
|
||
ancestors.push(node);
|
||
node = parent;
|
||
parent = parent.parent;
|
||
}
|
||
ancestors.push(node);
|
||
return ancestors;
|
||
}
|
||
function d3_layout_bundleLeastCommonAncestor(a, b) {
|
||
if (a === b) return a;
|
||
var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null;
|
||
while (aNode === bNode) {
|
||
sharedNode = aNode;
|
||
aNode = aNodes.pop();
|
||
bNode = bNodes.pop();
|
||
}
|
||
return sharedNode;
|
||
}
|
||
d3.layout.chord = function() {
|
||
var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords;
|
||
function relayout() {
|
||
var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j;
|
||
chords = [];
|
||
groups = [];
|
||
k = 0, i = -1;
|
||
while (++i < n) {
|
||
x = 0, j = -1;
|
||
while (++j < n) {
|
||
x += matrix[i][j];
|
||
}
|
||
groupSums.push(x);
|
||
subgroupIndex.push(d3.range(n));
|
||
k += x;
|
||
}
|
||
if (sortGroups) {
|
||
groupIndex.sort(function(a, b) {
|
||
return sortGroups(groupSums[a], groupSums[b]);
|
||
});
|
||
}
|
||
if (sortSubgroups) {
|
||
subgroupIndex.forEach(function(d, i) {
|
||
d.sort(function(a, b) {
|
||
return sortSubgroups(matrix[i][a], matrix[i][b]);
|
||
});
|
||
});
|
||
}
|
||
k = (τ - padding * n) / k;
|
||
x = 0, i = -1;
|
||
while (++i < n) {
|
||
x0 = x, j = -1;
|
||
while (++j < n) {
|
||
var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k;
|
||
subgroups[di + "-" + dj] = {
|
||
index: di,
|
||
subindex: dj,
|
||
startAngle: a0,
|
||
endAngle: a1,
|
||
value: v
|
||
};
|
||
}
|
||
groups[di] = {
|
||
index: di,
|
||
startAngle: x0,
|
||
endAngle: x,
|
||
value: (x - x0) / k
|
||
};
|
||
x += padding;
|
||
}
|
||
i = -1;
|
||
while (++i < n) {
|
||
j = i - 1;
|
||
while (++j < n) {
|
||
var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i];
|
||
if (source.value || target.value) {
|
||
chords.push(source.value < target.value ? {
|
||
source: target,
|
||
target: source
|
||
} : {
|
||
source: source,
|
||
target: target
|
||
});
|
||
}
|
||
}
|
||
}
|
||
if (sortChords) resort();
|
||
}
|
||
function resort() {
|
||
chords.sort(function(a, b) {
|
||
return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2);
|
||
});
|
||
}
|
||
chord.matrix = function(x) {
|
||
if (!arguments.length) return matrix;
|
||
n = (matrix = x) && matrix.length;
|
||
chords = groups = null;
|
||
return chord;
|
||
};
|
||
chord.padding = function(x) {
|
||
if (!arguments.length) return padding;
|
||
padding = x;
|
||
chords = groups = null;
|
||
return chord;
|
||
};
|
||
chord.sortGroups = function(x) {
|
||
if (!arguments.length) return sortGroups;
|
||
sortGroups = x;
|
||
chords = groups = null;
|
||
return chord;
|
||
};
|
||
chord.sortSubgroups = function(x) {
|
||
if (!arguments.length) return sortSubgroups;
|
||
sortSubgroups = x;
|
||
chords = null;
|
||
return chord;
|
||
};
|
||
chord.sortChords = function(x) {
|
||
if (!arguments.length) return sortChords;
|
||
sortChords = x;
|
||
if (chords) resort();
|
||
return chord;
|
||
};
|
||
chord.chords = function() {
|
||
if (!chords) relayout();
|
||
return chords;
|
||
};
|
||
chord.groups = function() {
|
||
if (!groups) relayout();
|
||
return groups;
|
||
};
|
||
return chord;
|
||
};
|
||
d3.layout.force = function() {
|
||
var force = {}, event = d3.dispatch("start", "tick", "end"), size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges;
|
||
function repulse(node) {
|
||
return function(quad, x1, _, x2) {
|
||
if (quad.point !== node) {
|
||
var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy;
|
||
if (dw * dw / theta2 < dn) {
|
||
if (dn < chargeDistance2) {
|
||
var k = quad.charge / dn;
|
||
node.px -= dx * k;
|
||
node.py -= dy * k;
|
||
}
|
||
return true;
|
||
}
|
||
if (quad.point && dn && dn < chargeDistance2) {
|
||
var k = quad.pointCharge / dn;
|
||
node.px -= dx * k;
|
||
node.py -= dy * k;
|
||
}
|
||
}
|
||
return !quad.charge;
|
||
};
|
||
}
|
||
force.tick = function() {
|
||
if ((alpha *= .99) < .005) {
|
||
event.end({
|
||
type: "end",
|
||
alpha: alpha = 0
|
||
});
|
||
return true;
|
||
}
|
||
var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y;
|
||
for (i = 0; i < m; ++i) {
|
||
o = links[i];
|
||
s = o.source;
|
||
t = o.target;
|
||
x = t.x - s.x;
|
||
y = t.y - s.y;
|
||
if (l = x * x + y * y) {
|
||
l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;
|
||
x *= l;
|
||
y *= l;
|
||
t.x -= x * (k = s.weight / (t.weight + s.weight));
|
||
t.y -= y * k;
|
||
s.x += x * (k = 1 - k);
|
||
s.y += y * k;
|
||
}
|
||
}
|
||
if (k = alpha * gravity) {
|
||
x = size[0] / 2;
|
||
y = size[1] / 2;
|
||
i = -1;
|
||
if (k) while (++i < n) {
|
||
o = nodes[i];
|
||
o.x += (x - o.x) * k;
|
||
o.y += (y - o.y) * k;
|
||
}
|
||
}
|
||
if (charge) {
|
||
d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges);
|
||
i = -1;
|
||
while (++i < n) {
|
||
if (!(o = nodes[i]).fixed) {
|
||
q.visit(repulse(o));
|
||
}
|
||
}
|
||
}
|
||
i = -1;
|
||
while (++i < n) {
|
||
o = nodes[i];
|
||
if (o.fixed) {
|
||
o.x = o.px;
|
||
o.y = o.py;
|
||
} else {
|
||
o.x -= (o.px - (o.px = o.x)) * friction;
|
||
o.y -= (o.py - (o.py = o.y)) * friction;
|
||
}
|
||
}
|
||
event.tick({
|
||
type: "tick",
|
||
alpha: alpha
|
||
});
|
||
};
|
||
force.nodes = function(x) {
|
||
if (!arguments.length) return nodes;
|
||
nodes = x;
|
||
return force;
|
||
};
|
||
force.links = function(x) {
|
||
if (!arguments.length) return links;
|
||
links = x;
|
||
return force;
|
||
};
|
||
force.size = function(x) {
|
||
if (!arguments.length) return size;
|
||
size = x;
|
||
return force;
|
||
};
|
||
force.linkDistance = function(x) {
|
||
if (!arguments.length) return linkDistance;
|
||
linkDistance = typeof x === "function" ? x : +x;
|
||
return force;
|
||
};
|
||
force.distance = force.linkDistance;
|
||
force.linkStrength = function(x) {
|
||
if (!arguments.length) return linkStrength;
|
||
linkStrength = typeof x === "function" ? x : +x;
|
||
return force;
|
||
};
|
||
force.friction = function(x) {
|
||
if (!arguments.length) return friction;
|
||
friction = +x;
|
||
return force;
|
||
};
|
||
force.charge = function(x) {
|
||
if (!arguments.length) return charge;
|
||
charge = typeof x === "function" ? x : +x;
|
||
return force;
|
||
};
|
||
force.chargeDistance = function(x) {
|
||
if (!arguments.length) return Math.sqrt(chargeDistance2);
|
||
chargeDistance2 = x * x;
|
||
return force;
|
||
};
|
||
force.gravity = function(x) {
|
||
if (!arguments.length) return gravity;
|
||
gravity = +x;
|
||
return force;
|
||
};
|
||
force.theta = function(x) {
|
||
if (!arguments.length) return Math.sqrt(theta2);
|
||
theta2 = x * x;
|
||
return force;
|
||
};
|
||
force.alpha = function(x) {
|
||
if (!arguments.length) return alpha;
|
||
x = +x;
|
||
if (alpha) {
|
||
if (x > 0) alpha = x; else alpha = 0;
|
||
} else if (x > 0) {
|
||
event.start({
|
||
type: "start",
|
||
alpha: alpha = x
|
||
});
|
||
d3.timer(force.tick);
|
||
}
|
||
return force;
|
||
};
|
||
force.start = function() {
|
||
var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o;
|
||
for (i = 0; i < n; ++i) {
|
||
(o = nodes[i]).index = i;
|
||
o.weight = 0;
|
||
}
|
||
for (i = 0; i < m; ++i) {
|
||
o = links[i];
|
||
if (typeof o.source == "number") o.source = nodes[o.source];
|
||
if (typeof o.target == "number") o.target = nodes[o.target];
|
||
++o.source.weight;
|
||
++o.target.weight;
|
||
}
|
||
for (i = 0; i < n; ++i) {
|
||
o = nodes[i];
|
||
if (isNaN(o.x)) o.x = position("x", w);
|
||
if (isNaN(o.y)) o.y = position("y", h);
|
||
if (isNaN(o.px)) o.px = o.x;
|
||
if (isNaN(o.py)) o.py = o.y;
|
||
}
|
||
distances = [];
|
||
if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance;
|
||
strengths = [];
|
||
if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength;
|
||
charges = [];
|
||
if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge;
|
||
function position(dimension, size) {
|
||
if (!neighbors) {
|
||
neighbors = new Array(n);
|
||
for (j = 0; j < n; ++j) {
|
||
neighbors[j] = [];
|
||
}
|
||
for (j = 0; j < m; ++j) {
|
||
var o = links[j];
|
||
neighbors[o.source.index].push(o.target);
|
||
neighbors[o.target.index].push(o.source);
|
||
}
|
||
}
|
||
var candidates = neighbors[i], j = -1, l = candidates.length, x;
|
||
while (++j < l) if (!isNaN(x = candidates[j][dimension])) return x;
|
||
return Math.random() * size;
|
||
}
|
||
return force.resume();
|
||
};
|
||
force.resume = function() {
|
||
return force.alpha(.1);
|
||
};
|
||
force.stop = function() {
|
||
return force.alpha(0);
|
||
};
|
||
force.drag = function() {
|
||
if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend);
|
||
if (!arguments.length) return drag;
|
||
this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag);
|
||
};
|
||
function dragmove(d) {
|
||
d.px = d3.event.x, d.py = d3.event.y;
|
||
force.resume();
|
||
}
|
||
return d3.rebind(force, event, "on");
|
||
};
|
||
function d3_layout_forceDragstart(d) {
|
||
d.fixed |= 2;
|
||
}
|
||
function d3_layout_forceDragend(d) {
|
||
d.fixed &= ~6;
|
||
}
|
||
function d3_layout_forceMouseover(d) {
|
||
d.fixed |= 4;
|
||
d.px = d.x, d.py = d.y;
|
||
}
|
||
function d3_layout_forceMouseout(d) {
|
||
d.fixed &= ~4;
|
||
}
|
||
function d3_layout_forceAccumulate(quad, alpha, charges) {
|
||
var cx = 0, cy = 0;
|
||
quad.charge = 0;
|
||
if (!quad.leaf) {
|
||
var nodes = quad.nodes, n = nodes.length, i = -1, c;
|
||
while (++i < n) {
|
||
c = nodes[i];
|
||
if (c == null) continue;
|
||
d3_layout_forceAccumulate(c, alpha, charges);
|
||
quad.charge += c.charge;
|
||
cx += c.charge * c.cx;
|
||
cy += c.charge * c.cy;
|
||
}
|
||
}
|
||
if (quad.point) {
|
||
if (!quad.leaf) {
|
||
quad.point.x += Math.random() - .5;
|
||
quad.point.y += Math.random() - .5;
|
||
}
|
||
var k = alpha * charges[quad.point.index];
|
||
quad.charge += quad.pointCharge = k;
|
||
cx += k * quad.point.x;
|
||
cy += k * quad.point.y;
|
||
}
|
||
quad.cx = cx / quad.charge;
|
||
quad.cy = cy / quad.charge;
|
||
}
|
||
var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity;
|
||
d3.layout.hierarchy = function() {
|
||
var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue;
|
||
function hierarchy(root) {
|
||
var stack = [ root ], nodes = [], node;
|
||
root.depth = 0;
|
||
while ((node = stack.pop()) != null) {
|
||
nodes.push(node);
|
||
if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) {
|
||
var n, childs, child;
|
||
while (--n >= 0) {
|
||
stack.push(child = childs[n]);
|
||
child.parent = node;
|
||
child.depth = node.depth + 1;
|
||
}
|
||
if (value) node.value = 0;
|
||
node.children = childs;
|
||
} else {
|
||
if (value) node.value = +value.call(hierarchy, node, node.depth) || 0;
|
||
delete node.children;
|
||
}
|
||
}
|
||
d3_layout_hierarchyVisitAfter(root, function(node) {
|
||
var childs, parent;
|
||
if (sort && (childs = node.children)) childs.sort(sort);
|
||
if (value && (parent = node.parent)) parent.value += node.value;
|
||
});
|
||
return nodes;
|
||
}
|
||
hierarchy.sort = function(x) {
|
||
if (!arguments.length) return sort;
|
||
sort = x;
|
||
return hierarchy;
|
||
};
|
||
hierarchy.children = function(x) {
|
||
if (!arguments.length) return children;
|
||
children = x;
|
||
return hierarchy;
|
||
};
|
||
hierarchy.value = function(x) {
|
||
if (!arguments.length) return value;
|
||
value = x;
|
||
return hierarchy;
|
||
};
|
||
hierarchy.revalue = function(root) {
|
||
if (value) {
|
||
d3_layout_hierarchyVisitBefore(root, function(node) {
|
||
if (node.children) node.value = 0;
|
||
});
|
||
d3_layout_hierarchyVisitAfter(root, function(node) {
|
||
var parent;
|
||
if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0;
|
||
if (parent = node.parent) parent.value += node.value;
|
||
});
|
||
}
|
||
return root;
|
||
};
|
||
return hierarchy;
|
||
};
|
||
function d3_layout_hierarchyRebind(object, hierarchy) {
|
||
d3.rebind(object, hierarchy, "sort", "children", "value");
|
||
object.nodes = object;
|
||
object.links = d3_layout_hierarchyLinks;
|
||
return object;
|
||
}
|
||
function d3_layout_hierarchyVisitBefore(node, callback) {
|
||
var nodes = [ node ];
|
||
while ((node = nodes.pop()) != null) {
|
||
callback(node);
|
||
if ((children = node.children) && (n = children.length)) {
|
||
var n, children;
|
||
while (--n >= 0) nodes.push(children[n]);
|
||
}
|
||
}
|
||
}
|
||
function d3_layout_hierarchyVisitAfter(node, callback) {
|
||
var nodes = [ node ], nodes2 = [];
|
||
while ((node = nodes.pop()) != null) {
|
||
nodes2.push(node);
|
||
if ((children = node.children) && (n = children.length)) {
|
||
var i = -1, n, children;
|
||
while (++i < n) nodes.push(children[i]);
|
||
}
|
||
}
|
||
while ((node = nodes2.pop()) != null) {
|
||
callback(node);
|
||
}
|
||
}
|
||
function d3_layout_hierarchyChildren(d) {
|
||
return d.children;
|
||
}
|
||
function d3_layout_hierarchyValue(d) {
|
||
return d.value;
|
||
}
|
||
function d3_layout_hierarchySort(a, b) {
|
||
return b.value - a.value;
|
||
}
|
||
function d3_layout_hierarchyLinks(nodes) {
|
||
return d3.merge(nodes.map(function(parent) {
|
||
return (parent.children || []).map(function(child) {
|
||
return {
|
||
source: parent,
|
||
target: child
|
||
};
|
||
});
|
||
}));
|
||
}
|
||
d3.layout.partition = function() {
|
||
var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ];
|
||
function position(node, x, dx, dy) {
|
||
var children = node.children;
|
||
node.x = x;
|
||
node.y = node.depth * dy;
|
||
node.dx = dx;
|
||
node.dy = dy;
|
||
if (children && (n = children.length)) {
|
||
var i = -1, n, c, d;
|
||
dx = node.value ? dx / node.value : 0;
|
||
while (++i < n) {
|
||
position(c = children[i], x, d = c.value * dx, dy);
|
||
x += d;
|
||
}
|
||
}
|
||
}
|
||
function depth(node) {
|
||
var children = node.children, d = 0;
|
||
if (children && (n = children.length)) {
|
||
var i = -1, n;
|
||
while (++i < n) d = Math.max(d, depth(children[i]));
|
||
}
|
||
return 1 + d;
|
||
}
|
||
function partition(d, i) {
|
||
var nodes = hierarchy.call(this, d, i);
|
||
position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));
|
||
return nodes;
|
||
}
|
||
partition.size = function(x) {
|
||
if (!arguments.length) return size;
|
||
size = x;
|
||
return partition;
|
||
};
|
||
return d3_layout_hierarchyRebind(partition, hierarchy);
|
||
};
|
||
d3.layout.pie = function() {
|
||
var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ, padAngle = 0;
|
||
function pie(data) {
|
||
var n = data.length, values = data.map(function(d, i) {
|
||
return +value.call(pie, d, i);
|
||
}), a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle), da = (typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a, p = Math.min(Math.abs(da) / n, +(typeof padAngle === "function" ? padAngle.apply(this, arguments) : padAngle)), pa = p * (da < 0 ? -1 : 1), k = (da - n * pa) / d3.sum(values), index = d3.range(n), arcs = [], v;
|
||
if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) {
|
||
return values[j] - values[i];
|
||
} : function(i, j) {
|
||
return sort(data[i], data[j]);
|
||
});
|
||
index.forEach(function(i) {
|
||
arcs[i] = {
|
||
data: data[i],
|
||
value: v = values[i],
|
||
startAngle: a,
|
||
endAngle: a += v * k + pa,
|
||
padAngle: p
|
||
};
|
||
});
|
||
return arcs;
|
||
}
|
||
pie.value = function(_) {
|
||
if (!arguments.length) return value;
|
||
value = _;
|
||
return pie;
|
||
};
|
||
pie.sort = function(_) {
|
||
if (!arguments.length) return sort;
|
||
sort = _;
|
||
return pie;
|
||
};
|
||
pie.startAngle = function(_) {
|
||
if (!arguments.length) return startAngle;
|
||
startAngle = _;
|
||
return pie;
|
||
};
|
||
pie.endAngle = function(_) {
|
||
if (!arguments.length) return endAngle;
|
||
endAngle = _;
|
||
return pie;
|
||
};
|
||
pie.padAngle = function(_) {
|
||
if (!arguments.length) return padAngle;
|
||
padAngle = _;
|
||
return pie;
|
||
};
|
||
return pie;
|
||
};
|
||
var d3_layout_pieSortByValue = {};
|
||
d3.layout.stack = function() {
|
||
var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY;
|
||
function stack(data, index) {
|
||
if (!(n = data.length)) return data;
|
||
var series = data.map(function(d, i) {
|
||
return values.call(stack, d, i);
|
||
});
|
||
var points = series.map(function(d) {
|
||
return d.map(function(v, i) {
|
||
return [ x.call(stack, v, i), y.call(stack, v, i) ];
|
||
});
|
||
});
|
||
var orders = order.call(stack, points, index);
|
||
series = d3.permute(series, orders);
|
||
points = d3.permute(points, orders);
|
||
var offsets = offset.call(stack, points, index);
|
||
var m = series[0].length, n, i, j, o;
|
||
for (j = 0; j < m; ++j) {
|
||
out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);
|
||
for (i = 1; i < n; ++i) {
|
||
out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);
|
||
}
|
||
}
|
||
return data;
|
||
}
|
||
stack.values = function(x) {
|
||
if (!arguments.length) return values;
|
||
values = x;
|
||
return stack;
|
||
};
|
||
stack.order = function(x) {
|
||
if (!arguments.length) return order;
|
||
order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault;
|
||
return stack;
|
||
};
|
||
stack.offset = function(x) {
|
||
if (!arguments.length) return offset;
|
||
offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero;
|
||
return stack;
|
||
};
|
||
stack.x = function(z) {
|
||
if (!arguments.length) return x;
|
||
x = z;
|
||
return stack;
|
||
};
|
||
stack.y = function(z) {
|
||
if (!arguments.length) return y;
|
||
y = z;
|
||
return stack;
|
||
};
|
||
stack.out = function(z) {
|
||
if (!arguments.length) return out;
|
||
out = z;
|
||
return stack;
|
||
};
|
||
return stack;
|
||
};
|
||
function d3_layout_stackX(d) {
|
||
return d.x;
|
||
}
|
||
function d3_layout_stackY(d) {
|
||
return d.y;
|
||
}
|
||
function d3_layout_stackOut(d, y0, y) {
|
||
d.y0 = y0;
|
||
d.y = y;
|
||
}
|
||
var d3_layout_stackOrders = d3.map({
|
||
"inside-out": function(data) {
|
||
var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) {
|
||
return max[a] - max[b];
|
||
}), top = 0, bottom = 0, tops = [], bottoms = [];
|
||
for (i = 0; i < n; ++i) {
|
||
j = index[i];
|
||
if (top < bottom) {
|
||
top += sums[j];
|
||
tops.push(j);
|
||
} else {
|
||
bottom += sums[j];
|
||
bottoms.push(j);
|
||
}
|
||
}
|
||
return bottoms.reverse().concat(tops);
|
||
},
|
||
reverse: function(data) {
|
||
return d3.range(data.length).reverse();
|
||
},
|
||
"default": d3_layout_stackOrderDefault
|
||
});
|
||
var d3_layout_stackOffsets = d3.map({
|
||
silhouette: function(data) {
|
||
var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = [];
|
||
for (j = 0; j < m; ++j) {
|
||
for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
|
||
if (o > max) max = o;
|
||
sums.push(o);
|
||
}
|
||
for (j = 0; j < m; ++j) {
|
||
y0[j] = (max - sums[j]) / 2;
|
||
}
|
||
return y0;
|
||
},
|
||
wiggle: function(data) {
|
||
var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = [];
|
||
y0[0] = o = o0 = 0;
|
||
for (j = 1; j < m; ++j) {
|
||
for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1];
|
||
for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) {
|
||
for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) {
|
||
s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;
|
||
}
|
||
s2 += s3 * data[i][j][1];
|
||
}
|
||
y0[j] = o -= s1 ? s2 / s1 * dx : 0;
|
||
if (o < o0) o0 = o;
|
||
}
|
||
for (j = 0; j < m; ++j) y0[j] -= o0;
|
||
return y0;
|
||
},
|
||
expand: function(data) {
|
||
var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = [];
|
||
for (j = 0; j < m; ++j) {
|
||
for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
|
||
if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k;
|
||
}
|
||
for (j = 0; j < m; ++j) y0[j] = 0;
|
||
return y0;
|
||
},
|
||
zero: d3_layout_stackOffsetZero
|
||
});
|
||
function d3_layout_stackOrderDefault(data) {
|
||
return d3.range(data.length);
|
||
}
|
||
function d3_layout_stackOffsetZero(data) {
|
||
var j = -1, m = data[0].length, y0 = [];
|
||
while (++j < m) y0[j] = 0;
|
||
return y0;
|
||
}
|
||
function d3_layout_stackMaxIndex(array) {
|
||
var i = 1, j = 0, v = array[0][1], k, n = array.length;
|
||
for (;i < n; ++i) {
|
||
if ((k = array[i][1]) > v) {
|
||
j = i;
|
||
v = k;
|
||
}
|
||
}
|
||
return j;
|
||
}
|
||
function d3_layout_stackReduceSum(d) {
|
||
return d.reduce(d3_layout_stackSum, 0);
|
||
}
|
||
function d3_layout_stackSum(p, d) {
|
||
return p + d[1];
|
||
}
|
||
d3.layout.histogram = function() {
|
||
var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges;
|
||
function histogram(data, i) {
|
||
var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x;
|
||
while (++i < m) {
|
||
bin = bins[i] = [];
|
||
bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);
|
||
bin.y = 0;
|
||
}
|
||
if (m > 0) {
|
||
i = -1;
|
||
while (++i < n) {
|
||
x = values[i];
|
||
if (x >= range[0] && x <= range[1]) {
|
||
bin = bins[d3.bisect(thresholds, x, 1, m) - 1];
|
||
bin.y += k;
|
||
bin.push(data[i]);
|
||
}
|
||
}
|
||
}
|
||
return bins;
|
||
}
|
||
histogram.value = function(x) {
|
||
if (!arguments.length) return valuer;
|
||
valuer = x;
|
||
return histogram;
|
||
};
|
||
histogram.range = function(x) {
|
||
if (!arguments.length) return ranger;
|
||
ranger = d3_functor(x);
|
||
return histogram;
|
||
};
|
||
histogram.bins = function(x) {
|
||
if (!arguments.length) return binner;
|
||
binner = typeof x === "number" ? function(range) {
|
||
return d3_layout_histogramBinFixed(range, x);
|
||
} : d3_functor(x);
|
||
return histogram;
|
||
};
|
||
histogram.frequency = function(x) {
|
||
if (!arguments.length) return frequency;
|
||
frequency = !!x;
|
||
return histogram;
|
||
};
|
||
return histogram;
|
||
};
|
||
function d3_layout_histogramBinSturges(range, values) {
|
||
return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
|
||
}
|
||
function d3_layout_histogramBinFixed(range, n) {
|
||
var x = -1, b = +range[0], m = (range[1] - b) / n, f = [];
|
||
while (++x <= n) f[x] = m * x + b;
|
||
return f;
|
||
}
|
||
function d3_layout_histogramRange(values) {
|
||
return [ d3.min(values), d3.max(values) ];
|
||
}
|
||
d3.layout.pack = function() {
|
||
var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius;
|
||
function pack(d, i) {
|
||
var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() {
|
||
return radius;
|
||
};
|
||
root.x = root.y = 0;
|
||
d3_layout_hierarchyVisitAfter(root, function(d) {
|
||
d.r = +r(d.value);
|
||
});
|
||
d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);
|
||
if (padding) {
|
||
var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2;
|
||
d3_layout_hierarchyVisitAfter(root, function(d) {
|
||
d.r += dr;
|
||
});
|
||
d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);
|
||
d3_layout_hierarchyVisitAfter(root, function(d) {
|
||
d.r -= dr;
|
||
});
|
||
}
|
||
d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h));
|
||
return nodes;
|
||
}
|
||
pack.size = function(_) {
|
||
if (!arguments.length) return size;
|
||
size = _;
|
||
return pack;
|
||
};
|
||
pack.radius = function(_) {
|
||
if (!arguments.length) return radius;
|
||
radius = _ == null || typeof _ === "function" ? _ : +_;
|
||
return pack;
|
||
};
|
||
pack.padding = function(_) {
|
||
if (!arguments.length) return padding;
|
||
padding = +_;
|
||
return pack;
|
||
};
|
||
return d3_layout_hierarchyRebind(pack, hierarchy);
|
||
};
|
||
function d3_layout_packSort(a, b) {
|
||
return a.value - b.value;
|
||
}
|
||
function d3_layout_packInsert(a, b) {
|
||
var c = a._pack_next;
|
||
a._pack_next = b;
|
||
b._pack_prev = a;
|
||
b._pack_next = c;
|
||
c._pack_prev = b;
|
||
}
|
||
function d3_layout_packSplice(a, b) {
|
||
a._pack_next = b;
|
||
b._pack_prev = a;
|
||
}
|
||
function d3_layout_packIntersects(a, b) {
|
||
var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r;
|
||
return .999 * dr * dr > dx * dx + dy * dy;
|
||
}
|
||
function d3_layout_packSiblings(node) {
|
||
if (!(nodes = node.children) || !(n = nodes.length)) return;
|
||
var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n;
|
||
function bound(node) {
|
||
xMin = Math.min(node.x - node.r, xMin);
|
||
xMax = Math.max(node.x + node.r, xMax);
|
||
yMin = Math.min(node.y - node.r, yMin);
|
||
yMax = Math.max(node.y + node.r, yMax);
|
||
}
|
||
nodes.forEach(d3_layout_packLink);
|
||
a = nodes[0];
|
||
a.x = -a.r;
|
||
a.y = 0;
|
||
bound(a);
|
||
if (n > 1) {
|
||
b = nodes[1];
|
||
b.x = b.r;
|
||
b.y = 0;
|
||
bound(b);
|
||
if (n > 2) {
|
||
c = nodes[2];
|
||
d3_layout_packPlace(a, b, c);
|
||
bound(c);
|
||
d3_layout_packInsert(a, c);
|
||
a._pack_prev = c;
|
||
d3_layout_packInsert(c, b);
|
||
b = a._pack_next;
|
||
for (i = 3; i < n; i++) {
|
||
d3_layout_packPlace(a, b, c = nodes[i]);
|
||
var isect = 0, s1 = 1, s2 = 1;
|
||
for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {
|
||
if (d3_layout_packIntersects(j, c)) {
|
||
isect = 1;
|
||
break;
|
||
}
|
||
}
|
||
if (isect == 1) {
|
||
for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) {
|
||
if (d3_layout_packIntersects(k, c)) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (isect) {
|
||
if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b);
|
||
i--;
|
||
} else {
|
||
d3_layout_packInsert(a, c);
|
||
b = c;
|
||
bound(c);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0;
|
||
for (i = 0; i < n; i++) {
|
||
c = nodes[i];
|
||
c.x -= cx;
|
||
c.y -= cy;
|
||
cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y));
|
||
}
|
||
node.r = cr;
|
||
nodes.forEach(d3_layout_packUnlink);
|
||
}
|
||
function d3_layout_packLink(node) {
|
||
node._pack_next = node._pack_prev = node;
|
||
}
|
||
function d3_layout_packUnlink(node) {
|
||
delete node._pack_next;
|
||
delete node._pack_prev;
|
||
}
|
||
function d3_layout_packTransform(node, x, y, k) {
|
||
var children = node.children;
|
||
node.x = x += k * node.x;
|
||
node.y = y += k * node.y;
|
||
node.r *= k;
|
||
if (children) {
|
||
var i = -1, n = children.length;
|
||
while (++i < n) d3_layout_packTransform(children[i], x, y, k);
|
||
}
|
||
}
|
||
function d3_layout_packPlace(a, b, c) {
|
||
var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y;
|
||
if (db && (dx || dy)) {
|
||
var da = b.r + c.r, dc = dx * dx + dy * dy;
|
||
da *= da;
|
||
db *= db;
|
||
var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
|
||
c.x = a.x + x * dx + y * dy;
|
||
c.y = a.y + x * dy - y * dx;
|
||
} else {
|
||
c.x = a.x + db;
|
||
c.y = a.y;
|
||
}
|
||
}
|
||
d3.layout.tree = function() {
|
||
var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null;
|
||
function tree(d, i) {
|
||
var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0);
|
||
d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z;
|
||
d3_layout_hierarchyVisitBefore(root1, secondWalk);
|
||
if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else {
|
||
var left = root0, right = root0, bottom = root0;
|
||
d3_layout_hierarchyVisitBefore(root0, function(node) {
|
||
if (node.x < left.x) left = node;
|
||
if (node.x > right.x) right = node;
|
||
if (node.depth > bottom.depth) bottom = node;
|
||
});
|
||
var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1);
|
||
d3_layout_hierarchyVisitBefore(root0, function(node) {
|
||
node.x = (node.x + tx) * kx;
|
||
node.y = node.depth * ky;
|
||
});
|
||
}
|
||
return nodes;
|
||
}
|
||
function wrapTree(root0) {
|
||
var root1 = {
|
||
A: null,
|
||
children: [ root0 ]
|
||
}, queue = [ root1 ], node1;
|
||
while ((node1 = queue.pop()) != null) {
|
||
for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) {
|
||
queue.push((children[i] = child = {
|
||
_: children[i],
|
||
parent: node1,
|
||
children: (child = children[i].children) && child.slice() || [],
|
||
A: null,
|
||
a: null,
|
||
z: 0,
|
||
m: 0,
|
||
c: 0,
|
||
s: 0,
|
||
t: null,
|
||
i: i
|
||
}).a = child);
|
||
}
|
||
}
|
||
return root1.children[0];
|
||
}
|
||
function firstWalk(v) {
|
||
var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null;
|
||
if (children.length) {
|
||
d3_layout_treeShift(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]);
|
||
}
|
||
function secondWalk(v) {
|
||
v._.x = v.z + v.parent.m;
|
||
v.m += v.parent.m;
|
||
}
|
||
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 = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {
|
||
vom = d3_layout_treeLeft(vom);
|
||
vop = d3_layout_treeRight(vop);
|
||
vop.a = v;
|
||
shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
|
||
if (shift > 0) {
|
||
d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift);
|
||
sip += shift;
|
||
sop += shift;
|
||
}
|
||
sim += vim.m;
|
||
sip += vip.m;
|
||
som += vom.m;
|
||
sop += vop.m;
|
||
}
|
||
if (vim && !d3_layout_treeRight(vop)) {
|
||
vop.t = vim;
|
||
vop.m += sim - sop;
|
||
}
|
||
if (vip && !d3_layout_treeLeft(vom)) {
|
||
vom.t = vip;
|
||
vom.m += sip - som;
|
||
ancestor = v;
|
||
}
|
||
}
|
||
return ancestor;
|
||
}
|
||
function sizeNode(node) {
|
||
node.x *= size[0];
|
||
node.y = node.depth * size[1];
|
||
}
|
||
tree.separation = function(x) {
|
||
if (!arguments.length) return separation;
|
||
separation = x;
|
||
return tree;
|
||
};
|
||
tree.size = function(x) {
|
||
if (!arguments.length) return nodeSize ? null : size;
|
||
nodeSize = (size = x) == null ? sizeNode : null;
|
||
return tree;
|
||
};
|
||
tree.nodeSize = function(x) {
|
||
if (!arguments.length) return nodeSize ? size : null;
|
||
nodeSize = (size = x) == null ? null : sizeNode;
|
||
return tree;
|
||
};
|
||
return d3_layout_hierarchyRebind(tree, hierarchy);
|
||
};
|
||
function d3_layout_treeSeparation(a, b) {
|
||
return a.parent == b.parent ? 1 : 2;
|
||
}
|
||
function d3_layout_treeLeft(v) {
|
||
var children = v.children;
|
||
return children.length ? children[0] : v.t;
|
||
}
|
||
function d3_layout_treeRight(v) {
|
||
var children = v.children, n;
|
||
return (n = children.length) ? children[n - 1] : v.t;
|
||
}
|
||
function d3_layout_treeMove(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;
|
||
}
|
||
function d3_layout_treeShift(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);
|
||
}
|
||
}
|
||
function d3_layout_treeAncestor(vim, v, ancestor) {
|
||
return vim.a.parent === v.parent ? vim.a : ancestor;
|
||
}
|
||
d3.layout.cluster = function() {
|
||
var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false;
|
||
function cluster(d, i) {
|
||
var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0;
|
||
d3_layout_hierarchyVisitAfter(root, function(node) {
|
||
var children = node.children;
|
||
if (children && children.length) {
|
||
node.x = d3_layout_clusterX(children);
|
||
node.y = d3_layout_clusterY(children);
|
||
} else {
|
||
node.x = previousNode ? x += separation(node, previousNode) : 0;
|
||
node.y = 0;
|
||
previousNode = node;
|
||
}
|
||
});
|
||
var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2;
|
||
d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) {
|
||
node.x = (node.x - root.x) * size[0];
|
||
node.y = (root.y - node.y) * size[1];
|
||
} : function(node) {
|
||
node.x = (node.x - x0) / (x1 - x0) * size[0];
|
||
node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1];
|
||
});
|
||
return nodes;
|
||
}
|
||
cluster.separation = function(x) {
|
||
if (!arguments.length) return separation;
|
||
separation = x;
|
||
return cluster;
|
||
};
|
||
cluster.size = function(x) {
|
||
if (!arguments.length) return nodeSize ? null : size;
|
||
nodeSize = (size = x) == null;
|
||
return cluster;
|
||
};
|
||
cluster.nodeSize = function(x) {
|
||
if (!arguments.length) return nodeSize ? size : null;
|
||
nodeSize = (size = x) != null;
|
||
return cluster;
|
||
};
|
||
return d3_layout_hierarchyRebind(cluster, hierarchy);
|
||
};
|
||
function d3_layout_clusterY(children) {
|
||
return 1 + d3.max(children, function(child) {
|
||
return child.y;
|
||
});
|
||
}
|
||
function d3_layout_clusterX(children) {
|
||
return children.reduce(function(x, child) {
|
||
return x + child.x;
|
||
}, 0) / children.length;
|
||
}
|
||
function d3_layout_clusterLeft(node) {
|
||
var children = node.children;
|
||
return children && children.length ? d3_layout_clusterLeft(children[0]) : node;
|
||
}
|
||
function d3_layout_clusterRight(node) {
|
||
var children = node.children, n;
|
||
return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;
|
||
}
|
||
d3.layout.treemap = function() {
|
||
var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5));
|
||
function scale(children, k) {
|
||
var i = -1, n = children.length, child, area;
|
||
while (++i < n) {
|
||
area = (child = children[i]).value * (k < 0 ? 0 : k);
|
||
child.area = isNaN(area) || area <= 0 ? 0 : area;
|
||
}
|
||
}
|
||
function squarify(node) {
|
||
var children = node.children;
|
||
if (children && children.length) {
|
||
var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n;
|
||
scale(remaining, rect.dx * rect.dy / node.value);
|
||
row.area = 0;
|
||
while ((n = remaining.length) > 0) {
|
||
row.push(child = remaining[n - 1]);
|
||
row.area += child.area;
|
||
if (mode !== "squarify" || (score = worst(row, u)) <= best) {
|
||
remaining.pop();
|
||
best = score;
|
||
} else {
|
||
row.area -= row.pop().area;
|
||
position(row, u, rect, false);
|
||
u = Math.min(rect.dx, rect.dy);
|
||
row.length = row.area = 0;
|
||
best = Infinity;
|
||
}
|
||
}
|
||
if (row.length) {
|
||
position(row, u, rect, true);
|
||
row.length = row.area = 0;
|
||
}
|
||
children.forEach(squarify);
|
||
}
|
||
}
|
||
function stickify(node) {
|
||
var children = node.children;
|
||
if (children && children.length) {
|
||
var rect = pad(node), remaining = children.slice(), child, row = [];
|
||
scale(remaining, rect.dx * rect.dy / node.value);
|
||
row.area = 0;
|
||
while (child = remaining.pop()) {
|
||
row.push(child);
|
||
row.area += child.area;
|
||
if (child.z != null) {
|
||
position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length);
|
||
row.length = row.area = 0;
|
||
}
|
||
}
|
||
children.forEach(stickify);
|
||
}
|
||
}
|
||
function worst(row, u) {
|
||
var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length;
|
||
while (++i < n) {
|
||
if (!(r = row[i].area)) continue;
|
||
if (r < rmin) rmin = r;
|
||
if (r > rmax) rmax = r;
|
||
}
|
||
s *= s;
|
||
u *= u;
|
||
return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity;
|
||
}
|
||
function position(row, u, rect, flush) {
|
||
var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o;
|
||
if (u == rect.dx) {
|
||
if (flush || v > rect.dy) v = rect.dy;
|
||
while (++i < n) {
|
||
o = row[i];
|
||
o.x = x;
|
||
o.y = y;
|
||
o.dy = v;
|
||
x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0);
|
||
}
|
||
o.z = true;
|
||
o.dx += rect.x + rect.dx - x;
|
||
rect.y += v;
|
||
rect.dy -= v;
|
||
} else {
|
||
if (flush || v > rect.dx) v = rect.dx;
|
||
while (++i < n) {
|
||
o = row[i];
|
||
o.x = x;
|
||
o.y = y;
|
||
o.dx = v;
|
||
y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0);
|
||
}
|
||
o.z = false;
|
||
o.dy += rect.y + rect.dy - y;
|
||
rect.x += v;
|
||
rect.dx -= v;
|
||
}
|
||
}
|
||
function treemap(d) {
|
||
var nodes = stickies || hierarchy(d), root = nodes[0];
|
||
root.x = 0;
|
||
root.y = 0;
|
||
root.dx = size[0];
|
||
root.dy = size[1];
|
||
if (stickies) hierarchy.revalue(root);
|
||
scale([ root ], root.dx * root.dy / root.value);
|
||
(stickies ? stickify : squarify)(root);
|
||
if (sticky) stickies = nodes;
|
||
return nodes;
|
||
}
|
||
treemap.size = function(x) {
|
||
if (!arguments.length) return size;
|
||
size = x;
|
||
return treemap;
|
||
};
|
||
treemap.padding = function(x) {
|
||
if (!arguments.length) return padding;
|
||
function padFunction(node) {
|
||
var p = x.call(treemap, node, node.depth);
|
||
return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p);
|
||
}
|
||
function padConstant(node) {
|
||
return d3_layout_treemapPad(node, x);
|
||
}
|
||
var type;
|
||
pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ],
|
||
padConstant) : padConstant;
|
||
return treemap;
|
||
};
|
||
treemap.round = function(x) {
|
||
if (!arguments.length) return round != Number;
|
||
round = x ? Math.round : Number;
|
||
return treemap;
|
||
};
|
||
treemap.sticky = function(x) {
|
||
if (!arguments.length) return sticky;
|
||
sticky = x;
|
||
stickies = null;
|
||
return treemap;
|
||
};
|
||
treemap.ratio = function(x) {
|
||
if (!arguments.length) return ratio;
|
||
ratio = x;
|
||
return treemap;
|
||
};
|
||
treemap.mode = function(x) {
|
||
if (!arguments.length) return mode;
|
||
mode = x + "";
|
||
return treemap;
|
||
};
|
||
return d3_layout_hierarchyRebind(treemap, hierarchy);
|
||
};
|
||
function d3_layout_treemapPadNull(node) {
|
||
return {
|
||
x: node.x,
|
||
y: node.y,
|
||
dx: node.dx,
|
||
dy: node.dy
|
||
};
|
||
}
|
||
function d3_layout_treemapPad(node, padding) {
|
||
var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2];
|
||
if (dx < 0) {
|
||
x += dx / 2;
|
||
dx = 0;
|
||
}
|
||
if (dy < 0) {
|
||
y += dy / 2;
|
||
dy = 0;
|
||
}
|
||
return {
|
||
x: x,
|
||
y: y,
|
||
dx: dx,
|
||
dy: dy
|
||
};
|
||
}
|
||
d3.random = {
|
||
normal: function(µ, σ) {
|
||
var n = arguments.length;
|
||
if (n < 2) σ = 1;
|
||
if (n < 1) µ = 0;
|
||
return function() {
|
||
var x, y, r;
|
||
do {
|
||
x = Math.random() * 2 - 1;
|
||
y = Math.random() * 2 - 1;
|
||
r = x * x + y * y;
|
||
} while (!r || r > 1);
|
||
return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r);
|
||
};
|
||
},
|
||
logNormal: function() {
|
||
var random = d3.random.normal.apply(d3, arguments);
|
||
return function() {
|
||
return Math.exp(random());
|
||
};
|
||
},
|
||
bates: function(m) {
|
||
var random = d3.random.irwinHall(m);
|
||
return function() {
|
||
return random() / m;
|
||
};
|
||
},
|
||
irwinHall: function(m) {
|
||
return function() {
|
||
for (var s = 0, j = 0; j < m; j++) s += Math.random();
|
||
return s;
|
||
};
|
||
}
|
||
};
|
||
d3.scale = {};
|
||
function d3_scaleExtent(domain) {
|
||
var start = domain[0], stop = domain[domain.length - 1];
|
||
return start < stop ? [ start, stop ] : [ stop, start ];
|
||
}
|
||
function d3_scaleRange(scale) {
|
||
return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());
|
||
}
|
||
function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {
|
||
var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]);
|
||
return function(x) {
|
||
return i(u(x));
|
||
};
|
||
}
|
||
function d3_scale_nice(domain, nice) {
|
||
var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx;
|
||
if (x1 < x0) {
|
||
dx = i0, i0 = i1, i1 = dx;
|
||
dx = x0, x0 = x1, x1 = dx;
|
||
}
|
||
domain[i0] = nice.floor(x0);
|
||
domain[i1] = nice.ceil(x1);
|
||
return domain;
|
||
}
|
||
function d3_scale_niceStep(step) {
|
||
return step ? {
|
||
floor: function(x) {
|
||
return Math.floor(x / step) * step;
|
||
},
|
||
ceil: function(x) {
|
||
return Math.ceil(x / step) * step;
|
||
}
|
||
} : d3_scale_niceIdentity;
|
||
}
|
||
var d3_scale_niceIdentity = {
|
||
floor: d3_identity,
|
||
ceil: d3_identity
|
||
};
|
||
function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
|
||
var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1;
|
||
if (domain[k] < domain[0]) {
|
||
domain = domain.slice().reverse();
|
||
range = range.slice().reverse();
|
||
}
|
||
while (++j <= k) {
|
||
u.push(uninterpolate(domain[j - 1], domain[j]));
|
||
i.push(interpolate(range[j - 1], range[j]));
|
||
}
|
||
return function(x) {
|
||
var j = d3.bisect(domain, x, 1, k) - 1;
|
||
return i[j](u[j](x));
|
||
};
|
||
}
|
||
d3.scale.linear = function() {
|
||
return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false);
|
||
};
|
||
function d3_scale_linear(domain, range, interpolate, clamp) {
|
||
var output, input;
|
||
function rescale() {
|
||
var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;
|
||
output = linear(domain, range, uninterpolate, interpolate);
|
||
input = linear(range, domain, uninterpolate, d3_interpolate);
|
||
return scale;
|
||
}
|
||
function scale(x) {
|
||
return output(x);
|
||
}
|
||
scale.invert = function(y) {
|
||
return input(y);
|
||
};
|
||
scale.domain = function(x) {
|
||
if (!arguments.length) return domain;
|
||
domain = x.map(Number);
|
||
return rescale();
|
||
};
|
||
scale.range = function(x) {
|
||
if (!arguments.length) return range;
|
||
range = x;
|
||
return rescale();
|
||
};
|
||
scale.rangeRound = function(x) {
|
||
return scale.range(x).interpolate(d3_interpolateRound);
|
||
};
|
||
scale.clamp = function(x) {
|
||
if (!arguments.length) return clamp;
|
||
clamp = x;
|
||
return rescale();
|
||
};
|
||
scale.interpolate = function(x) {
|
||
if (!arguments.length) return interpolate;
|
||
interpolate = x;
|
||
return rescale();
|
||
};
|
||
scale.ticks = function(m) {
|
||
return d3_scale_linearTicks(domain, m);
|
||
};
|
||
scale.tickFormat = function(m, format) {
|
||
return d3_scale_linearTickFormat(domain, m, format);
|
||
};
|
||
scale.nice = function(m) {
|
||
d3_scale_linearNice(domain, m);
|
||
return rescale();
|
||
};
|
||
scale.copy = function() {
|
||
return d3_scale_linear(domain, range, interpolate, clamp);
|
||
};
|
||
return rescale();
|
||
}
|
||
function d3_scale_linearRebind(scale, linear) {
|
||
return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
|
||
}
|
||
function d3_scale_linearNice(domain, m) {
|
||
return d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2]));
|
||
}
|
||
function d3_scale_linearTickRange(domain, m) {
|
||
if (m == null) m = 10;
|
||
var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step;
|
||
if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
|
||
extent[0] = Math.ceil(extent[0] / step) * step;
|
||
extent[1] = Math.floor(extent[1] / step) * step + step * .5;
|
||
extent[2] = step;
|
||
return extent;
|
||
}
|
||
function d3_scale_linearTicks(domain, m) {
|
||
return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
|
||
}
|
||
function d3_scale_linearTickFormat(domain, m, format) {
|
||
var range = d3_scale_linearTickRange(domain, m);
|
||
if (format) {
|
||
var match = d3_format_re.exec(format);
|
||
match.shift();
|
||
if (match[8] === "s") {
|
||
var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1])));
|
||
if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2]));
|
||
match[8] = "f";
|
||
format = d3.format(match.join(""));
|
||
return function(d) {
|
||
return format(prefix.scale(d)) + prefix.symbol;
|
||
};
|
||
}
|
||
if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range);
|
||
format = match.join("");
|
||
} else {
|
||
format = ",." + d3_scale_linearPrecision(range[2]) + "f";
|
||
}
|
||
return d3.format(format);
|
||
}
|
||
var d3_scale_linearFormatSignificant = {
|
||
s: 1,
|
||
g: 1,
|
||
p: 1,
|
||
r: 1,
|
||
e: 1
|
||
};
|
||
function d3_scale_linearPrecision(value) {
|
||
return -Math.floor(Math.log(value) / Math.LN10 + .01);
|
||
}
|
||
function d3_scale_linearFormatPrecision(type, range) {
|
||
var p = d3_scale_linearPrecision(range[2]);
|
||
return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2;
|
||
}
|
||
d3.scale.log = function() {
|
||
return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]);
|
||
};
|
||
function d3_scale_log(linear, base, positive, domain) {
|
||
function log(x) {
|
||
return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base);
|
||
}
|
||
function pow(x) {
|
||
return positive ? Math.pow(base, x) : -Math.pow(base, -x);
|
||
}
|
||
function scale(x) {
|
||
return linear(log(x));
|
||
}
|
||
scale.invert = function(x) {
|
||
return pow(linear.invert(x));
|
||
};
|
||
scale.domain = function(x) {
|
||
if (!arguments.length) return domain;
|
||
positive = x[0] >= 0;
|
||
linear.domain((domain = x.map(Number)).map(log));
|
||
return scale;
|
||
};
|
||
scale.base = function(_) {
|
||
if (!arguments.length) return base;
|
||
base = +_;
|
||
linear.domain(domain.map(log));
|
||
return scale;
|
||
};
|
||
scale.nice = function() {
|
||
var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative);
|
||
linear.domain(niced);
|
||
domain = niced.map(pow);
|
||
return scale;
|
||
};
|
||
scale.ticks = function() {
|
||
var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base;
|
||
if (isFinite(j - i)) {
|
||
if (positive) {
|
||
for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k);
|
||
ticks.push(pow(i));
|
||
} else {
|
||
ticks.push(pow(i));
|
||
for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k);
|
||
}
|
||
for (i = 0; ticks[i] < u; i++) {}
|
||
for (j = ticks.length; ticks[j - 1] > v; j--) {}
|
||
ticks = ticks.slice(i, j);
|
||
}
|
||
return ticks;
|
||
};
|
||
scale.tickFormat = function(n, format) {
|
||
if (!arguments.length) return d3_scale_logFormat;
|
||
if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format);
|
||
var k = Math.max(.1, n / scale.ticks().length), f = positive ? (e = 1e-12, Math.ceil) : (e = -1e-12,
|
||
Math.floor), e;
|
||
return function(d) {
|
||
return d / pow(f(log(d) + e)) <= k ? format(d) : "";
|
||
};
|
||
};
|
||
scale.copy = function() {
|
||
return d3_scale_log(linear.copy(), base, positive, domain);
|
||
};
|
||
return d3_scale_linearRebind(scale, linear);
|
||
}
|
||
var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = {
|
||
floor: function(x) {
|
||
return -Math.ceil(-x);
|
||
},
|
||
ceil: function(x) {
|
||
return -Math.floor(-x);
|
||
}
|
||
};
|
||
d3.scale.pow = function() {
|
||
return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]);
|
||
};
|
||
function d3_scale_pow(linear, exponent, domain) {
|
||
var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);
|
||
function scale(x) {
|
||
return linear(powp(x));
|
||
}
|
||
scale.invert = function(x) {
|
||
return powb(linear.invert(x));
|
||
};
|
||
scale.domain = function(x) {
|
||
if (!arguments.length) return domain;
|
||
linear.domain((domain = x.map(Number)).map(powp));
|
||
return scale;
|
||
};
|
||
scale.ticks = function(m) {
|
||
return d3_scale_linearTicks(domain, m);
|
||
};
|
||
scale.tickFormat = function(m, format) {
|
||
return d3_scale_linearTickFormat(domain, m, format);
|
||
};
|
||
scale.nice = function(m) {
|
||
return scale.domain(d3_scale_linearNice(domain, m));
|
||
};
|
||
scale.exponent = function(x) {
|
||
if (!arguments.length) return exponent;
|
||
powp = d3_scale_powPow(exponent = x);
|
||
powb = d3_scale_powPow(1 / exponent);
|
||
linear.domain(domain.map(powp));
|
||
return scale;
|
||
};
|
||
scale.copy = function() {
|
||
return d3_scale_pow(linear.copy(), exponent, domain);
|
||
};
|
||
return d3_scale_linearRebind(scale, linear);
|
||
}
|
||
function d3_scale_powPow(e) {
|
||
return function(x) {
|
||
return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
|
||
};
|
||
}
|
||
d3.scale.sqrt = function() {
|
||
return d3.scale.pow().exponent(.5);
|
||
};
|
||
d3.scale.ordinal = function() {
|
||
return d3_scale_ordinal([], {
|
||
t: "range",
|
||
a: [ [] ]
|
||
});
|
||
};
|
||
function d3_scale_ordinal(domain, ranger) {
|
||
var index, range, rangeBand;
|
||
function scale(x) {
|
||
return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length];
|
||
}
|
||
function steps(start, step) {
|
||
return d3.range(domain.length).map(function(i) {
|
||
return start + step * i;
|
||
});
|
||
}
|
||
scale.domain = function(x) {
|
||
if (!arguments.length) return domain;
|
||
domain = [];
|
||
index = new d3_Map();
|
||
var i = -1, n = x.length, xi;
|
||
while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));
|
||
return scale[ranger.t].apply(scale, ranger.a);
|
||
};
|
||
scale.range = function(x) {
|
||
if (!arguments.length) return range;
|
||
range = x;
|
||
rangeBand = 0;
|
||
ranger = {
|
||
t: "range",
|
||
a: arguments
|
||
};
|
||
return scale;
|
||
};
|
||
scale.rangePoints = function(x, padding) {
|
||
if (arguments.length < 2) padding = 0;
|
||
var start = x[0], stop = x[1], step = domain.length < 2 ? (start = (start + stop) / 2,
|
||
0) : (stop - start) / (domain.length - 1 + padding);
|
||
range = steps(start + step * padding / 2, step);
|
||
rangeBand = 0;
|
||
ranger = {
|
||
t: "rangePoints",
|
||
a: arguments
|
||
};
|
||
return scale;
|
||
};
|
||
scale.rangeRoundPoints = function(x, padding) {
|
||
if (arguments.length < 2) padding = 0;
|
||
var start = x[0], stop = x[1], step = domain.length < 2 ? (start = stop = Math.round((start + stop) / 2),
|
||
0) : (stop - start) / (domain.length - 1 + padding) | 0;
|
||
range = steps(start + Math.round(step * padding / 2 + (stop - start - (domain.length - 1 + padding) * step) / 2), step);
|
||
rangeBand = 0;
|
||
ranger = {
|
||
t: "rangeRoundPoints",
|
||
a: arguments
|
||
};
|
||
return scale;
|
||
};
|
||
scale.rangeBands = function(x, padding, outerPadding) {
|
||
if (arguments.length < 2) padding = 0;
|
||
if (arguments.length < 3) outerPadding = padding;
|
||
var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding);
|
||
range = steps(start + step * outerPadding, step);
|
||
if (reverse) range.reverse();
|
||
rangeBand = step * (1 - padding);
|
||
ranger = {
|
||
t: "rangeBands",
|
||
a: arguments
|
||
};
|
||
return scale;
|
||
};
|
||
scale.rangeRoundBands = function(x, padding, outerPadding) {
|
||
if (arguments.length < 2) padding = 0;
|
||
if (arguments.length < 3) outerPadding = padding;
|
||
var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding));
|
||
range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step);
|
||
if (reverse) range.reverse();
|
||
rangeBand = Math.round(step * (1 - padding));
|
||
ranger = {
|
||
t: "rangeRoundBands",
|
||
a: arguments
|
||
};
|
||
return scale;
|
||
};
|
||
scale.rangeBand = function() {
|
||
return rangeBand;
|
||
};
|
||
scale.rangeExtent = function() {
|
||
return d3_scaleExtent(ranger.a[0]);
|
||
};
|
||
scale.copy = function() {
|
||
return d3_scale_ordinal(domain, ranger);
|
||
};
|
||
return scale.domain(domain);
|
||
}
|
||
d3.scale.category10 = function() {
|
||
return d3.scale.ordinal().range(d3_category10);
|
||
};
|
||
d3.scale.category20 = function() {
|
||
return d3.scale.ordinal().range(d3_category20);
|
||
};
|
||
d3.scale.category20b = function() {
|
||
return d3.scale.ordinal().range(d3_category20b);
|
||
};
|
||
d3.scale.category20c = function() {
|
||
return d3.scale.ordinal().range(d3_category20c);
|
||
};
|
||
var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString);
|
||
var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString);
|
||
var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString);
|
||
var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString);
|
||
d3.scale.quantile = function() {
|
||
return d3_scale_quantile([], []);
|
||
};
|
||
function d3_scale_quantile(domain, range) {
|
||
var thresholds;
|
||
function rescale() {
|
||
var k = 0, q = range.length;
|
||
thresholds = [];
|
||
while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);
|
||
return scale;
|
||
}
|
||
function scale(x) {
|
||
if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)];
|
||
}
|
||
scale.domain = function(x) {
|
||
if (!arguments.length) return domain;
|
||
domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending);
|
||
return rescale();
|
||
};
|
||
scale.range = function(x) {
|
||
if (!arguments.length) return range;
|
||
range = x;
|
||
return rescale();
|
||
};
|
||
scale.quantiles = function() {
|
||
return thresholds;
|
||
};
|
||
scale.invertExtent = function(y) {
|
||
y = range.indexOf(y);
|
||
return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ];
|
||
};
|
||
scale.copy = function() {
|
||
return d3_scale_quantile(domain, range);
|
||
};
|
||
return rescale();
|
||
}
|
||
d3.scale.quantize = function() {
|
||
return d3_scale_quantize(0, 1, [ 0, 1 ]);
|
||
};
|
||
function d3_scale_quantize(x0, x1, range) {
|
||
var kx, i;
|
||
function scale(x) {
|
||
return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];
|
||
}
|
||
function rescale() {
|
||
kx = range.length / (x1 - x0);
|
||
i = range.length - 1;
|
||
return scale;
|
||
}
|
||
scale.domain = function(x) {
|
||
if (!arguments.length) return [ x0, x1 ];
|
||
x0 = +x[0];
|
||
x1 = +x[x.length - 1];
|
||
return rescale();
|
||
};
|
||
scale.range = function(x) {
|
||
if (!arguments.length) return range;
|
||
range = x;
|
||
return rescale();
|
||
};
|
||
scale.invertExtent = function(y) {
|
||
y = range.indexOf(y);
|
||
y = y < 0 ? NaN : y / kx + x0;
|
||
return [ y, y + 1 / kx ];
|
||
};
|
||
scale.copy = function() {
|
||
return d3_scale_quantize(x0, x1, range);
|
||
};
|
||
return rescale();
|
||
}
|
||
d3.scale.threshold = function() {
|
||
return d3_scale_threshold([ .5 ], [ 0, 1 ]);
|
||
};
|
||
function d3_scale_threshold(domain, range) {
|
||
function scale(x) {
|
||
if (x <= x) return range[d3.bisect(domain, x)];
|
||
}
|
||
scale.domain = function(_) {
|
||
if (!arguments.length) return domain;
|
||
domain = _;
|
||
return scale;
|
||
};
|
||
scale.range = function(_) {
|
||
if (!arguments.length) return range;
|
||
range = _;
|
||
return scale;
|
||
};
|
||
scale.invertExtent = function(y) {
|
||
y = range.indexOf(y);
|
||
return [ domain[y - 1], domain[y] ];
|
||
};
|
||
scale.copy = function() {
|
||
return d3_scale_threshold(domain, range);
|
||
};
|
||
return scale;
|
||
}
|
||
d3.scale.identity = function() {
|
||
return d3_scale_identity([ 0, 1 ]);
|
||
};
|
||
function d3_scale_identity(domain) {
|
||
function identity(x) {
|
||
return +x;
|
||
}
|
||
identity.invert = identity;
|
||
identity.domain = identity.range = function(x) {
|
||
if (!arguments.length) return domain;
|
||
domain = x.map(identity);
|
||
return identity;
|
||
};
|
||
identity.ticks = function(m) {
|
||
return d3_scale_linearTicks(domain, m);
|
||
};
|
||
identity.tickFormat = function(m, format) {
|
||
return d3_scale_linearTickFormat(domain, m, format);
|
||
};
|
||
identity.copy = function() {
|
||
return d3_scale_identity(domain);
|
||
};
|
||
return identity;
|
||
}
|
||
d3.svg = {};
|
||
function d3_zero() {
|
||
return 0;
|
||
}
|
||
d3.svg.arc = function() {
|
||
var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, cornerRadius = d3_zero, padRadius = d3_svg_arcAuto, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle, padAngle = d3_svg_arcPadAngle;
|
||
function arc() {
|
||
var r0 = Math.max(0, +innerRadius.apply(this, arguments)), r1 = Math.max(0, +outerRadius.apply(this, arguments)), a0 = startAngle.apply(this, arguments) - halfπ, a1 = endAngle.apply(this, arguments) - halfπ, da = Math.abs(a1 - a0), cw = a0 > a1 ? 0 : 1;
|
||
if (r1 < r0) rc = r1, r1 = r0, r0 = rc;
|
||
if (da >= τε) return circleSegment(r1, cw) + (r0 ? circleSegment(r0, 1 - cw) : "") + "Z";
|
||
var rc, cr, rp, ap, p0 = 0, p1 = 0, x0, y0, x1, y1, x2, y2, x3, y3, path = [];
|
||
if (ap = (+padAngle.apply(this, arguments) || 0) / 2) {
|
||
rp = padRadius === d3_svg_arcAuto ? Math.sqrt(r0 * r0 + r1 * r1) : +padRadius.apply(this, arguments);
|
||
if (!cw) p1 *= -1;
|
||
if (r1) p1 = d3_asin(rp / r1 * Math.sin(ap));
|
||
if (r0) p0 = d3_asin(rp / r0 * Math.sin(ap));
|
||
}
|
||
if (r1) {
|
||
x0 = r1 * Math.cos(a0 + p1);
|
||
y0 = r1 * Math.sin(a0 + p1);
|
||
x1 = r1 * Math.cos(a1 - p1);
|
||
y1 = r1 * Math.sin(a1 - p1);
|
||
var l1 = Math.abs(a1 - a0 - 2 * p1) <= π ? 0 : 1;
|
||
if (p1 && d3_svg_arcSweep(x0, y0, x1, y1) === cw ^ l1) {
|
||
var h1 = (a0 + a1) / 2;
|
||
x0 = r1 * Math.cos(h1);
|
||
y0 = r1 * Math.sin(h1);
|
||
x1 = y1 = null;
|
||
}
|
||
} else {
|
||
x0 = y0 = 0;
|
||
}
|
||
if (r0) {
|
||
x2 = r0 * Math.cos(a1 - p0);
|
||
y2 = r0 * Math.sin(a1 - p0);
|
||
x3 = r0 * Math.cos(a0 + p0);
|
||
y3 = r0 * Math.sin(a0 + p0);
|
||
var l0 = Math.abs(a0 - a1 + 2 * p0) <= π ? 0 : 1;
|
||
if (p0 && d3_svg_arcSweep(x2, y2, x3, y3) === 1 - cw ^ l0) {
|
||
var h0 = (a0 + a1) / 2;
|
||
x2 = r0 * Math.cos(h0);
|
||
y2 = r0 * Math.sin(h0);
|
||
x3 = y3 = null;
|
||
}
|
||
} else {
|
||
x2 = y2 = 0;
|
||
}
|
||
if ((rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments))) > .001) {
|
||
cr = r0 < r1 ^ cw ? 0 : 1;
|
||
var oc = x3 == null ? [ x2, y2 ] : x1 == null ? [ x0, y0 ] : d3_geom_polygonIntersect([ x0, y0 ], [ x3, y3 ], [ x1, y1 ], [ x2, y2 ]), ax = x0 - oc[0], ay = y0 - oc[1], bx = x1 - oc[0], by = y1 - oc[1], kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2), lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]);
|
||
if (x1 != null) {
|
||
var rc1 = Math.min(rc, (r1 - lc) / (kc + 1)), t30 = d3_svg_arcCornerTangents(x3 == null ? [ x2, y2 ] : [ x3, y3 ], [ x0, y0 ], r1, rc1, cw), t12 = d3_svg_arcCornerTangents([ x1, y1 ], [ x2, y2 ], r1, rc1, cw);
|
||
if (rc === rc1) {
|
||
path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]);
|
||
} else {
|
||
path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]);
|
||
}
|
||
} else {
|
||
path.push("M", x0, ",", y0);
|
||
}
|
||
if (x3 != null) {
|
||
var rc0 = Math.min(rc, (r0 - lc) / (kc - 1)), t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw);
|
||
if (rc === rc0) {
|
||
path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]);
|
||
} else {
|
||
path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]);
|
||
}
|
||
} else {
|
||
path.push("L", x2, ",", y2);
|
||
}
|
||
} else {
|
||
path.push("M", x0, ",", y0);
|
||
if (x1 != null) path.push("A", r1, ",", r1, " 0 ", l1, ",", cw, " ", x1, ",", y1);
|
||
path.push("L", x2, ",", y2);
|
||
if (x3 != null) path.push("A", r0, ",", r0, " 0 ", l0, ",", 1 - cw, " ", x3, ",", y3);
|
||
}
|
||
path.push("Z");
|
||
return path.join("");
|
||
}
|
||
function circleSegment(r1, cw) {
|
||
return "M0," + r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + -r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + r1;
|
||
}
|
||
arc.innerRadius = function(v) {
|
||
if (!arguments.length) return innerRadius;
|
||
innerRadius = d3_functor(v);
|
||
return arc;
|
||
};
|
||
arc.outerRadius = function(v) {
|
||
if (!arguments.length) return outerRadius;
|
||
outerRadius = d3_functor(v);
|
||
return arc;
|
||
};
|
||
arc.cornerRadius = function(v) {
|
||
if (!arguments.length) return cornerRadius;
|
||
cornerRadius = d3_functor(v);
|
||
return arc;
|
||
};
|
||
arc.padRadius = function(v) {
|
||
if (!arguments.length) return padRadius;
|
||
padRadius = v == d3_svg_arcAuto ? d3_svg_arcAuto : d3_functor(v);
|
||
return arc;
|
||
};
|
||
arc.startAngle = function(v) {
|
||
if (!arguments.length) return startAngle;
|
||
startAngle = d3_functor(v);
|
||
return arc;
|
||
};
|
||
arc.endAngle = function(v) {
|
||
if (!arguments.length) return endAngle;
|
||
endAngle = d3_functor(v);
|
||
return arc;
|
||
};
|
||
arc.padAngle = function(v) {
|
||
if (!arguments.length) return padAngle;
|
||
padAngle = d3_functor(v);
|
||
return arc;
|
||
};
|
||
arc.centroid = function() {
|
||
var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - halfπ;
|
||
return [ Math.cos(a) * r, Math.sin(a) * r ];
|
||
};
|
||
return arc;
|
||
};
|
||
var d3_svg_arcAuto = "auto";
|
||
function d3_svg_arcInnerRadius(d) {
|
||
return d.innerRadius;
|
||
}
|
||
function d3_svg_arcOuterRadius(d) {
|
||
return d.outerRadius;
|
||
}
|
||
function d3_svg_arcStartAngle(d) {
|
||
return d.startAngle;
|
||
}
|
||
function d3_svg_arcEndAngle(d) {
|
||
return d.endAngle;
|
||
}
|
||
function d3_svg_arcPadAngle(d) {
|
||
return d && d.padAngle;
|
||
}
|
||
function d3_svg_arcSweep(x0, y0, x1, y1) {
|
||
return (x0 - x1) * y0 - (y0 - y1) * x0 > 0 ? 0 : 1;
|
||
}
|
||
function d3_svg_arcCornerTangents(p0, p1, r1, rc, cw) {
|
||
var x01 = p0[0] - p1[0], y01 = p0[1] - p1[1], lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x1 = p0[0] + ox, y1 = p0[1] + oy, x2 = p1[0] + ox, y2 = p1[1] + oy, x3 = (x1 + x2) / 2, y3 = (y1 + y2) / 2, dx = x2 - x1, dy = y2 - y1, d2 = dx * dx + dy * dy, r = r1 - rc, D = x1 * y2 - x2 * y1, d = (dy < 0 ? -1 : 1) * Math.sqrt(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 - x3, dy0 = cy0 - y3, dx1 = cx1 - x3, dy1 = cy1 - y3;
|
||
if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;
|
||
return [ [ cx0 - ox, cy0 - oy ], [ cx0 * r1 / r, cy0 * r1 / r ] ];
|
||
}
|
||
function d3_svg_line(projection) {
|
||
var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7;
|
||
function line(data) {
|
||
var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y);
|
||
function segment() {
|
||
segments.push("M", interpolate(projection(points), tension));
|
||
}
|
||
while (++i < n) {
|
||
if (defined.call(this, d = data[i], i)) {
|
||
points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]);
|
||
} else if (points.length) {
|
||
segment();
|
||
points = [];
|
||
}
|
||
}
|
||
if (points.length) segment();
|
||
return segments.length ? segments.join("") : null;
|
||
}
|
||
line.x = function(_) {
|
||
if (!arguments.length) return x;
|
||
x = _;
|
||
return line;
|
||
};
|
||
line.y = function(_) {
|
||
if (!arguments.length) return y;
|
||
y = _;
|
||
return line;
|
||
};
|
||
line.defined = function(_) {
|
||
if (!arguments.length) return defined;
|
||
defined = _;
|
||
return line;
|
||
};
|
||
line.interpolate = function(_) {
|
||
if (!arguments.length) return interpolateKey;
|
||
if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
|
||
return line;
|
||
};
|
||
line.tension = function(_) {
|
||
if (!arguments.length) return tension;
|
||
tension = _;
|
||
return line;
|
||
};
|
||
return line;
|
||
}
|
||
d3.svg.line = function() {
|
||
return d3_svg_line(d3_identity);
|
||
};
|
||
var d3_svg_lineInterpolators = d3.map({
|
||
linear: d3_svg_lineLinear,
|
||
"linear-closed": d3_svg_lineLinearClosed,
|
||
step: d3_svg_lineStep,
|
||
"step-before": d3_svg_lineStepBefore,
|
||
"step-after": d3_svg_lineStepAfter,
|
||
basis: d3_svg_lineBasis,
|
||
"basis-open": d3_svg_lineBasisOpen,
|
||
"basis-closed": d3_svg_lineBasisClosed,
|
||
bundle: d3_svg_lineBundle,
|
||
cardinal: d3_svg_lineCardinal,
|
||
"cardinal-open": d3_svg_lineCardinalOpen,
|
||
"cardinal-closed": d3_svg_lineCardinalClosed,
|
||
monotone: d3_svg_lineMonotone
|
||
});
|
||
d3_svg_lineInterpolators.forEach(function(key, value) {
|
||
value.key = key;
|
||
value.closed = /-closed$/.test(key);
|
||
});
|
||
function d3_svg_lineLinear(points) {
|
||
return points.join("L");
|
||
}
|
||
function d3_svg_lineLinearClosed(points) {
|
||
return d3_svg_lineLinear(points) + "Z";
|
||
}
|
||
function d3_svg_lineStep(points) {
|
||
var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
|
||
while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]);
|
||
if (n > 1) path.push("H", p[0]);
|
||
return path.join("");
|
||
}
|
||
function d3_svg_lineStepBefore(points) {
|
||
var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
|
||
while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]);
|
||
return path.join("");
|
||
}
|
||
function d3_svg_lineStepAfter(points) {
|
||
var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
|
||
while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]);
|
||
return path.join("");
|
||
}
|
||
function d3_svg_lineCardinalOpen(points, tension) {
|
||
return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, -1), d3_svg_lineCardinalTangents(points, tension));
|
||
}
|
||
function d3_svg_lineCardinalClosed(points, tension) {
|
||
return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]),
|
||
points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension));
|
||
}
|
||
function d3_svg_lineCardinal(points, tension) {
|
||
return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension));
|
||
}
|
||
function d3_svg_lineHermite(points, tangents) {
|
||
if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) {
|
||
return d3_svg_lineLinear(points);
|
||
}
|
||
var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1;
|
||
if (quad) {
|
||
path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1];
|
||
p0 = points[1];
|
||
pi = 2;
|
||
}
|
||
if (tangents.length > 1) {
|
||
t = tangents[1];
|
||
p = points[pi];
|
||
pi++;
|
||
path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
|
||
for (var i = 2; i < tangents.length; i++, pi++) {
|
||
p = points[pi];
|
||
t = tangents[i];
|
||
path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
|
||
}
|
||
}
|
||
if (quad) {
|
||
var lp = points[pi];
|
||
path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1];
|
||
}
|
||
return path;
|
||
}
|
||
function d3_svg_lineCardinalTangents(points, tension) {
|
||
var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length;
|
||
while (++i < n) {
|
||
p0 = p1;
|
||
p1 = p2;
|
||
p2 = points[i];
|
||
tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]);
|
||
}
|
||
return tangents;
|
||
}
|
||
function d3_svg_lineBasis(points) {
|
||
if (points.length < 3) return d3_svg_lineLinear(points);
|
||
var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
|
||
points.push(points[n - 1]);
|
||
while (++i <= n) {
|
||
pi = points[i];
|
||
px.shift();
|
||
px.push(pi[0]);
|
||
py.shift();
|
||
py.push(pi[1]);
|
||
d3_svg_lineBasisBezier(path, px, py);
|
||
}
|
||
points.pop();
|
||
path.push("L", pi);
|
||
return path.join("");
|
||
}
|
||
function d3_svg_lineBasisOpen(points) {
|
||
if (points.length < 4) return d3_svg_lineLinear(points);
|
||
var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ];
|
||
while (++i < 3) {
|
||
pi = points[i];
|
||
px.push(pi[0]);
|
||
py.push(pi[1]);
|
||
}
|
||
path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));
|
||
--i;
|
||
while (++i < n) {
|
||
pi = points[i];
|
||
px.shift();
|
||
px.push(pi[0]);
|
||
py.shift();
|
||
py.push(pi[1]);
|
||
d3_svg_lineBasisBezier(path, px, py);
|
||
}
|
||
return path.join("");
|
||
}
|
||
function d3_svg_lineBasisClosed(points) {
|
||
var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = [];
|
||
while (++i < 4) {
|
||
pi = points[i % n];
|
||
px.push(pi[0]);
|
||
py.push(pi[1]);
|
||
}
|
||
path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
|
||
--i;
|
||
while (++i < m) {
|
||
pi = points[i % n];
|
||
px.shift();
|
||
px.push(pi[0]);
|
||
py.shift();
|
||
py.push(pi[1]);
|
||
d3_svg_lineBasisBezier(path, px, py);
|
||
}
|
||
return path.join("");
|
||
}
|
||
function d3_svg_lineBundle(points, tension) {
|
||
var n = points.length - 1;
|
||
if (n) {
|
||
var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t;
|
||
while (++i <= n) {
|
||
p = points[i];
|
||
t = i / n;
|
||
p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);
|
||
p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);
|
||
}
|
||
}
|
||
return d3_svg_lineBasis(points);
|
||
}
|
||
function d3_svg_lineDot4(a, b) {
|
||
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
|
||
}
|
||
var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ];
|
||
function d3_svg_lineBasisBezier(path, x, y) {
|
||
path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));
|
||
}
|
||
function d3_svg_lineSlope(p0, p1) {
|
||
return (p1[1] - p0[1]) / (p1[0] - p0[0]);
|
||
}
|
||
function d3_svg_lineFiniteDifferences(points) {
|
||
var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1);
|
||
while (++i < j) {
|
||
m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2;
|
||
}
|
||
m[i] = d;
|
||
return m;
|
||
}
|
||
function d3_svg_lineMonotoneTangents(points) {
|
||
var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1;
|
||
while (++i < j) {
|
||
d = d3_svg_lineSlope(points[i], points[i + 1]);
|
||
if (abs(d) < ε) {
|
||
m[i] = m[i + 1] = 0;
|
||
} else {
|
||
a = m[i] / d;
|
||
b = m[i + 1] / d;
|
||
s = a * a + b * b;
|
||
if (s > 9) {
|
||
s = d * 3 / Math.sqrt(s);
|
||
m[i] = s * a;
|
||
m[i + 1] = s * b;
|
||
}
|
||
}
|
||
}
|
||
i = -1;
|
||
while (++i <= j) {
|
||
s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i]));
|
||
tangents.push([ s || 0, m[i] * s || 0 ]);
|
||
}
|
||
return tangents;
|
||
}
|
||
function d3_svg_lineMonotone(points) {
|
||
return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
|
||
}
|
||
d3.svg.line.radial = function() {
|
||
var line = d3_svg_line(d3_svg_lineRadial);
|
||
line.radius = line.x, delete line.x;
|
||
line.angle = line.y, delete line.y;
|
||
return line;
|
||
};
|
||
function d3_svg_lineRadial(points) {
|
||
var point, i = -1, n = points.length, r, a;
|
||
while (++i < n) {
|
||
point = points[i];
|
||
r = point[0];
|
||
a = point[1] - halfπ;
|
||
point[0] = r * Math.cos(a);
|
||
point[1] = r * Math.sin(a);
|
||
}
|
||
return points;
|
||
}
|
||
function d3_svg_area(projection) {
|
||
var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7;
|
||
function area(data) {
|
||
var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() {
|
||
return x;
|
||
} : d3_functor(x1), fy1 = y0 === y1 ? function() {
|
||
return y;
|
||
} : d3_functor(y1), x, y;
|
||
function segment() {
|
||
segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z");
|
||
}
|
||
while (++i < n) {
|
||
if (defined.call(this, d = data[i], i)) {
|
||
points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]);
|
||
points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]);
|
||
} else if (points0.length) {
|
||
segment();
|
||
points0 = [];
|
||
points1 = [];
|
||
}
|
||
}
|
||
if (points0.length) segment();
|
||
return segments.length ? segments.join("") : null;
|
||
}
|
||
area.x = function(_) {
|
||
if (!arguments.length) return x1;
|
||
x0 = x1 = _;
|
||
return area;
|
||
};
|
||
area.x0 = function(_) {
|
||
if (!arguments.length) return x0;
|
||
x0 = _;
|
||
return area;
|
||
};
|
||
area.x1 = function(_) {
|
||
if (!arguments.length) return x1;
|
||
x1 = _;
|
||
return area;
|
||
};
|
||
area.y = function(_) {
|
||
if (!arguments.length) return y1;
|
||
y0 = y1 = _;
|
||
return area;
|
||
};
|
||
area.y0 = function(_) {
|
||
if (!arguments.length) return y0;
|
||
y0 = _;
|
||
return area;
|
||
};
|
||
area.y1 = function(_) {
|
||
if (!arguments.length) return y1;
|
||
y1 = _;
|
||
return area;
|
||
};
|
||
area.defined = function(_) {
|
||
if (!arguments.length) return defined;
|
||
defined = _;
|
||
return area;
|
||
};
|
||
area.interpolate = function(_) {
|
||
if (!arguments.length) return interpolateKey;
|
||
if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
|
||
interpolateReverse = interpolate.reverse || interpolate;
|
||
L = interpolate.closed ? "M" : "L";
|
||
return area;
|
||
};
|
||
area.tension = function(_) {
|
||
if (!arguments.length) return tension;
|
||
tension = _;
|
||
return area;
|
||
};
|
||
return area;
|
||
}
|
||
d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;
|
||
d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;
|
||
d3.svg.area = function() {
|
||
return d3_svg_area(d3_identity);
|
||
};
|
||
d3.svg.area.radial = function() {
|
||
var area = d3_svg_area(d3_svg_lineRadial);
|
||
area.radius = area.x, delete area.x;
|
||
area.innerRadius = area.x0, delete area.x0;
|
||
area.outerRadius = area.x1, delete area.x1;
|
||
area.angle = area.y, delete area.y;
|
||
area.startAngle = area.y0, delete area.y0;
|
||
area.endAngle = area.y1, delete area.y1;
|
||
return area;
|
||
};
|
||
d3.svg.chord = function() {
|
||
var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
|
||
function chord(d, i) {
|
||
var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i);
|
||
return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z";
|
||
}
|
||
function subgroup(self, f, d, i) {
|
||
var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) - halfπ, a1 = endAngle.call(self, subgroup, i) - halfπ;
|
||
return {
|
||
r: r,
|
||
a0: a0,
|
||
a1: a1,
|
||
p0: [ r * Math.cos(a0), r * Math.sin(a0) ],
|
||
p1: [ r * Math.cos(a1), r * Math.sin(a1) ]
|
||
};
|
||
}
|
||
function equals(a, b) {
|
||
return a.a0 == b.a0 && a.a1 == b.a1;
|
||
}
|
||
function arc(r, p, a) {
|
||
return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p;
|
||
}
|
||
function curve(r0, p0, r1, p1) {
|
||
return "Q 0,0 " + p1;
|
||
}
|
||
chord.radius = function(v) {
|
||
if (!arguments.length) return radius;
|
||
radius = d3_functor(v);
|
||
return chord;
|
||
};
|
||
chord.source = function(v) {
|
||
if (!arguments.length) return source;
|
||
source = d3_functor(v);
|
||
return chord;
|
||
};
|
||
chord.target = function(v) {
|
||
if (!arguments.length) return target;
|
||
target = d3_functor(v);
|
||
return chord;
|
||
};
|
||
chord.startAngle = function(v) {
|
||
if (!arguments.length) return startAngle;
|
||
startAngle = d3_functor(v);
|
||
return chord;
|
||
};
|
||
chord.endAngle = function(v) {
|
||
if (!arguments.length) return endAngle;
|
||
endAngle = d3_functor(v);
|
||
return chord;
|
||
};
|
||
return chord;
|
||
};
|
||
function d3_svg_chordRadius(d) {
|
||
return d.radius;
|
||
}
|
||
d3.svg.diagonal = function() {
|
||
var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection;
|
||
function diagonal(d, i) {
|
||
var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, {
|
||
x: p0.x,
|
||
y: m
|
||
}, {
|
||
x: p3.x,
|
||
y: m
|
||
}, p3 ];
|
||
p = p.map(projection);
|
||
return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
|
||
}
|
||
diagonal.source = function(x) {
|
||
if (!arguments.length) return source;
|
||
source = d3_functor(x);
|
||
return diagonal;
|
||
};
|
||
diagonal.target = function(x) {
|
||
if (!arguments.length) return target;
|
||
target = d3_functor(x);
|
||
return diagonal;
|
||
};
|
||
diagonal.projection = function(x) {
|
||
if (!arguments.length) return projection;
|
||
projection = x;
|
||
return diagonal;
|
||
};
|
||
return diagonal;
|
||
};
|
||
function d3_svg_diagonalProjection(d) {
|
||
return [ d.x, d.y ];
|
||
}
|
||
d3.svg.diagonal.radial = function() {
|
||
var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection;
|
||
diagonal.projection = function(x) {
|
||
return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection;
|
||
};
|
||
return diagonal;
|
||
};
|
||
function d3_svg_diagonalRadialProjection(projection) {
|
||
return function() {
|
||
var d = projection.apply(this, arguments), r = d[0], a = d[1] - halfπ;
|
||
return [ r * Math.cos(a), r * Math.sin(a) ];
|
||
};
|
||
}
|
||
d3.svg.symbol = function() {
|
||
var type = d3_svg_symbolType, size = d3_svg_symbolSize;
|
||
function symbol(d, i) {
|
||
return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i));
|
||
}
|
||
symbol.type = function(x) {
|
||
if (!arguments.length) return type;
|
||
type = d3_functor(x);
|
||
return symbol;
|
||
};
|
||
symbol.size = function(x) {
|
||
if (!arguments.length) return size;
|
||
size = d3_functor(x);
|
||
return symbol;
|
||
};
|
||
return symbol;
|
||
};
|
||
function d3_svg_symbolSize() {
|
||
return 64;
|
||
}
|
||
function d3_svg_symbolType() {
|
||
return "circle";
|
||
}
|
||
function d3_svg_symbolCircle(size) {
|
||
var r = Math.sqrt(size / π);
|
||
return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z";
|
||
}
|
||
var d3_svg_symbols = d3.map({
|
||
circle: d3_svg_symbolCircle,
|
||
cross: function(size) {
|
||
var r = Math.sqrt(size / 5) / 2;
|
||
return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z";
|
||
},
|
||
diamond: function(size) {
|
||
var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30;
|
||
return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z";
|
||
},
|
||
square: function(size) {
|
||
var r = Math.sqrt(size) / 2;
|
||
return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z";
|
||
},
|
||
"triangle-down": function(size) {
|
||
var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
|
||
return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z";
|
||
},
|
||
"triangle-up": function(size) {
|
||
var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
|
||
return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z";
|
||
}
|
||
});
|
||
d3.svg.symbolTypes = d3_svg_symbols.keys();
|
||
var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians);
|
||
d3_selectionPrototype.transition = function(name) {
|
||
var id = d3_transitionInheritId || ++d3_transitionId, ns = d3_transitionNamespace(name), subgroups = [], subgroup, node, transition = d3_transitionInherit || {
|
||
time: Date.now(),
|
||
ease: d3_ease_cubicInOut,
|
||
delay: 0,
|
||
duration: 250
|
||
};
|
||
for (var j = -1, m = this.length; ++j < m; ) {
|
||
subgroups.push(subgroup = []);
|
||
for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
|
||
if (node = group[i]) d3_transitionNode(node, i, ns, id, transition);
|
||
subgroup.push(node);
|
||
}
|
||
}
|
||
return d3_transition(subgroups, ns, id);
|
||
};
|
||
d3_selectionPrototype.interrupt = function(name) {
|
||
return this.each(name == null ? d3_selection_interrupt : d3_selection_interruptNS(d3_transitionNamespace(name)));
|
||
};
|
||
var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace());
|
||
function d3_selection_interruptNS(ns) {
|
||
return function() {
|
||
var lock, active;
|
||
if ((lock = this[ns]) && (active = lock[lock.active])) {
|
||
if (--lock.count) delete lock[lock.active]; else delete this[ns];
|
||
lock.active += .5;
|
||
active.event && active.event.interrupt.call(this, this.__data__, active.index);
|
||
}
|
||
};
|
||
}
|
||
function d3_transition(groups, ns, id) {
|
||
d3_subclass(groups, d3_transitionPrototype);
|
||
groups.namespace = ns;
|
||
groups.id = id;
|
||
return groups;
|
||
}
|
||
var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit;
|
||
d3_transitionPrototype.call = d3_selectionPrototype.call;
|
||
d3_transitionPrototype.empty = d3_selectionPrototype.empty;
|
||
d3_transitionPrototype.node = d3_selectionPrototype.node;
|
||
d3_transitionPrototype.size = d3_selectionPrototype.size;
|
||
d3.transition = function(selection, name) {
|
||
return selection && selection.transition ? d3_transitionInheritId ? selection.transition(name) : selection : d3.selection().transition(selection);
|
||
};
|
||
d3.transition.prototype = d3_transitionPrototype;
|
||
d3_transitionPrototype.select = function(selector) {
|
||
var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnode, node;
|
||
selector = d3_selection_selector(selector);
|
||
for (var j = -1, m = this.length; ++j < m; ) {
|
||
subgroups.push(subgroup = []);
|
||
for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
|
||
if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) {
|
||
if ("__data__" in node) subnode.__data__ = node.__data__;
|
||
d3_transitionNode(subnode, i, ns, id, node[ns][id]);
|
||
subgroup.push(subnode);
|
||
} else {
|
||
subgroup.push(null);
|
||
}
|
||
}
|
||
}
|
||
return d3_transition(subgroups, ns, id);
|
||
};
|
||
d3_transitionPrototype.selectAll = function(selector) {
|
||
var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnodes, node, subnode, transition;
|
||
selector = d3_selection_selectorAll(selector);
|
||
for (var j = -1, m = this.length; ++j < m; ) {
|
||
for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
|
||
if (node = group[i]) {
|
||
transition = node[ns][id];
|
||
subnodes = selector.call(node, node.__data__, i, j);
|
||
subgroups.push(subgroup = []);
|
||
for (var k = -1, o = subnodes.length; ++k < o; ) {
|
||
if (subnode = subnodes[k]) d3_transitionNode(subnode, k, ns, id, transition);
|
||
subgroup.push(subnode);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return d3_transition(subgroups, ns, id);
|
||
};
|
||
d3_transitionPrototype.filter = function(filter) {
|
||
var subgroups = [], subgroup, group, node;
|
||
if (typeof filter !== "function") filter = d3_selection_filter(filter);
|
||
for (var j = 0, m = this.length; j < m; j++) {
|
||
subgroups.push(subgroup = []);
|
||
for (var group = this[j], i = 0, n = group.length; i < n; i++) {
|
||
if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
|
||
subgroup.push(node);
|
||
}
|
||
}
|
||
}
|
||
return d3_transition(subgroups, this.namespace, this.id);
|
||
};
|
||
d3_transitionPrototype.tween = function(name, tween) {
|
||
var id = this.id, ns = this.namespace;
|
||
if (arguments.length < 2) return this.node()[ns][id].tween.get(name);
|
||
return d3_selection_each(this, tween == null ? function(node) {
|
||
node[ns][id].tween.remove(name);
|
||
} : function(node) {
|
||
node[ns][id].tween.set(name, tween);
|
||
});
|
||
};
|
||
function d3_transition_tween(groups, name, value, tween) {
|
||
var id = groups.id, ns = groups.namespace;
|
||
return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) {
|
||
node[ns][id].tween.set(name, tween(value.call(node, node.__data__, i, j)));
|
||
} : (value = tween(value), function(node) {
|
||
node[ns][id].tween.set(name, value);
|
||
}));
|
||
}
|
||
d3_transitionPrototype.attr = function(nameNS, value) {
|
||
if (arguments.length < 2) {
|
||
for (value in nameNS) this.attr(value, nameNS[value]);
|
||
return this;
|
||
}
|
||
var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS);
|
||
function attrNull() {
|
||
this.removeAttribute(name);
|
||
}
|
||
function attrNullNS() {
|
||
this.removeAttributeNS(name.space, name.local);
|
||
}
|
||
function attrTween(b) {
|
||
return b == null ? attrNull : (b += "", function() {
|
||
var a = this.getAttribute(name), i;
|
||
return a !== b && (i = interpolate(a, b), function(t) {
|
||
this.setAttribute(name, i(t));
|
||
});
|
||
});
|
||
}
|
||
function attrTweenNS(b) {
|
||
return b == null ? attrNullNS : (b += "", function() {
|
||
var a = this.getAttributeNS(name.space, name.local), i;
|
||
return a !== b && (i = interpolate(a, b), function(t) {
|
||
this.setAttributeNS(name.space, name.local, i(t));
|
||
});
|
||
});
|
||
}
|
||
return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween);
|
||
};
|
||
d3_transitionPrototype.attrTween = function(nameNS, tween) {
|
||
var name = d3.ns.qualify(nameNS);
|
||
function attrTween(d, i) {
|
||
var f = tween.call(this, d, i, this.getAttribute(name));
|
||
return f && function(t) {
|
||
this.setAttribute(name, f(t));
|
||
};
|
||
}
|
||
function attrTweenNS(d, i) {
|
||
var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
|
||
return f && function(t) {
|
||
this.setAttributeNS(name.space, name.local, f(t));
|
||
};
|
||
}
|
||
return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
|
||
};
|
||
d3_transitionPrototype.style = function(name, value, priority) {
|
||
var n = arguments.length;
|
||
if (n < 3) {
|
||
if (typeof name !== "string") {
|
||
if (n < 2) value = "";
|
||
for (priority in name) this.style(priority, name[priority], value);
|
||
return this;
|
||
}
|
||
priority = "";
|
||
}
|
||
function styleNull() {
|
||
this.style.removeProperty(name);
|
||
}
|
||
function styleString(b) {
|
||
return b == null ? styleNull : (b += "", function() {
|
||
var a = d3_window(this).getComputedStyle(this, null).getPropertyValue(name), i;
|
||
return a !== b && (i = d3_interpolate(a, b), function(t) {
|
||
this.style.setProperty(name, i(t), priority);
|
||
});
|
||
});
|
||
}
|
||
return d3_transition_tween(this, "style." + name, value, styleString);
|
||
};
|
||
d3_transitionPrototype.styleTween = function(name, tween, priority) {
|
||
if (arguments.length < 3) priority = "";
|
||
function styleTween(d, i) {
|
||
var f = tween.call(this, d, i, d3_window(this).getComputedStyle(this, null).getPropertyValue(name));
|
||
return f && function(t) {
|
||
this.style.setProperty(name, f(t), priority);
|
||
};
|
||
}
|
||
return this.tween("style." + name, styleTween);
|
||
};
|
||
d3_transitionPrototype.text = function(value) {
|
||
return d3_transition_tween(this, "text", value, d3_transition_text);
|
||
};
|
||
function d3_transition_text(b) {
|
||
if (b == null) b = "";
|
||
return function() {
|
||
this.textContent = b;
|
||
};
|
||
}
|
||
d3_transitionPrototype.remove = function() {
|
||
var ns = this.namespace;
|
||
return this.each("end.transition", function() {
|
||
var p;
|
||
if (this[ns].count < 2 && (p = this.parentNode)) p.removeChild(this);
|
||
});
|
||
};
|
||
d3_transitionPrototype.ease = function(value) {
|
||
var id = this.id, ns = this.namespace;
|
||
if (arguments.length < 1) return this.node()[ns][id].ease;
|
||
if (typeof value !== "function") value = d3.ease.apply(d3, arguments);
|
||
return d3_selection_each(this, function(node) {
|
||
node[ns][id].ease = value;
|
||
});
|
||
};
|
||
d3_transitionPrototype.delay = function(value) {
|
||
var id = this.id, ns = this.namespace;
|
||
if (arguments.length < 1) return this.node()[ns][id].delay;
|
||
return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
|
||
node[ns][id].delay = +value.call(node, node.__data__, i, j);
|
||
} : (value = +value, function(node) {
|
||
node[ns][id].delay = value;
|
||
}));
|
||
};
|
||
d3_transitionPrototype.duration = function(value) {
|
||
var id = this.id, ns = this.namespace;
|
||
if (arguments.length < 1) return this.node()[ns][id].duration;
|
||
return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
|
||
node[ns][id].duration = Math.max(1, value.call(node, node.__data__, i, j));
|
||
} : (value = Math.max(1, value), function(node) {
|
||
node[ns][id].duration = value;
|
||
}));
|
||
};
|
||
d3_transitionPrototype.each = function(type, listener) {
|
||
var id = this.id, ns = this.namespace;
|
||
if (arguments.length < 2) {
|
||
var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId;
|
||
try {
|
||
d3_transitionInheritId = id;
|
||
d3_selection_each(this, function(node, i, j) {
|
||
d3_transitionInherit = node[ns][id];
|
||
type.call(node, node.__data__, i, j);
|
||
});
|
||
} finally {
|
||
d3_transitionInherit = inherit;
|
||
d3_transitionInheritId = inheritId;
|
||
}
|
||
} else {
|
||
d3_selection_each(this, function(node) {
|
||
var transition = node[ns][id];
|
||
(transition.event || (transition.event = d3.dispatch("start", "end", "interrupt"))).on(type, listener);
|
||
});
|
||
}
|
||
return this;
|
||
};
|
||
d3_transitionPrototype.transition = function() {
|
||
var id0 = this.id, id1 = ++d3_transitionId, ns = this.namespace, subgroups = [], subgroup, group, node, transition;
|
||
for (var j = 0, m = this.length; j < m; j++) {
|
||
subgroups.push(subgroup = []);
|
||
for (var group = this[j], i = 0, n = group.length; i < n; i++) {
|
||
if (node = group[i]) {
|
||
transition = node[ns][id0];
|
||
d3_transitionNode(node, i, ns, id1, {
|
||
time: transition.time,
|
||
ease: transition.ease,
|
||
delay: transition.delay + transition.duration,
|
||
duration: transition.duration
|
||
});
|
||
}
|
||
subgroup.push(node);
|
||
}
|
||
}
|
||
return d3_transition(subgroups, ns, id1);
|
||
};
|
||
function d3_transitionNamespace(name) {
|
||
return name == null ? "__transition__" : "__transition_" + name + "__";
|
||
}
|
||
function d3_transitionNode(node, i, ns, id, inherit) {
|
||
var lock = node[ns] || (node[ns] = {
|
||
active: 0,
|
||
count: 0
|
||
}), transition = lock[id];
|
||
if (!transition) {
|
||
var time = inherit.time;
|
||
transition = lock[id] = {
|
||
tween: new d3_Map(),
|
||
time: time,
|
||
delay: inherit.delay,
|
||
duration: inherit.duration,
|
||
ease: inherit.ease,
|
||
index: i
|
||
};
|
||
inherit = null;
|
||
++lock.count;
|
||
d3.timer(function(elapsed) {
|
||
var delay = transition.delay, duration, ease, timer = d3_timer_active, tweened = [];
|
||
timer.t = delay + time;
|
||
if (delay <= elapsed) return start(elapsed - delay);
|
||
timer.c = start;
|
||
function start(elapsed) {
|
||
if (lock.active > id) return stop();
|
||
var active = lock[lock.active];
|
||
if (active) {
|
||
--lock.count;
|
||
delete lock[lock.active];
|
||
active.event && active.event.interrupt.call(node, node.__data__, active.index);
|
||
}
|
||
lock.active = id;
|
||
transition.event && transition.event.start.call(node, node.__data__, i);
|
||
transition.tween.forEach(function(key, value) {
|
||
if (value = value.call(node, node.__data__, i)) {
|
||
tweened.push(value);
|
||
}
|
||
});
|
||
ease = transition.ease;
|
||
duration = transition.duration;
|
||
d3.timer(function() {
|
||
timer.c = tick(elapsed || 1) ? d3_true : tick;
|
||
return 1;
|
||
}, 0, time);
|
||
}
|
||
function tick(elapsed) {
|
||
if (lock.active !== id) return 1;
|
||
var t = elapsed / duration, e = ease(t), n = tweened.length;
|
||
while (n > 0) {
|
||
tweened[--n].call(node, e);
|
||
}
|
||
if (t >= 1) {
|
||
transition.event && transition.event.end.call(node, node.__data__, i);
|
||
return stop();
|
||
}
|
||
}
|
||
function stop() {
|
||
if (--lock.count) delete lock[id]; else delete node[ns];
|
||
return 1;
|
||
}
|
||
}, 0, time);
|
||
}
|
||
}
|
||
d3.svg.axis = function() {
|
||
var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_;
|
||
function axis(g) {
|
||
g.each(function() {
|
||
var g = d3.select(this);
|
||
var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy();
|
||
var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform;
|
||
var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"),
|
||
d3.transition(path));
|
||
tickEnter.append("line");
|
||
tickEnter.append("text");
|
||
var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2;
|
||
if (orient === "bottom" || orient === "top") {
|
||
tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", y2 = "y2";
|
||
text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle");
|
||
pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize);
|
||
} else {
|
||
tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", y2 = "x2";
|
||
text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start");
|
||
pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize);
|
||
}
|
||
lineEnter.attr(y2, sign * innerTickSize);
|
||
textEnter.attr(y1, sign * tickSpacing);
|
||
lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize);
|
||
textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing);
|
||
if (scale1.rangeBand) {
|
||
var x = scale1, dx = x.rangeBand() / 2;
|
||
scale0 = scale1 = function(d) {
|
||
return x(d) + dx;
|
||
};
|
||
} else if (scale0.rangeBand) {
|
||
scale0 = scale1;
|
||
} else {
|
||
tickExit.call(tickTransform, scale1, scale0);
|
||
}
|
||
tickEnter.call(tickTransform, scale0, scale1);
|
||
tickUpdate.call(tickTransform, scale1, scale1);
|
||
});
|
||
}
|
||
axis.scale = function(x) {
|
||
if (!arguments.length) return scale;
|
||
scale = x;
|
||
return axis;
|
||
};
|
||
axis.orient = function(x) {
|
||
if (!arguments.length) return orient;
|
||
orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient;
|
||
return axis;
|
||
};
|
||
axis.ticks = function() {
|
||
if (!arguments.length) return tickArguments_;
|
||
tickArguments_ = arguments;
|
||
return axis;
|
||
};
|
||
axis.tickValues = function(x) {
|
||
if (!arguments.length) return tickValues;
|
||
tickValues = x;
|
||
return axis;
|
||
};
|
||
axis.tickFormat = function(x) {
|
||
if (!arguments.length) return tickFormat_;
|
||
tickFormat_ = x;
|
||
return axis;
|
||
};
|
||
axis.tickSize = function(x) {
|
||
var n = arguments.length;
|
||
if (!n) return innerTickSize;
|
||
innerTickSize = +x;
|
||
outerTickSize = +arguments[n - 1];
|
||
return axis;
|
||
};
|
||
axis.innerTickSize = function(x) {
|
||
if (!arguments.length) return innerTickSize;
|
||
innerTickSize = +x;
|
||
return axis;
|
||
};
|
||
axis.outerTickSize = function(x) {
|
||
if (!arguments.length) return outerTickSize;
|
||
outerTickSize = +x;
|
||
return axis;
|
||
};
|
||
axis.tickPadding = function(x) {
|
||
if (!arguments.length) return tickPadding;
|
||
tickPadding = +x;
|
||
return axis;
|
||
};
|
||
axis.tickSubdivide = function() {
|
||
return arguments.length && axis;
|
||
};
|
||
return axis;
|
||
};
|
||
var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = {
|
||
top: 1,
|
||
right: 1,
|
||
bottom: 1,
|
||
left: 1
|
||
};
|
||
function d3_svg_axisX(selection, x0, x1) {
|
||
selection.attr("transform", function(d) {
|
||
var v0 = x0(d);
|
||
return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)";
|
||
});
|
||
}
|
||
function d3_svg_axisY(selection, y0, y1) {
|
||
selection.attr("transform", function(d) {
|
||
var v0 = y0(d);
|
||
return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")";
|
||
});
|
||
}
|
||
d3.svg.brush = function() {
|
||
var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0];
|
||
function brush(g) {
|
||
g.each(function() {
|
||
var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart);
|
||
var background = g.selectAll(".background").data([ 0 ]);
|
||
background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair");
|
||
g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move");
|
||
var resize = g.selectAll(".resize").data(resizes, d3_identity);
|
||
resize.exit().remove();
|
||
resize.enter().append("g").attr("class", function(d) {
|
||
return "resize " + d;
|
||
}).style("cursor", function(d) {
|
||
return d3_svg_brushCursor[d];
|
||
}).append("rect").attr("x", function(d) {
|
||
return /[ew]$/.test(d) ? -3 : null;
|
||
}).attr("y", function(d) {
|
||
return /^[ns]/.test(d) ? -3 : null;
|
||
}).attr("width", 6).attr("height", 6).style("visibility", "hidden");
|
||
resize.style("display", brush.empty() ? "none" : null);
|
||
var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range;
|
||
if (x) {
|
||
range = d3_scaleRange(x);
|
||
backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]);
|
||
redrawX(gUpdate);
|
||
}
|
||
if (y) {
|
||
range = d3_scaleRange(y);
|
||
backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]);
|
||
redrawY(gUpdate);
|
||
}
|
||
redraw(gUpdate);
|
||
});
|
||
}
|
||
brush.event = function(g) {
|
||
g.each(function() {
|
||
var event_ = event.of(this, arguments), extent1 = {
|
||
x: xExtent,
|
||
y: yExtent,
|
||
i: xExtentDomain,
|
||
j: yExtentDomain
|
||
}, extent0 = this.__chart__ || extent1;
|
||
this.__chart__ = extent1;
|
||
if (d3_transitionInheritId) {
|
||
d3.select(this).transition().each("start.brush", function() {
|
||
xExtentDomain = extent0.i;
|
||
yExtentDomain = extent0.j;
|
||
xExtent = extent0.x;
|
||
yExtent = extent0.y;
|
||
event_({
|
||
type: "brushstart"
|
||
});
|
||
}).tween("brush:brush", function() {
|
||
var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y);
|
||
xExtentDomain = yExtentDomain = null;
|
||
return function(t) {
|
||
xExtent = extent1.x = xi(t);
|
||
yExtent = extent1.y = yi(t);
|
||
event_({
|
||
type: "brush",
|
||
mode: "resize"
|
||
});
|
||
};
|
||
}).each("end.brush", function() {
|
||
xExtentDomain = extent1.i;
|
||
yExtentDomain = extent1.j;
|
||
event_({
|
||
type: "brush",
|
||
mode: "resize"
|
||
});
|
||
event_({
|
||
type: "brushend"
|
||
});
|
||
});
|
||
} else {
|
||
event_({
|
||
type: "brushstart"
|
||
});
|
||
event_({
|
||
type: "brush",
|
||
mode: "resize"
|
||
});
|
||
event_({
|
||
type: "brushend"
|
||
});
|
||
}
|
||
});
|
||
};
|
||
function redraw(g) {
|
||
g.selectAll(".resize").attr("transform", function(d) {
|
||
return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")";
|
||
});
|
||
}
|
||
function redrawX(g) {
|
||
g.select(".extent").attr("x", xExtent[0]);
|
||
g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]);
|
||
}
|
||
function redrawY(g) {
|
||
g.select(".extent").attr("y", yExtent[0]);
|
||
g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]);
|
||
}
|
||
function brushstart() {
|
||
var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(target), center, origin = d3.mouse(target), offset;
|
||
var w = d3.select(d3_window(target)).on("keydown.brush", keydown).on("keyup.brush", keyup);
|
||
if (d3.event.changedTouches) {
|
||
w.on("touchmove.brush", brushmove).on("touchend.brush", brushend);
|
||
} else {
|
||
w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend);
|
||
}
|
||
g.interrupt().selectAll("*").interrupt();
|
||
if (dragging) {
|
||
origin[0] = xExtent[0] - origin[0];
|
||
origin[1] = yExtent[0] - origin[1];
|
||
} else if (resizing) {
|
||
var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);
|
||
offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ];
|
||
origin[0] = xExtent[ex];
|
||
origin[1] = yExtent[ey];
|
||
} else if (d3.event.altKey) center = origin.slice();
|
||
g.style("pointer-events", "none").selectAll(".resize").style("display", null);
|
||
d3.select("body").style("cursor", eventTarget.style("cursor"));
|
||
event_({
|
||
type: "brushstart"
|
||
});
|
||
brushmove();
|
||
function keydown() {
|
||
if (d3.event.keyCode == 32) {
|
||
if (!dragging) {
|
||
center = null;
|
||
origin[0] -= xExtent[1];
|
||
origin[1] -= yExtent[1];
|
||
dragging = 2;
|
||
}
|
||
d3_eventPreventDefault();
|
||
}
|
||
}
|
||
function keyup() {
|
||
if (d3.event.keyCode == 32 && dragging == 2) {
|
||
origin[0] += xExtent[1];
|
||
origin[1] += yExtent[1];
|
||
dragging = 0;
|
||
d3_eventPreventDefault();
|
||
}
|
||
}
|
||
function brushmove() {
|
||
var point = d3.mouse(target), moved = false;
|
||
if (offset) {
|
||
point[0] += offset[0];
|
||
point[1] += offset[1];
|
||
}
|
||
if (!dragging) {
|
||
if (d3.event.altKey) {
|
||
if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ];
|
||
origin[0] = xExtent[+(point[0] < center[0])];
|
||
origin[1] = yExtent[+(point[1] < center[1])];
|
||
} else center = null;
|
||
}
|
||
if (resizingX && move1(point, x, 0)) {
|
||
redrawX(g);
|
||
moved = true;
|
||
}
|
||
if (resizingY && move1(point, y, 1)) {
|
||
redrawY(g);
|
||
moved = true;
|
||
}
|
||
if (moved) {
|
||
redraw(g);
|
||
event_({
|
||
type: "brush",
|
||
mode: dragging ? "move" : "resize"
|
||
});
|
||
}
|
||
}
|
||
function move1(point, scale, i) {
|
||
var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max;
|
||
if (dragging) {
|
||
r0 -= position;
|
||
r1 -= size + position;
|
||
}
|
||
min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i];
|
||
if (dragging) {
|
||
max = (min += position) + size;
|
||
} else {
|
||
if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min));
|
||
if (position < min) {
|
||
max = min;
|
||
min = position;
|
||
} else {
|
||
max = position;
|
||
}
|
||
}
|
||
if (extent[0] != min || extent[1] != max) {
|
||
if (i) yExtentDomain = null; else xExtentDomain = null;
|
||
extent[0] = min;
|
||
extent[1] = max;
|
||
return true;
|
||
}
|
||
}
|
||
function brushend() {
|
||
brushmove();
|
||
g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null);
|
||
d3.select("body").style("cursor", null);
|
||
w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null);
|
||
dragRestore();
|
||
event_({
|
||
type: "brushend"
|
||
});
|
||
}
|
||
}
|
||
brush.x = function(z) {
|
||
if (!arguments.length) return x;
|
||
x = z;
|
||
resizes = d3_svg_brushResizes[!x << 1 | !y];
|
||
return brush;
|
||
};
|
||
brush.y = function(z) {
|
||
if (!arguments.length) return y;
|
||
y = z;
|
||
resizes = d3_svg_brushResizes[!x << 1 | !y];
|
||
return brush;
|
||
};
|
||
brush.clamp = function(z) {
|
||
if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null;
|
||
if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z;
|
||
return brush;
|
||
};
|
||
brush.extent = function(z) {
|
||
var x0, x1, y0, y1, t;
|
||
if (!arguments.length) {
|
||
if (x) {
|
||
if (xExtentDomain) {
|
||
x0 = xExtentDomain[0], x1 = xExtentDomain[1];
|
||
} else {
|
||
x0 = xExtent[0], x1 = xExtent[1];
|
||
if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);
|
||
if (x1 < x0) t = x0, x0 = x1, x1 = t;
|
||
}
|
||
}
|
||
if (y) {
|
||
if (yExtentDomain) {
|
||
y0 = yExtentDomain[0], y1 = yExtentDomain[1];
|
||
} else {
|
||
y0 = yExtent[0], y1 = yExtent[1];
|
||
if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1);
|
||
if (y1 < y0) t = y0, y0 = y1, y1 = t;
|
||
}
|
||
}
|
||
return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ];
|
||
}
|
||
if (x) {
|
||
x0 = z[0], x1 = z[1];
|
||
if (y) x0 = x0[0], x1 = x1[0];
|
||
xExtentDomain = [ x0, x1 ];
|
||
if (x.invert) x0 = x(x0), x1 = x(x1);
|
||
if (x1 < x0) t = x0, x0 = x1, x1 = t;
|
||
if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ];
|
||
}
|
||
if (y) {
|
||
y0 = z[0], y1 = z[1];
|
||
if (x) y0 = y0[1], y1 = y1[1];
|
||
yExtentDomain = [ y0, y1 ];
|
||
if (y.invert) y0 = y(y0), y1 = y(y1);
|
||
if (y1 < y0) t = y0, y0 = y1, y1 = t;
|
||
if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ];
|
||
}
|
||
return brush;
|
||
};
|
||
brush.clear = function() {
|
||
if (!brush.empty()) {
|
||
xExtent = [ 0, 0 ], yExtent = [ 0, 0 ];
|
||
xExtentDomain = yExtentDomain = null;
|
||
}
|
||
return brush;
|
||
};
|
||
brush.empty = function() {
|
||
return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1];
|
||
};
|
||
return d3.rebind(brush, event, "on");
|
||
};
|
||
var d3_svg_brushCursor = {
|
||
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 d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ];
|
||
var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat;
|
||
var d3_time_formatUtc = d3_time_format.utc;
|
||
var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ");
|
||
d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso;
|
||
function d3_time_formatIsoNative(date) {
|
||
return date.toISOString();
|
||
}
|
||
d3_time_formatIsoNative.parse = function(string) {
|
||
var date = new Date(string);
|
||
return isNaN(date) ? null : date;
|
||
};
|
||
d3_time_formatIsoNative.toString = d3_time_formatIso.toString;
|
||
d3_time.second = d3_time_interval(function(date) {
|
||
return new d3_date(Math.floor(date / 1e3) * 1e3);
|
||
}, function(date, offset) {
|
||
date.setTime(date.getTime() + Math.floor(offset) * 1e3);
|
||
}, function(date) {
|
||
return date.getSeconds();
|
||
});
|
||
d3_time.seconds = d3_time.second.range;
|
||
d3_time.seconds.utc = d3_time.second.utc.range;
|
||
d3_time.minute = d3_time_interval(function(date) {
|
||
return new d3_date(Math.floor(date / 6e4) * 6e4);
|
||
}, function(date, offset) {
|
||
date.setTime(date.getTime() + Math.floor(offset) * 6e4);
|
||
}, function(date) {
|
||
return date.getMinutes();
|
||
});
|
||
d3_time.minutes = d3_time.minute.range;
|
||
d3_time.minutes.utc = d3_time.minute.utc.range;
|
||
d3_time.hour = d3_time_interval(function(date) {
|
||
var timezone = date.getTimezoneOffset() / 60;
|
||
return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5);
|
||
}, function(date, offset) {
|
||
date.setTime(date.getTime() + Math.floor(offset) * 36e5);
|
||
}, function(date) {
|
||
return date.getHours();
|
||
});
|
||
d3_time.hours = d3_time.hour.range;
|
||
d3_time.hours.utc = d3_time.hour.utc.range;
|
||
d3_time.month = d3_time_interval(function(date) {
|
||
date = d3_time.day(date);
|
||
date.setDate(1);
|
||
return date;
|
||
}, function(date, offset) {
|
||
date.setMonth(date.getMonth() + offset);
|
||
}, function(date) {
|
||
return date.getMonth();
|
||
});
|
||
d3_time.months = d3_time.month.range;
|
||
d3_time.months.utc = d3_time.month.utc.range;
|
||
function d3_time_scale(linear, methods, format) {
|
||
function scale(x) {
|
||
return linear(x);
|
||
}
|
||
scale.invert = function(x) {
|
||
return d3_time_scaleDate(linear.invert(x));
|
||
};
|
||
scale.domain = function(x) {
|
||
if (!arguments.length) return linear.domain().map(d3_time_scaleDate);
|
||
linear.domain(x);
|
||
return scale;
|
||
};
|
||
function tickMethod(extent, count) {
|
||
var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target);
|
||
return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) {
|
||
return d / 31536e6;
|
||
}), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i];
|
||
}
|
||
scale.nice = function(interval, skip) {
|
||
var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval);
|
||
if (method) interval = method[0], skip = method[1];
|
||
function skipped(date) {
|
||
return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length;
|
||
}
|
||
return scale.domain(d3_scale_nice(domain, skip > 1 ? {
|
||
floor: function(date) {
|
||
while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1);
|
||
return date;
|
||
},
|
||
ceil: function(date) {
|
||
while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1);
|
||
return date;
|
||
}
|
||
} : interval));
|
||
};
|
||
scale.ticks = function(interval, skip) {
|
||
var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ {
|
||
range: interval
|
||
}, skip ];
|
||
if (method) interval = method[0], skip = method[1];
|
||
return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip);
|
||
};
|
||
scale.tickFormat = function() {
|
||
return format;
|
||
};
|
||
scale.copy = function() {
|
||
return d3_time_scale(linear.copy(), methods, format);
|
||
};
|
||
return d3_scale_linearRebind(scale, linear);
|
||
}
|
||
function d3_time_scaleDate(t) {
|
||
return new Date(t);
|
||
}
|
||
var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ];
|
||
var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ];
|
||
var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) {
|
||
return d.getMilliseconds();
|
||
} ], [ ":%S", function(d) {
|
||
return d.getSeconds();
|
||
} ], [ "%I:%M", function(d) {
|
||
return d.getMinutes();
|
||
} ], [ "%I %p", function(d) {
|
||
return d.getHours();
|
||
} ], [ "%a %d", function(d) {
|
||
return d.getDay() && d.getDate() != 1;
|
||
} ], [ "%b %d", function(d) {
|
||
return d.getDate() != 1;
|
||
} ], [ "%B", function(d) {
|
||
return d.getMonth();
|
||
} ], [ "%Y", d3_true ] ]);
|
||
var d3_time_scaleMilliseconds = {
|
||
range: function(start, stop, step) {
|
||
return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate);
|
||
},
|
||
floor: d3_identity,
|
||
ceil: d3_identity
|
||
};
|
||
d3_time_scaleLocalMethods.year = d3_time.year;
|
||
d3_time.scale = function() {
|
||
return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat);
|
||
};
|
||
var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) {
|
||
return [ m[0].utc, m[1] ];
|
||
});
|
||
var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) {
|
||
return d.getUTCMilliseconds();
|
||
} ], [ ":%S", function(d) {
|
||
return d.getUTCSeconds();
|
||
} ], [ "%I:%M", function(d) {
|
||
return d.getUTCMinutes();
|
||
} ], [ "%I %p", function(d) {
|
||
return d.getUTCHours();
|
||
} ], [ "%a %d", function(d) {
|
||
return d.getUTCDay() && d.getUTCDate() != 1;
|
||
} ], [ "%b %d", function(d) {
|
||
return d.getUTCDate() != 1;
|
||
} ], [ "%B", function(d) {
|
||
return d.getUTCMonth();
|
||
} ], [ "%Y", d3_true ] ]);
|
||
d3_time_scaleUtcMethods.year = d3_time.year.utc;
|
||
d3_time.scale.utc = function() {
|
||
return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat);
|
||
};
|
||
d3.text = d3_xhrType(function(request) {
|
||
return request.responseText;
|
||
});
|
||
d3.json = function(url, callback) {
|
||
return d3_xhr(url, "application/json", d3_json, callback);
|
||
};
|
||
function d3_json(request) {
|
||
return JSON.parse(request.responseText);
|
||
}
|
||
d3.html = function(url, callback) {
|
||
return d3_xhr(url, "text/html", d3_html, callback);
|
||
};
|
||
function d3_html(request) {
|
||
var range = d3_document.createRange();
|
||
range.selectNode(d3_document.body);
|
||
return range.createContextualFragment(request.responseText);
|
||
}
|
||
d3.xml = d3_xhrType(function(request) {
|
||
return request.responseXML;
|
||
});
|
||
if (typeof define === "function" && define.amd) define(d3); else if (typeof module === "object" && module.exports) module.exports = d3;
|
||
this.d3 = d3;
|
||
}();
|
||
},{}],5:[function(require,module,exports){
|
||
/**
|
||
* @license
|
||
* Copyright (c) 2012-2013 Chris Pettitt
|
||
*
|
||
* 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.
|
||
*/
|
||
module.exports = {
|
||
graphlib: require("./lib/graphlib"),
|
||
dagre: require("./lib/dagre"),
|
||
intersect: require("./lib/intersect"),
|
||
render: require("./lib/render"),
|
||
util: require("./lib/util"),
|
||
version: require("./lib/version")
|
||
};
|
||
|
||
},{"./lib/dagre":12,"./lib/graphlib":13,"./lib/intersect":14,"./lib/render":29,"./lib/util":31,"./lib/version":32}],6:[function(require,module,exports){
|
||
var util = require("./util");
|
||
|
||
module.exports = {
|
||
"default": normal,
|
||
"normal": normal,
|
||
"vee": vee,
|
||
"undirected": undirected
|
||
};
|
||
|
||
function normal(parent, id, edge, type) {
|
||
var marker = parent.append("marker")
|
||
.attr("id", id)
|
||
.attr("viewBox", "0 0 10 10")
|
||
.attr("refX", 9)
|
||
.attr("refY", 5)
|
||
.attr("markerUnits", "strokeWidth")
|
||
.attr("markerWidth", 8)
|
||
.attr("markerHeight", 6)
|
||
.attr("orient", "auto");
|
||
|
||
var path = marker.append("path")
|
||
.attr("d", "M 0 0 L 10 5 L 0 10 z")
|
||
.style("stroke-width", 1)
|
||
.style("stroke-dasharray", "1,0");
|
||
util.applyStyle(path, edge[type + "Style"]);
|
||
}
|
||
|
||
function vee(parent, id, edge, type) {
|
||
var marker = parent.append("marker")
|
||
.attr("id", id)
|
||
.attr("viewBox", "0 0 10 10")
|
||
.attr("refX", 9)
|
||
.attr("refY", 5)
|
||
.attr("markerUnits", "strokeWidth")
|
||
.attr("markerWidth", 8)
|
||
.attr("markerHeight", 6)
|
||
.attr("orient", "auto");
|
||
|
||
var path = marker.append("path")
|
||
.attr("d", "M 0 0 L 10 5 L 0 10 L 4 5 z")
|
||
.style("stroke-width", 1)
|
||
.style("stroke-dasharray", "1,0");
|
||
util.applyStyle(path, edge[type + "Style"]);
|
||
}
|
||
|
||
function undirected(parent, id, edge, type) {
|
||
var marker = parent.append("marker")
|
||
.attr("id", id)
|
||
.attr("viewBox", "0 0 10 10")
|
||
.attr("refX", 9)
|
||
.attr("refY", 5)
|
||
.attr("markerUnits", "strokeWidth")
|
||
.attr("markerWidth", 8)
|
||
.attr("markerHeight", 6)
|
||
.attr("orient", "auto");
|
||
|
||
var path = marker.append("path")
|
||
.attr("d", "M 0 5 L 10 5")
|
||
.style("stroke-width", 1)
|
||
.style("stroke-dasharray", "1,0");
|
||
util.applyStyle(path, edge[type + "Style"]);
|
||
}
|
||
|
||
},{"./util":31}],7:[function(require,module,exports){
|
||
var util = require("./util"),
|
||
addLabel = require("./label/add-label");
|
||
|
||
module.exports = createClusters;
|
||
|
||
function createClusters(selection, g) {
|
||
var clusters = g.nodes().filter(function(v) { return util.isSubgraph(g, v); }),
|
||
svgClusters = selection.selectAll("g.cluster")
|
||
.data(clusters, function(v) { return v; });
|
||
|
||
svgClusters.selectAll("*").remove();
|
||
svgClusters.enter()
|
||
.append("g")
|
||
.attr("class", "cluster")
|
||
.attr("id",function(v){
|
||
var node = g.node(v);
|
||
return node.id;
|
||
})
|
||
.style("opacity", 0);
|
||
|
||
util.applyTransition(svgClusters, g)
|
||
.style("opacity", 1);
|
||
|
||
svgClusters.each(function(v) {
|
||
var node = g.node(v),
|
||
thisGroup = d3.select(this);
|
||
d3.select(this).append("rect");
|
||
var labelGroup = thisGroup.append("g").attr("class", "label");
|
||
addLabel(labelGroup, node, node.clusterLabelPos);
|
||
});
|
||
|
||
svgClusters.selectAll("rect").each(function(c) {
|
||
var node = g.node(c);
|
||
var domCluster = d3.select(this);
|
||
util.applyStyle(domCluster, node.style);
|
||
});
|
||
|
||
util.applyTransition(svgClusters.exit(), g)
|
||
.style("opacity", 0)
|
||
.remove();
|
||
|
||
return svgClusters;
|
||
}
|
||
|
||
},{"./label/add-label":22,"./util":31}],8:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("./lodash"),
|
||
addLabel = require("./label/add-label"),
|
||
util = require("./util"),
|
||
d3 = require("./d3");
|
||
|
||
module.exports = createEdgeLabels;
|
||
|
||
function createEdgeLabels(selection, g) {
|
||
var svgEdgeLabels = selection.selectAll("g.edgeLabel")
|
||
.data(g.edges(), function(e) { return util.edgeToId(e); })
|
||
.classed("update", true);
|
||
|
||
svgEdgeLabels.selectAll("*").remove();
|
||
svgEdgeLabels.enter()
|
||
.append("g")
|
||
.classed("edgeLabel", true)
|
||
.style("opacity", 0);
|
||
svgEdgeLabels.each(function(e) {
|
||
var edge = g.edge(e),
|
||
label = addLabel(d3.select(this), g.edge(e), 0, 0).classed("label", true),
|
||
bbox = label.node().getBBox();
|
||
|
||
if (edge.labelId) { label.attr("id", edge.labelId); }
|
||
if (!_.has(edge, "width")) { edge.width = bbox.width; }
|
||
if (!_.has(edge, "height")) { edge.height = bbox.height; }
|
||
});
|
||
|
||
util.applyTransition(svgEdgeLabels.exit(), g)
|
||
.style("opacity", 0)
|
||
.remove();
|
||
|
||
return svgEdgeLabels;
|
||
}
|
||
|
||
},{"./d3":11,"./label/add-label":22,"./lodash":25,"./util":31}],9:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("./lodash"),
|
||
intersectNode = require("./intersect/intersect-node"),
|
||
util = require("./util"),
|
||
d3 = require("./d3");
|
||
|
||
module.exports = createEdgePaths;
|
||
|
||
function createEdgePaths(selection, g, arrows) {
|
||
var svgPaths = selection.selectAll("g.edgePath")
|
||
.data(g.edges(), function(e) { return util.edgeToId(e); })
|
||
.classed("update", true);
|
||
|
||
enter(svgPaths, g);
|
||
exit(svgPaths, g);
|
||
|
||
util.applyTransition(svgPaths, g)
|
||
.style("opacity", 1);
|
||
|
||
// Save DOM element in the path group, and set ID and class
|
||
svgPaths.each(function(e) {
|
||
var domEdge = d3.select(this);
|
||
var edge = g.edge(e);
|
||
edge.elem = this;
|
||
|
||
if (edge.id) {
|
||
domEdge.attr("id", edge.id);
|
||
}
|
||
|
||
util.applyClass(domEdge, edge["class"],
|
||
(domEdge.classed("update") ? "update " : "") + "edgePath");
|
||
});
|
||
|
||
svgPaths.selectAll("path.path")
|
||
.each(function(e) {
|
||
var edge = g.edge(e);
|
||
edge.arrowheadId = _.uniqueId("arrowhead");
|
||
|
||
var domEdge = d3.select(this)
|
||
.attr("marker-end", function() {
|
||
return "url(#" + edge.arrowheadId + ")";
|
||
})
|
||
.style("fill", "none");
|
||
|
||
util.applyTransition(domEdge, g)
|
||
.attr("d", function(e) { return calcPoints(g, e); });
|
||
|
||
util.applyStyle(domEdge, edge.style);
|
||
});
|
||
|
||
svgPaths.selectAll("defs *").remove();
|
||
svgPaths.selectAll("defs")
|
||
.each(function(e) {
|
||
var edge = g.edge(e),
|
||
arrowhead = arrows[edge.arrowhead];
|
||
arrowhead(d3.select(this), edge.arrowheadId, edge, "arrowhead");
|
||
});
|
||
|
||
return svgPaths;
|
||
}
|
||
|
||
function calcPoints(g, e) {
|
||
var edge = g.edge(e),
|
||
tail = g.node(e.v),
|
||
head = g.node(e.w),
|
||
points = edge.points.slice(1, edge.points.length - 1);
|
||
points.unshift(intersectNode(tail, points[0]));
|
||
points.push(intersectNode(head, points[points.length - 1]));
|
||
|
||
return createLine(edge, points);
|
||
}
|
||
|
||
function createLine(edge, points) {
|
||
var line = d3.svg.line()
|
||
.x(function(d) { return d.x; })
|
||
.y(function(d) { return d.y; });
|
||
|
||
if (_.has(edge, "lineInterpolate")) {
|
||
line.interpolate(edge.lineInterpolate);
|
||
}
|
||
|
||
if (_.has(edge, "lineTension")) {
|
||
line.tension(Number(edge.lineTension));
|
||
}
|
||
|
||
return line(points);
|
||
}
|
||
|
||
function getCoords(elem) {
|
||
var bbox = elem.getBBox(),
|
||
matrix = elem.getTransformToElement(elem.ownerSVGElement)
|
||
.translate(bbox.width / 2, bbox.height / 2);
|
||
return { x: matrix.e, y: matrix.f };
|
||
}
|
||
|
||
function enter(svgPaths, g) {
|
||
var svgPathsEnter = svgPaths.enter()
|
||
.append("g")
|
||
.attr("class", "edgePath")
|
||
.style("opacity", 0);
|
||
svgPathsEnter.append("path")
|
||
.attr("class", "path")
|
||
.attr("d", function(e) {
|
||
var edge = g.edge(e),
|
||
sourceElem = g.node(e.v).elem,
|
||
points = _.range(edge.points.length).map(function() { return getCoords(sourceElem); });
|
||
return createLine(edge, points);
|
||
});
|
||
svgPathsEnter.append("defs");
|
||
}
|
||
|
||
function exit(svgPaths, g) {
|
||
var svgPathExit = svgPaths.exit();
|
||
util.applyTransition(svgPathExit, g)
|
||
.style("opacity", 0)
|
||
.remove();
|
||
|
||
util.applyTransition(svgPathExit.select("path.path"), g)
|
||
.attr("d", function(e) {
|
||
var source = g.node(e.v);
|
||
|
||
if (source) {
|
||
var points = _.range(this.pathSegList.length).map(function() { return source; });
|
||
return createLine({}, points);
|
||
} else {
|
||
return d3.select(this).attr("d");
|
||
}
|
||
});
|
||
}
|
||
|
||
},{"./d3":11,"./intersect/intersect-node":18,"./lodash":25,"./util":31}],10:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("./lodash"),
|
||
addLabel = require("./label/add-label"),
|
||
util = require("./util"),
|
||
d3 = require("./d3");
|
||
|
||
module.exports = createNodes;
|
||
|
||
function createNodes(selection, g, shapes) {
|
||
var simpleNodes = g.nodes().filter(function(v) { return !util.isSubgraph(g, v); });
|
||
var svgNodes = selection.selectAll("g.node")
|
||
.data(simpleNodes, function(v) { return v; })
|
||
.classed("update", true);
|
||
|
||
svgNodes.selectAll("*").remove();
|
||
svgNodes.enter()
|
||
.append("g")
|
||
.attr("class", "node")
|
||
.style("opacity", 0);
|
||
svgNodes.each(function(v) {
|
||
var node = g.node(v),
|
||
thisGroup = d3.select(this),
|
||
labelGroup = thisGroup.append("g").attr("class", "label"),
|
||
labelDom = addLabel(labelGroup, node),
|
||
shape = shapes[node.shape],
|
||
bbox = _.pick(labelDom.node().getBBox(), "width", "height");
|
||
|
||
node.elem = this;
|
||
|
||
if (node.id) { thisGroup.attr("id", node.id); }
|
||
if (node.labelId) { labelGroup.attr("id", node.labelId); }
|
||
util.applyClass(thisGroup, node["class"],
|
||
(thisGroup.classed("update") ? "update " : "") + "node");
|
||
|
||
if (_.has(node, "width")) { bbox.width = node.width; }
|
||
if (_.has(node, "height")) { bbox.height = node.height; }
|
||
|
||
bbox.width += node.paddingLeft + node.paddingRight;
|
||
bbox.height += node.paddingTop + node.paddingBottom;
|
||
labelGroup.attr("transform", "translate(" +
|
||
((node.paddingLeft - node.paddingRight) / 2) + "," +
|
||
((node.paddingTop - node.paddingBottom) / 2) + ")");
|
||
|
||
var shapeSvg = shape(d3.select(this), bbox, node);
|
||
util.applyStyle(shapeSvg, node.style);
|
||
|
||
var shapeBBox = shapeSvg.node().getBBox();
|
||
node.width = shapeBBox.width;
|
||
node.height = shapeBBox.height;
|
||
});
|
||
|
||
util.applyTransition(svgNodes.exit(), g)
|
||
.style("opacity", 0)
|
||
.remove();
|
||
|
||
return svgNodes;
|
||
}
|
||
|
||
},{"./d3":11,"./label/add-label":22,"./lodash":25,"./util":31}],11:[function(require,module,exports){
|
||
// Stub to get D3 either via NPM or from the global object
|
||
module.exports = window.d3;
|
||
|
||
},{}],12:[function(require,module,exports){
|
||
/* global window */
|
||
|
||
var dagre;
|
||
|
||
if (require) {
|
||
try {
|
||
dagre = require("dagre");
|
||
} catch (e) {}
|
||
}
|
||
|
||
if (!dagre) {
|
||
dagre = window.dagre;
|
||
}
|
||
|
||
module.exports = dagre;
|
||
|
||
},{"dagre":54}],13:[function(require,module,exports){
|
||
/* global window */
|
||
|
||
var graphlib;
|
||
|
||
if (require) {
|
||
try {
|
||
graphlib = require("graphlib");
|
||
} catch (e) {}
|
||
}
|
||
|
||
if (!graphlib) {
|
||
graphlib = window.graphlib;
|
||
}
|
||
|
||
module.exports = graphlib;
|
||
|
||
},{"graphlib":33}],14:[function(require,module,exports){
|
||
module.exports = {
|
||
node: require("./intersect-node"),
|
||
circle: require("./intersect-circle"),
|
||
ellipse: require("./intersect-ellipse"),
|
||
polygon: require("./intersect-polygon"),
|
||
rect: require("./intersect-rect")
|
||
};
|
||
|
||
},{"./intersect-circle":15,"./intersect-ellipse":16,"./intersect-node":18,"./intersect-polygon":19,"./intersect-rect":20}],15:[function(require,module,exports){
|
||
var intersectEllipse = require("./intersect-ellipse");
|
||
|
||
module.exports = intersectCircle;
|
||
|
||
function intersectCircle(node, rx, point) {
|
||
return intersectEllipse(node, rx, rx, point);
|
||
}
|
||
|
||
},{"./intersect-ellipse":16}],16:[function(require,module,exports){
|
||
module.exports = intersectEllipse;
|
||
|
||
function intersectEllipse(node, rx, ry, point) {
|
||
// Formulae from: http://mathworld.wolfram.com/Ellipse-LineIntersection.html
|
||
|
||
var cx = node.x;
|
||
var cy = node.y;
|
||
|
||
var px = cx - point.x;
|
||
var py = cy - point.y;
|
||
|
||
var det = Math.sqrt(rx * rx * py * py + ry * ry * px * px);
|
||
|
||
var dx = Math.abs(rx * ry * px / det);
|
||
if (point.x < cx) {
|
||
dx = -dx;
|
||
}
|
||
var dy = Math.abs(rx * ry * py / det);
|
||
if (point.y < cy) {
|
||
dy = -dy;
|
||
}
|
||
|
||
return {x: cx + dx, y: cy + dy};
|
||
}
|
||
|
||
|
||
},{}],17:[function(require,module,exports){
|
||
module.exports = intersectLine;
|
||
|
||
/*
|
||
* Returns the point at which two lines, p and q, intersect or returns
|
||
* undefined if they do not intersect.
|
||
*/
|
||
function intersectLine(p1, p2, q1, q2) {
|
||
// Algorithm from J. Avro, (ed.) Graphics Gems, No 2, Morgan Kaufmann, 1994,
|
||
// p7 and p473.
|
||
|
||
var a1, a2, b1, b2, c1, c2;
|
||
var r1, r2 , r3, r4;
|
||
var denom, offset, num;
|
||
var x, y;
|
||
|
||
// Compute a1, b1, c1, where line joining points 1 and 2 is F(x,y) = a1 x +
|
||
// b1 y + c1 = 0.
|
||
a1 = p2.y - p1.y;
|
||
b1 = p1.x - p2.x;
|
||
c1 = (p2.x * p1.y) - (p1.x * p2.y);
|
||
|
||
// Compute r3 and r4.
|
||
r3 = ((a1 * q1.x) + (b1 * q1.y) + c1);
|
||
r4 = ((a1 * q2.x) + (b1 * q2.y) + c1);
|
||
|
||
// Check signs of r3 and r4. If both point 3 and point 4 lie on
|
||
// same side of line 1, the line segments do not intersect.
|
||
if ((r3 !== 0) && (r4 !== 0) && sameSign(r3, r4)) {
|
||
return /*DONT_INTERSECT*/;
|
||
}
|
||
|
||
// Compute a2, b2, c2 where line joining points 3 and 4 is G(x,y) = a2 x + b2 y + c2 = 0
|
||
a2 = q2.y - q1.y;
|
||
b2 = q1.x - q2.x;
|
||
c2 = (q2.x * q1.y) - (q1.x * q2.y);
|
||
|
||
// Compute r1 and r2
|
||
r1 = (a2 * p1.x) + (b2 * p1.yy) + c2;
|
||
r2 = (a2 * p2.x) + (b2 * p2.y) + c2;
|
||
|
||
// Check signs of r1 and r2. If both point 1 and point 2 lie
|
||
// on same side of second line segment, the line segments do
|
||
// not intersect.
|
||
if ((r1 !== 0) && (r2 !== 0) && (sameSign(r1, r2))) {
|
||
return /*DONT_INTERSECT*/;
|
||
}
|
||
|
||
// Line segments intersect: compute intersection point.
|
||
denom = (a1 * b2) - (a2 * b1);
|
||
if (denom === 0) {
|
||
return /*COLLINEAR*/;
|
||
}
|
||
|
||
offset = Math.abs(denom / 2);
|
||
|
||
// The denom/2 is to get rounding instead of truncating. It
|
||
// is added or subtracted to the numerator, depending upon the
|
||
// sign of the numerator.
|
||
num = (b1 * c2) - (b2 * c1);
|
||
x = (num < 0) ? ((num - offset) / denom) : ((num + offset) / denom);
|
||
|
||
num = (a2 * c1) - (a1 * c2);
|
||
y = (num < 0) ? ((num - offset) / denom) : ((num + offset) / denom);
|
||
|
||
return { x: x, y: y };
|
||
}
|
||
|
||
function sameSign(r1, r2) {
|
||
return r1 * r2 > 0;
|
||
}
|
||
|
||
},{}],18:[function(require,module,exports){
|
||
module.exports = intersectNode;
|
||
|
||
function intersectNode(node, point) {
|
||
return node.intersect(point);
|
||
}
|
||
|
||
},{}],19:[function(require,module,exports){
|
||
var intersectLine = require("./intersect-line");
|
||
|
||
module.exports = intersectPolygon;
|
||
|
||
/*
|
||
* Returns the point ({x, y}) at which the point argument intersects with the
|
||
* node argument assuming that it has the shape specified by polygon.
|
||
*/
|
||
function intersectPolygon(node, polyPoints, point) {
|
||
var x1 = node.x;
|
||
var y1 = node.y;
|
||
|
||
var intersections = [];
|
||
|
||
var minX = Number.POSITIVE_INFINITY,
|
||
minY = Number.POSITIVE_INFINITY;
|
||
polyPoints.forEach(function(entry) {
|
||
minX = Math.min(minX, entry.x);
|
||
minY = Math.min(minY, entry.y);
|
||
});
|
||
|
||
var left = x1 - node.width / 2 - minX;
|
||
var top = y1 - node.height / 2 - minY;
|
||
|
||
for (var i = 0; i < polyPoints.length; i++) {
|
||
var p1 = polyPoints[i];
|
||
var p2 = polyPoints[i < polyPoints.length - 1 ? i + 1 : 0];
|
||
var intersect = intersectLine(node, point,
|
||
{x: left + p1.x, y: top + p1.y}, {x: left + p2.x, y: top + p2.y});
|
||
if (intersect) {
|
||
intersections.push(intersect);
|
||
}
|
||
}
|
||
|
||
if (!intersections.length) {
|
||
console.log("NO INTERSECTION FOUND, RETURN NODE CENTER", node);
|
||
return node;
|
||
}
|
||
|
||
if (intersections.length > 1) {
|
||
// More intersections, find the one nearest to edge end point
|
||
intersections.sort(function(p, q) {
|
||
var pdx = p.x - point.x,
|
||
pdy = p.y - point.y,
|
||
distp = Math.sqrt(pdx * pdx + pdy * pdy),
|
||
|
||
qdx = q.x - point.x,
|
||
qdy = q.y - point.y,
|
||
distq = Math.sqrt(qdx * qdx + qdy * qdy);
|
||
|
||
return (distp < distq) ? -1 : (distp === distq ? 0 : 1);
|
||
});
|
||
}
|
||
return intersections[0];
|
||
}
|
||
|
||
},{"./intersect-line":17}],20:[function(require,module,exports){
|
||
module.exports = intersectRect;
|
||
|
||
function intersectRect(node, point) {
|
||
var x = node.x;
|
||
var y = node.y;
|
||
|
||
// Rectangle intersection algorithm from:
|
||
// http://math.stackexchange.com/questions/108113/find-edge-between-two-boxes
|
||
var dx = point.x - x;
|
||
var dy = point.y - y;
|
||
var w = node.width / 2;
|
||
var h = node.height / 2;
|
||
|
||
var sx, sy;
|
||
if (Math.abs(dy) * w > Math.abs(dx) * h) {
|
||
// Intersection is top or bottom of rect.
|
||
if (dy < 0) {
|
||
h = -h;
|
||
}
|
||
sx = dy === 0 ? 0 : h * dx / dy;
|
||
sy = h;
|
||
} else {
|
||
// Intersection is left or right of rect.
|
||
if (dx < 0) {
|
||
w = -w;
|
||
}
|
||
sx = w;
|
||
sy = dx === 0 ? 0 : w * dy / dx;
|
||
}
|
||
|
||
return {x: x + sx, y: y + sy};
|
||
}
|
||
|
||
},{}],21:[function(require,module,exports){
|
||
var util = require("../util");
|
||
|
||
module.exports = addHtmlLabel;
|
||
|
||
function addHtmlLabel(root, node) {
|
||
var fo = root
|
||
.append("foreignObject")
|
||
.attr("width", "100000");
|
||
|
||
var div = fo
|
||
.append("xhtml:div");
|
||
|
||
var label = node.label;
|
||
switch(typeof label) {
|
||
case "function":
|
||
div.insert(label);
|
||
break;
|
||
case "object":
|
||
// Currently we assume this is a DOM object.
|
||
div.insert(function() { return label; });
|
||
break;
|
||
default: div.html(label);
|
||
}
|
||
|
||
util.applyStyle(div, node.labelStyle);
|
||
div.style("display", "inline-block");
|
||
// Fix for firefox
|
||
div.style("white-space", "nowrap");
|
||
|
||
// TODO find a better way to get dimensions for foreignObjects...
|
||
var w, h;
|
||
div
|
||
.each(function() {
|
||
w = this.clientWidth;
|
||
h = this.clientHeight;
|
||
});
|
||
|
||
fo
|
||
.attr("width", w)
|
||
.attr("height", h);
|
||
|
||
return fo;
|
||
}
|
||
|
||
},{"../util":31}],22:[function(require,module,exports){
|
||
var addTextLabel = require("./add-text-label"),
|
||
addHtmlLabel = require("./add-html-label"),
|
||
addSVGLabel = require("./add-svg-label");
|
||
|
||
module.exports = addLabel;
|
||
|
||
function addLabel(root, node, location) {
|
||
var label = node.label;
|
||
var labelSvg = root.append("g");
|
||
|
||
// Allow the label to be a string, a function that returns a DOM element, or
|
||
// a DOM element itself.
|
||
if (node.labelType === "svg") {
|
||
addSVGLabel(labelSvg, node);
|
||
} else if (typeof label !== "string" || node.labelType === "html") {
|
||
addHtmlLabel(labelSvg, node);
|
||
} else {
|
||
addTextLabel(labelSvg, node);
|
||
}
|
||
|
||
var labelBBox = labelSvg.node().getBBox();
|
||
var y;
|
||
switch(location) {
|
||
case "top":
|
||
y = (-node.height / 2);
|
||
break;
|
||
case "bottom":
|
||
y = (node.height / 2) - labelBBox.height;
|
||
break;
|
||
default:
|
||
y = (-labelBBox.height / 2);
|
||
}
|
||
labelSvg.attr("transform",
|
||
"translate(" + (-labelBBox.width / 2) + "," + y + ")");
|
||
|
||
return labelSvg;
|
||
}
|
||
|
||
},{"./add-html-label":21,"./add-svg-label":23,"./add-text-label":24}],23:[function(require,module,exports){
|
||
var util = require("../util");
|
||
|
||
module.exports = addSVGLabel;
|
||
|
||
function addSVGLabel(root, node) {
|
||
var domNode = root;
|
||
|
||
domNode.node().appendChild(node.label);
|
||
|
||
util.applyStyle(domNode, node.labelStyle);
|
||
|
||
return domNode;
|
||
}
|
||
|
||
},{"../util":31}],24:[function(require,module,exports){
|
||
var util = require("../util");
|
||
|
||
module.exports = addTextLabel;
|
||
|
||
/*
|
||
* Attaches a text label to the specified root. Handles escape sequences.
|
||
*/
|
||
function addTextLabel(root, node) {
|
||
var domNode = root.append("text");
|
||
|
||
var lines = processEscapeSequences(node.label).split("\n");
|
||
for (var i = 0; i < lines.length; i++) {
|
||
domNode
|
||
.append("tspan")
|
||
.attr("xml:space", "preserve")
|
||
.attr("dy", "1em")
|
||
.attr("x", "1")
|
||
.text(lines[i]);
|
||
}
|
||
|
||
util.applyStyle(domNode, node.labelStyle);
|
||
|
||
return domNode;
|
||
}
|
||
|
||
function processEscapeSequences(text) {
|
||
var newText = "",
|
||
escaped = false,
|
||
ch;
|
||
for (var i = 0; i < text.length; ++i) {
|
||
ch = text[i];
|
||
if (escaped) {
|
||
switch(ch) {
|
||
case "n": newText += "\n"; break;
|
||
default: newText += ch;
|
||
}
|
||
escaped = false;
|
||
} else if (ch === "\\") {
|
||
escaped = true;
|
||
} else {
|
||
newText += ch;
|
||
}
|
||
}
|
||
return newText;
|
||
}
|
||
|
||
},{"../util":31}],25:[function(require,module,exports){
|
||
/* global window */
|
||
|
||
var lodash;
|
||
|
||
if (require) {
|
||
try {
|
||
lodash = require("lodash");
|
||
} catch (e) {}
|
||
}
|
||
|
||
if (!lodash) {
|
||
lodash = window._;
|
||
}
|
||
|
||
module.exports = lodash;
|
||
|
||
},{"lodash":53}],26:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var util = require("./util"),
|
||
d3 = require("./d3");
|
||
|
||
module.exports = positionClusters;
|
||
|
||
function positionClusters(selection, g) {
|
||
var created = selection.filter(function() { return !d3.select(this).classed("update"); });
|
||
|
||
function translate(v) {
|
||
var node = g.node(v);
|
||
return "translate(" + node.x + "," + node.y + ")";
|
||
}
|
||
|
||
created.attr("transform", translate);
|
||
|
||
util.applyTransition(selection, g)
|
||
.style("opacity", 1)
|
||
.attr("transform", translate);
|
||
|
||
util.applyTransition(created.selectAll("rect"), g)
|
||
.attr("width", function(v) { return g.node(v).width; })
|
||
.attr("height", function(v) { return g.node(v).height; })
|
||
.attr("x", function(v) {
|
||
var node = g.node(v);
|
||
return -node.width / 2;
|
||
})
|
||
.attr("y", function(v) {
|
||
var node = g.node(v);
|
||
return -node.height / 2;
|
||
});
|
||
|
||
}
|
||
|
||
},{"./d3":11,"./util":31}],27:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var util = require("./util"),
|
||
d3 = require("./d3"),
|
||
_ = require("./lodash");
|
||
|
||
module.exports = positionEdgeLabels;
|
||
|
||
function positionEdgeLabels(selection, g) {
|
||
var created = selection.filter(function() { return !d3.select(this).classed("update"); });
|
||
|
||
function translate(e) {
|
||
var edge = g.edge(e);
|
||
return _.has(edge, "x") ? "translate(" + edge.x + "," + edge.y + ")" : "";
|
||
}
|
||
|
||
created.attr("transform", translate);
|
||
|
||
util.applyTransition(selection, g)
|
||
.style("opacity", 1)
|
||
.attr("transform", translate);
|
||
}
|
||
|
||
},{"./d3":11,"./lodash":25,"./util":31}],28:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var util = require("./util"),
|
||
d3 = require("./d3");
|
||
|
||
module.exports = positionNodes;
|
||
|
||
function positionNodes(selection, g) {
|
||
var created = selection.filter(function() { return !d3.select(this).classed("update"); });
|
||
|
||
function translate(v) {
|
||
var node = g.node(v);
|
||
return "translate(" + node.x + "," + node.y + ")";
|
||
}
|
||
|
||
created.attr("transform", translate);
|
||
|
||
util.applyTransition(selection, g)
|
||
.style("opacity", 1)
|
||
.attr("transform", translate);
|
||
}
|
||
|
||
},{"./d3":11,"./util":31}],29:[function(require,module,exports){
|
||
var _ = require("./lodash"),
|
||
layout = require("./dagre").layout;
|
||
|
||
module.exports = render;
|
||
|
||
// This design is based on http://bost.ocks.org/mike/chart/.
|
||
function render() {
|
||
var createNodes = require("./create-nodes"),
|
||
createClusters = require("./create-clusters"),
|
||
createEdgeLabels = require("./create-edge-labels"),
|
||
createEdgePaths = require("./create-edge-paths"),
|
||
positionNodes = require("./position-nodes"),
|
||
positionEdgeLabels = require("./position-edge-labels"),
|
||
positionClusters = require("./position-clusters"),
|
||
shapes = require("./shapes"),
|
||
arrows = require("./arrows");
|
||
|
||
var fn = function(svg, g) {
|
||
preProcessGraph(g);
|
||
|
||
var outputGroup = createOrSelectGroup(svg, "output"),
|
||
clustersGroup = createOrSelectGroup(outputGroup, "clusters"),
|
||
edgePathsGroup = createOrSelectGroup(outputGroup, "edgePaths"),
|
||
edgeLabels = createEdgeLabels(createOrSelectGroup(outputGroup, "edgeLabels"), g),
|
||
nodes = createNodes(createOrSelectGroup(outputGroup, "nodes"), g, shapes);
|
||
|
||
layout(g);
|
||
|
||
positionNodes(nodes, g);
|
||
positionEdgeLabels(edgeLabels, g);
|
||
createEdgePaths(edgePathsGroup, g, arrows);
|
||
|
||
var clusters = createClusters(clustersGroup, g);
|
||
positionClusters(clusters, g);
|
||
|
||
postProcessGraph(g);
|
||
};
|
||
|
||
fn.createNodes = function(value) {
|
||
if (!arguments.length) return createNodes;
|
||
createNodes = value;
|
||
return fn;
|
||
};
|
||
|
||
fn.createClusters = function(value) {
|
||
if (!arguments.length) return createClusters;
|
||
createClusters = value;
|
||
return fn;
|
||
};
|
||
|
||
fn.createEdgeLabels = function(value) {
|
||
if (!arguments.length) return createEdgeLabels;
|
||
createEdgeLabels = value;
|
||
return fn;
|
||
};
|
||
|
||
fn.createEdgePaths = function(value) {
|
||
if (!arguments.length) return createEdgePaths;
|
||
createEdgePaths = value;
|
||
return fn;
|
||
};
|
||
|
||
fn.shapes = function(value) {
|
||
if (!arguments.length) return shapes;
|
||
shapes = value;
|
||
return fn;
|
||
};
|
||
|
||
fn.arrows = function(value) {
|
||
if (!arguments.length) return arrows;
|
||
arrows = value;
|
||
return fn;
|
||
};
|
||
|
||
return fn;
|
||
}
|
||
|
||
var NODE_DEFAULT_ATTRS = {
|
||
paddingLeft: 10,
|
||
paddingRight: 10,
|
||
paddingTop: 10,
|
||
paddingBottom: 10,
|
||
rx: 0,
|
||
ry: 0,
|
||
shape: "rect"
|
||
};
|
||
|
||
var EDGE_DEFAULT_ATTRS = {
|
||
arrowhead: "normal",
|
||
lineInterpolate: "linear"
|
||
};
|
||
|
||
function preProcessGraph(g) {
|
||
g.nodes().forEach(function(v) {
|
||
var node = g.node(v);
|
||
if (!_.has(node, "label") && !g.children(v).length) { node.label = v; }
|
||
|
||
if (_.has(node, "paddingX")) {
|
||
_.defaults(node, {
|
||
paddingLeft: node.paddingX,
|
||
paddingRight: node.paddingX
|
||
});
|
||
}
|
||
|
||
if (_.has(node, "paddingY")) {
|
||
_.defaults(node, {
|
||
paddingTop: node.paddingY,
|
||
paddingBottom: node.paddingY
|
||
});
|
||
}
|
||
|
||
if (_.has(node, "padding")) {
|
||
_.defaults(node, {
|
||
paddingLeft: node.padding,
|
||
paddingRight: node.padding,
|
||
paddingTop: node.padding,
|
||
paddingBottom: node.padding
|
||
});
|
||
}
|
||
|
||
_.defaults(node, NODE_DEFAULT_ATTRS);
|
||
|
||
_.each(["paddingLeft", "paddingRight", "paddingTop", "paddingBottom"], function(k) {
|
||
node[k] = Number(node[k]);
|
||
});
|
||
|
||
// Save dimensions for restore during post-processing
|
||
if (_.has(node, "width")) { node._prevWidth = node.width; }
|
||
if (_.has(node, "height")) { node._prevHeight = node.height; }
|
||
});
|
||
|
||
g.edges().forEach(function(e) {
|
||
var edge = g.edge(e);
|
||
if (!_.has(edge, "label")) { edge.label = ""; }
|
||
_.defaults(edge, EDGE_DEFAULT_ATTRS);
|
||
});
|
||
}
|
||
|
||
function postProcessGraph(g) {
|
||
_.each(g.nodes(), function(v) {
|
||
var node = g.node(v);
|
||
|
||
// Restore original dimensions
|
||
if (_.has(node, "_prevWidth")) {
|
||
node.width = node._prevWidth;
|
||
} else {
|
||
delete node.width;
|
||
}
|
||
|
||
if (_.has(node, "_prevHeight")) {
|
||
node.height = node._prevHeight;
|
||
} else {
|
||
delete node.height;
|
||
}
|
||
|
||
delete node._prevWidth;
|
||
delete node._prevHeight;
|
||
});
|
||
}
|
||
|
||
function createOrSelectGroup(root, name) {
|
||
var selection = root.select("g." + name);
|
||
if (selection.empty()) {
|
||
selection = root.append("g").attr("class", name);
|
||
}
|
||
return selection;
|
||
}
|
||
|
||
},{"./arrows":6,"./create-clusters":7,"./create-edge-labels":8,"./create-edge-paths":9,"./create-nodes":10,"./dagre":12,"./lodash":25,"./position-clusters":26,"./position-edge-labels":27,"./position-nodes":28,"./shapes":30}],30:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var intersectRect = require("./intersect/intersect-rect"),
|
||
intersectEllipse = require("./intersect/intersect-ellipse"),
|
||
intersectCircle = require("./intersect/intersect-circle"),
|
||
intersectPolygon = require("./intersect/intersect-polygon");
|
||
|
||
module.exports = {
|
||
rect: rect,
|
||
ellipse: ellipse,
|
||
circle: circle,
|
||
diamond: diamond
|
||
};
|
||
|
||
function rect(parent, bbox, node) {
|
||
var shapeSvg = parent.insert("rect", ":first-child")
|
||
.attr("rx", node.rx)
|
||
.attr("ry", node.ry)
|
||
.attr("x", -bbox.width / 2)
|
||
.attr("y", -bbox.height / 2)
|
||
.attr("width", bbox.width)
|
||
.attr("height", bbox.height);
|
||
|
||
node.intersect = function(point) {
|
||
return intersectRect(node, point);
|
||
};
|
||
|
||
return shapeSvg;
|
||
}
|
||
|
||
function ellipse(parent, bbox, node) {
|
||
var rx = bbox.width / 2,
|
||
ry = bbox.height / 2,
|
||
shapeSvg = parent.insert("ellipse", ":first-child")
|
||
.attr("x", -bbox.width / 2)
|
||
.attr("y", -bbox.height / 2)
|
||
.attr("rx", rx)
|
||
.attr("ry", ry);
|
||
|
||
node.intersect = function(point) {
|
||
return intersectEllipse(node, rx, ry, point);
|
||
};
|
||
|
||
return shapeSvg;
|
||
}
|
||
|
||
function circle(parent, bbox, node) {
|
||
var r = Math.max(bbox.width, bbox.height) / 2,
|
||
shapeSvg = parent.insert("circle", ":first-child")
|
||
.attr("x", -bbox.width / 2)
|
||
.attr("y", -bbox.height / 2)
|
||
.attr("r", r);
|
||
|
||
node.intersect = function(point) {
|
||
return intersectCircle(node, r, point);
|
||
};
|
||
|
||
return shapeSvg;
|
||
}
|
||
|
||
// Circumscribe an ellipse for the bounding box with a diamond shape. I derived
|
||
// the function to calculate the diamond shape from:
|
||
// http://mathforum.org/kb/message.jspa?messageID=3750236
|
||
function diamond(parent, bbox, node) {
|
||
var w = (bbox.width * Math.SQRT2) / 2,
|
||
h = (bbox.height * Math.SQRT2) / 2,
|
||
points = [
|
||
{ x: 0, y: -h },
|
||
{ x: -w, y: 0 },
|
||
{ x: 0, y: h },
|
||
{ x: w, y: 0 }
|
||
],
|
||
shapeSvg = parent.insert("polygon", ":first-child")
|
||
.attr("points", points.map(function(p) { return p.x + "," + p.y; }).join(" "));
|
||
|
||
node.intersect = function(p) {
|
||
return intersectPolygon(node, points, p);
|
||
};
|
||
|
||
return shapeSvg;
|
||
}
|
||
|
||
},{"./intersect/intersect-circle":15,"./intersect/intersect-ellipse":16,"./intersect/intersect-polygon":19,"./intersect/intersect-rect":20}],31:[function(require,module,exports){
|
||
var _ = require("./lodash");
|
||
|
||
// Public utility functions
|
||
module.exports = {
|
||
isSubgraph: isSubgraph,
|
||
edgeToId: edgeToId,
|
||
applyStyle: applyStyle,
|
||
applyClass: applyClass,
|
||
applyTransition: applyTransition
|
||
};
|
||
|
||
/*
|
||
* Returns true if the specified node in the graph is a subgraph node. A
|
||
* subgraph node is one that contains other nodes.
|
||
*/
|
||
function isSubgraph(g, v) {
|
||
return !!g.children(v).length;
|
||
}
|
||
|
||
function edgeToId(e) {
|
||
return escapeId(e.v) + ":" + escapeId(e.w) + ":" + escapeId(e.name);
|
||
}
|
||
|
||
var ID_DELIM = /:/g;
|
||
function escapeId(str) {
|
||
return str ? String(str).replace(ID_DELIM, "\\:") : "";
|
||
}
|
||
|
||
function applyStyle(dom, styleFn) {
|
||
if (styleFn) {
|
||
dom.attr("style", styleFn);
|
||
}
|
||
}
|
||
|
||
function applyClass(dom, classFn, otherClasses) {
|
||
if (classFn) {
|
||
dom
|
||
.attr("class", classFn)
|
||
.attr("class", otherClasses + " " + dom.attr("class"));
|
||
}
|
||
}
|
||
|
||
function applyTransition(selection, g) {
|
||
var graph = g.graph();
|
||
|
||
if (_.isPlainObject(graph)) {
|
||
var transition = graph.transition;
|
||
if (_.isFunction(transition)) {
|
||
return transition(selection);
|
||
}
|
||
}
|
||
|
||
return selection;
|
||
}
|
||
|
||
},{"./lodash":25}],32:[function(require,module,exports){
|
||
module.exports = "0.4.10";
|
||
|
||
},{}],33:[function(require,module,exports){
|
||
/**
|
||
* Copyright (c) 2014, Chris Pettitt
|
||
* All rights reserved.
|
||
*
|
||
* Redistribution and use in source and binary forms, with or without
|
||
* modification, are permitted provided that the following conditions are met:
|
||
*
|
||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||
* list of conditions and the following disclaimer.
|
||
*
|
||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||
* this list of conditions and the following disclaimer in the documentation
|
||
* and/or other materials provided with the distribution.
|
||
*
|
||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||
* may be used to endorse or promote products derived from this software without
|
||
* specific prior written permission.
|
||
*
|
||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
*/
|
||
|
||
var lib = require("./lib");
|
||
|
||
module.exports = {
|
||
Graph: lib.Graph,
|
||
json: require("./lib/json"),
|
||
alg: require("./lib/alg"),
|
||
version: lib.version
|
||
};
|
||
|
||
},{"./lib":49,"./lib/alg":40,"./lib/json":50}],34:[function(require,module,exports){
|
||
var _ = require("../lodash");
|
||
|
||
module.exports = components;
|
||
|
||
function components(g) {
|
||
var visited = {},
|
||
cmpts = [],
|
||
cmpt;
|
||
|
||
function dfs(v) {
|
||
if (_.has(visited, v)) return;
|
||
visited[v] = true;
|
||
cmpt.push(v);
|
||
_.each(g.successors(v), dfs);
|
||
_.each(g.predecessors(v), dfs);
|
||
}
|
||
|
||
_.each(g.nodes(), function(v) {
|
||
cmpt = [];
|
||
dfs(v);
|
||
if (cmpt.length) {
|
||
cmpts.push(cmpt);
|
||
}
|
||
});
|
||
|
||
return cmpts;
|
||
}
|
||
|
||
},{"../lodash":51}],35:[function(require,module,exports){
|
||
var _ = require("../lodash");
|
||
|
||
module.exports = dfs;
|
||
|
||
/*
|
||
* A helper that preforms a pre- or post-order traversal on the input graph
|
||
* and returns the nodes in the order they were visited. This algorithm treats
|
||
* the input as undirected.
|
||
*
|
||
* Order must be one of "pre" or "post".
|
||
*/
|
||
function dfs(g, vs, order) {
|
||
if (!_.isArray(vs)) {
|
||
vs = [vs];
|
||
}
|
||
|
||
var acc = [],
|
||
visited = {};
|
||
_.each(vs, function(v) {
|
||
if (!g.hasNode(v)) {
|
||
throw new Error("Graph does not have node: " + v);
|
||
}
|
||
|
||
doDfs(g, v, order === "post", visited, acc);
|
||
});
|
||
return acc;
|
||
}
|
||
|
||
function doDfs(g, v, postorder, visited, acc) {
|
||
if (!_.has(visited, v)) {
|
||
visited[v] = true;
|
||
|
||
if (!postorder) { acc.push(v); }
|
||
_.each(g.neighbors(v), function(w) {
|
||
doDfs(g, w, postorder, visited, acc);
|
||
});
|
||
if (postorder) { acc.push(v); }
|
||
}
|
||
}
|
||
|
||
},{"../lodash":51}],36:[function(require,module,exports){
|
||
var dijkstra = require("./dijkstra"),
|
||
_ = require("../lodash");
|
||
|
||
module.exports = dijkstraAll;
|
||
|
||
function dijkstraAll(g, weightFunc, edgeFunc) {
|
||
return _.transform(g.nodes(), function(acc, v) {
|
||
acc[v] = dijkstra(g, v, weightFunc, edgeFunc);
|
||
}, {});
|
||
}
|
||
|
||
},{"../lodash":51,"./dijkstra":37}],37:[function(require,module,exports){
|
||
var _ = require("../lodash"),
|
||
PriorityQueue = require("../data/priority-queue");
|
||
|
||
module.exports = dijkstra;
|
||
|
||
var DEFAULT_WEIGHT_FUNC = _.constant(1);
|
||
|
||
function dijkstra(g, source, weightFn, edgeFn) {
|
||
return runDijkstra(g, String(source),
|
||
weightFn || DEFAULT_WEIGHT_FUNC,
|
||
edgeFn || function(v) { return g.outEdges(v); });
|
||
}
|
||
|
||
function runDijkstra(g, source, weightFn, edgeFn) {
|
||
var results = {},
|
||
pq = new PriorityQueue(),
|
||
v, vEntry;
|
||
|
||
var updateNeighbors = function(edge) {
|
||
var w = edge.v !== v ? edge.v : edge.w,
|
||
wEntry = results[w],
|
||
weight = weightFn(edge),
|
||
distance = vEntry.distance + weight;
|
||
|
||
if (weight < 0) {
|
||
throw new Error("dijkstra does not allow negative edge weights. " +
|
||
"Bad edge: " + edge + " Weight: " + weight);
|
||
}
|
||
|
||
if (distance < wEntry.distance) {
|
||
wEntry.distance = distance;
|
||
wEntry.predecessor = v;
|
||
pq.decrease(w, distance);
|
||
}
|
||
};
|
||
|
||
g.nodes().forEach(function(v) {
|
||
var distance = v === source ? 0 : Number.POSITIVE_INFINITY;
|
||
results[v] = { distance: distance };
|
||
pq.add(v, distance);
|
||
});
|
||
|
||
while (pq.size() > 0) {
|
||
v = pq.removeMin();
|
||
vEntry = results[v];
|
||
if (vEntry.distance === Number.POSITIVE_INFINITY) {
|
||
break;
|
||
}
|
||
|
||
edgeFn(v).forEach(updateNeighbors);
|
||
}
|
||
|
||
return results;
|
||
}
|
||
|
||
},{"../data/priority-queue":47,"../lodash":51}],38:[function(require,module,exports){
|
||
var _ = require("../lodash"),
|
||
tarjan = require("./tarjan");
|
||
|
||
module.exports = findCycles;
|
||
|
||
function findCycles(g) {
|
||
return _.filter(tarjan(g), function(cmpt) {
|
||
return cmpt.length > 1 || (cmpt.length === 1 && g.hasEdge(cmpt[0], cmpt[0]));
|
||
});
|
||
}
|
||
|
||
},{"../lodash":51,"./tarjan":45}],39:[function(require,module,exports){
|
||
var _ = require("../lodash");
|
||
|
||
module.exports = floydWarshall;
|
||
|
||
var DEFAULT_WEIGHT_FUNC = _.constant(1);
|
||
|
||
function floydWarshall(g, weightFn, edgeFn) {
|
||
return runFloydWarshall(g,
|
||
weightFn || DEFAULT_WEIGHT_FUNC,
|
||
edgeFn || function(v) { return g.outEdges(v); });
|
||
}
|
||
|
||
function runFloydWarshall(g, weightFn, edgeFn) {
|
||
var results = {},
|
||
nodes = g.nodes();
|
||
|
||
nodes.forEach(function(v) {
|
||
results[v] = {};
|
||
results[v][v] = { distance: 0 };
|
||
nodes.forEach(function(w) {
|
||
if (v !== w) {
|
||
results[v][w] = { distance: Number.POSITIVE_INFINITY };
|
||
}
|
||
});
|
||
edgeFn(v).forEach(function(edge) {
|
||
var w = edge.v === v ? edge.w : edge.v,
|
||
d = weightFn(edge);
|
||
results[v][w] = { distance: d, predecessor: v };
|
||
});
|
||
});
|
||
|
||
nodes.forEach(function(k) {
|
||
var rowK = results[k];
|
||
nodes.forEach(function(i) {
|
||
var rowI = results[i];
|
||
nodes.forEach(function(j) {
|
||
var ik = rowI[k];
|
||
var kj = rowK[j];
|
||
var ij = rowI[j];
|
||
var altDistance = ik.distance + kj.distance;
|
||
if (altDistance < ij.distance) {
|
||
ij.distance = altDistance;
|
||
ij.predecessor = kj.predecessor;
|
||
}
|
||
});
|
||
});
|
||
});
|
||
|
||
return results;
|
||
}
|
||
|
||
},{"../lodash":51}],40:[function(require,module,exports){
|
||
module.exports = {
|
||
components: require("./components"),
|
||
dijkstra: require("./dijkstra"),
|
||
dijkstraAll: require("./dijkstra-all"),
|
||
findCycles: require("./find-cycles"),
|
||
floydWarshall: require("./floyd-warshall"),
|
||
isAcyclic: require("./is-acyclic"),
|
||
postorder: require("./postorder"),
|
||
preorder: require("./preorder"),
|
||
prim: require("./prim"),
|
||
tarjan: require("./tarjan"),
|
||
topsort: require("./topsort")
|
||
};
|
||
|
||
},{"./components":34,"./dijkstra":37,"./dijkstra-all":36,"./find-cycles":38,"./floyd-warshall":39,"./is-acyclic":41,"./postorder":42,"./preorder":43,"./prim":44,"./tarjan":45,"./topsort":46}],41:[function(require,module,exports){
|
||
var topsort = require("./topsort");
|
||
|
||
module.exports = isAcyclic;
|
||
|
||
function isAcyclic(g) {
|
||
try {
|
||
topsort(g);
|
||
} catch (e) {
|
||
if (e instanceof topsort.CycleException) {
|
||
return false;
|
||
}
|
||
throw e;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
},{"./topsort":46}],42:[function(require,module,exports){
|
||
var dfs = require("./dfs");
|
||
|
||
module.exports = postorder;
|
||
|
||
function postorder(g, vs) {
|
||
return dfs(g, vs, "post");
|
||
}
|
||
|
||
},{"./dfs":35}],43:[function(require,module,exports){
|
||
var dfs = require("./dfs");
|
||
|
||
module.exports = preorder;
|
||
|
||
function preorder(g, vs) {
|
||
return dfs(g, vs, "pre");
|
||
}
|
||
|
||
},{"./dfs":35}],44:[function(require,module,exports){
|
||
var _ = require("../lodash"),
|
||
Graph = require("../graph"),
|
||
PriorityQueue = require("../data/priority-queue");
|
||
|
||
module.exports = prim;
|
||
|
||
function prim(g, weightFunc) {
|
||
var result = new Graph(),
|
||
parents = {},
|
||
pq = new PriorityQueue(),
|
||
v;
|
||
|
||
function updateNeighbors(edge) {
|
||
var w = edge.v === v ? edge.w : edge.v,
|
||
pri = pq.priority(w);
|
||
if (pri !== undefined) {
|
||
var edgeWeight = weightFunc(edge);
|
||
if (edgeWeight < pri) {
|
||
parents[w] = v;
|
||
pq.decrease(w, edgeWeight);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (g.nodeCount() === 0) {
|
||
return result;
|
||
}
|
||
|
||
_.each(g.nodes(), function(v) {
|
||
pq.add(v, Number.POSITIVE_INFINITY);
|
||
result.setNode(v);
|
||
});
|
||
|
||
// Start from an arbitrary node
|
||
pq.decrease(g.nodes()[0], 0);
|
||
|
||
var init = false;
|
||
while (pq.size() > 0) {
|
||
v = pq.removeMin();
|
||
if (_.has(parents, v)) {
|
||
result.setEdge(v, parents[v]);
|
||
} else if (init) {
|
||
throw new Error("Input graph is not connected: " + g);
|
||
} else {
|
||
init = true;
|
||
}
|
||
|
||
g.nodeEdges(v).forEach(updateNeighbors);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
},{"../data/priority-queue":47,"../graph":48,"../lodash":51}],45:[function(require,module,exports){
|
||
var _ = require("../lodash");
|
||
|
||
module.exports = tarjan;
|
||
|
||
function tarjan(g) {
|
||
var index = 0,
|
||
stack = [],
|
||
visited = {}, // node id -> { onStack, lowlink, index }
|
||
results = [];
|
||
|
||
function dfs(v) {
|
||
var entry = visited[v] = {
|
||
onStack: true,
|
||
lowlink: index,
|
||
index: index++
|
||
};
|
||
stack.push(v);
|
||
|
||
g.successors(v).forEach(function(w) {
|
||
if (!_.has(visited, w)) {
|
||
dfs(w);
|
||
entry.lowlink = Math.min(entry.lowlink, visited[w].lowlink);
|
||
} else if (visited[w].onStack) {
|
||
entry.lowlink = Math.min(entry.lowlink, visited[w].index);
|
||
}
|
||
});
|
||
|
||
if (entry.lowlink === entry.index) {
|
||
var cmpt = [],
|
||
w;
|
||
do {
|
||
w = stack.pop();
|
||
visited[w].onStack = false;
|
||
cmpt.push(w);
|
||
} while (v !== w);
|
||
results.push(cmpt);
|
||
}
|
||
}
|
||
|
||
g.nodes().forEach(function(v) {
|
||
if (!_.has(visited, v)) {
|
||
dfs(v);
|
||
}
|
||
});
|
||
|
||
return results;
|
||
}
|
||
|
||
},{"../lodash":51}],46:[function(require,module,exports){
|
||
var _ = require("../lodash");
|
||
|
||
module.exports = topsort;
|
||
topsort.CycleException = CycleException;
|
||
|
||
function topsort(g) {
|
||
var visited = {},
|
||
stack = {},
|
||
results = [];
|
||
|
||
function visit(node) {
|
||
if (_.has(stack, node)) {
|
||
throw new CycleException();
|
||
}
|
||
|
||
if (!_.has(visited, node)) {
|
||
stack[node] = true;
|
||
visited[node] = true;
|
||
_.each(g.predecessors(node), visit);
|
||
delete stack[node];
|
||
results.push(node);
|
||
}
|
||
}
|
||
|
||
_.each(g.sinks(), visit);
|
||
|
||
if (_.size(visited) !== g.nodeCount()) {
|
||
throw new CycleException();
|
||
}
|
||
|
||
return results;
|
||
}
|
||
|
||
function CycleException() {}
|
||
|
||
},{"../lodash":51}],47:[function(require,module,exports){
|
||
var _ = require("../lodash");
|
||
|
||
module.exports = PriorityQueue;
|
||
|
||
/**
|
||
* A min-priority queue data structure. This algorithm is derived from Cormen,
|
||
* et al., "Introduction to Algorithms". The basic idea of a min-priority
|
||
* queue is that you can efficiently (in O(1) time) get the smallest key in
|
||
* the queue. Adding and removing elements takes O(log n) time. A key can
|
||
* have its priority decreased in O(log n) time.
|
||
*/
|
||
function PriorityQueue() {
|
||
this._arr = [];
|
||
this._keyIndices = {};
|
||
}
|
||
|
||
/**
|
||
* Returns the number of elements in the queue. Takes `O(1)` time.
|
||
*/
|
||
PriorityQueue.prototype.size = function() {
|
||
return this._arr.length;
|
||
};
|
||
|
||
/**
|
||
* Returns the keys that are in the queue. Takes `O(n)` time.
|
||
*/
|
||
PriorityQueue.prototype.keys = function() {
|
||
return this._arr.map(function(x) { return x.key; });
|
||
};
|
||
|
||
/**
|
||
* Returns `true` if **key** is in the queue and `false` if not.
|
||
*/
|
||
PriorityQueue.prototype.has = function(key) {
|
||
return _.has(this._keyIndices, key);
|
||
};
|
||
|
||
/**
|
||
* Returns the priority for **key**. If **key** is not present in the queue
|
||
* then this function returns `undefined`. Takes `O(1)` time.
|
||
*
|
||
* @param {Object} key
|
||
*/
|
||
PriorityQueue.prototype.priority = function(key) {
|
||
var index = this._keyIndices[key];
|
||
if (index !== undefined) {
|
||
return this._arr[index].priority;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Returns the key for the minimum element in this queue. If the queue is
|
||
* empty this function throws an Error. Takes `O(1)` time.
|
||
*/
|
||
PriorityQueue.prototype.min = function() {
|
||
if (this.size() === 0) {
|
||
throw new Error("Queue underflow");
|
||
}
|
||
return this._arr[0].key;
|
||
};
|
||
|
||
/**
|
||
* Inserts a new key into the priority queue. If the key already exists in
|
||
* the queue this function returns `false`; otherwise it will return `true`.
|
||
* Takes `O(n)` time.
|
||
*
|
||
* @param {Object} key the key to add
|
||
* @param {Number} priority the initial priority for the key
|
||
*/
|
||
PriorityQueue.prototype.add = function(key, priority) {
|
||
var keyIndices = this._keyIndices;
|
||
key = String(key);
|
||
if (!_.has(keyIndices, key)) {
|
||
var arr = this._arr;
|
||
var index = arr.length;
|
||
keyIndices[key] = index;
|
||
arr.push({key: key, priority: priority});
|
||
this._decrease(index);
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
|
||
/**
|
||
* Removes and returns the smallest key in the queue. Takes `O(log n)` time.
|
||
*/
|
||
PriorityQueue.prototype.removeMin = function() {
|
||
this._swap(0, this._arr.length - 1);
|
||
var min = this._arr.pop();
|
||
delete this._keyIndices[min.key];
|
||
this._heapify(0);
|
||
return min.key;
|
||
};
|
||
|
||
/**
|
||
* Decreases the priority for **key** to **priority**. If the new priority is
|
||
* greater than the previous priority, this function will throw an Error.
|
||
*
|
||
* @param {Object} key the key for which to raise priority
|
||
* @param {Number} priority the new priority for the key
|
||
*/
|
||
PriorityQueue.prototype.decrease = function(key, priority) {
|
||
var index = this._keyIndices[key];
|
||
if (priority > this._arr[index].priority) {
|
||
throw new Error("New priority is greater than current priority. " +
|
||
"Key: " + key + " Old: " + this._arr[index].priority + " New: " + priority);
|
||
}
|
||
this._arr[index].priority = priority;
|
||
this._decrease(index);
|
||
};
|
||
|
||
PriorityQueue.prototype._heapify = function(i) {
|
||
var arr = this._arr;
|
||
var l = 2 * i,
|
||
r = l + 1,
|
||
largest = i;
|
||
if (l < arr.length) {
|
||
largest = arr[l].priority < arr[largest].priority ? l : largest;
|
||
if (r < arr.length) {
|
||
largest = arr[r].priority < arr[largest].priority ? r : largest;
|
||
}
|
||
if (largest !== i) {
|
||
this._swap(i, largest);
|
||
this._heapify(largest);
|
||
}
|
||
}
|
||
};
|
||
|
||
PriorityQueue.prototype._decrease = function(index) {
|
||
var arr = this._arr;
|
||
var priority = arr[index].priority;
|
||
var parent;
|
||
while (index !== 0) {
|
||
parent = index >> 1;
|
||
if (arr[parent].priority < priority) {
|
||
break;
|
||
}
|
||
this._swap(index, parent);
|
||
index = parent;
|
||
}
|
||
};
|
||
|
||
PriorityQueue.prototype._swap = function(i, j) {
|
||
var arr = this._arr;
|
||
var keyIndices = this._keyIndices;
|
||
var origArrI = arr[i];
|
||
var origArrJ = arr[j];
|
||
arr[i] = origArrJ;
|
||
arr[j] = origArrI;
|
||
keyIndices[origArrJ.key] = i;
|
||
keyIndices[origArrI.key] = j;
|
||
};
|
||
|
||
},{"../lodash":51}],48:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("./lodash");
|
||
|
||
module.exports = Graph;
|
||
|
||
var DEFAULT_EDGE_NAME = "\x00",
|
||
GRAPH_NODE = "\x00",
|
||
EDGE_KEY_DELIM = "\x01";
|
||
|
||
// Implementation notes:
|
||
//
|
||
// * Node id query functions should return string ids for the nodes
|
||
// * Edge id query functions should return an "edgeObj", edge object, that is
|
||
// composed of enough information to uniquely identify an edge: {v, w, name}.
|
||
// * Internally we use an "edgeId", a stringified form of the edgeObj, to
|
||
// reference edges. This is because we need a performant way to look these
|
||
// edges up and, object properties, which have string keys, are the closest
|
||
// we're going to get to a performant hashtable in JavaScript.
|
||
|
||
function Graph(opts) {
|
||
this._isDirected = _.has(opts, "directed") ? opts.directed : true;
|
||
this._isMultigraph = _.has(opts, "multigraph") ? opts.multigraph : false;
|
||
this._isCompound = _.has(opts, "compound") ? opts.compound : false;
|
||
|
||
// Label for the graph itself
|
||
this._label = undefined;
|
||
|
||
// Defaults to be set when creating a new node
|
||
this._defaultNodeLabelFn = _.constant(undefined);
|
||
|
||
// Defaults to be set when creating a new edge
|
||
this._defaultEdgeLabelFn = _.constant(undefined);
|
||
|
||
// v -> label
|
||
this._nodes = {};
|
||
|
||
if (this._isCompound) {
|
||
// v -> parent
|
||
this._parent = {};
|
||
|
||
// v -> children
|
||
this._children = {};
|
||
this._children[GRAPH_NODE] = {};
|
||
}
|
||
|
||
// v -> edgeObj
|
||
this._in = {};
|
||
|
||
// u -> v -> Number
|
||
this._preds = {};
|
||
|
||
// v -> edgeObj
|
||
this._out = {};
|
||
|
||
// v -> w -> Number
|
||
this._sucs = {};
|
||
|
||
// e -> edgeObj
|
||
this._edgeObjs = {};
|
||
|
||
// e -> label
|
||
this._edgeLabels = {};
|
||
}
|
||
|
||
/* Number of nodes in the graph. Should only be changed by the implementation. */
|
||
Graph.prototype._nodeCount = 0;
|
||
|
||
/* Number of edges in the graph. Should only be changed by the implementation. */
|
||
Graph.prototype._edgeCount = 0;
|
||
|
||
|
||
/* === Graph functions ========= */
|
||
|
||
Graph.prototype.isDirected = function() {
|
||
return this._isDirected;
|
||
};
|
||
|
||
Graph.prototype.isMultigraph = function() {
|
||
return this._isMultigraph;
|
||
};
|
||
|
||
Graph.prototype.isCompound = function() {
|
||
return this._isCompound;
|
||
};
|
||
|
||
Graph.prototype.setGraph = function(label) {
|
||
this._label = label;
|
||
return this;
|
||
};
|
||
|
||
Graph.prototype.graph = function() {
|
||
return this._label;
|
||
};
|
||
|
||
|
||
/* === Node functions ========== */
|
||
|
||
Graph.prototype.setDefaultNodeLabel = function(newDefault) {
|
||
if (!_.isFunction(newDefault)) {
|
||
newDefault = _.constant(newDefault);
|
||
}
|
||
this._defaultNodeLabelFn = newDefault;
|
||
return this;
|
||
};
|
||
|
||
Graph.prototype.nodeCount = function() {
|
||
return this._nodeCount;
|
||
};
|
||
|
||
Graph.prototype.nodes = function() {
|
||
return _.keys(this._nodes);
|
||
};
|
||
|
||
Graph.prototype.sources = function() {
|
||
return _.filter(this.nodes(), function(v) {
|
||
return _.isEmpty(this._in[v]);
|
||
}, this);
|
||
};
|
||
|
||
Graph.prototype.sinks = function() {
|
||
return _.filter(this.nodes(), function(v) {
|
||
return _.isEmpty(this._out[v]);
|
||
}, this);
|
||
};
|
||
|
||
Graph.prototype.setNodes = function(vs, value) {
|
||
var args = arguments;
|
||
_.each(vs, function(v) {
|
||
if (args.length > 1) {
|
||
this.setNode(v, value);
|
||
} else {
|
||
this.setNode(v);
|
||
}
|
||
}, this);
|
||
return this;
|
||
};
|
||
|
||
Graph.prototype.setNode = function(v, value) {
|
||
if (_.has(this._nodes, v)) {
|
||
if (arguments.length > 1) {
|
||
this._nodes[v] = value;
|
||
}
|
||
return this;
|
||
}
|
||
|
||
this._nodes[v] = arguments.length > 1 ? value : this._defaultNodeLabelFn(v);
|
||
if (this._isCompound) {
|
||
this._parent[v] = GRAPH_NODE;
|
||
this._children[v] = {};
|
||
this._children[GRAPH_NODE][v] = true;
|
||
}
|
||
this._in[v] = {};
|
||
this._preds[v] = {};
|
||
this._out[v] = {};
|
||
this._sucs[v] = {};
|
||
++this._nodeCount;
|
||
return this;
|
||
};
|
||
|
||
Graph.prototype.node = function(v) {
|
||
return this._nodes[v];
|
||
};
|
||
|
||
Graph.prototype.hasNode = function(v) {
|
||
return _.has(this._nodes, v);
|
||
};
|
||
|
||
Graph.prototype.removeNode = function(v) {
|
||
var self = this;
|
||
if (_.has(this._nodes, v)) {
|
||
var removeEdge = function(e) { self.removeEdge(self._edgeObjs[e]); };
|
||
delete this._nodes[v];
|
||
if (this._isCompound) {
|
||
this._removeFromParentsChildList(v);
|
||
delete this._parent[v];
|
||
_.each(this.children(v), function(child) {
|
||
this.setParent(child);
|
||
}, this);
|
||
delete this._children[v];
|
||
}
|
||
_.each(_.keys(this._in[v]), removeEdge);
|
||
delete this._in[v];
|
||
delete this._preds[v];
|
||
_.each(_.keys(this._out[v]), removeEdge);
|
||
delete this._out[v];
|
||
delete this._sucs[v];
|
||
--this._nodeCount;
|
||
}
|
||
return this;
|
||
};
|
||
|
||
Graph.prototype.setParent = function(v, parent) {
|
||
if (!this._isCompound) {
|
||
throw new Error("Cannot set parent in a non-compound graph");
|
||
}
|
||
|
||
if (_.isUndefined(parent)) {
|
||
parent = GRAPH_NODE;
|
||
} else {
|
||
// Coerce parent to string
|
||
parent += "";
|
||
for (var ancestor = parent;
|
||
!_.isUndefined(ancestor);
|
||
ancestor = this.parent(ancestor)) {
|
||
if (ancestor === v) {
|
||
throw new Error("Setting " + parent+ " as parent of " + v +
|
||
" would create create a cycle");
|
||
}
|
||
}
|
||
|
||
this.setNode(parent);
|
||
}
|
||
|
||
this.setNode(v);
|
||
this._removeFromParentsChildList(v);
|
||
this._parent[v] = parent;
|
||
this._children[parent][v] = true;
|
||
return this;
|
||
};
|
||
|
||
Graph.prototype._removeFromParentsChildList = function(v) {
|
||
delete this._children[this._parent[v]][v];
|
||
};
|
||
|
||
Graph.prototype.parent = function(v) {
|
||
if (this._isCompound) {
|
||
var parent = this._parent[v];
|
||
if (parent !== GRAPH_NODE) {
|
||
return parent;
|
||
}
|
||
}
|
||
};
|
||
|
||
Graph.prototype.children = function(v) {
|
||
if (_.isUndefined(v)) {
|
||
v = GRAPH_NODE;
|
||
}
|
||
|
||
if (this._isCompound) {
|
||
var children = this._children[v];
|
||
if (children) {
|
||
return _.keys(children);
|
||
}
|
||
} else if (v === GRAPH_NODE) {
|
||
return this.nodes();
|
||
} else if (this.hasNode(v)) {
|
||
return [];
|
||
}
|
||
};
|
||
|
||
Graph.prototype.predecessors = function(v) {
|
||
var predsV = this._preds[v];
|
||
if (predsV) {
|
||
return _.keys(predsV);
|
||
}
|
||
};
|
||
|
||
Graph.prototype.successors = function(v) {
|
||
var sucsV = this._sucs[v];
|
||
if (sucsV) {
|
||
return _.keys(sucsV);
|
||
}
|
||
};
|
||
|
||
Graph.prototype.neighbors = function(v) {
|
||
var preds = this.predecessors(v);
|
||
if (preds) {
|
||
return _.union(preds, this.successors(v));
|
||
}
|
||
};
|
||
|
||
Graph.prototype.filterNodes = function(filter) {
|
||
var copy = new this.constructor({
|
||
directed: this._isDirected,
|
||
multigraph: this._isMultigraph,
|
||
compound: this._isCompound
|
||
});
|
||
|
||
copy.setGraph(this.graph());
|
||
|
||
_.each(this._nodes, function(value, v) {
|
||
if (filter(v)) {
|
||
copy.setNode(v, value);
|
||
}
|
||
}, this);
|
||
|
||
_.each(this._edgeObjs, function(e) {
|
||
if (copy.hasNode(e.v) && copy.hasNode(e.w)) {
|
||
copy.setEdge(e, this.edge(e));
|
||
}
|
||
}, this);
|
||
|
||
var self = this;
|
||
var parents = {};
|
||
function findParent(v) {
|
||
var parent = self.parent(v);
|
||
if (parent === undefined || copy.hasNode(parent)) {
|
||
parents[v] = parent;
|
||
return parent;
|
||
} else if (parent in parents) {
|
||
return parents[parent];
|
||
} else {
|
||
return findParent(parent);
|
||
}
|
||
}
|
||
|
||
if (this._isCompound) {
|
||
_.each(copy.nodes(), function(v) {
|
||
copy.setParent(v, findParent(v));
|
||
});
|
||
}
|
||
|
||
return copy;
|
||
};
|
||
|
||
/* === Edge functions ========== */
|
||
|
||
Graph.prototype.setDefaultEdgeLabel = function(newDefault) {
|
||
if (!_.isFunction(newDefault)) {
|
||
newDefault = _.constant(newDefault);
|
||
}
|
||
this._defaultEdgeLabelFn = newDefault;
|
||
return this;
|
||
};
|
||
|
||
Graph.prototype.edgeCount = function() {
|
||
return this._edgeCount;
|
||
};
|
||
|
||
Graph.prototype.edges = function() {
|
||
return _.values(this._edgeObjs);
|
||
};
|
||
|
||
Graph.prototype.setPath = function(vs, value) {
|
||
var self = this,
|
||
args = arguments;
|
||
_.reduce(vs, function(v, w) {
|
||
if (args.length > 1) {
|
||
self.setEdge(v, w, value);
|
||
} else {
|
||
self.setEdge(v, w);
|
||
}
|
||
return w;
|
||
});
|
||
return this;
|
||
};
|
||
|
||
/*
|
||
* setEdge(v, w, [value, [name]])
|
||
* setEdge({ v, w, [name] }, [value])
|
||
*/
|
||
Graph.prototype.setEdge = function() {
|
||
var v, w, name, value,
|
||
valueSpecified = false,
|
||
arg0 = arguments[0];
|
||
|
||
if (typeof arg0 === "object" && arg0 !== null && "v" in arg0) {
|
||
v = arg0.v;
|
||
w = arg0.w;
|
||
name = arg0.name;
|
||
if (arguments.length === 2) {
|
||
value = arguments[1];
|
||
valueSpecified = true;
|
||
}
|
||
} else {
|
||
v = arg0;
|
||
w = arguments[1];
|
||
name = arguments[3];
|
||
if (arguments.length > 2) {
|
||
value = arguments[2];
|
||
valueSpecified = true;
|
||
}
|
||
}
|
||
|
||
v = "" + v;
|
||
w = "" + w;
|
||
if (!_.isUndefined(name)) {
|
||
name = "" + name;
|
||
}
|
||
|
||
var e = edgeArgsToId(this._isDirected, v, w, name);
|
||
if (_.has(this._edgeLabels, e)) {
|
||
if (valueSpecified) {
|
||
this._edgeLabels[e] = value;
|
||
}
|
||
return this;
|
||
}
|
||
|
||
if (!_.isUndefined(name) && !this._isMultigraph) {
|
||
throw new Error("Cannot set a named edge when isMultigraph = false");
|
||
}
|
||
|
||
// It didn't exist, so we need to create it.
|
||
// First ensure the nodes exist.
|
||
this.setNode(v);
|
||
this.setNode(w);
|
||
|
||
this._edgeLabels[e] = valueSpecified ? value : this._defaultEdgeLabelFn(v, w, name);
|
||
|
||
var edgeObj = edgeArgsToObj(this._isDirected, v, w, name);
|
||
// Ensure we add undirected edges in a consistent way.
|
||
v = edgeObj.v;
|
||
w = edgeObj.w;
|
||
|
||
Object.freeze(edgeObj);
|
||
this._edgeObjs[e] = edgeObj;
|
||
incrementOrInitEntry(this._preds[w], v);
|
||
incrementOrInitEntry(this._sucs[v], w);
|
||
this._in[w][e] = edgeObj;
|
||
this._out[v][e] = edgeObj;
|
||
this._edgeCount++;
|
||
return this;
|
||
};
|
||
|
||
Graph.prototype.edge = function(v, w, name) {
|
||
var e = (arguments.length === 1
|
||
? edgeObjToId(this._isDirected, arguments[0])
|
||
: edgeArgsToId(this._isDirected, v, w, name));
|
||
return this._edgeLabels[e];
|
||
};
|
||
|
||
Graph.prototype.hasEdge = function(v, w, name) {
|
||
var e = (arguments.length === 1
|
||
? edgeObjToId(this._isDirected, arguments[0])
|
||
: edgeArgsToId(this._isDirected, v, w, name));
|
||
return _.has(this._edgeLabels, e);
|
||
};
|
||
|
||
Graph.prototype.removeEdge = function(v, w, name) {
|
||
var e = (arguments.length === 1
|
||
? edgeObjToId(this._isDirected, arguments[0])
|
||
: edgeArgsToId(this._isDirected, v, w, name)),
|
||
edge = this._edgeObjs[e];
|
||
if (edge) {
|
||
v = edge.v;
|
||
w = edge.w;
|
||
delete this._edgeLabels[e];
|
||
delete this._edgeObjs[e];
|
||
decrementOrRemoveEntry(this._preds[w], v);
|
||
decrementOrRemoveEntry(this._sucs[v], w);
|
||
delete this._in[w][e];
|
||
delete this._out[v][e];
|
||
this._edgeCount--;
|
||
}
|
||
return this;
|
||
};
|
||
|
||
Graph.prototype.inEdges = function(v, u) {
|
||
var inV = this._in[v];
|
||
if (inV) {
|
||
var edges = _.values(inV);
|
||
if (!u) {
|
||
return edges;
|
||
}
|
||
return _.filter(edges, function(edge) { return edge.v === u; });
|
||
}
|
||
};
|
||
|
||
Graph.prototype.outEdges = function(v, w) {
|
||
var outV = this._out[v];
|
||
if (outV) {
|
||
var edges = _.values(outV);
|
||
if (!w) {
|
||
return edges;
|
||
}
|
||
return _.filter(edges, function(edge) { return edge.w === w; });
|
||
}
|
||
};
|
||
|
||
Graph.prototype.nodeEdges = function(v, w) {
|
||
var inEdges = this.inEdges(v, w);
|
||
if (inEdges) {
|
||
return inEdges.concat(this.outEdges(v, w));
|
||
}
|
||
};
|
||
|
||
function incrementOrInitEntry(map, k) {
|
||
if (map[k]) {
|
||
map[k]++;
|
||
} else {
|
||
map[k] = 1;
|
||
}
|
||
}
|
||
|
||
function decrementOrRemoveEntry(map, k) {
|
||
if (!--map[k]) { delete map[k]; }
|
||
}
|
||
|
||
function edgeArgsToId(isDirected, v_, w_, name) {
|
||
var v = "" + v_;
|
||
var w = "" + w_;
|
||
if (!isDirected && v > w) {
|
||
var tmp = v;
|
||
v = w;
|
||
w = tmp;
|
||
}
|
||
return v + EDGE_KEY_DELIM + w + EDGE_KEY_DELIM +
|
||
(_.isUndefined(name) ? DEFAULT_EDGE_NAME : name);
|
||
}
|
||
|
||
function edgeArgsToObj(isDirected, v_, w_, name) {
|
||
var v = "" + v_;
|
||
var w = "" + w_;
|
||
if (!isDirected && v > w) {
|
||
var tmp = v;
|
||
v = w;
|
||
w = tmp;
|
||
}
|
||
var edgeObj = { v: v, w: w };
|
||
if (name) {
|
||
edgeObj.name = name;
|
||
}
|
||
return edgeObj;
|
||
}
|
||
|
||
function edgeObjToId(isDirected, edgeObj) {
|
||
return edgeArgsToId(isDirected, edgeObj.v, edgeObj.w, edgeObj.name);
|
||
}
|
||
|
||
},{"./lodash":51}],49:[function(require,module,exports){
|
||
// Includes only the "core" of graphlib
|
||
module.exports = {
|
||
Graph: require("./graph"),
|
||
version: require("./version")
|
||
};
|
||
|
||
},{"./graph":48,"./version":52}],50:[function(require,module,exports){
|
||
var _ = require("./lodash"),
|
||
Graph = require("./graph");
|
||
|
||
module.exports = {
|
||
write: write,
|
||
read: read
|
||
};
|
||
|
||
function write(g) {
|
||
var json = {
|
||
options: {
|
||
directed: g.isDirected(),
|
||
multigraph: g.isMultigraph(),
|
||
compound: g.isCompound()
|
||
},
|
||
nodes: writeNodes(g),
|
||
edges: writeEdges(g)
|
||
};
|
||
if (!_.isUndefined(g.graph())) {
|
||
json.value = _.clone(g.graph());
|
||
}
|
||
return json;
|
||
}
|
||
|
||
function writeNodes(g) {
|
||
return _.map(g.nodes(), function(v) {
|
||
var nodeValue = g.node(v),
|
||
parent = g.parent(v),
|
||
node = { v: v };
|
||
if (!_.isUndefined(nodeValue)) {
|
||
node.value = nodeValue;
|
||
}
|
||
if (!_.isUndefined(parent)) {
|
||
node.parent = parent;
|
||
}
|
||
return node;
|
||
});
|
||
}
|
||
|
||
function writeEdges(g) {
|
||
return _.map(g.edges(), function(e) {
|
||
var edgeValue = g.edge(e),
|
||
edge = { v: e.v, w: e.w };
|
||
if (!_.isUndefined(e.name)) {
|
||
edge.name = e.name;
|
||
}
|
||
if (!_.isUndefined(edgeValue)) {
|
||
edge.value = edgeValue;
|
||
}
|
||
return edge;
|
||
});
|
||
}
|
||
|
||
function read(json) {
|
||
var g = new Graph(json.options).setGraph(json.value);
|
||
_.each(json.nodes, function(entry) {
|
||
g.setNode(entry.v, entry.value);
|
||
if (entry.parent) {
|
||
g.setParent(entry.v, entry.parent);
|
||
}
|
||
});
|
||
_.each(json.edges, function(entry) {
|
||
g.setEdge({ v: entry.v, w: entry.w, name: entry.name }, entry.value);
|
||
});
|
||
return g;
|
||
}
|
||
|
||
},{"./graph":48,"./lodash":51}],51:[function(require,module,exports){
|
||
/* global window */
|
||
|
||
var lodash;
|
||
|
||
if (typeof require === "function") {
|
||
try {
|
||
lodash = require("lodash");
|
||
} catch (e) {}
|
||
}
|
||
|
||
if (!lodash) {
|
||
lodash = window._;
|
||
}
|
||
|
||
module.exports = lodash;
|
||
|
||
},{"lodash":53}],52:[function(require,module,exports){
|
||
module.exports = '1.0.7';
|
||
|
||
},{}],53:[function(require,module,exports){
|
||
(function (global){
|
||
/**
|
||
* @license
|
||
* lodash 3.10.1 (Custom Build) <https://lodash.com/>
|
||
* Build: `lodash modern -d -o ./index.js`
|
||
* Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
|
||
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
||
* Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||
* Available under MIT license <https://lodash.com/license>
|
||
*/
|
||
;(function() {
|
||
|
||
/** Used as a safe reference for `undefined` in pre-ES5 environments. */
|
||
var undefined;
|
||
|
||
/** Used as the semantic version number. */
|
||
var VERSION = '3.10.1';
|
||
|
||
/** Used to compose bitmasks for wrapper metadata. */
|
||
var BIND_FLAG = 1,
|
||
BIND_KEY_FLAG = 2,
|
||
CURRY_BOUND_FLAG = 4,
|
||
CURRY_FLAG = 8,
|
||
CURRY_RIGHT_FLAG = 16,
|
||
PARTIAL_FLAG = 32,
|
||
PARTIAL_RIGHT_FLAG = 64,
|
||
ARY_FLAG = 128,
|
||
REARG_FLAG = 256;
|
||
|
||
/** Used as default options for `_.trunc`. */
|
||
var DEFAULT_TRUNC_LENGTH = 30,
|
||
DEFAULT_TRUNC_OMISSION = '...';
|
||
|
||
/** Used to detect when a function becomes hot. */
|
||
var HOT_COUNT = 150,
|
||
HOT_SPAN = 16;
|
||
|
||
/** Used as the size to enable large array optimizations. */
|
||
var LARGE_ARRAY_SIZE = 200;
|
||
|
||
/** Used to indicate the type of lazy iteratees. */
|
||
var LAZY_FILTER_FLAG = 1,
|
||
LAZY_MAP_FLAG = 2;
|
||
|
||
/** Used as the `TypeError` message for "Functions" methods. */
|
||
var FUNC_ERROR_TEXT = 'Expected a function';
|
||
|
||
/** Used as the internal argument placeholder. */
|
||
var PLACEHOLDER = '__lodash_placeholder__';
|
||
|
||
/** `Object#toString` result references. */
|
||
var argsTag = '[object Arguments]',
|
||
arrayTag = '[object Array]',
|
||
boolTag = '[object Boolean]',
|
||
dateTag = '[object Date]',
|
||
errorTag = '[object Error]',
|
||
funcTag = '[object Function]',
|
||
mapTag = '[object Map]',
|
||
numberTag = '[object Number]',
|
||
objectTag = '[object Object]',
|
||
regexpTag = '[object RegExp]',
|
||
setTag = '[object Set]',
|
||
stringTag = '[object String]',
|
||
weakMapTag = '[object WeakMap]';
|
||
|
||
var arrayBufferTag = '[object ArrayBuffer]',
|
||
float32Tag = '[object Float32Array]',
|
||
float64Tag = '[object Float64Array]',
|
||
int8Tag = '[object Int8Array]',
|
||
int16Tag = '[object Int16Array]',
|
||
int32Tag = '[object Int32Array]',
|
||
uint8Tag = '[object Uint8Array]',
|
||
uint8ClampedTag = '[object Uint8ClampedArray]',
|
||
uint16Tag = '[object Uint16Array]',
|
||
uint32Tag = '[object Uint32Array]';
|
||
|
||
/** Used to match empty string literals in compiled template source. */
|
||
var reEmptyStringLeading = /\b__p \+= '';/g,
|
||
reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
|
||
reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
|
||
|
||
/** Used to match HTML entities and HTML characters. */
|
||
var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g,
|
||
reUnescapedHtml = /[&<>"'`]/g,
|
||
reHasEscapedHtml = RegExp(reEscapedHtml.source),
|
||
reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
|
||
|
||
/** Used to match template delimiters. */
|
||
var reEscape = /<%-([\s\S]+?)%>/g,
|
||
reEvaluate = /<%([\s\S]+?)%>/g,
|
||
reInterpolate = /<%=([\s\S]+?)%>/g;
|
||
|
||
/** Used to match property names within property paths. */
|
||
var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,
|
||
reIsPlainProp = /^\w*$/,
|
||
rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g;
|
||
|
||
/**
|
||
* Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns)
|
||
* and those outlined by [`EscapeRegExpPattern`](http://ecma-international.org/ecma-262/6.0/#sec-escaperegexppattern).
|
||
*/
|
||
var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g,
|
||
reHasRegExpChars = RegExp(reRegExpChars.source);
|
||
|
||
/** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */
|
||
var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g;
|
||
|
||
/** Used to match backslashes in property paths. */
|
||
var reEscapeChar = /\\(\\)?/g;
|
||
|
||
/** Used to match [ES template delimiters](http://ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components). */
|
||
var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
|
||
|
||
/** Used to match `RegExp` flags from their coerced string values. */
|
||
var reFlags = /\w*$/;
|
||
|
||
/** Used to detect hexadecimal string values. */
|
||
var reHasHexPrefix = /^0[xX]/;
|
||
|
||
/** Used to detect host constructors (Safari > 5). */
|
||
var reIsHostCtor = /^\[object .+?Constructor\]$/;
|
||
|
||
/** Used to detect unsigned integer values. */
|
||
var reIsUint = /^\d+$/;
|
||
|
||
/** Used to match latin-1 supplementary letters (excluding mathematical operators). */
|
||
var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g;
|
||
|
||
/** Used to ensure capturing order of template delimiters. */
|
||
var reNoMatch = /($^)/;
|
||
|
||
/** Used to match unescaped characters in compiled string literals. */
|
||
var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
|
||
|
||
/** Used to match words to create compound words. */
|
||
var reWords = (function() {
|
||
var upper = '[A-Z\\xc0-\\xd6\\xd8-\\xde]',
|
||
lower = '[a-z\\xdf-\\xf6\\xf8-\\xff]+';
|
||
|
||
return RegExp(upper + '+(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|[0-9]+', 'g');
|
||
}());
|
||
|
||
/** Used to assign default `context` object properties. */
|
||
var contextProps = [
|
||
'Array', 'ArrayBuffer', 'Date', 'Error', 'Float32Array', 'Float64Array',
|
||
'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number',
|
||
'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'isFinite',
|
||
'parseFloat', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array',
|
||
'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap'
|
||
];
|
||
|
||
/** Used to make template sourceURLs easier to identify. */
|
||
var templateCounter = -1;
|
||
|
||
/** Used to identify `toStringTag` values of typed arrays. */
|
||
var typedArrayTags = {};
|
||
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
|
||
typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
|
||
typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
|
||
typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
|
||
typedArrayTags[uint32Tag] = true;
|
||
typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
|
||
typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
|
||
typedArrayTags[dateTag] = typedArrayTags[errorTag] =
|
||
typedArrayTags[funcTag] = typedArrayTags[mapTag] =
|
||
typedArrayTags[numberTag] = typedArrayTags[objectTag] =
|
||
typedArrayTags[regexpTag] = typedArrayTags[setTag] =
|
||
typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
|
||
|
||
/** Used to identify `toStringTag` values supported by `_.clone`. */
|
||
var cloneableTags = {};
|
||
cloneableTags[argsTag] = cloneableTags[arrayTag] =
|
||
cloneableTags[arrayBufferTag] = cloneableTags[boolTag] =
|
||
cloneableTags[dateTag] = cloneableTags[float32Tag] =
|
||
cloneableTags[float64Tag] = cloneableTags[int8Tag] =
|
||
cloneableTags[int16Tag] = cloneableTags[int32Tag] =
|
||
cloneableTags[numberTag] = cloneableTags[objectTag] =
|
||
cloneableTags[regexpTag] = cloneableTags[stringTag] =
|
||
cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
|
||
cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
|
||
cloneableTags[errorTag] = cloneableTags[funcTag] =
|
||
cloneableTags[mapTag] = cloneableTags[setTag] =
|
||
cloneableTags[weakMapTag] = false;
|
||
|
||
/** Used to map latin-1 supplementary letters to basic latin letters. */
|
||
var deburredLetters = {
|
||
'\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
|
||
'\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
|
||
'\xc7': 'C', '\xe7': 'c',
|
||
'\xd0': 'D', '\xf0': 'd',
|
||
'\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
|
||
'\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
|
||
'\xcC': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
|
||
'\xeC': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i',
|
||
'\xd1': 'N', '\xf1': 'n',
|
||
'\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
|
||
'\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
|
||
'\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
|
||
'\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
|
||
'\xdd': 'Y', '\xfd': 'y', '\xff': 'y',
|
||
'\xc6': 'Ae', '\xe6': 'ae',
|
||
'\xde': 'Th', '\xfe': 'th',
|
||
'\xdf': 'ss'
|
||
};
|
||
|
||
/** Used to map characters to HTML entities. */
|
||
var htmlEscapes = {
|
||
'&': '&',
|
||
'<': '<',
|
||
'>': '>',
|
||
'"': '"',
|
||
"'": ''',
|
||
'`': '`'
|
||
};
|
||
|
||
/** Used to map HTML entities to characters. */
|
||
var htmlUnescapes = {
|
||
'&': '&',
|
||
'<': '<',
|
||
'>': '>',
|
||
'"': '"',
|
||
''': "'",
|
||
'`': '`'
|
||
};
|
||
|
||
/** Used to determine if values are of the language type `Object`. */
|
||
var objectTypes = {
|
||
'function': true,
|
||
'object': true
|
||
};
|
||
|
||
/** Used to escape characters for inclusion in compiled regexes. */
|
||
var regexpEscapes = {
|
||
'0': 'x30', '1': 'x31', '2': 'x32', '3': 'x33', '4': 'x34',
|
||
'5': 'x35', '6': 'x36', '7': 'x37', '8': 'x38', '9': 'x39',
|
||
'A': 'x41', 'B': 'x42', 'C': 'x43', 'D': 'x44', 'E': 'x45', 'F': 'x46',
|
||
'a': 'x61', 'b': 'x62', 'c': 'x63', 'd': 'x64', 'e': 'x65', 'f': 'x66',
|
||
'n': 'x6e', 'r': 'x72', 't': 'x74', 'u': 'x75', 'v': 'x76', 'x': 'x78'
|
||
};
|
||
|
||
/** Used to escape characters for inclusion in compiled string literals. */
|
||
var stringEscapes = {
|
||
'\\': '\\',
|
||
"'": "'",
|
||
'\n': 'n',
|
||
'\r': 'r',
|
||
'\u2028': 'u2028',
|
||
'\u2029': 'u2029'
|
||
};
|
||
|
||
/** Detect free variable `exports`. */
|
||
var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
|
||
|
||
/** Detect free variable `module`. */
|
||
var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
|
||
|
||
/** Detect free variable `global` from Node.js. */
|
||
var freeGlobal = freeExports && freeModule && typeof global == 'object' && global && global.Object && global;
|
||
|
||
/** Detect free variable `self`. */
|
||
var freeSelf = objectTypes[typeof self] && self && self.Object && self;
|
||
|
||
/** Detect free variable `window`. */
|
||
var freeWindow = objectTypes[typeof window] && window && window.Object && window;
|
||
|
||
/** Detect the popular CommonJS extension `module.exports`. */
|
||
var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
|
||
|
||
/**
|
||
* Used as a reference to the global object.
|
||
*
|
||
* The `this` value is used if it's the global object to avoid Greasemonkey's
|
||
* restricted `window` object, otherwise the `window` object is used.
|
||
*/
|
||
var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this;
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* The base implementation of `compareAscending` which compares values and
|
||
* sorts them in ascending order without guaranteeing a stable sort.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to compare.
|
||
* @param {*} other The other value to compare.
|
||
* @returns {number} Returns the sort order indicator for `value`.
|
||
*/
|
||
function baseCompareAscending(value, other) {
|
||
if (value !== other) {
|
||
var valIsNull = value === null,
|
||
valIsUndef = value === undefined,
|
||
valIsReflexive = value === value;
|
||
|
||
var othIsNull = other === null,
|
||
othIsUndef = other === undefined,
|
||
othIsReflexive = other === other;
|
||
|
||
if ((value > other && !othIsNull) || !valIsReflexive ||
|
||
(valIsNull && !othIsUndef && othIsReflexive) ||
|
||
(valIsUndef && othIsReflexive)) {
|
||
return 1;
|
||
}
|
||
if ((value < other && !valIsNull) || !othIsReflexive ||
|
||
(othIsNull && !valIsUndef && valIsReflexive) ||
|
||
(othIsUndef && valIsReflexive)) {
|
||
return -1;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.findIndex` and `_.findLastIndex` without
|
||
* support for callback shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to search.
|
||
* @param {Function} predicate The function invoked per iteration.
|
||
* @param {boolean} [fromRight] Specify iterating from right to left.
|
||
* @returns {number} Returns the index of the matched value, else `-1`.
|
||
*/
|
||
function baseFindIndex(array, predicate, fromRight) {
|
||
var length = array.length,
|
||
index = fromRight ? length : -1;
|
||
|
||
while ((fromRight ? index-- : ++index < length)) {
|
||
if (predicate(array[index], index, array)) {
|
||
return index;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.indexOf` without support for binary searches.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to search.
|
||
* @param {*} value The value to search for.
|
||
* @param {number} fromIndex The index to search from.
|
||
* @returns {number} Returns the index of the matched value, else `-1`.
|
||
*/
|
||
function baseIndexOf(array, value, fromIndex) {
|
||
if (value !== value) {
|
||
return indexOfNaN(array, fromIndex);
|
||
}
|
||
var index = fromIndex - 1,
|
||
length = array.length;
|
||
|
||
while (++index < length) {
|
||
if (array[index] === value) {
|
||
return index;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.isFunction` without support for environments
|
||
* with incorrect `typeof` results.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
|
||
*/
|
||
function baseIsFunction(value) {
|
||
// Avoid a Chakra JIT bug in compatibility modes of IE 11.
|
||
// See https://github.com/jashkenas/underscore/issues/1621 for more details.
|
||
return typeof value == 'function' || false;
|
||
}
|
||
|
||
/**
|
||
* Converts `value` to a string if it's not one. An empty string is returned
|
||
* for `null` or `undefined` values.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to process.
|
||
* @returns {string} Returns the string.
|
||
*/
|
||
function baseToString(value) {
|
||
return value == null ? '' : (value + '');
|
||
}
|
||
|
||
/**
|
||
* Used by `_.trim` and `_.trimLeft` to get the index of the first character
|
||
* of `string` that is not found in `chars`.
|
||
*
|
||
* @private
|
||
* @param {string} string The string to inspect.
|
||
* @param {string} chars The characters to find.
|
||
* @returns {number} Returns the index of the first character not found in `chars`.
|
||
*/
|
||
function charsLeftIndex(string, chars) {
|
||
var index = -1,
|
||
length = string.length;
|
||
|
||
while (++index < length && chars.indexOf(string.charAt(index)) > -1) {}
|
||
return index;
|
||
}
|
||
|
||
/**
|
||
* Used by `_.trim` and `_.trimRight` to get the index of the last character
|
||
* of `string` that is not found in `chars`.
|
||
*
|
||
* @private
|
||
* @param {string} string The string to inspect.
|
||
* @param {string} chars The characters to find.
|
||
* @returns {number} Returns the index of the last character not found in `chars`.
|
||
*/
|
||
function charsRightIndex(string, chars) {
|
||
var index = string.length;
|
||
|
||
while (index-- && chars.indexOf(string.charAt(index)) > -1) {}
|
||
return index;
|
||
}
|
||
|
||
/**
|
||
* Used by `_.sortBy` to compare transformed elements of a collection and stable
|
||
* sort them in ascending order.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to compare.
|
||
* @param {Object} other The other object to compare.
|
||
* @returns {number} Returns the sort order indicator for `object`.
|
||
*/
|
||
function compareAscending(object, other) {
|
||
return baseCompareAscending(object.criteria, other.criteria) || (object.index - other.index);
|
||
}
|
||
|
||
/**
|
||
* Used by `_.sortByOrder` to compare multiple properties of a value to another
|
||
* and stable sort them.
|
||
*
|
||
* If `orders` is unspecified, all valuess are sorted in ascending order. Otherwise,
|
||
* a value is sorted in ascending order if its corresponding order is "asc", and
|
||
* descending if "desc".
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to compare.
|
||
* @param {Object} other The other object to compare.
|
||
* @param {boolean[]} orders The order to sort by for each property.
|
||
* @returns {number} Returns the sort order indicator for `object`.
|
||
*/
|
||
function compareMultiple(object, other, orders) {
|
||
var index = -1,
|
||
objCriteria = object.criteria,
|
||
othCriteria = other.criteria,
|
||
length = objCriteria.length,
|
||
ordersLength = orders.length;
|
||
|
||
while (++index < length) {
|
||
var result = baseCompareAscending(objCriteria[index], othCriteria[index]);
|
||
if (result) {
|
||
if (index >= ordersLength) {
|
||
return result;
|
||
}
|
||
var order = orders[index];
|
||
return result * ((order === 'asc' || order === true) ? 1 : -1);
|
||
}
|
||
}
|
||
// Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
|
||
// that causes it, under certain circumstances, to provide the same value for
|
||
// `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
|
||
// for more details.
|
||
//
|
||
// This also ensures a stable sort in V8 and other engines.
|
||
// See https://code.google.com/p/v8/issues/detail?id=90 for more details.
|
||
return object.index - other.index;
|
||
}
|
||
|
||
/**
|
||
* Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters.
|
||
*
|
||
* @private
|
||
* @param {string} letter The matched letter to deburr.
|
||
* @returns {string} Returns the deburred letter.
|
||
*/
|
||
function deburrLetter(letter) {
|
||
return deburredLetters[letter];
|
||
}
|
||
|
||
/**
|
||
* Used by `_.escape` to convert characters to HTML entities.
|
||
*
|
||
* @private
|
||
* @param {string} chr The matched character to escape.
|
||
* @returns {string} Returns the escaped character.
|
||
*/
|
||
function escapeHtmlChar(chr) {
|
||
return htmlEscapes[chr];
|
||
}
|
||
|
||
/**
|
||
* Used by `_.escapeRegExp` to escape characters for inclusion in compiled regexes.
|
||
*
|
||
* @private
|
||
* @param {string} chr The matched character to escape.
|
||
* @param {string} leadingChar The capture group for a leading character.
|
||
* @param {string} whitespaceChar The capture group for a whitespace character.
|
||
* @returns {string} Returns the escaped character.
|
||
*/
|
||
function escapeRegExpChar(chr, leadingChar, whitespaceChar) {
|
||
if (leadingChar) {
|
||
chr = regexpEscapes[chr];
|
||
} else if (whitespaceChar) {
|
||
chr = stringEscapes[chr];
|
||
}
|
||
return '\\' + chr;
|
||
}
|
||
|
||
/**
|
||
* Used by `_.template` to escape characters for inclusion in compiled string literals.
|
||
*
|
||
* @private
|
||
* @param {string} chr The matched character to escape.
|
||
* @returns {string} Returns the escaped character.
|
||
*/
|
||
function escapeStringChar(chr) {
|
||
return '\\' + stringEscapes[chr];
|
||
}
|
||
|
||
/**
|
||
* Gets the index at which the first occurrence of `NaN` is found in `array`.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to search.
|
||
* @param {number} fromIndex The index to search from.
|
||
* @param {boolean} [fromRight] Specify iterating from right to left.
|
||
* @returns {number} Returns the index of the matched `NaN`, else `-1`.
|
||
*/
|
||
function indexOfNaN(array, fromIndex, fromRight) {
|
||
var length = array.length,
|
||
index = fromIndex + (fromRight ? 0 : -1);
|
||
|
||
while ((fromRight ? index-- : ++index < length)) {
|
||
var other = array[index];
|
||
if (other !== other) {
|
||
return index;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is object-like.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
|
||
*/
|
||
function isObjectLike(value) {
|
||
return !!value && typeof value == 'object';
|
||
}
|
||
|
||
/**
|
||
* Used by `trimmedLeftIndex` and `trimmedRightIndex` to determine if a
|
||
* character code is whitespace.
|
||
*
|
||
* @private
|
||
* @param {number} charCode The character code to inspect.
|
||
* @returns {boolean} Returns `true` if `charCode` is whitespace, else `false`.
|
||
*/
|
||
function isSpace(charCode) {
|
||
return ((charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160) || charCode == 5760 || charCode == 6158 ||
|
||
(charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279)));
|
||
}
|
||
|
||
/**
|
||
* Replaces all `placeholder` elements in `array` with an internal placeholder
|
||
* and returns an array of their indexes.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to modify.
|
||
* @param {*} placeholder The placeholder to replace.
|
||
* @returns {Array} Returns the new array of placeholder indexes.
|
||
*/
|
||
function replaceHolders(array, placeholder) {
|
||
var index = -1,
|
||
length = array.length,
|
||
resIndex = -1,
|
||
result = [];
|
||
|
||
while (++index < length) {
|
||
if (array[index] === placeholder) {
|
||
array[index] = PLACEHOLDER;
|
||
result[++resIndex] = index;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* An implementation of `_.uniq` optimized for sorted arrays without support
|
||
* for callback shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to inspect.
|
||
* @param {Function} [iteratee] The function invoked per iteration.
|
||
* @returns {Array} Returns the new duplicate-value-free array.
|
||
*/
|
||
function sortedUniq(array, iteratee) {
|
||
var seen,
|
||
index = -1,
|
||
length = array.length,
|
||
resIndex = -1,
|
||
result = [];
|
||
|
||
while (++index < length) {
|
||
var value = array[index],
|
||
computed = iteratee ? iteratee(value, index, array) : value;
|
||
|
||
if (!index || seen !== computed) {
|
||
seen = computed;
|
||
result[++resIndex] = value;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace
|
||
* character of `string`.
|
||
*
|
||
* @private
|
||
* @param {string} string The string to inspect.
|
||
* @returns {number} Returns the index of the first non-whitespace character.
|
||
*/
|
||
function trimmedLeftIndex(string) {
|
||
var index = -1,
|
||
length = string.length;
|
||
|
||
while (++index < length && isSpace(string.charCodeAt(index))) {}
|
||
return index;
|
||
}
|
||
|
||
/**
|
||
* Used by `_.trim` and `_.trimRight` to get the index of the last non-whitespace
|
||
* character of `string`.
|
||
*
|
||
* @private
|
||
* @param {string} string The string to inspect.
|
||
* @returns {number} Returns the index of the last non-whitespace character.
|
||
*/
|
||
function trimmedRightIndex(string) {
|
||
var index = string.length;
|
||
|
||
while (index-- && isSpace(string.charCodeAt(index))) {}
|
||
return index;
|
||
}
|
||
|
||
/**
|
||
* Used by `_.unescape` to convert HTML entities to characters.
|
||
*
|
||
* @private
|
||
* @param {string} chr The matched character to unescape.
|
||
* @returns {string} Returns the unescaped character.
|
||
*/
|
||
function unescapeHtmlChar(chr) {
|
||
return htmlUnescapes[chr];
|
||
}
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Create a new pristine `lodash` function using the given `context` object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Utility
|
||
* @param {Object} [context=root] The context object.
|
||
* @returns {Function} Returns a new `lodash` function.
|
||
* @example
|
||
*
|
||
* _.mixin({ 'foo': _.constant('foo') });
|
||
*
|
||
* var lodash = _.runInContext();
|
||
* lodash.mixin({ 'bar': lodash.constant('bar') });
|
||
*
|
||
* _.isFunction(_.foo);
|
||
* // => true
|
||
* _.isFunction(_.bar);
|
||
* // => false
|
||
*
|
||
* lodash.isFunction(lodash.foo);
|
||
* // => false
|
||
* lodash.isFunction(lodash.bar);
|
||
* // => true
|
||
*
|
||
* // using `context` to mock `Date#getTime` use in `_.now`
|
||
* var mock = _.runInContext({
|
||
* 'Date': function() {
|
||
* return { 'getTime': getTimeMock };
|
||
* }
|
||
* });
|
||
*
|
||
* // or creating a suped-up `defer` in Node.js
|
||
* var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
|
||
*/
|
||
function runInContext(context) {
|
||
// Avoid issues with some ES3 environments that attempt to use values, named
|
||
// after built-in constructors like `Object`, for the creation of literals.
|
||
// ES5 clears this up by stating that literals must use built-in constructors.
|
||
// See https://es5.github.io/#x11.1.5 for more details.
|
||
context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
|
||
|
||
/** Native constructor references. */
|
||
var Array = context.Array,
|
||
Date = context.Date,
|
||
Error = context.Error,
|
||
Function = context.Function,
|
||
Math = context.Math,
|
||
Number = context.Number,
|
||
Object = context.Object,
|
||
RegExp = context.RegExp,
|
||
String = context.String,
|
||
TypeError = context.TypeError;
|
||
|
||
/** Used for native method references. */
|
||
var arrayProto = Array.prototype,
|
||
objectProto = Object.prototype,
|
||
stringProto = String.prototype;
|
||
|
||
/** Used to resolve the decompiled source of functions. */
|
||
var fnToString = Function.prototype.toString;
|
||
|
||
/** Used to check objects for own properties. */
|
||
var hasOwnProperty = objectProto.hasOwnProperty;
|
||
|
||
/** Used to generate unique IDs. */
|
||
var idCounter = 0;
|
||
|
||
/**
|
||
* Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
|
||
* of values.
|
||
*/
|
||
var objToString = objectProto.toString;
|
||
|
||
/** Used to restore the original `_` reference in `_.noConflict`. */
|
||
var oldDash = root._;
|
||
|
||
/** Used to detect if a method is native. */
|
||
var reIsNative = RegExp('^' +
|
||
fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
|
||
.replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
|
||
);
|
||
|
||
/** Native method references. */
|
||
var ArrayBuffer = context.ArrayBuffer,
|
||
clearTimeout = context.clearTimeout,
|
||
parseFloat = context.parseFloat,
|
||
pow = Math.pow,
|
||
propertyIsEnumerable = objectProto.propertyIsEnumerable,
|
||
Set = getNative(context, 'Set'),
|
||
setTimeout = context.setTimeout,
|
||
splice = arrayProto.splice,
|
||
Uint8Array = context.Uint8Array,
|
||
WeakMap = getNative(context, 'WeakMap');
|
||
|
||
/* Native method references for those with the same name as other `lodash` methods. */
|
||
var nativeCeil = Math.ceil,
|
||
nativeCreate = getNative(Object, 'create'),
|
||
nativeFloor = Math.floor,
|
||
nativeIsArray = getNative(Array, 'isArray'),
|
||
nativeIsFinite = context.isFinite,
|
||
nativeKeys = getNative(Object, 'keys'),
|
||
nativeMax = Math.max,
|
||
nativeMin = Math.min,
|
||
nativeNow = getNative(Date, 'now'),
|
||
nativeParseInt = context.parseInt,
|
||
nativeRandom = Math.random;
|
||
|
||
/** Used as references for `-Infinity` and `Infinity`. */
|
||
var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY,
|
||
POSITIVE_INFINITY = Number.POSITIVE_INFINITY;
|
||
|
||
/** Used as references for the maximum length and index of an array. */
|
||
var MAX_ARRAY_LENGTH = 4294967295,
|
||
MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
|
||
HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
|
||
|
||
/**
|
||
* Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
|
||
* of an array-like value.
|
||
*/
|
||
var MAX_SAFE_INTEGER = 9007199254740991;
|
||
|
||
/** Used to store function metadata. */
|
||
var metaMap = WeakMap && new WeakMap;
|
||
|
||
/** Used to lookup unminified function names. */
|
||
var realNames = {};
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Creates a `lodash` object which wraps `value` to enable implicit chaining.
|
||
* Methods that operate on and return arrays, collections, and functions can
|
||
* be chained together. Methods that retrieve a single value or may return a
|
||
* primitive value will automatically end the chain returning the unwrapped
|
||
* value. Explicit chaining may be enabled using `_.chain`. The execution of
|
||
* chained methods is lazy, that is, execution is deferred until `_#value`
|
||
* is implicitly or explicitly called.
|
||
*
|
||
* Lazy evaluation allows several methods to support shortcut fusion. Shortcut
|
||
* fusion is an optimization strategy which merge iteratee calls; this can help
|
||
* to avoid the creation of intermediate data structures and greatly reduce the
|
||
* number of iteratee executions.
|
||
*
|
||
* Chaining is supported in custom builds as long as the `_#value` method is
|
||
* directly or indirectly included in the build.
|
||
*
|
||
* In addition to lodash methods, wrappers have `Array` and `String` methods.
|
||
*
|
||
* The wrapper `Array` methods are:
|
||
* `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`,
|
||
* `splice`, and `unshift`
|
||
*
|
||
* The wrapper `String` methods are:
|
||
* `replace` and `split`
|
||
*
|
||
* The wrapper methods that support shortcut fusion are:
|
||
* `compact`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`,
|
||
* `first`, `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`,
|
||
* `slice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `toArray`,
|
||
* and `where`
|
||
*
|
||
* The chainable wrapper methods are:
|
||
* `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`,
|
||
* `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`,
|
||
* `countBy`, `create`, `curry`, `debounce`, `defaults`, `defaultsDeep`,
|
||
* `defer`, `delay`, `difference`, `drop`, `dropRight`, `dropRightWhile`,
|
||
* `dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`,
|
||
* `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
|
||
* `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
|
||
* `invoke`, `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`,
|
||
* `matchesProperty`, `memoize`, `merge`, `method`, `methodOf`, `mixin`,
|
||
* `modArgs`, `negate`, `omit`, `once`, `pairs`, `partial`, `partialRight`,
|
||
* `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`,
|
||
* `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `restParam`,
|
||
* `reverse`, `set`, `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`,
|
||
* `sortByOrder`, `splice`, `spread`, `take`, `takeRight`, `takeRightWhile`,
|
||
* `takeWhile`, `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`,
|
||
* `transform`, `union`, `uniq`, `unshift`, `unzip`, `unzipWith`, `values`,
|
||
* `valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, `zipObject`, `zipWith`
|
||
*
|
||
* The wrapper methods that are **not** chainable by default are:
|
||
* `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clone`, `cloneDeep`,
|
||
* `deburr`, `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`,
|
||
* `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`,
|
||
* `floor`, `get`, `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`,
|
||
* `inRange`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
|
||
* `isEmpty`, `isEqual`, `isError`, `isFinite` `isFunction`, `isMatch`,
|
||
* `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`,
|
||
* `isRegExp`, `isString`, `isUndefined`, `isTypedArray`, `join`, `kebabCase`,
|
||
* `last`, `lastIndexOf`, `lt`, `lte`, `max`, `min`, `noConflict`, `noop`,
|
||
* `now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, `random`, `reduce`,
|
||
* `reduceRight`, `repeat`, `result`, `round`, `runInContext`, `shift`, `size`,
|
||
* `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, `startCase`,
|
||
* `startsWith`, `sum`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`,
|
||
* `unescape`, `uniqueId`, `value`, and `words`
|
||
*
|
||
* The wrapper method `sample` will return a wrapped value when `n` is provided,
|
||
* otherwise an unwrapped value is returned.
|
||
*
|
||
* @name _
|
||
* @constructor
|
||
* @category Chain
|
||
* @param {*} value The value to wrap in a `lodash` instance.
|
||
* @returns {Object} Returns the new `lodash` wrapper instance.
|
||
* @example
|
||
*
|
||
* var wrapped = _([1, 2, 3]);
|
||
*
|
||
* // returns an unwrapped value
|
||
* wrapped.reduce(function(total, n) {
|
||
* return total + n;
|
||
* });
|
||
* // => 6
|
||
*
|
||
* // returns a wrapped value
|
||
* var squares = wrapped.map(function(n) {
|
||
* return n * n;
|
||
* });
|
||
*
|
||
* _.isArray(squares);
|
||
* // => false
|
||
*
|
||
* _.isArray(squares.value());
|
||
* // => true
|
||
*/
|
||
function lodash(value) {
|
||
if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
|
||
if (value instanceof LodashWrapper) {
|
||
return value;
|
||
}
|
||
if (hasOwnProperty.call(value, '__chain__') && hasOwnProperty.call(value, '__wrapped__')) {
|
||
return wrapperClone(value);
|
||
}
|
||
}
|
||
return new LodashWrapper(value);
|
||
}
|
||
|
||
/**
|
||
* The function whose prototype all chaining wrappers inherit from.
|
||
*
|
||
* @private
|
||
*/
|
||
function baseLodash() {
|
||
// No operation performed.
|
||
}
|
||
|
||
/**
|
||
* The base constructor for creating `lodash` wrapper objects.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to wrap.
|
||
* @param {boolean} [chainAll] Enable chaining for all wrapper methods.
|
||
* @param {Array} [actions=[]] Actions to peform to resolve the unwrapped value.
|
||
*/
|
||
function LodashWrapper(value, chainAll, actions) {
|
||
this.__wrapped__ = value;
|
||
this.__actions__ = actions || [];
|
||
this.__chain__ = !!chainAll;
|
||
}
|
||
|
||
/**
|
||
* An object environment feature flags.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @type Object
|
||
*/
|
||
var support = lodash.support = {};
|
||
|
||
/**
|
||
* By default, the template delimiters used by lodash are like those in
|
||
* embedded Ruby (ERB). Change the following template settings to use
|
||
* alternative delimiters.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @type Object
|
||
*/
|
||
lodash.templateSettings = {
|
||
|
||
/**
|
||
* Used to detect `data` property values to be HTML-escaped.
|
||
*
|
||
* @memberOf _.templateSettings
|
||
* @type RegExp
|
||
*/
|
||
'escape': reEscape,
|
||
|
||
/**
|
||
* Used to detect code to be evaluated.
|
||
*
|
||
* @memberOf _.templateSettings
|
||
* @type RegExp
|
||
*/
|
||
'evaluate': reEvaluate,
|
||
|
||
/**
|
||
* Used to detect `data` property values to inject.
|
||
*
|
||
* @memberOf _.templateSettings
|
||
* @type RegExp
|
||
*/
|
||
'interpolate': reInterpolate,
|
||
|
||
/**
|
||
* Used to reference the data object in the template text.
|
||
*
|
||
* @memberOf _.templateSettings
|
||
* @type string
|
||
*/
|
||
'variable': '',
|
||
|
||
/**
|
||
* Used to import variables into the compiled template.
|
||
*
|
||
* @memberOf _.templateSettings
|
||
* @type Object
|
||
*/
|
||
'imports': {
|
||
|
||
/**
|
||
* A reference to the `lodash` function.
|
||
*
|
||
* @memberOf _.templateSettings.imports
|
||
* @type Function
|
||
*/
|
||
'_': lodash
|
||
}
|
||
};
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to wrap.
|
||
*/
|
||
function LazyWrapper(value) {
|
||
this.__wrapped__ = value;
|
||
this.__actions__ = [];
|
||
this.__dir__ = 1;
|
||
this.__filtered__ = false;
|
||
this.__iteratees__ = [];
|
||
this.__takeCount__ = POSITIVE_INFINITY;
|
||
this.__views__ = [];
|
||
}
|
||
|
||
/**
|
||
* Creates a clone of the lazy wrapper object.
|
||
*
|
||
* @private
|
||
* @name clone
|
||
* @memberOf LazyWrapper
|
||
* @returns {Object} Returns the cloned `LazyWrapper` object.
|
||
*/
|
||
function lazyClone() {
|
||
var result = new LazyWrapper(this.__wrapped__);
|
||
result.__actions__ = arrayCopy(this.__actions__);
|
||
result.__dir__ = this.__dir__;
|
||
result.__filtered__ = this.__filtered__;
|
||
result.__iteratees__ = arrayCopy(this.__iteratees__);
|
||
result.__takeCount__ = this.__takeCount__;
|
||
result.__views__ = arrayCopy(this.__views__);
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Reverses the direction of lazy iteration.
|
||
*
|
||
* @private
|
||
* @name reverse
|
||
* @memberOf LazyWrapper
|
||
* @returns {Object} Returns the new reversed `LazyWrapper` object.
|
||
*/
|
||
function lazyReverse() {
|
||
if (this.__filtered__) {
|
||
var result = new LazyWrapper(this);
|
||
result.__dir__ = -1;
|
||
result.__filtered__ = true;
|
||
} else {
|
||
result = this.clone();
|
||
result.__dir__ *= -1;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Extracts the unwrapped value from its lazy wrapper.
|
||
*
|
||
* @private
|
||
* @name value
|
||
* @memberOf LazyWrapper
|
||
* @returns {*} Returns the unwrapped value.
|
||
*/
|
||
function lazyValue() {
|
||
var array = this.__wrapped__.value(),
|
||
dir = this.__dir__,
|
||
isArr = isArray(array),
|
||
isRight = dir < 0,
|
||
arrLength = isArr ? array.length : 0,
|
||
view = getView(0, arrLength, this.__views__),
|
||
start = view.start,
|
||
end = view.end,
|
||
length = end - start,
|
||
index = isRight ? end : (start - 1),
|
||
iteratees = this.__iteratees__,
|
||
iterLength = iteratees.length,
|
||
resIndex = 0,
|
||
takeCount = nativeMin(length, this.__takeCount__);
|
||
|
||
if (!isArr || arrLength < LARGE_ARRAY_SIZE || (arrLength == length && takeCount == length)) {
|
||
return baseWrapperValue((isRight && isArr) ? array.reverse() : array, this.__actions__);
|
||
}
|
||
var result = [];
|
||
|
||
outer:
|
||
while (length-- && resIndex < takeCount) {
|
||
index += dir;
|
||
|
||
var iterIndex = -1,
|
||
value = array[index];
|
||
|
||
while (++iterIndex < iterLength) {
|
||
var data = iteratees[iterIndex],
|
||
iteratee = data.iteratee,
|
||
type = data.type,
|
||
computed = iteratee(value);
|
||
|
||
if (type == LAZY_MAP_FLAG) {
|
||
value = computed;
|
||
} else if (!computed) {
|
||
if (type == LAZY_FILTER_FLAG) {
|
||
continue outer;
|
||
} else {
|
||
break outer;
|
||
}
|
||
}
|
||
}
|
||
result[resIndex++] = value;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Creates a cache object to store key/value pairs.
|
||
*
|
||
* @private
|
||
* @static
|
||
* @name Cache
|
||
* @memberOf _.memoize
|
||
*/
|
||
function MapCache() {
|
||
this.__data__ = {};
|
||
}
|
||
|
||
/**
|
||
* Removes `key` and its value from the cache.
|
||
*
|
||
* @private
|
||
* @name delete
|
||
* @memberOf _.memoize.Cache
|
||
* @param {string} key The key of the value to remove.
|
||
* @returns {boolean} Returns `true` if the entry was removed successfully, else `false`.
|
||
*/
|
||
function mapDelete(key) {
|
||
return this.has(key) && delete this.__data__[key];
|
||
}
|
||
|
||
/**
|
||
* Gets the cached value for `key`.
|
||
*
|
||
* @private
|
||
* @name get
|
||
* @memberOf _.memoize.Cache
|
||
* @param {string} key The key of the value to get.
|
||
* @returns {*} Returns the cached value.
|
||
*/
|
||
function mapGet(key) {
|
||
return key == '__proto__' ? undefined : this.__data__[key];
|
||
}
|
||
|
||
/**
|
||
* Checks if a cached value for `key` exists.
|
||
*
|
||
* @private
|
||
* @name has
|
||
* @memberOf _.memoize.Cache
|
||
* @param {string} key The key of the entry to check.
|
||
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
|
||
*/
|
||
function mapHas(key) {
|
||
return key != '__proto__' && hasOwnProperty.call(this.__data__, key);
|
||
}
|
||
|
||
/**
|
||
* Sets `value` to `key` of the cache.
|
||
*
|
||
* @private
|
||
* @name set
|
||
* @memberOf _.memoize.Cache
|
||
* @param {string} key The key of the value to cache.
|
||
* @param {*} value The value to cache.
|
||
* @returns {Object} Returns the cache object.
|
||
*/
|
||
function mapSet(key, value) {
|
||
if (key != '__proto__') {
|
||
this.__data__[key] = value;
|
||
}
|
||
return this;
|
||
}
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
*
|
||
* Creates a cache object to store unique values.
|
||
*
|
||
* @private
|
||
* @param {Array} [values] The values to cache.
|
||
*/
|
||
function SetCache(values) {
|
||
var length = values ? values.length : 0;
|
||
|
||
this.data = { 'hash': nativeCreate(null), 'set': new Set };
|
||
while (length--) {
|
||
this.push(values[length]);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is in `cache` mimicking the return signature of
|
||
* `_.indexOf` by returning `0` if the value is found, else `-1`.
|
||
*
|
||
* @private
|
||
* @param {Object} cache The cache to search.
|
||
* @param {*} value The value to search for.
|
||
* @returns {number} Returns `0` if `value` is found, else `-1`.
|
||
*/
|
||
function cacheIndexOf(cache, value) {
|
||
var data = cache.data,
|
||
result = (typeof value == 'string' || isObject(value)) ? data.set.has(value) : data.hash[value];
|
||
|
||
return result ? 0 : -1;
|
||
}
|
||
|
||
/**
|
||
* Adds `value` to the cache.
|
||
*
|
||
* @private
|
||
* @name push
|
||
* @memberOf SetCache
|
||
* @param {*} value The value to cache.
|
||
*/
|
||
function cachePush(value) {
|
||
var data = this.data;
|
||
if (typeof value == 'string' || isObject(value)) {
|
||
data.set.add(value);
|
||
} else {
|
||
data.hash[value] = true;
|
||
}
|
||
}
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Creates a new array joining `array` with `other`.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to join.
|
||
* @param {Array} other The other array to join.
|
||
* @returns {Array} Returns the new concatenated array.
|
||
*/
|
||
function arrayConcat(array, other) {
|
||
var index = -1,
|
||
length = array.length,
|
||
othIndex = -1,
|
||
othLength = other.length,
|
||
result = Array(length + othLength);
|
||
|
||
while (++index < length) {
|
||
result[index] = array[index];
|
||
}
|
||
while (++othIndex < othLength) {
|
||
result[index++] = other[othIndex];
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Copies the values of `source` to `array`.
|
||
*
|
||
* @private
|
||
* @param {Array} source The array to copy values from.
|
||
* @param {Array} [array=[]] The array to copy values to.
|
||
* @returns {Array} Returns `array`.
|
||
*/
|
||
function arrayCopy(source, array) {
|
||
var index = -1,
|
||
length = source.length;
|
||
|
||
array || (array = Array(length));
|
||
while (++index < length) {
|
||
array[index] = source[index];
|
||
}
|
||
return array;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `_.forEach` for arrays without support for callback
|
||
* shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @returns {Array} Returns `array`.
|
||
*/
|
||
function arrayEach(array, iteratee) {
|
||
var index = -1,
|
||
length = array.length;
|
||
|
||
while (++index < length) {
|
||
if (iteratee(array[index], index, array) === false) {
|
||
break;
|
||
}
|
||
}
|
||
return array;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `_.forEachRight` for arrays without support for
|
||
* callback shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @returns {Array} Returns `array`.
|
||
*/
|
||
function arrayEachRight(array, iteratee) {
|
||
var length = array.length;
|
||
|
||
while (length--) {
|
||
if (iteratee(array[length], length, array) === false) {
|
||
break;
|
||
}
|
||
}
|
||
return array;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `_.every` for arrays without support for callback
|
||
* shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} predicate The function invoked per iteration.
|
||
* @returns {boolean} Returns `true` if all elements pass the predicate check,
|
||
* else `false`.
|
||
*/
|
||
function arrayEvery(array, predicate) {
|
||
var index = -1,
|
||
length = array.length;
|
||
|
||
while (++index < length) {
|
||
if (!predicate(array[index], index, array)) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `baseExtremum` for arrays which invokes `iteratee`
|
||
* with one argument: (value).
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @param {Function} comparator The function used to compare values.
|
||
* @param {*} exValue The initial extremum value.
|
||
* @returns {*} Returns the extremum value.
|
||
*/
|
||
function arrayExtremum(array, iteratee, comparator, exValue) {
|
||
var index = -1,
|
||
length = array.length,
|
||
computed = exValue,
|
||
result = computed;
|
||
|
||
while (++index < length) {
|
||
var value = array[index],
|
||
current = +iteratee(value);
|
||
|
||
if (comparator(current, computed)) {
|
||
computed = current;
|
||
result = value;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `_.filter` for arrays without support for callback
|
||
* shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} predicate The function invoked per iteration.
|
||
* @returns {Array} Returns the new filtered array.
|
||
*/
|
||
function arrayFilter(array, predicate) {
|
||
var index = -1,
|
||
length = array.length,
|
||
resIndex = -1,
|
||
result = [];
|
||
|
||
while (++index < length) {
|
||
var value = array[index];
|
||
if (predicate(value, index, array)) {
|
||
result[++resIndex] = value;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `_.map` for arrays without support for callback
|
||
* shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @returns {Array} Returns the new mapped array.
|
||
*/
|
||
function arrayMap(array, iteratee) {
|
||
var index = -1,
|
||
length = array.length,
|
||
result = Array(length);
|
||
|
||
while (++index < length) {
|
||
result[index] = iteratee(array[index], index, array);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Appends the elements of `values` to `array`.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to modify.
|
||
* @param {Array} values The values to append.
|
||
* @returns {Array} Returns `array`.
|
||
*/
|
||
function arrayPush(array, values) {
|
||
var index = -1,
|
||
length = values.length,
|
||
offset = array.length;
|
||
|
||
while (++index < length) {
|
||
array[offset + index] = values[index];
|
||
}
|
||
return array;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `_.reduce` for arrays without support for callback
|
||
* shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @param {*} [accumulator] The initial value.
|
||
* @param {boolean} [initFromArray] Specify using the first element of `array`
|
||
* as the initial value.
|
||
* @returns {*} Returns the accumulated value.
|
||
*/
|
||
function arrayReduce(array, iteratee, accumulator, initFromArray) {
|
||
var index = -1,
|
||
length = array.length;
|
||
|
||
if (initFromArray && length) {
|
||
accumulator = array[++index];
|
||
}
|
||
while (++index < length) {
|
||
accumulator = iteratee(accumulator, array[index], index, array);
|
||
}
|
||
return accumulator;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `_.reduceRight` for arrays without support for
|
||
* callback shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @param {*} [accumulator] The initial value.
|
||
* @param {boolean} [initFromArray] Specify using the last element of `array`
|
||
* as the initial value.
|
||
* @returns {*} Returns the accumulated value.
|
||
*/
|
||
function arrayReduceRight(array, iteratee, accumulator, initFromArray) {
|
||
var length = array.length;
|
||
if (initFromArray && length) {
|
||
accumulator = array[--length];
|
||
}
|
||
while (length--) {
|
||
accumulator = iteratee(accumulator, array[length], length, array);
|
||
}
|
||
return accumulator;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `_.some` for arrays without support for callback
|
||
* shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} predicate The function invoked per iteration.
|
||
* @returns {boolean} Returns `true` if any element passes the predicate check,
|
||
* else `false`.
|
||
*/
|
||
function arraySome(array, predicate) {
|
||
var index = -1,
|
||
length = array.length;
|
||
|
||
while (++index < length) {
|
||
if (predicate(array[index], index, array)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `_.sum` for arrays without support for callback
|
||
* shorthands and `this` binding..
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @returns {number} Returns the sum.
|
||
*/
|
||
function arraySum(array, iteratee) {
|
||
var length = array.length,
|
||
result = 0;
|
||
|
||
while (length--) {
|
||
result += +iteratee(array[length]) || 0;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Used by `_.defaults` to customize its `_.assign` use.
|
||
*
|
||
* @private
|
||
* @param {*} objectValue The destination object property value.
|
||
* @param {*} sourceValue The source object property value.
|
||
* @returns {*} Returns the value to assign to the destination object.
|
||
*/
|
||
function assignDefaults(objectValue, sourceValue) {
|
||
return objectValue === undefined ? sourceValue : objectValue;
|
||
}
|
||
|
||
/**
|
||
* Used by `_.template` to customize its `_.assign` use.
|
||
*
|
||
* **Note:** This function is like `assignDefaults` except that it ignores
|
||
* inherited property values when checking if a property is `undefined`.
|
||
*
|
||
* @private
|
||
* @param {*} objectValue The destination object property value.
|
||
* @param {*} sourceValue The source object property value.
|
||
* @param {string} key The key associated with the object and source values.
|
||
* @param {Object} object The destination object.
|
||
* @returns {*} Returns the value to assign to the destination object.
|
||
*/
|
||
function assignOwnDefaults(objectValue, sourceValue, key, object) {
|
||
return (objectValue === undefined || !hasOwnProperty.call(object, key))
|
||
? sourceValue
|
||
: objectValue;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `_.assign` for customizing assigned values without
|
||
* support for argument juggling, multiple sources, and `this` binding `customizer`
|
||
* functions.
|
||
*
|
||
* @private
|
||
* @param {Object} object The destination object.
|
||
* @param {Object} source The source object.
|
||
* @param {Function} customizer The function to customize assigned values.
|
||
* @returns {Object} Returns `object`.
|
||
*/
|
||
function assignWith(object, source, customizer) {
|
||
var index = -1,
|
||
props = keys(source),
|
||
length = props.length;
|
||
|
||
while (++index < length) {
|
||
var key = props[index],
|
||
value = object[key],
|
||
result = customizer(value, source[key], key, object, source);
|
||
|
||
if ((result === result ? (result !== value) : (value === value)) ||
|
||
(value === undefined && !(key in object))) {
|
||
object[key] = result;
|
||
}
|
||
}
|
||
return object;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.assign` without support for argument juggling,
|
||
* multiple sources, and `customizer` functions.
|
||
*
|
||
* @private
|
||
* @param {Object} object The destination object.
|
||
* @param {Object} source The source object.
|
||
* @returns {Object} Returns `object`.
|
||
*/
|
||
function baseAssign(object, source) {
|
||
return source == null
|
||
? object
|
||
: baseCopy(source, keys(source), object);
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.at` without support for string collections
|
||
* and individual key arguments.
|
||
*
|
||
* @private
|
||
* @param {Array|Object} collection The collection to iterate over.
|
||
* @param {number[]|string[]} props The property names or indexes of elements to pick.
|
||
* @returns {Array} Returns the new array of picked elements.
|
||
*/
|
||
function baseAt(collection, props) {
|
||
var index = -1,
|
||
isNil = collection == null,
|
||
isArr = !isNil && isArrayLike(collection),
|
||
length = isArr ? collection.length : 0,
|
||
propsLength = props.length,
|
||
result = Array(propsLength);
|
||
|
||
while(++index < propsLength) {
|
||
var key = props[index];
|
||
if (isArr) {
|
||
result[index] = isIndex(key, length) ? collection[key] : undefined;
|
||
} else {
|
||
result[index] = isNil ? undefined : collection[key];
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Copies properties of `source` to `object`.
|
||
*
|
||
* @private
|
||
* @param {Object} source The object to copy properties from.
|
||
* @param {Array} props The property names to copy.
|
||
* @param {Object} [object={}] The object to copy properties to.
|
||
* @returns {Object} Returns `object`.
|
||
*/
|
||
function baseCopy(source, props, object) {
|
||
object || (object = {});
|
||
|
||
var index = -1,
|
||
length = props.length;
|
||
|
||
while (++index < length) {
|
||
var key = props[index];
|
||
object[key] = source[key];
|
||
}
|
||
return object;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.callback` which supports specifying the
|
||
* number of arguments to provide to `func`.
|
||
*
|
||
* @private
|
||
* @param {*} [func=_.identity] The value to convert to a callback.
|
||
* @param {*} [thisArg] The `this` binding of `func`.
|
||
* @param {number} [argCount] The number of arguments to provide to `func`.
|
||
* @returns {Function} Returns the callback.
|
||
*/
|
||
function baseCallback(func, thisArg, argCount) {
|
||
var type = typeof func;
|
||
if (type == 'function') {
|
||
return thisArg === undefined
|
||
? func
|
||
: bindCallback(func, thisArg, argCount);
|
||
}
|
||
if (func == null) {
|
||
return identity;
|
||
}
|
||
if (type == 'object') {
|
||
return baseMatches(func);
|
||
}
|
||
return thisArg === undefined
|
||
? property(func)
|
||
: baseMatchesProperty(func, thisArg);
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.clone` without support for argument juggling
|
||
* and `this` binding `customizer` functions.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to clone.
|
||
* @param {boolean} [isDeep] Specify a deep clone.
|
||
* @param {Function} [customizer] The function to customize cloning values.
|
||
* @param {string} [key] The key of `value`.
|
||
* @param {Object} [object] The object `value` belongs to.
|
||
* @param {Array} [stackA=[]] Tracks traversed source objects.
|
||
* @param {Array} [stackB=[]] Associates clones with source counterparts.
|
||
* @returns {*} Returns the cloned value.
|
||
*/
|
||
function baseClone(value, isDeep, customizer, key, object, stackA, stackB) {
|
||
var result;
|
||
if (customizer) {
|
||
result = object ? customizer(value, key, object) : customizer(value);
|
||
}
|
||
if (result !== undefined) {
|
||
return result;
|
||
}
|
||
if (!isObject(value)) {
|
||
return value;
|
||
}
|
||
var isArr = isArray(value);
|
||
if (isArr) {
|
||
result = initCloneArray(value);
|
||
if (!isDeep) {
|
||
return arrayCopy(value, result);
|
||
}
|
||
} else {
|
||
var tag = objToString.call(value),
|
||
isFunc = tag == funcTag;
|
||
|
||
if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
|
||
result = initCloneObject(isFunc ? {} : value);
|
||
if (!isDeep) {
|
||
return baseAssign(result, value);
|
||
}
|
||
} else {
|
||
return cloneableTags[tag]
|
||
? initCloneByTag(value, tag, isDeep)
|
||
: (object ? value : {});
|
||
}
|
||
}
|
||
// Check for circular references and return its corresponding clone.
|
||
stackA || (stackA = []);
|
||
stackB || (stackB = []);
|
||
|
||
var length = stackA.length;
|
||
while (length--) {
|
||
if (stackA[length] == value) {
|
||
return stackB[length];
|
||
}
|
||
}
|
||
// Add the source value to the stack of traversed objects and associate it with its clone.
|
||
stackA.push(value);
|
||
stackB.push(result);
|
||
|
||
// Recursively populate clone (susceptible to call stack limits).
|
||
(isArr ? arrayEach : baseForOwn)(value, function(subValue, key) {
|
||
result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB);
|
||
});
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.create` without support for assigning
|
||
* properties to the created object.
|
||
*
|
||
* @private
|
||
* @param {Object} prototype The object to inherit from.
|
||
* @returns {Object} Returns the new object.
|
||
*/
|
||
var baseCreate = (function() {
|
||
function object() {}
|
||
return function(prototype) {
|
||
if (isObject(prototype)) {
|
||
object.prototype = prototype;
|
||
var result = new object;
|
||
object.prototype = undefined;
|
||
}
|
||
return result || {};
|
||
};
|
||
}());
|
||
|
||
/**
|
||
* The base implementation of `_.delay` and `_.defer` which accepts an index
|
||
* of where to slice the arguments to provide to `func`.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to delay.
|
||
* @param {number} wait The number of milliseconds to delay invocation.
|
||
* @param {Object} args The arguments provide to `func`.
|
||
* @returns {number} Returns the timer id.
|
||
*/
|
||
function baseDelay(func, wait, args) {
|
||
if (typeof func != 'function') {
|
||
throw new TypeError(FUNC_ERROR_TEXT);
|
||
}
|
||
return setTimeout(function() { func.apply(undefined, args); }, wait);
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.difference` which accepts a single array
|
||
* of values to exclude.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to inspect.
|
||
* @param {Array} values The values to exclude.
|
||
* @returns {Array} Returns the new array of filtered values.
|
||
*/
|
||
function baseDifference(array, values) {
|
||
var length = array ? array.length : 0,
|
||
result = [];
|
||
|
||
if (!length) {
|
||
return result;
|
||
}
|
||
var index = -1,
|
||
indexOf = getIndexOf(),
|
||
isCommon = indexOf == baseIndexOf,
|
||
cache = (isCommon && values.length >= LARGE_ARRAY_SIZE) ? createCache(values) : null,
|
||
valuesLength = values.length;
|
||
|
||
if (cache) {
|
||
indexOf = cacheIndexOf;
|
||
isCommon = false;
|
||
values = cache;
|
||
}
|
||
outer:
|
||
while (++index < length) {
|
||
var value = array[index];
|
||
|
||
if (isCommon && value === value) {
|
||
var valuesIndex = valuesLength;
|
||
while (valuesIndex--) {
|
||
if (values[valuesIndex] === value) {
|
||
continue outer;
|
||
}
|
||
}
|
||
result.push(value);
|
||
}
|
||
else if (indexOf(values, value, 0) < 0) {
|
||
result.push(value);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.forEach` without support for callback
|
||
* shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @returns {Array|Object|string} Returns `collection`.
|
||
*/
|
||
var baseEach = createBaseEach(baseForOwn);
|
||
|
||
/**
|
||
* The base implementation of `_.forEachRight` without support for callback
|
||
* shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @returns {Array|Object|string} Returns `collection`.
|
||
*/
|
||
var baseEachRight = createBaseEach(baseForOwnRight, true);
|
||
|
||
/**
|
||
* The base implementation of `_.every` without support for callback
|
||
* shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function} predicate The function invoked per iteration.
|
||
* @returns {boolean} Returns `true` if all elements pass the predicate check,
|
||
* else `false`
|
||
*/
|
||
function baseEvery(collection, predicate) {
|
||
var result = true;
|
||
baseEach(collection, function(value, index, collection) {
|
||
result = !!predicate(value, index, collection);
|
||
return result;
|
||
});
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Gets the extremum value of `collection` invoking `iteratee` for each value
|
||
* in `collection` to generate the criterion by which the value is ranked.
|
||
* The `iteratee` is invoked with three arguments: (value, index|key, collection).
|
||
*
|
||
* @private
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @param {Function} comparator The function used to compare values.
|
||
* @param {*} exValue The initial extremum value.
|
||
* @returns {*} Returns the extremum value.
|
||
*/
|
||
function baseExtremum(collection, iteratee, comparator, exValue) {
|
||
var computed = exValue,
|
||
result = computed;
|
||
|
||
baseEach(collection, function(value, index, collection) {
|
||
var current = +iteratee(value, index, collection);
|
||
if (comparator(current, computed) || (current === exValue && current === result)) {
|
||
computed = current;
|
||
result = value;
|
||
}
|
||
});
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.fill` without an iteratee call guard.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to fill.
|
||
* @param {*} value The value to fill `array` with.
|
||
* @param {number} [start=0] The start position.
|
||
* @param {number} [end=array.length] The end position.
|
||
* @returns {Array} Returns `array`.
|
||
*/
|
||
function baseFill(array, value, start, end) {
|
||
var length = array.length;
|
||
|
||
start = start == null ? 0 : (+start || 0);
|
||
if (start < 0) {
|
||
start = -start > length ? 0 : (length + start);
|
||
}
|
||
end = (end === undefined || end > length) ? length : (+end || 0);
|
||
if (end < 0) {
|
||
end += length;
|
||
}
|
||
length = start > end ? 0 : (end >>> 0);
|
||
start >>>= 0;
|
||
|
||
while (start < length) {
|
||
array[start++] = value;
|
||
}
|
||
return array;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.filter` without support for callback
|
||
* shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function} predicate The function invoked per iteration.
|
||
* @returns {Array} Returns the new filtered array.
|
||
*/
|
||
function baseFilter(collection, predicate) {
|
||
var result = [];
|
||
baseEach(collection, function(value, index, collection) {
|
||
if (predicate(value, index, collection)) {
|
||
result.push(value);
|
||
}
|
||
});
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`,
|
||
* without support for callback shorthands and `this` binding, which iterates
|
||
* over `collection` using the provided `eachFunc`.
|
||
*
|
||
* @private
|
||
* @param {Array|Object|string} collection The collection to search.
|
||
* @param {Function} predicate The function invoked per iteration.
|
||
* @param {Function} eachFunc The function to iterate over `collection`.
|
||
* @param {boolean} [retKey] Specify returning the key of the found element
|
||
* instead of the element itself.
|
||
* @returns {*} Returns the found element or its key, else `undefined`.
|
||
*/
|
||
function baseFind(collection, predicate, eachFunc, retKey) {
|
||
var result;
|
||
eachFunc(collection, function(value, key, collection) {
|
||
if (predicate(value, key, collection)) {
|
||
result = retKey ? key : value;
|
||
return false;
|
||
}
|
||
});
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.flatten` with added support for restricting
|
||
* flattening and specifying the start index.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to flatten.
|
||
* @param {boolean} [isDeep] Specify a deep flatten.
|
||
* @param {boolean} [isStrict] Restrict flattening to arrays-like objects.
|
||
* @param {Array} [result=[]] The initial result value.
|
||
* @returns {Array} Returns the new flattened array.
|
||
*/
|
||
function baseFlatten(array, isDeep, isStrict, result) {
|
||
result || (result = []);
|
||
|
||
var index = -1,
|
||
length = array.length;
|
||
|
||
while (++index < length) {
|
||
var value = array[index];
|
||
if (isObjectLike(value) && isArrayLike(value) &&
|
||
(isStrict || isArray(value) || isArguments(value))) {
|
||
if (isDeep) {
|
||
// Recursively flatten arrays (susceptible to call stack limits).
|
||
baseFlatten(value, isDeep, isStrict, result);
|
||
} else {
|
||
arrayPush(result, value);
|
||
}
|
||
} else if (!isStrict) {
|
||
result[result.length] = value;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `baseForIn` and `baseForOwn` which iterates
|
||
* over `object` properties returned by `keysFunc` invoking `iteratee` for
|
||
* each property. Iteratee functions may exit iteration early by explicitly
|
||
* returning `false`.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @param {Function} keysFunc The function to get the keys of `object`.
|
||
* @returns {Object} Returns `object`.
|
||
*/
|
||
var baseFor = createBaseFor();
|
||
|
||
/**
|
||
* This function is like `baseFor` except that it iterates over properties
|
||
* in the opposite order.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @param {Function} keysFunc The function to get the keys of `object`.
|
||
* @returns {Object} Returns `object`.
|
||
*/
|
||
var baseForRight = createBaseFor(true);
|
||
|
||
/**
|
||
* The base implementation of `_.forIn` without support for callback
|
||
* shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @returns {Object} Returns `object`.
|
||
*/
|
||
function baseForIn(object, iteratee) {
|
||
return baseFor(object, iteratee, keysIn);
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.forOwn` without support for callback
|
||
* shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @returns {Object} Returns `object`.
|
||
*/
|
||
function baseForOwn(object, iteratee) {
|
||
return baseFor(object, iteratee, keys);
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.forOwnRight` without support for callback
|
||
* shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @returns {Object} Returns `object`.
|
||
*/
|
||
function baseForOwnRight(object, iteratee) {
|
||
return baseForRight(object, iteratee, keys);
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.functions` which creates an array of
|
||
* `object` function property names filtered from those provided.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to inspect.
|
||
* @param {Array} props The property names to filter.
|
||
* @returns {Array} Returns the new array of filtered property names.
|
||
*/
|
||
function baseFunctions(object, props) {
|
||
var index = -1,
|
||
length = props.length,
|
||
resIndex = -1,
|
||
result = [];
|
||
|
||
while (++index < length) {
|
||
var key = props[index];
|
||
if (isFunction(object[key])) {
|
||
result[++resIndex] = key;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `get` without support for string paths
|
||
* and default values.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to query.
|
||
* @param {Array} path The path of the property to get.
|
||
* @param {string} [pathKey] The key representation of path.
|
||
* @returns {*} Returns the resolved value.
|
||
*/
|
||
function baseGet(object, path, pathKey) {
|
||
if (object == null) {
|
||
return;
|
||
}
|
||
if (pathKey !== undefined && pathKey in toObject(object)) {
|
||
path = [pathKey];
|
||
}
|
||
var index = 0,
|
||
length = path.length;
|
||
|
||
while (object != null && index < length) {
|
||
object = object[path[index++]];
|
||
}
|
||
return (index && index == length) ? object : undefined;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.isEqual` without support for `this` binding
|
||
* `customizer` functions.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to compare.
|
||
* @param {*} other The other value to compare.
|
||
* @param {Function} [customizer] The function to customize comparing values.
|
||
* @param {boolean} [isLoose] Specify performing partial comparisons.
|
||
* @param {Array} [stackA] Tracks traversed `value` objects.
|
||
* @param {Array} [stackB] Tracks traversed `other` objects.
|
||
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
|
||
*/
|
||
function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) {
|
||
if (value === other) {
|
||
return true;
|
||
}
|
||
if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
|
||
return value !== value && other !== other;
|
||
}
|
||
return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB);
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `baseIsEqual` for arrays and objects which performs
|
||
* deep comparisons and tracks traversed objects enabling objects with circular
|
||
* references to be compared.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to compare.
|
||
* @param {Object} other The other object to compare.
|
||
* @param {Function} equalFunc The function to determine equivalents of values.
|
||
* @param {Function} [customizer] The function to customize comparing objects.
|
||
* @param {boolean} [isLoose] Specify performing partial comparisons.
|
||
* @param {Array} [stackA=[]] Tracks traversed `value` objects.
|
||
* @param {Array} [stackB=[]] Tracks traversed `other` objects.
|
||
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
|
||
*/
|
||
function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
|
||
var objIsArr = isArray(object),
|
||
othIsArr = isArray(other),
|
||
objTag = arrayTag,
|
||
othTag = arrayTag;
|
||
|
||
if (!objIsArr) {
|
||
objTag = objToString.call(object);
|
||
if (objTag == argsTag) {
|
||
objTag = objectTag;
|
||
} else if (objTag != objectTag) {
|
||
objIsArr = isTypedArray(object);
|
||
}
|
||
}
|
||
if (!othIsArr) {
|
||
othTag = objToString.call(other);
|
||
if (othTag == argsTag) {
|
||
othTag = objectTag;
|
||
} else if (othTag != objectTag) {
|
||
othIsArr = isTypedArray(other);
|
||
}
|
||
}
|
||
var objIsObj = objTag == objectTag,
|
||
othIsObj = othTag == objectTag,
|
||
isSameTag = objTag == othTag;
|
||
|
||
if (isSameTag && !(objIsArr || objIsObj)) {
|
||
return equalByTag(object, other, objTag);
|
||
}
|
||
if (!isLoose) {
|
||
var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
|
||
othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
|
||
|
||
if (objIsWrapped || othIsWrapped) {
|
||
return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB);
|
||
}
|
||
}
|
||
if (!isSameTag) {
|
||
return false;
|
||
}
|
||
// Assume cyclic values are equal.
|
||
// For more information on detecting circular references see https://es5.github.io/#JO.
|
||
stackA || (stackA = []);
|
||
stackB || (stackB = []);
|
||
|
||
var length = stackA.length;
|
||
while (length--) {
|
||
if (stackA[length] == object) {
|
||
return stackB[length] == other;
|
||
}
|
||
}
|
||
// Add `object` and `other` to the stack of traversed objects.
|
||
stackA.push(object);
|
||
stackB.push(other);
|
||
|
||
var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB);
|
||
|
||
stackA.pop();
|
||
stackB.pop();
|
||
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.isMatch` without support for callback
|
||
* shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to inspect.
|
||
* @param {Array} matchData The propery names, values, and compare flags to match.
|
||
* @param {Function} [customizer] The function to customize comparing objects.
|
||
* @returns {boolean} Returns `true` if `object` is a match, else `false`.
|
||
*/
|
||
function baseIsMatch(object, matchData, customizer) {
|
||
var index = matchData.length,
|
||
length = index,
|
||
noCustomizer = !customizer;
|
||
|
||
if (object == null) {
|
||
return !length;
|
||
}
|
||
object = toObject(object);
|
||
while (index--) {
|
||
var data = matchData[index];
|
||
if ((noCustomizer && data[2])
|
||
? data[1] !== object[data[0]]
|
||
: !(data[0] in object)
|
||
) {
|
||
return false;
|
||
}
|
||
}
|
||
while (++index < length) {
|
||
data = matchData[index];
|
||
var key = data[0],
|
||
objValue = object[key],
|
||
srcValue = data[1];
|
||
|
||
if (noCustomizer && data[2]) {
|
||
if (objValue === undefined && !(key in object)) {
|
||
return false;
|
||
}
|
||
} else {
|
||
var result = customizer ? customizer(objValue, srcValue, key) : undefined;
|
||
if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) {
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.map` without support for callback shorthands
|
||
* and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @returns {Array} Returns the new mapped array.
|
||
*/
|
||
function baseMap(collection, iteratee) {
|
||
var index = -1,
|
||
result = isArrayLike(collection) ? Array(collection.length) : [];
|
||
|
||
baseEach(collection, function(value, key, collection) {
|
||
result[++index] = iteratee(value, key, collection);
|
||
});
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.matches` which does not clone `source`.
|
||
*
|
||
* @private
|
||
* @param {Object} source The object of property values to match.
|
||
* @returns {Function} Returns the new function.
|
||
*/
|
||
function baseMatches(source) {
|
||
var matchData = getMatchData(source);
|
||
if (matchData.length == 1 && matchData[0][2]) {
|
||
var key = matchData[0][0],
|
||
value = matchData[0][1];
|
||
|
||
return function(object) {
|
||
if (object == null) {
|
||
return false;
|
||
}
|
||
return object[key] === value && (value !== undefined || (key in toObject(object)));
|
||
};
|
||
}
|
||
return function(object) {
|
||
return baseIsMatch(object, matchData);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.matchesProperty` which does not clone `srcValue`.
|
||
*
|
||
* @private
|
||
* @param {string} path The path of the property to get.
|
||
* @param {*} srcValue The value to compare.
|
||
* @returns {Function} Returns the new function.
|
||
*/
|
||
function baseMatchesProperty(path, srcValue) {
|
||
var isArr = isArray(path),
|
||
isCommon = isKey(path) && isStrictComparable(srcValue),
|
||
pathKey = (path + '');
|
||
|
||
path = toPath(path);
|
||
return function(object) {
|
||
if (object == null) {
|
||
return false;
|
||
}
|
||
var key = pathKey;
|
||
object = toObject(object);
|
||
if ((isArr || !isCommon) && !(key in object)) {
|
||
object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
|
||
if (object == null) {
|
||
return false;
|
||
}
|
||
key = last(path);
|
||
object = toObject(object);
|
||
}
|
||
return object[key] === srcValue
|
||
? (srcValue !== undefined || (key in object))
|
||
: baseIsEqual(srcValue, object[key], undefined, true);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.merge` without support for argument juggling,
|
||
* multiple sources, and `this` binding `customizer` functions.
|
||
*
|
||
* @private
|
||
* @param {Object} object The destination object.
|
||
* @param {Object} source The source object.
|
||
* @param {Function} [customizer] The function to customize merged values.
|
||
* @param {Array} [stackA=[]] Tracks traversed source objects.
|
||
* @param {Array} [stackB=[]] Associates values with source counterparts.
|
||
* @returns {Object} Returns `object`.
|
||
*/
|
||
function baseMerge(object, source, customizer, stackA, stackB) {
|
||
if (!isObject(object)) {
|
||
return object;
|
||
}
|
||
var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)),
|
||
props = isSrcArr ? undefined : keys(source);
|
||
|
||
arrayEach(props || source, function(srcValue, key) {
|
||
if (props) {
|
||
key = srcValue;
|
||
srcValue = source[key];
|
||
}
|
||
if (isObjectLike(srcValue)) {
|
||
stackA || (stackA = []);
|
||
stackB || (stackB = []);
|
||
baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB);
|
||
}
|
||
else {
|
||
var value = object[key],
|
||
result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
|
||
isCommon = result === undefined;
|
||
|
||
if (isCommon) {
|
||
result = srcValue;
|
||
}
|
||
if ((result !== undefined || (isSrcArr && !(key in object))) &&
|
||
(isCommon || (result === result ? (result !== value) : (value === value)))) {
|
||
object[key] = result;
|
||
}
|
||
}
|
||
});
|
||
return object;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `baseMerge` for arrays and objects which performs
|
||
* deep merges and tracks traversed objects enabling objects with circular
|
||
* references to be merged.
|
||
*
|
||
* @private
|
||
* @param {Object} object The destination object.
|
||
* @param {Object} source The source object.
|
||
* @param {string} key The key of the value to merge.
|
||
* @param {Function} mergeFunc The function to merge values.
|
||
* @param {Function} [customizer] The function to customize merged values.
|
||
* @param {Array} [stackA=[]] Tracks traversed source objects.
|
||
* @param {Array} [stackB=[]] Associates values with source counterparts.
|
||
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
|
||
*/
|
||
function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) {
|
||
var length = stackA.length,
|
||
srcValue = source[key];
|
||
|
||
while (length--) {
|
||
if (stackA[length] == srcValue) {
|
||
object[key] = stackB[length];
|
||
return;
|
||
}
|
||
}
|
||
var value = object[key],
|
||
result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
|
||
isCommon = result === undefined;
|
||
|
||
if (isCommon) {
|
||
result = srcValue;
|
||
if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) {
|
||
result = isArray(value)
|
||
? value
|
||
: (isArrayLike(value) ? arrayCopy(value) : []);
|
||
}
|
||
else if (isPlainObject(srcValue) || isArguments(srcValue)) {
|
||
result = isArguments(value)
|
||
? toPlainObject(value)
|
||
: (isPlainObject(value) ? value : {});
|
||
}
|
||
else {
|
||
isCommon = false;
|
||
}
|
||
}
|
||
// Add the source value to the stack of traversed objects and associate
|
||
// it with its merged value.
|
||
stackA.push(srcValue);
|
||
stackB.push(result);
|
||
|
||
if (isCommon) {
|
||
// Recursively merge objects and arrays (susceptible to call stack limits).
|
||
object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB);
|
||
} else if (result === result ? (result !== value) : (value === value)) {
|
||
object[key] = result;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.property` without support for deep paths.
|
||
*
|
||
* @private
|
||
* @param {string} key The key of the property to get.
|
||
* @returns {Function} Returns the new function.
|
||
*/
|
||
function baseProperty(key) {
|
||
return function(object) {
|
||
return object == null ? undefined : object[key];
|
||
};
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `baseProperty` which supports deep paths.
|
||
*
|
||
* @private
|
||
* @param {Array|string} path The path of the property to get.
|
||
* @returns {Function} Returns the new function.
|
||
*/
|
||
function basePropertyDeep(path) {
|
||
var pathKey = (path + '');
|
||
path = toPath(path);
|
||
return function(object) {
|
||
return baseGet(object, path, pathKey);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.pullAt` without support for individual
|
||
* index arguments and capturing the removed elements.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to modify.
|
||
* @param {number[]} indexes The indexes of elements to remove.
|
||
* @returns {Array} Returns `array`.
|
||
*/
|
||
function basePullAt(array, indexes) {
|
||
var length = array ? indexes.length : 0;
|
||
while (length--) {
|
||
var index = indexes[length];
|
||
if (index != previous && isIndex(index)) {
|
||
var previous = index;
|
||
splice.call(array, index, 1);
|
||
}
|
||
}
|
||
return array;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.random` without support for argument juggling
|
||
* and returning floating-point numbers.
|
||
*
|
||
* @private
|
||
* @param {number} min The minimum possible value.
|
||
* @param {number} max The maximum possible value.
|
||
* @returns {number} Returns the random number.
|
||
*/
|
||
function baseRandom(min, max) {
|
||
return min + nativeFloor(nativeRandom() * (max - min + 1));
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.reduce` and `_.reduceRight` without support
|
||
* for callback shorthands and `this` binding, which iterates over `collection`
|
||
* using the provided `eachFunc`.
|
||
*
|
||
* @private
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @param {*} accumulator The initial value.
|
||
* @param {boolean} initFromCollection Specify using the first or last element
|
||
* of `collection` as the initial value.
|
||
* @param {Function} eachFunc The function to iterate over `collection`.
|
||
* @returns {*} Returns the accumulated value.
|
||
*/
|
||
function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) {
|
||
eachFunc(collection, function(value, index, collection) {
|
||
accumulator = initFromCollection
|
||
? (initFromCollection = false, value)
|
||
: iteratee(accumulator, value, index, collection);
|
||
});
|
||
return accumulator;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `setData` without support for hot loop detection.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to associate metadata with.
|
||
* @param {*} data The metadata.
|
||
* @returns {Function} Returns `func`.
|
||
*/
|
||
var baseSetData = !metaMap ? identity : function(func, data) {
|
||
metaMap.set(func, data);
|
||
return func;
|
||
};
|
||
|
||
/**
|
||
* The base implementation of `_.slice` without an iteratee call guard.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to slice.
|
||
* @param {number} [start=0] The start position.
|
||
* @param {number} [end=array.length] The end position.
|
||
* @returns {Array} Returns the slice of `array`.
|
||
*/
|
||
function baseSlice(array, start, end) {
|
||
var index = -1,
|
||
length = array.length;
|
||
|
||
start = start == null ? 0 : (+start || 0);
|
||
if (start < 0) {
|
||
start = -start > length ? 0 : (length + start);
|
||
}
|
||
end = (end === undefined || end > length) ? length : (+end || 0);
|
||
if (end < 0) {
|
||
end += length;
|
||
}
|
||
length = start > end ? 0 : ((end - start) >>> 0);
|
||
start >>>= 0;
|
||
|
||
var result = Array(length);
|
||
while (++index < length) {
|
||
result[index] = array[index + start];
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.some` without support for callback shorthands
|
||
* and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function} predicate The function invoked per iteration.
|
||
* @returns {boolean} Returns `true` if any element passes the predicate check,
|
||
* else `false`.
|
||
*/
|
||
function baseSome(collection, predicate) {
|
||
var result;
|
||
|
||
baseEach(collection, function(value, index, collection) {
|
||
result = predicate(value, index, collection);
|
||
return !result;
|
||
});
|
||
return !!result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.sortBy` which uses `comparer` to define
|
||
* the sort order of `array` and replaces criteria objects with their
|
||
* corresponding values.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to sort.
|
||
* @param {Function} comparer The function to define sort order.
|
||
* @returns {Array} Returns `array`.
|
||
*/
|
||
function baseSortBy(array, comparer) {
|
||
var length = array.length;
|
||
|
||
array.sort(comparer);
|
||
while (length--) {
|
||
array[length] = array[length].value;
|
||
}
|
||
return array;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.sortByOrder` without param guards.
|
||
*
|
||
* @private
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
|
||
* @param {boolean[]} orders The sort orders of `iteratees`.
|
||
* @returns {Array} Returns the new sorted array.
|
||
*/
|
||
function baseSortByOrder(collection, iteratees, orders) {
|
||
var callback = getCallback(),
|
||
index = -1;
|
||
|
||
iteratees = arrayMap(iteratees, function(iteratee) { return callback(iteratee); });
|
||
|
||
var result = baseMap(collection, function(value) {
|
||
var criteria = arrayMap(iteratees, function(iteratee) { return iteratee(value); });
|
||
return { 'criteria': criteria, 'index': ++index, 'value': value };
|
||
});
|
||
|
||
return baseSortBy(result, function(object, other) {
|
||
return compareMultiple(object, other, orders);
|
||
});
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.sum` without support for callback shorthands
|
||
* and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @returns {number} Returns the sum.
|
||
*/
|
||
function baseSum(collection, iteratee) {
|
||
var result = 0;
|
||
baseEach(collection, function(value, index, collection) {
|
||
result += +iteratee(value, index, collection) || 0;
|
||
});
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.uniq` without support for callback shorthands
|
||
* and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to inspect.
|
||
* @param {Function} [iteratee] The function invoked per iteration.
|
||
* @returns {Array} Returns the new duplicate-value-free array.
|
||
*/
|
||
function baseUniq(array, iteratee) {
|
||
var index = -1,
|
||
indexOf = getIndexOf(),
|
||
length = array.length,
|
||
isCommon = indexOf == baseIndexOf,
|
||
isLarge = isCommon && length >= LARGE_ARRAY_SIZE,
|
||
seen = isLarge ? createCache() : null,
|
||
result = [];
|
||
|
||
if (seen) {
|
||
indexOf = cacheIndexOf;
|
||
isCommon = false;
|
||
} else {
|
||
isLarge = false;
|
||
seen = iteratee ? [] : result;
|
||
}
|
||
outer:
|
||
while (++index < length) {
|
||
var value = array[index],
|
||
computed = iteratee ? iteratee(value, index, array) : value;
|
||
|
||
if (isCommon && value === value) {
|
||
var seenIndex = seen.length;
|
||
while (seenIndex--) {
|
||
if (seen[seenIndex] === computed) {
|
||
continue outer;
|
||
}
|
||
}
|
||
if (iteratee) {
|
||
seen.push(computed);
|
||
}
|
||
result.push(value);
|
||
}
|
||
else if (indexOf(seen, computed, 0) < 0) {
|
||
if (iteratee || isLarge) {
|
||
seen.push(computed);
|
||
}
|
||
result.push(value);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.values` and `_.valuesIn` which creates an
|
||
* array of `object` property values corresponding to the property names
|
||
* of `props`.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to query.
|
||
* @param {Array} props The property names to get values for.
|
||
* @returns {Object} Returns the array of property values.
|
||
*/
|
||
function baseValues(object, props) {
|
||
var index = -1,
|
||
length = props.length,
|
||
result = Array(length);
|
||
|
||
while (++index < length) {
|
||
result[index] = object[props[index]];
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.dropRightWhile`, `_.dropWhile`, `_.takeRightWhile`,
|
||
* and `_.takeWhile` without support for callback shorthands and `this` binding.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to query.
|
||
* @param {Function} predicate The function invoked per iteration.
|
||
* @param {boolean} [isDrop] Specify dropping elements instead of taking them.
|
||
* @param {boolean} [fromRight] Specify iterating from right to left.
|
||
* @returns {Array} Returns the slice of `array`.
|
||
*/
|
||
function baseWhile(array, predicate, isDrop, fromRight) {
|
||
var length = array.length,
|
||
index = fromRight ? length : -1;
|
||
|
||
while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {}
|
||
return isDrop
|
||
? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
|
||
: baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `wrapperValue` which returns the result of
|
||
* performing a sequence of actions on the unwrapped `value`, where each
|
||
* successive action is supplied the return value of the previous.
|
||
*
|
||
* @private
|
||
* @param {*} value The unwrapped value.
|
||
* @param {Array} actions Actions to peform to resolve the unwrapped value.
|
||
* @returns {*} Returns the resolved value.
|
||
*/
|
||
function baseWrapperValue(value, actions) {
|
||
var result = value;
|
||
if (result instanceof LazyWrapper) {
|
||
result = result.value();
|
||
}
|
||
var index = -1,
|
||
length = actions.length;
|
||
|
||
while (++index < length) {
|
||
var action = actions[index];
|
||
result = action.func.apply(action.thisArg, arrayPush([result], action.args));
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Performs a binary search of `array` to determine the index at which `value`
|
||
* should be inserted into `array` in order to maintain its sort order.
|
||
*
|
||
* @private
|
||
* @param {Array} array The sorted array to inspect.
|
||
* @param {*} value The value to evaluate.
|
||
* @param {boolean} [retHighest] Specify returning the highest qualified index.
|
||
* @returns {number} Returns the index at which `value` should be inserted
|
||
* into `array`.
|
||
*/
|
||
function binaryIndex(array, value, retHighest) {
|
||
var low = 0,
|
||
high = array ? array.length : low;
|
||
|
||
if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
|
||
while (low < high) {
|
||
var mid = (low + high) >>> 1,
|
||
computed = array[mid];
|
||
|
||
if ((retHighest ? (computed <= value) : (computed < value)) && computed !== null) {
|
||
low = mid + 1;
|
||
} else {
|
||
high = mid;
|
||
}
|
||
}
|
||
return high;
|
||
}
|
||
return binaryIndexBy(array, value, identity, retHighest);
|
||
}
|
||
|
||
/**
|
||
* This function is like `binaryIndex` except that it invokes `iteratee` for
|
||
* `value` and each element of `array` to compute their sort ranking. The
|
||
* iteratee is invoked with one argument; (value).
|
||
*
|
||
* @private
|
||
* @param {Array} array The sorted array to inspect.
|
||
* @param {*} value The value to evaluate.
|
||
* @param {Function} iteratee The function invoked per iteration.
|
||
* @param {boolean} [retHighest] Specify returning the highest qualified index.
|
||
* @returns {number} Returns the index at which `value` should be inserted
|
||
* into `array`.
|
||
*/
|
||
function binaryIndexBy(array, value, iteratee, retHighest) {
|
||
value = iteratee(value);
|
||
|
||
var low = 0,
|
||
high = array ? array.length : 0,
|
||
valIsNaN = value !== value,
|
||
valIsNull = value === null,
|
||
valIsUndef = value === undefined;
|
||
|
||
while (low < high) {
|
||
var mid = nativeFloor((low + high) / 2),
|
||
computed = iteratee(array[mid]),
|
||
isDef = computed !== undefined,
|
||
isReflexive = computed === computed;
|
||
|
||
if (valIsNaN) {
|
||
var setLow = isReflexive || retHighest;
|
||
} else if (valIsNull) {
|
||
setLow = isReflexive && isDef && (retHighest || computed != null);
|
||
} else if (valIsUndef) {
|
||
setLow = isReflexive && (retHighest || isDef);
|
||
} else if (computed == null) {
|
||
setLow = false;
|
||
} else {
|
||
setLow = retHighest ? (computed <= value) : (computed < value);
|
||
}
|
||
if (setLow) {
|
||
low = mid + 1;
|
||
} else {
|
||
high = mid;
|
||
}
|
||
}
|
||
return nativeMin(high, MAX_ARRAY_INDEX);
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `baseCallback` which only supports `this` binding
|
||
* and specifying the number of arguments to provide to `func`.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to bind.
|
||
* @param {*} thisArg The `this` binding of `func`.
|
||
* @param {number} [argCount] The number of arguments to provide to `func`.
|
||
* @returns {Function} Returns the callback.
|
||
*/
|
||
function bindCallback(func, thisArg, argCount) {
|
||
if (typeof func != 'function') {
|
||
return identity;
|
||
}
|
||
if (thisArg === undefined) {
|
||
return func;
|
||
}
|
||
switch (argCount) {
|
||
case 1: return function(value) {
|
||
return func.call(thisArg, value);
|
||
};
|
||
case 3: return function(value, index, collection) {
|
||
return func.call(thisArg, value, index, collection);
|
||
};
|
||
case 4: return function(accumulator, value, index, collection) {
|
||
return func.call(thisArg, accumulator, value, index, collection);
|
||
};
|
||
case 5: return function(value, other, key, object, source) {
|
||
return func.call(thisArg, value, other, key, object, source);
|
||
};
|
||
}
|
||
return function() {
|
||
return func.apply(thisArg, arguments);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a clone of the given array buffer.
|
||
*
|
||
* @private
|
||
* @param {ArrayBuffer} buffer The array buffer to clone.
|
||
* @returns {ArrayBuffer} Returns the cloned array buffer.
|
||
*/
|
||
function bufferClone(buffer) {
|
||
var result = new ArrayBuffer(buffer.byteLength),
|
||
view = new Uint8Array(result);
|
||
|
||
view.set(new Uint8Array(buffer));
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Creates an array that is the composition of partially applied arguments,
|
||
* placeholders, and provided arguments into a single array of arguments.
|
||
*
|
||
* @private
|
||
* @param {Array|Object} args The provided arguments.
|
||
* @param {Array} partials The arguments to prepend to those provided.
|
||
* @param {Array} holders The `partials` placeholder indexes.
|
||
* @returns {Array} Returns the new array of composed arguments.
|
||
*/
|
||
function composeArgs(args, partials, holders) {
|
||
var holdersLength = holders.length,
|
||
argsIndex = -1,
|
||
argsLength = nativeMax(args.length - holdersLength, 0),
|
||
leftIndex = -1,
|
||
leftLength = partials.length,
|
||
result = Array(leftLength + argsLength);
|
||
|
||
while (++leftIndex < leftLength) {
|
||
result[leftIndex] = partials[leftIndex];
|
||
}
|
||
while (++argsIndex < holdersLength) {
|
||
result[holders[argsIndex]] = args[argsIndex];
|
||
}
|
||
while (argsLength--) {
|
||
result[leftIndex++] = args[argsIndex++];
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* This function is like `composeArgs` except that the arguments composition
|
||
* is tailored for `_.partialRight`.
|
||
*
|
||
* @private
|
||
* @param {Array|Object} args The provided arguments.
|
||
* @param {Array} partials The arguments to append to those provided.
|
||
* @param {Array} holders The `partials` placeholder indexes.
|
||
* @returns {Array} Returns the new array of composed arguments.
|
||
*/
|
||
function composeArgsRight(args, partials, holders) {
|
||
var holdersIndex = -1,
|
||
holdersLength = holders.length,
|
||
argsIndex = -1,
|
||
argsLength = nativeMax(args.length - holdersLength, 0),
|
||
rightIndex = -1,
|
||
rightLength = partials.length,
|
||
result = Array(argsLength + rightLength);
|
||
|
||
while (++argsIndex < argsLength) {
|
||
result[argsIndex] = args[argsIndex];
|
||
}
|
||
var offset = argsIndex;
|
||
while (++rightIndex < rightLength) {
|
||
result[offset + rightIndex] = partials[rightIndex];
|
||
}
|
||
while (++holdersIndex < holdersLength) {
|
||
result[offset + holders[holdersIndex]] = args[argsIndex++];
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Creates a `_.countBy`, `_.groupBy`, `_.indexBy`, or `_.partition` function.
|
||
*
|
||
* @private
|
||
* @param {Function} setter The function to set keys and values of the accumulator object.
|
||
* @param {Function} [initializer] The function to initialize the accumulator object.
|
||
* @returns {Function} Returns the new aggregator function.
|
||
*/
|
||
function createAggregator(setter, initializer) {
|
||
return function(collection, iteratee, thisArg) {
|
||
var result = initializer ? initializer() : {};
|
||
iteratee = getCallback(iteratee, thisArg, 3);
|
||
|
||
if (isArray(collection)) {
|
||
var index = -1,
|
||
length = collection.length;
|
||
|
||
while (++index < length) {
|
||
var value = collection[index];
|
||
setter(result, value, iteratee(value, index, collection), collection);
|
||
}
|
||
} else {
|
||
baseEach(collection, function(value, key, collection) {
|
||
setter(result, value, iteratee(value, key, collection), collection);
|
||
});
|
||
}
|
||
return result;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a `_.assign`, `_.defaults`, or `_.merge` function.
|
||
*
|
||
* @private
|
||
* @param {Function} assigner The function to assign values.
|
||
* @returns {Function} Returns the new assigner function.
|
||
*/
|
||
function createAssigner(assigner) {
|
||
return restParam(function(object, sources) {
|
||
var index = -1,
|
||
length = object == null ? 0 : sources.length,
|
||
customizer = length > 2 ? sources[length - 2] : undefined,
|
||
guard = length > 2 ? sources[2] : undefined,
|
||
thisArg = length > 1 ? sources[length - 1] : undefined;
|
||
|
||
if (typeof customizer == 'function') {
|
||
customizer = bindCallback(customizer, thisArg, 5);
|
||
length -= 2;
|
||
} else {
|
||
customizer = typeof thisArg == 'function' ? thisArg : undefined;
|
||
length -= (customizer ? 1 : 0);
|
||
}
|
||
if (guard && isIterateeCall(sources[0], sources[1], guard)) {
|
||
customizer = length < 3 ? undefined : customizer;
|
||
length = 1;
|
||
}
|
||
while (++index < length) {
|
||
var source = sources[index];
|
||
if (source) {
|
||
assigner(object, source, customizer);
|
||
}
|
||
}
|
||
return object;
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Creates a `baseEach` or `baseEachRight` function.
|
||
*
|
||
* @private
|
||
* @param {Function} eachFunc The function to iterate over a collection.
|
||
* @param {boolean} [fromRight] Specify iterating from right to left.
|
||
* @returns {Function} Returns the new base function.
|
||
*/
|
||
function createBaseEach(eachFunc, fromRight) {
|
||
return function(collection, iteratee) {
|
||
var length = collection ? getLength(collection) : 0;
|
||
if (!isLength(length)) {
|
||
return eachFunc(collection, iteratee);
|
||
}
|
||
var index = fromRight ? length : -1,
|
||
iterable = toObject(collection);
|
||
|
||
while ((fromRight ? index-- : ++index < length)) {
|
||
if (iteratee(iterable[index], index, iterable) === false) {
|
||
break;
|
||
}
|
||
}
|
||
return collection;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a base function for `_.forIn` or `_.forInRight`.
|
||
*
|
||
* @private
|
||
* @param {boolean} [fromRight] Specify iterating from right to left.
|
||
* @returns {Function} Returns the new base function.
|
||
*/
|
||
function createBaseFor(fromRight) {
|
||
return function(object, iteratee, keysFunc) {
|
||
var iterable = toObject(object),
|
||
props = keysFunc(object),
|
||
length = props.length,
|
||
index = fromRight ? length : -1;
|
||
|
||
while ((fromRight ? index-- : ++index < length)) {
|
||
var key = props[index];
|
||
if (iteratee(iterable[key], key, iterable) === false) {
|
||
break;
|
||
}
|
||
}
|
||
return object;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a function that wraps `func` and invokes it with the `this`
|
||
* binding of `thisArg`.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to bind.
|
||
* @param {*} [thisArg] The `this` binding of `func`.
|
||
* @returns {Function} Returns the new bound function.
|
||
*/
|
||
function createBindWrapper(func, thisArg) {
|
||
var Ctor = createCtorWrapper(func);
|
||
|
||
function wrapper() {
|
||
var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
|
||
return fn.apply(thisArg, arguments);
|
||
}
|
||
return wrapper;
|
||
}
|
||
|
||
/**
|
||
* Creates a `Set` cache object to optimize linear searches of large arrays.
|
||
*
|
||
* @private
|
||
* @param {Array} [values] The values to cache.
|
||
* @returns {null|Object} Returns the new cache object if `Set` is supported, else `null`.
|
||
*/
|
||
function createCache(values) {
|
||
return (nativeCreate && Set) ? new SetCache(values) : null;
|
||
}
|
||
|
||
/**
|
||
* Creates a function that produces compound words out of the words in a
|
||
* given string.
|
||
*
|
||
* @private
|
||
* @param {Function} callback The function to combine each word.
|
||
* @returns {Function} Returns the new compounder function.
|
||
*/
|
||
function createCompounder(callback) {
|
||
return function(string) {
|
||
var index = -1,
|
||
array = words(deburr(string)),
|
||
length = array.length,
|
||
result = '';
|
||
|
||
while (++index < length) {
|
||
result = callback(result, array[index], index);
|
||
}
|
||
return result;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a function that produces an instance of `Ctor` regardless of
|
||
* whether it was invoked as part of a `new` expression or by `call` or `apply`.
|
||
*
|
||
* @private
|
||
* @param {Function} Ctor The constructor to wrap.
|
||
* @returns {Function} Returns the new wrapped function.
|
||
*/
|
||
function createCtorWrapper(Ctor) {
|
||
return function() {
|
||
// Use a `switch` statement to work with class constructors.
|
||
// See http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
|
||
// for more details.
|
||
var args = arguments;
|
||
switch (args.length) {
|
||
case 0: return new Ctor;
|
||
case 1: return new Ctor(args[0]);
|
||
case 2: return new Ctor(args[0], args[1]);
|
||
case 3: return new Ctor(args[0], args[1], args[2]);
|
||
case 4: return new Ctor(args[0], args[1], args[2], args[3]);
|
||
case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
|
||
case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
|
||
case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
|
||
}
|
||
var thisBinding = baseCreate(Ctor.prototype),
|
||
result = Ctor.apply(thisBinding, args);
|
||
|
||
// Mimic the constructor's `return` behavior.
|
||
// See https://es5.github.io/#x13.2.2 for more details.
|
||
return isObject(result) ? result : thisBinding;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a `_.curry` or `_.curryRight` function.
|
||
*
|
||
* @private
|
||
* @param {boolean} flag The curry bit flag.
|
||
* @returns {Function} Returns the new curry function.
|
||
*/
|
||
function createCurry(flag) {
|
||
function curryFunc(func, arity, guard) {
|
||
if (guard && isIterateeCall(func, arity, guard)) {
|
||
arity = undefined;
|
||
}
|
||
var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity);
|
||
result.placeholder = curryFunc.placeholder;
|
||
return result;
|
||
}
|
||
return curryFunc;
|
||
}
|
||
|
||
/**
|
||
* Creates a `_.defaults` or `_.defaultsDeep` function.
|
||
*
|
||
* @private
|
||
* @param {Function} assigner The function to assign values.
|
||
* @param {Function} customizer The function to customize assigned values.
|
||
* @returns {Function} Returns the new defaults function.
|
||
*/
|
||
function createDefaults(assigner, customizer) {
|
||
return restParam(function(args) {
|
||
var object = args[0];
|
||
if (object == null) {
|
||
return object;
|
||
}
|
||
args.push(customizer);
|
||
return assigner.apply(undefined, args);
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Creates a `_.max` or `_.min` function.
|
||
*
|
||
* @private
|
||
* @param {Function} comparator The function used to compare values.
|
||
* @param {*} exValue The initial extremum value.
|
||
* @returns {Function} Returns the new extremum function.
|
||
*/
|
||
function createExtremum(comparator, exValue) {
|
||
return function(collection, iteratee, thisArg) {
|
||
if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {
|
||
iteratee = undefined;
|
||
}
|
||
iteratee = getCallback(iteratee, thisArg, 3);
|
||
if (iteratee.length == 1) {
|
||
collection = isArray(collection) ? collection : toIterable(collection);
|
||
var result = arrayExtremum(collection, iteratee, comparator, exValue);
|
||
if (!(collection.length && result === exValue)) {
|
||
return result;
|
||
}
|
||
}
|
||
return baseExtremum(collection, iteratee, comparator, exValue);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a `_.find` or `_.findLast` function.
|
||
*
|
||
* @private
|
||
* @param {Function} eachFunc The function to iterate over a collection.
|
||
* @param {boolean} [fromRight] Specify iterating from right to left.
|
||
* @returns {Function} Returns the new find function.
|
||
*/
|
||
function createFind(eachFunc, fromRight) {
|
||
return function(collection, predicate, thisArg) {
|
||
predicate = getCallback(predicate, thisArg, 3);
|
||
if (isArray(collection)) {
|
||
var index = baseFindIndex(collection, predicate, fromRight);
|
||
return index > -1 ? collection[index] : undefined;
|
||
}
|
||
return baseFind(collection, predicate, eachFunc);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a `_.findIndex` or `_.findLastIndex` function.
|
||
*
|
||
* @private
|
||
* @param {boolean} [fromRight] Specify iterating from right to left.
|
||
* @returns {Function} Returns the new find function.
|
||
*/
|
||
function createFindIndex(fromRight) {
|
||
return function(array, predicate, thisArg) {
|
||
if (!(array && array.length)) {
|
||
return -1;
|
||
}
|
||
predicate = getCallback(predicate, thisArg, 3);
|
||
return baseFindIndex(array, predicate, fromRight);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a `_.findKey` or `_.findLastKey` function.
|
||
*
|
||
* @private
|
||
* @param {Function} objectFunc The function to iterate over an object.
|
||
* @returns {Function} Returns the new find function.
|
||
*/
|
||
function createFindKey(objectFunc) {
|
||
return function(object, predicate, thisArg) {
|
||
predicate = getCallback(predicate, thisArg, 3);
|
||
return baseFind(object, predicate, objectFunc, true);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a `_.flow` or `_.flowRight` function.
|
||
*
|
||
* @private
|
||
* @param {boolean} [fromRight] Specify iterating from right to left.
|
||
* @returns {Function} Returns the new flow function.
|
||
*/
|
||
function createFlow(fromRight) {
|
||
return function() {
|
||
var wrapper,
|
||
length = arguments.length,
|
||
index = fromRight ? length : -1,
|
||
leftIndex = 0,
|
||
funcs = Array(length);
|
||
|
||
while ((fromRight ? index-- : ++index < length)) {
|
||
var func = funcs[leftIndex++] = arguments[index];
|
||
if (typeof func != 'function') {
|
||
throw new TypeError(FUNC_ERROR_TEXT);
|
||
}
|
||
if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == 'wrapper') {
|
||
wrapper = new LodashWrapper([], true);
|
||
}
|
||
}
|
||
index = wrapper ? -1 : length;
|
||
while (++index < length) {
|
||
func = funcs[index];
|
||
|
||
var funcName = getFuncName(func),
|
||
data = funcName == 'wrapper' ? getData(func) : undefined;
|
||
|
||
if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) {
|
||
wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
|
||
} else {
|
||
wrapper = (func.length == 1 && isLaziable(func)) ? wrapper[funcName]() : wrapper.thru(func);
|
||
}
|
||
}
|
||
return function() {
|
||
var args = arguments,
|
||
value = args[0];
|
||
|
||
if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) {
|
||
return wrapper.plant(value).value();
|
||
}
|
||
var index = 0,
|
||
result = length ? funcs[index].apply(this, args) : value;
|
||
|
||
while (++index < length) {
|
||
result = funcs[index].call(this, result);
|
||
}
|
||
return result;
|
||
};
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a function for `_.forEach` or `_.forEachRight`.
|
||
*
|
||
* @private
|
||
* @param {Function} arrayFunc The function to iterate over an array.
|
||
* @param {Function} eachFunc The function to iterate over a collection.
|
||
* @returns {Function} Returns the new each function.
|
||
*/
|
||
function createForEach(arrayFunc, eachFunc) {
|
||
return function(collection, iteratee, thisArg) {
|
||
return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))
|
||
? arrayFunc(collection, iteratee)
|
||
: eachFunc(collection, bindCallback(iteratee, thisArg, 3));
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a function for `_.forIn` or `_.forInRight`.
|
||
*
|
||
* @private
|
||
* @param {Function} objectFunc The function to iterate over an object.
|
||
* @returns {Function} Returns the new each function.
|
||
*/
|
||
function createForIn(objectFunc) {
|
||
return function(object, iteratee, thisArg) {
|
||
if (typeof iteratee != 'function' || thisArg !== undefined) {
|
||
iteratee = bindCallback(iteratee, thisArg, 3);
|
||
}
|
||
return objectFunc(object, iteratee, keysIn);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a function for `_.forOwn` or `_.forOwnRight`.
|
||
*
|
||
* @private
|
||
* @param {Function} objectFunc The function to iterate over an object.
|
||
* @returns {Function} Returns the new each function.
|
||
*/
|
||
function createForOwn(objectFunc) {
|
||
return function(object, iteratee, thisArg) {
|
||
if (typeof iteratee != 'function' || thisArg !== undefined) {
|
||
iteratee = bindCallback(iteratee, thisArg, 3);
|
||
}
|
||
return objectFunc(object, iteratee);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a function for `_.mapKeys` or `_.mapValues`.
|
||
*
|
||
* @private
|
||
* @param {boolean} [isMapKeys] Specify mapping keys instead of values.
|
||
* @returns {Function} Returns the new map function.
|
||
*/
|
||
function createObjectMapper(isMapKeys) {
|
||
return function(object, iteratee, thisArg) {
|
||
var result = {};
|
||
iteratee = getCallback(iteratee, thisArg, 3);
|
||
|
||
baseForOwn(object, function(value, key, object) {
|
||
var mapped = iteratee(value, key, object);
|
||
key = isMapKeys ? mapped : key;
|
||
value = isMapKeys ? value : mapped;
|
||
result[key] = value;
|
||
});
|
||
return result;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a function for `_.padLeft` or `_.padRight`.
|
||
*
|
||
* @private
|
||
* @param {boolean} [fromRight] Specify padding from the right.
|
||
* @returns {Function} Returns the new pad function.
|
||
*/
|
||
function createPadDir(fromRight) {
|
||
return function(string, length, chars) {
|
||
string = baseToString(string);
|
||
return (fromRight ? string : '') + createPadding(string, length, chars) + (fromRight ? '' : string);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a `_.partial` or `_.partialRight` function.
|
||
*
|
||
* @private
|
||
* @param {boolean} flag The partial bit flag.
|
||
* @returns {Function} Returns the new partial function.
|
||
*/
|
||
function createPartial(flag) {
|
||
var partialFunc = restParam(function(func, partials) {
|
||
var holders = replaceHolders(partials, partialFunc.placeholder);
|
||
return createWrapper(func, flag, undefined, partials, holders);
|
||
});
|
||
return partialFunc;
|
||
}
|
||
|
||
/**
|
||
* Creates a function for `_.reduce` or `_.reduceRight`.
|
||
*
|
||
* @private
|
||
* @param {Function} arrayFunc The function to iterate over an array.
|
||
* @param {Function} eachFunc The function to iterate over a collection.
|
||
* @returns {Function} Returns the new each function.
|
||
*/
|
||
function createReduce(arrayFunc, eachFunc) {
|
||
return function(collection, iteratee, accumulator, thisArg) {
|
||
var initFromArray = arguments.length < 3;
|
||
return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))
|
||
? arrayFunc(collection, iteratee, accumulator, initFromArray)
|
||
: baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a function that wraps `func` and invokes it with optional `this`
|
||
* binding of, partial application, and currying.
|
||
*
|
||
* @private
|
||
* @param {Function|string} func The function or method name to reference.
|
||
* @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.
|
||
* @param {*} [thisArg] The `this` binding of `func`.
|
||
* @param {Array} [partials] The arguments to prepend to those provided to the new function.
|
||
* @param {Array} [holders] The `partials` placeholder indexes.
|
||
* @param {Array} [partialsRight] The arguments to append to those provided to the new function.
|
||
* @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
|
||
* @param {Array} [argPos] The argument positions of the new function.
|
||
* @param {number} [ary] The arity cap of `func`.
|
||
* @param {number} [arity] The arity of `func`.
|
||
* @returns {Function} Returns the new wrapped function.
|
||
*/
|
||
function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
|
||
var isAry = bitmask & ARY_FLAG,
|
||
isBind = bitmask & BIND_FLAG,
|
||
isBindKey = bitmask & BIND_KEY_FLAG,
|
||
isCurry = bitmask & CURRY_FLAG,
|
||
isCurryBound = bitmask & CURRY_BOUND_FLAG,
|
||
isCurryRight = bitmask & CURRY_RIGHT_FLAG,
|
||
Ctor = isBindKey ? undefined : createCtorWrapper(func);
|
||
|
||
function wrapper() {
|
||
// Avoid `arguments` object use disqualifying optimizations by
|
||
// converting it to an array before providing it to other functions.
|
||
var length = arguments.length,
|
||
index = length,
|
||
args = Array(length);
|
||
|
||
while (index--) {
|
||
args[index] = arguments[index];
|
||
}
|
||
if (partials) {
|
||
args = composeArgs(args, partials, holders);
|
||
}
|
||
if (partialsRight) {
|
||
args = composeArgsRight(args, partialsRight, holdersRight);
|
||
}
|
||
if (isCurry || isCurryRight) {
|
||
var placeholder = wrapper.placeholder,
|
||
argsHolders = replaceHolders(args, placeholder);
|
||
|
||
length -= argsHolders.length;
|
||
if (length < arity) {
|
||
var newArgPos = argPos ? arrayCopy(argPos) : undefined,
|
||
newArity = nativeMax(arity - length, 0),
|
||
newsHolders = isCurry ? argsHolders : undefined,
|
||
newHoldersRight = isCurry ? undefined : argsHolders,
|
||
newPartials = isCurry ? args : undefined,
|
||
newPartialsRight = isCurry ? undefined : args;
|
||
|
||
bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG);
|
||
bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG);
|
||
|
||
if (!isCurryBound) {
|
||
bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
|
||
}
|
||
var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity],
|
||
result = createHybridWrapper.apply(undefined, newData);
|
||
|
||
if (isLaziable(func)) {
|
||
setData(result, newData);
|
||
}
|
||
result.placeholder = placeholder;
|
||
return result;
|
||
}
|
||
}
|
||
var thisBinding = isBind ? thisArg : this,
|
||
fn = isBindKey ? thisBinding[func] : func;
|
||
|
||
if (argPos) {
|
||
args = reorder(args, argPos);
|
||
}
|
||
if (isAry && ary < args.length) {
|
||
args.length = ary;
|
||
}
|
||
if (this && this !== root && this instanceof wrapper) {
|
||
fn = Ctor || createCtorWrapper(func);
|
||
}
|
||
return fn.apply(thisBinding, args);
|
||
}
|
||
return wrapper;
|
||
}
|
||
|
||
/**
|
||
* Creates the padding required for `string` based on the given `length`.
|
||
* The `chars` string is truncated if the number of characters exceeds `length`.
|
||
*
|
||
* @private
|
||
* @param {string} string The string to create padding for.
|
||
* @param {number} [length=0] The padding length.
|
||
* @param {string} [chars=' '] The string used as padding.
|
||
* @returns {string} Returns the pad for `string`.
|
||
*/
|
||
function createPadding(string, length, chars) {
|
||
var strLength = string.length;
|
||
length = +length;
|
||
|
||
if (strLength >= length || !nativeIsFinite(length)) {
|
||
return '';
|
||
}
|
||
var padLength = length - strLength;
|
||
chars = chars == null ? ' ' : (chars + '');
|
||
return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength);
|
||
}
|
||
|
||
/**
|
||
* Creates a function that wraps `func` and invokes it with the optional `this`
|
||
* binding of `thisArg` and the `partials` prepended to those provided to
|
||
* the wrapper.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to partially apply arguments to.
|
||
* @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.
|
||
* @param {*} thisArg The `this` binding of `func`.
|
||
* @param {Array} partials The arguments to prepend to those provided to the new function.
|
||
* @returns {Function} Returns the new bound function.
|
||
*/
|
||
function createPartialWrapper(func, bitmask, thisArg, partials) {
|
||
var isBind = bitmask & BIND_FLAG,
|
||
Ctor = createCtorWrapper(func);
|
||
|
||
function wrapper() {
|
||
// Avoid `arguments` object use disqualifying optimizations by
|
||
// converting it to an array before providing it `func`.
|
||
var argsIndex = -1,
|
||
argsLength = arguments.length,
|
||
leftIndex = -1,
|
||
leftLength = partials.length,
|
||
args = Array(leftLength + argsLength);
|
||
|
||
while (++leftIndex < leftLength) {
|
||
args[leftIndex] = partials[leftIndex];
|
||
}
|
||
while (argsLength--) {
|
||
args[leftIndex++] = arguments[++argsIndex];
|
||
}
|
||
var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
|
||
return fn.apply(isBind ? thisArg : this, args);
|
||
}
|
||
return wrapper;
|
||
}
|
||
|
||
/**
|
||
* Creates a `_.ceil`, `_.floor`, or `_.round` function.
|
||
*
|
||
* @private
|
||
* @param {string} methodName The name of the `Math` method to use when rounding.
|
||
* @returns {Function} Returns the new round function.
|
||
*/
|
||
function createRound(methodName) {
|
||
var func = Math[methodName];
|
||
return function(number, precision) {
|
||
precision = precision === undefined ? 0 : (+precision || 0);
|
||
if (precision) {
|
||
precision = pow(10, precision);
|
||
return func(number * precision) / precision;
|
||
}
|
||
return func(number);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a `_.sortedIndex` or `_.sortedLastIndex` function.
|
||
*
|
||
* @private
|
||
* @param {boolean} [retHighest] Specify returning the highest qualified index.
|
||
* @returns {Function} Returns the new index function.
|
||
*/
|
||
function createSortedIndex(retHighest) {
|
||
return function(array, value, iteratee, thisArg) {
|
||
var callback = getCallback(iteratee);
|
||
return (iteratee == null && callback === baseCallback)
|
||
? binaryIndex(array, value, retHighest)
|
||
: binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a function that either curries or invokes `func` with optional
|
||
* `this` binding and partially applied arguments.
|
||
*
|
||
* @private
|
||
* @param {Function|string} func The function or method name to reference.
|
||
* @param {number} bitmask The bitmask of flags.
|
||
* The bitmask may be composed of the following flags:
|
||
* 1 - `_.bind`
|
||
* 2 - `_.bindKey`
|
||
* 4 - `_.curry` or `_.curryRight` of a bound function
|
||
* 8 - `_.curry`
|
||
* 16 - `_.curryRight`
|
||
* 32 - `_.partial`
|
||
* 64 - `_.partialRight`
|
||
* 128 - `_.rearg`
|
||
* 256 - `_.ary`
|
||
* @param {*} [thisArg] The `this` binding of `func`.
|
||
* @param {Array} [partials] The arguments to be partially applied.
|
||
* @param {Array} [holders] The `partials` placeholder indexes.
|
||
* @param {Array} [argPos] The argument positions of the new function.
|
||
* @param {number} [ary] The arity cap of `func`.
|
||
* @param {number} [arity] The arity of `func`.
|
||
* @returns {Function} Returns the new wrapped function.
|
||
*/
|
||
function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
|
||
var isBindKey = bitmask & BIND_KEY_FLAG;
|
||
if (!isBindKey && typeof func != 'function') {
|
||
throw new TypeError(FUNC_ERROR_TEXT);
|
||
}
|
||
var length = partials ? partials.length : 0;
|
||
if (!length) {
|
||
bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG);
|
||
partials = holders = undefined;
|
||
}
|
||
length -= (holders ? holders.length : 0);
|
||
if (bitmask & PARTIAL_RIGHT_FLAG) {
|
||
var partialsRight = partials,
|
||
holdersRight = holders;
|
||
|
||
partials = holders = undefined;
|
||
}
|
||
var data = isBindKey ? undefined : getData(func),
|
||
newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity];
|
||
|
||
if (data) {
|
||
mergeData(newData, data);
|
||
bitmask = newData[1];
|
||
arity = newData[9];
|
||
}
|
||
newData[9] = arity == null
|
||
? (isBindKey ? 0 : func.length)
|
||
: (nativeMax(arity - length, 0) || 0);
|
||
|
||
if (bitmask == BIND_FLAG) {
|
||
var result = createBindWrapper(newData[0], newData[2]);
|
||
} else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) {
|
||
result = createPartialWrapper.apply(undefined, newData);
|
||
} else {
|
||
result = createHybridWrapper.apply(undefined, newData);
|
||
}
|
||
var setter = data ? baseSetData : setData;
|
||
return setter(result, newData);
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `baseIsEqualDeep` for arrays with support for
|
||
* partial deep comparisons.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to compare.
|
||
* @param {Array} other The other array to compare.
|
||
* @param {Function} equalFunc The function to determine equivalents of values.
|
||
* @param {Function} [customizer] The function to customize comparing arrays.
|
||
* @param {boolean} [isLoose] Specify performing partial comparisons.
|
||
* @param {Array} [stackA] Tracks traversed `value` objects.
|
||
* @param {Array} [stackB] Tracks traversed `other` objects.
|
||
* @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
|
||
*/
|
||
function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) {
|
||
var index = -1,
|
||
arrLength = array.length,
|
||
othLength = other.length;
|
||
|
||
if (arrLength != othLength && !(isLoose && othLength > arrLength)) {
|
||
return false;
|
||
}
|
||
// Ignore non-index properties.
|
||
while (++index < arrLength) {
|
||
var arrValue = array[index],
|
||
othValue = other[index],
|
||
result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined;
|
||
|
||
if (result !== undefined) {
|
||
if (result) {
|
||
continue;
|
||
}
|
||
return false;
|
||
}
|
||
// Recursively compare arrays (susceptible to call stack limits).
|
||
if (isLoose) {
|
||
if (!arraySome(other, function(othValue) {
|
||
return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);
|
||
})) {
|
||
return false;
|
||
}
|
||
} else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `baseIsEqualDeep` for comparing objects of
|
||
* the same `toStringTag`.
|
||
*
|
||
* **Note:** This function only supports comparing values with tags of
|
||
* `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to compare.
|
||
* @param {Object} other The other object to compare.
|
||
* @param {string} tag The `toStringTag` of the objects to compare.
|
||
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
|
||
*/
|
||
function equalByTag(object, other, tag) {
|
||
switch (tag) {
|
||
case boolTag:
|
||
case dateTag:
|
||
// Coerce dates and booleans to numbers, dates to milliseconds and booleans
|
||
// to `1` or `0` treating invalid dates coerced to `NaN` as not equal.
|
||
return +object == +other;
|
||
|
||
case errorTag:
|
||
return object.name == other.name && object.message == other.message;
|
||
|
||
case numberTag:
|
||
// Treat `NaN` vs. `NaN` as equal.
|
||
return (object != +object)
|
||
? other != +other
|
||
: object == +other;
|
||
|
||
case regexpTag:
|
||
case stringTag:
|
||
// Coerce regexes to strings and treat strings primitives and string
|
||
// objects as equal. See https://es5.github.io/#x15.10.6.4 for more details.
|
||
return object == (other + '');
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `baseIsEqualDeep` for objects with support for
|
||
* partial deep comparisons.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to compare.
|
||
* @param {Object} other The other object to compare.
|
||
* @param {Function} equalFunc The function to determine equivalents of values.
|
||
* @param {Function} [customizer] The function to customize comparing values.
|
||
* @param {boolean} [isLoose] Specify performing partial comparisons.
|
||
* @param {Array} [stackA] Tracks traversed `value` objects.
|
||
* @param {Array} [stackB] Tracks traversed `other` objects.
|
||
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
|
||
*/
|
||
function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
|
||
var objProps = keys(object),
|
||
objLength = objProps.length,
|
||
othProps = keys(other),
|
||
othLength = othProps.length;
|
||
|
||
if (objLength != othLength && !isLoose) {
|
||
return false;
|
||
}
|
||
var index = objLength;
|
||
while (index--) {
|
||
var key = objProps[index];
|
||
if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) {
|
||
return false;
|
||
}
|
||
}
|
||
var skipCtor = isLoose;
|
||
while (++index < objLength) {
|
||
key = objProps[index];
|
||
var objValue = object[key],
|
||
othValue = other[key],
|
||
result = customizer ? customizer(isLoose ? othValue : objValue, isLoose? objValue : othValue, key) : undefined;
|
||
|
||
// Recursively compare objects (susceptible to call stack limits).
|
||
if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) {
|
||
return false;
|
||
}
|
||
skipCtor || (skipCtor = key == 'constructor');
|
||
}
|
||
if (!skipCtor) {
|
||
var objCtor = object.constructor,
|
||
othCtor = other.constructor;
|
||
|
||
// Non `Object` object instances with different constructors are not equal.
|
||
if (objCtor != othCtor &&
|
||
('constructor' in object && 'constructor' in other) &&
|
||
!(typeof objCtor == 'function' && objCtor instanceof objCtor &&
|
||
typeof othCtor == 'function' && othCtor instanceof othCtor)) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Gets the appropriate "callback" function. If the `_.callback` method is
|
||
* customized this function returns the custom method, otherwise it returns
|
||
* the `baseCallback` function. If arguments are provided the chosen function
|
||
* is invoked with them and its result is returned.
|
||
*
|
||
* @private
|
||
* @returns {Function} Returns the chosen function or its result.
|
||
*/
|
||
function getCallback(func, thisArg, argCount) {
|
||
var result = lodash.callback || callback;
|
||
result = result === callback ? baseCallback : result;
|
||
return argCount ? result(func, thisArg, argCount) : result;
|
||
}
|
||
|
||
/**
|
||
* Gets metadata for `func`.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to query.
|
||
* @returns {*} Returns the metadata for `func`.
|
||
*/
|
||
var getData = !metaMap ? noop : function(func) {
|
||
return metaMap.get(func);
|
||
};
|
||
|
||
/**
|
||
* Gets the name of `func`.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to query.
|
||
* @returns {string} Returns the function name.
|
||
*/
|
||
function getFuncName(func) {
|
||
var result = func.name,
|
||
array = realNames[result],
|
||
length = array ? array.length : 0;
|
||
|
||
while (length--) {
|
||
var data = array[length],
|
||
otherFunc = data.func;
|
||
if (otherFunc == null || otherFunc == func) {
|
||
return data.name;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Gets the appropriate "indexOf" function. If the `_.indexOf` method is
|
||
* customized this function returns the custom method, otherwise it returns
|
||
* the `baseIndexOf` function. If arguments are provided the chosen function
|
||
* is invoked with them and its result is returned.
|
||
*
|
||
* @private
|
||
* @returns {Function|number} Returns the chosen function or its result.
|
||
*/
|
||
function getIndexOf(collection, target, fromIndex) {
|
||
var result = lodash.indexOf || indexOf;
|
||
result = result === indexOf ? baseIndexOf : result;
|
||
return collection ? result(collection, target, fromIndex) : result;
|
||
}
|
||
|
||
/**
|
||
* Gets the "length" property value of `object`.
|
||
*
|
||
* **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
|
||
* that affects Safari on at least iOS 8.1-8.3 ARM64.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to query.
|
||
* @returns {*} Returns the "length" value.
|
||
*/
|
||
var getLength = baseProperty('length');
|
||
|
||
/**
|
||
* Gets the propery names, values, and compare flags of `object`.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to query.
|
||
* @returns {Array} Returns the match data of `object`.
|
||
*/
|
||
function getMatchData(object) {
|
||
var result = pairs(object),
|
||
length = result.length;
|
||
|
||
while (length--) {
|
||
result[length][2] = isStrictComparable(result[length][1]);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Gets the native function at `key` of `object`.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to query.
|
||
* @param {string} key The key of the method to get.
|
||
* @returns {*} Returns the function if it's native, else `undefined`.
|
||
*/
|
||
function getNative(object, key) {
|
||
var value = object == null ? undefined : object[key];
|
||
return isNative(value) ? value : undefined;
|
||
}
|
||
|
||
/**
|
||
* Gets the view, applying any `transforms` to the `start` and `end` positions.
|
||
*
|
||
* @private
|
||
* @param {number} start The start of the view.
|
||
* @param {number} end The end of the view.
|
||
* @param {Array} transforms The transformations to apply to the view.
|
||
* @returns {Object} Returns an object containing the `start` and `end`
|
||
* positions of the view.
|
||
*/
|
||
function getView(start, end, transforms) {
|
||
var index = -1,
|
||
length = transforms.length;
|
||
|
||
while (++index < length) {
|
||
var data = transforms[index],
|
||
size = data.size;
|
||
|
||
switch (data.type) {
|
||
case 'drop': start += size; break;
|
||
case 'dropRight': end -= size; break;
|
||
case 'take': end = nativeMin(end, start + size); break;
|
||
case 'takeRight': start = nativeMax(start, end - size); break;
|
||
}
|
||
}
|
||
return { 'start': start, 'end': end };
|
||
}
|
||
|
||
/**
|
||
* Initializes an array clone.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to clone.
|
||
* @returns {Array} Returns the initialized clone.
|
||
*/
|
||
function initCloneArray(array) {
|
||
var length = array.length,
|
||
result = new array.constructor(length);
|
||
|
||
// Add array properties assigned by `RegExp#exec`.
|
||
if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
|
||
result.index = array.index;
|
||
result.input = array.input;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Initializes an object clone.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to clone.
|
||
* @returns {Object} Returns the initialized clone.
|
||
*/
|
||
function initCloneObject(object) {
|
||
var Ctor = object.constructor;
|
||
if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) {
|
||
Ctor = Object;
|
||
}
|
||
return new Ctor;
|
||
}
|
||
|
||
/**
|
||
* Initializes an object clone based on its `toStringTag`.
|
||
*
|
||
* **Note:** This function only supports cloning values with tags of
|
||
* `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to clone.
|
||
* @param {string} tag The `toStringTag` of the object to clone.
|
||
* @param {boolean} [isDeep] Specify a deep clone.
|
||
* @returns {Object} Returns the initialized clone.
|
||
*/
|
||
function initCloneByTag(object, tag, isDeep) {
|
||
var Ctor = object.constructor;
|
||
switch (tag) {
|
||
case arrayBufferTag:
|
||
return bufferClone(object);
|
||
|
||
case boolTag:
|
||
case dateTag:
|
||
return new Ctor(+object);
|
||
|
||
case float32Tag: case float64Tag:
|
||
case int8Tag: case int16Tag: case int32Tag:
|
||
case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
|
||
var buffer = object.buffer;
|
||
return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length);
|
||
|
||
case numberTag:
|
||
case stringTag:
|
||
return new Ctor(object);
|
||
|
||
case regexpTag:
|
||
var result = new Ctor(object.source, reFlags.exec(object));
|
||
result.lastIndex = object.lastIndex;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Invokes the method at `path` on `object`.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to query.
|
||
* @param {Array|string} path The path of the method to invoke.
|
||
* @param {Array} args The arguments to invoke the method with.
|
||
* @returns {*} Returns the result of the invoked method.
|
||
*/
|
||
function invokePath(object, path, args) {
|
||
if (object != null && !isKey(path, object)) {
|
||
path = toPath(path);
|
||
object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
|
||
path = last(path);
|
||
}
|
||
var func = object == null ? object : object[path];
|
||
return func == null ? undefined : func.apply(object, args);
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is array-like.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is array-like, else `false`.
|
||
*/
|
||
function isArrayLike(value) {
|
||
return value != null && isLength(getLength(value));
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is a valid array-like index.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
|
||
* @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
|
||
*/
|
||
function isIndex(value, length) {
|
||
value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
|
||
length = length == null ? MAX_SAFE_INTEGER : length;
|
||
return value > -1 && value % 1 == 0 && value < length;
|
||
}
|
||
|
||
/**
|
||
* Checks if the provided arguments are from an iteratee call.
|
||
*
|
||
* @private
|
||
* @param {*} value The potential iteratee value argument.
|
||
* @param {*} index The potential iteratee index or key argument.
|
||
* @param {*} object The potential iteratee object argument.
|
||
* @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`.
|
||
*/
|
||
function isIterateeCall(value, index, object) {
|
||
if (!isObject(object)) {
|
||
return false;
|
||
}
|
||
var type = typeof index;
|
||
if (type == 'number'
|
||
? (isArrayLike(object) && isIndex(index, object.length))
|
||
: (type == 'string' && index in object)) {
|
||
var other = object[index];
|
||
return value === value ? (value === other) : (other !== other);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is a property name and not a property path.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @param {Object} [object] The object to query keys on.
|
||
* @returns {boolean} Returns `true` if `value` is a property name, else `false`.
|
||
*/
|
||
function isKey(value, object) {
|
||
var type = typeof value;
|
||
if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') {
|
||
return true;
|
||
}
|
||
if (isArray(value)) {
|
||
return false;
|
||
}
|
||
var result = !reIsDeepProp.test(value);
|
||
return result || (object != null && value in toObject(object));
|
||
}
|
||
|
||
/**
|
||
* Checks if `func` has a lazy counterpart.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to check.
|
||
* @returns {boolean} Returns `true` if `func` has a lazy counterpart, else `false`.
|
||
*/
|
||
function isLaziable(func) {
|
||
var funcName = getFuncName(func);
|
||
if (!(funcName in LazyWrapper.prototype)) {
|
||
return false;
|
||
}
|
||
var other = lodash[funcName];
|
||
if (func === other) {
|
||
return true;
|
||
}
|
||
var data = getData(other);
|
||
return !!data && func === data[0];
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is a valid array-like length.
|
||
*
|
||
* **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
|
||
*/
|
||
function isLength(value) {
|
||
return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` if suitable for strict
|
||
* equality comparisons, else `false`.
|
||
*/
|
||
function isStrictComparable(value) {
|
||
return value === value && !isObject(value);
|
||
}
|
||
|
||
/**
|
||
* Merges the function metadata of `source` into `data`.
|
||
*
|
||
* Merging metadata reduces the number of wrappers required to invoke a function.
|
||
* This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
|
||
* may be applied regardless of execution order. Methods like `_.ary` and `_.rearg`
|
||
* augment function arguments, making the order in which they are executed important,
|
||
* preventing the merging of metadata. However, we make an exception for a safe
|
||
* common case where curried functions have `_.ary` and or `_.rearg` applied.
|
||
*
|
||
* @private
|
||
* @param {Array} data The destination metadata.
|
||
* @param {Array} source The source metadata.
|
||
* @returns {Array} Returns `data`.
|
||
*/
|
||
function mergeData(data, source) {
|
||
var bitmask = data[1],
|
||
srcBitmask = source[1],
|
||
newBitmask = bitmask | srcBitmask,
|
||
isCommon = newBitmask < ARY_FLAG;
|
||
|
||
var isCombo =
|
||
(srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG) ||
|
||
(srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8]) ||
|
||
(srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG);
|
||
|
||
// Exit early if metadata can't be merged.
|
||
if (!(isCommon || isCombo)) {
|
||
return data;
|
||
}
|
||
// Use source `thisArg` if available.
|
||
if (srcBitmask & BIND_FLAG) {
|
||
data[2] = source[2];
|
||
// Set when currying a bound function.
|
||
newBitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG;
|
||
}
|
||
// Compose partial arguments.
|
||
var value = source[3];
|
||
if (value) {
|
||
var partials = data[3];
|
||
data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value);
|
||
data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]);
|
||
}
|
||
// Compose partial right arguments.
|
||
value = source[5];
|
||
if (value) {
|
||
partials = data[5];
|
||
data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value);
|
||
data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]);
|
||
}
|
||
// Use source `argPos` if available.
|
||
value = source[7];
|
||
if (value) {
|
||
data[7] = arrayCopy(value);
|
||
}
|
||
// Use source `ary` if it's smaller.
|
||
if (srcBitmask & ARY_FLAG) {
|
||
data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
|
||
}
|
||
// Use source `arity` if one is not provided.
|
||
if (data[9] == null) {
|
||
data[9] = source[9];
|
||
}
|
||
// Use source `func` and merge bitmasks.
|
||
data[0] = source[0];
|
||
data[1] = newBitmask;
|
||
|
||
return data;
|
||
}
|
||
|
||
/**
|
||
* Used by `_.defaultsDeep` to customize its `_.merge` use.
|
||
*
|
||
* @private
|
||
* @param {*} objectValue The destination object property value.
|
||
* @param {*} sourceValue The source object property value.
|
||
* @returns {*} Returns the value to assign to the destination object.
|
||
*/
|
||
function mergeDefaults(objectValue, sourceValue) {
|
||
return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults);
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `_.pick` which picks `object` properties specified
|
||
* by `props`.
|
||
*
|
||
* @private
|
||
* @param {Object} object The source object.
|
||
* @param {string[]} props The property names to pick.
|
||
* @returns {Object} Returns the new object.
|
||
*/
|
||
function pickByArray(object, props) {
|
||
object = toObject(object);
|
||
|
||
var index = -1,
|
||
length = props.length,
|
||
result = {};
|
||
|
||
while (++index < length) {
|
||
var key = props[index];
|
||
if (key in object) {
|
||
result[key] = object[key];
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* A specialized version of `_.pick` which picks `object` properties `predicate`
|
||
* returns truthy for.
|
||
*
|
||
* @private
|
||
* @param {Object} object The source object.
|
||
* @param {Function} predicate The function invoked per iteration.
|
||
* @returns {Object} Returns the new object.
|
||
*/
|
||
function pickByCallback(object, predicate) {
|
||
var result = {};
|
||
baseForIn(object, function(value, key, object) {
|
||
if (predicate(value, key, object)) {
|
||
result[key] = value;
|
||
}
|
||
});
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Reorder `array` according to the specified indexes where the element at
|
||
* the first index is assigned as the first element, the element at
|
||
* the second index is assigned as the second element, and so on.
|
||
*
|
||
* @private
|
||
* @param {Array} array The array to reorder.
|
||
* @param {Array} indexes The arranged array indexes.
|
||
* @returns {Array} Returns `array`.
|
||
*/
|
||
function reorder(array, indexes) {
|
||
var arrLength = array.length,
|
||
length = nativeMin(indexes.length, arrLength),
|
||
oldArray = arrayCopy(array);
|
||
|
||
while (length--) {
|
||
var index = indexes[length];
|
||
array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
|
||
}
|
||
return array;
|
||
}
|
||
|
||
/**
|
||
* Sets metadata for `func`.
|
||
*
|
||
* **Note:** If this function becomes hot, i.e. is invoked a lot in a short
|
||
* period of time, it will trip its breaker and transition to an identity function
|
||
* to avoid garbage collection pauses in V8. See [V8 issue 2070](https://code.google.com/p/v8/issues/detail?id=2070)
|
||
* for more details.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to associate metadata with.
|
||
* @param {*} data The metadata.
|
||
* @returns {Function} Returns `func`.
|
||
*/
|
||
var setData = (function() {
|
||
var count = 0,
|
||
lastCalled = 0;
|
||
|
||
return function(key, value) {
|
||
var stamp = now(),
|
||
remaining = HOT_SPAN - (stamp - lastCalled);
|
||
|
||
lastCalled = stamp;
|
||
if (remaining > 0) {
|
||
if (++count >= HOT_COUNT) {
|
||
return key;
|
||
}
|
||
} else {
|
||
count = 0;
|
||
}
|
||
return baseSetData(key, value);
|
||
};
|
||
}());
|
||
|
||
/**
|
||
* A fallback implementation of `Object.keys` which creates an array of the
|
||
* own enumerable property names of `object`.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to query.
|
||
* @returns {Array} Returns the array of property names.
|
||
*/
|
||
function shimKeys(object) {
|
||
var props = keysIn(object),
|
||
propsLength = props.length,
|
||
length = propsLength && object.length;
|
||
|
||
var allowIndexes = !!length && isLength(length) &&
|
||
(isArray(object) || isArguments(object));
|
||
|
||
var index = -1,
|
||
result = [];
|
||
|
||
while (++index < propsLength) {
|
||
var key = props[index];
|
||
if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {
|
||
result.push(key);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Converts `value` to an array-like object if it's not one.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to process.
|
||
* @returns {Array|Object} Returns the array-like object.
|
||
*/
|
||
function toIterable(value) {
|
||
if (value == null) {
|
||
return [];
|
||
}
|
||
if (!isArrayLike(value)) {
|
||
return values(value);
|
||
}
|
||
return isObject(value) ? value : Object(value);
|
||
}
|
||
|
||
/**
|
||
* Converts `value` to an object if it's not one.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to process.
|
||
* @returns {Object} Returns the object.
|
||
*/
|
||
function toObject(value) {
|
||
return isObject(value) ? value : Object(value);
|
||
}
|
||
|
||
/**
|
||
* Converts `value` to property path array if it's not one.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to process.
|
||
* @returns {Array} Returns the property path array.
|
||
*/
|
||
function toPath(value) {
|
||
if (isArray(value)) {
|
||
return value;
|
||
}
|
||
var result = [];
|
||
baseToString(value).replace(rePropName, function(match, number, quote, string) {
|
||
result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
|
||
});
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Creates a clone of `wrapper`.
|
||
*
|
||
* @private
|
||
* @param {Object} wrapper The wrapper to clone.
|
||
* @returns {Object} Returns the cloned wrapper.
|
||
*/
|
||
function wrapperClone(wrapper) {
|
||
return wrapper instanceof LazyWrapper
|
||
? wrapper.clone()
|
||
: new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__));
|
||
}
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Creates an array of elements split into groups the length of `size`.
|
||
* If `collection` can't be split evenly, the final chunk will be the remaining
|
||
* elements.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to process.
|
||
* @param {number} [size=1] The length of each chunk.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {Array} Returns the new array containing chunks.
|
||
* @example
|
||
*
|
||
* _.chunk(['a', 'b', 'c', 'd'], 2);
|
||
* // => [['a', 'b'], ['c', 'd']]
|
||
*
|
||
* _.chunk(['a', 'b', 'c', 'd'], 3);
|
||
* // => [['a', 'b', 'c'], ['d']]
|
||
*/
|
||
function chunk(array, size, guard) {
|
||
if (guard ? isIterateeCall(array, size, guard) : size == null) {
|
||
size = 1;
|
||
} else {
|
||
size = nativeMax(nativeFloor(size) || 1, 1);
|
||
}
|
||
var index = 0,
|
||
length = array ? array.length : 0,
|
||
resIndex = -1,
|
||
result = Array(nativeCeil(length / size));
|
||
|
||
while (index < length) {
|
||
result[++resIndex] = baseSlice(array, index, (index += size));
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Creates an array with all falsey values removed. The values `false`, `null`,
|
||
* `0`, `""`, `undefined`, and `NaN` are falsey.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to compact.
|
||
* @returns {Array} Returns the new array of filtered values.
|
||
* @example
|
||
*
|
||
* _.compact([0, 1, false, 2, '', 3]);
|
||
* // => [1, 2, 3]
|
||
*/
|
||
function compact(array) {
|
||
var index = -1,
|
||
length = array ? array.length : 0,
|
||
resIndex = -1,
|
||
result = [];
|
||
|
||
while (++index < length) {
|
||
var value = array[index];
|
||
if (value) {
|
||
result[++resIndex] = value;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Creates an array of unique `array` values not included in the other
|
||
* provided arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
|
||
* for equality comparisons.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to inspect.
|
||
* @param {...Array} [values] The arrays of values to exclude.
|
||
* @returns {Array} Returns the new array of filtered values.
|
||
* @example
|
||
*
|
||
* _.difference([1, 2, 3], [4, 2]);
|
||
* // => [1, 3]
|
||
*/
|
||
var difference = restParam(function(array, values) {
|
||
return (isObjectLike(array) && isArrayLike(array))
|
||
? baseDifference(array, baseFlatten(values, false, true))
|
||
: [];
|
||
});
|
||
|
||
/**
|
||
* Creates a slice of `array` with `n` elements dropped from the beginning.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to query.
|
||
* @param {number} [n=1] The number of elements to drop.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {Array} Returns the slice of `array`.
|
||
* @example
|
||
*
|
||
* _.drop([1, 2, 3]);
|
||
* // => [2, 3]
|
||
*
|
||
* _.drop([1, 2, 3], 2);
|
||
* // => [3]
|
||
*
|
||
* _.drop([1, 2, 3], 5);
|
||
* // => []
|
||
*
|
||
* _.drop([1, 2, 3], 0);
|
||
* // => [1, 2, 3]
|
||
*/
|
||
function drop(array, n, guard) {
|
||
var length = array ? array.length : 0;
|
||
if (!length) {
|
||
return [];
|
||
}
|
||
if (guard ? isIterateeCall(array, n, guard) : n == null) {
|
||
n = 1;
|
||
}
|
||
return baseSlice(array, n < 0 ? 0 : n);
|
||
}
|
||
|
||
/**
|
||
* Creates a slice of `array` with `n` elements dropped from the end.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to query.
|
||
* @param {number} [n=1] The number of elements to drop.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {Array} Returns the slice of `array`.
|
||
* @example
|
||
*
|
||
* _.dropRight([1, 2, 3]);
|
||
* // => [1, 2]
|
||
*
|
||
* _.dropRight([1, 2, 3], 2);
|
||
* // => [1]
|
||
*
|
||
* _.dropRight([1, 2, 3], 5);
|
||
* // => []
|
||
*
|
||
* _.dropRight([1, 2, 3], 0);
|
||
* // => [1, 2, 3]
|
||
*/
|
||
function dropRight(array, n, guard) {
|
||
var length = array ? array.length : 0;
|
||
if (!length) {
|
||
return [];
|
||
}
|
||
if (guard ? isIterateeCall(array, n, guard) : n == null) {
|
||
n = 1;
|
||
}
|
||
n = length - (+n || 0);
|
||
return baseSlice(array, 0, n < 0 ? 0 : n);
|
||
}
|
||
|
||
/**
|
||
* Creates a slice of `array` excluding elements dropped from the end.
|
||
* Elements are dropped until `predicate` returns falsey. The predicate is
|
||
* bound to `thisArg` and invoked with three arguments: (value, index, array).
|
||
*
|
||
* If a property name is provided for `predicate` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `predicate` the created `_.matches` style
|
||
* callback returns `true` for elements that match the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to query.
|
||
* @param {Function|Object|string} [predicate=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {Array} Returns the slice of `array`.
|
||
* @example
|
||
*
|
||
* _.dropRightWhile([1, 2, 3], function(n) {
|
||
* return n > 1;
|
||
* });
|
||
* // => [1]
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'active': true },
|
||
* { 'user': 'fred', 'active': false },
|
||
* { 'user': 'pebbles', 'active': false }
|
||
* ];
|
||
*
|
||
* // using the `_.matches` callback shorthand
|
||
* _.pluck(_.dropRightWhile(users, { 'user': 'pebbles', 'active': false }), 'user');
|
||
* // => ['barney', 'fred']
|
||
*
|
||
* // using the `_.matchesProperty` callback shorthand
|
||
* _.pluck(_.dropRightWhile(users, 'active', false), 'user');
|
||
* // => ['barney']
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.pluck(_.dropRightWhile(users, 'active'), 'user');
|
||
* // => ['barney', 'fred', 'pebbles']
|
||
*/
|
||
function dropRightWhile(array, predicate, thisArg) {
|
||
return (array && array.length)
|
||
? baseWhile(array, getCallback(predicate, thisArg, 3), true, true)
|
||
: [];
|
||
}
|
||
|
||
/**
|
||
* Creates a slice of `array` excluding elements dropped from the beginning.
|
||
* Elements are dropped until `predicate` returns falsey. The predicate is
|
||
* bound to `thisArg` and invoked with three arguments: (value, index, array).
|
||
*
|
||
* If a property name is provided for `predicate` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `predicate` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to query.
|
||
* @param {Function|Object|string} [predicate=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {Array} Returns the slice of `array`.
|
||
* @example
|
||
*
|
||
* _.dropWhile([1, 2, 3], function(n) {
|
||
* return n < 3;
|
||
* });
|
||
* // => [3]
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'active': false },
|
||
* { 'user': 'fred', 'active': false },
|
||
* { 'user': 'pebbles', 'active': true }
|
||
* ];
|
||
*
|
||
* // using the `_.matches` callback shorthand
|
||
* _.pluck(_.dropWhile(users, { 'user': 'barney', 'active': false }), 'user');
|
||
* // => ['fred', 'pebbles']
|
||
*
|
||
* // using the `_.matchesProperty` callback shorthand
|
||
* _.pluck(_.dropWhile(users, 'active', false), 'user');
|
||
* // => ['pebbles']
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.pluck(_.dropWhile(users, 'active'), 'user');
|
||
* // => ['barney', 'fred', 'pebbles']
|
||
*/
|
||
function dropWhile(array, predicate, thisArg) {
|
||
return (array && array.length)
|
||
? baseWhile(array, getCallback(predicate, thisArg, 3), true)
|
||
: [];
|
||
}
|
||
|
||
/**
|
||
* Fills elements of `array` with `value` from `start` up to, but not
|
||
* including, `end`.
|
||
*
|
||
* **Note:** This method mutates `array`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to fill.
|
||
* @param {*} value The value to fill `array` with.
|
||
* @param {number} [start=0] The start position.
|
||
* @param {number} [end=array.length] The end position.
|
||
* @returns {Array} Returns `array`.
|
||
* @example
|
||
*
|
||
* var array = [1, 2, 3];
|
||
*
|
||
* _.fill(array, 'a');
|
||
* console.log(array);
|
||
* // => ['a', 'a', 'a']
|
||
*
|
||
* _.fill(Array(3), 2);
|
||
* // => [2, 2, 2]
|
||
*
|
||
* _.fill([4, 6, 8], '*', 1, 2);
|
||
* // => [4, '*', 8]
|
||
*/
|
||
function fill(array, value, start, end) {
|
||
var length = array ? array.length : 0;
|
||
if (!length) {
|
||
return [];
|
||
}
|
||
if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
|
||
start = 0;
|
||
end = length;
|
||
}
|
||
return baseFill(array, value, start, end);
|
||
}
|
||
|
||
/**
|
||
* This method is like `_.find` except that it returns the index of the first
|
||
* element `predicate` returns truthy for instead of the element itself.
|
||
*
|
||
* If a property name is provided for `predicate` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `predicate` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to search.
|
||
* @param {Function|Object|string} [predicate=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {number} Returns the index of the found element, else `-1`.
|
||
* @example
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'active': false },
|
||
* { 'user': 'fred', 'active': false },
|
||
* { 'user': 'pebbles', 'active': true }
|
||
* ];
|
||
*
|
||
* _.findIndex(users, function(chr) {
|
||
* return chr.user == 'barney';
|
||
* });
|
||
* // => 0
|
||
*
|
||
* // using the `_.matches` callback shorthand
|
||
* _.findIndex(users, { 'user': 'fred', 'active': false });
|
||
* // => 1
|
||
*
|
||
* // using the `_.matchesProperty` callback shorthand
|
||
* _.findIndex(users, 'active', false);
|
||
* // => 0
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.findIndex(users, 'active');
|
||
* // => 2
|
||
*/
|
||
var findIndex = createFindIndex();
|
||
|
||
/**
|
||
* This method is like `_.findIndex` except that it iterates over elements
|
||
* of `collection` from right to left.
|
||
*
|
||
* If a property name is provided for `predicate` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `predicate` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to search.
|
||
* @param {Function|Object|string} [predicate=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {number} Returns the index of the found element, else `-1`.
|
||
* @example
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'active': true },
|
||
* { 'user': 'fred', 'active': false },
|
||
* { 'user': 'pebbles', 'active': false }
|
||
* ];
|
||
*
|
||
* _.findLastIndex(users, function(chr) {
|
||
* return chr.user == 'pebbles';
|
||
* });
|
||
* // => 2
|
||
*
|
||
* // using the `_.matches` callback shorthand
|
||
* _.findLastIndex(users, { 'user': 'barney', 'active': true });
|
||
* // => 0
|
||
*
|
||
* // using the `_.matchesProperty` callback shorthand
|
||
* _.findLastIndex(users, 'active', false);
|
||
* // => 2
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.findLastIndex(users, 'active');
|
||
* // => 0
|
||
*/
|
||
var findLastIndex = createFindIndex(true);
|
||
|
||
/**
|
||
* Gets the first element of `array`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias head
|
||
* @category Array
|
||
* @param {Array} array The array to query.
|
||
* @returns {*} Returns the first element of `array`.
|
||
* @example
|
||
*
|
||
* _.first([1, 2, 3]);
|
||
* // => 1
|
||
*
|
||
* _.first([]);
|
||
* // => undefined
|
||
*/
|
||
function first(array) {
|
||
return array ? array[0] : undefined;
|
||
}
|
||
|
||
/**
|
||
* Flattens a nested array. If `isDeep` is `true` the array is recursively
|
||
* flattened, otherwise it is only flattened a single level.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to flatten.
|
||
* @param {boolean} [isDeep] Specify a deep flatten.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {Array} Returns the new flattened array.
|
||
* @example
|
||
*
|
||
* _.flatten([1, [2, 3, [4]]]);
|
||
* // => [1, 2, 3, [4]]
|
||
*
|
||
* // using `isDeep`
|
||
* _.flatten([1, [2, 3, [4]]], true);
|
||
* // => [1, 2, 3, 4]
|
||
*/
|
||
function flatten(array, isDeep, guard) {
|
||
var length = array ? array.length : 0;
|
||
if (guard && isIterateeCall(array, isDeep, guard)) {
|
||
isDeep = false;
|
||
}
|
||
return length ? baseFlatten(array, isDeep) : [];
|
||
}
|
||
|
||
/**
|
||
* Recursively flattens a nested array.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to recursively flatten.
|
||
* @returns {Array} Returns the new flattened array.
|
||
* @example
|
||
*
|
||
* _.flattenDeep([1, [2, 3, [4]]]);
|
||
* // => [1, 2, 3, 4]
|
||
*/
|
||
function flattenDeep(array) {
|
||
var length = array ? array.length : 0;
|
||
return length ? baseFlatten(array, true) : [];
|
||
}
|
||
|
||
/**
|
||
* Gets the index at which the first occurrence of `value` is found in `array`
|
||
* using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
|
||
* for equality comparisons. If `fromIndex` is negative, it is used as the offset
|
||
* from the end of `array`. If `array` is sorted providing `true` for `fromIndex`
|
||
* performs a faster binary search.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to search.
|
||
* @param {*} value The value to search for.
|
||
* @param {boolean|number} [fromIndex=0] The index to search from or `true`
|
||
* to perform a binary search on a sorted array.
|
||
* @returns {number} Returns the index of the matched value, else `-1`.
|
||
* @example
|
||
*
|
||
* _.indexOf([1, 2, 1, 2], 2);
|
||
* // => 1
|
||
*
|
||
* // using `fromIndex`
|
||
* _.indexOf([1, 2, 1, 2], 2, 2);
|
||
* // => 3
|
||
*
|
||
* // performing a binary search
|
||
* _.indexOf([1, 1, 2, 2], 2, true);
|
||
* // => 2
|
||
*/
|
||
function indexOf(array, value, fromIndex) {
|
||
var length = array ? array.length : 0;
|
||
if (!length) {
|
||
return -1;
|
||
}
|
||
if (typeof fromIndex == 'number') {
|
||
fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex;
|
||
} else if (fromIndex) {
|
||
var index = binaryIndex(array, value);
|
||
if (index < length &&
|
||
(value === value ? (value === array[index]) : (array[index] !== array[index]))) {
|
||
return index;
|
||
}
|
||
return -1;
|
||
}
|
||
return baseIndexOf(array, value, fromIndex || 0);
|
||
}
|
||
|
||
/**
|
||
* Gets all but the last element of `array`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to query.
|
||
* @returns {Array} Returns the slice of `array`.
|
||
* @example
|
||
*
|
||
* _.initial([1, 2, 3]);
|
||
* // => [1, 2]
|
||
*/
|
||
function initial(array) {
|
||
return dropRight(array, 1);
|
||
}
|
||
|
||
/**
|
||
* Creates an array of unique values that are included in all of the provided
|
||
* arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
|
||
* for equality comparisons.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {...Array} [arrays] The arrays to inspect.
|
||
* @returns {Array} Returns the new array of shared values.
|
||
* @example
|
||
* _.intersection([1, 2], [4, 2], [2, 1]);
|
||
* // => [2]
|
||
*/
|
||
var intersection = restParam(function(arrays) {
|
||
var othLength = arrays.length,
|
||
othIndex = othLength,
|
||
caches = Array(length),
|
||
indexOf = getIndexOf(),
|
||
isCommon = indexOf == baseIndexOf,
|
||
result = [];
|
||
|
||
while (othIndex--) {
|
||
var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : [];
|
||
caches[othIndex] = (isCommon && value.length >= 120) ? createCache(othIndex && value) : null;
|
||
}
|
||
var array = arrays[0],
|
||
index = -1,
|
||
length = array ? array.length : 0,
|
||
seen = caches[0];
|
||
|
||
outer:
|
||
while (++index < length) {
|
||
value = array[index];
|
||
if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) {
|
||
var othIndex = othLength;
|
||
while (--othIndex) {
|
||
var cache = caches[othIndex];
|
||
if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) {
|
||
continue outer;
|
||
}
|
||
}
|
||
if (seen) {
|
||
seen.push(value);
|
||
}
|
||
result.push(value);
|
||
}
|
||
}
|
||
return result;
|
||
});
|
||
|
||
/**
|
||
* Gets the last element of `array`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to query.
|
||
* @returns {*} Returns the last element of `array`.
|
||
* @example
|
||
*
|
||
* _.last([1, 2, 3]);
|
||
* // => 3
|
||
*/
|
||
function last(array) {
|
||
var length = array ? array.length : 0;
|
||
return length ? array[length - 1] : undefined;
|
||
}
|
||
|
||
/**
|
||
* This method is like `_.indexOf` except that it iterates over elements of
|
||
* `array` from right to left.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to search.
|
||
* @param {*} value The value to search for.
|
||
* @param {boolean|number} [fromIndex=array.length-1] The index to search from
|
||
* or `true` to perform a binary search on a sorted array.
|
||
* @returns {number} Returns the index of the matched value, else `-1`.
|
||
* @example
|
||
*
|
||
* _.lastIndexOf([1, 2, 1, 2], 2);
|
||
* // => 3
|
||
*
|
||
* // using `fromIndex`
|
||
* _.lastIndexOf([1, 2, 1, 2], 2, 2);
|
||
* // => 1
|
||
*
|
||
* // performing a binary search
|
||
* _.lastIndexOf([1, 1, 2, 2], 2, true);
|
||
* // => 3
|
||
*/
|
||
function lastIndexOf(array, value, fromIndex) {
|
||
var length = array ? array.length : 0;
|
||
if (!length) {
|
||
return -1;
|
||
}
|
||
var index = length;
|
||
if (typeof fromIndex == 'number') {
|
||
index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1;
|
||
} else if (fromIndex) {
|
||
index = binaryIndex(array, value, true) - 1;
|
||
var other = array[index];
|
||
if (value === value ? (value === other) : (other !== other)) {
|
||
return index;
|
||
}
|
||
return -1;
|
||
}
|
||
if (value !== value) {
|
||
return indexOfNaN(array, index, true);
|
||
}
|
||
while (index--) {
|
||
if (array[index] === value) {
|
||
return index;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* Removes all provided values from `array` using
|
||
* [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
|
||
* for equality comparisons.
|
||
*
|
||
* **Note:** Unlike `_.without`, this method mutates `array`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to modify.
|
||
* @param {...*} [values] The values to remove.
|
||
* @returns {Array} Returns `array`.
|
||
* @example
|
||
*
|
||
* var array = [1, 2, 3, 1, 2, 3];
|
||
*
|
||
* _.pull(array, 2, 3);
|
||
* console.log(array);
|
||
* // => [1, 1]
|
||
*/
|
||
function pull() {
|
||
var args = arguments,
|
||
array = args[0];
|
||
|
||
if (!(array && array.length)) {
|
||
return array;
|
||
}
|
||
var index = 0,
|
||
indexOf = getIndexOf(),
|
||
length = args.length;
|
||
|
||
while (++index < length) {
|
||
var fromIndex = 0,
|
||
value = args[index];
|
||
|
||
while ((fromIndex = indexOf(array, value, fromIndex)) > -1) {
|
||
splice.call(array, fromIndex, 1);
|
||
}
|
||
}
|
||
return array;
|
||
}
|
||
|
||
/**
|
||
* Removes elements from `array` corresponding to the given indexes and returns
|
||
* an array of the removed elements. Indexes may be specified as an array of
|
||
* indexes or as individual arguments.
|
||
*
|
||
* **Note:** Unlike `_.at`, this method mutates `array`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to modify.
|
||
* @param {...(number|number[])} [indexes] The indexes of elements to remove,
|
||
* specified as individual indexes or arrays of indexes.
|
||
* @returns {Array} Returns the new array of removed elements.
|
||
* @example
|
||
*
|
||
* var array = [5, 10, 15, 20];
|
||
* var evens = _.pullAt(array, 1, 3);
|
||
*
|
||
* console.log(array);
|
||
* // => [5, 15]
|
||
*
|
||
* console.log(evens);
|
||
* // => [10, 20]
|
||
*/
|
||
var pullAt = restParam(function(array, indexes) {
|
||
indexes = baseFlatten(indexes);
|
||
|
||
var result = baseAt(array, indexes);
|
||
basePullAt(array, indexes.sort(baseCompareAscending));
|
||
return result;
|
||
});
|
||
|
||
/**
|
||
* Removes all elements from `array` that `predicate` returns truthy for
|
||
* and returns an array of the removed elements. The predicate is bound to
|
||
* `thisArg` and invoked with three arguments: (value, index, array).
|
||
*
|
||
* If a property name is provided for `predicate` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `predicate` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* **Note:** Unlike `_.filter`, this method mutates `array`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to modify.
|
||
* @param {Function|Object|string} [predicate=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {Array} Returns the new array of removed elements.
|
||
* @example
|
||
*
|
||
* var array = [1, 2, 3, 4];
|
||
* var evens = _.remove(array, function(n) {
|
||
* return n % 2 == 0;
|
||
* });
|
||
*
|
||
* console.log(array);
|
||
* // => [1, 3]
|
||
*
|
||
* console.log(evens);
|
||
* // => [2, 4]
|
||
*/
|
||
function remove(array, predicate, thisArg) {
|
||
var result = [];
|
||
if (!(array && array.length)) {
|
||
return result;
|
||
}
|
||
var index = -1,
|
||
indexes = [],
|
||
length = array.length;
|
||
|
||
predicate = getCallback(predicate, thisArg, 3);
|
||
while (++index < length) {
|
||
var value = array[index];
|
||
if (predicate(value, index, array)) {
|
||
result.push(value);
|
||
indexes.push(index);
|
||
}
|
||
}
|
||
basePullAt(array, indexes);
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Gets all but the first element of `array`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias tail
|
||
* @category Array
|
||
* @param {Array} array The array to query.
|
||
* @returns {Array} Returns the slice of `array`.
|
||
* @example
|
||
*
|
||
* _.rest([1, 2, 3]);
|
||
* // => [2, 3]
|
||
*/
|
||
function rest(array) {
|
||
return drop(array, 1);
|
||
}
|
||
|
||
/**
|
||
* Creates a slice of `array` from `start` up to, but not including, `end`.
|
||
*
|
||
* **Note:** This method is used instead of `Array#slice` to support node
|
||
* lists in IE < 9 and to ensure dense arrays are returned.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to slice.
|
||
* @param {number} [start=0] The start position.
|
||
* @param {number} [end=array.length] The end position.
|
||
* @returns {Array} Returns the slice of `array`.
|
||
*/
|
||
function slice(array, start, end) {
|
||
var length = array ? array.length : 0;
|
||
if (!length) {
|
||
return [];
|
||
}
|
||
if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
|
||
start = 0;
|
||
end = length;
|
||
}
|
||
return baseSlice(array, start, end);
|
||
}
|
||
|
||
/**
|
||
* Uses a binary search to determine the lowest index at which `value` should
|
||
* be inserted into `array` in order to maintain its sort order. If an iteratee
|
||
* function is provided it is invoked for `value` and each element of `array`
|
||
* to compute their sort ranking. The iteratee is bound to `thisArg` and
|
||
* invoked with one argument; (value).
|
||
*
|
||
* If a property name is provided for `iteratee` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `iteratee` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The sorted array to inspect.
|
||
* @param {*} value The value to evaluate.
|
||
* @param {Function|Object|string} [iteratee=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {number} Returns the index at which `value` should be inserted
|
||
* into `array`.
|
||
* @example
|
||
*
|
||
* _.sortedIndex([30, 50], 40);
|
||
* // => 1
|
||
*
|
||
* _.sortedIndex([4, 4, 5, 5], 5);
|
||
* // => 2
|
||
*
|
||
* var dict = { 'data': { 'thirty': 30, 'forty': 40, 'fifty': 50 } };
|
||
*
|
||
* // using an iteratee function
|
||
* _.sortedIndex(['thirty', 'fifty'], 'forty', function(word) {
|
||
* return this.data[word];
|
||
* }, dict);
|
||
* // => 1
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
|
||
* // => 1
|
||
*/
|
||
var sortedIndex = createSortedIndex();
|
||
|
||
/**
|
||
* This method is like `_.sortedIndex` except that it returns the highest
|
||
* index at which `value` should be inserted into `array` in order to
|
||
* maintain its sort order.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The sorted array to inspect.
|
||
* @param {*} value The value to evaluate.
|
||
* @param {Function|Object|string} [iteratee=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {number} Returns the index at which `value` should be inserted
|
||
* into `array`.
|
||
* @example
|
||
*
|
||
* _.sortedLastIndex([4, 4, 5, 5], 5);
|
||
* // => 4
|
||
*/
|
||
var sortedLastIndex = createSortedIndex(true);
|
||
|
||
/**
|
||
* Creates a slice of `array` with `n` elements taken from the beginning.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to query.
|
||
* @param {number} [n=1] The number of elements to take.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {Array} Returns the slice of `array`.
|
||
* @example
|
||
*
|
||
* _.take([1, 2, 3]);
|
||
* // => [1]
|
||
*
|
||
* _.take([1, 2, 3], 2);
|
||
* // => [1, 2]
|
||
*
|
||
* _.take([1, 2, 3], 5);
|
||
* // => [1, 2, 3]
|
||
*
|
||
* _.take([1, 2, 3], 0);
|
||
* // => []
|
||
*/
|
||
function take(array, n, guard) {
|
||
var length = array ? array.length : 0;
|
||
if (!length) {
|
||
return [];
|
||
}
|
||
if (guard ? isIterateeCall(array, n, guard) : n == null) {
|
||
n = 1;
|
||
}
|
||
return baseSlice(array, 0, n < 0 ? 0 : n);
|
||
}
|
||
|
||
/**
|
||
* Creates a slice of `array` with `n` elements taken from the end.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to query.
|
||
* @param {number} [n=1] The number of elements to take.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {Array} Returns the slice of `array`.
|
||
* @example
|
||
*
|
||
* _.takeRight([1, 2, 3]);
|
||
* // => [3]
|
||
*
|
||
* _.takeRight([1, 2, 3], 2);
|
||
* // => [2, 3]
|
||
*
|
||
* _.takeRight([1, 2, 3], 5);
|
||
* // => [1, 2, 3]
|
||
*
|
||
* _.takeRight([1, 2, 3], 0);
|
||
* // => []
|
||
*/
|
||
function takeRight(array, n, guard) {
|
||
var length = array ? array.length : 0;
|
||
if (!length) {
|
||
return [];
|
||
}
|
||
if (guard ? isIterateeCall(array, n, guard) : n == null) {
|
||
n = 1;
|
||
}
|
||
n = length - (+n || 0);
|
||
return baseSlice(array, n < 0 ? 0 : n);
|
||
}
|
||
|
||
/**
|
||
* Creates a slice of `array` with elements taken from the end. Elements are
|
||
* taken until `predicate` returns falsey. The predicate is bound to `thisArg`
|
||
* and invoked with three arguments: (value, index, array).
|
||
*
|
||
* If a property name is provided for `predicate` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `predicate` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to query.
|
||
* @param {Function|Object|string} [predicate=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {Array} Returns the slice of `array`.
|
||
* @example
|
||
*
|
||
* _.takeRightWhile([1, 2, 3], function(n) {
|
||
* return n > 1;
|
||
* });
|
||
* // => [2, 3]
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'active': true },
|
||
* { 'user': 'fred', 'active': false },
|
||
* { 'user': 'pebbles', 'active': false }
|
||
* ];
|
||
*
|
||
* // using the `_.matches` callback shorthand
|
||
* _.pluck(_.takeRightWhile(users, { 'user': 'pebbles', 'active': false }), 'user');
|
||
* // => ['pebbles']
|
||
*
|
||
* // using the `_.matchesProperty` callback shorthand
|
||
* _.pluck(_.takeRightWhile(users, 'active', false), 'user');
|
||
* // => ['fred', 'pebbles']
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.pluck(_.takeRightWhile(users, 'active'), 'user');
|
||
* // => []
|
||
*/
|
||
function takeRightWhile(array, predicate, thisArg) {
|
||
return (array && array.length)
|
||
? baseWhile(array, getCallback(predicate, thisArg, 3), false, true)
|
||
: [];
|
||
}
|
||
|
||
/**
|
||
* Creates a slice of `array` with elements taken from the beginning. Elements
|
||
* are taken until `predicate` returns falsey. The predicate is bound to
|
||
* `thisArg` and invoked with three arguments: (value, index, array).
|
||
*
|
||
* If a property name is provided for `predicate` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `predicate` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to query.
|
||
* @param {Function|Object|string} [predicate=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {Array} Returns the slice of `array`.
|
||
* @example
|
||
*
|
||
* _.takeWhile([1, 2, 3], function(n) {
|
||
* return n < 3;
|
||
* });
|
||
* // => [1, 2]
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'active': false },
|
||
* { 'user': 'fred', 'active': false},
|
||
* { 'user': 'pebbles', 'active': true }
|
||
* ];
|
||
*
|
||
* // using the `_.matches` callback shorthand
|
||
* _.pluck(_.takeWhile(users, { 'user': 'barney', 'active': false }), 'user');
|
||
* // => ['barney']
|
||
*
|
||
* // using the `_.matchesProperty` callback shorthand
|
||
* _.pluck(_.takeWhile(users, 'active', false), 'user');
|
||
* // => ['barney', 'fred']
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.pluck(_.takeWhile(users, 'active'), 'user');
|
||
* // => []
|
||
*/
|
||
function takeWhile(array, predicate, thisArg) {
|
||
return (array && array.length)
|
||
? baseWhile(array, getCallback(predicate, thisArg, 3))
|
||
: [];
|
||
}
|
||
|
||
/**
|
||
* Creates an array of unique values, in order, from all of the provided arrays
|
||
* using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
|
||
* for equality comparisons.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {...Array} [arrays] The arrays to inspect.
|
||
* @returns {Array} Returns the new array of combined values.
|
||
* @example
|
||
*
|
||
* _.union([1, 2], [4, 2], [2, 1]);
|
||
* // => [1, 2, 4]
|
||
*/
|
||
var union = restParam(function(arrays) {
|
||
return baseUniq(baseFlatten(arrays, false, true));
|
||
});
|
||
|
||
/**
|
||
* Creates a duplicate-free version of an array, using
|
||
* [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
|
||
* for equality comparisons, in which only the first occurence of each element
|
||
* is kept. Providing `true` for `isSorted` performs a faster search algorithm
|
||
* for sorted arrays. If an iteratee function is provided it is invoked for
|
||
* each element in the array to generate the criterion by which uniqueness
|
||
* is computed. The `iteratee` is bound to `thisArg` and invoked with three
|
||
* arguments: (value, index, array).
|
||
*
|
||
* If a property name is provided for `iteratee` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `iteratee` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias unique
|
||
* @category Array
|
||
* @param {Array} array The array to inspect.
|
||
* @param {boolean} [isSorted] Specify the array is sorted.
|
||
* @param {Function|Object|string} [iteratee] The function invoked per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Array} Returns the new duplicate-value-free array.
|
||
* @example
|
||
*
|
||
* _.uniq([2, 1, 2]);
|
||
* // => [2, 1]
|
||
*
|
||
* // using `isSorted`
|
||
* _.uniq([1, 1, 2], true);
|
||
* // => [1, 2]
|
||
*
|
||
* // using an iteratee function
|
||
* _.uniq([1, 2.5, 1.5, 2], function(n) {
|
||
* return this.floor(n);
|
||
* }, Math);
|
||
* // => [1, 2.5]
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
|
||
* // => [{ 'x': 1 }, { 'x': 2 }]
|
||
*/
|
||
function uniq(array, isSorted, iteratee, thisArg) {
|
||
var length = array ? array.length : 0;
|
||
if (!length) {
|
||
return [];
|
||
}
|
||
if (isSorted != null && typeof isSorted != 'boolean') {
|
||
thisArg = iteratee;
|
||
iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted;
|
||
isSorted = false;
|
||
}
|
||
var callback = getCallback();
|
||
if (!(iteratee == null && callback === baseCallback)) {
|
||
iteratee = callback(iteratee, thisArg, 3);
|
||
}
|
||
return (isSorted && getIndexOf() == baseIndexOf)
|
||
? sortedUniq(array, iteratee)
|
||
: baseUniq(array, iteratee);
|
||
}
|
||
|
||
/**
|
||
* This method is like `_.zip` except that it accepts an array of grouped
|
||
* elements and creates an array regrouping the elements to their pre-zip
|
||
* configuration.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array of grouped elements to process.
|
||
* @returns {Array} Returns the new array of regrouped elements.
|
||
* @example
|
||
*
|
||
* var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]);
|
||
* // => [['fred', 30, true], ['barney', 40, false]]
|
||
*
|
||
* _.unzip(zipped);
|
||
* // => [['fred', 'barney'], [30, 40], [true, false]]
|
||
*/
|
||
function unzip(array) {
|
||
if (!(array && array.length)) {
|
||
return [];
|
||
}
|
||
var index = -1,
|
||
length = 0;
|
||
|
||
array = arrayFilter(array, function(group) {
|
||
if (isArrayLike(group)) {
|
||
length = nativeMax(group.length, length);
|
||
return true;
|
||
}
|
||
});
|
||
var result = Array(length);
|
||
while (++index < length) {
|
||
result[index] = arrayMap(array, baseProperty(index));
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* This method is like `_.unzip` except that it accepts an iteratee to specify
|
||
* how regrouped values should be combined. The `iteratee` is bound to `thisArg`
|
||
* and invoked with four arguments: (accumulator, value, index, group).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array of grouped elements to process.
|
||
* @param {Function} [iteratee] The function to combine regrouped values.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Array} Returns the new array of regrouped elements.
|
||
* @example
|
||
*
|
||
* var zipped = _.zip([1, 2], [10, 20], [100, 200]);
|
||
* // => [[1, 10, 100], [2, 20, 200]]
|
||
*
|
||
* _.unzipWith(zipped, _.add);
|
||
* // => [3, 30, 300]
|
||
*/
|
||
function unzipWith(array, iteratee, thisArg) {
|
||
var length = array ? array.length : 0;
|
||
if (!length) {
|
||
return [];
|
||
}
|
||
var result = unzip(array);
|
||
if (iteratee == null) {
|
||
return result;
|
||
}
|
||
iteratee = bindCallback(iteratee, thisArg, 4);
|
||
return arrayMap(result, function(group) {
|
||
return arrayReduce(group, iteratee, undefined, true);
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Creates an array excluding all provided values using
|
||
* [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
|
||
* for equality comparisons.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {Array} array The array to filter.
|
||
* @param {...*} [values] The values to exclude.
|
||
* @returns {Array} Returns the new array of filtered values.
|
||
* @example
|
||
*
|
||
* _.without([1, 2, 1, 3], 1, 2);
|
||
* // => [3]
|
||
*/
|
||
var without = restParam(function(array, values) {
|
||
return isArrayLike(array)
|
||
? baseDifference(array, values)
|
||
: [];
|
||
});
|
||
|
||
/**
|
||
* Creates an array of unique values that is the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
|
||
* of the provided arrays.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {...Array} [arrays] The arrays to inspect.
|
||
* @returns {Array} Returns the new array of values.
|
||
* @example
|
||
*
|
||
* _.xor([1, 2], [4, 2]);
|
||
* // => [1, 4]
|
||
*/
|
||
function xor() {
|
||
var index = -1,
|
||
length = arguments.length;
|
||
|
||
while (++index < length) {
|
||
var array = arguments[index];
|
||
if (isArrayLike(array)) {
|
||
var result = result
|
||
? arrayPush(baseDifference(result, array), baseDifference(array, result))
|
||
: array;
|
||
}
|
||
}
|
||
return result ? baseUniq(result) : [];
|
||
}
|
||
|
||
/**
|
||
* Creates an array of grouped elements, the first of which contains the first
|
||
* elements of the given arrays, the second of which contains the second elements
|
||
* of the given arrays, and so on.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {...Array} [arrays] The arrays to process.
|
||
* @returns {Array} Returns the new array of grouped elements.
|
||
* @example
|
||
*
|
||
* _.zip(['fred', 'barney'], [30, 40], [true, false]);
|
||
* // => [['fred', 30, true], ['barney', 40, false]]
|
||
*/
|
||
var zip = restParam(unzip);
|
||
|
||
/**
|
||
* The inverse of `_.pairs`; this method returns an object composed from arrays
|
||
* of property names and values. Provide either a single two dimensional array,
|
||
* e.g. `[[key1, value1], [key2, value2]]` or two arrays, one of property names
|
||
* and one of corresponding values.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias object
|
||
* @category Array
|
||
* @param {Array} props The property names.
|
||
* @param {Array} [values=[]] The property values.
|
||
* @returns {Object} Returns the new object.
|
||
* @example
|
||
*
|
||
* _.zipObject([['fred', 30], ['barney', 40]]);
|
||
* // => { 'fred': 30, 'barney': 40 }
|
||
*
|
||
* _.zipObject(['fred', 'barney'], [30, 40]);
|
||
* // => { 'fred': 30, 'barney': 40 }
|
||
*/
|
||
function zipObject(props, values) {
|
||
var index = -1,
|
||
length = props ? props.length : 0,
|
||
result = {};
|
||
|
||
if (length && !values && !isArray(props[0])) {
|
||
values = [];
|
||
}
|
||
while (++index < length) {
|
||
var key = props[index];
|
||
if (values) {
|
||
result[key] = values[index];
|
||
} else if (key) {
|
||
result[key[0]] = key[1];
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* This method is like `_.zip` except that it accepts an iteratee to specify
|
||
* how grouped values should be combined. The `iteratee` is bound to `thisArg`
|
||
* and invoked with four arguments: (accumulator, value, index, group).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Array
|
||
* @param {...Array} [arrays] The arrays to process.
|
||
* @param {Function} [iteratee] The function to combine grouped values.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Array} Returns the new array of grouped elements.
|
||
* @example
|
||
*
|
||
* _.zipWith([1, 2], [10, 20], [100, 200], _.add);
|
||
* // => [111, 222]
|
||
*/
|
||
var zipWith = restParam(function(arrays) {
|
||
var length = arrays.length,
|
||
iteratee = length > 2 ? arrays[length - 2] : undefined,
|
||
thisArg = length > 1 ? arrays[length - 1] : undefined;
|
||
|
||
if (length > 2 && typeof iteratee == 'function') {
|
||
length -= 2;
|
||
} else {
|
||
iteratee = (length > 1 && typeof thisArg == 'function') ? (--length, thisArg) : undefined;
|
||
thisArg = undefined;
|
||
}
|
||
arrays.length = length;
|
||
return unzipWith(arrays, iteratee, thisArg);
|
||
});
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Creates a `lodash` object that wraps `value` with explicit method
|
||
* chaining enabled.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Chain
|
||
* @param {*} value The value to wrap.
|
||
* @returns {Object} Returns the new `lodash` wrapper instance.
|
||
* @example
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'age': 36 },
|
||
* { 'user': 'fred', 'age': 40 },
|
||
* { 'user': 'pebbles', 'age': 1 }
|
||
* ];
|
||
*
|
||
* var youngest = _.chain(users)
|
||
* .sortBy('age')
|
||
* .map(function(chr) {
|
||
* return chr.user + ' is ' + chr.age;
|
||
* })
|
||
* .first()
|
||
* .value();
|
||
* // => 'pebbles is 1'
|
||
*/
|
||
function chain(value) {
|
||
var result = lodash(value);
|
||
result.__chain__ = true;
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* This method invokes `interceptor` and returns `value`. The interceptor is
|
||
* bound to `thisArg` and invoked with one argument; (value). The purpose of
|
||
* this method is to "tap into" a method chain in order to perform operations
|
||
* on intermediate results within the chain.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Chain
|
||
* @param {*} value The value to provide to `interceptor`.
|
||
* @param {Function} interceptor The function to invoke.
|
||
* @param {*} [thisArg] The `this` binding of `interceptor`.
|
||
* @returns {*} Returns `value`.
|
||
* @example
|
||
*
|
||
* _([1, 2, 3])
|
||
* .tap(function(array) {
|
||
* array.pop();
|
||
* })
|
||
* .reverse()
|
||
* .value();
|
||
* // => [2, 1]
|
||
*/
|
||
function tap(value, interceptor, thisArg) {
|
||
interceptor.call(thisArg, value);
|
||
return value;
|
||
}
|
||
|
||
/**
|
||
* This method is like `_.tap` except that it returns the result of `interceptor`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Chain
|
||
* @param {*} value The value to provide to `interceptor`.
|
||
* @param {Function} interceptor The function to invoke.
|
||
* @param {*} [thisArg] The `this` binding of `interceptor`.
|
||
* @returns {*} Returns the result of `interceptor`.
|
||
* @example
|
||
*
|
||
* _(' abc ')
|
||
* .chain()
|
||
* .trim()
|
||
* .thru(function(value) {
|
||
* return [value];
|
||
* })
|
||
* .value();
|
||
* // => ['abc']
|
||
*/
|
||
function thru(value, interceptor, thisArg) {
|
||
return interceptor.call(thisArg, value);
|
||
}
|
||
|
||
/**
|
||
* Enables explicit method chaining on the wrapper object.
|
||
*
|
||
* @name chain
|
||
* @memberOf _
|
||
* @category Chain
|
||
* @returns {Object} Returns the new `lodash` wrapper instance.
|
||
* @example
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'age': 36 },
|
||
* { 'user': 'fred', 'age': 40 }
|
||
* ];
|
||
*
|
||
* // without explicit chaining
|
||
* _(users).first();
|
||
* // => { 'user': 'barney', 'age': 36 }
|
||
*
|
||
* // with explicit chaining
|
||
* _(users).chain()
|
||
* .first()
|
||
* .pick('user')
|
||
* .value();
|
||
* // => { 'user': 'barney' }
|
||
*/
|
||
function wrapperChain() {
|
||
return chain(this);
|
||
}
|
||
|
||
/**
|
||
* Executes the chained sequence and returns the wrapped result.
|
||
*
|
||
* @name commit
|
||
* @memberOf _
|
||
* @category Chain
|
||
* @returns {Object} Returns the new `lodash` wrapper instance.
|
||
* @example
|
||
*
|
||
* var array = [1, 2];
|
||
* var wrapped = _(array).push(3);
|
||
*
|
||
* console.log(array);
|
||
* // => [1, 2]
|
||
*
|
||
* wrapped = wrapped.commit();
|
||
* console.log(array);
|
||
* // => [1, 2, 3]
|
||
*
|
||
* wrapped.last();
|
||
* // => 3
|
||
*
|
||
* console.log(array);
|
||
* // => [1, 2, 3]
|
||
*/
|
||
function wrapperCommit() {
|
||
return new LodashWrapper(this.value(), this.__chain__);
|
||
}
|
||
|
||
/**
|
||
* Creates a new array joining a wrapped array with any additional arrays
|
||
* and/or values.
|
||
*
|
||
* @name concat
|
||
* @memberOf _
|
||
* @category Chain
|
||
* @param {...*} [values] The values to concatenate.
|
||
* @returns {Array} Returns the new concatenated array.
|
||
* @example
|
||
*
|
||
* var array = [1];
|
||
* var wrapped = _(array).concat(2, [3], [[4]]);
|
||
*
|
||
* console.log(wrapped.value());
|
||
* // => [1, 2, 3, [4]]
|
||
*
|
||
* console.log(array);
|
||
* // => [1]
|
||
*/
|
||
var wrapperConcat = restParam(function(values) {
|
||
values = baseFlatten(values);
|
||
return this.thru(function(array) {
|
||
return arrayConcat(isArray(array) ? array : [toObject(array)], values);
|
||
});
|
||
});
|
||
|
||
/**
|
||
* Creates a clone of the chained sequence planting `value` as the wrapped value.
|
||
*
|
||
* @name plant
|
||
* @memberOf _
|
||
* @category Chain
|
||
* @returns {Object} Returns the new `lodash` wrapper instance.
|
||
* @example
|
||
*
|
||
* var array = [1, 2];
|
||
* var wrapped = _(array).map(function(value) {
|
||
* return Math.pow(value, 2);
|
||
* });
|
||
*
|
||
* var other = [3, 4];
|
||
* var otherWrapped = wrapped.plant(other);
|
||
*
|
||
* otherWrapped.value();
|
||
* // => [9, 16]
|
||
*
|
||
* wrapped.value();
|
||
* // => [1, 4]
|
||
*/
|
||
function wrapperPlant(value) {
|
||
var result,
|
||
parent = this;
|
||
|
||
while (parent instanceof baseLodash) {
|
||
var clone = wrapperClone(parent);
|
||
if (result) {
|
||
previous.__wrapped__ = clone;
|
||
} else {
|
||
result = clone;
|
||
}
|
||
var previous = clone;
|
||
parent = parent.__wrapped__;
|
||
}
|
||
previous.__wrapped__ = value;
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Reverses the wrapped array so the first element becomes the last, the
|
||
* second element becomes the second to last, and so on.
|
||
*
|
||
* **Note:** This method mutates the wrapped array.
|
||
*
|
||
* @name reverse
|
||
* @memberOf _
|
||
* @category Chain
|
||
* @returns {Object} Returns the new reversed `lodash` wrapper instance.
|
||
* @example
|
||
*
|
||
* var array = [1, 2, 3];
|
||
*
|
||
* _(array).reverse().value()
|
||
* // => [3, 2, 1]
|
||
*
|
||
* console.log(array);
|
||
* // => [3, 2, 1]
|
||
*/
|
||
function wrapperReverse() {
|
||
var value = this.__wrapped__;
|
||
|
||
var interceptor = function(value) {
|
||
return (wrapped && wrapped.__dir__ < 0) ? value : value.reverse();
|
||
};
|
||
if (value instanceof LazyWrapper) {
|
||
var wrapped = value;
|
||
if (this.__actions__.length) {
|
||
wrapped = new LazyWrapper(this);
|
||
}
|
||
wrapped = wrapped.reverse();
|
||
wrapped.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
|
||
return new LodashWrapper(wrapped, this.__chain__);
|
||
}
|
||
return this.thru(interceptor);
|
||
}
|
||
|
||
/**
|
||
* Produces the result of coercing the unwrapped value to a string.
|
||
*
|
||
* @name toString
|
||
* @memberOf _
|
||
* @category Chain
|
||
* @returns {string} Returns the coerced string value.
|
||
* @example
|
||
*
|
||
* _([1, 2, 3]).toString();
|
||
* // => '1,2,3'
|
||
*/
|
||
function wrapperToString() {
|
||
return (this.value() + '');
|
||
}
|
||
|
||
/**
|
||
* Executes the chained sequence to extract the unwrapped value.
|
||
*
|
||
* @name value
|
||
* @memberOf _
|
||
* @alias run, toJSON, valueOf
|
||
* @category Chain
|
||
* @returns {*} Returns the resolved unwrapped value.
|
||
* @example
|
||
*
|
||
* _([1, 2, 3]).value();
|
||
* // => [1, 2, 3]
|
||
*/
|
||
function wrapperValue() {
|
||
return baseWrapperValue(this.__wrapped__, this.__actions__);
|
||
}
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Creates an array of elements corresponding to the given keys, or indexes,
|
||
* of `collection`. Keys may be specified as individual arguments or as arrays
|
||
* of keys.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {...(number|number[]|string|string[])} [props] The property names
|
||
* or indexes of elements to pick, specified individually or in arrays.
|
||
* @returns {Array} Returns the new array of picked elements.
|
||
* @example
|
||
*
|
||
* _.at(['a', 'b', 'c'], [0, 2]);
|
||
* // => ['a', 'c']
|
||
*
|
||
* _.at(['barney', 'fred', 'pebbles'], 0, 2);
|
||
* // => ['barney', 'pebbles']
|
||
*/
|
||
var at = restParam(function(collection, props) {
|
||
return baseAt(collection, baseFlatten(props));
|
||
});
|
||
|
||
/**
|
||
* Creates an object composed of keys generated from the results of running
|
||
* each element of `collection` through `iteratee`. The corresponding value
|
||
* of each key is the number of times the key was returned by `iteratee`.
|
||
* The `iteratee` is bound to `thisArg` and invoked with three arguments:
|
||
* (value, index|key, collection).
|
||
*
|
||
* If a property name is provided for `iteratee` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `iteratee` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function|Object|string} [iteratee=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Object} Returns the composed aggregate object.
|
||
* @example
|
||
*
|
||
* _.countBy([4.3, 6.1, 6.4], function(n) {
|
||
* return Math.floor(n);
|
||
* });
|
||
* // => { '4': 1, '6': 2 }
|
||
*
|
||
* _.countBy([4.3, 6.1, 6.4], function(n) {
|
||
* return this.floor(n);
|
||
* }, Math);
|
||
* // => { '4': 1, '6': 2 }
|
||
*
|
||
* _.countBy(['one', 'two', 'three'], 'length');
|
||
* // => { '3': 2, '5': 1 }
|
||
*/
|
||
var countBy = createAggregator(function(result, value, key) {
|
||
hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1);
|
||
});
|
||
|
||
/**
|
||
* Checks if `predicate` returns truthy for **all** elements of `collection`.
|
||
* The predicate is bound to `thisArg` and invoked with three arguments:
|
||
* (value, index|key, collection).
|
||
*
|
||
* If a property name is provided for `predicate` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `predicate` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias all
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function|Object|string} [predicate=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {boolean} Returns `true` if all elements pass the predicate check,
|
||
* else `false`.
|
||
* @example
|
||
*
|
||
* _.every([true, 1, null, 'yes'], Boolean);
|
||
* // => false
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'active': false },
|
||
* { 'user': 'fred', 'active': false }
|
||
* ];
|
||
*
|
||
* // using the `_.matches` callback shorthand
|
||
* _.every(users, { 'user': 'barney', 'active': false });
|
||
* // => false
|
||
*
|
||
* // using the `_.matchesProperty` callback shorthand
|
||
* _.every(users, 'active', false);
|
||
* // => true
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.every(users, 'active');
|
||
* // => false
|
||
*/
|
||
function every(collection, predicate, thisArg) {
|
||
var func = isArray(collection) ? arrayEvery : baseEvery;
|
||
if (thisArg && isIterateeCall(collection, predicate, thisArg)) {
|
||
predicate = undefined;
|
||
}
|
||
if (typeof predicate != 'function' || thisArg !== undefined) {
|
||
predicate = getCallback(predicate, thisArg, 3);
|
||
}
|
||
return func(collection, predicate);
|
||
}
|
||
|
||
/**
|
||
* Iterates over elements of `collection`, returning an array of all elements
|
||
* `predicate` returns truthy for. The predicate is bound to `thisArg` and
|
||
* invoked with three arguments: (value, index|key, collection).
|
||
*
|
||
* If a property name is provided for `predicate` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `predicate` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias select
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function|Object|string} [predicate=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {Array} Returns the new filtered array.
|
||
* @example
|
||
*
|
||
* _.filter([4, 5, 6], function(n) {
|
||
* return n % 2 == 0;
|
||
* });
|
||
* // => [4, 6]
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'age': 36, 'active': true },
|
||
* { 'user': 'fred', 'age': 40, 'active': false }
|
||
* ];
|
||
*
|
||
* // using the `_.matches` callback shorthand
|
||
* _.pluck(_.filter(users, { 'age': 36, 'active': true }), 'user');
|
||
* // => ['barney']
|
||
*
|
||
* // using the `_.matchesProperty` callback shorthand
|
||
* _.pluck(_.filter(users, 'active', false), 'user');
|
||
* // => ['fred']
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.pluck(_.filter(users, 'active'), 'user');
|
||
* // => ['barney']
|
||
*/
|
||
function filter(collection, predicate, thisArg) {
|
||
var func = isArray(collection) ? arrayFilter : baseFilter;
|
||
predicate = getCallback(predicate, thisArg, 3);
|
||
return func(collection, predicate);
|
||
}
|
||
|
||
/**
|
||
* Iterates over elements of `collection`, returning the first element
|
||
* `predicate` returns truthy for. The predicate is bound to `thisArg` and
|
||
* invoked with three arguments: (value, index|key, collection).
|
||
*
|
||
* If a property name is provided for `predicate` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `predicate` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias detect
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to search.
|
||
* @param {Function|Object|string} [predicate=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {*} Returns the matched element, else `undefined`.
|
||
* @example
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'age': 36, 'active': true },
|
||
* { 'user': 'fred', 'age': 40, 'active': false },
|
||
* { 'user': 'pebbles', 'age': 1, 'active': true }
|
||
* ];
|
||
*
|
||
* _.result(_.find(users, function(chr) {
|
||
* return chr.age < 40;
|
||
* }), 'user');
|
||
* // => 'barney'
|
||
*
|
||
* // using the `_.matches` callback shorthand
|
||
* _.result(_.find(users, { 'age': 1, 'active': true }), 'user');
|
||
* // => 'pebbles'
|
||
*
|
||
* // using the `_.matchesProperty` callback shorthand
|
||
* _.result(_.find(users, 'active', false), 'user');
|
||
* // => 'fred'
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.result(_.find(users, 'active'), 'user');
|
||
* // => 'barney'
|
||
*/
|
||
var find = createFind(baseEach);
|
||
|
||
/**
|
||
* This method is like `_.find` except that it iterates over elements of
|
||
* `collection` from right to left.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to search.
|
||
* @param {Function|Object|string} [predicate=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {*} Returns the matched element, else `undefined`.
|
||
* @example
|
||
*
|
||
* _.findLast([1, 2, 3, 4], function(n) {
|
||
* return n % 2 == 1;
|
||
* });
|
||
* // => 3
|
||
*/
|
||
var findLast = createFind(baseEachRight, true);
|
||
|
||
/**
|
||
* Performs a deep comparison between each element in `collection` and the
|
||
* source object, returning the first element that has equivalent property
|
||
* values.
|
||
*
|
||
* **Note:** This method supports comparing arrays, booleans, `Date` objects,
|
||
* numbers, `Object` objects, regexes, and strings. Objects are compared by
|
||
* their own, not inherited, enumerable properties. For comparing a single
|
||
* own or inherited property value see `_.matchesProperty`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to search.
|
||
* @param {Object} source The object of property values to match.
|
||
* @returns {*} Returns the matched element, else `undefined`.
|
||
* @example
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'age': 36, 'active': true },
|
||
* { 'user': 'fred', 'age': 40, 'active': false }
|
||
* ];
|
||
*
|
||
* _.result(_.findWhere(users, { 'age': 36, 'active': true }), 'user');
|
||
* // => 'barney'
|
||
*
|
||
* _.result(_.findWhere(users, { 'age': 40, 'active': false }), 'user');
|
||
* // => 'fred'
|
||
*/
|
||
function findWhere(collection, source) {
|
||
return find(collection, baseMatches(source));
|
||
}
|
||
|
||
/**
|
||
* Iterates over elements of `collection` invoking `iteratee` for each element.
|
||
* The `iteratee` is bound to `thisArg` and invoked with three arguments:
|
||
* (value, index|key, collection). Iteratee functions may exit iteration early
|
||
* by explicitly returning `false`.
|
||
*
|
||
* **Note:** As with other "Collections" methods, objects with a "length" property
|
||
* are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
|
||
* may be used for object iteration.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias each
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Array|Object|string} Returns `collection`.
|
||
* @example
|
||
*
|
||
* _([1, 2]).forEach(function(n) {
|
||
* console.log(n);
|
||
* }).value();
|
||
* // => logs each value from left to right and returns the array
|
||
*
|
||
* _.forEach({ 'a': 1, 'b': 2 }, function(n, key) {
|
||
* console.log(n, key);
|
||
* });
|
||
* // => logs each value-key pair and returns the object (iteration order is not guaranteed)
|
||
*/
|
||
var forEach = createForEach(arrayEach, baseEach);
|
||
|
||
/**
|
||
* This method is like `_.forEach` except that it iterates over elements of
|
||
* `collection` from right to left.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias eachRight
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Array|Object|string} Returns `collection`.
|
||
* @example
|
||
*
|
||
* _([1, 2]).forEachRight(function(n) {
|
||
* console.log(n);
|
||
* }).value();
|
||
* // => logs each value from right to left and returns the array
|
||
*/
|
||
var forEachRight = createForEach(arrayEachRight, baseEachRight);
|
||
|
||
/**
|
||
* Creates an object composed of keys generated from the results of running
|
||
* each element of `collection` through `iteratee`. The corresponding value
|
||
* of each key is an array of the elements responsible for generating the key.
|
||
* The `iteratee` is bound to `thisArg` and invoked with three arguments:
|
||
* (value, index|key, collection).
|
||
*
|
||
* If a property name is provided for `iteratee` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `iteratee` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function|Object|string} [iteratee=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Object} Returns the composed aggregate object.
|
||
* @example
|
||
*
|
||
* _.groupBy([4.2, 6.1, 6.4], function(n) {
|
||
* return Math.floor(n);
|
||
* });
|
||
* // => { '4': [4.2], '6': [6.1, 6.4] }
|
||
*
|
||
* _.groupBy([4.2, 6.1, 6.4], function(n) {
|
||
* return this.floor(n);
|
||
* }, Math);
|
||
* // => { '4': [4.2], '6': [6.1, 6.4] }
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.groupBy(['one', 'two', 'three'], 'length');
|
||
* // => { '3': ['one', 'two'], '5': ['three'] }
|
||
*/
|
||
var groupBy = createAggregator(function(result, value, key) {
|
||
if (hasOwnProperty.call(result, key)) {
|
||
result[key].push(value);
|
||
} else {
|
||
result[key] = [value];
|
||
}
|
||
});
|
||
|
||
/**
|
||
* Checks if `value` is in `collection` using
|
||
* [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
|
||
* for equality comparisons. If `fromIndex` is negative, it is used as the offset
|
||
* from the end of `collection`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias contains, include
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to search.
|
||
* @param {*} target The value to search for.
|
||
* @param {number} [fromIndex=0] The index to search from.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`.
|
||
* @returns {boolean} Returns `true` if a matching element is found, else `false`.
|
||
* @example
|
||
*
|
||
* _.includes([1, 2, 3], 1);
|
||
* // => true
|
||
*
|
||
* _.includes([1, 2, 3], 1, 2);
|
||
* // => false
|
||
*
|
||
* _.includes({ 'user': 'fred', 'age': 40 }, 'fred');
|
||
* // => true
|
||
*
|
||
* _.includes('pebbles', 'eb');
|
||
* // => true
|
||
*/
|
||
function includes(collection, target, fromIndex, guard) {
|
||
var length = collection ? getLength(collection) : 0;
|
||
if (!isLength(length)) {
|
||
collection = values(collection);
|
||
length = collection.length;
|
||
}
|
||
if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) {
|
||
fromIndex = 0;
|
||
} else {
|
||
fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0);
|
||
}
|
||
return (typeof collection == 'string' || !isArray(collection) && isString(collection))
|
||
? (fromIndex <= length && collection.indexOf(target, fromIndex) > -1)
|
||
: (!!length && getIndexOf(collection, target, fromIndex) > -1);
|
||
}
|
||
|
||
/**
|
||
* Creates an object composed of keys generated from the results of running
|
||
* each element of `collection` through `iteratee`. The corresponding value
|
||
* of each key is the last element responsible for generating the key. The
|
||
* iteratee function is bound to `thisArg` and invoked with three arguments:
|
||
* (value, index|key, collection).
|
||
*
|
||
* If a property name is provided for `iteratee` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `iteratee` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function|Object|string} [iteratee=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Object} Returns the composed aggregate object.
|
||
* @example
|
||
*
|
||
* var keyData = [
|
||
* { 'dir': 'left', 'code': 97 },
|
||
* { 'dir': 'right', 'code': 100 }
|
||
* ];
|
||
*
|
||
* _.indexBy(keyData, 'dir');
|
||
* // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
|
||
*
|
||
* _.indexBy(keyData, function(object) {
|
||
* return String.fromCharCode(object.code);
|
||
* });
|
||
* // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
|
||
*
|
||
* _.indexBy(keyData, function(object) {
|
||
* return this.fromCharCode(object.code);
|
||
* }, String);
|
||
* // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
|
||
*/
|
||
var indexBy = createAggregator(function(result, value, key) {
|
||
result[key] = value;
|
||
});
|
||
|
||
/**
|
||
* Invokes the method at `path` of each element in `collection`, returning
|
||
* an array of the results of each invoked method. Any additional arguments
|
||
* are provided to each invoked method. If `methodName` is a function it is
|
||
* invoked for, and `this` bound to, each element in `collection`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Array|Function|string} path The path of the method to invoke or
|
||
* the function invoked per iteration.
|
||
* @param {...*} [args] The arguments to invoke the method with.
|
||
* @returns {Array} Returns the array of results.
|
||
* @example
|
||
*
|
||
* _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
|
||
* // => [[1, 5, 7], [1, 2, 3]]
|
||
*
|
||
* _.invoke([123, 456], String.prototype.split, '');
|
||
* // => [['1', '2', '3'], ['4', '5', '6']]
|
||
*/
|
||
var invoke = restParam(function(collection, path, args) {
|
||
var index = -1,
|
||
isFunc = typeof path == 'function',
|
||
isProp = isKey(path),
|
||
result = isArrayLike(collection) ? Array(collection.length) : [];
|
||
|
||
baseEach(collection, function(value) {
|
||
var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined);
|
||
result[++index] = func ? func.apply(value, args) : invokePath(value, path, args);
|
||
});
|
||
return result;
|
||
});
|
||
|
||
/**
|
||
* Creates an array of values by running each element in `collection` through
|
||
* `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three
|
||
* arguments: (value, index|key, collection).
|
||
*
|
||
* If a property name is provided for `iteratee` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `iteratee` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* Many lodash methods are guarded to work as iteratees for methods like
|
||
* `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
|
||
*
|
||
* The guarded methods are:
|
||
* `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`,
|
||
* `drop`, `dropRight`, `every`, `fill`, `flatten`, `invert`, `max`, `min`,
|
||
* `parseInt`, `slice`, `sortBy`, `take`, `takeRight`, `template`, `trim`,
|
||
* `trimLeft`, `trimRight`, `trunc`, `random`, `range`, `sample`, `some`,
|
||
* `sum`, `uniq`, and `words`
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias collect
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function|Object|string} [iteratee=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Array} Returns the new mapped array.
|
||
* @example
|
||
*
|
||
* function timesThree(n) {
|
||
* return n * 3;
|
||
* }
|
||
*
|
||
* _.map([1, 2], timesThree);
|
||
* // => [3, 6]
|
||
*
|
||
* _.map({ 'a': 1, 'b': 2 }, timesThree);
|
||
* // => [3, 6] (iteration order is not guaranteed)
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney' },
|
||
* { 'user': 'fred' }
|
||
* ];
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.map(users, 'user');
|
||
* // => ['barney', 'fred']
|
||
*/
|
||
function map(collection, iteratee, thisArg) {
|
||
var func = isArray(collection) ? arrayMap : baseMap;
|
||
iteratee = getCallback(iteratee, thisArg, 3);
|
||
return func(collection, iteratee);
|
||
}
|
||
|
||
/**
|
||
* Creates an array of elements split into two groups, the first of which
|
||
* contains elements `predicate` returns truthy for, while the second of which
|
||
* contains elements `predicate` returns falsey for. The predicate is bound
|
||
* to `thisArg` and invoked with three arguments: (value, index|key, collection).
|
||
*
|
||
* If a property name is provided for `predicate` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `predicate` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function|Object|string} [predicate=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {Array} Returns the array of grouped elements.
|
||
* @example
|
||
*
|
||
* _.partition([1, 2, 3], function(n) {
|
||
* return n % 2;
|
||
* });
|
||
* // => [[1, 3], [2]]
|
||
*
|
||
* _.partition([1.2, 2.3, 3.4], function(n) {
|
||
* return this.floor(n) % 2;
|
||
* }, Math);
|
||
* // => [[1.2, 3.4], [2.3]]
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'age': 36, 'active': false },
|
||
* { 'user': 'fred', 'age': 40, 'active': true },
|
||
* { 'user': 'pebbles', 'age': 1, 'active': false }
|
||
* ];
|
||
*
|
||
* var mapper = function(array) {
|
||
* return _.pluck(array, 'user');
|
||
* };
|
||
*
|
||
* // using the `_.matches` callback shorthand
|
||
* _.map(_.partition(users, { 'age': 1, 'active': false }), mapper);
|
||
* // => [['pebbles'], ['barney', 'fred']]
|
||
*
|
||
* // using the `_.matchesProperty` callback shorthand
|
||
* _.map(_.partition(users, 'active', false), mapper);
|
||
* // => [['barney', 'pebbles'], ['fred']]
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.map(_.partition(users, 'active'), mapper);
|
||
* // => [['fred'], ['barney', 'pebbles']]
|
||
*/
|
||
var partition = createAggregator(function(result, value, key) {
|
||
result[key ? 0 : 1].push(value);
|
||
}, function() { return [[], []]; });
|
||
|
||
/**
|
||
* Gets the property value of `path` from all elements in `collection`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Array|string} path The path of the property to pluck.
|
||
* @returns {Array} Returns the property values.
|
||
* @example
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'age': 36 },
|
||
* { 'user': 'fred', 'age': 40 }
|
||
* ];
|
||
*
|
||
* _.pluck(users, 'user');
|
||
* // => ['barney', 'fred']
|
||
*
|
||
* var userIndex = _.indexBy(users, 'user');
|
||
* _.pluck(userIndex, 'age');
|
||
* // => [36, 40] (iteration order is not guaranteed)
|
||
*/
|
||
function pluck(collection, path) {
|
||
return map(collection, property(path));
|
||
}
|
||
|
||
/**
|
||
* Reduces `collection` to a value which is the accumulated result of running
|
||
* each element in `collection` through `iteratee`, where each successive
|
||
* invocation is supplied the return value of the previous. If `accumulator`
|
||
* is not provided the first element of `collection` is used as the initial
|
||
* value. The `iteratee` is bound to `thisArg` and invoked with four arguments:
|
||
* (accumulator, value, index|key, collection).
|
||
*
|
||
* Many lodash methods are guarded to work as iteratees for methods like
|
||
* `_.reduce`, `_.reduceRight`, and `_.transform`.
|
||
*
|
||
* The guarded methods are:
|
||
* `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `sortByAll`,
|
||
* and `sortByOrder`
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias foldl, inject
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
||
* @param {*} [accumulator] The initial value.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {*} Returns the accumulated value.
|
||
* @example
|
||
*
|
||
* _.reduce([1, 2], function(total, n) {
|
||
* return total + n;
|
||
* });
|
||
* // => 3
|
||
*
|
||
* _.reduce({ 'a': 1, 'b': 2 }, function(result, n, key) {
|
||
* result[key] = n * 3;
|
||
* return result;
|
||
* }, {});
|
||
* // => { 'a': 3, 'b': 6 } (iteration order is not guaranteed)
|
||
*/
|
||
var reduce = createReduce(arrayReduce, baseEach);
|
||
|
||
/**
|
||
* This method is like `_.reduce` except that it iterates over elements of
|
||
* `collection` from right to left.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias foldr
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
||
* @param {*} [accumulator] The initial value.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {*} Returns the accumulated value.
|
||
* @example
|
||
*
|
||
* var array = [[0, 1], [2, 3], [4, 5]];
|
||
*
|
||
* _.reduceRight(array, function(flattened, other) {
|
||
* return flattened.concat(other);
|
||
* }, []);
|
||
* // => [4, 5, 2, 3, 0, 1]
|
||
*/
|
||
var reduceRight = createReduce(arrayReduceRight, baseEachRight);
|
||
|
||
/**
|
||
* The opposite of `_.filter`; this method returns the elements of `collection`
|
||
* that `predicate` does **not** return truthy for.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function|Object|string} [predicate=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {Array} Returns the new filtered array.
|
||
* @example
|
||
*
|
||
* _.reject([1, 2, 3, 4], function(n) {
|
||
* return n % 2 == 0;
|
||
* });
|
||
* // => [1, 3]
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'age': 36, 'active': false },
|
||
* { 'user': 'fred', 'age': 40, 'active': true }
|
||
* ];
|
||
*
|
||
* // using the `_.matches` callback shorthand
|
||
* _.pluck(_.reject(users, { 'age': 40, 'active': true }), 'user');
|
||
* // => ['barney']
|
||
*
|
||
* // using the `_.matchesProperty` callback shorthand
|
||
* _.pluck(_.reject(users, 'active', false), 'user');
|
||
* // => ['fred']
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.pluck(_.reject(users, 'active'), 'user');
|
||
* // => ['barney']
|
||
*/
|
||
function reject(collection, predicate, thisArg) {
|
||
var func = isArray(collection) ? arrayFilter : baseFilter;
|
||
predicate = getCallback(predicate, thisArg, 3);
|
||
return func(collection, function(value, index, collection) {
|
||
return !predicate(value, index, collection);
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Gets a random element or `n` random elements from a collection.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to sample.
|
||
* @param {number} [n] The number of elements to sample.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {*} Returns the random sample(s).
|
||
* @example
|
||
*
|
||
* _.sample([1, 2, 3, 4]);
|
||
* // => 2
|
||
*
|
||
* _.sample([1, 2, 3, 4], 2);
|
||
* // => [3, 1]
|
||
*/
|
||
function sample(collection, n, guard) {
|
||
if (guard ? isIterateeCall(collection, n, guard) : n == null) {
|
||
collection = toIterable(collection);
|
||
var length = collection.length;
|
||
return length > 0 ? collection[baseRandom(0, length - 1)] : undefined;
|
||
}
|
||
var index = -1,
|
||
result = toArray(collection),
|
||
length = result.length,
|
||
lastIndex = length - 1;
|
||
|
||
n = nativeMin(n < 0 ? 0 : (+n || 0), length);
|
||
while (++index < n) {
|
||
var rand = baseRandom(index, lastIndex),
|
||
value = result[rand];
|
||
|
||
result[rand] = result[index];
|
||
result[index] = value;
|
||
}
|
||
result.length = n;
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Creates an array of shuffled values, using a version of the
|
||
* [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to shuffle.
|
||
* @returns {Array} Returns the new shuffled array.
|
||
* @example
|
||
*
|
||
* _.shuffle([1, 2, 3, 4]);
|
||
* // => [4, 1, 3, 2]
|
||
*/
|
||
function shuffle(collection) {
|
||
return sample(collection, POSITIVE_INFINITY);
|
||
}
|
||
|
||
/**
|
||
* Gets the size of `collection` by returning its length for array-like
|
||
* values or the number of own enumerable properties for objects.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to inspect.
|
||
* @returns {number} Returns the size of `collection`.
|
||
* @example
|
||
*
|
||
* _.size([1, 2, 3]);
|
||
* // => 3
|
||
*
|
||
* _.size({ 'a': 1, 'b': 2 });
|
||
* // => 2
|
||
*
|
||
* _.size('pebbles');
|
||
* // => 7
|
||
*/
|
||
function size(collection) {
|
||
var length = collection ? getLength(collection) : 0;
|
||
return isLength(length) ? length : keys(collection).length;
|
||
}
|
||
|
||
/**
|
||
* Checks if `predicate` returns truthy for **any** element of `collection`.
|
||
* The function returns as soon as it finds a passing value and does not iterate
|
||
* over the entire collection. The predicate is bound to `thisArg` and invoked
|
||
* with three arguments: (value, index|key, collection).
|
||
*
|
||
* If a property name is provided for `predicate` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `predicate` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias any
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function|Object|string} [predicate=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {boolean} Returns `true` if any element passes the predicate check,
|
||
* else `false`.
|
||
* @example
|
||
*
|
||
* _.some([null, 0, 'yes', false], Boolean);
|
||
* // => true
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'active': true },
|
||
* { 'user': 'fred', 'active': false }
|
||
* ];
|
||
*
|
||
* // using the `_.matches` callback shorthand
|
||
* _.some(users, { 'user': 'barney', 'active': false });
|
||
* // => false
|
||
*
|
||
* // using the `_.matchesProperty` callback shorthand
|
||
* _.some(users, 'active', false);
|
||
* // => true
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.some(users, 'active');
|
||
* // => true
|
||
*/
|
||
function some(collection, predicate, thisArg) {
|
||
var func = isArray(collection) ? arraySome : baseSome;
|
||
if (thisArg && isIterateeCall(collection, predicate, thisArg)) {
|
||
predicate = undefined;
|
||
}
|
||
if (typeof predicate != 'function' || thisArg !== undefined) {
|
||
predicate = getCallback(predicate, thisArg, 3);
|
||
}
|
||
return func(collection, predicate);
|
||
}
|
||
|
||
/**
|
||
* Creates an array of elements, sorted in ascending order by the results of
|
||
* running each element in a collection through `iteratee`. This method performs
|
||
* a stable sort, that is, it preserves the original sort order of equal elements.
|
||
* The `iteratee` is bound to `thisArg` and invoked with three arguments:
|
||
* (value, index|key, collection).
|
||
*
|
||
* If a property name is provided for `iteratee` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `iteratee` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function|Object|string} [iteratee=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Array} Returns the new sorted array.
|
||
* @example
|
||
*
|
||
* _.sortBy([1, 2, 3], function(n) {
|
||
* return Math.sin(n);
|
||
* });
|
||
* // => [3, 1, 2]
|
||
*
|
||
* _.sortBy([1, 2, 3], function(n) {
|
||
* return this.sin(n);
|
||
* }, Math);
|
||
* // => [3, 1, 2]
|
||
*
|
||
* var users = [
|
||
* { 'user': 'fred' },
|
||
* { 'user': 'pebbles' },
|
||
* { 'user': 'barney' }
|
||
* ];
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.pluck(_.sortBy(users, 'user'), 'user');
|
||
* // => ['barney', 'fred', 'pebbles']
|
||
*/
|
||
function sortBy(collection, iteratee, thisArg) {
|
||
if (collection == null) {
|
||
return [];
|
||
}
|
||
if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {
|
||
iteratee = undefined;
|
||
}
|
||
var index = -1;
|
||
iteratee = getCallback(iteratee, thisArg, 3);
|
||
|
||
var result = baseMap(collection, function(value, key, collection) {
|
||
return { 'criteria': iteratee(value, key, collection), 'index': ++index, 'value': value };
|
||
});
|
||
return baseSortBy(result, compareAscending);
|
||
}
|
||
|
||
/**
|
||
* This method is like `_.sortBy` except that it can sort by multiple iteratees
|
||
* or property names.
|
||
*
|
||
* If a property name is provided for an iteratee the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If an object is provided for an iteratee the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {...(Function|Function[]|Object|Object[]|string|string[])} iteratees
|
||
* The iteratees to sort by, specified as individual values or arrays of values.
|
||
* @returns {Array} Returns the new sorted array.
|
||
* @example
|
||
*
|
||
* var users = [
|
||
* { 'user': 'fred', 'age': 48 },
|
||
* { 'user': 'barney', 'age': 36 },
|
||
* { 'user': 'fred', 'age': 42 },
|
||
* { 'user': 'barney', 'age': 34 }
|
||
* ];
|
||
*
|
||
* _.map(_.sortByAll(users, ['user', 'age']), _.values);
|
||
* // => [['barney', 34], ['barney', 36], ['fred', 42], ['fred', 48]]
|
||
*
|
||
* _.map(_.sortByAll(users, 'user', function(chr) {
|
||
* return Math.floor(chr.age / 10);
|
||
* }), _.values);
|
||
* // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
|
||
*/
|
||
var sortByAll = restParam(function(collection, iteratees) {
|
||
if (collection == null) {
|
||
return [];
|
||
}
|
||
var guard = iteratees[2];
|
||
if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) {
|
||
iteratees.length = 1;
|
||
}
|
||
return baseSortByOrder(collection, baseFlatten(iteratees), []);
|
||
});
|
||
|
||
/**
|
||
* This method is like `_.sortByAll` except that it allows specifying the
|
||
* sort orders of the iteratees to sort by. If `orders` is unspecified, all
|
||
* values are sorted in ascending order. Otherwise, a value is sorted in
|
||
* ascending order if its corresponding order is "asc", and descending if "desc".
|
||
*
|
||
* If a property name is provided for an iteratee the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If an object is provided for an iteratee the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
|
||
* @param {boolean[]} [orders] The sort orders of `iteratees`.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`.
|
||
* @returns {Array} Returns the new sorted array.
|
||
* @example
|
||
*
|
||
* var users = [
|
||
* { 'user': 'fred', 'age': 48 },
|
||
* { 'user': 'barney', 'age': 34 },
|
||
* { 'user': 'fred', 'age': 42 },
|
||
* { 'user': 'barney', 'age': 36 }
|
||
* ];
|
||
*
|
||
* // sort by `user` in ascending order and by `age` in descending order
|
||
* _.map(_.sortByOrder(users, ['user', 'age'], ['asc', 'desc']), _.values);
|
||
* // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
|
||
*/
|
||
function sortByOrder(collection, iteratees, orders, guard) {
|
||
if (collection == null) {
|
||
return [];
|
||
}
|
||
if (guard && isIterateeCall(iteratees, orders, guard)) {
|
||
orders = undefined;
|
||
}
|
||
if (!isArray(iteratees)) {
|
||
iteratees = iteratees == null ? [] : [iteratees];
|
||
}
|
||
if (!isArray(orders)) {
|
||
orders = orders == null ? [] : [orders];
|
||
}
|
||
return baseSortByOrder(collection, iteratees, orders);
|
||
}
|
||
|
||
/**
|
||
* Performs a deep comparison between each element in `collection` and the
|
||
* source object, returning an array of all elements that have equivalent
|
||
* property values.
|
||
*
|
||
* **Note:** This method supports comparing arrays, booleans, `Date` objects,
|
||
* numbers, `Object` objects, regexes, and strings. Objects are compared by
|
||
* their own, not inherited, enumerable properties. For comparing a single
|
||
* own or inherited property value see `_.matchesProperty`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Collection
|
||
* @param {Array|Object|string} collection The collection to search.
|
||
* @param {Object} source The object of property values to match.
|
||
* @returns {Array} Returns the new filtered array.
|
||
* @example
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'age': 36, 'active': false, 'pets': ['hoppy'] },
|
||
* { 'user': 'fred', 'age': 40, 'active': true, 'pets': ['baby puss', 'dino'] }
|
||
* ];
|
||
*
|
||
* _.pluck(_.where(users, { 'age': 36, 'active': false }), 'user');
|
||
* // => ['barney']
|
||
*
|
||
* _.pluck(_.where(users, { 'pets': ['dino'] }), 'user');
|
||
* // => ['fred']
|
||
*/
|
||
function where(collection, source) {
|
||
return filter(collection, baseMatches(source));
|
||
}
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Gets the number of milliseconds that have elapsed since the Unix epoch
|
||
* (1 January 1970 00:00:00 UTC).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Date
|
||
* @example
|
||
*
|
||
* _.defer(function(stamp) {
|
||
* console.log(_.now() - stamp);
|
||
* }, _.now());
|
||
* // => logs the number of milliseconds it took for the deferred function to be invoked
|
||
*/
|
||
var now = nativeNow || function() {
|
||
return new Date().getTime();
|
||
};
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* The opposite of `_.before`; this method creates a function that invokes
|
||
* `func` once it is called `n` or more times.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {number} n The number of calls before `func` is invoked.
|
||
* @param {Function} func The function to restrict.
|
||
* @returns {Function} Returns the new restricted function.
|
||
* @example
|
||
*
|
||
* var saves = ['profile', 'settings'];
|
||
*
|
||
* var done = _.after(saves.length, function() {
|
||
* console.log('done saving!');
|
||
* });
|
||
*
|
||
* _.forEach(saves, function(type) {
|
||
* asyncSave({ 'type': type, 'complete': done });
|
||
* });
|
||
* // => logs 'done saving!' after the two async saves have completed
|
||
*/
|
||
function after(n, func) {
|
||
if (typeof func != 'function') {
|
||
if (typeof n == 'function') {
|
||
var temp = n;
|
||
n = func;
|
||
func = temp;
|
||
} else {
|
||
throw new TypeError(FUNC_ERROR_TEXT);
|
||
}
|
||
}
|
||
n = nativeIsFinite(n = +n) ? n : 0;
|
||
return function() {
|
||
if (--n < 1) {
|
||
return func.apply(this, arguments);
|
||
}
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a function that accepts up to `n` arguments ignoring any
|
||
* additional arguments.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to cap arguments for.
|
||
* @param {number} [n=func.length] The arity cap.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* _.map(['6', '8', '10'], _.ary(parseInt, 1));
|
||
* // => [6, 8, 10]
|
||
*/
|
||
function ary(func, n, guard) {
|
||
if (guard && isIterateeCall(func, n, guard)) {
|
||
n = undefined;
|
||
}
|
||
n = (func && n == null) ? func.length : nativeMax(+n || 0, 0);
|
||
return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n);
|
||
}
|
||
|
||
/**
|
||
* Creates a function that invokes `func`, with the `this` binding and arguments
|
||
* of the created function, while it is called less than `n` times. Subsequent
|
||
* calls to the created function return the result of the last `func` invocation.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {number} n The number of calls at which `func` is no longer invoked.
|
||
* @param {Function} func The function to restrict.
|
||
* @returns {Function} Returns the new restricted function.
|
||
* @example
|
||
*
|
||
* jQuery('#add').on('click', _.before(5, addContactToList));
|
||
* // => allows adding up to 4 contacts to the list
|
||
*/
|
||
function before(n, func) {
|
||
var result;
|
||
if (typeof func != 'function') {
|
||
if (typeof n == 'function') {
|
||
var temp = n;
|
||
n = func;
|
||
func = temp;
|
||
} else {
|
||
throw new TypeError(FUNC_ERROR_TEXT);
|
||
}
|
||
}
|
||
return function() {
|
||
if (--n > 0) {
|
||
result = func.apply(this, arguments);
|
||
}
|
||
if (n <= 1) {
|
||
func = undefined;
|
||
}
|
||
return result;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a function that invokes `func` with the `this` binding of `thisArg`
|
||
* and prepends any additional `_.bind` arguments to those provided to the
|
||
* bound function.
|
||
*
|
||
* The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
|
||
* may be used as a placeholder for partially applied arguments.
|
||
*
|
||
* **Note:** Unlike native `Function#bind` this method does not set the "length"
|
||
* property of bound functions.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to bind.
|
||
* @param {*} thisArg The `this` binding of `func`.
|
||
* @param {...*} [partials] The arguments to be partially applied.
|
||
* @returns {Function} Returns the new bound function.
|
||
* @example
|
||
*
|
||
* var greet = function(greeting, punctuation) {
|
||
* return greeting + ' ' + this.user + punctuation;
|
||
* };
|
||
*
|
||
* var object = { 'user': 'fred' };
|
||
*
|
||
* var bound = _.bind(greet, object, 'hi');
|
||
* bound('!');
|
||
* // => 'hi fred!'
|
||
*
|
||
* // using placeholders
|
||
* var bound = _.bind(greet, object, _, '!');
|
||
* bound('hi');
|
||
* // => 'hi fred!'
|
||
*/
|
||
var bind = restParam(function(func, thisArg, partials) {
|
||
var bitmask = BIND_FLAG;
|
||
if (partials.length) {
|
||
var holders = replaceHolders(partials, bind.placeholder);
|
||
bitmask |= PARTIAL_FLAG;
|
||
}
|
||
return createWrapper(func, bitmask, thisArg, partials, holders);
|
||
});
|
||
|
||
/**
|
||
* Binds methods of an object to the object itself, overwriting the existing
|
||
* method. Method names may be specified as individual arguments or as arrays
|
||
* of method names. If no method names are provided all enumerable function
|
||
* properties, own and inherited, of `object` are bound.
|
||
*
|
||
* **Note:** This method does not set the "length" property of bound functions.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Object} object The object to bind and assign the bound methods to.
|
||
* @param {...(string|string[])} [methodNames] The object method names to bind,
|
||
* specified as individual method names or arrays of method names.
|
||
* @returns {Object} Returns `object`.
|
||
* @example
|
||
*
|
||
* var view = {
|
||
* 'label': 'docs',
|
||
* 'onClick': function() {
|
||
* console.log('clicked ' + this.label);
|
||
* }
|
||
* };
|
||
*
|
||
* _.bindAll(view);
|
||
* jQuery('#docs').on('click', view.onClick);
|
||
* // => logs 'clicked docs' when the element is clicked
|
||
*/
|
||
var bindAll = restParam(function(object, methodNames) {
|
||
methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object);
|
||
|
||
var index = -1,
|
||
length = methodNames.length;
|
||
|
||
while (++index < length) {
|
||
var key = methodNames[index];
|
||
object[key] = createWrapper(object[key], BIND_FLAG, object);
|
||
}
|
||
return object;
|
||
});
|
||
|
||
/**
|
||
* Creates a function that invokes the method at `object[key]` and prepends
|
||
* any additional `_.bindKey` arguments to those provided to the bound function.
|
||
*
|
||
* This method differs from `_.bind` by allowing bound functions to reference
|
||
* methods that may be redefined or don't yet exist.
|
||
* See [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
|
||
* for more details.
|
||
*
|
||
* The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
|
||
* builds, may be used as a placeholder for partially applied arguments.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Object} object The object the method belongs to.
|
||
* @param {string} key The key of the method.
|
||
* @param {...*} [partials] The arguments to be partially applied.
|
||
* @returns {Function} Returns the new bound function.
|
||
* @example
|
||
*
|
||
* var object = {
|
||
* 'user': 'fred',
|
||
* 'greet': function(greeting, punctuation) {
|
||
* return greeting + ' ' + this.user + punctuation;
|
||
* }
|
||
* };
|
||
*
|
||
* var bound = _.bindKey(object, 'greet', 'hi');
|
||
* bound('!');
|
||
* // => 'hi fred!'
|
||
*
|
||
* object.greet = function(greeting, punctuation) {
|
||
* return greeting + 'ya ' + this.user + punctuation;
|
||
* };
|
||
*
|
||
* bound('!');
|
||
* // => 'hiya fred!'
|
||
*
|
||
* // using placeholders
|
||
* var bound = _.bindKey(object, 'greet', _, '!');
|
||
* bound('hi');
|
||
* // => 'hiya fred!'
|
||
*/
|
||
var bindKey = restParam(function(object, key, partials) {
|
||
var bitmask = BIND_FLAG | BIND_KEY_FLAG;
|
||
if (partials.length) {
|
||
var holders = replaceHolders(partials, bindKey.placeholder);
|
||
bitmask |= PARTIAL_FLAG;
|
||
}
|
||
return createWrapper(key, bitmask, object, partials, holders);
|
||
});
|
||
|
||
/**
|
||
* Creates a function that accepts one or more arguments of `func` that when
|
||
* called either invokes `func` returning its result, if all `func` arguments
|
||
* have been provided, or returns a function that accepts one or more of the
|
||
* remaining `func` arguments, and so on. The arity of `func` may be specified
|
||
* if `func.length` is not sufficient.
|
||
*
|
||
* The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
|
||
* may be used as a placeholder for provided arguments.
|
||
*
|
||
* **Note:** This method does not set the "length" property of curried functions.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to curry.
|
||
* @param {number} [arity=func.length] The arity of `func`.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {Function} Returns the new curried function.
|
||
* @example
|
||
*
|
||
* var abc = function(a, b, c) {
|
||
* return [a, b, c];
|
||
* };
|
||
*
|
||
* var curried = _.curry(abc);
|
||
*
|
||
* curried(1)(2)(3);
|
||
* // => [1, 2, 3]
|
||
*
|
||
* curried(1, 2)(3);
|
||
* // => [1, 2, 3]
|
||
*
|
||
* curried(1, 2, 3);
|
||
* // => [1, 2, 3]
|
||
*
|
||
* // using placeholders
|
||
* curried(1)(_, 3)(2);
|
||
* // => [1, 2, 3]
|
||
*/
|
||
var curry = createCurry(CURRY_FLAG);
|
||
|
||
/**
|
||
* This method is like `_.curry` except that arguments are applied to `func`
|
||
* in the manner of `_.partialRight` instead of `_.partial`.
|
||
*
|
||
* The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
|
||
* builds, may be used as a placeholder for provided arguments.
|
||
*
|
||
* **Note:** This method does not set the "length" property of curried functions.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to curry.
|
||
* @param {number} [arity=func.length] The arity of `func`.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {Function} Returns the new curried function.
|
||
* @example
|
||
*
|
||
* var abc = function(a, b, c) {
|
||
* return [a, b, c];
|
||
* };
|
||
*
|
||
* var curried = _.curryRight(abc);
|
||
*
|
||
* curried(3)(2)(1);
|
||
* // => [1, 2, 3]
|
||
*
|
||
* curried(2, 3)(1);
|
||
* // => [1, 2, 3]
|
||
*
|
||
* curried(1, 2, 3);
|
||
* // => [1, 2, 3]
|
||
*
|
||
* // using placeholders
|
||
* curried(3)(1, _)(2);
|
||
* // => [1, 2, 3]
|
||
*/
|
||
var curryRight = createCurry(CURRY_RIGHT_FLAG);
|
||
|
||
/**
|
||
* Creates a debounced function that delays invoking `func` until after `wait`
|
||
* milliseconds have elapsed since the last time the debounced function was
|
||
* invoked. The debounced function comes with a `cancel` method to cancel
|
||
* delayed invocations. Provide an options object to indicate that `func`
|
||
* should be invoked on the leading and/or trailing edge of the `wait` timeout.
|
||
* Subsequent calls to the debounced function return the result of the last
|
||
* `func` invocation.
|
||
*
|
||
* **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
|
||
* on the trailing edge of the timeout only if the the debounced function is
|
||
* invoked more than once during the `wait` timeout.
|
||
*
|
||
* See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
|
||
* for details over the differences between `_.debounce` and `_.throttle`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to debounce.
|
||
* @param {number} [wait=0] The number of milliseconds to delay.
|
||
* @param {Object} [options] The options object.
|
||
* @param {boolean} [options.leading=false] Specify invoking on the leading
|
||
* edge of the timeout.
|
||
* @param {number} [options.maxWait] The maximum time `func` is allowed to be
|
||
* delayed before it is invoked.
|
||
* @param {boolean} [options.trailing=true] Specify invoking on the trailing
|
||
* edge of the timeout.
|
||
* @returns {Function} Returns the new debounced function.
|
||
* @example
|
||
*
|
||
* // avoid costly calculations while the window size is in flux
|
||
* jQuery(window).on('resize', _.debounce(calculateLayout, 150));
|
||
*
|
||
* // invoke `sendMail` when the click event is fired, debouncing subsequent calls
|
||
* jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
|
||
* 'leading': true,
|
||
* 'trailing': false
|
||
* }));
|
||
*
|
||
* // ensure `batchLog` is invoked once after 1 second of debounced calls
|
||
* var source = new EventSource('/stream');
|
||
* jQuery(source).on('message', _.debounce(batchLog, 250, {
|
||
* 'maxWait': 1000
|
||
* }));
|
||
*
|
||
* // cancel a debounced call
|
||
* var todoChanges = _.debounce(batchLog, 1000);
|
||
* Object.observe(models.todo, todoChanges);
|
||
*
|
||
* Object.observe(models, function(changes) {
|
||
* if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) {
|
||
* todoChanges.cancel();
|
||
* }
|
||
* }, ['delete']);
|
||
*
|
||
* // ...at some point `models.todo` is changed
|
||
* models.todo.completed = true;
|
||
*
|
||
* // ...before 1 second has passed `models.todo` is deleted
|
||
* // which cancels the debounced `todoChanges` call
|
||
* delete models.todo;
|
||
*/
|
||
function debounce(func, wait, options) {
|
||
var args,
|
||
maxTimeoutId,
|
||
result,
|
||
stamp,
|
||
thisArg,
|
||
timeoutId,
|
||
trailingCall,
|
||
lastCalled = 0,
|
||
maxWait = false,
|
||
trailing = true;
|
||
|
||
if (typeof func != 'function') {
|
||
throw new TypeError(FUNC_ERROR_TEXT);
|
||
}
|
||
wait = wait < 0 ? 0 : (+wait || 0);
|
||
if (options === true) {
|
||
var leading = true;
|
||
trailing = false;
|
||
} else if (isObject(options)) {
|
||
leading = !!options.leading;
|
||
maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait);
|
||
trailing = 'trailing' in options ? !!options.trailing : trailing;
|
||
}
|
||
|
||
function cancel() {
|
||
if (timeoutId) {
|
||
clearTimeout(timeoutId);
|
||
}
|
||
if (maxTimeoutId) {
|
||
clearTimeout(maxTimeoutId);
|
||
}
|
||
lastCalled = 0;
|
||
maxTimeoutId = timeoutId = trailingCall = undefined;
|
||
}
|
||
|
||
function complete(isCalled, id) {
|
||
if (id) {
|
||
clearTimeout(id);
|
||
}
|
||
maxTimeoutId = timeoutId = trailingCall = undefined;
|
||
if (isCalled) {
|
||
lastCalled = now();
|
||
result = func.apply(thisArg, args);
|
||
if (!timeoutId && !maxTimeoutId) {
|
||
args = thisArg = undefined;
|
||
}
|
||
}
|
||
}
|
||
|
||
function delayed() {
|
||
var remaining = wait - (now() - stamp);
|
||
if (remaining <= 0 || remaining > wait) {
|
||
complete(trailingCall, maxTimeoutId);
|
||
} else {
|
||
timeoutId = setTimeout(delayed, remaining);
|
||
}
|
||
}
|
||
|
||
function maxDelayed() {
|
||
complete(trailing, timeoutId);
|
||
}
|
||
|
||
function debounced() {
|
||
args = arguments;
|
||
stamp = now();
|
||
thisArg = this;
|
||
trailingCall = trailing && (timeoutId || !leading);
|
||
|
||
if (maxWait === false) {
|
||
var leadingCall = leading && !timeoutId;
|
||
} else {
|
||
if (!maxTimeoutId && !leading) {
|
||
lastCalled = stamp;
|
||
}
|
||
var remaining = maxWait - (stamp - lastCalled),
|
||
isCalled = remaining <= 0 || remaining > maxWait;
|
||
|
||
if (isCalled) {
|
||
if (maxTimeoutId) {
|
||
maxTimeoutId = clearTimeout(maxTimeoutId);
|
||
}
|
||
lastCalled = stamp;
|
||
result = func.apply(thisArg, args);
|
||
}
|
||
else if (!maxTimeoutId) {
|
||
maxTimeoutId = setTimeout(maxDelayed, remaining);
|
||
}
|
||
}
|
||
if (isCalled && timeoutId) {
|
||
timeoutId = clearTimeout(timeoutId);
|
||
}
|
||
else if (!timeoutId && wait !== maxWait) {
|
||
timeoutId = setTimeout(delayed, wait);
|
||
}
|
||
if (leadingCall) {
|
||
isCalled = true;
|
||
result = func.apply(thisArg, args);
|
||
}
|
||
if (isCalled && !timeoutId && !maxTimeoutId) {
|
||
args = thisArg = undefined;
|
||
}
|
||
return result;
|
||
}
|
||
debounced.cancel = cancel;
|
||
return debounced;
|
||
}
|
||
|
||
/**
|
||
* Defers invoking the `func` until the current call stack has cleared. Any
|
||
* additional arguments are provided to `func` when it is invoked.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to defer.
|
||
* @param {...*} [args] The arguments to invoke the function with.
|
||
* @returns {number} Returns the timer id.
|
||
* @example
|
||
*
|
||
* _.defer(function(text) {
|
||
* console.log(text);
|
||
* }, 'deferred');
|
||
* // logs 'deferred' after one or more milliseconds
|
||
*/
|
||
var defer = restParam(function(func, args) {
|
||
return baseDelay(func, 1, args);
|
||
});
|
||
|
||
/**
|
||
* Invokes `func` after `wait` milliseconds. Any additional arguments are
|
||
* provided to `func` when it is invoked.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to delay.
|
||
* @param {number} wait The number of milliseconds to delay invocation.
|
||
* @param {...*} [args] The arguments to invoke the function with.
|
||
* @returns {number} Returns the timer id.
|
||
* @example
|
||
*
|
||
* _.delay(function(text) {
|
||
* console.log(text);
|
||
* }, 1000, 'later');
|
||
* // => logs 'later' after one second
|
||
*/
|
||
var delay = restParam(function(func, wait, args) {
|
||
return baseDelay(func, wait, args);
|
||
});
|
||
|
||
/**
|
||
* Creates a function that returns the result of invoking the provided
|
||
* functions with the `this` binding of the created function, where each
|
||
* successive invocation is supplied the return value of the previous.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {...Function} [funcs] Functions to invoke.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* function square(n) {
|
||
* return n * n;
|
||
* }
|
||
*
|
||
* var addSquare = _.flow(_.add, square);
|
||
* addSquare(1, 2);
|
||
* // => 9
|
||
*/
|
||
var flow = createFlow();
|
||
|
||
/**
|
||
* This method is like `_.flow` except that it creates a function that
|
||
* invokes the provided functions from right to left.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias backflow, compose
|
||
* @category Function
|
||
* @param {...Function} [funcs] Functions to invoke.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* function square(n) {
|
||
* return n * n;
|
||
* }
|
||
*
|
||
* var addSquare = _.flowRight(square, _.add);
|
||
* addSquare(1, 2);
|
||
* // => 9
|
||
*/
|
||
var flowRight = createFlow(true);
|
||
|
||
/**
|
||
* Creates a function that memoizes the result of `func`. If `resolver` is
|
||
* provided it determines the cache key for storing the result based on the
|
||
* arguments provided to the memoized function. By default, the first argument
|
||
* provided to the memoized function is coerced to a string and used as the
|
||
* cache key. The `func` is invoked with the `this` binding of the memoized
|
||
* function.
|
||
*
|
||
* **Note:** The cache is exposed as the `cache` property on the memoized
|
||
* function. Its creation may be customized by replacing the `_.memoize.Cache`
|
||
* constructor with one whose instances implement the [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object)
|
||
* method interface of `get`, `has`, and `set`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to have its output memoized.
|
||
* @param {Function} [resolver] The function to resolve the cache key.
|
||
* @returns {Function} Returns the new memoizing function.
|
||
* @example
|
||
*
|
||
* var upperCase = _.memoize(function(string) {
|
||
* return string.toUpperCase();
|
||
* });
|
||
*
|
||
* upperCase('fred');
|
||
* // => 'FRED'
|
||
*
|
||
* // modifying the result cache
|
||
* upperCase.cache.set('fred', 'BARNEY');
|
||
* upperCase('fred');
|
||
* // => 'BARNEY'
|
||
*
|
||
* // replacing `_.memoize.Cache`
|
||
* var object = { 'user': 'fred' };
|
||
* var other = { 'user': 'barney' };
|
||
* var identity = _.memoize(_.identity);
|
||
*
|
||
* identity(object);
|
||
* // => { 'user': 'fred' }
|
||
* identity(other);
|
||
* // => { 'user': 'fred' }
|
||
*
|
||
* _.memoize.Cache = WeakMap;
|
||
* var identity = _.memoize(_.identity);
|
||
*
|
||
* identity(object);
|
||
* // => { 'user': 'fred' }
|
||
* identity(other);
|
||
* // => { 'user': 'barney' }
|
||
*/
|
||
function memoize(func, resolver) {
|
||
if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {
|
||
throw new TypeError(FUNC_ERROR_TEXT);
|
||
}
|
||
var memoized = function() {
|
||
var args = arguments,
|
||
key = resolver ? resolver.apply(this, args) : args[0],
|
||
cache = memoized.cache;
|
||
|
||
if (cache.has(key)) {
|
||
return cache.get(key);
|
||
}
|
||
var result = func.apply(this, args);
|
||
memoized.cache = cache.set(key, result);
|
||
return result;
|
||
};
|
||
memoized.cache = new memoize.Cache;
|
||
return memoized;
|
||
}
|
||
|
||
/**
|
||
* Creates a function that runs each argument through a corresponding
|
||
* transform function.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to wrap.
|
||
* @param {...(Function|Function[])} [transforms] The functions to transform
|
||
* arguments, specified as individual functions or arrays of functions.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* function doubled(n) {
|
||
* return n * 2;
|
||
* }
|
||
*
|
||
* function square(n) {
|
||
* return n * n;
|
||
* }
|
||
*
|
||
* var modded = _.modArgs(function(x, y) {
|
||
* return [x, y];
|
||
* }, square, doubled);
|
||
*
|
||
* modded(1, 2);
|
||
* // => [1, 4]
|
||
*
|
||
* modded(5, 10);
|
||
* // => [25, 20]
|
||
*/
|
||
var modArgs = restParam(function(func, transforms) {
|
||
transforms = baseFlatten(transforms);
|
||
if (typeof func != 'function' || !arrayEvery(transforms, baseIsFunction)) {
|
||
throw new TypeError(FUNC_ERROR_TEXT);
|
||
}
|
||
var length = transforms.length;
|
||
return restParam(function(args) {
|
||
var index = nativeMin(args.length, length);
|
||
while (index--) {
|
||
args[index] = transforms[index](args[index]);
|
||
}
|
||
return func.apply(this, args);
|
||
});
|
||
});
|
||
|
||
/**
|
||
* Creates a function that negates the result of the predicate `func`. The
|
||
* `func` predicate is invoked with the `this` binding and arguments of the
|
||
* created function.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} predicate The predicate to negate.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* function isEven(n) {
|
||
* return n % 2 == 0;
|
||
* }
|
||
*
|
||
* _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
|
||
* // => [1, 3, 5]
|
||
*/
|
||
function negate(predicate) {
|
||
if (typeof predicate != 'function') {
|
||
throw new TypeError(FUNC_ERROR_TEXT);
|
||
}
|
||
return function() {
|
||
return !predicate.apply(this, arguments);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a function that is restricted to invoking `func` once. Repeat calls
|
||
* to the function return the value of the first call. The `func` is invoked
|
||
* with the `this` binding and arguments of the created function.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to restrict.
|
||
* @returns {Function} Returns the new restricted function.
|
||
* @example
|
||
*
|
||
* var initialize = _.once(createApplication);
|
||
* initialize();
|
||
* initialize();
|
||
* // `initialize` invokes `createApplication` once
|
||
*/
|
||
function once(func) {
|
||
return before(2, func);
|
||
}
|
||
|
||
/**
|
||
* Creates a function that invokes `func` with `partial` arguments prepended
|
||
* to those provided to the new function. This method is like `_.bind` except
|
||
* it does **not** alter the `this` binding.
|
||
*
|
||
* The `_.partial.placeholder` value, which defaults to `_` in monolithic
|
||
* builds, may be used as a placeholder for partially applied arguments.
|
||
*
|
||
* **Note:** This method does not set the "length" property of partially
|
||
* applied functions.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to partially apply arguments to.
|
||
* @param {...*} [partials] The arguments to be partially applied.
|
||
* @returns {Function} Returns the new partially applied function.
|
||
* @example
|
||
*
|
||
* var greet = function(greeting, name) {
|
||
* return greeting + ' ' + name;
|
||
* };
|
||
*
|
||
* var sayHelloTo = _.partial(greet, 'hello');
|
||
* sayHelloTo('fred');
|
||
* // => 'hello fred'
|
||
*
|
||
* // using placeholders
|
||
* var greetFred = _.partial(greet, _, 'fred');
|
||
* greetFred('hi');
|
||
* // => 'hi fred'
|
||
*/
|
||
var partial = createPartial(PARTIAL_FLAG);
|
||
|
||
/**
|
||
* This method is like `_.partial` except that partially applied arguments
|
||
* are appended to those provided to the new function.
|
||
*
|
||
* The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
|
||
* builds, may be used as a placeholder for partially applied arguments.
|
||
*
|
||
* **Note:** This method does not set the "length" property of partially
|
||
* applied functions.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to partially apply arguments to.
|
||
* @param {...*} [partials] The arguments to be partially applied.
|
||
* @returns {Function} Returns the new partially applied function.
|
||
* @example
|
||
*
|
||
* var greet = function(greeting, name) {
|
||
* return greeting + ' ' + name;
|
||
* };
|
||
*
|
||
* var greetFred = _.partialRight(greet, 'fred');
|
||
* greetFred('hi');
|
||
* // => 'hi fred'
|
||
*
|
||
* // using placeholders
|
||
* var sayHelloTo = _.partialRight(greet, 'hello', _);
|
||
* sayHelloTo('fred');
|
||
* // => 'hello fred'
|
||
*/
|
||
var partialRight = createPartial(PARTIAL_RIGHT_FLAG);
|
||
|
||
/**
|
||
* Creates a function that invokes `func` with arguments arranged according
|
||
* to the specified indexes where the argument value at the first index is
|
||
* provided as the first argument, the argument value at the second index is
|
||
* provided as the second argument, and so on.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to rearrange arguments for.
|
||
* @param {...(number|number[])} indexes The arranged argument indexes,
|
||
* specified as individual indexes or arrays of indexes.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* var rearged = _.rearg(function(a, b, c) {
|
||
* return [a, b, c];
|
||
* }, 2, 0, 1);
|
||
*
|
||
* rearged('b', 'c', 'a')
|
||
* // => ['a', 'b', 'c']
|
||
*
|
||
* var map = _.rearg(_.map, [1, 0]);
|
||
* map(function(n) {
|
||
* return n * 3;
|
||
* }, [1, 2, 3]);
|
||
* // => [3, 6, 9]
|
||
*/
|
||
var rearg = restParam(function(func, indexes) {
|
||
return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes));
|
||
});
|
||
|
||
/**
|
||
* Creates a function that invokes `func` with the `this` binding of the
|
||
* created function and arguments from `start` and beyond provided as an array.
|
||
*
|
||
* **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to apply a rest parameter to.
|
||
* @param {number} [start=func.length-1] The start position of the rest parameter.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* var say = _.restParam(function(what, names) {
|
||
* return what + ' ' + _.initial(names).join(', ') +
|
||
* (_.size(names) > 1 ? ', & ' : '') + _.last(names);
|
||
* });
|
||
*
|
||
* say('hello', 'fred', 'barney', 'pebbles');
|
||
* // => 'hello fred, barney, & pebbles'
|
||
*/
|
||
function restParam(func, start) {
|
||
if (typeof func != 'function') {
|
||
throw new TypeError(FUNC_ERROR_TEXT);
|
||
}
|
||
start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0);
|
||
return function() {
|
||
var args = arguments,
|
||
index = -1,
|
||
length = nativeMax(args.length - start, 0),
|
||
rest = Array(length);
|
||
|
||
while (++index < length) {
|
||
rest[index] = args[start + index];
|
||
}
|
||
switch (start) {
|
||
case 0: return func.call(this, rest);
|
||
case 1: return func.call(this, args[0], rest);
|
||
case 2: return func.call(this, args[0], args[1], rest);
|
||
}
|
||
var otherArgs = Array(start + 1);
|
||
index = -1;
|
||
while (++index < start) {
|
||
otherArgs[index] = args[index];
|
||
}
|
||
otherArgs[start] = rest;
|
||
return func.apply(this, otherArgs);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a function that invokes `func` with the `this` binding of the created
|
||
* function and an array of arguments much like [`Function#apply`](https://es5.github.io/#x15.3.4.3).
|
||
*
|
||
* **Note:** This method is based on the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to spread arguments over.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* var say = _.spread(function(who, what) {
|
||
* return who + ' says ' + what;
|
||
* });
|
||
*
|
||
* say(['fred', 'hello']);
|
||
* // => 'fred says hello'
|
||
*
|
||
* // with a Promise
|
||
* var numbers = Promise.all([
|
||
* Promise.resolve(40),
|
||
* Promise.resolve(36)
|
||
* ]);
|
||
*
|
||
* numbers.then(_.spread(function(x, y) {
|
||
* return x + y;
|
||
* }));
|
||
* // => a Promise of 76
|
||
*/
|
||
function spread(func) {
|
||
if (typeof func != 'function') {
|
||
throw new TypeError(FUNC_ERROR_TEXT);
|
||
}
|
||
return function(array) {
|
||
return func.apply(this, array);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates a throttled function that only invokes `func` at most once per
|
||
* every `wait` milliseconds. The throttled function comes with a `cancel`
|
||
* method to cancel delayed invocations. Provide an options object to indicate
|
||
* that `func` should be invoked on the leading and/or trailing edge of the
|
||
* `wait` timeout. Subsequent calls to the throttled function return the
|
||
* result of the last `func` call.
|
||
*
|
||
* **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
|
||
* on the trailing edge of the timeout only if the the throttled function is
|
||
* invoked more than once during the `wait` timeout.
|
||
*
|
||
* See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
|
||
* for details over the differences between `_.throttle` and `_.debounce`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to throttle.
|
||
* @param {number} [wait=0] The number of milliseconds to throttle invocations to.
|
||
* @param {Object} [options] The options object.
|
||
* @param {boolean} [options.leading=true] Specify invoking on the leading
|
||
* edge of the timeout.
|
||
* @param {boolean} [options.trailing=true] Specify invoking on the trailing
|
||
* edge of the timeout.
|
||
* @returns {Function} Returns the new throttled function.
|
||
* @example
|
||
*
|
||
* // avoid excessively updating the position while scrolling
|
||
* jQuery(window).on('scroll', _.throttle(updatePosition, 100));
|
||
*
|
||
* // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes
|
||
* jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
|
||
* 'trailing': false
|
||
* }));
|
||
*
|
||
* // cancel a trailing throttled call
|
||
* jQuery(window).on('popstate', throttled.cancel);
|
||
*/
|
||
function throttle(func, wait, options) {
|
||
var leading = true,
|
||
trailing = true;
|
||
|
||
if (typeof func != 'function') {
|
||
throw new TypeError(FUNC_ERROR_TEXT);
|
||
}
|
||
if (options === false) {
|
||
leading = false;
|
||
} else if (isObject(options)) {
|
||
leading = 'leading' in options ? !!options.leading : leading;
|
||
trailing = 'trailing' in options ? !!options.trailing : trailing;
|
||
}
|
||
return debounce(func, wait, { 'leading': leading, 'maxWait': +wait, 'trailing': trailing });
|
||
}
|
||
|
||
/**
|
||
* Creates a function that provides `value` to the wrapper function as its
|
||
* first argument. Any additional arguments provided to the function are
|
||
* appended to those provided to the wrapper function. The wrapper is invoked
|
||
* with the `this` binding of the created function.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {*} value The value to wrap.
|
||
* @param {Function} wrapper The wrapper function.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* var p = _.wrap(_.escape, function(func, text) {
|
||
* return '<p>' + func(text) + '</p>';
|
||
* });
|
||
*
|
||
* p('fred, barney, & pebbles');
|
||
* // => '<p>fred, barney, & pebbles</p>'
|
||
*/
|
||
function wrap(value, wrapper) {
|
||
wrapper = wrapper == null ? identity : wrapper;
|
||
return createWrapper(wrapper, PARTIAL_FLAG, undefined, [value], []);
|
||
}
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned,
|
||
* otherwise they are assigned by reference. If `customizer` is provided it is
|
||
* invoked to produce the cloned values. If `customizer` returns `undefined`
|
||
* cloning is handled by the method instead. The `customizer` is bound to
|
||
* `thisArg` and invoked with two argument; (value [, index|key, object]).
|
||
*
|
||
* **Note:** This method is loosely based on the
|
||
* [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm).
|
||
* The enumerable properties of `arguments` objects and objects created by
|
||
* constructors other than `Object` are cloned to plain `Object` objects. An
|
||
* empty object is returned for uncloneable values such as functions, DOM nodes,
|
||
* Maps, Sets, and WeakMaps.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to clone.
|
||
* @param {boolean} [isDeep] Specify a deep clone.
|
||
* @param {Function} [customizer] The function to customize cloning values.
|
||
* @param {*} [thisArg] The `this` binding of `customizer`.
|
||
* @returns {*} Returns the cloned value.
|
||
* @example
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney' },
|
||
* { 'user': 'fred' }
|
||
* ];
|
||
*
|
||
* var shallow = _.clone(users);
|
||
* shallow[0] === users[0];
|
||
* // => true
|
||
*
|
||
* var deep = _.clone(users, true);
|
||
* deep[0] === users[0];
|
||
* // => false
|
||
*
|
||
* // using a customizer callback
|
||
* var el = _.clone(document.body, function(value) {
|
||
* if (_.isElement(value)) {
|
||
* return value.cloneNode(false);
|
||
* }
|
||
* });
|
||
*
|
||
* el === document.body
|
||
* // => false
|
||
* el.nodeName
|
||
* // => BODY
|
||
* el.childNodes.length;
|
||
* // => 0
|
||
*/
|
||
function clone(value, isDeep, customizer, thisArg) {
|
||
if (isDeep && typeof isDeep != 'boolean' && isIterateeCall(value, isDeep, customizer)) {
|
||
isDeep = false;
|
||
}
|
||
else if (typeof isDeep == 'function') {
|
||
thisArg = customizer;
|
||
customizer = isDeep;
|
||
isDeep = false;
|
||
}
|
||
return typeof customizer == 'function'
|
||
? baseClone(value, isDeep, bindCallback(customizer, thisArg, 1))
|
||
: baseClone(value, isDeep);
|
||
}
|
||
|
||
/**
|
||
* Creates a deep clone of `value`. If `customizer` is provided it is invoked
|
||
* to produce the cloned values. If `customizer` returns `undefined` cloning
|
||
* is handled by the method instead. The `customizer` is bound to `thisArg`
|
||
* and invoked with two argument; (value [, index|key, object]).
|
||
*
|
||
* **Note:** This method is loosely based on the
|
||
* [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm).
|
||
* The enumerable properties of `arguments` objects and objects created by
|
||
* constructors other than `Object` are cloned to plain `Object` objects. An
|
||
* empty object is returned for uncloneable values such as functions, DOM nodes,
|
||
* Maps, Sets, and WeakMaps.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to deep clone.
|
||
* @param {Function} [customizer] The function to customize cloning values.
|
||
* @param {*} [thisArg] The `this` binding of `customizer`.
|
||
* @returns {*} Returns the deep cloned value.
|
||
* @example
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney' },
|
||
* { 'user': 'fred' }
|
||
* ];
|
||
*
|
||
* var deep = _.cloneDeep(users);
|
||
* deep[0] === users[0];
|
||
* // => false
|
||
*
|
||
* // using a customizer callback
|
||
* var el = _.cloneDeep(document.body, function(value) {
|
||
* if (_.isElement(value)) {
|
||
* return value.cloneNode(true);
|
||
* }
|
||
* });
|
||
*
|
||
* el === document.body
|
||
* // => false
|
||
* el.nodeName
|
||
* // => BODY
|
||
* el.childNodes.length;
|
||
* // => 20
|
||
*/
|
||
function cloneDeep(value, customizer, thisArg) {
|
||
return typeof customizer == 'function'
|
||
? baseClone(value, true, bindCallback(customizer, thisArg, 1))
|
||
: baseClone(value, true);
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is greater than `other`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to compare.
|
||
* @param {*} other The other value to compare.
|
||
* @returns {boolean} Returns `true` if `value` is greater than `other`, else `false`.
|
||
* @example
|
||
*
|
||
* _.gt(3, 1);
|
||
* // => true
|
||
*
|
||
* _.gt(3, 3);
|
||
* // => false
|
||
*
|
||
* _.gt(1, 3);
|
||
* // => false
|
||
*/
|
||
function gt(value, other) {
|
||
return value > other;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is greater than or equal to `other`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to compare.
|
||
* @param {*} other The other value to compare.
|
||
* @returns {boolean} Returns `true` if `value` is greater than or equal to `other`, else `false`.
|
||
* @example
|
||
*
|
||
* _.gte(3, 1);
|
||
* // => true
|
||
*
|
||
* _.gte(3, 3);
|
||
* // => true
|
||
*
|
||
* _.gte(1, 3);
|
||
* // => false
|
||
*/
|
||
function gte(value, other) {
|
||
return value >= other;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is classified as an `arguments` object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
|
||
* @example
|
||
*
|
||
* _.isArguments(function() { return arguments; }());
|
||
* // => true
|
||
*
|
||
* _.isArguments([1, 2, 3]);
|
||
* // => false
|
||
*/
|
||
function isArguments(value) {
|
||
return isObjectLike(value) && isArrayLike(value) &&
|
||
hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is classified as an `Array` object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
|
||
* @example
|
||
*
|
||
* _.isArray([1, 2, 3]);
|
||
* // => true
|
||
*
|
||
* _.isArray(function() { return arguments; }());
|
||
* // => false
|
||
*/
|
||
var isArray = nativeIsArray || function(value) {
|
||
return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;
|
||
};
|
||
|
||
/**
|
||
* Checks if `value` is classified as a boolean primitive or object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
|
||
* @example
|
||
*
|
||
* _.isBoolean(false);
|
||
* // => true
|
||
*
|
||
* _.isBoolean(null);
|
||
* // => false
|
||
*/
|
||
function isBoolean(value) {
|
||
return value === true || value === false || (isObjectLike(value) && objToString.call(value) == boolTag);
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is classified as a `Date` object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
|
||
* @example
|
||
*
|
||
* _.isDate(new Date);
|
||
* // => true
|
||
*
|
||
* _.isDate('Mon April 23 2012');
|
||
* // => false
|
||
*/
|
||
function isDate(value) {
|
||
return isObjectLike(value) && objToString.call(value) == dateTag;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is a DOM element.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
|
||
* @example
|
||
*
|
||
* _.isElement(document.body);
|
||
* // => true
|
||
*
|
||
* _.isElement('<body>');
|
||
* // => false
|
||
*/
|
||
function isElement(value) {
|
||
return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value);
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is empty. A value is considered empty unless it is an
|
||
* `arguments` object, array, string, or jQuery-like collection with a length
|
||
* greater than `0` or an object with own enumerable properties.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {Array|Object|string} value The value to inspect.
|
||
* @returns {boolean} Returns `true` if `value` is empty, else `false`.
|
||
* @example
|
||
*
|
||
* _.isEmpty(null);
|
||
* // => true
|
||
*
|
||
* _.isEmpty(true);
|
||
* // => true
|
||
*
|
||
* _.isEmpty(1);
|
||
* // => true
|
||
*
|
||
* _.isEmpty([1, 2, 3]);
|
||
* // => false
|
||
*
|
||
* _.isEmpty({ 'a': 1 });
|
||
* // => false
|
||
*/
|
||
function isEmpty(value) {
|
||
if (value == null) {
|
||
return true;
|
||
}
|
||
if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) ||
|
||
(isObjectLike(value) && isFunction(value.splice)))) {
|
||
return !value.length;
|
||
}
|
||
return !keys(value).length;
|
||
}
|
||
|
||
/**
|
||
* Performs a deep comparison between two values to determine if they are
|
||
* equivalent. If `customizer` is provided it is invoked to compare values.
|
||
* If `customizer` returns `undefined` comparisons are handled by the method
|
||
* instead. The `customizer` is bound to `thisArg` and invoked with three
|
||
* arguments: (value, other [, index|key]).
|
||
*
|
||
* **Note:** This method supports comparing arrays, booleans, `Date` objects,
|
||
* numbers, `Object` objects, regexes, and strings. Objects are compared by
|
||
* their own, not inherited, enumerable properties. Functions and DOM nodes
|
||
* are **not** supported. Provide a customizer function to extend support
|
||
* for comparing other values.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias eq
|
||
* @category Lang
|
||
* @param {*} value The value to compare.
|
||
* @param {*} other The other value to compare.
|
||
* @param {Function} [customizer] The function to customize value comparisons.
|
||
* @param {*} [thisArg] The `this` binding of `customizer`.
|
||
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
|
||
* @example
|
||
*
|
||
* var object = { 'user': 'fred' };
|
||
* var other = { 'user': 'fred' };
|
||
*
|
||
* object == other;
|
||
* // => false
|
||
*
|
||
* _.isEqual(object, other);
|
||
* // => true
|
||
*
|
||
* // using a customizer callback
|
||
* var array = ['hello', 'goodbye'];
|
||
* var other = ['hi', 'goodbye'];
|
||
*
|
||
* _.isEqual(array, other, function(value, other) {
|
||
* if (_.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/)) {
|
||
* return true;
|
||
* }
|
||
* });
|
||
* // => true
|
||
*/
|
||
function isEqual(value, other, customizer, thisArg) {
|
||
customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined;
|
||
var result = customizer ? customizer(value, other) : undefined;
|
||
return result === undefined ? baseIsEqual(value, other, customizer) : !!result;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
|
||
* `SyntaxError`, `TypeError`, or `URIError` object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is an error object, else `false`.
|
||
* @example
|
||
*
|
||
* _.isError(new Error);
|
||
* // => true
|
||
*
|
||
* _.isError(Error);
|
||
* // => false
|
||
*/
|
||
function isError(value) {
|
||
return isObjectLike(value) && typeof value.message == 'string' && objToString.call(value) == errorTag;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is a finite primitive number.
|
||
*
|
||
* **Note:** This method is based on [`Number.isFinite`](http://ecma-international.org/ecma-262/6.0/#sec-number.isfinite).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
|
||
* @example
|
||
*
|
||
* _.isFinite(10);
|
||
* // => true
|
||
*
|
||
* _.isFinite('10');
|
||
* // => false
|
||
*
|
||
* _.isFinite(true);
|
||
* // => false
|
||
*
|
||
* _.isFinite(Object(10));
|
||
* // => false
|
||
*
|
||
* _.isFinite(Infinity);
|
||
* // => false
|
||
*/
|
||
function isFinite(value) {
|
||
return typeof value == 'number' && nativeIsFinite(value);
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is classified as a `Function` object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
|
||
* @example
|
||
*
|
||
* _.isFunction(_);
|
||
* // => true
|
||
*
|
||
* _.isFunction(/abc/);
|
||
* // => false
|
||
*/
|
||
function isFunction(value) {
|
||
// The use of `Object#toString` avoids issues with the `typeof` operator
|
||
// in older versions of Chrome and Safari which return 'function' for regexes
|
||
// and Safari 8 equivalents which return 'object' for typed array constructors.
|
||
return isObject(value) && objToString.call(value) == funcTag;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
|
||
* (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is an object, else `false`.
|
||
* @example
|
||
*
|
||
* _.isObject({});
|
||
* // => true
|
||
*
|
||
* _.isObject([1, 2, 3]);
|
||
* // => true
|
||
*
|
||
* _.isObject(1);
|
||
* // => false
|
||
*/
|
||
function isObject(value) {
|
||
// Avoid a V8 JIT bug in Chrome 19-20.
|
||
// See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
|
||
var type = typeof value;
|
||
return !!value && (type == 'object' || type == 'function');
|
||
}
|
||
|
||
/**
|
||
* Performs a deep comparison between `object` and `source` to determine if
|
||
* `object` contains equivalent property values. If `customizer` is provided
|
||
* it is invoked to compare values. If `customizer` returns `undefined`
|
||
* comparisons are handled by the method instead. The `customizer` is bound
|
||
* to `thisArg` and invoked with three arguments: (value, other, index|key).
|
||
*
|
||
* **Note:** This method supports comparing properties of arrays, booleans,
|
||
* `Date` objects, numbers, `Object` objects, regexes, and strings. Functions
|
||
* and DOM nodes are **not** supported. Provide a customizer function to extend
|
||
* support for comparing other values.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {Object} object The object to inspect.
|
||
* @param {Object} source The object of property values to match.
|
||
* @param {Function} [customizer] The function to customize value comparisons.
|
||
* @param {*} [thisArg] The `this` binding of `customizer`.
|
||
* @returns {boolean} Returns `true` if `object` is a match, else `false`.
|
||
* @example
|
||
*
|
||
* var object = { 'user': 'fred', 'age': 40 };
|
||
*
|
||
* _.isMatch(object, { 'age': 40 });
|
||
* // => true
|
||
*
|
||
* _.isMatch(object, { 'age': 36 });
|
||
* // => false
|
||
*
|
||
* // using a customizer callback
|
||
* var object = { 'greeting': 'hello' };
|
||
* var source = { 'greeting': 'hi' };
|
||
*
|
||
* _.isMatch(object, source, function(value, other) {
|
||
* return _.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/) || undefined;
|
||
* });
|
||
* // => true
|
||
*/
|
||
function isMatch(object, source, customizer, thisArg) {
|
||
customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined;
|
||
return baseIsMatch(object, getMatchData(source), customizer);
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is `NaN`.
|
||
*
|
||
* **Note:** This method is not the same as [`isNaN`](https://es5.github.io/#x15.1.2.4)
|
||
* which returns `true` for `undefined` and other non-numeric values.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
|
||
* @example
|
||
*
|
||
* _.isNaN(NaN);
|
||
* // => true
|
||
*
|
||
* _.isNaN(new Number(NaN));
|
||
* // => true
|
||
*
|
||
* isNaN(undefined);
|
||
* // => true
|
||
*
|
||
* _.isNaN(undefined);
|
||
* // => false
|
||
*/
|
||
function isNaN(value) {
|
||
// An `NaN` primitive is the only value that is not equal to itself.
|
||
// Perform the `toStringTag` check first to avoid errors with some host objects in IE.
|
||
return isNumber(value) && value != +value;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is a native function.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a native function, else `false`.
|
||
* @example
|
||
*
|
||
* _.isNative(Array.prototype.push);
|
||
* // => true
|
||
*
|
||
* _.isNative(_);
|
||
* // => false
|
||
*/
|
||
function isNative(value) {
|
||
if (value == null) {
|
||
return false;
|
||
}
|
||
if (isFunction(value)) {
|
||
return reIsNative.test(fnToString.call(value));
|
||
}
|
||
return isObjectLike(value) && reIsHostCtor.test(value);
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is `null`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is `null`, else `false`.
|
||
* @example
|
||
*
|
||
* _.isNull(null);
|
||
* // => true
|
||
*
|
||
* _.isNull(void 0);
|
||
* // => false
|
||
*/
|
||
function isNull(value) {
|
||
return value === null;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is classified as a `Number` primitive or object.
|
||
*
|
||
* **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified
|
||
* as numbers, use the `_.isFinite` method.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
|
||
* @example
|
||
*
|
||
* _.isNumber(8.4);
|
||
* // => true
|
||
*
|
||
* _.isNumber(NaN);
|
||
* // => true
|
||
*
|
||
* _.isNumber('8.4');
|
||
* // => false
|
||
*/
|
||
function isNumber(value) {
|
||
return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag);
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is a plain object, that is, an object created by the
|
||
* `Object` constructor or one with a `[[Prototype]]` of `null`.
|
||
*
|
||
* **Note:** This method assumes objects created by the `Object` constructor
|
||
* have no inherited enumerable properties.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
|
||
* @example
|
||
*
|
||
* function Foo() {
|
||
* this.a = 1;
|
||
* }
|
||
*
|
||
* _.isPlainObject(new Foo);
|
||
* // => false
|
||
*
|
||
* _.isPlainObject([1, 2, 3]);
|
||
* // => false
|
||
*
|
||
* _.isPlainObject({ 'x': 0, 'y': 0 });
|
||
* // => true
|
||
*
|
||
* _.isPlainObject(Object.create(null));
|
||
* // => true
|
||
*/
|
||
function isPlainObject(value) {
|
||
var Ctor;
|
||
|
||
// Exit early for non `Object` objects.
|
||
if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) ||
|
||
(!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) {
|
||
return false;
|
||
}
|
||
// IE < 9 iterates inherited properties before own properties. If the first
|
||
// iterated property is an object's own property then there are no inherited
|
||
// enumerable properties.
|
||
var result;
|
||
// In most environments an object's own properties are iterated before
|
||
// its inherited properties. If the last iterated property is an object's
|
||
// own property then there are no inherited enumerable properties.
|
||
baseForIn(value, function(subValue, key) {
|
||
result = key;
|
||
});
|
||
return result === undefined || hasOwnProperty.call(value, result);
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is classified as a `RegExp` object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
|
||
* @example
|
||
*
|
||
* _.isRegExp(/abc/);
|
||
* // => true
|
||
*
|
||
* _.isRegExp('/abc/');
|
||
* // => false
|
||
*/
|
||
function isRegExp(value) {
|
||
return isObject(value) && objToString.call(value) == regexpTag;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is classified as a `String` primitive or object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
|
||
* @example
|
||
*
|
||
* _.isString('abc');
|
||
* // => true
|
||
*
|
||
* _.isString(1);
|
||
* // => false
|
||
*/
|
||
function isString(value) {
|
||
return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag);
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is classified as a typed array.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
|
||
* @example
|
||
*
|
||
* _.isTypedArray(new Uint8Array);
|
||
* // => true
|
||
*
|
||
* _.isTypedArray([]);
|
||
* // => false
|
||
*/
|
||
function isTypedArray(value) {
|
||
return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)];
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is `undefined`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
|
||
* @example
|
||
*
|
||
* _.isUndefined(void 0);
|
||
* // => true
|
||
*
|
||
* _.isUndefined(null);
|
||
* // => false
|
||
*/
|
||
function isUndefined(value) {
|
||
return value === undefined;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is less than `other`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to compare.
|
||
* @param {*} other The other value to compare.
|
||
* @returns {boolean} Returns `true` if `value` is less than `other`, else `false`.
|
||
* @example
|
||
*
|
||
* _.lt(1, 3);
|
||
* // => true
|
||
*
|
||
* _.lt(3, 3);
|
||
* // => false
|
||
*
|
||
* _.lt(3, 1);
|
||
* // => false
|
||
*/
|
||
function lt(value, other) {
|
||
return value < other;
|
||
}
|
||
|
||
/**
|
||
* Checks if `value` is less than or equal to `other`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to compare.
|
||
* @param {*} other The other value to compare.
|
||
* @returns {boolean} Returns `true` if `value` is less than or equal to `other`, else `false`.
|
||
* @example
|
||
*
|
||
* _.lte(1, 3);
|
||
* // => true
|
||
*
|
||
* _.lte(3, 3);
|
||
* // => true
|
||
*
|
||
* _.lte(3, 1);
|
||
* // => false
|
||
*/
|
||
function lte(value, other) {
|
||
return value <= other;
|
||
}
|
||
|
||
/**
|
||
* Converts `value` to an array.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to convert.
|
||
* @returns {Array} Returns the converted array.
|
||
* @example
|
||
*
|
||
* (function() {
|
||
* return _.toArray(arguments).slice(1);
|
||
* }(1, 2, 3));
|
||
* // => [2, 3]
|
||
*/
|
||
function toArray(value) {
|
||
var length = value ? getLength(value) : 0;
|
||
if (!isLength(length)) {
|
||
return values(value);
|
||
}
|
||
if (!length) {
|
||
return [];
|
||
}
|
||
return arrayCopy(value);
|
||
}
|
||
|
||
/**
|
||
* Converts `value` to a plain object flattening inherited enumerable
|
||
* properties of `value` to own properties of the plain object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Lang
|
||
* @param {*} value The value to convert.
|
||
* @returns {Object} Returns the converted plain object.
|
||
* @example
|
||
*
|
||
* function Foo() {
|
||
* this.b = 2;
|
||
* }
|
||
*
|
||
* Foo.prototype.c = 3;
|
||
*
|
||
* _.assign({ 'a': 1 }, new Foo);
|
||
* // => { 'a': 1, 'b': 2 }
|
||
*
|
||
* _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
|
||
* // => { 'a': 1, 'b': 2, 'c': 3 }
|
||
*/
|
||
function toPlainObject(value) {
|
||
return baseCopy(value, keysIn(value));
|
||
}
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Recursively merges own enumerable properties of the source object(s), that
|
||
* don't resolve to `undefined` into the destination object. Subsequent sources
|
||
* overwrite property assignments of previous sources. If `customizer` is
|
||
* provided it is invoked to produce the merged values of the destination and
|
||
* source properties. If `customizer` returns `undefined` merging is handled
|
||
* by the method instead. The `customizer` is bound to `thisArg` and invoked
|
||
* with five arguments: (objectValue, sourceValue, key, object, source).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The destination object.
|
||
* @param {...Object} [sources] The source objects.
|
||
* @param {Function} [customizer] The function to customize assigned values.
|
||
* @param {*} [thisArg] The `this` binding of `customizer`.
|
||
* @returns {Object} Returns `object`.
|
||
* @example
|
||
*
|
||
* var users = {
|
||
* 'data': [{ 'user': 'barney' }, { 'user': 'fred' }]
|
||
* };
|
||
*
|
||
* var ages = {
|
||
* 'data': [{ 'age': 36 }, { 'age': 40 }]
|
||
* };
|
||
*
|
||
* _.merge(users, ages);
|
||
* // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] }
|
||
*
|
||
* // using a customizer callback
|
||
* var object = {
|
||
* 'fruits': ['apple'],
|
||
* 'vegetables': ['beet']
|
||
* };
|
||
*
|
||
* var other = {
|
||
* 'fruits': ['banana'],
|
||
* 'vegetables': ['carrot']
|
||
* };
|
||
*
|
||
* _.merge(object, other, function(a, b) {
|
||
* if (_.isArray(a)) {
|
||
* return a.concat(b);
|
||
* }
|
||
* });
|
||
* // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }
|
||
*/
|
||
var merge = createAssigner(baseMerge);
|
||
|
||
/**
|
||
* Assigns own enumerable properties of source object(s) to the destination
|
||
* object. Subsequent sources overwrite property assignments of previous sources.
|
||
* If `customizer` is provided it is invoked to produce the assigned values.
|
||
* The `customizer` is bound to `thisArg` and invoked with five arguments:
|
||
* (objectValue, sourceValue, key, object, source).
|
||
*
|
||
* **Note:** This method mutates `object` and is based on
|
||
* [`Object.assign`](http://ecma-international.org/ecma-262/6.0/#sec-object.assign).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias extend
|
||
* @category Object
|
||
* @param {Object} object The destination object.
|
||
* @param {...Object} [sources] The source objects.
|
||
* @param {Function} [customizer] The function to customize assigned values.
|
||
* @param {*} [thisArg] The `this` binding of `customizer`.
|
||
* @returns {Object} Returns `object`.
|
||
* @example
|
||
*
|
||
* _.assign({ 'user': 'barney' }, { 'age': 40 }, { 'user': 'fred' });
|
||
* // => { 'user': 'fred', 'age': 40 }
|
||
*
|
||
* // using a customizer callback
|
||
* var defaults = _.partialRight(_.assign, function(value, other) {
|
||
* return _.isUndefined(value) ? other : value;
|
||
* });
|
||
*
|
||
* defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' });
|
||
* // => { 'user': 'barney', 'age': 36 }
|
||
*/
|
||
var assign = createAssigner(function(object, source, customizer) {
|
||
return customizer
|
||
? assignWith(object, source, customizer)
|
||
: baseAssign(object, source);
|
||
});
|
||
|
||
/**
|
||
* Creates an object that inherits from the given `prototype` object. If a
|
||
* `properties` object is provided its own enumerable properties are assigned
|
||
* to the created object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} prototype The object to inherit from.
|
||
* @param {Object} [properties] The properties to assign to the object.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {Object} Returns the new object.
|
||
* @example
|
||
*
|
||
* function Shape() {
|
||
* this.x = 0;
|
||
* this.y = 0;
|
||
* }
|
||
*
|
||
* function Circle() {
|
||
* Shape.call(this);
|
||
* }
|
||
*
|
||
* Circle.prototype = _.create(Shape.prototype, {
|
||
* 'constructor': Circle
|
||
* });
|
||
*
|
||
* var circle = new Circle;
|
||
* circle instanceof Circle;
|
||
* // => true
|
||
*
|
||
* circle instanceof Shape;
|
||
* // => true
|
||
*/
|
||
function create(prototype, properties, guard) {
|
||
var result = baseCreate(prototype);
|
||
if (guard && isIterateeCall(prototype, properties, guard)) {
|
||
properties = undefined;
|
||
}
|
||
return properties ? baseAssign(result, properties) : result;
|
||
}
|
||
|
||
/**
|
||
* Assigns own enumerable properties of source object(s) to the destination
|
||
* object for all destination properties that resolve to `undefined`. Once a
|
||
* property is set, additional values of the same property are ignored.
|
||
*
|
||
* **Note:** This method mutates `object`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The destination object.
|
||
* @param {...Object} [sources] The source objects.
|
||
* @returns {Object} Returns `object`.
|
||
* @example
|
||
*
|
||
* _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' });
|
||
* // => { 'user': 'barney', 'age': 36 }
|
||
*/
|
||
var defaults = createDefaults(assign, assignDefaults);
|
||
|
||
/**
|
||
* This method is like `_.defaults` except that it recursively assigns
|
||
* default properties.
|
||
*
|
||
* **Note:** This method mutates `object`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The destination object.
|
||
* @param {...Object} [sources] The source objects.
|
||
* @returns {Object} Returns `object`.
|
||
* @example
|
||
*
|
||
* _.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } });
|
||
* // => { 'user': { 'name': 'barney', 'age': 36 } }
|
||
*
|
||
*/
|
||
var defaultsDeep = createDefaults(merge, mergeDefaults);
|
||
|
||
/**
|
||
* This method is like `_.find` except that it returns the key of the first
|
||
* element `predicate` returns truthy for instead of the element itself.
|
||
*
|
||
* If a property name is provided for `predicate` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `predicate` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to search.
|
||
* @param {Function|Object|string} [predicate=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {string|undefined} Returns the key of the matched element, else `undefined`.
|
||
* @example
|
||
*
|
||
* var users = {
|
||
* 'barney': { 'age': 36, 'active': true },
|
||
* 'fred': { 'age': 40, 'active': false },
|
||
* 'pebbles': { 'age': 1, 'active': true }
|
||
* };
|
||
*
|
||
* _.findKey(users, function(chr) {
|
||
* return chr.age < 40;
|
||
* });
|
||
* // => 'barney' (iteration order is not guaranteed)
|
||
*
|
||
* // using the `_.matches` callback shorthand
|
||
* _.findKey(users, { 'age': 1, 'active': true });
|
||
* // => 'pebbles'
|
||
*
|
||
* // using the `_.matchesProperty` callback shorthand
|
||
* _.findKey(users, 'active', false);
|
||
* // => 'fred'
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.findKey(users, 'active');
|
||
* // => 'barney'
|
||
*/
|
||
var findKey = createFindKey(baseForOwn);
|
||
|
||
/**
|
||
* This method is like `_.findKey` except that it iterates over elements of
|
||
* a collection in the opposite order.
|
||
*
|
||
* If a property name is provided for `predicate` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `predicate` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to search.
|
||
* @param {Function|Object|string} [predicate=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {string|undefined} Returns the key of the matched element, else `undefined`.
|
||
* @example
|
||
*
|
||
* var users = {
|
||
* 'barney': { 'age': 36, 'active': true },
|
||
* 'fred': { 'age': 40, 'active': false },
|
||
* 'pebbles': { 'age': 1, 'active': true }
|
||
* };
|
||
*
|
||
* _.findLastKey(users, function(chr) {
|
||
* return chr.age < 40;
|
||
* });
|
||
* // => returns `pebbles` assuming `_.findKey` returns `barney`
|
||
*
|
||
* // using the `_.matches` callback shorthand
|
||
* _.findLastKey(users, { 'age': 36, 'active': true });
|
||
* // => 'barney'
|
||
*
|
||
* // using the `_.matchesProperty` callback shorthand
|
||
* _.findLastKey(users, 'active', false);
|
||
* // => 'fred'
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.findLastKey(users, 'active');
|
||
* // => 'pebbles'
|
||
*/
|
||
var findLastKey = createFindKey(baseForOwnRight);
|
||
|
||
/**
|
||
* Iterates over own and inherited enumerable properties of an object invoking
|
||
* `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked
|
||
* with three arguments: (value, key, object). Iteratee functions may exit
|
||
* iteration early by explicitly returning `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to iterate over.
|
||
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Object} Returns `object`.
|
||
* @example
|
||
*
|
||
* function Foo() {
|
||
* this.a = 1;
|
||
* this.b = 2;
|
||
* }
|
||
*
|
||
* Foo.prototype.c = 3;
|
||
*
|
||
* _.forIn(new Foo, function(value, key) {
|
||
* console.log(key);
|
||
* });
|
||
* // => logs 'a', 'b', and 'c' (iteration order is not guaranteed)
|
||
*/
|
||
var forIn = createForIn(baseFor);
|
||
|
||
/**
|
||
* This method is like `_.forIn` except that it iterates over properties of
|
||
* `object` in the opposite order.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to iterate over.
|
||
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Object} Returns `object`.
|
||
* @example
|
||
*
|
||
* function Foo() {
|
||
* this.a = 1;
|
||
* this.b = 2;
|
||
* }
|
||
*
|
||
* Foo.prototype.c = 3;
|
||
*
|
||
* _.forInRight(new Foo, function(value, key) {
|
||
* console.log(key);
|
||
* });
|
||
* // => logs 'c', 'b', and 'a' assuming `_.forIn ` logs 'a', 'b', and 'c'
|
||
*/
|
||
var forInRight = createForIn(baseForRight);
|
||
|
||
/**
|
||
* Iterates over own enumerable properties of an object invoking `iteratee`
|
||
* for each property. The `iteratee` is bound to `thisArg` and invoked with
|
||
* three arguments: (value, key, object). Iteratee functions may exit iteration
|
||
* early by explicitly returning `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to iterate over.
|
||
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Object} Returns `object`.
|
||
* @example
|
||
*
|
||
* function Foo() {
|
||
* this.a = 1;
|
||
* this.b = 2;
|
||
* }
|
||
*
|
||
* Foo.prototype.c = 3;
|
||
*
|
||
* _.forOwn(new Foo, function(value, key) {
|
||
* console.log(key);
|
||
* });
|
||
* // => logs 'a' and 'b' (iteration order is not guaranteed)
|
||
*/
|
||
var forOwn = createForOwn(baseForOwn);
|
||
|
||
/**
|
||
* This method is like `_.forOwn` except that it iterates over properties of
|
||
* `object` in the opposite order.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to iterate over.
|
||
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Object} Returns `object`.
|
||
* @example
|
||
*
|
||
* function Foo() {
|
||
* this.a = 1;
|
||
* this.b = 2;
|
||
* }
|
||
*
|
||
* Foo.prototype.c = 3;
|
||
*
|
||
* _.forOwnRight(new Foo, function(value, key) {
|
||
* console.log(key);
|
||
* });
|
||
* // => logs 'b' and 'a' assuming `_.forOwn` logs 'a' and 'b'
|
||
*/
|
||
var forOwnRight = createForOwn(baseForOwnRight);
|
||
|
||
/**
|
||
* Creates an array of function property names from all enumerable properties,
|
||
* own and inherited, of `object`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias methods
|
||
* @category Object
|
||
* @param {Object} object The object to inspect.
|
||
* @returns {Array} Returns the new array of property names.
|
||
* @example
|
||
*
|
||
* _.functions(_);
|
||
* // => ['after', 'ary', 'assign', ...]
|
||
*/
|
||
function functions(object) {
|
||
return baseFunctions(object, keysIn(object));
|
||
}
|
||
|
||
/**
|
||
* Gets the property value at `path` of `object`. If the resolved value is
|
||
* `undefined` the `defaultValue` is used in its place.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to query.
|
||
* @param {Array|string} path The path of the property to get.
|
||
* @param {*} [defaultValue] The value returned if the resolved value is `undefined`.
|
||
* @returns {*} Returns the resolved value.
|
||
* @example
|
||
*
|
||
* var object = { 'a': [{ 'b': { 'c': 3 } }] };
|
||
*
|
||
* _.get(object, 'a[0].b.c');
|
||
* // => 3
|
||
*
|
||
* _.get(object, ['a', '0', 'b', 'c']);
|
||
* // => 3
|
||
*
|
||
* _.get(object, 'a.b.c', 'default');
|
||
* // => 'default'
|
||
*/
|
||
function get(object, path, defaultValue) {
|
||
var result = object == null ? undefined : baseGet(object, toPath(path), path + '');
|
||
return result === undefined ? defaultValue : result;
|
||
}
|
||
|
||
/**
|
||
* Checks if `path` is a direct property.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to query.
|
||
* @param {Array|string} path The path to check.
|
||
* @returns {boolean} Returns `true` if `path` is a direct property, else `false`.
|
||
* @example
|
||
*
|
||
* var object = { 'a': { 'b': { 'c': 3 } } };
|
||
*
|
||
* _.has(object, 'a');
|
||
* // => true
|
||
*
|
||
* _.has(object, 'a.b.c');
|
||
* // => true
|
||
*
|
||
* _.has(object, ['a', 'b', 'c']);
|
||
* // => true
|
||
*/
|
||
function has(object, path) {
|
||
if (object == null) {
|
||
return false;
|
||
}
|
||
var result = hasOwnProperty.call(object, path);
|
||
if (!result && !isKey(path)) {
|
||
path = toPath(path);
|
||
object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
|
||
if (object == null) {
|
||
return false;
|
||
}
|
||
path = last(path);
|
||
result = hasOwnProperty.call(object, path);
|
||
}
|
||
return result || (isLength(object.length) && isIndex(path, object.length) &&
|
||
(isArray(object) || isArguments(object)));
|
||
}
|
||
|
||
/**
|
||
* Creates an object composed of the inverted keys and values of `object`.
|
||
* If `object` contains duplicate values, subsequent values overwrite property
|
||
* assignments of previous values unless `multiValue` is `true`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to invert.
|
||
* @param {boolean} [multiValue] Allow multiple values per key.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {Object} Returns the new inverted object.
|
||
* @example
|
||
*
|
||
* var object = { 'a': 1, 'b': 2, 'c': 1 };
|
||
*
|
||
* _.invert(object);
|
||
* // => { '1': 'c', '2': 'b' }
|
||
*
|
||
* // with `multiValue`
|
||
* _.invert(object, true);
|
||
* // => { '1': ['a', 'c'], '2': ['b'] }
|
||
*/
|
||
function invert(object, multiValue, guard) {
|
||
if (guard && isIterateeCall(object, multiValue, guard)) {
|
||
multiValue = undefined;
|
||
}
|
||
var index = -1,
|
||
props = keys(object),
|
||
length = props.length,
|
||
result = {};
|
||
|
||
while (++index < length) {
|
||
var key = props[index],
|
||
value = object[key];
|
||
|
||
if (multiValue) {
|
||
if (hasOwnProperty.call(result, value)) {
|
||
result[value].push(key);
|
||
} else {
|
||
result[value] = [key];
|
||
}
|
||
}
|
||
else {
|
||
result[value] = key;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Creates an array of the own enumerable property names of `object`.
|
||
*
|
||
* **Note:** Non-object values are coerced to objects. See the
|
||
* [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)
|
||
* for more details.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to query.
|
||
* @returns {Array} Returns the array of property names.
|
||
* @example
|
||
*
|
||
* function Foo() {
|
||
* this.a = 1;
|
||
* this.b = 2;
|
||
* }
|
||
*
|
||
* Foo.prototype.c = 3;
|
||
*
|
||
* _.keys(new Foo);
|
||
* // => ['a', 'b'] (iteration order is not guaranteed)
|
||
*
|
||
* _.keys('hi');
|
||
* // => ['0', '1']
|
||
*/
|
||
var keys = !nativeKeys ? shimKeys : function(object) {
|
||
var Ctor = object == null ? undefined : object.constructor;
|
||
if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
|
||
(typeof object != 'function' && isArrayLike(object))) {
|
||
return shimKeys(object);
|
||
}
|
||
return isObject(object) ? nativeKeys(object) : [];
|
||
};
|
||
|
||
/**
|
||
* Creates an array of the own and inherited enumerable property names of `object`.
|
||
*
|
||
* **Note:** Non-object values are coerced to objects.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to query.
|
||
* @returns {Array} Returns the array of property names.
|
||
* @example
|
||
*
|
||
* function Foo() {
|
||
* this.a = 1;
|
||
* this.b = 2;
|
||
* }
|
||
*
|
||
* Foo.prototype.c = 3;
|
||
*
|
||
* _.keysIn(new Foo);
|
||
* // => ['a', 'b', 'c'] (iteration order is not guaranteed)
|
||
*/
|
||
function keysIn(object) {
|
||
if (object == null) {
|
||
return [];
|
||
}
|
||
if (!isObject(object)) {
|
||
object = Object(object);
|
||
}
|
||
var length = object.length;
|
||
length = (length && isLength(length) &&
|
||
(isArray(object) || isArguments(object)) && length) || 0;
|
||
|
||
var Ctor = object.constructor,
|
||
index = -1,
|
||
isProto = typeof Ctor == 'function' && Ctor.prototype === object,
|
||
result = Array(length),
|
||
skipIndexes = length > 0;
|
||
|
||
while (++index < length) {
|
||
result[index] = (index + '');
|
||
}
|
||
for (var key in object) {
|
||
if (!(skipIndexes && isIndex(key, length)) &&
|
||
!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
|
||
result.push(key);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* The opposite of `_.mapValues`; this method creates an object with the
|
||
* same values as `object` and keys generated by running each own enumerable
|
||
* property of `object` through `iteratee`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to iterate over.
|
||
* @param {Function|Object|string} [iteratee=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Object} Returns the new mapped object.
|
||
* @example
|
||
*
|
||
* _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
|
||
* return key + value;
|
||
* });
|
||
* // => { 'a1': 1, 'b2': 2 }
|
||
*/
|
||
var mapKeys = createObjectMapper(true);
|
||
|
||
/**
|
||
* Creates an object with the same keys as `object` and values generated by
|
||
* running each own enumerable property of `object` through `iteratee`. The
|
||
* iteratee function is bound to `thisArg` and invoked with three arguments:
|
||
* (value, key, object).
|
||
*
|
||
* If a property name is provided for `iteratee` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `iteratee` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to iterate over.
|
||
* @param {Function|Object|string} [iteratee=_.identity] The function invoked
|
||
* per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Object} Returns the new mapped object.
|
||
* @example
|
||
*
|
||
* _.mapValues({ 'a': 1, 'b': 2 }, function(n) {
|
||
* return n * 3;
|
||
* });
|
||
* // => { 'a': 3, 'b': 6 }
|
||
*
|
||
* var users = {
|
||
* 'fred': { 'user': 'fred', 'age': 40 },
|
||
* 'pebbles': { 'user': 'pebbles', 'age': 1 }
|
||
* };
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.mapValues(users, 'age');
|
||
* // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
|
||
*/
|
||
var mapValues = createObjectMapper();
|
||
|
||
/**
|
||
* The opposite of `_.pick`; this method creates an object composed of the
|
||
* own and inherited enumerable properties of `object` that are not omitted.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The source object.
|
||
* @param {Function|...(string|string[])} [predicate] The function invoked per
|
||
* iteration or property names to omit, specified as individual property
|
||
* names or arrays of property names.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {Object} Returns the new object.
|
||
* @example
|
||
*
|
||
* var object = { 'user': 'fred', 'age': 40 };
|
||
*
|
||
* _.omit(object, 'age');
|
||
* // => { 'user': 'fred' }
|
||
*
|
||
* _.omit(object, _.isNumber);
|
||
* // => { 'user': 'fred' }
|
||
*/
|
||
var omit = restParam(function(object, props) {
|
||
if (object == null) {
|
||
return {};
|
||
}
|
||
if (typeof props[0] != 'function') {
|
||
var props = arrayMap(baseFlatten(props), String);
|
||
return pickByArray(object, baseDifference(keysIn(object), props));
|
||
}
|
||
var predicate = bindCallback(props[0], props[1], 3);
|
||
return pickByCallback(object, function(value, key, object) {
|
||
return !predicate(value, key, object);
|
||
});
|
||
});
|
||
|
||
/**
|
||
* Creates a two dimensional array of the key-value pairs for `object`,
|
||
* e.g. `[[key1, value1], [key2, value2]]`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to query.
|
||
* @returns {Array} Returns the new array of key-value pairs.
|
||
* @example
|
||
*
|
||
* _.pairs({ 'barney': 36, 'fred': 40 });
|
||
* // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed)
|
||
*/
|
||
function pairs(object) {
|
||
object = toObject(object);
|
||
|
||
var index = -1,
|
||
props = keys(object),
|
||
length = props.length,
|
||
result = Array(length);
|
||
|
||
while (++index < length) {
|
||
var key = props[index];
|
||
result[index] = [key, object[key]];
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Creates an object composed of the picked `object` properties. Property
|
||
* names may be specified as individual arguments or as arrays of property
|
||
* names. If `predicate` is provided it is invoked for each property of `object`
|
||
* picking the properties `predicate` returns truthy for. The predicate is
|
||
* bound to `thisArg` and invoked with three arguments: (value, key, object).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The source object.
|
||
* @param {Function|...(string|string[])} [predicate] The function invoked per
|
||
* iteration or property names to pick, specified as individual property
|
||
* names or arrays of property names.
|
||
* @param {*} [thisArg] The `this` binding of `predicate`.
|
||
* @returns {Object} Returns the new object.
|
||
* @example
|
||
*
|
||
* var object = { 'user': 'fred', 'age': 40 };
|
||
*
|
||
* _.pick(object, 'user');
|
||
* // => { 'user': 'fred' }
|
||
*
|
||
* _.pick(object, _.isString);
|
||
* // => { 'user': 'fred' }
|
||
*/
|
||
var pick = restParam(function(object, props) {
|
||
if (object == null) {
|
||
return {};
|
||
}
|
||
return typeof props[0] == 'function'
|
||
? pickByCallback(object, bindCallback(props[0], props[1], 3))
|
||
: pickByArray(object, baseFlatten(props));
|
||
});
|
||
|
||
/**
|
||
* This method is like `_.get` except that if the resolved value is a function
|
||
* it is invoked with the `this` binding of its parent object and its result
|
||
* is returned.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to query.
|
||
* @param {Array|string} path The path of the property to resolve.
|
||
* @param {*} [defaultValue] The value returned if the resolved value is `undefined`.
|
||
* @returns {*} Returns the resolved value.
|
||
* @example
|
||
*
|
||
* var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
|
||
*
|
||
* _.result(object, 'a[0].b.c1');
|
||
* // => 3
|
||
*
|
||
* _.result(object, 'a[0].b.c2');
|
||
* // => 4
|
||
*
|
||
* _.result(object, 'a.b.c', 'default');
|
||
* // => 'default'
|
||
*
|
||
* _.result(object, 'a.b.c', _.constant('default'));
|
||
* // => 'default'
|
||
*/
|
||
function result(object, path, defaultValue) {
|
||
var result = object == null ? undefined : object[path];
|
||
if (result === undefined) {
|
||
if (object != null && !isKey(path, object)) {
|
||
path = toPath(path);
|
||
object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
|
||
result = object == null ? undefined : object[last(path)];
|
||
}
|
||
result = result === undefined ? defaultValue : result;
|
||
}
|
||
return isFunction(result) ? result.call(object) : result;
|
||
}
|
||
|
||
/**
|
||
* Sets the property value of `path` on `object`. If a portion of `path`
|
||
* does not exist it is created.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to augment.
|
||
* @param {Array|string} path The path of the property to set.
|
||
* @param {*} value The value to set.
|
||
* @returns {Object} Returns `object`.
|
||
* @example
|
||
*
|
||
* var object = { 'a': [{ 'b': { 'c': 3 } }] };
|
||
*
|
||
* _.set(object, 'a[0].b.c', 4);
|
||
* console.log(object.a[0].b.c);
|
||
* // => 4
|
||
*
|
||
* _.set(object, 'x[0].y.z', 5);
|
||
* console.log(object.x[0].y.z);
|
||
* // => 5
|
||
*/
|
||
function set(object, path, value) {
|
||
if (object == null) {
|
||
return object;
|
||
}
|
||
var pathKey = (path + '');
|
||
path = (object[pathKey] != null || isKey(path, object)) ? [pathKey] : toPath(path);
|
||
|
||
var index = -1,
|
||
length = path.length,
|
||
lastIndex = length - 1,
|
||
nested = object;
|
||
|
||
while (nested != null && ++index < length) {
|
||
var key = path[index];
|
||
if (isObject(nested)) {
|
||
if (index == lastIndex) {
|
||
nested[key] = value;
|
||
} else if (nested[key] == null) {
|
||
nested[key] = isIndex(path[index + 1]) ? [] : {};
|
||
}
|
||
}
|
||
nested = nested[key];
|
||
}
|
||
return object;
|
||
}
|
||
|
||
/**
|
||
* An alternative to `_.reduce`; this method transforms `object` to a new
|
||
* `accumulator` object which is the result of running each of its own enumerable
|
||
* properties through `iteratee`, with each invocation potentially mutating
|
||
* the `accumulator` object. The `iteratee` is bound to `thisArg` and invoked
|
||
* with four arguments: (accumulator, value, key, object). Iteratee functions
|
||
* may exit iteration early by explicitly returning `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Array|Object} object The object to iterate over.
|
||
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
||
* @param {*} [accumulator] The custom accumulator value.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {*} Returns the accumulated value.
|
||
* @example
|
||
*
|
||
* _.transform([2, 3, 4], function(result, n) {
|
||
* result.push(n *= n);
|
||
* return n % 2 == 0;
|
||
* });
|
||
* // => [4, 9]
|
||
*
|
||
* _.transform({ 'a': 1, 'b': 2 }, function(result, n, key) {
|
||
* result[key] = n * 3;
|
||
* });
|
||
* // => { 'a': 3, 'b': 6 }
|
||
*/
|
||
function transform(object, iteratee, accumulator, thisArg) {
|
||
var isArr = isArray(object) || isTypedArray(object);
|
||
iteratee = getCallback(iteratee, thisArg, 4);
|
||
|
||
if (accumulator == null) {
|
||
if (isArr || isObject(object)) {
|
||
var Ctor = object.constructor;
|
||
if (isArr) {
|
||
accumulator = isArray(object) ? new Ctor : [];
|
||
} else {
|
||
accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined);
|
||
}
|
||
} else {
|
||
accumulator = {};
|
||
}
|
||
}
|
||
(isArr ? arrayEach : baseForOwn)(object, function(value, index, object) {
|
||
return iteratee(accumulator, value, index, object);
|
||
});
|
||
return accumulator;
|
||
}
|
||
|
||
/**
|
||
* Creates an array of the own enumerable property values of `object`.
|
||
*
|
||
* **Note:** Non-object values are coerced to objects.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to query.
|
||
* @returns {Array} Returns the array of property values.
|
||
* @example
|
||
*
|
||
* function Foo() {
|
||
* this.a = 1;
|
||
* this.b = 2;
|
||
* }
|
||
*
|
||
* Foo.prototype.c = 3;
|
||
*
|
||
* _.values(new Foo);
|
||
* // => [1, 2] (iteration order is not guaranteed)
|
||
*
|
||
* _.values('hi');
|
||
* // => ['h', 'i']
|
||
*/
|
||
function values(object) {
|
||
return baseValues(object, keys(object));
|
||
}
|
||
|
||
/**
|
||
* Creates an array of the own and inherited enumerable property values
|
||
* of `object`.
|
||
*
|
||
* **Note:** Non-object values are coerced to objects.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Object
|
||
* @param {Object} object The object to query.
|
||
* @returns {Array} Returns the array of property values.
|
||
* @example
|
||
*
|
||
* function Foo() {
|
||
* this.a = 1;
|
||
* this.b = 2;
|
||
* }
|
||
*
|
||
* Foo.prototype.c = 3;
|
||
*
|
||
* _.valuesIn(new Foo);
|
||
* // => [1, 2, 3] (iteration order is not guaranteed)
|
||
*/
|
||
function valuesIn(object) {
|
||
return baseValues(object, keysIn(object));
|
||
}
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Checks if `n` is between `start` and up to but not including, `end`. If
|
||
* `end` is not specified it is set to `start` with `start` then set to `0`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Number
|
||
* @param {number} n The number to check.
|
||
* @param {number} [start=0] The start of the range.
|
||
* @param {number} end The end of the range.
|
||
* @returns {boolean} Returns `true` if `n` is in the range, else `false`.
|
||
* @example
|
||
*
|
||
* _.inRange(3, 2, 4);
|
||
* // => true
|
||
*
|
||
* _.inRange(4, 8);
|
||
* // => true
|
||
*
|
||
* _.inRange(4, 2);
|
||
* // => false
|
||
*
|
||
* _.inRange(2, 2);
|
||
* // => false
|
||
*
|
||
* _.inRange(1.2, 2);
|
||
* // => true
|
||
*
|
||
* _.inRange(5.2, 4);
|
||
* // => false
|
||
*/
|
||
function inRange(value, start, end) {
|
||
start = +start || 0;
|
||
if (end === undefined) {
|
||
end = start;
|
||
start = 0;
|
||
} else {
|
||
end = +end || 0;
|
||
}
|
||
return value >= nativeMin(start, end) && value < nativeMax(start, end);
|
||
}
|
||
|
||
/**
|
||
* Produces a random number between `min` and `max` (inclusive). If only one
|
||
* argument is provided a number between `0` and the given number is returned.
|
||
* If `floating` is `true`, or either `min` or `max` are floats, a floating-point
|
||
* number is returned instead of an integer.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Number
|
||
* @param {number} [min=0] The minimum possible value.
|
||
* @param {number} [max=1] The maximum possible value.
|
||
* @param {boolean} [floating] Specify returning a floating-point number.
|
||
* @returns {number} Returns the random number.
|
||
* @example
|
||
*
|
||
* _.random(0, 5);
|
||
* // => an integer between 0 and 5
|
||
*
|
||
* _.random(5);
|
||
* // => also an integer between 0 and 5
|
||
*
|
||
* _.random(5, true);
|
||
* // => a floating-point number between 0 and 5
|
||
*
|
||
* _.random(1.2, 5.2);
|
||
* // => a floating-point number between 1.2 and 5.2
|
||
*/
|
||
function random(min, max, floating) {
|
||
if (floating && isIterateeCall(min, max, floating)) {
|
||
max = floating = undefined;
|
||
}
|
||
var noMin = min == null,
|
||
noMax = max == null;
|
||
|
||
if (floating == null) {
|
||
if (noMax && typeof min == 'boolean') {
|
||
floating = min;
|
||
min = 1;
|
||
}
|
||
else if (typeof max == 'boolean') {
|
||
floating = max;
|
||
noMax = true;
|
||
}
|
||
}
|
||
if (noMin && noMax) {
|
||
max = 1;
|
||
noMax = false;
|
||
}
|
||
min = +min || 0;
|
||
if (noMax) {
|
||
max = min;
|
||
min = 0;
|
||
} else {
|
||
max = +max || 0;
|
||
}
|
||
if (floating || min % 1 || max % 1) {
|
||
var rand = nativeRandom();
|
||
return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand + '').length - 1)))), max);
|
||
}
|
||
return baseRandom(min, max);
|
||
}
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to convert.
|
||
* @returns {string} Returns the camel cased string.
|
||
* @example
|
||
*
|
||
* _.camelCase('Foo Bar');
|
||
* // => 'fooBar'
|
||
*
|
||
* _.camelCase('--foo-bar');
|
||
* // => 'fooBar'
|
||
*
|
||
* _.camelCase('__foo_bar__');
|
||
* // => 'fooBar'
|
||
*/
|
||
var camelCase = createCompounder(function(result, word, index) {
|
||
word = word.toLowerCase();
|
||
return result + (index ? (word.charAt(0).toUpperCase() + word.slice(1)) : word);
|
||
});
|
||
|
||
/**
|
||
* Capitalizes the first character of `string`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to capitalize.
|
||
* @returns {string} Returns the capitalized string.
|
||
* @example
|
||
*
|
||
* _.capitalize('fred');
|
||
* // => 'Fred'
|
||
*/
|
||
function capitalize(string) {
|
||
string = baseToString(string);
|
||
return string && (string.charAt(0).toUpperCase() + string.slice(1));
|
||
}
|
||
|
||
/**
|
||
* Deburrs `string` by converting [latin-1 supplementary letters](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
|
||
* to basic latin letters and removing [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to deburr.
|
||
* @returns {string} Returns the deburred string.
|
||
* @example
|
||
*
|
||
* _.deburr('déjà vu');
|
||
* // => 'deja vu'
|
||
*/
|
||
function deburr(string) {
|
||
string = baseToString(string);
|
||
return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, '');
|
||
}
|
||
|
||
/**
|
||
* Checks if `string` ends with the given target string.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to search.
|
||
* @param {string} [target] The string to search for.
|
||
* @param {number} [position=string.length] The position to search from.
|
||
* @returns {boolean} Returns `true` if `string` ends with `target`, else `false`.
|
||
* @example
|
||
*
|
||
* _.endsWith('abc', 'c');
|
||
* // => true
|
||
*
|
||
* _.endsWith('abc', 'b');
|
||
* // => false
|
||
*
|
||
* _.endsWith('abc', 'b', 2);
|
||
* // => true
|
||
*/
|
||
function endsWith(string, target, position) {
|
||
string = baseToString(string);
|
||
target = (target + '');
|
||
|
||
var length = string.length;
|
||
position = position === undefined
|
||
? length
|
||
: nativeMin(position < 0 ? 0 : (+position || 0), length);
|
||
|
||
position -= target.length;
|
||
return position >= 0 && string.indexOf(target, position) == position;
|
||
}
|
||
|
||
/**
|
||
* Converts the characters "&", "<", ">", '"', "'", and "\`", in `string` to
|
||
* their corresponding HTML entities.
|
||
*
|
||
* **Note:** No other characters are escaped. To escape additional characters
|
||
* use a third-party library like [_he_](https://mths.be/he).
|
||
*
|
||
* Though the ">" character is escaped for symmetry, characters like
|
||
* ">" and "/" don't need escaping in HTML and have no special meaning
|
||
* unless they're part of a tag or unquoted attribute value.
|
||
* See [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
|
||
* (under "semi-related fun fact") for more details.
|
||
*
|
||
* Backticks are escaped because in Internet Explorer < 9, they can break out
|
||
* of attribute values or HTML comments. See [#59](https://html5sec.org/#59),
|
||
* [#102](https://html5sec.org/#102), [#108](https://html5sec.org/#108), and
|
||
* [#133](https://html5sec.org/#133) of the [HTML5 Security Cheatsheet](https://html5sec.org/)
|
||
* for more details.
|
||
*
|
||
* When working with HTML you should always [quote attribute values](http://wonko.com/post/html-escaping)
|
||
* to reduce XSS vectors.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to escape.
|
||
* @returns {string} Returns the escaped string.
|
||
* @example
|
||
*
|
||
* _.escape('fred, barney, & pebbles');
|
||
* // => 'fred, barney, & pebbles'
|
||
*/
|
||
function escape(string) {
|
||
// Reset `lastIndex` because in IE < 9 `String#replace` does not.
|
||
string = baseToString(string);
|
||
return (string && reHasUnescapedHtml.test(string))
|
||
? string.replace(reUnescapedHtml, escapeHtmlChar)
|
||
: string;
|
||
}
|
||
|
||
/**
|
||
* Escapes the `RegExp` special characters "\", "/", "^", "$", ".", "|", "?",
|
||
* "*", "+", "(", ")", "[", "]", "{" and "}" in `string`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to escape.
|
||
* @returns {string} Returns the escaped string.
|
||
* @example
|
||
*
|
||
* _.escapeRegExp('[lodash](https://lodash.com/)');
|
||
* // => '\[lodash\]\(https:\/\/lodash\.com\/\)'
|
||
*/
|
||
function escapeRegExp(string) {
|
||
string = baseToString(string);
|
||
return (string && reHasRegExpChars.test(string))
|
||
? string.replace(reRegExpChars, escapeRegExpChar)
|
||
: (string || '(?:)');
|
||
}
|
||
|
||
/**
|
||
* Converts `string` to [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to convert.
|
||
* @returns {string} Returns the kebab cased string.
|
||
* @example
|
||
*
|
||
* _.kebabCase('Foo Bar');
|
||
* // => 'foo-bar'
|
||
*
|
||
* _.kebabCase('fooBar');
|
||
* // => 'foo-bar'
|
||
*
|
||
* _.kebabCase('__foo_bar__');
|
||
* // => 'foo-bar'
|
||
*/
|
||
var kebabCase = createCompounder(function(result, word, index) {
|
||
return result + (index ? '-' : '') + word.toLowerCase();
|
||
});
|
||
|
||
/**
|
||
* Pads `string` on the left and right sides if it's shorter than `length`.
|
||
* Padding characters are truncated if they can't be evenly divided by `length`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to pad.
|
||
* @param {number} [length=0] The padding length.
|
||
* @param {string} [chars=' '] The string used as padding.
|
||
* @returns {string} Returns the padded string.
|
||
* @example
|
||
*
|
||
* _.pad('abc', 8);
|
||
* // => ' abc '
|
||
*
|
||
* _.pad('abc', 8, '_-');
|
||
* // => '_-abc_-_'
|
||
*
|
||
* _.pad('abc', 3);
|
||
* // => 'abc'
|
||
*/
|
||
function pad(string, length, chars) {
|
||
string = baseToString(string);
|
||
length = +length;
|
||
|
||
var strLength = string.length;
|
||
if (strLength >= length || !nativeIsFinite(length)) {
|
||
return string;
|
||
}
|
||
var mid = (length - strLength) / 2,
|
||
leftLength = nativeFloor(mid),
|
||
rightLength = nativeCeil(mid);
|
||
|
||
chars = createPadding('', rightLength, chars);
|
||
return chars.slice(0, leftLength) + string + chars;
|
||
}
|
||
|
||
/**
|
||
* Pads `string` on the left side if it's shorter than `length`. Padding
|
||
* characters are truncated if they exceed `length`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to pad.
|
||
* @param {number} [length=0] The padding length.
|
||
* @param {string} [chars=' '] The string used as padding.
|
||
* @returns {string} Returns the padded string.
|
||
* @example
|
||
*
|
||
* _.padLeft('abc', 6);
|
||
* // => ' abc'
|
||
*
|
||
* _.padLeft('abc', 6, '_-');
|
||
* // => '_-_abc'
|
||
*
|
||
* _.padLeft('abc', 3);
|
||
* // => 'abc'
|
||
*/
|
||
var padLeft = createPadDir();
|
||
|
||
/**
|
||
* Pads `string` on the right side if it's shorter than `length`. Padding
|
||
* characters are truncated if they exceed `length`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to pad.
|
||
* @param {number} [length=0] The padding length.
|
||
* @param {string} [chars=' '] The string used as padding.
|
||
* @returns {string} Returns the padded string.
|
||
* @example
|
||
*
|
||
* _.padRight('abc', 6);
|
||
* // => 'abc '
|
||
*
|
||
* _.padRight('abc', 6, '_-');
|
||
* // => 'abc_-_'
|
||
*
|
||
* _.padRight('abc', 3);
|
||
* // => 'abc'
|
||
*/
|
||
var padRight = createPadDir(true);
|
||
|
||
/**
|
||
* Converts `string` to an integer of the specified radix. If `radix` is
|
||
* `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal,
|
||
* in which case a `radix` of `16` is used.
|
||
*
|
||
* **Note:** This method aligns with the [ES5 implementation](https://es5.github.io/#E)
|
||
* of `parseInt`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} string The string to convert.
|
||
* @param {number} [radix] The radix to interpret `value` by.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {number} Returns the converted integer.
|
||
* @example
|
||
*
|
||
* _.parseInt('08');
|
||
* // => 8
|
||
*
|
||
* _.map(['6', '08', '10'], _.parseInt);
|
||
* // => [6, 8, 10]
|
||
*/
|
||
function parseInt(string, radix, guard) {
|
||
// Firefox < 21 and Opera < 15 follow ES3 for `parseInt`.
|
||
// Chrome fails to trim leading <BOM> whitespace characters.
|
||
// See https://code.google.com/p/v8/issues/detail?id=3109 for more details.
|
||
if (guard ? isIterateeCall(string, radix, guard) : radix == null) {
|
||
radix = 0;
|
||
} else if (radix) {
|
||
radix = +radix;
|
||
}
|
||
string = trim(string);
|
||
return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10));
|
||
}
|
||
|
||
/**
|
||
* Repeats the given string `n` times.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to repeat.
|
||
* @param {number} [n=0] The number of times to repeat the string.
|
||
* @returns {string} Returns the repeated string.
|
||
* @example
|
||
*
|
||
* _.repeat('*', 3);
|
||
* // => '***'
|
||
*
|
||
* _.repeat('abc', 2);
|
||
* // => 'abcabc'
|
||
*
|
||
* _.repeat('abc', 0);
|
||
* // => ''
|
||
*/
|
||
function repeat(string, n) {
|
||
var result = '';
|
||
string = baseToString(string);
|
||
n = +n;
|
||
if (n < 1 || !string || !nativeIsFinite(n)) {
|
||
return result;
|
||
}
|
||
// Leverage the exponentiation by squaring algorithm for a faster repeat.
|
||
// See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
|
||
do {
|
||
if (n % 2) {
|
||
result += string;
|
||
}
|
||
n = nativeFloor(n / 2);
|
||
string += string;
|
||
} while (n);
|
||
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Converts `string` to [snake case](https://en.wikipedia.org/wiki/Snake_case).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to convert.
|
||
* @returns {string} Returns the snake cased string.
|
||
* @example
|
||
*
|
||
* _.snakeCase('Foo Bar');
|
||
* // => 'foo_bar'
|
||
*
|
||
* _.snakeCase('fooBar');
|
||
* // => 'foo_bar'
|
||
*
|
||
* _.snakeCase('--foo-bar');
|
||
* // => 'foo_bar'
|
||
*/
|
||
var snakeCase = createCompounder(function(result, word, index) {
|
||
return result + (index ? '_' : '') + word.toLowerCase();
|
||
});
|
||
|
||
/**
|
||
* Converts `string` to [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to convert.
|
||
* @returns {string} Returns the start cased string.
|
||
* @example
|
||
*
|
||
* _.startCase('--foo-bar');
|
||
* // => 'Foo Bar'
|
||
*
|
||
* _.startCase('fooBar');
|
||
* // => 'Foo Bar'
|
||
*
|
||
* _.startCase('__foo_bar__');
|
||
* // => 'Foo Bar'
|
||
*/
|
||
var startCase = createCompounder(function(result, word, index) {
|
||
return result + (index ? ' ' : '') + (word.charAt(0).toUpperCase() + word.slice(1));
|
||
});
|
||
|
||
/**
|
||
* Checks if `string` starts with the given target string.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to search.
|
||
* @param {string} [target] The string to search for.
|
||
* @param {number} [position=0] The position to search from.
|
||
* @returns {boolean} Returns `true` if `string` starts with `target`, else `false`.
|
||
* @example
|
||
*
|
||
* _.startsWith('abc', 'a');
|
||
* // => true
|
||
*
|
||
* _.startsWith('abc', 'b');
|
||
* // => false
|
||
*
|
||
* _.startsWith('abc', 'b', 1);
|
||
* // => true
|
||
*/
|
||
function startsWith(string, target, position) {
|
||
string = baseToString(string);
|
||
position = position == null
|
||
? 0
|
||
: nativeMin(position < 0 ? 0 : (+position || 0), string.length);
|
||
|
||
return string.lastIndexOf(target, position) == position;
|
||
}
|
||
|
||
/**
|
||
* Creates a compiled template function that can interpolate data properties
|
||
* in "interpolate" delimiters, HTML-escape interpolated data properties in
|
||
* "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
|
||
* properties may be accessed as free variables in the template. If a setting
|
||
* object is provided it takes precedence over `_.templateSettings` values.
|
||
*
|
||
* **Note:** In the development build `_.template` utilizes
|
||
* [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
|
||
* for easier debugging.
|
||
*
|
||
* For more information on precompiling templates see
|
||
* [lodash's custom builds documentation](https://lodash.com/custom-builds).
|
||
*
|
||
* For more information on Chrome extension sandboxes see
|
||
* [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The template string.
|
||
* @param {Object} [options] The options object.
|
||
* @param {RegExp} [options.escape] The HTML "escape" delimiter.
|
||
* @param {RegExp} [options.evaluate] The "evaluate" delimiter.
|
||
* @param {Object} [options.imports] An object to import into the template as free variables.
|
||
* @param {RegExp} [options.interpolate] The "interpolate" delimiter.
|
||
* @param {string} [options.sourceURL] The sourceURL of the template's compiled source.
|
||
* @param {string} [options.variable] The data object variable name.
|
||
* @param- {Object} [otherOptions] Enables the legacy `options` param signature.
|
||
* @returns {Function} Returns the compiled template function.
|
||
* @example
|
||
*
|
||
* // using the "interpolate" delimiter to create a compiled template
|
||
* var compiled = _.template('hello <%= user %>!');
|
||
* compiled({ 'user': 'fred' });
|
||
* // => 'hello fred!'
|
||
*
|
||
* // using the HTML "escape" delimiter to escape data property values
|
||
* var compiled = _.template('<b><%- value %></b>');
|
||
* compiled({ 'value': '<script>' });
|
||
* // => '<b><script></b>'
|
||
*
|
||
* // using the "evaluate" delimiter to execute JavaScript and generate HTML
|
||
* var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
|
||
* compiled({ 'users': ['fred', 'barney'] });
|
||
* // => '<li>fred</li><li>barney</li>'
|
||
*
|
||
* // using the internal `print` function in "evaluate" delimiters
|
||
* var compiled = _.template('<% print("hello " + user); %>!');
|
||
* compiled({ 'user': 'barney' });
|
||
* // => 'hello barney!'
|
||
*
|
||
* // using the ES delimiter as an alternative to the default "interpolate" delimiter
|
||
* var compiled = _.template('hello ${ user }!');
|
||
* compiled({ 'user': 'pebbles' });
|
||
* // => 'hello pebbles!'
|
||
*
|
||
* // using custom template delimiters
|
||
* _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
|
||
* var compiled = _.template('hello {{ user }}!');
|
||
* compiled({ 'user': 'mustache' });
|
||
* // => 'hello mustache!'
|
||
*
|
||
* // using backslashes to treat delimiters as plain text
|
||
* var compiled = _.template('<%= "\\<%- value %\\>" %>');
|
||
* compiled({ 'value': 'ignored' });
|
||
* // => '<%- value %>'
|
||
*
|
||
* // using the `imports` option to import `jQuery` as `jq`
|
||
* var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
|
||
* var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
|
||
* compiled({ 'users': ['fred', 'barney'] });
|
||
* // => '<li>fred</li><li>barney</li>'
|
||
*
|
||
* // using the `sourceURL` option to specify a custom sourceURL for the template
|
||
* var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
|
||
* compiled(data);
|
||
* // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
|
||
*
|
||
* // using the `variable` option to ensure a with-statement isn't used in the compiled template
|
||
* var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
|
||
* compiled.source;
|
||
* // => function(data) {
|
||
* // var __t, __p = '';
|
||
* // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
|
||
* // return __p;
|
||
* // }
|
||
*
|
||
* // using the `source` property to inline compiled templates for meaningful
|
||
* // line numbers in error messages and a stack trace
|
||
* fs.writeFileSync(path.join(cwd, 'jst.js'), '\
|
||
* var JST = {\
|
||
* "main": ' + _.template(mainText).source + '\
|
||
* };\
|
||
* ');
|
||
*/
|
||
function template(string, options, otherOptions) {
|
||
// Based on John Resig's `tmpl` implementation (http://ejohn.org/blog/javascript-micro-templating/)
|
||
// and Laura Doktorova's doT.js (https://github.com/olado/doT).
|
||
var settings = lodash.templateSettings;
|
||
|
||
if (otherOptions && isIterateeCall(string, options, otherOptions)) {
|
||
options = otherOptions = undefined;
|
||
}
|
||
string = baseToString(string);
|
||
options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults);
|
||
|
||
var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults),
|
||
importsKeys = keys(imports),
|
||
importsValues = baseValues(imports, importsKeys);
|
||
|
||
var isEscaping,
|
||
isEvaluating,
|
||
index = 0,
|
||
interpolate = options.interpolate || reNoMatch,
|
||
source = "__p += '";
|
||
|
||
// Compile the regexp to match each delimiter.
|
||
var reDelimiters = RegExp(
|
||
(options.escape || reNoMatch).source + '|' +
|
||
interpolate.source + '|' +
|
||
(interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
|
||
(options.evaluate || reNoMatch).source + '|$'
|
||
, 'g');
|
||
|
||
// Use a sourceURL for easier debugging.
|
||
var sourceURL = '//# sourceURL=' +
|
||
('sourceURL' in options
|
||
? options.sourceURL
|
||
: ('lodash.templateSources[' + (++templateCounter) + ']')
|
||
) + '\n';
|
||
|
||
string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
|
||
interpolateValue || (interpolateValue = esTemplateValue);
|
||
|
||
// Escape characters that can't be included in string literals.
|
||
source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
|
||
|
||
// Replace delimiters with snippets.
|
||
if (escapeValue) {
|
||
isEscaping = true;
|
||
source += "' +\n__e(" + escapeValue + ") +\n'";
|
||
}
|
||
if (evaluateValue) {
|
||
isEvaluating = true;
|
||
source += "';\n" + evaluateValue + ";\n__p += '";
|
||
}
|
||
if (interpolateValue) {
|
||
source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
|
||
}
|
||
index = offset + match.length;
|
||
|
||
// The JS engine embedded in Adobe products requires returning the `match`
|
||
// string in order to produce the correct `offset` value.
|
||
return match;
|
||
});
|
||
|
||
source += "';\n";
|
||
|
||
// If `variable` is not specified wrap a with-statement around the generated
|
||
// code to add the data object to the top of the scope chain.
|
||
var variable = options.variable;
|
||
if (!variable) {
|
||
source = 'with (obj) {\n' + source + '\n}\n';
|
||
}
|
||
// Cleanup code by stripping empty strings.
|
||
source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
|
||
.replace(reEmptyStringMiddle, '$1')
|
||
.replace(reEmptyStringTrailing, '$1;');
|
||
|
||
// Frame code as the function body.
|
||
source = 'function(' + (variable || 'obj') + ') {\n' +
|
||
(variable
|
||
? ''
|
||
: 'obj || (obj = {});\n'
|
||
) +
|
||
"var __t, __p = ''" +
|
||
(isEscaping
|
||
? ', __e = _.escape'
|
||
: ''
|
||
) +
|
||
(isEvaluating
|
||
? ', __j = Array.prototype.join;\n' +
|
||
"function print() { __p += __j.call(arguments, '') }\n"
|
||
: ';\n'
|
||
) +
|
||
source +
|
||
'return __p\n}';
|
||
|
||
var result = attempt(function() {
|
||
return Function(importsKeys, sourceURL + 'return ' + source).apply(undefined, importsValues);
|
||
});
|
||
|
||
// Provide the compiled function's source by its `toString` method or
|
||
// the `source` property as a convenience for inlining compiled templates.
|
||
result.source = source;
|
||
if (isError(result)) {
|
||
throw result;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Removes leading and trailing whitespace or specified characters from `string`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to trim.
|
||
* @param {string} [chars=whitespace] The characters to trim.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {string} Returns the trimmed string.
|
||
* @example
|
||
*
|
||
* _.trim(' abc ');
|
||
* // => 'abc'
|
||
*
|
||
* _.trim('-_-abc-_-', '_-');
|
||
* // => 'abc'
|
||
*
|
||
* _.map([' foo ', ' bar '], _.trim);
|
||
* // => ['foo', 'bar']
|
||
*/
|
||
function trim(string, chars, guard) {
|
||
var value = string;
|
||
string = baseToString(string);
|
||
if (!string) {
|
||
return string;
|
||
}
|
||
if (guard ? isIterateeCall(value, chars, guard) : chars == null) {
|
||
return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1);
|
||
}
|
||
chars = (chars + '');
|
||
return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1);
|
||
}
|
||
|
||
/**
|
||
* Removes leading whitespace or specified characters from `string`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to trim.
|
||
* @param {string} [chars=whitespace] The characters to trim.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {string} Returns the trimmed string.
|
||
* @example
|
||
*
|
||
* _.trimLeft(' abc ');
|
||
* // => 'abc '
|
||
*
|
||
* _.trimLeft('-_-abc-_-', '_-');
|
||
* // => 'abc-_-'
|
||
*/
|
||
function trimLeft(string, chars, guard) {
|
||
var value = string;
|
||
string = baseToString(string);
|
||
if (!string) {
|
||
return string;
|
||
}
|
||
if (guard ? isIterateeCall(value, chars, guard) : chars == null) {
|
||
return string.slice(trimmedLeftIndex(string));
|
||
}
|
||
return string.slice(charsLeftIndex(string, (chars + '')));
|
||
}
|
||
|
||
/**
|
||
* Removes trailing whitespace or specified characters from `string`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to trim.
|
||
* @param {string} [chars=whitespace] The characters to trim.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {string} Returns the trimmed string.
|
||
* @example
|
||
*
|
||
* _.trimRight(' abc ');
|
||
* // => ' abc'
|
||
*
|
||
* _.trimRight('-_-abc-_-', '_-');
|
||
* // => '-_-abc'
|
||
*/
|
||
function trimRight(string, chars, guard) {
|
||
var value = string;
|
||
string = baseToString(string);
|
||
if (!string) {
|
||
return string;
|
||
}
|
||
if (guard ? isIterateeCall(value, chars, guard) : chars == null) {
|
||
return string.slice(0, trimmedRightIndex(string) + 1);
|
||
}
|
||
return string.slice(0, charsRightIndex(string, (chars + '')) + 1);
|
||
}
|
||
|
||
/**
|
||
* Truncates `string` if it's longer than the given maximum string length.
|
||
* The last characters of the truncated string are replaced with the omission
|
||
* string which defaults to "...".
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to truncate.
|
||
* @param {Object|number} [options] The options object or maximum string length.
|
||
* @param {number} [options.length=30] The maximum string length.
|
||
* @param {string} [options.omission='...'] The string to indicate text is omitted.
|
||
* @param {RegExp|string} [options.separator] The separator pattern to truncate to.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {string} Returns the truncated string.
|
||
* @example
|
||
*
|
||
* _.trunc('hi-diddly-ho there, neighborino');
|
||
* // => 'hi-diddly-ho there, neighbo...'
|
||
*
|
||
* _.trunc('hi-diddly-ho there, neighborino', 24);
|
||
* // => 'hi-diddly-ho there, n...'
|
||
*
|
||
* _.trunc('hi-diddly-ho there, neighborino', {
|
||
* 'length': 24,
|
||
* 'separator': ' '
|
||
* });
|
||
* // => 'hi-diddly-ho there,...'
|
||
*
|
||
* _.trunc('hi-diddly-ho there, neighborino', {
|
||
* 'length': 24,
|
||
* 'separator': /,? +/
|
||
* });
|
||
* // => 'hi-diddly-ho there...'
|
||
*
|
||
* _.trunc('hi-diddly-ho there, neighborino', {
|
||
* 'omission': ' [...]'
|
||
* });
|
||
* // => 'hi-diddly-ho there, neig [...]'
|
||
*/
|
||
function trunc(string, options, guard) {
|
||
if (guard && isIterateeCall(string, options, guard)) {
|
||
options = undefined;
|
||
}
|
||
var length = DEFAULT_TRUNC_LENGTH,
|
||
omission = DEFAULT_TRUNC_OMISSION;
|
||
|
||
if (options != null) {
|
||
if (isObject(options)) {
|
||
var separator = 'separator' in options ? options.separator : separator;
|
||
length = 'length' in options ? (+options.length || 0) : length;
|
||
omission = 'omission' in options ? baseToString(options.omission) : omission;
|
||
} else {
|
||
length = +options || 0;
|
||
}
|
||
}
|
||
string = baseToString(string);
|
||
if (length >= string.length) {
|
||
return string;
|
||
}
|
||
var end = length - omission.length;
|
||
if (end < 1) {
|
||
return omission;
|
||
}
|
||
var result = string.slice(0, end);
|
||
if (separator == null) {
|
||
return result + omission;
|
||
}
|
||
if (isRegExp(separator)) {
|
||
if (string.slice(end).search(separator)) {
|
||
var match,
|
||
newEnd,
|
||
substring = string.slice(0, end);
|
||
|
||
if (!separator.global) {
|
||
separator = RegExp(separator.source, (reFlags.exec(separator) || '') + 'g');
|
||
}
|
||
separator.lastIndex = 0;
|
||
while ((match = separator.exec(substring))) {
|
||
newEnd = match.index;
|
||
}
|
||
result = result.slice(0, newEnd == null ? end : newEnd);
|
||
}
|
||
} else if (string.indexOf(separator, end) != end) {
|
||
var index = result.lastIndexOf(separator);
|
||
if (index > -1) {
|
||
result = result.slice(0, index);
|
||
}
|
||
}
|
||
return result + omission;
|
||
}
|
||
|
||
/**
|
||
* The inverse of `_.escape`; this method converts the HTML entities
|
||
* `&`, `<`, `>`, `"`, `'`, and ``` in `string` to their
|
||
* corresponding characters.
|
||
*
|
||
* **Note:** No other HTML entities are unescaped. To unescape additional HTML
|
||
* entities use a third-party library like [_he_](https://mths.be/he).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to unescape.
|
||
* @returns {string} Returns the unescaped string.
|
||
* @example
|
||
*
|
||
* _.unescape('fred, barney, & pebbles');
|
||
* // => 'fred, barney, & pebbles'
|
||
*/
|
||
function unescape(string) {
|
||
string = baseToString(string);
|
||
return (string && reHasEscapedHtml.test(string))
|
||
? string.replace(reEscapedHtml, unescapeHtmlChar)
|
||
: string;
|
||
}
|
||
|
||
/**
|
||
* Splits `string` into an array of its words.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category String
|
||
* @param {string} [string=''] The string to inspect.
|
||
* @param {RegExp|string} [pattern] The pattern to match words.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {Array} Returns the words of `string`.
|
||
* @example
|
||
*
|
||
* _.words('fred, barney, & pebbles');
|
||
* // => ['fred', 'barney', 'pebbles']
|
||
*
|
||
* _.words('fred, barney, & pebbles', /[^, ]+/g);
|
||
* // => ['fred', 'barney', '&', 'pebbles']
|
||
*/
|
||
function words(string, pattern, guard) {
|
||
if (guard && isIterateeCall(string, pattern, guard)) {
|
||
pattern = undefined;
|
||
}
|
||
string = baseToString(string);
|
||
return string.match(pattern || reWords) || [];
|
||
}
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Attempts to invoke `func`, returning either the result or the caught error
|
||
* object. Any additional arguments are provided to `func` when it is invoked.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Utility
|
||
* @param {Function} func The function to attempt.
|
||
* @returns {*} Returns the `func` result or error object.
|
||
* @example
|
||
*
|
||
* // avoid throwing errors for invalid selectors
|
||
* var elements = _.attempt(function(selector) {
|
||
* return document.querySelectorAll(selector);
|
||
* }, '>_>');
|
||
*
|
||
* if (_.isError(elements)) {
|
||
* elements = [];
|
||
* }
|
||
*/
|
||
var attempt = restParam(function(func, args) {
|
||
try {
|
||
return func.apply(undefined, args);
|
||
} catch(e) {
|
||
return isError(e) ? e : new Error(e);
|
||
}
|
||
});
|
||
|
||
/**
|
||
* Creates a function that invokes `func` with the `this` binding of `thisArg`
|
||
* and arguments of the created function. If `func` is a property name the
|
||
* created callback returns the property value for a given element. If `func`
|
||
* is an object the created callback returns `true` for elements that contain
|
||
* the equivalent object properties, otherwise it returns `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @alias iteratee
|
||
* @category Utility
|
||
* @param {*} [func=_.identity] The value to convert to a callback.
|
||
* @param {*} [thisArg] The `this` binding of `func`.
|
||
* @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
|
||
* @returns {Function} Returns the callback.
|
||
* @example
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'age': 36 },
|
||
* { 'user': 'fred', 'age': 40 }
|
||
* ];
|
||
*
|
||
* // wrap to create custom callback shorthands
|
||
* _.callback = _.wrap(_.callback, function(callback, func, thisArg) {
|
||
* var match = /^(.+?)__([gl]t)(.+)$/.exec(func);
|
||
* if (!match) {
|
||
* return callback(func, thisArg);
|
||
* }
|
||
* return function(object) {
|
||
* return match[2] == 'gt'
|
||
* ? object[match[1]] > match[3]
|
||
* : object[match[1]] < match[3];
|
||
* };
|
||
* });
|
||
*
|
||
* _.filter(users, 'age__gt36');
|
||
* // => [{ 'user': 'fred', 'age': 40 }]
|
||
*/
|
||
function callback(func, thisArg, guard) {
|
||
if (guard && isIterateeCall(func, thisArg, guard)) {
|
||
thisArg = undefined;
|
||
}
|
||
return isObjectLike(func)
|
||
? matches(func)
|
||
: baseCallback(func, thisArg);
|
||
}
|
||
|
||
/**
|
||
* Creates a function that returns `value`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Utility
|
||
* @param {*} value The value to return from the new function.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* var object = { 'user': 'fred' };
|
||
* var getter = _.constant(object);
|
||
*
|
||
* getter() === object;
|
||
* // => true
|
||
*/
|
||
function constant(value) {
|
||
return function() {
|
||
return value;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* This method returns the first argument provided to it.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Utility
|
||
* @param {*} value Any value.
|
||
* @returns {*} Returns `value`.
|
||
* @example
|
||
*
|
||
* var object = { 'user': 'fred' };
|
||
*
|
||
* _.identity(object) === object;
|
||
* // => true
|
||
*/
|
||
function identity(value) {
|
||
return value;
|
||
}
|
||
|
||
/**
|
||
* Creates a function that performs a deep comparison between a given object
|
||
* and `source`, returning `true` if the given object has equivalent property
|
||
* values, else `false`.
|
||
*
|
||
* **Note:** This method supports comparing arrays, booleans, `Date` objects,
|
||
* numbers, `Object` objects, regexes, and strings. Objects are compared by
|
||
* their own, not inherited, enumerable properties. For comparing a single
|
||
* own or inherited property value see `_.matchesProperty`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Utility
|
||
* @param {Object} source The object of property values to match.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'age': 36, 'active': true },
|
||
* { 'user': 'fred', 'age': 40, 'active': false }
|
||
* ];
|
||
*
|
||
* _.filter(users, _.matches({ 'age': 40, 'active': false }));
|
||
* // => [{ 'user': 'fred', 'age': 40, 'active': false }]
|
||
*/
|
||
function matches(source) {
|
||
return baseMatches(baseClone(source, true));
|
||
}
|
||
|
||
/**
|
||
* Creates a function that compares the property value of `path` on a given
|
||
* object to `value`.
|
||
*
|
||
* **Note:** This method supports comparing arrays, booleans, `Date` objects,
|
||
* numbers, `Object` objects, regexes, and strings. Objects are compared by
|
||
* their own, not inherited, enumerable properties.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Utility
|
||
* @param {Array|string} path The path of the property to get.
|
||
* @param {*} srcValue The value to match.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney' },
|
||
* { 'user': 'fred' }
|
||
* ];
|
||
*
|
||
* _.find(users, _.matchesProperty('user', 'fred'));
|
||
* // => { 'user': 'fred' }
|
||
*/
|
||
function matchesProperty(path, srcValue) {
|
||
return baseMatchesProperty(path, baseClone(srcValue, true));
|
||
}
|
||
|
||
/**
|
||
* Creates a function that invokes the method at `path` on a given object.
|
||
* Any additional arguments are provided to the invoked method.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Utility
|
||
* @param {Array|string} path The path of the method to invoke.
|
||
* @param {...*} [args] The arguments to invoke the method with.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* var objects = [
|
||
* { 'a': { 'b': { 'c': _.constant(2) } } },
|
||
* { 'a': { 'b': { 'c': _.constant(1) } } }
|
||
* ];
|
||
*
|
||
* _.map(objects, _.method('a.b.c'));
|
||
* // => [2, 1]
|
||
*
|
||
* _.invoke(_.sortBy(objects, _.method(['a', 'b', 'c'])), 'a.b.c');
|
||
* // => [1, 2]
|
||
*/
|
||
var method = restParam(function(path, args) {
|
||
return function(object) {
|
||
return invokePath(object, path, args);
|
||
};
|
||
});
|
||
|
||
/**
|
||
* The opposite of `_.method`; this method creates a function that invokes
|
||
* the method at a given path on `object`. Any additional arguments are
|
||
* provided to the invoked method.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Utility
|
||
* @param {Object} object The object to query.
|
||
* @param {...*} [args] The arguments to invoke the method with.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* var array = _.times(3, _.constant),
|
||
* object = { 'a': array, 'b': array, 'c': array };
|
||
*
|
||
* _.map(['a[2]', 'c[0]'], _.methodOf(object));
|
||
* // => [2, 0]
|
||
*
|
||
* _.map([['a', '2'], ['c', '0']], _.methodOf(object));
|
||
* // => [2, 0]
|
||
*/
|
||
var methodOf = restParam(function(object, args) {
|
||
return function(path) {
|
||
return invokePath(object, path, args);
|
||
};
|
||
});
|
||
|
||
/**
|
||
* Adds all own enumerable function properties of a source object to the
|
||
* destination object. If `object` is a function then methods are added to
|
||
* its prototype as well.
|
||
*
|
||
* **Note:** Use `_.runInContext` to create a pristine `lodash` function to
|
||
* avoid conflicts caused by modifying the original.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Utility
|
||
* @param {Function|Object} [object=lodash] The destination object.
|
||
* @param {Object} source The object of functions to add.
|
||
* @param {Object} [options] The options object.
|
||
* @param {boolean} [options.chain=true] Specify whether the functions added
|
||
* are chainable.
|
||
* @returns {Function|Object} Returns `object`.
|
||
* @example
|
||
*
|
||
* function vowels(string) {
|
||
* return _.filter(string, function(v) {
|
||
* return /[aeiou]/i.test(v);
|
||
* });
|
||
* }
|
||
*
|
||
* _.mixin({ 'vowels': vowels });
|
||
* _.vowels('fred');
|
||
* // => ['e']
|
||
*
|
||
* _('fred').vowels().value();
|
||
* // => ['e']
|
||
*
|
||
* _.mixin({ 'vowels': vowels }, { 'chain': false });
|
||
* _('fred').vowels();
|
||
* // => ['e']
|
||
*/
|
||
function mixin(object, source, options) {
|
||
if (options == null) {
|
||
var isObj = isObject(source),
|
||
props = isObj ? keys(source) : undefined,
|
||
methodNames = (props && props.length) ? baseFunctions(source, props) : undefined;
|
||
|
||
if (!(methodNames ? methodNames.length : isObj)) {
|
||
methodNames = false;
|
||
options = source;
|
||
source = object;
|
||
object = this;
|
||
}
|
||
}
|
||
if (!methodNames) {
|
||
methodNames = baseFunctions(source, keys(source));
|
||
}
|
||
var chain = true,
|
||
index = -1,
|
||
isFunc = isFunction(object),
|
||
length = methodNames.length;
|
||
|
||
if (options === false) {
|
||
chain = false;
|
||
} else if (isObject(options) && 'chain' in options) {
|
||
chain = options.chain;
|
||
}
|
||
while (++index < length) {
|
||
var methodName = methodNames[index],
|
||
func = source[methodName];
|
||
|
||
object[methodName] = func;
|
||
if (isFunc) {
|
||
object.prototype[methodName] = (function(func) {
|
||
return function() {
|
||
var chainAll = this.__chain__;
|
||
if (chain || chainAll) {
|
||
var result = object(this.__wrapped__),
|
||
actions = result.__actions__ = arrayCopy(this.__actions__);
|
||
|
||
actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
|
||
result.__chain__ = chainAll;
|
||
return result;
|
||
}
|
||
return func.apply(object, arrayPush([this.value()], arguments));
|
||
};
|
||
}(func));
|
||
}
|
||
}
|
||
return object;
|
||
}
|
||
|
||
/**
|
||
* Reverts the `_` variable to its previous value and returns a reference to
|
||
* the `lodash` function.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Utility
|
||
* @returns {Function} Returns the `lodash` function.
|
||
* @example
|
||
*
|
||
* var lodash = _.noConflict();
|
||
*/
|
||
function noConflict() {
|
||
root._ = oldDash;
|
||
return this;
|
||
}
|
||
|
||
/**
|
||
* A no-operation function that returns `undefined` regardless of the
|
||
* arguments it receives.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Utility
|
||
* @example
|
||
*
|
||
* var object = { 'user': 'fred' };
|
||
*
|
||
* _.noop(object) === undefined;
|
||
* // => true
|
||
*/
|
||
function noop() {
|
||
// No operation performed.
|
||
}
|
||
|
||
/**
|
||
* Creates a function that returns the property value at `path` on a
|
||
* given object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Utility
|
||
* @param {Array|string} path The path of the property to get.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* var objects = [
|
||
* { 'a': { 'b': { 'c': 2 } } },
|
||
* { 'a': { 'b': { 'c': 1 } } }
|
||
* ];
|
||
*
|
||
* _.map(objects, _.property('a.b.c'));
|
||
* // => [2, 1]
|
||
*
|
||
* _.pluck(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c');
|
||
* // => [1, 2]
|
||
*/
|
||
function property(path) {
|
||
return isKey(path) ? baseProperty(path) : basePropertyDeep(path);
|
||
}
|
||
|
||
/**
|
||
* The opposite of `_.property`; this method creates a function that returns
|
||
* the property value at a given path on `object`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Utility
|
||
* @param {Object} object The object to query.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* var array = [0, 1, 2],
|
||
* object = { 'a': array, 'b': array, 'c': array };
|
||
*
|
||
* _.map(['a[2]', 'c[0]'], _.propertyOf(object));
|
||
* // => [2, 0]
|
||
*
|
||
* _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
|
||
* // => [2, 0]
|
||
*/
|
||
function propertyOf(object) {
|
||
return function(path) {
|
||
return baseGet(object, toPath(path), path + '');
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates an array of numbers (positive and/or negative) progressing from
|
||
* `start` up to, but not including, `end`. If `end` is not specified it is
|
||
* set to `start` with `start` then set to `0`. If `end` is less than `start`
|
||
* a zero-length range is created unless a negative `step` is specified.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Utility
|
||
* @param {number} [start=0] The start of the range.
|
||
* @param {number} end The end of the range.
|
||
* @param {number} [step=1] The value to increment or decrement by.
|
||
* @returns {Array} Returns the new array of numbers.
|
||
* @example
|
||
*
|
||
* _.range(4);
|
||
* // => [0, 1, 2, 3]
|
||
*
|
||
* _.range(1, 5);
|
||
* // => [1, 2, 3, 4]
|
||
*
|
||
* _.range(0, 20, 5);
|
||
* // => [0, 5, 10, 15]
|
||
*
|
||
* _.range(0, -4, -1);
|
||
* // => [0, -1, -2, -3]
|
||
*
|
||
* _.range(1, 4, 0);
|
||
* // => [1, 1, 1]
|
||
*
|
||
* _.range(0);
|
||
* // => []
|
||
*/
|
||
function range(start, end, step) {
|
||
if (step && isIterateeCall(start, end, step)) {
|
||
end = step = undefined;
|
||
}
|
||
start = +start || 0;
|
||
step = step == null ? 1 : (+step || 0);
|
||
|
||
if (end == null) {
|
||
end = start;
|
||
start = 0;
|
||
} else {
|
||
end = +end || 0;
|
||
}
|
||
// Use `Array(length)` so engines like Chakra and V8 avoid slower modes.
|
||
// See https://youtu.be/XAqIpGU8ZZk#t=17m25s for more details.
|
||
var index = -1,
|
||
length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
|
||
result = Array(length);
|
||
|
||
while (++index < length) {
|
||
result[index] = start;
|
||
start += step;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Invokes the iteratee function `n` times, returning an array of the results
|
||
* of each invocation. The `iteratee` is bound to `thisArg` and invoked with
|
||
* one argument; (index).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Utility
|
||
* @param {number} n The number of times to invoke `iteratee`.
|
||
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {Array} Returns the array of results.
|
||
* @example
|
||
*
|
||
* var diceRolls = _.times(3, _.partial(_.random, 1, 6, false));
|
||
* // => [3, 6, 4]
|
||
*
|
||
* _.times(3, function(n) {
|
||
* mage.castSpell(n);
|
||
* });
|
||
* // => invokes `mage.castSpell(n)` three times with `n` of `0`, `1`, and `2`
|
||
*
|
||
* _.times(3, function(n) {
|
||
* this.cast(n);
|
||
* }, mage);
|
||
* // => also invokes `mage.castSpell(n)` three times
|
||
*/
|
||
function times(n, iteratee, thisArg) {
|
||
n = nativeFloor(n);
|
||
|
||
// Exit early to avoid a JSC JIT bug in Safari 8
|
||
// where `Array(0)` is treated as `Array(1)`.
|
||
if (n < 1 || !nativeIsFinite(n)) {
|
||
return [];
|
||
}
|
||
var index = -1,
|
||
result = Array(nativeMin(n, MAX_ARRAY_LENGTH));
|
||
|
||
iteratee = bindCallback(iteratee, thisArg, 1);
|
||
while (++index < n) {
|
||
if (index < MAX_ARRAY_LENGTH) {
|
||
result[index] = iteratee(index);
|
||
} else {
|
||
iteratee(index);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Generates a unique ID. If `prefix` is provided the ID is appended to it.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Utility
|
||
* @param {string} [prefix] The value to prefix the ID with.
|
||
* @returns {string} Returns the unique ID.
|
||
* @example
|
||
*
|
||
* _.uniqueId('contact_');
|
||
* // => 'contact_104'
|
||
*
|
||
* _.uniqueId();
|
||
* // => '105'
|
||
*/
|
||
function uniqueId(prefix) {
|
||
var id = ++idCounter;
|
||
return baseToString(prefix) + id;
|
||
}
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Adds two numbers.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Math
|
||
* @param {number} augend The first number to add.
|
||
* @param {number} addend The second number to add.
|
||
* @returns {number} Returns the sum.
|
||
* @example
|
||
*
|
||
* _.add(6, 4);
|
||
* // => 10
|
||
*/
|
||
function add(augend, addend) {
|
||
return (+augend || 0) + (+addend || 0);
|
||
}
|
||
|
||
/**
|
||
* Calculates `n` rounded up to `precision`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Math
|
||
* @param {number} n The number to round up.
|
||
* @param {number} [precision=0] The precision to round up to.
|
||
* @returns {number} Returns the rounded up number.
|
||
* @example
|
||
*
|
||
* _.ceil(4.006);
|
||
* // => 5
|
||
*
|
||
* _.ceil(6.004, 2);
|
||
* // => 6.01
|
||
*
|
||
* _.ceil(6040, -2);
|
||
* // => 6100
|
||
*/
|
||
var ceil = createRound('ceil');
|
||
|
||
/**
|
||
* Calculates `n` rounded down to `precision`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Math
|
||
* @param {number} n The number to round down.
|
||
* @param {number} [precision=0] The precision to round down to.
|
||
* @returns {number} Returns the rounded down number.
|
||
* @example
|
||
*
|
||
* _.floor(4.006);
|
||
* // => 4
|
||
*
|
||
* _.floor(0.046, 2);
|
||
* // => 0.04
|
||
*
|
||
* _.floor(4060, -2);
|
||
* // => 4000
|
||
*/
|
||
var floor = createRound('floor');
|
||
|
||
/**
|
||
* Gets the maximum value of `collection`. If `collection` is empty or falsey
|
||
* `-Infinity` is returned. If an iteratee function is provided it is invoked
|
||
* for each value in `collection` to generate the criterion by which the value
|
||
* is ranked. The `iteratee` is bound to `thisArg` and invoked with three
|
||
* arguments: (value, index, collection).
|
||
*
|
||
* If a property name is provided for `iteratee` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `iteratee` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Math
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function|Object|string} [iteratee] The function invoked per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {*} Returns the maximum value.
|
||
* @example
|
||
*
|
||
* _.max([4, 2, 8, 6]);
|
||
* // => 8
|
||
*
|
||
* _.max([]);
|
||
* // => -Infinity
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'age': 36 },
|
||
* { 'user': 'fred', 'age': 40 }
|
||
* ];
|
||
*
|
||
* _.max(users, function(chr) {
|
||
* return chr.age;
|
||
* });
|
||
* // => { 'user': 'fred', 'age': 40 }
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.max(users, 'age');
|
||
* // => { 'user': 'fred', 'age': 40 }
|
||
*/
|
||
var max = createExtremum(gt, NEGATIVE_INFINITY);
|
||
|
||
/**
|
||
* Gets the minimum value of `collection`. If `collection` is empty or falsey
|
||
* `Infinity` is returned. If an iteratee function is provided it is invoked
|
||
* for each value in `collection` to generate the criterion by which the value
|
||
* is ranked. The `iteratee` is bound to `thisArg` and invoked with three
|
||
* arguments: (value, index, collection).
|
||
*
|
||
* If a property name is provided for `iteratee` the created `_.property`
|
||
* style callback returns the property value of the given element.
|
||
*
|
||
* If a value is also provided for `thisArg` the created `_.matchesProperty`
|
||
* style callback returns `true` for elements that have a matching property
|
||
* value, else `false`.
|
||
*
|
||
* If an object is provided for `iteratee` the created `_.matches` style
|
||
* callback returns `true` for elements that have the properties of the given
|
||
* object, else `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Math
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function|Object|string} [iteratee] The function invoked per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {*} Returns the minimum value.
|
||
* @example
|
||
*
|
||
* _.min([4, 2, 8, 6]);
|
||
* // => 2
|
||
*
|
||
* _.min([]);
|
||
* // => Infinity
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'age': 36 },
|
||
* { 'user': 'fred', 'age': 40 }
|
||
* ];
|
||
*
|
||
* _.min(users, function(chr) {
|
||
* return chr.age;
|
||
* });
|
||
* // => { 'user': 'barney', 'age': 36 }
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.min(users, 'age');
|
||
* // => { 'user': 'barney', 'age': 36 }
|
||
*/
|
||
var min = createExtremum(lt, POSITIVE_INFINITY);
|
||
|
||
/**
|
||
* Calculates `n` rounded to `precision`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Math
|
||
* @param {number} n The number to round.
|
||
* @param {number} [precision=0] The precision to round to.
|
||
* @returns {number} Returns the rounded number.
|
||
* @example
|
||
*
|
||
* _.round(4.006);
|
||
* // => 4
|
||
*
|
||
* _.round(4.006, 2);
|
||
* // => 4.01
|
||
*
|
||
* _.round(4060, -2);
|
||
* // => 4100
|
||
*/
|
||
var round = createRound('round');
|
||
|
||
/**
|
||
* Gets the sum of the values in `collection`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @category Math
|
||
* @param {Array|Object|string} collection The collection to iterate over.
|
||
* @param {Function|Object|string} [iteratee] The function invoked per iteration.
|
||
* @param {*} [thisArg] The `this` binding of `iteratee`.
|
||
* @returns {number} Returns the sum.
|
||
* @example
|
||
*
|
||
* _.sum([4, 6]);
|
||
* // => 10
|
||
*
|
||
* _.sum({ 'a': 4, 'b': 6 });
|
||
* // => 10
|
||
*
|
||
* var objects = [
|
||
* { 'n': 4 },
|
||
* { 'n': 6 }
|
||
* ];
|
||
*
|
||
* _.sum(objects, function(object) {
|
||
* return object.n;
|
||
* });
|
||
* // => 10
|
||
*
|
||
* // using the `_.property` callback shorthand
|
||
* _.sum(objects, 'n');
|
||
* // => 10
|
||
*/
|
||
function sum(collection, iteratee, thisArg) {
|
||
if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {
|
||
iteratee = undefined;
|
||
}
|
||
iteratee = getCallback(iteratee, thisArg, 3);
|
||
return iteratee.length == 1
|
||
? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee)
|
||
: baseSum(collection, iteratee);
|
||
}
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
// Ensure wrappers are instances of `baseLodash`.
|
||
lodash.prototype = baseLodash.prototype;
|
||
|
||
LodashWrapper.prototype = baseCreate(baseLodash.prototype);
|
||
LodashWrapper.prototype.constructor = LodashWrapper;
|
||
|
||
LazyWrapper.prototype = baseCreate(baseLodash.prototype);
|
||
LazyWrapper.prototype.constructor = LazyWrapper;
|
||
|
||
// Add functions to the `Map` cache.
|
||
MapCache.prototype['delete'] = mapDelete;
|
||
MapCache.prototype.get = mapGet;
|
||
MapCache.prototype.has = mapHas;
|
||
MapCache.prototype.set = mapSet;
|
||
|
||
// Add functions to the `Set` cache.
|
||
SetCache.prototype.push = cachePush;
|
||
|
||
// Assign cache to `_.memoize`.
|
||
memoize.Cache = MapCache;
|
||
|
||
// Add functions that return wrapped values when chaining.
|
||
lodash.after = after;
|
||
lodash.ary = ary;
|
||
lodash.assign = assign;
|
||
lodash.at = at;
|
||
lodash.before = before;
|
||
lodash.bind = bind;
|
||
lodash.bindAll = bindAll;
|
||
lodash.bindKey = bindKey;
|
||
lodash.callback = callback;
|
||
lodash.chain = chain;
|
||
lodash.chunk = chunk;
|
||
lodash.compact = compact;
|
||
lodash.constant = constant;
|
||
lodash.countBy = countBy;
|
||
lodash.create = create;
|
||
lodash.curry = curry;
|
||
lodash.curryRight = curryRight;
|
||
lodash.debounce = debounce;
|
||
lodash.defaults = defaults;
|
||
lodash.defaultsDeep = defaultsDeep;
|
||
lodash.defer = defer;
|
||
lodash.delay = delay;
|
||
lodash.difference = difference;
|
||
lodash.drop = drop;
|
||
lodash.dropRight = dropRight;
|
||
lodash.dropRightWhile = dropRightWhile;
|
||
lodash.dropWhile = dropWhile;
|
||
lodash.fill = fill;
|
||
lodash.filter = filter;
|
||
lodash.flatten = flatten;
|
||
lodash.flattenDeep = flattenDeep;
|
||
lodash.flow = flow;
|
||
lodash.flowRight = flowRight;
|
||
lodash.forEach = forEach;
|
||
lodash.forEachRight = forEachRight;
|
||
lodash.forIn = forIn;
|
||
lodash.forInRight = forInRight;
|
||
lodash.forOwn = forOwn;
|
||
lodash.forOwnRight = forOwnRight;
|
||
lodash.functions = functions;
|
||
lodash.groupBy = groupBy;
|
||
lodash.indexBy = indexBy;
|
||
lodash.initial = initial;
|
||
lodash.intersection = intersection;
|
||
lodash.invert = invert;
|
||
lodash.invoke = invoke;
|
||
lodash.keys = keys;
|
||
lodash.keysIn = keysIn;
|
||
lodash.map = map;
|
||
lodash.mapKeys = mapKeys;
|
||
lodash.mapValues = mapValues;
|
||
lodash.matches = matches;
|
||
lodash.matchesProperty = matchesProperty;
|
||
lodash.memoize = memoize;
|
||
lodash.merge = merge;
|
||
lodash.method = method;
|
||
lodash.methodOf = methodOf;
|
||
lodash.mixin = mixin;
|
||
lodash.modArgs = modArgs;
|
||
lodash.negate = negate;
|
||
lodash.omit = omit;
|
||
lodash.once = once;
|
||
lodash.pairs = pairs;
|
||
lodash.partial = partial;
|
||
lodash.partialRight = partialRight;
|
||
lodash.partition = partition;
|
||
lodash.pick = pick;
|
||
lodash.pluck = pluck;
|
||
lodash.property = property;
|
||
lodash.propertyOf = propertyOf;
|
||
lodash.pull = pull;
|
||
lodash.pullAt = pullAt;
|
||
lodash.range = range;
|
||
lodash.rearg = rearg;
|
||
lodash.reject = reject;
|
||
lodash.remove = remove;
|
||
lodash.rest = rest;
|
||
lodash.restParam = restParam;
|
||
lodash.set = set;
|
||
lodash.shuffle = shuffle;
|
||
lodash.slice = slice;
|
||
lodash.sortBy = sortBy;
|
||
lodash.sortByAll = sortByAll;
|
||
lodash.sortByOrder = sortByOrder;
|
||
lodash.spread = spread;
|
||
lodash.take = take;
|
||
lodash.takeRight = takeRight;
|
||
lodash.takeRightWhile = takeRightWhile;
|
||
lodash.takeWhile = takeWhile;
|
||
lodash.tap = tap;
|
||
lodash.throttle = throttle;
|
||
lodash.thru = thru;
|
||
lodash.times = times;
|
||
lodash.toArray = toArray;
|
||
lodash.toPlainObject = toPlainObject;
|
||
lodash.transform = transform;
|
||
lodash.union = union;
|
||
lodash.uniq = uniq;
|
||
lodash.unzip = unzip;
|
||
lodash.unzipWith = unzipWith;
|
||
lodash.values = values;
|
||
lodash.valuesIn = valuesIn;
|
||
lodash.where = where;
|
||
lodash.without = without;
|
||
lodash.wrap = wrap;
|
||
lodash.xor = xor;
|
||
lodash.zip = zip;
|
||
lodash.zipObject = zipObject;
|
||
lodash.zipWith = zipWith;
|
||
|
||
// Add aliases.
|
||
lodash.backflow = flowRight;
|
||
lodash.collect = map;
|
||
lodash.compose = flowRight;
|
||
lodash.each = forEach;
|
||
lodash.eachRight = forEachRight;
|
||
lodash.extend = assign;
|
||
lodash.iteratee = callback;
|
||
lodash.methods = functions;
|
||
lodash.object = zipObject;
|
||
lodash.select = filter;
|
||
lodash.tail = rest;
|
||
lodash.unique = uniq;
|
||
|
||
// Add functions to `lodash.prototype`.
|
||
mixin(lodash, lodash);
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
// Add functions that return unwrapped values when chaining.
|
||
lodash.add = add;
|
||
lodash.attempt = attempt;
|
||
lodash.camelCase = camelCase;
|
||
lodash.capitalize = capitalize;
|
||
lodash.ceil = ceil;
|
||
lodash.clone = clone;
|
||
lodash.cloneDeep = cloneDeep;
|
||
lodash.deburr = deburr;
|
||
lodash.endsWith = endsWith;
|
||
lodash.escape = escape;
|
||
lodash.escapeRegExp = escapeRegExp;
|
||
lodash.every = every;
|
||
lodash.find = find;
|
||
lodash.findIndex = findIndex;
|
||
lodash.findKey = findKey;
|
||
lodash.findLast = findLast;
|
||
lodash.findLastIndex = findLastIndex;
|
||
lodash.findLastKey = findLastKey;
|
||
lodash.findWhere = findWhere;
|
||
lodash.first = first;
|
||
lodash.floor = floor;
|
||
lodash.get = get;
|
||
lodash.gt = gt;
|
||
lodash.gte = gte;
|
||
lodash.has = has;
|
||
lodash.identity = identity;
|
||
lodash.includes = includes;
|
||
lodash.indexOf = indexOf;
|
||
lodash.inRange = inRange;
|
||
lodash.isArguments = isArguments;
|
||
lodash.isArray = isArray;
|
||
lodash.isBoolean = isBoolean;
|
||
lodash.isDate = isDate;
|
||
lodash.isElement = isElement;
|
||
lodash.isEmpty = isEmpty;
|
||
lodash.isEqual = isEqual;
|
||
lodash.isError = isError;
|
||
lodash.isFinite = isFinite;
|
||
lodash.isFunction = isFunction;
|
||
lodash.isMatch = isMatch;
|
||
lodash.isNaN = isNaN;
|
||
lodash.isNative = isNative;
|
||
lodash.isNull = isNull;
|
||
lodash.isNumber = isNumber;
|
||
lodash.isObject = isObject;
|
||
lodash.isPlainObject = isPlainObject;
|
||
lodash.isRegExp = isRegExp;
|
||
lodash.isString = isString;
|
||
lodash.isTypedArray = isTypedArray;
|
||
lodash.isUndefined = isUndefined;
|
||
lodash.kebabCase = kebabCase;
|
||
lodash.last = last;
|
||
lodash.lastIndexOf = lastIndexOf;
|
||
lodash.lt = lt;
|
||
lodash.lte = lte;
|
||
lodash.max = max;
|
||
lodash.min = min;
|
||
lodash.noConflict = noConflict;
|
||
lodash.noop = noop;
|
||
lodash.now = now;
|
||
lodash.pad = pad;
|
||
lodash.padLeft = padLeft;
|
||
lodash.padRight = padRight;
|
||
lodash.parseInt = parseInt;
|
||
lodash.random = random;
|
||
lodash.reduce = reduce;
|
||
lodash.reduceRight = reduceRight;
|
||
lodash.repeat = repeat;
|
||
lodash.result = result;
|
||
lodash.round = round;
|
||
lodash.runInContext = runInContext;
|
||
lodash.size = size;
|
||
lodash.snakeCase = snakeCase;
|
||
lodash.some = some;
|
||
lodash.sortedIndex = sortedIndex;
|
||
lodash.sortedLastIndex = sortedLastIndex;
|
||
lodash.startCase = startCase;
|
||
lodash.startsWith = startsWith;
|
||
lodash.sum = sum;
|
||
lodash.template = template;
|
||
lodash.trim = trim;
|
||
lodash.trimLeft = trimLeft;
|
||
lodash.trimRight = trimRight;
|
||
lodash.trunc = trunc;
|
||
lodash.unescape = unescape;
|
||
lodash.uniqueId = uniqueId;
|
||
lodash.words = words;
|
||
|
||
// Add aliases.
|
||
lodash.all = every;
|
||
lodash.any = some;
|
||
lodash.contains = includes;
|
||
lodash.eq = isEqual;
|
||
lodash.detect = find;
|
||
lodash.foldl = reduce;
|
||
lodash.foldr = reduceRight;
|
||
lodash.head = first;
|
||
lodash.include = includes;
|
||
lodash.inject = reduce;
|
||
|
||
mixin(lodash, (function() {
|
||
var source = {};
|
||
baseForOwn(lodash, function(func, methodName) {
|
||
if (!lodash.prototype[methodName]) {
|
||
source[methodName] = func;
|
||
}
|
||
});
|
||
return source;
|
||
}()), false);
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
// Add functions capable of returning wrapped and unwrapped values when chaining.
|
||
lodash.sample = sample;
|
||
|
||
lodash.prototype.sample = function(n) {
|
||
if (!this.__chain__ && n == null) {
|
||
return sample(this.value());
|
||
}
|
||
return this.thru(function(value) {
|
||
return sample(value, n);
|
||
});
|
||
};
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* The semantic version number.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @type string
|
||
*/
|
||
lodash.VERSION = VERSION;
|
||
|
||
// Assign default placeholders.
|
||
arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
|
||
lodash[methodName].placeholder = lodash;
|
||
});
|
||
|
||
// Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
|
||
arrayEach(['drop', 'take'], function(methodName, index) {
|
||
LazyWrapper.prototype[methodName] = function(n) {
|
||
var filtered = this.__filtered__;
|
||
if (filtered && !index) {
|
||
return new LazyWrapper(this);
|
||
}
|
||
n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0);
|
||
|
||
var result = this.clone();
|
||
if (filtered) {
|
||
result.__takeCount__ = nativeMin(result.__takeCount__, n);
|
||
} else {
|
||
result.__views__.push({ 'size': n, 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') });
|
||
}
|
||
return result;
|
||
};
|
||
|
||
LazyWrapper.prototype[methodName + 'Right'] = function(n) {
|
||
return this.reverse()[methodName](n).reverse();
|
||
};
|
||
});
|
||
|
||
// Add `LazyWrapper` methods that accept an `iteratee` value.
|
||
arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
|
||
var type = index + 1,
|
||
isFilter = type != LAZY_MAP_FLAG;
|
||
|
||
LazyWrapper.prototype[methodName] = function(iteratee, thisArg) {
|
||
var result = this.clone();
|
||
result.__iteratees__.push({ 'iteratee': getCallback(iteratee, thisArg, 1), 'type': type });
|
||
result.__filtered__ = result.__filtered__ || isFilter;
|
||
return result;
|
||
};
|
||
});
|
||
|
||
// Add `LazyWrapper` methods for `_.first` and `_.last`.
|
||
arrayEach(['first', 'last'], function(methodName, index) {
|
||
var takeName = 'take' + (index ? 'Right' : '');
|
||
|
||
LazyWrapper.prototype[methodName] = function() {
|
||
return this[takeName](1).value()[0];
|
||
};
|
||
});
|
||
|
||
// Add `LazyWrapper` methods for `_.initial` and `_.rest`.
|
||
arrayEach(['initial', 'rest'], function(methodName, index) {
|
||
var dropName = 'drop' + (index ? '' : 'Right');
|
||
|
||
LazyWrapper.prototype[methodName] = function() {
|
||
return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
|
||
};
|
||
});
|
||
|
||
// Add `LazyWrapper` methods for `_.pluck` and `_.where`.
|
||
arrayEach(['pluck', 'where'], function(methodName, index) {
|
||
var operationName = index ? 'filter' : 'map',
|
||
createCallback = index ? baseMatches : property;
|
||
|
||
LazyWrapper.prototype[methodName] = function(value) {
|
||
return this[operationName](createCallback(value));
|
||
};
|
||
});
|
||
|
||
LazyWrapper.prototype.compact = function() {
|
||
return this.filter(identity);
|
||
};
|
||
|
||
LazyWrapper.prototype.reject = function(predicate, thisArg) {
|
||
predicate = getCallback(predicate, thisArg, 1);
|
||
return this.filter(function(value) {
|
||
return !predicate(value);
|
||
});
|
||
};
|
||
|
||
LazyWrapper.prototype.slice = function(start, end) {
|
||
start = start == null ? 0 : (+start || 0);
|
||
|
||
var result = this;
|
||
if (result.__filtered__ && (start > 0 || end < 0)) {
|
||
return new LazyWrapper(result);
|
||
}
|
||
if (start < 0) {
|
||
result = result.takeRight(-start);
|
||
} else if (start) {
|
||
result = result.drop(start);
|
||
}
|
||
if (end !== undefined) {
|
||
end = (+end || 0);
|
||
result = end < 0 ? result.dropRight(-end) : result.take(end - start);
|
||
}
|
||
return result;
|
||
};
|
||
|
||
LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) {
|
||
return this.reverse().takeWhile(predicate, thisArg).reverse();
|
||
};
|
||
|
||
LazyWrapper.prototype.toArray = function() {
|
||
return this.take(POSITIVE_INFINITY);
|
||
};
|
||
|
||
// Add `LazyWrapper` methods to `lodash.prototype`.
|
||
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
|
||
var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName),
|
||
retUnwrapped = /^(?:first|last)$/.test(methodName),
|
||
lodashFunc = lodash[retUnwrapped ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName];
|
||
|
||
if (!lodashFunc) {
|
||
return;
|
||
}
|
||
lodash.prototype[methodName] = function() {
|
||
var args = retUnwrapped ? [1] : arguments,
|
||
chainAll = this.__chain__,
|
||
value = this.__wrapped__,
|
||
isHybrid = !!this.__actions__.length,
|
||
isLazy = value instanceof LazyWrapper,
|
||
iteratee = args[0],
|
||
useLazy = isLazy || isArray(value);
|
||
|
||
if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
|
||
// Avoid lazy use if the iteratee has a "length" value other than `1`.
|
||
isLazy = useLazy = false;
|
||
}
|
||
var interceptor = function(value) {
|
||
return (retUnwrapped && chainAll)
|
||
? lodashFunc(value, 1)[0]
|
||
: lodashFunc.apply(undefined, arrayPush([value], args));
|
||
};
|
||
|
||
var action = { 'func': thru, 'args': [interceptor], 'thisArg': undefined },
|
||
onlyLazy = isLazy && !isHybrid;
|
||
|
||
if (retUnwrapped && !chainAll) {
|
||
if (onlyLazy) {
|
||
value = value.clone();
|
||
value.__actions__.push(action);
|
||
return func.call(value);
|
||
}
|
||
return lodashFunc.call(undefined, this.value())[0];
|
||
}
|
||
if (!retUnwrapped && useLazy) {
|
||
value = onlyLazy ? value : new LazyWrapper(this);
|
||
var result = func.apply(value, args);
|
||
result.__actions__.push(action);
|
||
return new LodashWrapper(result, chainAll);
|
||
}
|
||
return this.thru(interceptor);
|
||
};
|
||
});
|
||
|
||
// Add `Array` and `String` methods to `lodash.prototype`.
|
||
arrayEach(['join', 'pop', 'push', 'replace', 'shift', 'sort', 'splice', 'split', 'unshift'], function(methodName) {
|
||
var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName],
|
||
chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
|
||
retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName);
|
||
|
||
lodash.prototype[methodName] = function() {
|
||
var args = arguments;
|
||
if (retUnwrapped && !this.__chain__) {
|
||
return func.apply(this.value(), args);
|
||
}
|
||
return this[chainName](function(value) {
|
||
return func.apply(value, args);
|
||
});
|
||
};
|
||
});
|
||
|
||
// Map minified function names to their real names.
|
||
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
|
||
var lodashFunc = lodash[methodName];
|
||
if (lodashFunc) {
|
||
var key = lodashFunc.name,
|
||
names = realNames[key] || (realNames[key] = []);
|
||
|
||
names.push({ 'name': methodName, 'func': lodashFunc });
|
||
}
|
||
});
|
||
|
||
realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [{ 'name': 'wrapper', 'func': undefined }];
|
||
|
||
// Add functions to the lazy wrapper.
|
||
LazyWrapper.prototype.clone = lazyClone;
|
||
LazyWrapper.prototype.reverse = lazyReverse;
|
||
LazyWrapper.prototype.value = lazyValue;
|
||
|
||
// Add chaining functions to the `lodash` wrapper.
|
||
lodash.prototype.chain = wrapperChain;
|
||
lodash.prototype.commit = wrapperCommit;
|
||
lodash.prototype.concat = wrapperConcat;
|
||
lodash.prototype.plant = wrapperPlant;
|
||
lodash.prototype.reverse = wrapperReverse;
|
||
lodash.prototype.toString = wrapperToString;
|
||
lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
|
||
|
||
// Add function aliases to the `lodash` wrapper.
|
||
lodash.prototype.collect = lodash.prototype.map;
|
||
lodash.prototype.head = lodash.prototype.first;
|
||
lodash.prototype.select = lodash.prototype.filter;
|
||
lodash.prototype.tail = lodash.prototype.rest;
|
||
|
||
return lodash;
|
||
}
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
// Export lodash.
|
||
var _ = runInContext();
|
||
|
||
// Some AMD build optimizers like r.js check for condition patterns like the following:
|
||
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
|
||
// Expose lodash to the global object when an AMD loader is present to avoid
|
||
// errors in cases where lodash is loaded by a script tag and not intended
|
||
// as an AMD module. See http://requirejs.org/docs/errors.html#mismatch for
|
||
// more details.
|
||
root._ = _;
|
||
|
||
// Define as an anonymous module so, through path mapping, it can be
|
||
// referenced as the "underscore" module.
|
||
define(function() {
|
||
return _;
|
||
});
|
||
}
|
||
// Check for `exports` after `define` in case a build optimizer adds an `exports` object.
|
||
else if (freeExports && freeModule) {
|
||
// Export for Node.js or RingoJS.
|
||
if (moduleExports) {
|
||
(freeModule.exports = _)._ = _;
|
||
}
|
||
// Export for Rhino with CommonJS support.
|
||
else {
|
||
freeExports._ = _;
|
||
}
|
||
}
|
||
else {
|
||
// Export for a browser or Rhino.
|
||
root._ = _;
|
||
}
|
||
}.call(this));
|
||
|
||
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{}],54:[function(require,module,exports){
|
||
/*
|
||
Copyright (c) 2012-2014 Chris Pettitt
|
||
|
||
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.
|
||
*/
|
||
|
||
module.exports = {
|
||
graphlib: require("./lib/graphlib"),
|
||
|
||
layout: require("./lib/layout"),
|
||
debug: require("./lib/debug"),
|
||
util: {
|
||
time: require("./lib/util").time,
|
||
notime: require("./lib/util").notime
|
||
},
|
||
version: require("./lib/version")
|
||
};
|
||
|
||
},{"./lib/debug":59,"./lib/graphlib":60,"./lib/layout":62,"./lib/util":82,"./lib/version":83}],55:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("./lodash"),
|
||
greedyFAS = require("./greedy-fas");
|
||
|
||
module.exports = {
|
||
run: run,
|
||
undo: undo
|
||
};
|
||
|
||
function run(g) {
|
||
var fas = (g.graph().acyclicer === "greedy"
|
||
? greedyFAS(g, weightFn(g))
|
||
: dfsFAS(g));
|
||
_.each(fas, function(e) {
|
||
var label = g.edge(e);
|
||
g.removeEdge(e);
|
||
label.forwardName = e.name;
|
||
label.reversed = true;
|
||
g.setEdge(e.w, e.v, label, _.uniqueId("rev"));
|
||
});
|
||
|
||
function weightFn(g) {
|
||
return function(e) {
|
||
return g.edge(e).weight;
|
||
};
|
||
}
|
||
}
|
||
|
||
function dfsFAS(g) {
|
||
var fas = [],
|
||
stack = {},
|
||
visited = {};
|
||
|
||
function dfs(v) {
|
||
if (_.has(visited, v)) {
|
||
return;
|
||
}
|
||
visited[v] = true;
|
||
stack[v] = true;
|
||
_.each(g.outEdges(v), function(e) {
|
||
if (_.has(stack, e.w)) {
|
||
fas.push(e);
|
||
} else {
|
||
dfs(e.w);
|
||
}
|
||
});
|
||
delete stack[v];
|
||
}
|
||
|
||
_.each(g.nodes(), dfs);
|
||
return fas;
|
||
}
|
||
|
||
function undo(g) {
|
||
_.each(g.edges(), function(e) {
|
||
var label = g.edge(e);
|
||
if (label.reversed) {
|
||
g.removeEdge(e);
|
||
|
||
var forwardName = label.forwardName;
|
||
delete label.reversed;
|
||
delete label.forwardName;
|
||
g.setEdge(e.w, e.v, label, forwardName);
|
||
}
|
||
});
|
||
}
|
||
|
||
},{"./greedy-fas":61,"./lodash":63}],56:[function(require,module,exports){
|
||
var _ = require("./lodash"),
|
||
util = require("./util");
|
||
|
||
module.exports = addBorderSegments;
|
||
|
||
function addBorderSegments(g) {
|
||
function dfs(v) {
|
||
var children = g.children(v),
|
||
node = g.node(v);
|
||
if (children.length) {
|
||
_.each(children, dfs);
|
||
}
|
||
|
||
if (_.has(node, "minRank")) {
|
||
node.borderLeft = [];
|
||
node.borderRight = [];
|
||
for (var rank = node.minRank, maxRank = node.maxRank + 1;
|
||
rank < maxRank;
|
||
++rank) {
|
||
addBorderNode(g, "borderLeft", "_bl", v, node, rank);
|
||
addBorderNode(g, "borderRight", "_br", v, node, rank);
|
||
}
|
||
}
|
||
}
|
||
|
||
_.each(g.children(), dfs);
|
||
}
|
||
|
||
function addBorderNode(g, prop, prefix, sg, sgNode, rank) {
|
||
var label = { width: 0, height: 0, rank: rank, borderType: prop },
|
||
prev = sgNode[prop][rank - 1],
|
||
curr = util.addDummyNode(g, "border", label, prefix);
|
||
sgNode[prop][rank] = curr;
|
||
g.setParent(curr, sg);
|
||
if (prev) {
|
||
g.setEdge(prev, curr, { weight: 1 });
|
||
}
|
||
}
|
||
|
||
},{"./lodash":63,"./util":82}],57:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("./lodash");
|
||
|
||
module.exports = {
|
||
adjust: adjust,
|
||
undo: undo
|
||
};
|
||
|
||
function adjust(g) {
|
||
var rankDir = g.graph().rankdir.toLowerCase();
|
||
if (rankDir === "lr" || rankDir === "rl") {
|
||
swapWidthHeight(g);
|
||
}
|
||
}
|
||
|
||
function undo(g) {
|
||
var rankDir = g.graph().rankdir.toLowerCase();
|
||
if (rankDir === "bt" || rankDir === "rl") {
|
||
reverseY(g);
|
||
}
|
||
|
||
if (rankDir === "lr" || rankDir === "rl") {
|
||
swapXY(g);
|
||
swapWidthHeight(g);
|
||
}
|
||
}
|
||
|
||
function swapWidthHeight(g) {
|
||
_.each(g.nodes(), function(v) { swapWidthHeightOne(g.node(v)); });
|
||
_.each(g.edges(), function(e) { swapWidthHeightOne(g.edge(e)); });
|
||
}
|
||
|
||
function swapWidthHeightOne(attrs) {
|
||
var w = attrs.width;
|
||
attrs.width = attrs.height;
|
||
attrs.height = w;
|
||
}
|
||
|
||
function reverseY(g) {
|
||
_.each(g.nodes(), function(v) { reverseYOne(g.node(v)); });
|
||
|
||
_.each(g.edges(), function(e) {
|
||
var edge = g.edge(e);
|
||
_.each(edge.points, reverseYOne);
|
||
if (_.has(edge, "y")) {
|
||
reverseYOne(edge);
|
||
}
|
||
});
|
||
}
|
||
|
||
function reverseYOne(attrs) {
|
||
attrs.y = -attrs.y;
|
||
}
|
||
|
||
function swapXY(g) {
|
||
_.each(g.nodes(), function(v) { swapXYOne(g.node(v)); });
|
||
|
||
_.each(g.edges(), function(e) {
|
||
var edge = g.edge(e);
|
||
_.each(edge.points, swapXYOne);
|
||
if (_.has(edge, "x")) {
|
||
swapXYOne(edge);
|
||
}
|
||
});
|
||
}
|
||
|
||
function swapXYOne(attrs) {
|
||
var x = attrs.x;
|
||
attrs.x = attrs.y;
|
||
attrs.y = x;
|
||
}
|
||
|
||
},{"./lodash":63}],58:[function(require,module,exports){
|
||
/*
|
||
* Simple doubly linked list implementation derived from Cormen, et al.,
|
||
* "Introduction to Algorithms".
|
||
*/
|
||
|
||
module.exports = List;
|
||
|
||
function List() {
|
||
var sentinel = {};
|
||
sentinel._next = sentinel._prev = sentinel;
|
||
this._sentinel = sentinel;
|
||
}
|
||
|
||
List.prototype.dequeue = function() {
|
||
var sentinel = this._sentinel,
|
||
entry = sentinel._prev;
|
||
if (entry !== sentinel) {
|
||
unlink(entry);
|
||
return entry;
|
||
}
|
||
};
|
||
|
||
List.prototype.enqueue = function(entry) {
|
||
var sentinel = this._sentinel;
|
||
if (entry._prev && entry._next) {
|
||
unlink(entry);
|
||
}
|
||
entry._next = sentinel._next;
|
||
sentinel._next._prev = entry;
|
||
sentinel._next = entry;
|
||
entry._prev = sentinel;
|
||
};
|
||
|
||
List.prototype.toString = function() {
|
||
var strs = [],
|
||
sentinel = this._sentinel,
|
||
curr = sentinel._prev;
|
||
while (curr !== sentinel) {
|
||
strs.push(JSON.stringify(curr, filterOutLinks));
|
||
curr = curr._prev;
|
||
}
|
||
return "[" + strs.join(", ") + "]";
|
||
};
|
||
|
||
function unlink(entry) {
|
||
entry._prev._next = entry._next;
|
||
entry._next._prev = entry._prev;
|
||
delete entry._next;
|
||
delete entry._prev;
|
||
}
|
||
|
||
function filterOutLinks(k, v) {
|
||
if (k !== "_next" && k !== "_prev") {
|
||
return v;
|
||
}
|
||
}
|
||
|
||
},{}],59:[function(require,module,exports){
|
||
var _ = require("./lodash"),
|
||
util = require("./util"),
|
||
Graph = require("./graphlib").Graph;
|
||
|
||
module.exports = {
|
||
debugOrdering: debugOrdering
|
||
};
|
||
|
||
/* istanbul ignore next */
|
||
function debugOrdering(g) {
|
||
var layerMatrix = util.buildLayerMatrix(g);
|
||
|
||
var h = new Graph({ compound: true, multigraph: true }).setGraph({});
|
||
|
||
_.each(g.nodes(), function(v) {
|
||
h.setNode(v, { label: v });
|
||
h.setParent(v, "layer" + g.node(v).rank);
|
||
});
|
||
|
||
_.each(g.edges(), function(e) {
|
||
h.setEdge(e.v, e.w, {}, e.name);
|
||
});
|
||
|
||
_.each(layerMatrix, function(layer, i) {
|
||
var layerV = "layer" + i;
|
||
h.setNode(layerV, { rank: "same" });
|
||
_.reduce(layer, function(u, v) {
|
||
h.setEdge(u, v, { style: "invis" });
|
||
return v;
|
||
});
|
||
});
|
||
|
||
return h;
|
||
}
|
||
|
||
},{"./graphlib":60,"./lodash":63,"./util":82}],60:[function(require,module,exports){
|
||
/* global window */
|
||
|
||
var graphlib;
|
||
|
||
if (typeof require === "function") {
|
||
try {
|
||
graphlib = require("graphlib");
|
||
} catch (e) {}
|
||
}
|
||
|
||
if (!graphlib) {
|
||
graphlib = window.graphlib;
|
||
}
|
||
|
||
module.exports = graphlib;
|
||
|
||
},{"graphlib":84}],61:[function(require,module,exports){
|
||
var _ = require("./lodash"),
|
||
Graph = require("./graphlib").Graph,
|
||
List = require("./data/list");
|
||
|
||
/*
|
||
* A greedy heuristic for finding a feedback arc set for a graph. A feedback
|
||
* arc set is a set of edges that can be removed to make a graph acyclic.
|
||
* The algorithm comes from: P. Eades, X. Lin, and W. F. Smyth, "A fast and
|
||
* effective heuristic for the feedback arc set problem." This implementation
|
||
* adjusts that from the paper to allow for weighted edges.
|
||
*/
|
||
module.exports = greedyFAS;
|
||
|
||
var DEFAULT_WEIGHT_FN = _.constant(1);
|
||
|
||
function greedyFAS(g, weightFn) {
|
||
if (g.nodeCount() <= 1) {
|
||
return [];
|
||
}
|
||
var state = buildState(g, weightFn || DEFAULT_WEIGHT_FN);
|
||
var results = doGreedyFAS(state.graph, state.buckets, state.zeroIdx);
|
||
|
||
// Expand multi-edges
|
||
return _.flatten(_.map(results, function(e) {
|
||
return g.outEdges(e.v, e.w);
|
||
}), true);
|
||
}
|
||
|
||
function doGreedyFAS(g, buckets, zeroIdx) {
|
||
var results = [],
|
||
sources = buckets[buckets.length - 1],
|
||
sinks = buckets[0];
|
||
|
||
var entry;
|
||
while (g.nodeCount()) {
|
||
while ((entry = sinks.dequeue())) { removeNode(g, buckets, zeroIdx, entry); }
|
||
while ((entry = sources.dequeue())) { removeNode(g, buckets, zeroIdx, entry); }
|
||
if (g.nodeCount()) {
|
||
for (var i = buckets.length - 2; i > 0; --i) {
|
||
entry = buckets[i].dequeue();
|
||
if (entry) {
|
||
results = results.concat(removeNode(g, buckets, zeroIdx, entry, true));
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return results;
|
||
}
|
||
|
||
function removeNode(g, buckets, zeroIdx, entry, collectPredecessors) {
|
||
var results = collectPredecessors ? [] : undefined;
|
||
|
||
_.each(g.inEdges(entry.v), function(edge) {
|
||
var weight = g.edge(edge),
|
||
uEntry = g.node(edge.v);
|
||
|
||
if (collectPredecessors) {
|
||
results.push({ v: edge.v, w: edge.w });
|
||
}
|
||
|
||
uEntry.out -= weight;
|
||
assignBucket(buckets, zeroIdx, uEntry);
|
||
});
|
||
|
||
_.each(g.outEdges(entry.v), function(edge) {
|
||
var weight = g.edge(edge),
|
||
w = edge.w,
|
||
wEntry = g.node(w);
|
||
wEntry["in"] -= weight;
|
||
assignBucket(buckets, zeroIdx, wEntry);
|
||
});
|
||
|
||
g.removeNode(entry.v);
|
||
|
||
return results;
|
||
}
|
||
|
||
function buildState(g, weightFn) {
|
||
var fasGraph = new Graph(),
|
||
maxIn = 0,
|
||
maxOut = 0;
|
||
|
||
_.each(g.nodes(), function(v) {
|
||
fasGraph.setNode(v, { v: v, "in": 0, out: 0 });
|
||
});
|
||
|
||
// Aggregate weights on nodes, but also sum the weights across multi-edges
|
||
// into a single edge for the fasGraph.
|
||
_.each(g.edges(), function(e) {
|
||
var prevWeight = fasGraph.edge(e.v, e.w) || 0,
|
||
weight = weightFn(e),
|
||
edgeWeight = prevWeight + weight;
|
||
fasGraph.setEdge(e.v, e.w, edgeWeight);
|
||
maxOut = Math.max(maxOut, fasGraph.node(e.v).out += weight);
|
||
maxIn = Math.max(maxIn, fasGraph.node(e.w)["in"] += weight);
|
||
});
|
||
|
||
var buckets = _.range(maxOut + maxIn + 3).map(function() { return new List(); });
|
||
var zeroIdx = maxIn + 1;
|
||
|
||
_.each(fasGraph.nodes(), function(v) {
|
||
assignBucket(buckets, zeroIdx, fasGraph.node(v));
|
||
});
|
||
|
||
return { graph: fasGraph, buckets: buckets, zeroIdx: zeroIdx };
|
||
}
|
||
|
||
function assignBucket(buckets, zeroIdx, entry) {
|
||
if (!entry.out) {
|
||
buckets[0].enqueue(entry);
|
||
} else if (!entry["in"]) {
|
||
buckets[buckets.length - 1].enqueue(entry);
|
||
} else {
|
||
buckets[entry.out - entry["in"] + zeroIdx].enqueue(entry);
|
||
}
|
||
}
|
||
|
||
},{"./data/list":58,"./graphlib":60,"./lodash":63}],62:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("./lodash"),
|
||
acyclic = require("./acyclic"),
|
||
normalize = require("./normalize"),
|
||
rank = require("./rank"),
|
||
normalizeRanks = require("./util").normalizeRanks,
|
||
parentDummyChains = require("./parent-dummy-chains"),
|
||
removeEmptyRanks = require("./util").removeEmptyRanks,
|
||
nestingGraph = require("./nesting-graph"),
|
||
addBorderSegments = require("./add-border-segments"),
|
||
coordinateSystem = require("./coordinate-system"),
|
||
order = require("./order"),
|
||
position = require("./position"),
|
||
util = require("./util"),
|
||
Graph = require("./graphlib").Graph;
|
||
|
||
module.exports = layout;
|
||
|
||
function layout(g, opts) {
|
||
var time = opts && opts.debugTiming ? util.time : util.notime;
|
||
time("layout", function() {
|
||
var layoutGraph = time(" buildLayoutGraph",
|
||
function() { return buildLayoutGraph(g); });
|
||
time(" runLayout", function() { runLayout(layoutGraph, time); });
|
||
time(" updateInputGraph", function() { updateInputGraph(g, layoutGraph); });
|
||
});
|
||
}
|
||
|
||
function runLayout(g, time) {
|
||
time(" makeSpaceForEdgeLabels", function() { makeSpaceForEdgeLabels(g); });
|
||
time(" removeSelfEdges", function() { removeSelfEdges(g); });
|
||
time(" acyclic", function() { acyclic.run(g); });
|
||
time(" nestingGraph.run", function() { nestingGraph.run(g); });
|
||
time(" rank", function() { rank(util.asNonCompoundGraph(g)); });
|
||
time(" injectEdgeLabelProxies", function() { injectEdgeLabelProxies(g); });
|
||
time(" removeEmptyRanks", function() { removeEmptyRanks(g); });
|
||
time(" nestingGraph.cleanup", function() { nestingGraph.cleanup(g); });
|
||
time(" normalizeRanks", function() { normalizeRanks(g); });
|
||
time(" assignRankMinMax", function() { assignRankMinMax(g); });
|
||
time(" removeEdgeLabelProxies", function() { removeEdgeLabelProxies(g); });
|
||
time(" normalize.run", function() { normalize.run(g); });
|
||
time(" parentDummyChains", function() { parentDummyChains(g); });
|
||
time(" addBorderSegments", function() { addBorderSegments(g); });
|
||
time(" order", function() { order(g); });
|
||
time(" insertSelfEdges", function() { insertSelfEdges(g); });
|
||
time(" adjustCoordinateSystem", function() { coordinateSystem.adjust(g); });
|
||
time(" position", function() { position(g); });
|
||
time(" positionSelfEdges", function() { positionSelfEdges(g); });
|
||
time(" removeBorderNodes", function() { removeBorderNodes(g); });
|
||
time(" normalize.undo", function() { normalize.undo(g); });
|
||
time(" fixupEdgeLabelCoords", function() { fixupEdgeLabelCoords(g); });
|
||
time(" undoCoordinateSystem", function() { coordinateSystem.undo(g); });
|
||
time(" translateGraph", function() { translateGraph(g); });
|
||
time(" assignNodeIntersects", function() { assignNodeIntersects(g); });
|
||
time(" reversePoints", function() { reversePointsForReversedEdges(g); });
|
||
time(" acyclic.undo", function() { acyclic.undo(g); });
|
||
}
|
||
|
||
/*
|
||
* Copies final layout information from the layout graph back to the input
|
||
* graph. This process only copies whitelisted attributes from the layout graph
|
||
* to the input graph, so it serves as a good place to determine what
|
||
* attributes can influence layout.
|
||
*/
|
||
function updateInputGraph(inputGraph, layoutGraph) {
|
||
_.each(inputGraph.nodes(), function(v) {
|
||
var inputLabel = inputGraph.node(v),
|
||
layoutLabel = layoutGraph.node(v);
|
||
|
||
if (inputLabel) {
|
||
inputLabel.x = layoutLabel.x;
|
||
inputLabel.y = layoutLabel.y;
|
||
|
||
if (layoutGraph.children(v).length) {
|
||
inputLabel.width = layoutLabel.width;
|
||
inputLabel.height = layoutLabel.height;
|
||
}
|
||
}
|
||
});
|
||
|
||
_.each(inputGraph.edges(), function(e) {
|
||
var inputLabel = inputGraph.edge(e),
|
||
layoutLabel = layoutGraph.edge(e);
|
||
|
||
inputLabel.points = layoutLabel.points;
|
||
if (_.has(layoutLabel, "x")) {
|
||
inputLabel.x = layoutLabel.x;
|
||
inputLabel.y = layoutLabel.y;
|
||
}
|
||
});
|
||
|
||
inputGraph.graph().width = layoutGraph.graph().width;
|
||
inputGraph.graph().height = layoutGraph.graph().height;
|
||
}
|
||
|
||
var graphNumAttrs = ["nodesep", "edgesep", "ranksep", "marginx", "marginy"],
|
||
graphDefaults = { ranksep: 50, edgesep: 20, nodesep: 50, rankdir: "tb" },
|
||
graphAttrs = ["acyclicer", "ranker", "rankdir", "align"],
|
||
nodeNumAttrs = ["width", "height"],
|
||
nodeDefaults = { width: 0, height: 0 },
|
||
edgeNumAttrs = ["minlen", "weight", "width", "height", "labeloffset"],
|
||
edgeDefaults = {
|
||
minlen: 1, weight: 1, width: 0, height: 0,
|
||
labeloffset: 10, labelpos: "r"
|
||
},
|
||
edgeAttrs = ["labelpos"];
|
||
|
||
/*
|
||
* Constructs a new graph from the input graph, which can be used for layout.
|
||
* This process copies only whitelisted attributes from the input graph to the
|
||
* layout graph. Thus this function serves as a good place to determine what
|
||
* attributes can influence layout.
|
||
*/
|
||
function buildLayoutGraph(inputGraph) {
|
||
var g = new Graph({ multigraph: true, compound: true }),
|
||
graph = canonicalize(inputGraph.graph());
|
||
|
||
g.setGraph(_.merge({},
|
||
graphDefaults,
|
||
selectNumberAttrs(graph, graphNumAttrs),
|
||
_.pick(graph, graphAttrs)));
|
||
|
||
_.each(inputGraph.nodes(), function(v) {
|
||
var node = canonicalize(inputGraph.node(v));
|
||
g.setNode(v, _.defaults(selectNumberAttrs(node, nodeNumAttrs), nodeDefaults));
|
||
g.setParent(v, inputGraph.parent(v));
|
||
});
|
||
|
||
_.each(inputGraph.edges(), function(e) {
|
||
var edge = canonicalize(inputGraph.edge(e));
|
||
g.setEdge(e, _.merge({},
|
||
edgeDefaults,
|
||
selectNumberAttrs(edge, edgeNumAttrs),
|
||
_.pick(edge, edgeAttrs)));
|
||
});
|
||
|
||
return g;
|
||
}
|
||
|
||
/*
|
||
* This idea comes from the Gansner paper: to account for edge labels in our
|
||
* layout we split each rank in half by doubling minlen and halving ranksep.
|
||
* Then we can place labels at these mid-points between nodes.
|
||
*
|
||
* We also add some minimal padding to the width to push the label for the edge
|
||
* away from the edge itself a bit.
|
||
*/
|
||
function makeSpaceForEdgeLabels(g) {
|
||
var graph = g.graph();
|
||
graph.ranksep /= 2;
|
||
_.each(g.edges(), function(e) {
|
||
var edge = g.edge(e);
|
||
edge.minlen *= 2;
|
||
if (edge.labelpos.toLowerCase() !== "c") {
|
||
if (graph.rankdir === "TB" || graph.rankdir === "BT") {
|
||
edge.width += edge.labeloffset;
|
||
} else {
|
||
edge.height += edge.labeloffset;
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
/*
|
||
* Creates temporary dummy nodes that capture the rank in which each edge's
|
||
* label is going to, if it has one of non-zero width and height. We do this
|
||
* so that we can safely remove empty ranks while preserving balance for the
|
||
* label's position.
|
||
*/
|
||
function injectEdgeLabelProxies(g) {
|
||
_.each(g.edges(), function(e) {
|
||
var edge = g.edge(e);
|
||
if (edge.width && edge.height) {
|
||
var v = g.node(e.v),
|
||
w = g.node(e.w),
|
||
label = { rank: (w.rank - v.rank) / 2 + v.rank, e: e };
|
||
util.addDummyNode(g, "edge-proxy", label, "_ep");
|
||
}
|
||
});
|
||
}
|
||
|
||
function assignRankMinMax(g) {
|
||
var maxRank = 0;
|
||
_.each(g.nodes(), function(v) {
|
||
var node = g.node(v);
|
||
if (node.borderTop) {
|
||
node.minRank = g.node(node.borderTop).rank;
|
||
node.maxRank = g.node(node.borderBottom).rank;
|
||
maxRank = _.max(maxRank, node.maxRank);
|
||
}
|
||
});
|
||
g.graph().maxRank = maxRank;
|
||
}
|
||
|
||
function removeEdgeLabelProxies(g) {
|
||
_.each(g.nodes(), function(v) {
|
||
var node = g.node(v);
|
||
if (node.dummy === "edge-proxy") {
|
||
g.edge(node.e).labelRank = node.rank;
|
||
g.removeNode(v);
|
||
}
|
||
});
|
||
}
|
||
|
||
function translateGraph(g) {
|
||
var minX = Number.POSITIVE_INFINITY,
|
||
maxX = 0,
|
||
minY = Number.POSITIVE_INFINITY,
|
||
maxY = 0,
|
||
graphLabel = g.graph(),
|
||
marginX = graphLabel.marginx || 0,
|
||
marginY = graphLabel.marginy || 0;
|
||
|
||
function getExtremes(attrs) {
|
||
var x = attrs.x,
|
||
y = attrs.y,
|
||
w = attrs.width,
|
||
h = attrs.height;
|
||
minX = Math.min(minX, x - w / 2);
|
||
maxX = Math.max(maxX, x + w / 2);
|
||
minY = Math.min(minY, y - h / 2);
|
||
maxY = Math.max(maxY, y + h / 2);
|
||
}
|
||
|
||
_.each(g.nodes(), function(v) { getExtremes(g.node(v)); });
|
||
_.each(g.edges(), function(e) {
|
||
var edge = g.edge(e);
|
||
if (_.has(edge, "x")) {
|
||
getExtremes(edge);
|
||
}
|
||
});
|
||
|
||
minX -= marginX;
|
||
minY -= marginY;
|
||
|
||
_.each(g.nodes(), function(v) {
|
||
var node = g.node(v);
|
||
node.x -= minX;
|
||
node.y -= minY;
|
||
});
|
||
|
||
_.each(g.edges(), function(e) {
|
||
var edge = g.edge(e);
|
||
_.each(edge.points, function(p) {
|
||
p.x -= minX;
|
||
p.y -= minY;
|
||
});
|
||
if (_.has(edge, "x")) { edge.x -= minX; }
|
||
if (_.has(edge, "y")) { edge.y -= minY; }
|
||
});
|
||
|
||
graphLabel.width = maxX - minX + marginX;
|
||
graphLabel.height = maxY - minY + marginY;
|
||
}
|
||
|
||
function assignNodeIntersects(g) {
|
||
_.each(g.edges(), function(e) {
|
||
var edge = g.edge(e),
|
||
nodeV = g.node(e.v),
|
||
nodeW = g.node(e.w),
|
||
p1, p2;
|
||
if (!edge.points) {
|
||
edge.points = [];
|
||
p1 = nodeW;
|
||
p2 = nodeV;
|
||
} else {
|
||
p1 = edge.points[0];
|
||
p2 = edge.points[edge.points.length - 1];
|
||
}
|
||
edge.points.unshift(util.intersectRect(nodeV, p1));
|
||
edge.points.push(util.intersectRect(nodeW, p2));
|
||
});
|
||
}
|
||
|
||
function fixupEdgeLabelCoords(g) {
|
||
_.each(g.edges(), function(e) {
|
||
var edge = g.edge(e);
|
||
if (_.has(edge, "x")) {
|
||
if (edge.labelpos === "l" || edge.labelpos === "r") {
|
||
edge.width -= edge.labeloffset;
|
||
}
|
||
switch (edge.labelpos) {
|
||
case "l": edge.x -= edge.width / 2 + edge.labeloffset; break;
|
||
case "r": edge.x += edge.width / 2 + edge.labeloffset; break;
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
function reversePointsForReversedEdges(g) {
|
||
_.each(g.edges(), function(e) {
|
||
var edge = g.edge(e);
|
||
if (edge.reversed) {
|
||
edge.points.reverse();
|
||
}
|
||
});
|
||
}
|
||
|
||
function removeBorderNodes(g) {
|
||
_.each(g.nodes(), function(v) {
|
||
if (g.children(v).length) {
|
||
var node = g.node(v),
|
||
t = g.node(node.borderTop),
|
||
b = g.node(node.borderBottom),
|
||
l = g.node(_.last(node.borderLeft)),
|
||
r = g.node(_.last(node.borderRight));
|
||
|
||
node.width = Math.abs(r.x - l.x);
|
||
node.height = Math.abs(b.y - t.y);
|
||
node.x = l.x + node.width / 2;
|
||
node.y = t.y + node.height / 2;
|
||
}
|
||
});
|
||
|
||
_.each(g.nodes(), function(v) {
|
||
if (g.node(v).dummy === "border") {
|
||
g.removeNode(v);
|
||
}
|
||
});
|
||
}
|
||
|
||
function removeSelfEdges(g) {
|
||
_.each(g.edges(), function(e) {
|
||
if (e.v === e.w) {
|
||
var node = g.node(e.v);
|
||
if (!node.selfEdges) {
|
||
node.selfEdges = [];
|
||
}
|
||
node.selfEdges.push({ e: e, label: g.edge(e) });
|
||
g.removeEdge(e);
|
||
}
|
||
});
|
||
}
|
||
|
||
function insertSelfEdges(g) {
|
||
var layers = util.buildLayerMatrix(g);
|
||
_.each(layers, function(layer) {
|
||
var orderShift = 0;
|
||
_.each(layer, function(v, i) {
|
||
var node = g.node(v);
|
||
node.order = i + orderShift;
|
||
_.each(node.selfEdges, function(selfEdge) {
|
||
util.addDummyNode(g, "selfedge", {
|
||
width: selfEdge.label.width,
|
||
height: selfEdge.label.height,
|
||
rank: node.rank,
|
||
order: i + (++orderShift),
|
||
e: selfEdge.e,
|
||
label: selfEdge.label
|
||
}, "_se");
|
||
});
|
||
delete node.selfEdges;
|
||
});
|
||
});
|
||
}
|
||
|
||
function positionSelfEdges(g) {
|
||
_.each(g.nodes(), function(v) {
|
||
var node = g.node(v);
|
||
if (node.dummy === "selfedge") {
|
||
var selfNode = g.node(node.e.v),
|
||
x = selfNode.x + selfNode.width / 2,
|
||
y = selfNode.y,
|
||
dx = node.x - x,
|
||
dy = selfNode.height / 2;
|
||
g.setEdge(node.e, node.label);
|
||
g.removeNode(v);
|
||
node.label.points = [
|
||
{ x: x + 2 * dx / 3, y: y - dy },
|
||
{ x: x + 5 * dx / 6, y: y - dy },
|
||
{ x: x + dx , y: y },
|
||
{ x: x + 5 * dx / 6, y: y + dy },
|
||
{ x: x + 2 * dx / 3, y: y + dy },
|
||
];
|
||
node.label.x = node.x;
|
||
node.label.y = node.y;
|
||
}
|
||
});
|
||
}
|
||
|
||
function selectNumberAttrs(obj, attrs) {
|
||
return _.mapValues(_.pick(obj, attrs), Number);
|
||
}
|
||
|
||
function canonicalize(attrs) {
|
||
var newAttrs = {};
|
||
_.each(attrs, function(v, k) {
|
||
newAttrs[k.toLowerCase()] = v;
|
||
});
|
||
return newAttrs;
|
||
}
|
||
|
||
},{"./acyclic":55,"./add-border-segments":56,"./coordinate-system":57,"./graphlib":60,"./lodash":63,"./nesting-graph":64,"./normalize":65,"./order":70,"./parent-dummy-chains":75,"./position":77,"./rank":79,"./util":82}],63:[function(require,module,exports){
|
||
module.exports=require(51)
|
||
},{"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/lodash.js":51,"lodash":104}],64:[function(require,module,exports){
|
||
var _ = require("./lodash"),
|
||
util = require("./util");
|
||
|
||
module.exports = {
|
||
run: run,
|
||
cleanup: cleanup
|
||
};
|
||
|
||
/*
|
||
* A nesting graph creates dummy nodes for the tops and bottoms of subgraphs,
|
||
* adds appropriate edges to ensure that all cluster nodes are placed between
|
||
* these boundries, and ensures that the graph is connected.
|
||
*
|
||
* In addition we ensure, through the use of the minlen property, that nodes
|
||
* and subgraph border nodes to not end up on the same rank.
|
||
*
|
||
* Preconditions:
|
||
*
|
||
* 1. Input graph is a DAG
|
||
* 2. Nodes in the input graph has a minlen attribute
|
||
*
|
||
* Postconditions:
|
||
*
|
||
* 1. Input graph is connected.
|
||
* 2. Dummy nodes are added for the tops and bottoms of subgraphs.
|
||
* 3. The minlen attribute for nodes is adjusted to ensure nodes do not
|
||
* get placed on the same rank as subgraph border nodes.
|
||
*
|
||
* The nesting graph idea comes from Sander, "Layout of Compound Directed
|
||
* Graphs."
|
||
*/
|
||
function run(g) {
|
||
var root = util.addDummyNode(g, "root", {}, "_root"),
|
||
depths = treeDepths(g),
|
||
height = _.max(depths) - 1,
|
||
nodeSep = 2 * height + 1;
|
||
|
||
g.graph().nestingRoot = root;
|
||
|
||
// Multiply minlen by nodeSep to align nodes on non-border ranks.
|
||
_.each(g.edges(), function(e) { g.edge(e).minlen *= nodeSep; });
|
||
|
||
// Calculate a weight that is sufficient to keep subgraphs vertically compact
|
||
var weight = sumWeights(g) + 1;
|
||
|
||
// Create border nodes and link them up
|
||
_.each(g.children(), function(child) {
|
||
dfs(g, root, nodeSep, weight, height, depths, child);
|
||
});
|
||
|
||
// Save the multiplier for node layers for later removal of empty border
|
||
// layers.
|
||
g.graph().nodeRankFactor = nodeSep;
|
||
}
|
||
|
||
function dfs(g, root, nodeSep, weight, height, depths, v) {
|
||
var children = g.children(v);
|
||
if (!children.length) {
|
||
if (v !== root) {
|
||
g.setEdge(root, v, { weight: 0, minlen: nodeSep });
|
||
}
|
||
return;
|
||
}
|
||
|
||
var top = util.addBorderNode(g, "_bt"),
|
||
bottom = util.addBorderNode(g, "_bb"),
|
||
label = g.node(v);
|
||
|
||
g.setParent(top, v);
|
||
label.borderTop = top;
|
||
g.setParent(bottom, v);
|
||
label.borderBottom = bottom;
|
||
|
||
_.each(children, function(child) {
|
||
dfs(g, root, nodeSep, weight, height, depths, child);
|
||
|
||
var childNode = g.node(child),
|
||
childTop = childNode.borderTop ? childNode.borderTop : child,
|
||
childBottom = childNode.borderBottom ? childNode.borderBottom : child,
|
||
thisWeight = childNode.borderTop ? weight : 2 * weight,
|
||
minlen = childTop !== childBottom ? 1 : height - depths[v] + 1;
|
||
|
||
g.setEdge(top, childTop, {
|
||
weight: thisWeight,
|
||
minlen: minlen,
|
||
nestingEdge: true
|
||
});
|
||
|
||
g.setEdge(childBottom, bottom, {
|
||
weight: thisWeight,
|
||
minlen: minlen,
|
||
nestingEdge: true
|
||
});
|
||
});
|
||
|
||
if (!g.parent(v)) {
|
||
g.setEdge(root, top, { weight: 0, minlen: height + depths[v] });
|
||
}
|
||
}
|
||
|
||
function treeDepths(g) {
|
||
var depths = {};
|
||
function dfs(v, depth) {
|
||
var children = g.children(v);
|
||
if (children && children.length) {
|
||
_.each(children, function(child) {
|
||
dfs(child, depth + 1);
|
||
});
|
||
}
|
||
depths[v] = depth;
|
||
}
|
||
_.each(g.children(), function(v) { dfs(v, 1); });
|
||
return depths;
|
||
}
|
||
|
||
function sumWeights(g) {
|
||
return _.reduce(g.edges(), function(acc, e) {
|
||
return acc + g.edge(e).weight;
|
||
}, 0);
|
||
}
|
||
|
||
function cleanup(g) {
|
||
var graphLabel = g.graph();
|
||
g.removeNode(graphLabel.nestingRoot);
|
||
delete graphLabel.nestingRoot;
|
||
_.each(g.edges(), function(e) {
|
||
var edge = g.edge(e);
|
||
if (edge.nestingEdge) {
|
||
g.removeEdge(e);
|
||
}
|
||
});
|
||
}
|
||
|
||
},{"./lodash":63,"./util":82}],65:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("./lodash"),
|
||
util = require("./util");
|
||
|
||
module.exports = {
|
||
run: run,
|
||
undo: undo
|
||
};
|
||
|
||
/*
|
||
* Breaks any long edges in the graph into short segments that span 1 layer
|
||
* each. This operation is undoable with the denormalize function.
|
||
*
|
||
* Pre-conditions:
|
||
*
|
||
* 1. The input graph is a DAG.
|
||
* 2. Each node in the graph has a "rank" property.
|
||
*
|
||
* Post-condition:
|
||
*
|
||
* 1. All edges in the graph have a length of 1.
|
||
* 2. Dummy nodes are added where edges have been split into segments.
|
||
* 3. The graph is augmented with a "dummyChains" attribute which contains
|
||
* the first dummy in each chain of dummy nodes produced.
|
||
*/
|
||
function run(g) {
|
||
g.graph().dummyChains = [];
|
||
_.each(g.edges(), function(edge) { normalizeEdge(g, edge); });
|
||
}
|
||
|
||
function normalizeEdge(g, e) {
|
||
var v = e.v,
|
||
vRank = g.node(v).rank,
|
||
w = e.w,
|
||
wRank = g.node(w).rank,
|
||
name = e.name,
|
||
edgeLabel = g.edge(e),
|
||
labelRank = edgeLabel.labelRank;
|
||
|
||
if (wRank === vRank + 1) return;
|
||
|
||
g.removeEdge(e);
|
||
|
||
var dummy, attrs, i;
|
||
for (i = 0, ++vRank; vRank < wRank; ++i, ++vRank) {
|
||
edgeLabel.points = [];
|
||
attrs = {
|
||
width: 0, height: 0,
|
||
edgeLabel: edgeLabel, edgeObj: e,
|
||
rank: vRank
|
||
};
|
||
dummy = util.addDummyNode(g, "edge", attrs, "_d");
|
||
if (vRank === labelRank) {
|
||
attrs.width = edgeLabel.width;
|
||
attrs.height = edgeLabel.height;
|
||
attrs.dummy = "edge-label";
|
||
attrs.labelpos = edgeLabel.labelpos;
|
||
}
|
||
g.setEdge(v, dummy, { weight: edgeLabel.weight }, name);
|
||
if (i === 0) {
|
||
g.graph().dummyChains.push(dummy);
|
||
}
|
||
v = dummy;
|
||
}
|
||
|
||
g.setEdge(v, w, { weight: edgeLabel.weight }, name);
|
||
}
|
||
|
||
function undo(g) {
|
||
_.each(g.graph().dummyChains, function(v) {
|
||
var node = g.node(v),
|
||
origLabel = node.edgeLabel,
|
||
w;
|
||
g.setEdge(node.edgeObj, origLabel);
|
||
while (node.dummy) {
|
||
w = g.successors(v)[0];
|
||
g.removeNode(v);
|
||
origLabel.points.push({ x: node.x, y: node.y });
|
||
if (node.dummy === "edge-label") {
|
||
origLabel.x = node.x;
|
||
origLabel.y = node.y;
|
||
origLabel.width = node.width;
|
||
origLabel.height = node.height;
|
||
}
|
||
v = w;
|
||
node = g.node(v);
|
||
}
|
||
});
|
||
}
|
||
|
||
},{"./lodash":63,"./util":82}],66:[function(require,module,exports){
|
||
var _ = require("../lodash");
|
||
|
||
module.exports = addSubgraphConstraints;
|
||
|
||
function addSubgraphConstraints(g, cg, vs) {
|
||
var prev = {},
|
||
rootPrev;
|
||
|
||
_.each(vs, function(v) {
|
||
var child = g.parent(v),
|
||
parent,
|
||
prevChild;
|
||
while (child) {
|
||
parent = g.parent(child);
|
||
if (parent) {
|
||
prevChild = prev[parent];
|
||
prev[parent] = child;
|
||
} else {
|
||
prevChild = rootPrev;
|
||
rootPrev = child;
|
||
}
|
||
if (prevChild && prevChild !== child) {
|
||
cg.setEdge(prevChild, child);
|
||
return;
|
||
}
|
||
child = parent;
|
||
}
|
||
});
|
||
|
||
/*
|
||
function dfs(v) {
|
||
var children = v ? g.children(v) : g.children();
|
||
if (children.length) {
|
||
var min = Number.POSITIVE_INFINITY,
|
||
subgraphs = [];
|
||
_.each(children, function(child) {
|
||
var childMin = dfs(child);
|
||
if (g.children(child).length) {
|
||
subgraphs.push({ v: child, order: childMin });
|
||
}
|
||
min = Math.min(min, childMin);
|
||
});
|
||
_.reduce(_.sortBy(subgraphs, "order"), function(prev, curr) {
|
||
cg.setEdge(prev.v, curr.v);
|
||
return curr;
|
||
});
|
||
return min;
|
||
}
|
||
return g.node(v).order;
|
||
}
|
||
dfs(undefined);
|
||
*/
|
||
}
|
||
|
||
},{"../lodash":63}],67:[function(require,module,exports){
|
||
var _ = require("../lodash");
|
||
|
||
module.exports = barycenter;
|
||
|
||
function barycenter(g, movable) {
|
||
return _.map(movable, function(v) {
|
||
var inV = g.inEdges(v);
|
||
if (!inV.length) {
|
||
return { v: v };
|
||
} else {
|
||
var result = _.reduce(inV, function(acc, e) {
|
||
var edge = g.edge(e),
|
||
nodeU = g.node(e.v);
|
||
return {
|
||
sum: acc.sum + (edge.weight * nodeU.order),
|
||
weight: acc.weight + edge.weight
|
||
};
|
||
}, { sum: 0, weight: 0 });
|
||
|
||
return {
|
||
v: v,
|
||
barycenter: result.sum / result.weight,
|
||
weight: result.weight
|
||
};
|
||
}
|
||
});
|
||
}
|
||
|
||
|
||
},{"../lodash":63}],68:[function(require,module,exports){
|
||
var _ = require("../lodash"),
|
||
Graph = require("../graphlib").Graph;
|
||
|
||
module.exports = buildLayerGraph;
|
||
|
||
/*
|
||
* Constructs a graph that can be used to sort a layer of nodes. The graph will
|
||
* contain all base and subgraph nodes from the request layer in their original
|
||
* hierarchy and any edges that are incident on these nodes and are of the type
|
||
* requested by the "relationship" parameter.
|
||
*
|
||
* Nodes from the requested rank that do not have parents are assigned a root
|
||
* node in the output graph, which is set in the root graph attribute. This
|
||
* makes it easy to walk the hierarchy of movable nodes during ordering.
|
||
*
|
||
* Pre-conditions:
|
||
*
|
||
* 1. Input graph is a DAG
|
||
* 2. Base nodes in the input graph have a rank attribute
|
||
* 3. Subgraph nodes in the input graph has minRank and maxRank attributes
|
||
* 4. Edges have an assigned weight
|
||
*
|
||
* Post-conditions:
|
||
*
|
||
* 1. Output graph has all nodes in the movable rank with preserved
|
||
* hierarchy.
|
||
* 2. Root nodes in the movable layer are made children of the node
|
||
* indicated by the root attribute of the graph.
|
||
* 3. Non-movable nodes incident on movable nodes, selected by the
|
||
* relationship parameter, are included in the graph (without hierarchy).
|
||
* 4. Edges incident on movable nodes, selected by the relationship
|
||
* parameter, are added to the output graph.
|
||
* 5. The weights for copied edges are aggregated as need, since the output
|
||
* graph is not a multi-graph.
|
||
*/
|
||
function buildLayerGraph(g, rank, relationship) {
|
||
var root = createRootNode(g),
|
||
result = new Graph({ compound: true }).setGraph({ root: root })
|
||
.setDefaultNodeLabel(function(v) { return g.node(v); });
|
||
|
||
_.each(g.nodes(), function(v) {
|
||
var node = g.node(v),
|
||
parent = g.parent(v);
|
||
|
||
if (node.rank === rank || node.minRank <= rank && rank <= node.maxRank) {
|
||
result.setNode(v);
|
||
result.setParent(v, parent || root);
|
||
|
||
// This assumes we have only short edges!
|
||
_.each(g[relationship](v), function(e) {
|
||
var u = e.v === v ? e.w : e.v,
|
||
edge = result.edge(u, v),
|
||
weight = !_.isUndefined(edge) ? edge.weight : 0;
|
||
result.setEdge(u, v, { weight: g.edge(e).weight + weight });
|
||
});
|
||
|
||
if (_.has(node, "minRank")) {
|
||
result.setNode(v, {
|
||
borderLeft: node.borderLeft[rank],
|
||
borderRight: node.borderRight[rank]
|
||
});
|
||
}
|
||
}
|
||
});
|
||
|
||
return result;
|
||
}
|
||
|
||
function createRootNode(g) {
|
||
var v;
|
||
while (g.hasNode((v = _.uniqueId("_root"))));
|
||
return v;
|
||
}
|
||
|
||
},{"../graphlib":60,"../lodash":63}],69:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("../lodash");
|
||
|
||
module.exports = crossCount;
|
||
|
||
/*
|
||
* A function that takes a layering (an array of layers, each with an array of
|
||
* ordererd nodes) and a graph and returns a weighted crossing count.
|
||
*
|
||
* Pre-conditions:
|
||
*
|
||
* 1. Input graph must be simple (not a multigraph), directed, and include
|
||
* only simple edges.
|
||
* 2. Edges in the input graph must have assigned weights.
|
||
*
|
||
* Post-conditions:
|
||
*
|
||
* 1. The graph and layering matrix are left unchanged.
|
||
*
|
||
* This algorithm is derived from Barth, et al., "Bilayer Cross Counting."
|
||
*/
|
||
function crossCount(g, layering) {
|
||
var cc = 0;
|
||
for (var i = 1; i < layering.length; ++i) {
|
||
cc += twoLayerCrossCount(g, layering[i-1], layering[i]);
|
||
}
|
||
return cc;
|
||
}
|
||
|
||
function twoLayerCrossCount(g, northLayer, southLayer) {
|
||
// Sort all of the edges between the north and south layers by their position
|
||
// in the north layer and then the south. Map these edges to the position of
|
||
// their head in the south layer.
|
||
var southPos = _.zipObject(southLayer,
|
||
_.map(southLayer, function (v, i) { return i; }));
|
||
var southEntries = _.flatten(_.map(northLayer, function(v) {
|
||
return _.chain(g.outEdges(v))
|
||
.map(function(e) {
|
||
return { pos: southPos[e.w], weight: g.edge(e).weight };
|
||
})
|
||
.sortBy("pos")
|
||
.value();
|
||
}), true);
|
||
|
||
// Build the accumulator tree
|
||
var firstIndex = 1;
|
||
while (firstIndex < southLayer.length) firstIndex <<= 1;
|
||
var treeSize = 2 * firstIndex - 1;
|
||
firstIndex -= 1;
|
||
var tree = _.map(new Array(treeSize), function() { return 0; });
|
||
|
||
// Calculate the weighted crossings
|
||
var cc = 0;
|
||
_.each(southEntries.forEach(function(entry) {
|
||
var index = entry.pos + firstIndex;
|
||
tree[index] += entry.weight;
|
||
var weightSum = 0;
|
||
while (index > 0) {
|
||
if (index % 2) {
|
||
weightSum += tree[index + 1];
|
||
}
|
||
index = (index - 1) >> 1;
|
||
tree[index] += entry.weight;
|
||
}
|
||
cc += entry.weight * weightSum;
|
||
}));
|
||
|
||
return cc;
|
||
}
|
||
|
||
},{"../lodash":63}],70:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("../lodash"),
|
||
initOrder = require("./init-order"),
|
||
crossCount = require("./cross-count"),
|
||
sortSubgraph = require("./sort-subgraph"),
|
||
buildLayerGraph = require("./build-layer-graph"),
|
||
addSubgraphConstraints = require("./add-subgraph-constraints"),
|
||
Graph = require("../graphlib").Graph,
|
||
util = require("../util");
|
||
|
||
module.exports = order;
|
||
|
||
/*
|
||
* Applies heuristics to minimize edge crossings in the graph and sets the best
|
||
* order solution as an order attribute on each node.
|
||
*
|
||
* Pre-conditions:
|
||
*
|
||
* 1. Graph must be DAG
|
||
* 2. Graph nodes must be objects with a "rank" attribute
|
||
* 3. Graph edges must have the "weight" attribute
|
||
*
|
||
* Post-conditions:
|
||
*
|
||
* 1. Graph nodes will have an "order" attribute based on the results of the
|
||
* algorithm.
|
||
*/
|
||
function order(g) {
|
||
var maxRank = util.maxRank(g),
|
||
downLayerGraphs = buildLayerGraphs(g, _.range(1, maxRank + 1), "inEdges"),
|
||
upLayerGraphs = buildLayerGraphs(g, _.range(maxRank - 1, -1, -1), "outEdges");
|
||
|
||
var layering = initOrder(g);
|
||
assignOrder(g, layering);
|
||
|
||
var bestCC = Number.POSITIVE_INFINITY,
|
||
best;
|
||
|
||
for (var i = 0, lastBest = 0; lastBest < 4; ++i, ++lastBest) {
|
||
sweepLayerGraphs(i % 2 ? downLayerGraphs : upLayerGraphs, i % 4 >= 2);
|
||
|
||
layering = util.buildLayerMatrix(g);
|
||
var cc = crossCount(g, layering);
|
||
if (cc < bestCC) {
|
||
lastBest = 0;
|
||
best = _.cloneDeep(layering);
|
||
bestCC = cc;
|
||
}
|
||
}
|
||
|
||
assignOrder(g, best);
|
||
}
|
||
|
||
function buildLayerGraphs(g, ranks, relationship) {
|
||
return _.map(ranks, function(rank) {
|
||
return buildLayerGraph(g, rank, relationship);
|
||
});
|
||
}
|
||
|
||
function sweepLayerGraphs(layerGraphs, biasRight) {
|
||
var cg = new Graph();
|
||
_.each(layerGraphs, function(lg) {
|
||
var root = lg.graph().root;
|
||
var sorted = sortSubgraph(lg, root, cg, biasRight);
|
||
_.each(sorted.vs, function(v, i) {
|
||
lg.node(v).order = i;
|
||
});
|
||
addSubgraphConstraints(lg, cg, sorted.vs);
|
||
});
|
||
}
|
||
|
||
function assignOrder(g, layering) {
|
||
_.each(layering, function(layer) {
|
||
_.each(layer, function(v, i) {
|
||
g.node(v).order = i;
|
||
});
|
||
});
|
||
}
|
||
|
||
},{"../graphlib":60,"../lodash":63,"../util":82,"./add-subgraph-constraints":66,"./build-layer-graph":68,"./cross-count":69,"./init-order":71,"./sort-subgraph":73}],71:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("../lodash");
|
||
|
||
module.exports = initOrder;
|
||
|
||
/*
|
||
* Assigns an initial order value for each node by performing a DFS search
|
||
* starting from nodes in the first rank. Nodes are assigned an order in their
|
||
* rank as they are first visited.
|
||
*
|
||
* This approach comes from Gansner, et al., "A Technique for Drawing Directed
|
||
* Graphs."
|
||
*
|
||
* Returns a layering matrix with an array per layer and each layer sorted by
|
||
* the order of its nodes.
|
||
*/
|
||
function initOrder(g) {
|
||
var visited = {},
|
||
simpleNodes = _.filter(g.nodes(), function(v) {
|
||
return !g.children(v).length;
|
||
}),
|
||
maxRank = _.max(_.map(simpleNodes, function(v) { return g.node(v).rank; })),
|
||
layers = _.map(_.range(maxRank + 1), function() { return []; });
|
||
|
||
function dfs(v) {
|
||
if (_.has(visited, v)) return;
|
||
visited[v] = true;
|
||
var node = g.node(v);
|
||
layers[node.rank].push(v);
|
||
_.each(g.successors(v), dfs);
|
||
}
|
||
|
||
var orderedVs = _.sortBy(simpleNodes, function(v) { return g.node(v).rank; });
|
||
_.each(orderedVs, dfs);
|
||
|
||
return layers;
|
||
}
|
||
|
||
},{"../lodash":63}],72:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("../lodash");
|
||
|
||
module.exports = resolveConflicts;
|
||
|
||
/*
|
||
* Given a list of entries of the form {v, barycenter, weight} and a
|
||
* constraint graph this function will resolve any conflicts between the
|
||
* constraint graph and the barycenters for the entries. If the barycenters for
|
||
* an entry would violate a constraint in the constraint graph then we coalesce
|
||
* the nodes in the conflict into a new node that respects the contraint and
|
||
* aggregates barycenter and weight information.
|
||
*
|
||
* This implementation is based on the description in Forster, "A Fast and
|
||
* Simple Hueristic for Constrained Two-Level Crossing Reduction," thought it
|
||
* differs in some specific details.
|
||
*
|
||
* Pre-conditions:
|
||
*
|
||
* 1. Each entry has the form {v, barycenter, weight}, or if the node has
|
||
* no barycenter, then {v}.
|
||
*
|
||
* Returns:
|
||
*
|
||
* A new list of entries of the form {vs, i, barycenter, weight}. The list
|
||
* `vs` may either be a singleton or it may be an aggregation of nodes
|
||
* ordered such that they do not violate constraints from the constraint
|
||
* graph. The property `i` is the lowest original index of any of the
|
||
* elements in `vs`.
|
||
*/
|
||
function resolveConflicts(entries, cg) {
|
||
var mappedEntries = {};
|
||
_.each(entries, function(entry, i) {
|
||
var tmp = mappedEntries[entry.v] = {
|
||
indegree: 0,
|
||
"in": [],
|
||
out: [],
|
||
vs: [entry.v],
|
||
i: i
|
||
};
|
||
if (!_.isUndefined(entry.barycenter)) {
|
||
tmp.barycenter = entry.barycenter;
|
||
tmp.weight = entry.weight;
|
||
}
|
||
});
|
||
|
||
_.each(cg.edges(), function(e) {
|
||
var entryV = mappedEntries[e.v],
|
||
entryW = mappedEntries[e.w];
|
||
if (!_.isUndefined(entryV) && !_.isUndefined(entryW)) {
|
||
entryW.indegree++;
|
||
entryV.out.push(mappedEntries[e.w]);
|
||
}
|
||
});
|
||
|
||
var sourceSet = _.filter(mappedEntries, function(entry) {
|
||
return !entry.indegree;
|
||
});
|
||
|
||
return doResolveConflicts(sourceSet);
|
||
}
|
||
|
||
function doResolveConflicts(sourceSet) {
|
||
var entries = [];
|
||
|
||
function handleIn(vEntry) {
|
||
return function(uEntry) {
|
||
if (uEntry.merged) {
|
||
return;
|
||
}
|
||
if (_.isUndefined(uEntry.barycenter) ||
|
||
_.isUndefined(vEntry.barycenter) ||
|
||
uEntry.barycenter >= vEntry.barycenter) {
|
||
mergeEntries(vEntry, uEntry);
|
||
}
|
||
};
|
||
}
|
||
|
||
function handleOut(vEntry) {
|
||
return function(wEntry) {
|
||
wEntry["in"].push(vEntry);
|
||
if (--wEntry.indegree === 0) {
|
||
sourceSet.push(wEntry);
|
||
}
|
||
};
|
||
}
|
||
|
||
while (sourceSet.length) {
|
||
var entry = sourceSet.pop();
|
||
entries.push(entry);
|
||
_.each(entry["in"].reverse(), handleIn(entry));
|
||
_.each(entry.out, handleOut(entry));
|
||
}
|
||
|
||
return _.chain(entries)
|
||
.filter(function(entry) { return !entry.merged; })
|
||
.map(function(entry) {
|
||
return _.pick(entry, ["vs", "i", "barycenter", "weight"]);
|
||
})
|
||
.value();
|
||
}
|
||
|
||
function mergeEntries(target, source) {
|
||
var sum = 0,
|
||
weight = 0;
|
||
|
||
if (target.weight) {
|
||
sum += target.barycenter * target.weight;
|
||
weight += target.weight;
|
||
}
|
||
|
||
if (source.weight) {
|
||
sum += source.barycenter * source.weight;
|
||
weight += source.weight;
|
||
}
|
||
|
||
target.vs = source.vs.concat(target.vs);
|
||
target.barycenter = sum / weight;
|
||
target.weight = weight;
|
||
target.i = Math.min(source.i, target.i);
|
||
source.merged = true;
|
||
}
|
||
|
||
},{"../lodash":63}],73:[function(require,module,exports){
|
||
var _ = require("../lodash"),
|
||
barycenter = require("./barycenter"),
|
||
resolveConflicts = require("./resolve-conflicts"),
|
||
sort = require("./sort");
|
||
|
||
module.exports = sortSubgraph;
|
||
|
||
function sortSubgraph(g, v, cg, biasRight) {
|
||
var movable = g.children(v),
|
||
node = g.node(v),
|
||
bl = node ? node.borderLeft : undefined,
|
||
br = node ? node.borderRight: undefined,
|
||
subgraphs = {};
|
||
|
||
if (bl) {
|
||
movable = _.filter(movable, function(w) {
|
||
return w !== bl && w !== br;
|
||
});
|
||
}
|
||
|
||
var barycenters = barycenter(g, movable);
|
||
_.each(barycenters, function(entry) {
|
||
if (g.children(entry.v).length) {
|
||
var subgraphResult = sortSubgraph(g, entry.v, cg, biasRight);
|
||
subgraphs[entry.v] = subgraphResult;
|
||
if (_.has(subgraphResult, "barycenter")) {
|
||
mergeBarycenters(entry, subgraphResult);
|
||
}
|
||
}
|
||
});
|
||
|
||
var entries = resolveConflicts(barycenters, cg);
|
||
expandSubgraphs(entries, subgraphs);
|
||
|
||
var result = sort(entries, biasRight);
|
||
|
||
if (bl) {
|
||
result.vs = _.flatten([bl, result.vs, br], true);
|
||
if (g.predecessors(bl).length) {
|
||
var blPred = g.node(g.predecessors(bl)[0]),
|
||
brPred = g.node(g.predecessors(br)[0]);
|
||
if (!_.has(result, "barycenter")) {
|
||
result.barycenter = 0;
|
||
result.weight = 0;
|
||
}
|
||
result.barycenter = (result.barycenter * result.weight +
|
||
blPred.order + brPred.order) / (result.weight + 2);
|
||
result.weight += 2;
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
function expandSubgraphs(entries, subgraphs) {
|
||
_.each(entries, function(entry) {
|
||
entry.vs = _.flatten(entry.vs.map(function(v) {
|
||
if (subgraphs[v]) {
|
||
return subgraphs[v].vs;
|
||
}
|
||
return v;
|
||
}), true);
|
||
});
|
||
}
|
||
|
||
function mergeBarycenters(target, other) {
|
||
if (!_.isUndefined(target.barycenter)) {
|
||
target.barycenter = (target.barycenter * target.weight +
|
||
other.barycenter * other.weight) /
|
||
(target.weight + other.weight);
|
||
target.weight += other.weight;
|
||
} else {
|
||
target.barycenter = other.barycenter;
|
||
target.weight = other.weight;
|
||
}
|
||
}
|
||
|
||
},{"../lodash":63,"./barycenter":67,"./resolve-conflicts":72,"./sort":74}],74:[function(require,module,exports){
|
||
var _ = require("../lodash"),
|
||
util = require("../util");
|
||
|
||
module.exports = sort;
|
||
|
||
function sort(entries, biasRight) {
|
||
var parts = util.partition(entries, function(entry) {
|
||
return _.has(entry, "barycenter");
|
||
});
|
||
var sortable = parts.lhs,
|
||
unsortable = _.sortBy(parts.rhs, function(entry) { return -entry.i; }),
|
||
vs = [],
|
||
sum = 0,
|
||
weight = 0,
|
||
vsIndex = 0;
|
||
|
||
sortable.sort(compareWithBias(!!biasRight));
|
||
|
||
vsIndex = consumeUnsortable(vs, unsortable, vsIndex);
|
||
|
||
_.each(sortable, function (entry) {
|
||
vsIndex += entry.vs.length;
|
||
vs.push(entry.vs);
|
||
sum += entry.barycenter * entry.weight;
|
||
weight += entry.weight;
|
||
vsIndex = consumeUnsortable(vs, unsortable, vsIndex);
|
||
});
|
||
|
||
var result = { vs: _.flatten(vs, true) };
|
||
if (weight) {
|
||
result.barycenter = sum / weight;
|
||
result.weight = weight;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
function consumeUnsortable(vs, unsortable, index) {
|
||
var last;
|
||
while (unsortable.length && (last = _.last(unsortable)).i <= index) {
|
||
unsortable.pop();
|
||
vs.push(last.vs);
|
||
index++;
|
||
}
|
||
return index;
|
||
}
|
||
|
||
function compareWithBias(bias) {
|
||
return function(entryV, entryW) {
|
||
if (entryV.barycenter < entryW.barycenter) {
|
||
return -1;
|
||
} else if (entryV.barycenter > entryW.barycenter) {
|
||
return 1;
|
||
}
|
||
|
||
return !bias ? entryV.i - entryW.i : entryW.i - entryV.i;
|
||
};
|
||
}
|
||
|
||
},{"../lodash":63,"../util":82}],75:[function(require,module,exports){
|
||
var _ = require("./lodash");
|
||
|
||
module.exports = parentDummyChains;
|
||
|
||
function parentDummyChains(g) {
|
||
var postorderNums = postorder(g);
|
||
|
||
_.each(g.graph().dummyChains, function(v) {
|
||
var node = g.node(v),
|
||
edgeObj = node.edgeObj,
|
||
pathData = findPath(g, postorderNums, edgeObj.v, edgeObj.w),
|
||
path = pathData.path,
|
||
lca = pathData.lca,
|
||
pathIdx = 0,
|
||
pathV = path[pathIdx],
|
||
ascending = true;
|
||
|
||
while (v !== edgeObj.w) {
|
||
node = g.node(v);
|
||
|
||
if (ascending) {
|
||
while ((pathV = path[pathIdx]) !== lca &&
|
||
g.node(pathV).maxRank < node.rank) {
|
||
pathIdx++;
|
||
}
|
||
|
||
if (pathV === lca) {
|
||
ascending = false;
|
||
}
|
||
}
|
||
|
||
if (!ascending) {
|
||
while (pathIdx < path.length - 1 &&
|
||
g.node(pathV = path[pathIdx + 1]).minRank <= node.rank) {
|
||
pathIdx++;
|
||
}
|
||
pathV = path[pathIdx];
|
||
}
|
||
|
||
g.setParent(v, pathV);
|
||
v = g.successors(v)[0];
|
||
}
|
||
});
|
||
}
|
||
|
||
// Find a path from v to w through the lowest common ancestor (LCA). Return the
|
||
// full path and the LCA.
|
||
function findPath(g, postorderNums, v, w) {
|
||
var vPath = [],
|
||
wPath = [],
|
||
low = Math.min(postorderNums[v].low, postorderNums[w].low),
|
||
lim = Math.max(postorderNums[v].lim, postorderNums[w].lim),
|
||
parent,
|
||
lca;
|
||
|
||
// Traverse up from v to find the LCA
|
||
parent = v;
|
||
do {
|
||
parent = g.parent(parent);
|
||
vPath.push(parent);
|
||
} while (parent &&
|
||
(postorderNums[parent].low > low || lim > postorderNums[parent].lim));
|
||
lca = parent;
|
||
|
||
// Traverse from w to LCA
|
||
parent = w;
|
||
while ((parent = g.parent(parent)) !== lca) {
|
||
wPath.push(parent);
|
||
}
|
||
|
||
return { path: vPath.concat(wPath.reverse()), lca: lca };
|
||
}
|
||
|
||
function postorder(g) {
|
||
var result = {},
|
||
lim = 0;
|
||
|
||
function dfs(v) {
|
||
var low = lim;
|
||
_.each(g.children(v), dfs);
|
||
result[v] = { low: low, lim: lim++ };
|
||
}
|
||
_.each(g.children(), dfs);
|
||
|
||
return result;
|
||
}
|
||
|
||
},{"./lodash":63}],76:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("../lodash"),
|
||
Graph = require("../graphlib").Graph,
|
||
util = require("../util");
|
||
|
||
/*
|
||
* This module provides coordinate assignment based on Brandes and Köpf, "Fast
|
||
* and Simple Horizontal Coordinate Assignment."
|
||
*/
|
||
|
||
module.exports = {
|
||
positionX: positionX,
|
||
findType1Conflicts: findType1Conflicts,
|
||
findType2Conflicts: findType2Conflicts,
|
||
addConflict: addConflict,
|
||
hasConflict: hasConflict,
|
||
verticalAlignment: verticalAlignment,
|
||
horizontalCompaction: horizontalCompaction,
|
||
alignCoordinates: alignCoordinates,
|
||
findSmallestWidthAlignment: findSmallestWidthAlignment,
|
||
balance: balance
|
||
};
|
||
|
||
/*
|
||
* Marks all edges in the graph with a type-1 conflict with the "type1Conflict"
|
||
* property. A type-1 conflict is one where a non-inner segment crosses an
|
||
* inner segment. An inner segment is an edge with both incident nodes marked
|
||
* with the "dummy" property.
|
||
*
|
||
* This algorithm scans layer by layer, starting with the second, for type-1
|
||
* conflicts between the current layer and the previous layer. For each layer
|
||
* it scans the nodes from left to right until it reaches one that is incident
|
||
* on an inner segment. It then scans predecessors to determine if they have
|
||
* edges that cross that inner segment. At the end a final scan is done for all
|
||
* nodes on the current rank to see if they cross the last visited inner
|
||
* segment.
|
||
*
|
||
* This algorithm (safely) assumes that a dummy node will only be incident on a
|
||
* single node in the layers being scanned.
|
||
*/
|
||
function findType1Conflicts(g, layering) {
|
||
var conflicts = {};
|
||
|
||
function visitLayer(prevLayer, layer) {
|
||
var
|
||
// last visited node in the previous layer that is incident on an inner
|
||
// segment.
|
||
k0 = 0,
|
||
// Tracks the last node in this layer scanned for crossings with a type-1
|
||
// segment.
|
||
scanPos = 0,
|
||
prevLayerLength = prevLayer.length,
|
||
lastNode = _.last(layer);
|
||
|
||
_.each(layer, function(v, i) {
|
||
var w = findOtherInnerSegmentNode(g, v),
|
||
k1 = w ? g.node(w).order : prevLayerLength;
|
||
|
||
if (w || v === lastNode) {
|
||
_.each(layer.slice(scanPos, i +1), function(scanNode) {
|
||
_.each(g.predecessors(scanNode), function(u) {
|
||
var uLabel = g.node(u),
|
||
uPos = uLabel.order;
|
||
if ((uPos < k0 || k1 < uPos) &&
|
||
!(uLabel.dummy && g.node(scanNode).dummy)) {
|
||
addConflict(conflicts, u, scanNode);
|
||
}
|
||
});
|
||
});
|
||
scanPos = i + 1;
|
||
k0 = k1;
|
||
}
|
||
});
|
||
|
||
return layer;
|
||
}
|
||
|
||
_.reduce(layering, visitLayer);
|
||
return conflicts;
|
||
}
|
||
|
||
function findType2Conflicts(g, layering) {
|
||
var conflicts = {};
|
||
|
||
function scan(south, southPos, southEnd, prevNorthBorder, nextNorthBorder) {
|
||
var v;
|
||
_.each(_.range(southPos, southEnd), function(i) {
|
||
v = south[i];
|
||
if (g.node(v).dummy) {
|
||
_.each(g.predecessors(v), function(u) {
|
||
var uNode = g.node(u);
|
||
if (uNode.dummy &&
|
||
(uNode.order < prevNorthBorder || uNode.order > nextNorthBorder)) {
|
||
addConflict(conflicts, u, v);
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
|
||
function visitLayer(north, south) {
|
||
var prevNorthPos = -1,
|
||
nextNorthPos,
|
||
southPos = 0;
|
||
|
||
_.each(south, function(v, southLookahead) {
|
||
if (g.node(v).dummy === "border") {
|
||
var predecessors = g.predecessors(v);
|
||
if (predecessors.length) {
|
||
nextNorthPos = g.node(predecessors[0]).order;
|
||
scan(south, southPos, southLookahead, prevNorthPos, nextNorthPos);
|
||
southPos = southLookahead;
|
||
prevNorthPos = nextNorthPos;
|
||
}
|
||
}
|
||
scan(south, southPos, south.length, nextNorthPos, north.length);
|
||
});
|
||
|
||
return south;
|
||
}
|
||
|
||
_.reduce(layering, visitLayer);
|
||
return conflicts;
|
||
}
|
||
|
||
function findOtherInnerSegmentNode(g, v) {
|
||
if (g.node(v).dummy) {
|
||
return _.find(g.predecessors(v), function(u) {
|
||
return g.node(u).dummy;
|
||
});
|
||
}
|
||
}
|
||
|
||
function addConflict(conflicts, v, w) {
|
||
if (v > w) {
|
||
var tmp = v;
|
||
v = w;
|
||
w = tmp;
|
||
}
|
||
|
||
var conflictsV = conflicts[v];
|
||
if (!conflictsV) {
|
||
conflicts[v] = conflictsV = {};
|
||
}
|
||
conflictsV[w] = true;
|
||
}
|
||
|
||
function hasConflict(conflicts, v, w) {
|
||
if (v > w) {
|
||
var tmp = v;
|
||
v = w;
|
||
w = tmp;
|
||
}
|
||
return _.has(conflicts[v], w);
|
||
}
|
||
|
||
/*
|
||
* Try to align nodes into vertical "blocks" where possible. This algorithm
|
||
* attempts to align a node with one of its median neighbors. If the edge
|
||
* connecting a neighbor is a type-1 conflict then we ignore that possibility.
|
||
* If a previous node has already formed a block with a node after the node
|
||
* we're trying to form a block with, we also ignore that possibility - our
|
||
* blocks would be split in that scenario.
|
||
*/
|
||
function verticalAlignment(g, layering, conflicts, neighborFn) {
|
||
var root = {},
|
||
align = {},
|
||
pos = {};
|
||
|
||
// We cache the position here based on the layering because the graph and
|
||
// layering may be out of sync. The layering matrix is manipulated to
|
||
// generate different extreme alignments.
|
||
_.each(layering, function(layer) {
|
||
_.each(layer, function(v, order) {
|
||
root[v] = v;
|
||
align[v] = v;
|
||
pos[v] = order;
|
||
});
|
||
});
|
||
|
||
_.each(layering, function(layer) {
|
||
var prevIdx = -1;
|
||
_.each(layer, function(v) {
|
||
var ws = neighborFn(v);
|
||
if (ws.length) {
|
||
ws = _.sortBy(ws, function(w) { return pos[w]; });
|
||
var mp = (ws.length - 1) / 2;
|
||
for (var i = Math.floor(mp), il = Math.ceil(mp); i <= il; ++i) {
|
||
var w = ws[i];
|
||
if (align[v] === v &&
|
||
prevIdx < pos[w] &&
|
||
!hasConflict(conflicts, v, w)) {
|
||
align[w] = v;
|
||
align[v] = root[v] = root[w];
|
||
prevIdx = pos[w];
|
||
}
|
||
}
|
||
}
|
||
});
|
||
});
|
||
|
||
return { root: root, align: align };
|
||
}
|
||
|
||
function horizontalCompaction(g, layering, root, align, reverseSep) {
|
||
// This portion of the algorithm differs from BK due to a number of problems.
|
||
// Instead of their algorithm we construct a new block graph and do two
|
||
// sweeps. The first sweep places blocks with the smallest possible
|
||
// coordinates. The second sweep removes unused space by moving blocks to the
|
||
// greatest coordinates without violating separation.
|
||
var xs = {},
|
||
blockG = buildBlockGraph(g, layering, root, reverseSep);
|
||
|
||
// First pass, assign smallest coordinates via DFS
|
||
var visited = {};
|
||
function pass1(v) {
|
||
if (!_.has(visited, v)) {
|
||
visited[v] = true;
|
||
xs[v] = _.reduce(blockG.inEdges(v), function(max, e) {
|
||
pass1(e.v);
|
||
return Math.max(max, xs[e.v] + blockG.edge(e));
|
||
}, 0);
|
||
}
|
||
}
|
||
_.each(blockG.nodes(), pass1);
|
||
|
||
var borderType = reverseSep ? "borderLeft" : "borderRight";
|
||
function pass2(v) {
|
||
if (visited[v] !== 2) {
|
||
visited[v]++;
|
||
var node = g.node(v);
|
||
var min = _.reduce(blockG.outEdges(v), function(min, e) {
|
||
pass2(e.w);
|
||
return Math.min(min, xs[e.w] - blockG.edge(e));
|
||
}, Number.POSITIVE_INFINITY);
|
||
if (min !== Number.POSITIVE_INFINITY && node.borderType !== borderType) {
|
||
xs[v] = Math.max(xs[v], min);
|
||
}
|
||
}
|
||
}
|
||
_.each(blockG.nodes(), pass2);
|
||
|
||
// Assign x coordinates to all nodes
|
||
_.each(align, function(v) {
|
||
xs[v] = xs[root[v]];
|
||
});
|
||
|
||
return xs;
|
||
}
|
||
|
||
|
||
function buildBlockGraph(g, layering, root, reverseSep) {
|
||
var blockGraph = new Graph(),
|
||
graphLabel = g.graph(),
|
||
sepFn = sep(graphLabel.nodesep, graphLabel.edgesep, reverseSep);
|
||
|
||
_.each(layering, function(layer) {
|
||
var u;
|
||
_.each(layer, function(v) {
|
||
var vRoot = root[v];
|
||
blockGraph.setNode(vRoot);
|
||
if (u) {
|
||
var uRoot = root[u],
|
||
prevMax = blockGraph.edge(uRoot, vRoot);
|
||
blockGraph.setEdge(uRoot, vRoot, Math.max(sepFn(g, v, u), prevMax || 0));
|
||
}
|
||
u = v;
|
||
});
|
||
});
|
||
|
||
return blockGraph;
|
||
}
|
||
|
||
/*
|
||
* Returns the alignment that has the smallest width of the given alignments.
|
||
*/
|
||
function findSmallestWidthAlignment(g, xss) {
|
||
return _.min(xss, function(xs) {
|
||
var min = _.min(xs, function(x, v) { return x - width(g, v) / 2; }),
|
||
max = _.max(xs, function(x, v) { return x + width(g, v) / 2; });
|
||
return max - min;
|
||
});
|
||
}
|
||
|
||
/*
|
||
* Align the coordinates of each of the layout alignments such that
|
||
* left-biased alignments have their minimum coordinate at the same point as
|
||
* the minimum coordinate of the smallest width alignment and right-biased
|
||
* alignments have their maximum coordinate at the same point as the maximum
|
||
* coordinate of the smallest width alignment.
|
||
*/
|
||
function alignCoordinates(xss, alignTo) {
|
||
var alignToMin = _.min(alignTo),
|
||
alignToMax = _.max(alignTo);
|
||
|
||
_.each(["u", "d"], function(vert) {
|
||
_.each(["l", "r"], function(horiz) {
|
||
var alignment = vert + horiz,
|
||
xs = xss[alignment],
|
||
delta;
|
||
if (xs === alignTo) return;
|
||
|
||
delta = horiz === "l" ? alignToMin - _.min(xs) : alignToMax - _.max(xs);
|
||
|
||
if (delta) {
|
||
xss[alignment] = _.mapValues(xs, function(x) { return x + delta; });
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
function balance(xss, align) {
|
||
return _.mapValues(xss.ul, function(ignore, v) {
|
||
if (align) {
|
||
return xss[align.toLowerCase()][v];
|
||
} else {
|
||
var xs = _.sortBy(_.pluck(xss, v));
|
||
return (xs[1] + xs[2]) / 2;
|
||
}
|
||
});
|
||
}
|
||
|
||
function positionX(g) {
|
||
var layering = util.buildLayerMatrix(g),
|
||
conflicts = _.merge(findType1Conflicts(g, layering),
|
||
findType2Conflicts(g, layering));
|
||
|
||
var xss = {},
|
||
adjustedLayering;
|
||
_.each(["u", "d"], function(vert) {
|
||
adjustedLayering = vert === "u" ? layering : _.values(layering).reverse();
|
||
_.each(["l", "r"], function(horiz) {
|
||
if (horiz === "r") {
|
||
adjustedLayering = _.map(adjustedLayering, function(inner) {
|
||
return _.values(inner).reverse();
|
||
});
|
||
}
|
||
|
||
var neighborFn = _.bind(vert === "u" ? g.predecessors : g.successors, g);
|
||
var align = verticalAlignment(g, adjustedLayering, conflicts, neighborFn);
|
||
var xs = horizontalCompaction(g, adjustedLayering,
|
||
align.root, align.align,
|
||
horiz === "r");
|
||
if (horiz === "r") {
|
||
xs = _.mapValues(xs, function(x) { return -x; });
|
||
}
|
||
xss[vert + horiz] = xs;
|
||
});
|
||
});
|
||
|
||
var smallestWidth = findSmallestWidthAlignment(g, xss);
|
||
alignCoordinates(xss, smallestWidth);
|
||
return balance(xss, g.graph().align);
|
||
}
|
||
|
||
function sep(nodeSep, edgeSep, reverseSep) {
|
||
return function(g, v, w) {
|
||
var vLabel = g.node(v),
|
||
wLabel = g.node(w),
|
||
sum = 0,
|
||
delta;
|
||
|
||
sum += vLabel.width / 2;
|
||
if (_.has(vLabel, "labelpos")) {
|
||
switch (vLabel.labelpos.toLowerCase()) {
|
||
case "l": delta = -vLabel.width / 2; break;
|
||
case "r": delta = vLabel.width / 2; break;
|
||
}
|
||
}
|
||
if (delta) {
|
||
sum += reverseSep ? delta : -delta;
|
||
}
|
||
delta = 0;
|
||
|
||
sum += (vLabel.dummy ? edgeSep : nodeSep) / 2;
|
||
sum += (wLabel.dummy ? edgeSep : nodeSep) / 2;
|
||
|
||
sum += wLabel.width / 2;
|
||
if (_.has(wLabel, "labelpos")) {
|
||
switch (wLabel.labelpos.toLowerCase()) {
|
||
case "l": delta = wLabel.width / 2; break;
|
||
case "r": delta = -wLabel.width / 2; break;
|
||
}
|
||
}
|
||
if (delta) {
|
||
sum += reverseSep ? delta : -delta;
|
||
}
|
||
delta = 0;
|
||
|
||
return sum;
|
||
};
|
||
}
|
||
|
||
function width(g, v) {
|
||
return g.node(v).width;
|
||
}
|
||
|
||
},{"../graphlib":60,"../lodash":63,"../util":82}],77:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("../lodash"),
|
||
util = require("../util"),
|
||
positionX = require("./bk").positionX;
|
||
|
||
module.exports = position;
|
||
|
||
function position(g) {
|
||
g = util.asNonCompoundGraph(g);
|
||
|
||
positionY(g);
|
||
_.each(positionX(g), function(x, v) {
|
||
g.node(v).x = x;
|
||
});
|
||
}
|
||
|
||
function positionY(g) {
|
||
var layering = util.buildLayerMatrix(g),
|
||
rankSep = g.graph().ranksep,
|
||
prevY = 0;
|
||
_.each(layering, function(layer) {
|
||
var maxHeight = _.max(_.map(layer, function(v) { return g.node(v).height; }));
|
||
_.each(layer, function(v) {
|
||
g.node(v).y = prevY + maxHeight / 2;
|
||
});
|
||
prevY += maxHeight + rankSep;
|
||
});
|
||
}
|
||
|
||
|
||
},{"../lodash":63,"../util":82,"./bk":76}],78:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("../lodash"),
|
||
Graph = require("../graphlib").Graph,
|
||
slack = require("./util").slack;
|
||
|
||
module.exports = feasibleTree;
|
||
|
||
/*
|
||
* Constructs a spanning tree with tight edges and adjusted the input node's
|
||
* ranks to achieve this. A tight edge is one that is has a length that matches
|
||
* its "minlen" attribute.
|
||
*
|
||
* The basic structure for this function is derived from Gansner, et al., "A
|
||
* Technique for Drawing Directed Graphs."
|
||
*
|
||
* Pre-conditions:
|
||
*
|
||
* 1. Graph must be a DAG.
|
||
* 2. Graph must be connected.
|
||
* 3. Graph must have at least one node.
|
||
* 5. Graph nodes must have been previously assigned a "rank" property that
|
||
* respects the "minlen" property of incident edges.
|
||
* 6. Graph edges must have a "minlen" property.
|
||
*
|
||
* Post-conditions:
|
||
*
|
||
* - Graph nodes will have their rank adjusted to ensure that all edges are
|
||
* tight.
|
||
*
|
||
* Returns a tree (undirected graph) that is constructed using only "tight"
|
||
* edges.
|
||
*/
|
||
function feasibleTree(g) {
|
||
var t = new Graph({ directed: false });
|
||
|
||
// Choose arbitrary node from which to start our tree
|
||
var start = g.nodes()[0],
|
||
size = g.nodeCount();
|
||
t.setNode(start, {});
|
||
|
||
var edge, delta;
|
||
while (tightTree(t, g) < size) {
|
||
edge = findMinSlackEdge(t, g);
|
||
delta = t.hasNode(edge.v) ? slack(g, edge) : -slack(g, edge);
|
||
shiftRanks(t, g, delta);
|
||
}
|
||
|
||
return t;
|
||
}
|
||
|
||
/*
|
||
* Finds a maximal tree of tight edges and returns the number of nodes in the
|
||
* tree.
|
||
*/
|
||
function tightTree(t, g) {
|
||
function dfs(v) {
|
||
_.each(g.nodeEdges(v), function(e) {
|
||
var edgeV = e.v,
|
||
w = (v === edgeV) ? e.w : edgeV;
|
||
if (!t.hasNode(w) && !slack(g, e)) {
|
||
t.setNode(w, {});
|
||
t.setEdge(v, w, {});
|
||
dfs(w);
|
||
}
|
||
});
|
||
}
|
||
|
||
_.each(t.nodes(), dfs);
|
||
return t.nodeCount();
|
||
}
|
||
|
||
/*
|
||
* Finds the edge with the smallest slack that is incident on tree and returns
|
||
* it.
|
||
*/
|
||
function findMinSlackEdge(t, g) {
|
||
return _.min(g.edges(), function(e) {
|
||
if (t.hasNode(e.v) !== t.hasNode(e.w)) {
|
||
return slack(g, e);
|
||
}
|
||
});
|
||
}
|
||
|
||
function shiftRanks(t, g, delta) {
|
||
_.each(t.nodes(), function(v) {
|
||
g.node(v).rank += delta;
|
||
});
|
||
}
|
||
|
||
},{"../graphlib":60,"../lodash":63,"./util":81}],79:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var rankUtil = require("./util"),
|
||
longestPath = rankUtil.longestPath,
|
||
feasibleTree = require("./feasible-tree"),
|
||
networkSimplex = require("./network-simplex");
|
||
|
||
module.exports = rank;
|
||
|
||
/*
|
||
* Assigns a rank to each node in the input graph that respects the "minlen"
|
||
* constraint specified on edges between nodes.
|
||
*
|
||
* This basic structure is derived from Gansner, et al., "A Technique for
|
||
* Drawing Directed Graphs."
|
||
*
|
||
* Pre-conditions:
|
||
*
|
||
* 1. Graph must be a connected DAG
|
||
* 2. Graph nodes must be objects
|
||
* 3. Graph edges must have "weight" and "minlen" attributes
|
||
*
|
||
* Post-conditions:
|
||
*
|
||
* 1. Graph nodes will have a "rank" attribute based on the results of the
|
||
* algorithm. Ranks can start at any index (including negative), we'll
|
||
* fix them up later.
|
||
*/
|
||
function rank(g) {
|
||
switch(g.graph().ranker) {
|
||
case "network-simplex": networkSimplexRanker(g); break;
|
||
case "tight-tree": tightTreeRanker(g); break;
|
||
case "longest-path": longestPathRanker(g); break;
|
||
default: networkSimplexRanker(g);
|
||
}
|
||
}
|
||
|
||
// A fast and simple ranker, but results are far from optimal.
|
||
var longestPathRanker = longestPath;
|
||
|
||
function tightTreeRanker(g) {
|
||
longestPath(g);
|
||
feasibleTree(g);
|
||
}
|
||
|
||
function networkSimplexRanker(g) {
|
||
networkSimplex(g);
|
||
}
|
||
|
||
},{"./feasible-tree":78,"./network-simplex":80,"./util":81}],80:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("../lodash"),
|
||
feasibleTree = require("./feasible-tree"),
|
||
slack = require("./util").slack,
|
||
initRank = require("./util").longestPath,
|
||
preorder = require("../graphlib").alg.preorder,
|
||
postorder = require("../graphlib").alg.postorder,
|
||
simplify = require("../util").simplify;
|
||
|
||
module.exports = networkSimplex;
|
||
|
||
// Expose some internals for testing purposes
|
||
networkSimplex.initLowLimValues = initLowLimValues;
|
||
networkSimplex.initCutValues = initCutValues;
|
||
networkSimplex.calcCutValue = calcCutValue;
|
||
networkSimplex.leaveEdge = leaveEdge;
|
||
networkSimplex.enterEdge = enterEdge;
|
||
networkSimplex.exchangeEdges = exchangeEdges;
|
||
|
||
/*
|
||
* The network simplex algorithm assigns ranks to each node in the input graph
|
||
* and iteratively improves the ranking to reduce the length of edges.
|
||
*
|
||
* Preconditions:
|
||
*
|
||
* 1. The input graph must be a DAG.
|
||
* 2. All nodes in the graph must have an object value.
|
||
* 3. All edges in the graph must have "minlen" and "weight" attributes.
|
||
*
|
||
* Postconditions:
|
||
*
|
||
* 1. All nodes in the graph will have an assigned "rank" attribute that has
|
||
* been optimized by the network simplex algorithm. Ranks start at 0.
|
||
*
|
||
*
|
||
* A rough sketch of the algorithm is as follows:
|
||
*
|
||
* 1. Assign initial ranks to each node. We use the longest path algorithm,
|
||
* which assigns ranks to the lowest position possible. In general this
|
||
* leads to very wide bottom ranks and unnecessarily long edges.
|
||
* 2. Construct a feasible tight tree. A tight tree is one such that all
|
||
* edges in the tree have no slack (difference between length of edge
|
||
* and minlen for the edge). This by itself greatly improves the assigned
|
||
* rankings by shorting edges.
|
||
* 3. Iteratively find edges that have negative cut values. Generally a
|
||
* negative cut value indicates that the edge could be removed and a new
|
||
* tree edge could be added to produce a more compact graph.
|
||
*
|
||
* Much of the algorithms here are derived from Gansner, et al., "A Technique
|
||
* for Drawing Directed Graphs." The structure of the file roughly follows the
|
||
* structure of the overall algorithm.
|
||
*/
|
||
function networkSimplex(g) {
|
||
g = simplify(g);
|
||
initRank(g);
|
||
var t = feasibleTree(g);
|
||
initLowLimValues(t);
|
||
initCutValues(t, g);
|
||
|
||
var e, f;
|
||
while ((e = leaveEdge(t))) {
|
||
f = enterEdge(t, g, e);
|
||
exchangeEdges(t, g, e, f);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Initializes cut values for all edges in the tree.
|
||
*/
|
||
function initCutValues(t, g) {
|
||
var vs = postorder(t, t.nodes());
|
||
vs = vs.slice(0, vs.length - 1);
|
||
_.each(vs, function(v) {
|
||
assignCutValue(t, g, v);
|
||
});
|
||
}
|
||
|
||
function assignCutValue(t, g, child) {
|
||
var childLab = t.node(child),
|
||
parent = childLab.parent;
|
||
t.edge(child, parent).cutvalue = calcCutValue(t, g, child);
|
||
}
|
||
|
||
/*
|
||
* Given the tight tree, its graph, and a child in the graph calculate and
|
||
* return the cut value for the edge between the child and its parent.
|
||
*/
|
||
function calcCutValue(t, g, child) {
|
||
var childLab = t.node(child),
|
||
parent = childLab.parent,
|
||
// True if the child is on the tail end of the edge in the directed graph
|
||
childIsTail = true,
|
||
// The graph's view of the tree edge we're inspecting
|
||
graphEdge = g.edge(child, parent),
|
||
// The accumulated cut value for the edge between this node and its parent
|
||
cutValue = 0;
|
||
|
||
if (!graphEdge) {
|
||
childIsTail = false;
|
||
graphEdge = g.edge(parent, child);
|
||
}
|
||
|
||
cutValue = graphEdge.weight;
|
||
|
||
_.each(g.nodeEdges(child), function(e) {
|
||
var isOutEdge = e.v === child,
|
||
other = isOutEdge ? e.w : e.v;
|
||
|
||
if (other !== parent) {
|
||
var pointsToHead = isOutEdge === childIsTail,
|
||
otherWeight = g.edge(e).weight;
|
||
|
||
cutValue += pointsToHead ? otherWeight : -otherWeight;
|
||
if (isTreeEdge(t, child, other)) {
|
||
var otherCutValue = t.edge(child, other).cutvalue;
|
||
cutValue += pointsToHead ? -otherCutValue : otherCutValue;
|
||
}
|
||
}
|
||
});
|
||
|
||
return cutValue;
|
||
}
|
||
|
||
function initLowLimValues(tree, root) {
|
||
if (arguments.length < 2) {
|
||
root = tree.nodes()[0];
|
||
}
|
||
dfsAssignLowLim(tree, {}, 1, root);
|
||
}
|
||
|
||
function dfsAssignLowLim(tree, visited, nextLim, v, parent) {
|
||
var low = nextLim,
|
||
label = tree.node(v);
|
||
|
||
visited[v] = true;
|
||
_.each(tree.neighbors(v), function(w) {
|
||
if (!_.has(visited, w)) {
|
||
nextLim = dfsAssignLowLim(tree, visited, nextLim, w, v);
|
||
}
|
||
});
|
||
|
||
label.low = low;
|
||
label.lim = nextLim++;
|
||
if (parent) {
|
||
label.parent = parent;
|
||
} else {
|
||
// TODO should be able to remove this when we incrementally update low lim
|
||
delete label.parent;
|
||
}
|
||
|
||
return nextLim;
|
||
}
|
||
|
||
function leaveEdge(tree) {
|
||
return _.find(tree.edges(), function(e) {
|
||
return tree.edge(e).cutvalue < 0;
|
||
});
|
||
}
|
||
|
||
function enterEdge(t, g, edge) {
|
||
var v = edge.v,
|
||
w = edge.w;
|
||
|
||
// For the rest of this function we assume that v is the tail and w is the
|
||
// head, so if we don't have this edge in the graph we should flip it to
|
||
// match the correct orientation.
|
||
if (!g.hasEdge(v, w)) {
|
||
v = edge.w;
|
||
w = edge.v;
|
||
}
|
||
|
||
var vLabel = t.node(v),
|
||
wLabel = t.node(w),
|
||
tailLabel = vLabel,
|
||
flip = false;
|
||
|
||
// If the root is in the tail of the edge then we need to flip the logic that
|
||
// checks for the head and tail nodes in the candidates function below.
|
||
if (vLabel.lim > wLabel.lim) {
|
||
tailLabel = wLabel;
|
||
flip = true;
|
||
}
|
||
|
||
var candidates = _.filter(g.edges(), function(edge) {
|
||
return flip === isDescendant(t, t.node(edge.v), tailLabel) &&
|
||
flip !== isDescendant(t, t.node(edge.w), tailLabel);
|
||
});
|
||
|
||
return _.min(candidates, function(edge) { return slack(g, edge); });
|
||
}
|
||
|
||
function exchangeEdges(t, g, e, f) {
|
||
var v = e.v,
|
||
w = e.w;
|
||
t.removeEdge(v, w);
|
||
t.setEdge(f.v, f.w, {});
|
||
initLowLimValues(t);
|
||
initCutValues(t, g);
|
||
updateRanks(t, g);
|
||
}
|
||
|
||
function updateRanks(t, g) {
|
||
var root = _.find(t.nodes(), function(v) { return !g.node(v).parent; }),
|
||
vs = preorder(t, root);
|
||
vs = vs.slice(1);
|
||
_.each(vs, function(v) {
|
||
var parent = t.node(v).parent,
|
||
edge = g.edge(v, parent),
|
||
flipped = false;
|
||
|
||
if (!edge) {
|
||
edge = g.edge(parent, v);
|
||
flipped = true;
|
||
}
|
||
|
||
g.node(v).rank = g.node(parent).rank + (flipped ? edge.minlen : -edge.minlen);
|
||
});
|
||
}
|
||
|
||
/*
|
||
* Returns true if the edge is in the tree.
|
||
*/
|
||
function isTreeEdge(tree, u, v) {
|
||
return tree.hasEdge(u, v);
|
||
}
|
||
|
||
/*
|
||
* Returns true if the specified node is descendant of the root node per the
|
||
* assigned low and lim attributes in the tree.
|
||
*/
|
||
function isDescendant(tree, vLabel, rootLabel) {
|
||
return rootLabel.low <= vLabel.lim && vLabel.lim <= rootLabel.lim;
|
||
}
|
||
|
||
},{"../graphlib":60,"../lodash":63,"../util":82,"./feasible-tree":78,"./util":81}],81:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("../lodash");
|
||
|
||
module.exports = {
|
||
longestPath: longestPath,
|
||
slack: slack
|
||
};
|
||
|
||
/*
|
||
* Initializes ranks for the input graph using the longest path algorithm. This
|
||
* algorithm scales well and is fast in practice, it yields rather poor
|
||
* solutions. Nodes are pushed to the lowest layer possible, leaving the bottom
|
||
* ranks wide and leaving edges longer than necessary. However, due to its
|
||
* speed, this algorithm is good for getting an initial ranking that can be fed
|
||
* into other algorithms.
|
||
*
|
||
* This algorithm does not normalize layers because it will be used by other
|
||
* algorithms in most cases. If using this algorithm directly, be sure to
|
||
* run normalize at the end.
|
||
*
|
||
* Pre-conditions:
|
||
*
|
||
* 1. Input graph is a DAG.
|
||
* 2. Input graph node labels can be assigned properties.
|
||
*
|
||
* Post-conditions:
|
||
*
|
||
* 1. Each node will be assign an (unnormalized) "rank" property.
|
||
*/
|
||
function longestPath(g) {
|
||
var visited = {};
|
||
|
||
function dfs(v) {
|
||
var label = g.node(v);
|
||
if (_.has(visited, v)) {
|
||
return label.rank;
|
||
}
|
||
visited[v] = true;
|
||
|
||
var rank = _.min(_.map(g.outEdges(v), function(e) {
|
||
return dfs(e.w) - g.edge(e).minlen;
|
||
}));
|
||
|
||
if (rank === Number.POSITIVE_INFINITY) {
|
||
rank = 0;
|
||
}
|
||
|
||
return (label.rank = rank);
|
||
}
|
||
|
||
_.each(g.sources(), dfs);
|
||
}
|
||
|
||
/*
|
||
* Returns the amount of slack for the given edge. The slack is defined as the
|
||
* difference between the length of the edge and its minimum length.
|
||
*/
|
||
function slack(g, e) {
|
||
return g.node(e.w).rank - g.node(e.v).rank - g.edge(e).minlen;
|
||
}
|
||
|
||
},{"../lodash":63}],82:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _ = require("./lodash"),
|
||
Graph = require("./graphlib").Graph;
|
||
|
||
module.exports = {
|
||
addDummyNode: addDummyNode,
|
||
simplify: simplify,
|
||
asNonCompoundGraph: asNonCompoundGraph,
|
||
successorWeights: successorWeights,
|
||
predecessorWeights: predecessorWeights,
|
||
intersectRect: intersectRect,
|
||
buildLayerMatrix: buildLayerMatrix,
|
||
normalizeRanks: normalizeRanks,
|
||
removeEmptyRanks: removeEmptyRanks,
|
||
addBorderNode: addBorderNode,
|
||
maxRank: maxRank,
|
||
partition: partition,
|
||
time: time,
|
||
notime: notime
|
||
};
|
||
|
||
/*
|
||
* Adds a dummy node to the graph and return v.
|
||
*/
|
||
function addDummyNode(g, type, attrs, name) {
|
||
var v;
|
||
do {
|
||
v = _.uniqueId(name);
|
||
} while (g.hasNode(v));
|
||
|
||
attrs.dummy = type;
|
||
g.setNode(v, attrs);
|
||
return v;
|
||
}
|
||
|
||
/*
|
||
* Returns a new graph with only simple edges. Handles aggregation of data
|
||
* associated with multi-edges.
|
||
*/
|
||
function simplify(g) {
|
||
var simplified = new Graph().setGraph(g.graph());
|
||
_.each(g.nodes(), function(v) { simplified.setNode(v, g.node(v)); });
|
||
_.each(g.edges(), function(e) {
|
||
var simpleLabel = simplified.edge(e.v, e.w) || { weight: 0, minlen: 1 },
|
||
label = g.edge(e);
|
||
simplified.setEdge(e.v, e.w, {
|
||
weight: simpleLabel.weight + label.weight,
|
||
minlen: Math.max(simpleLabel.minlen, label.minlen)
|
||
});
|
||
});
|
||
return simplified;
|
||
}
|
||
|
||
function asNonCompoundGraph(g) {
|
||
var simplified = new Graph({ multigraph: g.isMultigraph() }).setGraph(g.graph());
|
||
_.each(g.nodes(), function(v) {
|
||
if (!g.children(v).length) {
|
||
simplified.setNode(v, g.node(v));
|
||
}
|
||
});
|
||
_.each(g.edges(), function(e) {
|
||
simplified.setEdge(e, g.edge(e));
|
||
});
|
||
return simplified;
|
||
}
|
||
|
||
function successorWeights(g) {
|
||
var weightMap = _.map(g.nodes(), function(v) {
|
||
var sucs = {};
|
||
_.each(g.outEdges(v), function(e) {
|
||
sucs[e.w] = (sucs[e.w] || 0) + g.edge(e).weight;
|
||
});
|
||
return sucs;
|
||
});
|
||
return _.zipObject(g.nodes(), weightMap);
|
||
}
|
||
|
||
function predecessorWeights(g) {
|
||
var weightMap = _.map(g.nodes(), function(v) {
|
||
var preds = {};
|
||
_.each(g.inEdges(v), function(e) {
|
||
preds[e.v] = (preds[e.v] || 0) + g.edge(e).weight;
|
||
});
|
||
return preds;
|
||
});
|
||
return _.zipObject(g.nodes(), weightMap);
|
||
}
|
||
|
||
/*
|
||
* Finds where a line starting at point ({x, y}) would intersect a rectangle
|
||
* ({x, y, width, height}) if it were pointing at the rectangle's center.
|
||
*/
|
||
function intersectRect(rect, point) {
|
||
var x = rect.x;
|
||
var y = rect.y;
|
||
|
||
// Rectangle intersection algorithm from:
|
||
// http://math.stackexchange.com/questions/108113/find-edge-between-two-boxes
|
||
var dx = point.x - x;
|
||
var dy = point.y - y;
|
||
var w = rect.width / 2;
|
||
var h = rect.height / 2;
|
||
|
||
if (!dx && !dy) {
|
||
throw new Error("Not possible to find intersection inside of the rectangle");
|
||
}
|
||
|
||
var sx, sy;
|
||
if (Math.abs(dy) * w > Math.abs(dx) * h) {
|
||
// Intersection is top or bottom of rect.
|
||
if (dy < 0) {
|
||
h = -h;
|
||
}
|
||
sx = h * dx / dy;
|
||
sy = h;
|
||
} else {
|
||
// Intersection is left or right of rect.
|
||
if (dx < 0) {
|
||
w = -w;
|
||
}
|
||
sx = w;
|
||
sy = w * dy / dx;
|
||
}
|
||
|
||
return { x: x + sx, y: y + sy };
|
||
}
|
||
|
||
/*
|
||
* Given a DAG with each node assigned "rank" and "order" properties, this
|
||
* function will produce a matrix with the ids of each node.
|
||
*/
|
||
function buildLayerMatrix(g) {
|
||
var layering = _.map(_.range(maxRank(g) + 1), function() { return []; });
|
||
_.each(g.nodes(), function(v) {
|
||
var node = g.node(v),
|
||
rank = node.rank;
|
||
if (!_.isUndefined(rank)) {
|
||
layering[rank][node.order] = v;
|
||
}
|
||
});
|
||
return layering;
|
||
}
|
||
|
||
/*
|
||
* Adjusts the ranks for all nodes in the graph such that all nodes v have
|
||
* rank(v) >= 0 and at least one node w has rank(w) = 0.
|
||
*/
|
||
function normalizeRanks(g) {
|
||
var min = _.min(_.map(g.nodes(), function(v) { return g.node(v).rank; }));
|
||
_.each(g.nodes(), function(v) {
|
||
var node = g.node(v);
|
||
if (_.has(node, "rank")) {
|
||
node.rank -= min;
|
||
}
|
||
});
|
||
}
|
||
|
||
function removeEmptyRanks(g) {
|
||
// Ranks may not start at 0, so we need to offset them
|
||
var offset = _.min(_.map(g.nodes(), function(v) { return g.node(v).rank; }));
|
||
|
||
var layers = [];
|
||
_.each(g.nodes(), function(v) {
|
||
var rank = g.node(v).rank - offset;
|
||
if (!layers[rank]) {
|
||
layers[rank] = [];
|
||
}
|
||
layers[rank].push(v);
|
||
});
|
||
|
||
var delta = 0,
|
||
nodeRankFactor = g.graph().nodeRankFactor;
|
||
_.each(layers, function(vs, i) {
|
||
if (_.isUndefined(vs) && i % nodeRankFactor !== 0) {
|
||
--delta;
|
||
} else if (delta) {
|
||
_.each(vs, function(v) { g.node(v).rank += delta; });
|
||
}
|
||
});
|
||
}
|
||
|
||
function addBorderNode(g, prefix, rank, order) {
|
||
var node = {
|
||
width: 0,
|
||
height: 0
|
||
};
|
||
if (arguments.length >= 4) {
|
||
node.rank = rank;
|
||
node.order = order;
|
||
}
|
||
return addDummyNode(g, "border", node, prefix);
|
||
}
|
||
|
||
function maxRank(g) {
|
||
return _.max(_.map(g.nodes(), function(v) {
|
||
var rank = g.node(v).rank;
|
||
if (!_.isUndefined(rank)) {
|
||
return rank;
|
||
}
|
||
}));
|
||
}
|
||
|
||
/*
|
||
* Partition a collection into two groups: `lhs` and `rhs`. If the supplied
|
||
* function returns true for an entry it goes into `lhs`. Otherwise it goes
|
||
* into `rhs.
|
||
*/
|
||
function partition(collection, fn) {
|
||
var result = { lhs: [], rhs: [] };
|
||
_.each(collection, function(value) {
|
||
if (fn(value)) {
|
||
result.lhs.push(value);
|
||
} else {
|
||
result.rhs.push(value);
|
||
}
|
||
});
|
||
return result;
|
||
}
|
||
|
||
/*
|
||
* Returns a new function that wraps `fn` with a timer. The wrapper logs the
|
||
* time it takes to execute the function.
|
||
*/
|
||
function time(name, fn) {
|
||
var start = _.now();
|
||
try {
|
||
return fn();
|
||
} finally {
|
||
console.log(name + " time: " + (_.now() - start) + "ms");
|
||
}
|
||
}
|
||
|
||
function notime(name, fn) {
|
||
return fn();
|
||
}
|
||
|
||
},{"./graphlib":60,"./lodash":63}],83:[function(require,module,exports){
|
||
module.exports = "0.7.4";
|
||
|
||
},{}],84:[function(require,module,exports){
|
||
module.exports=require(33)
|
||
},{"./lib":100,"./lib/alg":91,"./lib/json":101,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/index.js":33}],85:[function(require,module,exports){
|
||
module.exports=require(34)
|
||
},{"../lodash":102,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/alg/components.js":34}],86:[function(require,module,exports){
|
||
module.exports=require(35)
|
||
},{"../lodash":102,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/alg/dfs.js":35}],87:[function(require,module,exports){
|
||
module.exports=require(36)
|
||
},{"../lodash":102,"./dijkstra":88,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/alg/dijkstra-all.js":36}],88:[function(require,module,exports){
|
||
module.exports=require(37)
|
||
},{"../data/priority-queue":98,"../lodash":102,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/alg/dijkstra.js":37}],89:[function(require,module,exports){
|
||
module.exports=require(38)
|
||
},{"../lodash":102,"./tarjan":96,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/alg/find-cycles.js":38}],90:[function(require,module,exports){
|
||
module.exports=require(39)
|
||
},{"../lodash":102,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/alg/floyd-warshall.js":39}],91:[function(require,module,exports){
|
||
module.exports=require(40)
|
||
},{"./components":85,"./dijkstra":88,"./dijkstra-all":87,"./find-cycles":89,"./floyd-warshall":90,"./is-acyclic":92,"./postorder":93,"./preorder":94,"./prim":95,"./tarjan":96,"./topsort":97,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/alg/index.js":40}],92:[function(require,module,exports){
|
||
module.exports=require(41)
|
||
},{"./topsort":97,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/alg/is-acyclic.js":41}],93:[function(require,module,exports){
|
||
module.exports=require(42)
|
||
},{"./dfs":86,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/alg/postorder.js":42}],94:[function(require,module,exports){
|
||
module.exports=require(43)
|
||
},{"./dfs":86,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/alg/preorder.js":43}],95:[function(require,module,exports){
|
||
module.exports=require(44)
|
||
},{"../data/priority-queue":98,"../graph":99,"../lodash":102,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/alg/prim.js":44}],96:[function(require,module,exports){
|
||
module.exports=require(45)
|
||
},{"../lodash":102,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/alg/tarjan.js":45}],97:[function(require,module,exports){
|
||
module.exports=require(46)
|
||
},{"../lodash":102,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/alg/topsort.js":46}],98:[function(require,module,exports){
|
||
module.exports=require(47)
|
||
},{"../lodash":102,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/data/priority-queue.js":47}],99:[function(require,module,exports){
|
||
module.exports=require(48)
|
||
},{"./lodash":102,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/graph.js":48}],100:[function(require,module,exports){
|
||
module.exports=require(49)
|
||
},{"./graph":99,"./version":103,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/index.js":49}],101:[function(require,module,exports){
|
||
module.exports=require(50)
|
||
},{"./graph":99,"./lodash":102,"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/json.js":50}],102:[function(require,module,exports){
|
||
module.exports=require(51)
|
||
},{"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/lodash.js":51,"lodash":104}],103:[function(require,module,exports){
|
||
module.exports=require(52)
|
||
},{"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/graphlib/lib/version.js":52}],104:[function(require,module,exports){
|
||
module.exports=require(53)
|
||
},{"/Users/knuts/source/GitHub/mermaid/mermaid/node_modules/dagre-d3/node_modules/lodash/index.js":53}],105:[function(require,module,exports){
|
||
//! moment.js
|
||
//! version : 2.11.1
|
||
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
|
||
//! license : MIT
|
||
//! momentjs.com
|
||
|
||
;(function (global, factory) {
|
||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
||
typeof define === 'function' && define.amd ? define(factory) :
|
||
global.moment = factory()
|
||
}(this, function () { 'use strict';
|
||
|
||
var hookCallback;
|
||
|
||
function utils_hooks__hooks () {
|
||
return hookCallback.apply(null, arguments);
|
||
}
|
||
|
||
// This is done to register the method called with moment()
|
||
// without creating circular dependencies.
|
||
function setHookCallback (callback) {
|
||
hookCallback = callback;
|
||
}
|
||
|
||
function isArray(input) {
|
||
return Object.prototype.toString.call(input) === '[object Array]';
|
||
}
|
||
|
||
function isDate(input) {
|
||
return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
|
||
}
|
||
|
||
function map(arr, fn) {
|
||
var res = [], i;
|
||
for (i = 0; i < arr.length; ++i) {
|
||
res.push(fn(arr[i], i));
|
||
}
|
||
return res;
|
||
}
|
||
|
||
function hasOwnProp(a, b) {
|
||
return Object.prototype.hasOwnProperty.call(a, b);
|
||
}
|
||
|
||
function extend(a, b) {
|
||
for (var i in b) {
|
||
if (hasOwnProp(b, i)) {
|
||
a[i] = b[i];
|
||
}
|
||
}
|
||
|
||
if (hasOwnProp(b, 'toString')) {
|
||
a.toString = b.toString;
|
||
}
|
||
|
||
if (hasOwnProp(b, 'valueOf')) {
|
||
a.valueOf = b.valueOf;
|
||
}
|
||
|
||
return a;
|
||
}
|
||
|
||
function create_utc__createUTC (input, format, locale, strict) {
|
||
return createLocalOrUTC(input, format, locale, strict, true).utc();
|
||
}
|
||
|
||
function defaultParsingFlags() {
|
||
// We need to deep clone this object.
|
||
return {
|
||
empty : false,
|
||
unusedTokens : [],
|
||
unusedInput : [],
|
||
overflow : -2,
|
||
charsLeftOver : 0,
|
||
nullInput : false,
|
||
invalidMonth : null,
|
||
invalidFormat : false,
|
||
userInvalidated : false,
|
||
iso : false
|
||
};
|
||
}
|
||
|
||
function getParsingFlags(m) {
|
||
if (m._pf == null) {
|
||
m._pf = defaultParsingFlags();
|
||
}
|
||
return m._pf;
|
||
}
|
||
|
||
function valid__isValid(m) {
|
||
if (m._isValid == null) {
|
||
var flags = getParsingFlags(m);
|
||
m._isValid = !isNaN(m._d.getTime()) &&
|
||
flags.overflow < 0 &&
|
||
!flags.empty &&
|
||
!flags.invalidMonth &&
|
||
!flags.invalidWeekday &&
|
||
!flags.nullInput &&
|
||
!flags.invalidFormat &&
|
||
!flags.userInvalidated;
|
||
|
||
if (m._strict) {
|
||
m._isValid = m._isValid &&
|
||
flags.charsLeftOver === 0 &&
|
||
flags.unusedTokens.length === 0 &&
|
||
flags.bigHour === undefined;
|
||
}
|
||
}
|
||
return m._isValid;
|
||
}
|
||
|
||
function valid__createInvalid (flags) {
|
||
var m = create_utc__createUTC(NaN);
|
||
if (flags != null) {
|
||
extend(getParsingFlags(m), flags);
|
||
}
|
||
else {
|
||
getParsingFlags(m).userInvalidated = true;
|
||
}
|
||
|
||
return m;
|
||
}
|
||
|
||
function isUndefined(input) {
|
||
return input === void 0;
|
||
}
|
||
|
||
// Plugins that add properties should also add the key here (null value),
|
||
// so we can properly clone ourselves.
|
||
var momentProperties = utils_hooks__hooks.momentProperties = [];
|
||
|
||
function copyConfig(to, from) {
|
||
var i, prop, val;
|
||
|
||
if (!isUndefined(from._isAMomentObject)) {
|
||
to._isAMomentObject = from._isAMomentObject;
|
||
}
|
||
if (!isUndefined(from._i)) {
|
||
to._i = from._i;
|
||
}
|
||
if (!isUndefined(from._f)) {
|
||
to._f = from._f;
|
||
}
|
||
if (!isUndefined(from._l)) {
|
||
to._l = from._l;
|
||
}
|
||
if (!isUndefined(from._strict)) {
|
||
to._strict = from._strict;
|
||
}
|
||
if (!isUndefined(from._tzm)) {
|
||
to._tzm = from._tzm;
|
||
}
|
||
if (!isUndefined(from._isUTC)) {
|
||
to._isUTC = from._isUTC;
|
||
}
|
||
if (!isUndefined(from._offset)) {
|
||
to._offset = from._offset;
|
||
}
|
||
if (!isUndefined(from._pf)) {
|
||
to._pf = getParsingFlags(from);
|
||
}
|
||
if (!isUndefined(from._locale)) {
|
||
to._locale = from._locale;
|
||
}
|
||
|
||
if (momentProperties.length > 0) {
|
||
for (i in momentProperties) {
|
||
prop = momentProperties[i];
|
||
val = from[prop];
|
||
if (!isUndefined(val)) {
|
||
to[prop] = val;
|
||
}
|
||
}
|
||
}
|
||
|
||
return to;
|
||
}
|
||
|
||
var updateInProgress = false;
|
||
|
||
// Moment prototype object
|
||
function Moment(config) {
|
||
copyConfig(this, config);
|
||
this._d = new Date(config._d != null ? config._d.getTime() : NaN);
|
||
// Prevent infinite loop in case updateOffset creates new moment
|
||
// objects.
|
||
if (updateInProgress === false) {
|
||
updateInProgress = true;
|
||
utils_hooks__hooks.updateOffset(this);
|
||
updateInProgress = false;
|
||
}
|
||
}
|
||
|
||
function isMoment (obj) {
|
||
return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
|
||
}
|
||
|
||
function absFloor (number) {
|
||
if (number < 0) {
|
||
return Math.ceil(number);
|
||
} else {
|
||
return Math.floor(number);
|
||
}
|
||
}
|
||
|
||
function toInt(argumentForCoercion) {
|
||
var coercedNumber = +argumentForCoercion,
|
||
value = 0;
|
||
|
||
if (coercedNumber !== 0 && isFinite(coercedNumber)) {
|
||
value = absFloor(coercedNumber);
|
||
}
|
||
|
||
return value;
|
||
}
|
||
|
||
// compare two arrays, return the number of differences
|
||
function compareArrays(array1, array2, dontConvert) {
|
||
var len = Math.min(array1.length, array2.length),
|
||
lengthDiff = Math.abs(array1.length - array2.length),
|
||
diffs = 0,
|
||
i;
|
||
for (i = 0; i < len; i++) {
|
||
if ((dontConvert && array1[i] !== array2[i]) ||
|
||
(!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
|
||
diffs++;
|
||
}
|
||
}
|
||
return diffs + lengthDiff;
|
||
}
|
||
|
||
function Locale() {
|
||
}
|
||
|
||
// internal storage for locale config files
|
||
var locales = {};
|
||
var globalLocale;
|
||
|
||
function normalizeLocale(key) {
|
||
return key ? key.toLowerCase().replace('_', '-') : key;
|
||
}
|
||
|
||
// pick the locale from the array
|
||
// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
|
||
// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
|
||
function chooseLocale(names) {
|
||
var i = 0, j, next, locale, split;
|
||
|
||
while (i < names.length) {
|
||
split = normalizeLocale(names[i]).split('-');
|
||
j = split.length;
|
||
next = normalizeLocale(names[i + 1]);
|
||
next = next ? next.split('-') : null;
|
||
while (j > 0) {
|
||
locale = loadLocale(split.slice(0, j).join('-'));
|
||
if (locale) {
|
||
return locale;
|
||
}
|
||
if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
|
||
//the next array item is better than a shallower substring of this one
|
||
break;
|
||
}
|
||
j--;
|
||
}
|
||
i++;
|
||
}
|
||
return null;
|
||
}
|
||
|
||
function loadLocale(name) {
|
||
var oldLocale = null;
|
||
// TODO: Find a better way to register and load all the locales in Node
|
||
if (!locales[name] && (typeof module !== 'undefined') &&
|
||
module && module.exports) {
|
||
try {
|
||
oldLocale = globalLocale._abbr;
|
||
require('./locale/' + name);
|
||
// because defineLocale currently also sets the global locale, we
|
||
// want to undo that for lazy loaded locales
|
||
locale_locales__getSetGlobalLocale(oldLocale);
|
||
} catch (e) { }
|
||
}
|
||
return locales[name];
|
||
}
|
||
|
||
// This function will load locale and then set the global locale. If
|
||
// no arguments are passed in, it will simply return the current global
|
||
// locale key.
|
||
function locale_locales__getSetGlobalLocale (key, values) {
|
||
var data;
|
||
if (key) {
|
||
if (isUndefined(values)) {
|
||
data = locale_locales__getLocale(key);
|
||
}
|
||
else {
|
||
data = defineLocale(key, values);
|
||
}
|
||
|
||
if (data) {
|
||
// moment.duration._locale = moment._locale = data;
|
||
globalLocale = data;
|
||
}
|
||
}
|
||
|
||
return globalLocale._abbr;
|
||
}
|
||
|
||
function defineLocale (name, values) {
|
||
if (values !== null) {
|
||
values.abbr = name;
|
||
locales[name] = locales[name] || new Locale();
|
||
locales[name].set(values);
|
||
|
||
// backwards compat for now: also set the locale
|
||
locale_locales__getSetGlobalLocale(name);
|
||
|
||
return locales[name];
|
||
} else {
|
||
// useful for testing
|
||
delete locales[name];
|
||
return null;
|
||
}
|
||
}
|
||
|
||
// returns locale data
|
||
function locale_locales__getLocale (key) {
|
||
var locale;
|
||
|
||
if (key && key._locale && key._locale._abbr) {
|
||
key = key._locale._abbr;
|
||
}
|
||
|
||
if (!key) {
|
||
return globalLocale;
|
||
}
|
||
|
||
if (!isArray(key)) {
|
||
//short-circuit everything else
|
||
locale = loadLocale(key);
|
||
if (locale) {
|
||
return locale;
|
||
}
|
||
key = [key];
|
||
}
|
||
|
||
return chooseLocale(key);
|
||
}
|
||
|
||
var aliases = {};
|
||
|
||
function addUnitAlias (unit, shorthand) {
|
||
var lowerCase = unit.toLowerCase();
|
||
aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
|
||
}
|
||
|
||
function normalizeUnits(units) {
|
||
return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
|
||
}
|
||
|
||
function normalizeObjectUnits(inputObject) {
|
||
var normalizedInput = {},
|
||
normalizedProp,
|
||
prop;
|
||
|
||
for (prop in inputObject) {
|
||
if (hasOwnProp(inputObject, prop)) {
|
||
normalizedProp = normalizeUnits(prop);
|
||
if (normalizedProp) {
|
||
normalizedInput[normalizedProp] = inputObject[prop];
|
||
}
|
||
}
|
||
}
|
||
|
||
return normalizedInput;
|
||
}
|
||
|
||
function isFunction(input) {
|
||
return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
|
||
}
|
||
|
||
function makeGetSet (unit, keepTime) {
|
||
return function (value) {
|
||
if (value != null) {
|
||
get_set__set(this, unit, value);
|
||
utils_hooks__hooks.updateOffset(this, keepTime);
|
||
return this;
|
||
} else {
|
||
return get_set__get(this, unit);
|
||
}
|
||
};
|
||
}
|
||
|
||
function get_set__get (mom, unit) {
|
||
return mom.isValid() ?
|
||
mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
|
||
}
|
||
|
||
function get_set__set (mom, unit, value) {
|
||
if (mom.isValid()) {
|
||
mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
|
||
}
|
||
}
|
||
|
||
// MOMENTS
|
||
|
||
function getSet (units, value) {
|
||
var unit;
|
||
if (typeof units === 'object') {
|
||
for (unit in units) {
|
||
this.set(unit, units[unit]);
|
||
}
|
||
} else {
|
||
units = normalizeUnits(units);
|
||
if (isFunction(this[units])) {
|
||
return this[units](value);
|
||
}
|
||
}
|
||
return this;
|
||
}
|
||
|
||
function zeroFill(number, targetLength, forceSign) {
|
||
var absNumber = '' + Math.abs(number),
|
||
zerosToFill = targetLength - absNumber.length,
|
||
sign = number >= 0;
|
||
return (sign ? (forceSign ? '+' : '') : '-') +
|
||
Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
|
||
}
|
||
|
||
var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
|
||
|
||
var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
|
||
|
||
var formatFunctions = {};
|
||
|
||
var formatTokenFunctions = {};
|
||
|
||
// token: 'M'
|
||
// padded: ['MM', 2]
|
||
// ordinal: 'Mo'
|
||
// callback: function () { this.month() + 1 }
|
||
function addFormatToken (token, padded, ordinal, callback) {
|
||
var func = callback;
|
||
if (typeof callback === 'string') {
|
||
func = function () {
|
||
return this[callback]();
|
||
};
|
||
}
|
||
if (token) {
|
||
formatTokenFunctions[token] = func;
|
||
}
|
||
if (padded) {
|
||
formatTokenFunctions[padded[0]] = function () {
|
||
return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
|
||
};
|
||
}
|
||
if (ordinal) {
|
||
formatTokenFunctions[ordinal] = function () {
|
||
return this.localeData().ordinal(func.apply(this, arguments), token);
|
||
};
|
||
}
|
||
}
|
||
|
||
function removeFormattingTokens(input) {
|
||
if (input.match(/\[[\s\S]/)) {
|
||
return input.replace(/^\[|\]$/g, '');
|
||
}
|
||
return input.replace(/\\/g, '');
|
||
}
|
||
|
||
function makeFormatFunction(format) {
|
||
var array = format.match(formattingTokens), i, length;
|
||
|
||
for (i = 0, length = array.length; i < length; i++) {
|
||
if (formatTokenFunctions[array[i]]) {
|
||
array[i] = formatTokenFunctions[array[i]];
|
||
} else {
|
||
array[i] = removeFormattingTokens(array[i]);
|
||
}
|
||
}
|
||
|
||
return function (mom) {
|
||
var output = '';
|
||
for (i = 0; i < length; i++) {
|
||
output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
|
||
}
|
||
return output;
|
||
};
|
||
}
|
||
|
||
// format date using native date object
|
||
function formatMoment(m, format) {
|
||
if (!m.isValid()) {
|
||
return m.localeData().invalidDate();
|
||
}
|
||
|
||
format = expandFormat(format, m.localeData());
|
||
formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
|
||
|
||
return formatFunctions[format](m);
|
||
}
|
||
|
||
function expandFormat(format, locale) {
|
||
var i = 5;
|
||
|
||
function replaceLongDateFormatTokens(input) {
|
||
return locale.longDateFormat(input) || input;
|
||
}
|
||
|
||
localFormattingTokens.lastIndex = 0;
|
||
while (i >= 0 && localFormattingTokens.test(format)) {
|
||
format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
|
||
localFormattingTokens.lastIndex = 0;
|
||
i -= 1;
|
||
}
|
||
|
||
return format;
|
||
}
|
||
|
||
var match1 = /\d/; // 0 - 9
|
||
var match2 = /\d\d/; // 00 - 99
|
||
var match3 = /\d{3}/; // 000 - 999
|
||
var match4 = /\d{4}/; // 0000 - 9999
|
||
var match6 = /[+-]?\d{6}/; // -999999 - 999999
|
||
var match1to2 = /\d\d?/; // 0 - 99
|
||
var match3to4 = /\d\d\d\d?/; // 999 - 9999
|
||
var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999
|
||
var match1to3 = /\d{1,3}/; // 0 - 999
|
||
var match1to4 = /\d{1,4}/; // 0 - 9999
|
||
var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999
|
||
|
||
var matchUnsigned = /\d+/; // 0 - inf
|
||
var matchSigned = /[+-]?\d+/; // -inf - inf
|
||
|
||
var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
|
||
var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
|
||
|
||
var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
|
||
|
||
// any word (or two) characters or numbers including two/three word month in arabic.
|
||
// includes scottish gaelic two word and hyphenated months
|
||
var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i;
|
||
|
||
|
||
var regexes = {};
|
||
|
||
function addRegexToken (token, regex, strictRegex) {
|
||
regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
|
||
return (isStrict && strictRegex) ? strictRegex : regex;
|
||
};
|
||
}
|
||
|
||
function getParseRegexForToken (token, config) {
|
||
if (!hasOwnProp(regexes, token)) {
|
||
return new RegExp(unescapeFormat(token));
|
||
}
|
||
|
||
return regexes[token](config._strict, config._locale);
|
||
}
|
||
|
||
// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
|
||
function unescapeFormat(s) {
|
||
return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
|
||
return p1 || p2 || p3 || p4;
|
||
}));
|
||
}
|
||
|
||
function regexEscape(s) {
|
||
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
|
||
}
|
||
|
||
var tokens = {};
|
||
|
||
function addParseToken (token, callback) {
|
||
var i, func = callback;
|
||
if (typeof token === 'string') {
|
||
token = [token];
|
||
}
|
||
if (typeof callback === 'number') {
|
||
func = function (input, array) {
|
||
array[callback] = toInt(input);
|
||
};
|
||
}
|
||
for (i = 0; i < token.length; i++) {
|
||
tokens[token[i]] = func;
|
||
}
|
||
}
|
||
|
||
function addWeekParseToken (token, callback) {
|
||
addParseToken(token, function (input, array, config, token) {
|
||
config._w = config._w || {};
|
||
callback(input, config._w, config, token);
|
||
});
|
||
}
|
||
|
||
function addTimeToArrayFromToken(token, input, config) {
|
||
if (input != null && hasOwnProp(tokens, token)) {
|
||
tokens[token](input, config._a, config, token);
|
||
}
|
||
}
|
||
|
||
var YEAR = 0;
|
||
var MONTH = 1;
|
||
var DATE = 2;
|
||
var HOUR = 3;
|
||
var MINUTE = 4;
|
||
var SECOND = 5;
|
||
var MILLISECOND = 6;
|
||
var WEEK = 7;
|
||
var WEEKDAY = 8;
|
||
|
||
function daysInMonth(year, month) {
|
||
return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
|
||
}
|
||
|
||
// FORMATTING
|
||
|
||
addFormatToken('M', ['MM', 2], 'Mo', function () {
|
||
return this.month() + 1;
|
||
});
|
||
|
||
addFormatToken('MMM', 0, 0, function (format) {
|
||
return this.localeData().monthsShort(this, format);
|
||
});
|
||
|
||
addFormatToken('MMMM', 0, 0, function (format) {
|
||
return this.localeData().months(this, format);
|
||
});
|
||
|
||
// ALIASES
|
||
|
||
addUnitAlias('month', 'M');
|
||
|
||
// PARSING
|
||
|
||
addRegexToken('M', match1to2);
|
||
addRegexToken('MM', match1to2, match2);
|
||
addRegexToken('MMM', function (isStrict, locale) {
|
||
return locale.monthsShortRegex(isStrict);
|
||
});
|
||
addRegexToken('MMMM', function (isStrict, locale) {
|
||
return locale.monthsRegex(isStrict);
|
||
});
|
||
|
||
addParseToken(['M', 'MM'], function (input, array) {
|
||
array[MONTH] = toInt(input) - 1;
|
||
});
|
||
|
||
addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
|
||
var month = config._locale.monthsParse(input, token, config._strict);
|
||
// if we didn't find a month name, mark the date as invalid.
|
||
if (month != null) {
|
||
array[MONTH] = month;
|
||
} else {
|
||
getParsingFlags(config).invalidMonth = input;
|
||
}
|
||
});
|
||
|
||
// LOCALES
|
||
|
||
var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/;
|
||
var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
|
||
function localeMonths (m, format) {
|
||
return isArray(this._months) ? this._months[m.month()] :
|
||
this._months[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
|
||
}
|
||
|
||
var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
|
||
function localeMonthsShort (m, format) {
|
||
return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
|
||
this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
|
||
}
|
||
|
||
function localeMonthsParse (monthName, format, strict) {
|
||
var i, mom, regex;
|
||
|
||
if (!this._monthsParse) {
|
||
this._monthsParse = [];
|
||
this._longMonthsParse = [];
|
||
this._shortMonthsParse = [];
|
||
}
|
||
|
||
for (i = 0; i < 12; i++) {
|
||
// make the regex if we don't have it already
|
||
mom = create_utc__createUTC([2000, i]);
|
||
if (strict && !this._longMonthsParse[i]) {
|
||
this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
|
||
this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
|
||
}
|
||
if (!strict && !this._monthsParse[i]) {
|
||
regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
|
||
this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
|
||
}
|
||
// test the regex
|
||
if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
|
||
return i;
|
||
} else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
|
||
return i;
|
||
} else if (!strict && this._monthsParse[i].test(monthName)) {
|
||
return i;
|
||
}
|
||
}
|
||
}
|
||
|
||
// MOMENTS
|
||
|
||
function setMonth (mom, value) {
|
||
var dayOfMonth;
|
||
|
||
if (!mom.isValid()) {
|
||
// No op
|
||
return mom;
|
||
}
|
||
|
||
// TODO: Move this out of here!
|
||
if (typeof value === 'string') {
|
||
value = mom.localeData().monthsParse(value);
|
||
// TODO: Another silent failure?
|
||
if (typeof value !== 'number') {
|
||
return mom;
|
||
}
|
||
}
|
||
|
||
dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
|
||
mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
|
||
return mom;
|
||
}
|
||
|
||
function getSetMonth (value) {
|
||
if (value != null) {
|
||
setMonth(this, value);
|
||
utils_hooks__hooks.updateOffset(this, true);
|
||
return this;
|
||
} else {
|
||
return get_set__get(this, 'Month');
|
||
}
|
||
}
|
||
|
||
function getDaysInMonth () {
|
||
return daysInMonth(this.year(), this.month());
|
||
}
|
||
|
||
var defaultMonthsShortRegex = matchWord;
|
||
function monthsShortRegex (isStrict) {
|
||
if (this._monthsParseExact) {
|
||
if (!hasOwnProp(this, '_monthsRegex')) {
|
||
computeMonthsParse.call(this);
|
||
}
|
||
if (isStrict) {
|
||
return this._monthsShortStrictRegex;
|
||
} else {
|
||
return this._monthsShortRegex;
|
||
}
|
||
} else {
|
||
return this._monthsShortStrictRegex && isStrict ?
|
||
this._monthsShortStrictRegex : this._monthsShortRegex;
|
||
}
|
||
}
|
||
|
||
var defaultMonthsRegex = matchWord;
|
||
function monthsRegex (isStrict) {
|
||
if (this._monthsParseExact) {
|
||
if (!hasOwnProp(this, '_monthsRegex')) {
|
||
computeMonthsParse.call(this);
|
||
}
|
||
if (isStrict) {
|
||
return this._monthsStrictRegex;
|
||
} else {
|
||
return this._monthsRegex;
|
||
}
|
||
} else {
|
||
return this._monthsStrictRegex && isStrict ?
|
||
this._monthsStrictRegex : this._monthsRegex;
|
||
}
|
||
}
|
||
|
||
function computeMonthsParse () {
|
||
function cmpLenRev(a, b) {
|
||
return b.length - a.length;
|
||
}
|
||
|
||
var shortPieces = [], longPieces = [], mixedPieces = [],
|
||
i, mom;
|
||
for (i = 0; i < 12; i++) {
|
||
// make the regex if we don't have it already
|
||
mom = create_utc__createUTC([2000, i]);
|
||
shortPieces.push(this.monthsShort(mom, ''));
|
||
longPieces.push(this.months(mom, ''));
|
||
mixedPieces.push(this.months(mom, ''));
|
||
mixedPieces.push(this.monthsShort(mom, ''));
|
||
}
|
||
// Sorting makes sure if one month (or abbr) is a prefix of another it
|
||
// will match the longer piece.
|
||
shortPieces.sort(cmpLenRev);
|
||
longPieces.sort(cmpLenRev);
|
||
mixedPieces.sort(cmpLenRev);
|
||
for (i = 0; i < 12; i++) {
|
||
shortPieces[i] = regexEscape(shortPieces[i]);
|
||
longPieces[i] = regexEscape(longPieces[i]);
|
||
mixedPieces[i] = regexEscape(mixedPieces[i]);
|
||
}
|
||
|
||
this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
|
||
this._monthsShortRegex = this._monthsRegex;
|
||
this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')$', 'i');
|
||
this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')$', 'i');
|
||
}
|
||
|
||
function checkOverflow (m) {
|
||
var overflow;
|
||
var a = m._a;
|
||
|
||
if (a && getParsingFlags(m).overflow === -2) {
|
||
overflow =
|
||
a[MONTH] < 0 || a[MONTH] > 11 ? MONTH :
|
||
a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
|
||
a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
|
||
a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE :
|
||
a[SECOND] < 0 || a[SECOND] > 59 ? SECOND :
|
||
a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
|
||
-1;
|
||
|
||
if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
|
||
overflow = DATE;
|
||
}
|
||
if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
|
||
overflow = WEEK;
|
||
}
|
||
if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
|
||
overflow = WEEKDAY;
|
||
}
|
||
|
||
getParsingFlags(m).overflow = overflow;
|
||
}
|
||
|
||
return m;
|
||
}
|
||
|
||
function warn(msg) {
|
||
if (utils_hooks__hooks.suppressDeprecationWarnings === false &&
|
||
(typeof console !== 'undefined') && console.warn) {
|
||
console.warn('Deprecation warning: ' + msg);
|
||
}
|
||
}
|
||
|
||
function deprecate(msg, fn) {
|
||
var firstTime = true;
|
||
|
||
return extend(function () {
|
||
if (firstTime) {
|
||
warn(msg + '\nArguments: ' + Array.prototype.slice.call(arguments).join(', ') + '\n' + (new Error()).stack);
|
||
firstTime = false;
|
||
}
|
||
return fn.apply(this, arguments);
|
||
}, fn);
|
||
}
|
||
|
||
var deprecations = {};
|
||
|
||
function deprecateSimple(name, msg) {
|
||
if (!deprecations[name]) {
|
||
warn(msg);
|
||
deprecations[name] = true;
|
||
}
|
||
}
|
||
|
||
utils_hooks__hooks.suppressDeprecationWarnings = false;
|
||
|
||
// iso 8601 regex
|
||
// 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
|
||
var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/;
|
||
var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/;
|
||
|
||
var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
|
||
|
||
var isoDates = [
|
||
['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
|
||
['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
|
||
['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
|
||
['GGGG-[W]WW', /\d{4}-W\d\d/, false],
|
||
['YYYY-DDD', /\d{4}-\d{3}/],
|
||
['YYYY-MM', /\d{4}-\d\d/, false],
|
||
['YYYYYYMMDD', /[+-]\d{10}/],
|
||
['YYYYMMDD', /\d{8}/],
|
||
// YYYYMM is NOT allowed by the standard
|
||
['GGGG[W]WWE', /\d{4}W\d{3}/],
|
||
['GGGG[W]WW', /\d{4}W\d{2}/, false],
|
||
['YYYYDDD', /\d{7}/]
|
||
];
|
||
|
||
// iso time formats and regexes
|
||
var isoTimes = [
|
||
['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
|
||
['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
|
||
['HH:mm:ss', /\d\d:\d\d:\d\d/],
|
||
['HH:mm', /\d\d:\d\d/],
|
||
['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
|
||
['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
|
||
['HHmmss', /\d\d\d\d\d\d/],
|
||
['HHmm', /\d\d\d\d/],
|
||
['HH', /\d\d/]
|
||
];
|
||
|
||
var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
|
||
|
||
// date from iso format
|
||
function configFromISO(config) {
|
||
var i, l,
|
||
string = config._i,
|
||
match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
|
||
allowTime, dateFormat, timeFormat, tzFormat;
|
||
|
||
if (match) {
|
||
getParsingFlags(config).iso = true;
|
||
|
||
for (i = 0, l = isoDates.length; i < l; i++) {
|
||
if (isoDates[i][1].exec(match[1])) {
|
||
dateFormat = isoDates[i][0];
|
||
allowTime = isoDates[i][2] !== false;
|
||
break;
|
||
}
|
||
}
|
||
if (dateFormat == null) {
|
||
config._isValid = false;
|
||
return;
|
||
}
|
||
if (match[3]) {
|
||
for (i = 0, l = isoTimes.length; i < l; i++) {
|
||
if (isoTimes[i][1].exec(match[3])) {
|
||
// match[2] should be 'T' or space
|
||
timeFormat = (match[2] || ' ') + isoTimes[i][0];
|
||
break;
|
||
}
|
||
}
|
||
if (timeFormat == null) {
|
||
config._isValid = false;
|
||
return;
|
||
}
|
||
}
|
||
if (!allowTime && timeFormat != null) {
|
||
config._isValid = false;
|
||
return;
|
||
}
|
||
if (match[4]) {
|
||
if (tzRegex.exec(match[4])) {
|
||
tzFormat = 'Z';
|
||
} else {
|
||
config._isValid = false;
|
||
return;
|
||
}
|
||
}
|
||
config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
|
||
configFromStringAndFormat(config);
|
||
} else {
|
||
config._isValid = false;
|
||
}
|
||
}
|
||
|
||
// date from iso format or fallback
|
||
function configFromString(config) {
|
||
var matched = aspNetJsonRegex.exec(config._i);
|
||
|
||
if (matched !== null) {
|
||
config._d = new Date(+matched[1]);
|
||
return;
|
||
}
|
||
|
||
configFromISO(config);
|
||
if (config._isValid === false) {
|
||
delete config._isValid;
|
||
utils_hooks__hooks.createFromInputFallback(config);
|
||
}
|
||
}
|
||
|
||
utils_hooks__hooks.createFromInputFallback = deprecate(
|
||
'moment construction falls back to js Date. This is ' +
|
||
'discouraged and will be removed in upcoming major ' +
|
||
'release. Please refer to ' +
|
||
'https://github.com/moment/moment/issues/1407 for more info.',
|
||
function (config) {
|
||
config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
|
||
}
|
||
);
|
||
|
||
function createDate (y, m, d, h, M, s, ms) {
|
||
//can't just apply() to create a date:
|
||
//http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
|
||
var date = new Date(y, m, d, h, M, s, ms);
|
||
|
||
//the date constructor remaps years 0-99 to 1900-1999
|
||
if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
|
||
date.setFullYear(y);
|
||
}
|
||
return date;
|
||
}
|
||
|
||
function createUTCDate (y) {
|
||
var date = new Date(Date.UTC.apply(null, arguments));
|
||
|
||
//the Date.UTC function remaps years 0-99 to 1900-1999
|
||
if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
|
||
date.setUTCFullYear(y);
|
||
}
|
||
return date;
|
||
}
|
||
|
||
// FORMATTING
|
||
|
||
addFormatToken('Y', 0, 0, function () {
|
||
var y = this.year();
|
||
return y <= 9999 ? '' + y : '+' + y;
|
||
});
|
||
|
||
addFormatToken(0, ['YY', 2], 0, function () {
|
||
return this.year() % 100;
|
||
});
|
||
|
||
addFormatToken(0, ['YYYY', 4], 0, 'year');
|
||
addFormatToken(0, ['YYYYY', 5], 0, 'year');
|
||
addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
|
||
|
||
// ALIASES
|
||
|
||
addUnitAlias('year', 'y');
|
||
|
||
// PARSING
|
||
|
||
addRegexToken('Y', matchSigned);
|
||
addRegexToken('YY', match1to2, match2);
|
||
addRegexToken('YYYY', match1to4, match4);
|
||
addRegexToken('YYYYY', match1to6, match6);
|
||
addRegexToken('YYYYYY', match1to6, match6);
|
||
|
||
addParseToken(['YYYYY', 'YYYYYY'], YEAR);
|
||
addParseToken('YYYY', function (input, array) {
|
||
array[YEAR] = input.length === 2 ? utils_hooks__hooks.parseTwoDigitYear(input) : toInt(input);
|
||
});
|
||
addParseToken('YY', function (input, array) {
|
||
array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input);
|
||
});
|
||
addParseToken('Y', function (input, array) {
|
||
array[YEAR] = parseInt(input, 10);
|
||
});
|
||
|
||
// HELPERS
|
||
|
||
function daysInYear(year) {
|
||
return isLeapYear(year) ? 366 : 365;
|
||
}
|
||
|
||
function isLeapYear(year) {
|
||
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
||
}
|
||
|
||
// HOOKS
|
||
|
||
utils_hooks__hooks.parseTwoDigitYear = function (input) {
|
||
return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
|
||
};
|
||
|
||
// MOMENTS
|
||
|
||
var getSetYear = makeGetSet('FullYear', false);
|
||
|
||
function getIsLeapYear () {
|
||
return isLeapYear(this.year());
|
||
}
|
||
|
||
// start-of-first-week - start-of-year
|
||
function firstWeekOffset(year, dow, doy) {
|
||
var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
|
||
fwd = 7 + dow - doy,
|
||
// first-week day local weekday -- which local weekday is fwd
|
||
fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
|
||
|
||
return -fwdlw + fwd - 1;
|
||
}
|
||
|
||
//http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
|
||
function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
|
||
var localWeekday = (7 + weekday - dow) % 7,
|
||
weekOffset = firstWeekOffset(year, dow, doy),
|
||
dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
|
||
resYear, resDayOfYear;
|
||
|
||
if (dayOfYear <= 0) {
|
||
resYear = year - 1;
|
||
resDayOfYear = daysInYear(resYear) + dayOfYear;
|
||
} else if (dayOfYear > daysInYear(year)) {
|
||
resYear = year + 1;
|
||
resDayOfYear = dayOfYear - daysInYear(year);
|
||
} else {
|
||
resYear = year;
|
||
resDayOfYear = dayOfYear;
|
||
}
|
||
|
||
return {
|
||
year: resYear,
|
||
dayOfYear: resDayOfYear
|
||
};
|
||
}
|
||
|
||
function weekOfYear(mom, dow, doy) {
|
||
var weekOffset = firstWeekOffset(mom.year(), dow, doy),
|
||
week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
|
||
resWeek, resYear;
|
||
|
||
if (week < 1) {
|
||
resYear = mom.year() - 1;
|
||
resWeek = week + weeksInYear(resYear, dow, doy);
|
||
} else if (week > weeksInYear(mom.year(), dow, doy)) {
|
||
resWeek = week - weeksInYear(mom.year(), dow, doy);
|
||
resYear = mom.year() + 1;
|
||
} else {
|
||
resYear = mom.year();
|
||
resWeek = week;
|
||
}
|
||
|
||
return {
|
||
week: resWeek,
|
||
year: resYear
|
||
};
|
||
}
|
||
|
||
function weeksInYear(year, dow, doy) {
|
||
var weekOffset = firstWeekOffset(year, dow, doy),
|
||
weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
|
||
return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
|
||
}
|
||
|
||
// Pick the first defined of two or three arguments.
|
||
function defaults(a, b, c) {
|
||
if (a != null) {
|
||
return a;
|
||
}
|
||
if (b != null) {
|
||
return b;
|
||
}
|
||
return c;
|
||
}
|
||
|
||
function currentDateArray(config) {
|
||
// hooks is actually the exported moment object
|
||
var nowValue = new Date(utils_hooks__hooks.now());
|
||
if (config._useUTC) {
|
||
return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
|
||
}
|
||
return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
|
||
}
|
||
|
||
// convert an array to a date.
|
||
// the array should mirror the parameters below
|
||
// note: all values past the year are optional and will default to the lowest possible value.
|
||
// [year, month, day , hour, minute, second, millisecond]
|
||
function configFromArray (config) {
|
||
var i, date, input = [], currentDate, yearToUse;
|
||
|
||
if (config._d) {
|
||
return;
|
||
}
|
||
|
||
currentDate = currentDateArray(config);
|
||
|
||
//compute day of the year from weeks and weekdays
|
||
if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
|
||
dayOfYearFromWeekInfo(config);
|
||
}
|
||
|
||
//if the day of the year is set, figure out what it is
|
||
if (config._dayOfYear) {
|
||
yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
|
||
|
||
if (config._dayOfYear > daysInYear(yearToUse)) {
|
||
getParsingFlags(config)._overflowDayOfYear = true;
|
||
}
|
||
|
||
date = createUTCDate(yearToUse, 0, config._dayOfYear);
|
||
config._a[MONTH] = date.getUTCMonth();
|
||
config._a[DATE] = date.getUTCDate();
|
||
}
|
||
|
||
// Default to current date.
|
||
// * if no year, month, day of month are given, default to today
|
||
// * if day of month is given, default month and year
|
||
// * if month is given, default only year
|
||
// * if year is given, don't default anything
|
||
for (i = 0; i < 3 && config._a[i] == null; ++i) {
|
||
config._a[i] = input[i] = currentDate[i];
|
||
}
|
||
|
||
// Zero out whatever was not defaulted, including time
|
||
for (; i < 7; i++) {
|
||
config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
|
||
}
|
||
|
||
// Check for 24:00:00.000
|
||
if (config._a[HOUR] === 24 &&
|
||
config._a[MINUTE] === 0 &&
|
||
config._a[SECOND] === 0 &&
|
||
config._a[MILLISECOND] === 0) {
|
||
config._nextDay = true;
|
||
config._a[HOUR] = 0;
|
||
}
|
||
|
||
config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
|
||
// Apply timezone offset from input. The actual utcOffset can be changed
|
||
// with parseZone.
|
||
if (config._tzm != null) {
|
||
config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
|
||
}
|
||
|
||
if (config._nextDay) {
|
||
config._a[HOUR] = 24;
|
||
}
|
||
}
|
||
|
||
function dayOfYearFromWeekInfo(config) {
|
||
var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
|
||
|
||
w = config._w;
|
||
if (w.GG != null || w.W != null || w.E != null) {
|
||
dow = 1;
|
||
doy = 4;
|
||
|
||
// TODO: We need to take the current isoWeekYear, but that depends on
|
||
// how we interpret now (local, utc, fixed offset). So create
|
||
// a now version of current config (take local/utc/offset flags, and
|
||
// create now).
|
||
weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year);
|
||
week = defaults(w.W, 1);
|
||
weekday = defaults(w.E, 1);
|
||
if (weekday < 1 || weekday > 7) {
|
||
weekdayOverflow = true;
|
||
}
|
||
} else {
|
||
dow = config._locale._week.dow;
|
||
doy = config._locale._week.doy;
|
||
|
||
weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year);
|
||
week = defaults(w.w, 1);
|
||
|
||
if (w.d != null) {
|
||
// weekday -- low day numbers are considered next week
|
||
weekday = w.d;
|
||
if (weekday < 0 || weekday > 6) {
|
||
weekdayOverflow = true;
|
||
}
|
||
} else if (w.e != null) {
|
||
// local weekday -- counting starts from begining of week
|
||
weekday = w.e + dow;
|
||
if (w.e < 0 || w.e > 6) {
|
||
weekdayOverflow = true;
|
||
}
|
||
} else {
|
||
// default to begining of week
|
||
weekday = dow;
|
||
}
|
||
}
|
||
if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
|
||
getParsingFlags(config)._overflowWeeks = true;
|
||
} else if (weekdayOverflow != null) {
|
||
getParsingFlags(config)._overflowWeekday = true;
|
||
} else {
|
||
temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
|
||
config._a[YEAR] = temp.year;
|
||
config._dayOfYear = temp.dayOfYear;
|
||
}
|
||
}
|
||
|
||
// constant that refers to the ISO standard
|
||
utils_hooks__hooks.ISO_8601 = function () {};
|
||
|
||
// date from string and format string
|
||
function configFromStringAndFormat(config) {
|
||
// TODO: Move this to another part of the creation flow to prevent circular deps
|
||
if (config._f === utils_hooks__hooks.ISO_8601) {
|
||
configFromISO(config);
|
||
return;
|
||
}
|
||
|
||
config._a = [];
|
||
getParsingFlags(config).empty = true;
|
||
|
||
// This array is used to make a Date, either with `new Date` or `Date.UTC`
|
||
var string = '' + config._i,
|
||
i, parsedInput, tokens, token, skipped,
|
||
stringLength = string.length,
|
||
totalParsedInputLength = 0;
|
||
|
||
tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
|
||
|
||
for (i = 0; i < tokens.length; i++) {
|
||
token = tokens[i];
|
||
parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
|
||
// console.log('token', token, 'parsedInput', parsedInput,
|
||
// 'regex', getParseRegexForToken(token, config));
|
||
if (parsedInput) {
|
||
skipped = string.substr(0, string.indexOf(parsedInput));
|
||
if (skipped.length > 0) {
|
||
getParsingFlags(config).unusedInput.push(skipped);
|
||
}
|
||
string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
|
||
totalParsedInputLength += parsedInput.length;
|
||
}
|
||
// don't parse if it's not a known token
|
||
if (formatTokenFunctions[token]) {
|
||
if (parsedInput) {
|
||
getParsingFlags(config).empty = false;
|
||
}
|
||
else {
|
||
getParsingFlags(config).unusedTokens.push(token);
|
||
}
|
||
addTimeToArrayFromToken(token, parsedInput, config);
|
||
}
|
||
else if (config._strict && !parsedInput) {
|
||
getParsingFlags(config).unusedTokens.push(token);
|
||
}
|
||
}
|
||
|
||
// add remaining unparsed input length to the string
|
||
getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
|
||
if (string.length > 0) {
|
||
getParsingFlags(config).unusedInput.push(string);
|
||
}
|
||
|
||
// clear _12h flag if hour is <= 12
|
||
if (getParsingFlags(config).bigHour === true &&
|
||
config._a[HOUR] <= 12 &&
|
||
config._a[HOUR] > 0) {
|
||
getParsingFlags(config).bigHour = undefined;
|
||
}
|
||
// handle meridiem
|
||
config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
|
||
|
||
configFromArray(config);
|
||
checkOverflow(config);
|
||
}
|
||
|
||
|
||
function meridiemFixWrap (locale, hour, meridiem) {
|
||
var isPm;
|
||
|
||
if (meridiem == null) {
|
||
// nothing to do
|
||
return hour;
|
||
}
|
||
if (locale.meridiemHour != null) {
|
||
return locale.meridiemHour(hour, meridiem);
|
||
} else if (locale.isPM != null) {
|
||
// Fallback
|
||
isPm = locale.isPM(meridiem);
|
||
if (isPm && hour < 12) {
|
||
hour += 12;
|
||
}
|
||
if (!isPm && hour === 12) {
|
||
hour = 0;
|
||
}
|
||
return hour;
|
||
} else {
|
||
// this is not supposed to happen
|
||
return hour;
|
||
}
|
||
}
|
||
|
||
// date from string and array of format strings
|
||
function configFromStringAndArray(config) {
|
||
var tempConfig,
|
||
bestMoment,
|
||
|
||
scoreToBeat,
|
||
i,
|
||
currentScore;
|
||
|
||
if (config._f.length === 0) {
|
||
getParsingFlags(config).invalidFormat = true;
|
||
config._d = new Date(NaN);
|
||
return;
|
||
}
|
||
|
||
for (i = 0; i < config._f.length; i++) {
|
||
currentScore = 0;
|
||
tempConfig = copyConfig({}, config);
|
||
if (config._useUTC != null) {
|
||
tempConfig._useUTC = config._useUTC;
|
||
}
|
||
tempConfig._f = config._f[i];
|
||
configFromStringAndFormat(tempConfig);
|
||
|
||
if (!valid__isValid(tempConfig)) {
|
||
continue;
|
||
}
|
||
|
||
// if there is any input that was not parsed add a penalty for that format
|
||
currentScore += getParsingFlags(tempConfig).charsLeftOver;
|
||
|
||
//or tokens
|
||
currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
|
||
|
||
getParsingFlags(tempConfig).score = currentScore;
|
||
|
||
if (scoreToBeat == null || currentScore < scoreToBeat) {
|
||
scoreToBeat = currentScore;
|
||
bestMoment = tempConfig;
|
||
}
|
||
}
|
||
|
||
extend(config, bestMoment || tempConfig);
|
||
}
|
||
|
||
function configFromObject(config) {
|
||
if (config._d) {
|
||
return;
|
||
}
|
||
|
||
var i = normalizeObjectUnits(config._i);
|
||
config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
|
||
return obj && parseInt(obj, 10);
|
||
});
|
||
|
||
configFromArray(config);
|
||
}
|
||
|
||
function createFromConfig (config) {
|
||
var res = new Moment(checkOverflow(prepareConfig(config)));
|
||
if (res._nextDay) {
|
||
// Adding is smart enough around DST
|
||
res.add(1, 'd');
|
||
res._nextDay = undefined;
|
||
}
|
||
|
||
return res;
|
||
}
|
||
|
||
function prepareConfig (config) {
|
||
var input = config._i,
|
||
format = config._f;
|
||
|
||
config._locale = config._locale || locale_locales__getLocale(config._l);
|
||
|
||
if (input === null || (format === undefined && input === '')) {
|
||
return valid__createInvalid({nullInput: true});
|
||
}
|
||
|
||
if (typeof input === 'string') {
|
||
config._i = input = config._locale.preparse(input);
|
||
}
|
||
|
||
if (isMoment(input)) {
|
||
return new Moment(checkOverflow(input));
|
||
} else if (isArray(format)) {
|
||
configFromStringAndArray(config);
|
||
} else if (format) {
|
||
configFromStringAndFormat(config);
|
||
} else if (isDate(input)) {
|
||
config._d = input;
|
||
} else {
|
||
configFromInput(config);
|
||
}
|
||
|
||
if (!valid__isValid(config)) {
|
||
config._d = null;
|
||
}
|
||
|
||
return config;
|
||
}
|
||
|
||
function configFromInput(config) {
|
||
var input = config._i;
|
||
if (input === undefined) {
|
||
config._d = new Date(utils_hooks__hooks.now());
|
||
} else if (isDate(input)) {
|
||
config._d = new Date(+input);
|
||
} else if (typeof input === 'string') {
|
||
configFromString(config);
|
||
} else if (isArray(input)) {
|
||
config._a = map(input.slice(0), function (obj) {
|
||
return parseInt(obj, 10);
|
||
});
|
||
configFromArray(config);
|
||
} else if (typeof(input) === 'object') {
|
||
configFromObject(config);
|
||
} else if (typeof(input) === 'number') {
|
||
// from milliseconds
|
||
config._d = new Date(input);
|
||
} else {
|
||
utils_hooks__hooks.createFromInputFallback(config);
|
||
}
|
||
}
|
||
|
||
function createLocalOrUTC (input, format, locale, strict, isUTC) {
|
||
var c = {};
|
||
|
||
if (typeof(locale) === 'boolean') {
|
||
strict = locale;
|
||
locale = undefined;
|
||
}
|
||
// object construction must be done this way.
|
||
// https://github.com/moment/moment/issues/1423
|
||
c._isAMomentObject = true;
|
||
c._useUTC = c._isUTC = isUTC;
|
||
c._l = locale;
|
||
c._i = input;
|
||
c._f = format;
|
||
c._strict = strict;
|
||
|
||
return createFromConfig(c);
|
||
}
|
||
|
||
function local__createLocal (input, format, locale, strict) {
|
||
return createLocalOrUTC(input, format, locale, strict, false);
|
||
}
|
||
|
||
var prototypeMin = deprecate(
|
||
'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
|
||
function () {
|
||
var other = local__createLocal.apply(null, arguments);
|
||
if (this.isValid() && other.isValid()) {
|
||
return other < this ? this : other;
|
||
} else {
|
||
return valid__createInvalid();
|
||
}
|
||
}
|
||
);
|
||
|
||
var prototypeMax = deprecate(
|
||
'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
|
||
function () {
|
||
var other = local__createLocal.apply(null, arguments);
|
||
if (this.isValid() && other.isValid()) {
|
||
return other > this ? this : other;
|
||
} else {
|
||
return valid__createInvalid();
|
||
}
|
||
}
|
||
);
|
||
|
||
// Pick a moment m from moments so that m[fn](other) is true for all
|
||
// other. This relies on the function fn to be transitive.
|
||
//
|
||
// moments should either be an array of moment objects or an array, whose
|
||
// first element is an array of moment objects.
|
||
function pickBy(fn, moments) {
|
||
var res, i;
|
||
if (moments.length === 1 && isArray(moments[0])) {
|
||
moments = moments[0];
|
||
}
|
||
if (!moments.length) {
|
||
return local__createLocal();
|
||
}
|
||
res = moments[0];
|
||
for (i = 1; i < moments.length; ++i) {
|
||
if (!moments[i].isValid() || moments[i][fn](res)) {
|
||
res = moments[i];
|
||
}
|
||
}
|
||
return res;
|
||
}
|
||
|
||
// TODO: Use [].sort instead?
|
||
function min () {
|
||
var args = [].slice.call(arguments, 0);
|
||
|
||
return pickBy('isBefore', args);
|
||
}
|
||
|
||
function max () {
|
||
var args = [].slice.call(arguments, 0);
|
||
|
||
return pickBy('isAfter', args);
|
||
}
|
||
|
||
var now = function () {
|
||
return Date.now ? Date.now() : +(new Date());
|
||
};
|
||
|
||
function Duration (duration) {
|
||
var normalizedInput = normalizeObjectUnits(duration),
|
||
years = normalizedInput.year || 0,
|
||
quarters = normalizedInput.quarter || 0,
|
||
months = normalizedInput.month || 0,
|
||
weeks = normalizedInput.week || 0,
|
||
days = normalizedInput.day || 0,
|
||
hours = normalizedInput.hour || 0,
|
||
minutes = normalizedInput.minute || 0,
|
||
seconds = normalizedInput.second || 0,
|
||
milliseconds = normalizedInput.millisecond || 0;
|
||
|
||
// representation for dateAddRemove
|
||
this._milliseconds = +milliseconds +
|
||
seconds * 1e3 + // 1000
|
||
minutes * 6e4 + // 1000 * 60
|
||
hours * 36e5; // 1000 * 60 * 60
|
||
// Because of dateAddRemove treats 24 hours as different from a
|
||
// day when working around DST, we need to store them separately
|
||
this._days = +days +
|
||
weeks * 7;
|
||
// It is impossible translate months into days without knowing
|
||
// which months you are are talking about, so we have to store
|
||
// it separately.
|
||
this._months = +months +
|
||
quarters * 3 +
|
||
years * 12;
|
||
|
||
this._data = {};
|
||
|
||
this._locale = locale_locales__getLocale();
|
||
|
||
this._bubble();
|
||
}
|
||
|
||
function isDuration (obj) {
|
||
return obj instanceof Duration;
|
||
}
|
||
|
||
// FORMATTING
|
||
|
||
function offset (token, separator) {
|
||
addFormatToken(token, 0, 0, function () {
|
||
var offset = this.utcOffset();
|
||
var sign = '+';
|
||
if (offset < 0) {
|
||
offset = -offset;
|
||
sign = '-';
|
||
}
|
||
return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
|
||
});
|
||
}
|
||
|
||
offset('Z', ':');
|
||
offset('ZZ', '');
|
||
|
||
// PARSING
|
||
|
||
addRegexToken('Z', matchShortOffset);
|
||
addRegexToken('ZZ', matchShortOffset);
|
||
addParseToken(['Z', 'ZZ'], function (input, array, config) {
|
||
config._useUTC = true;
|
||
config._tzm = offsetFromString(matchShortOffset, input);
|
||
});
|
||
|
||
// HELPERS
|
||
|
||
// timezone chunker
|
||
// '+10:00' > ['10', '00']
|
||
// '-1530' > ['-15', '30']
|
||
var chunkOffset = /([\+\-]|\d\d)/gi;
|
||
|
||
function offsetFromString(matcher, string) {
|
||
var matches = ((string || '').match(matcher) || []);
|
||
var chunk = matches[matches.length - 1] || [];
|
||
var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
|
||
var minutes = +(parts[1] * 60) + toInt(parts[2]);
|
||
|
||
return parts[0] === '+' ? minutes : -minutes;
|
||
}
|
||
|
||
// Return a moment from input, that is local/utc/zone equivalent to model.
|
||
function cloneWithOffset(input, model) {
|
||
var res, diff;
|
||
if (model._isUTC) {
|
||
res = model.clone();
|
||
diff = (isMoment(input) || isDate(input) ? +input : +local__createLocal(input)) - (+res);
|
||
// Use low-level api, because this fn is low-level api.
|
||
res._d.setTime(+res._d + diff);
|
||
utils_hooks__hooks.updateOffset(res, false);
|
||
return res;
|
||
} else {
|
||
return local__createLocal(input).local();
|
||
}
|
||
}
|
||
|
||
function getDateOffset (m) {
|
||
// On Firefox.24 Date#getTimezoneOffset returns a floating point.
|
||
// https://github.com/moment/moment/pull/1871
|
||
return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
|
||
}
|
||
|
||
// HOOKS
|
||
|
||
// This function will be called whenever a moment is mutated.
|
||
// It is intended to keep the offset in sync with the timezone.
|
||
utils_hooks__hooks.updateOffset = function () {};
|
||
|
||
// MOMENTS
|
||
|
||
// keepLocalTime = true means only change the timezone, without
|
||
// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
|
||
// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
|
||
// +0200, so we adjust the time as needed, to be valid.
|
||
//
|
||
// Keeping the time actually adds/subtracts (one hour)
|
||
// from the actual represented time. That is why we call updateOffset
|
||
// a second time. In case it wants us to change the offset again
|
||
// _changeInProgress == true case, then we have to adjust, because
|
||
// there is no such time in the given timezone.
|
||
function getSetOffset (input, keepLocalTime) {
|
||
var offset = this._offset || 0,
|
||
localAdjust;
|
||
if (!this.isValid()) {
|
||
return input != null ? this : NaN;
|
||
}
|
||
if (input != null) {
|
||
if (typeof input === 'string') {
|
||
input = offsetFromString(matchShortOffset, input);
|
||
} else if (Math.abs(input) < 16) {
|
||
input = input * 60;
|
||
}
|
||
if (!this._isUTC && keepLocalTime) {
|
||
localAdjust = getDateOffset(this);
|
||
}
|
||
this._offset = input;
|
||
this._isUTC = true;
|
||
if (localAdjust != null) {
|
||
this.add(localAdjust, 'm');
|
||
}
|
||
if (offset !== input) {
|
||
if (!keepLocalTime || this._changeInProgress) {
|
||
add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false);
|
||
} else if (!this._changeInProgress) {
|
||
this._changeInProgress = true;
|
||
utils_hooks__hooks.updateOffset(this, true);
|
||
this._changeInProgress = null;
|
||
}
|
||
}
|
||
return this;
|
||
} else {
|
||
return this._isUTC ? offset : getDateOffset(this);
|
||
}
|
||
}
|
||
|
||
function getSetZone (input, keepLocalTime) {
|
||
if (input != null) {
|
||
if (typeof input !== 'string') {
|
||
input = -input;
|
||
}
|
||
|
||
this.utcOffset(input, keepLocalTime);
|
||
|
||
return this;
|
||
} else {
|
||
return -this.utcOffset();
|
||
}
|
||
}
|
||
|
||
function setOffsetToUTC (keepLocalTime) {
|
||
return this.utcOffset(0, keepLocalTime);
|
||
}
|
||
|
||
function setOffsetToLocal (keepLocalTime) {
|
||
if (this._isUTC) {
|
||
this.utcOffset(0, keepLocalTime);
|
||
this._isUTC = false;
|
||
|
||
if (keepLocalTime) {
|
||
this.subtract(getDateOffset(this), 'm');
|
||
}
|
||
}
|
||
return this;
|
||
}
|
||
|
||
function setOffsetToParsedOffset () {
|
||
if (this._tzm) {
|
||
this.utcOffset(this._tzm);
|
||
} else if (typeof this._i === 'string') {
|
||
this.utcOffset(offsetFromString(matchOffset, this._i));
|
||
}
|
||
return this;
|
||
}
|
||
|
||
function hasAlignedHourOffset (input) {
|
||
if (!this.isValid()) {
|
||
return false;
|
||
}
|
||
input = input ? local__createLocal(input).utcOffset() : 0;
|
||
|
||
return (this.utcOffset() - input) % 60 === 0;
|
||
}
|
||
|
||
function isDaylightSavingTime () {
|
||
return (
|
||
this.utcOffset() > this.clone().month(0).utcOffset() ||
|
||
this.utcOffset() > this.clone().month(5).utcOffset()
|
||
);
|
||
}
|
||
|
||
function isDaylightSavingTimeShifted () {
|
||
if (!isUndefined(this._isDSTShifted)) {
|
||
return this._isDSTShifted;
|
||
}
|
||
|
||
var c = {};
|
||
|
||
copyConfig(c, this);
|
||
c = prepareConfig(c);
|
||
|
||
if (c._a) {
|
||
var other = c._isUTC ? create_utc__createUTC(c._a) : local__createLocal(c._a);
|
||
this._isDSTShifted = this.isValid() &&
|
||
compareArrays(c._a, other.toArray()) > 0;
|
||
} else {
|
||
this._isDSTShifted = false;
|
||
}
|
||
|
||
return this._isDSTShifted;
|
||
}
|
||
|
||
function isLocal () {
|
||
return this.isValid() ? !this._isUTC : false;
|
||
}
|
||
|
||
function isUtcOffset () {
|
||
return this.isValid() ? this._isUTC : false;
|
||
}
|
||
|
||
function isUtc () {
|
||
return this.isValid() ? this._isUTC && this._offset === 0 : false;
|
||
}
|
||
|
||
// ASP.NET json date format regex
|
||
var aspNetRegex = /(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/;
|
||
|
||
// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
|
||
// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
|
||
var isoRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/;
|
||
|
||
function create__createDuration (input, key) {
|
||
var duration = input,
|
||
// matching against regexp is expensive, do it on demand
|
||
match = null,
|
||
sign,
|
||
ret,
|
||
diffRes;
|
||
|
||
if (isDuration(input)) {
|
||
duration = {
|
||
ms : input._milliseconds,
|
||
d : input._days,
|
||
M : input._months
|
||
};
|
||
} else if (typeof input === 'number') {
|
||
duration = {};
|
||
if (key) {
|
||
duration[key] = input;
|
||
} else {
|
||
duration.milliseconds = input;
|
||
}
|
||
} else if (!!(match = aspNetRegex.exec(input))) {
|
||
sign = (match[1] === '-') ? -1 : 1;
|
||
duration = {
|
||
y : 0,
|
||
d : toInt(match[DATE]) * sign,
|
||
h : toInt(match[HOUR]) * sign,
|
||
m : toInt(match[MINUTE]) * sign,
|
||
s : toInt(match[SECOND]) * sign,
|
||
ms : toInt(match[MILLISECOND]) * sign
|
||
};
|
||
} else if (!!(match = isoRegex.exec(input))) {
|
||
sign = (match[1] === '-') ? -1 : 1;
|
||
duration = {
|
||
y : parseIso(match[2], sign),
|
||
M : parseIso(match[3], sign),
|
||
d : parseIso(match[4], sign),
|
||
h : parseIso(match[5], sign),
|
||
m : parseIso(match[6], sign),
|
||
s : parseIso(match[7], sign),
|
||
w : parseIso(match[8], sign)
|
||
};
|
||
} else if (duration == null) {// checks for null or undefined
|
||
duration = {};
|
||
} else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
|
||
diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to));
|
||
|
||
duration = {};
|
||
duration.ms = diffRes.milliseconds;
|
||
duration.M = diffRes.months;
|
||
}
|
||
|
||
ret = new Duration(duration);
|
||
|
||
if (isDuration(input) && hasOwnProp(input, '_locale')) {
|
||
ret._locale = input._locale;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
create__createDuration.fn = Duration.prototype;
|
||
|
||
function parseIso (inp, sign) {
|
||
// We'd normally use ~~inp for this, but unfortunately it also
|
||
// converts floats to ints.
|
||
// inp may be undefined, so careful calling replace on it.
|
||
var res = inp && parseFloat(inp.replace(',', '.'));
|
||
// apply sign while we're at it
|
||
return (isNaN(res) ? 0 : res) * sign;
|
||
}
|
||
|
||
function positiveMomentsDifference(base, other) {
|
||
var res = {milliseconds: 0, months: 0};
|
||
|
||
res.months = other.month() - base.month() +
|
||
(other.year() - base.year()) * 12;
|
||
if (base.clone().add(res.months, 'M').isAfter(other)) {
|
||
--res.months;
|
||
}
|
||
|
||
res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
|
||
|
||
return res;
|
||
}
|
||
|
||
function momentsDifference(base, other) {
|
||
var res;
|
||
if (!(base.isValid() && other.isValid())) {
|
||
return {milliseconds: 0, months: 0};
|
||
}
|
||
|
||
other = cloneWithOffset(other, base);
|
||
if (base.isBefore(other)) {
|
||
res = positiveMomentsDifference(base, other);
|
||
} else {
|
||
res = positiveMomentsDifference(other, base);
|
||
res.milliseconds = -res.milliseconds;
|
||
res.months = -res.months;
|
||
}
|
||
|
||
return res;
|
||
}
|
||
|
||
// TODO: remove 'name' arg after deprecation is removed
|
||
function createAdder(direction, name) {
|
||
return function (val, period) {
|
||
var dur, tmp;
|
||
//invert the arguments, but complain about it
|
||
if (period !== null && !isNaN(+period)) {
|
||
deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
|
||
tmp = val; val = period; period = tmp;
|
||
}
|
||
|
||
val = typeof val === 'string' ? +val : val;
|
||
dur = create__createDuration(val, period);
|
||
add_subtract__addSubtract(this, dur, direction);
|
||
return this;
|
||
};
|
||
}
|
||
|
||
function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) {
|
||
var milliseconds = duration._milliseconds,
|
||
days = duration._days,
|
||
months = duration._months;
|
||
|
||
if (!mom.isValid()) {
|
||
// No op
|
||
return;
|
||
}
|
||
|
||
updateOffset = updateOffset == null ? true : updateOffset;
|
||
|
||
if (milliseconds) {
|
||
mom._d.setTime(+mom._d + milliseconds * isAdding);
|
||
}
|
||
if (days) {
|
||
get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding);
|
||
}
|
||
if (months) {
|
||
setMonth(mom, get_set__get(mom, 'Month') + months * isAdding);
|
||
}
|
||
if (updateOffset) {
|
||
utils_hooks__hooks.updateOffset(mom, days || months);
|
||
}
|
||
}
|
||
|
||
var add_subtract__add = createAdder(1, 'add');
|
||
var add_subtract__subtract = createAdder(-1, 'subtract');
|
||
|
||
function moment_calendar__calendar (time, formats) {
|
||
// We want to compare the start of today, vs this.
|
||
// Getting start-of-today depends on whether we're local/utc/offset or not.
|
||
var now = time || local__createLocal(),
|
||
sod = cloneWithOffset(now, this).startOf('day'),
|
||
diff = this.diff(sod, 'days', true),
|
||
format = diff < -6 ? 'sameElse' :
|
||
diff < -1 ? 'lastWeek' :
|
||
diff < 0 ? 'lastDay' :
|
||
diff < 1 ? 'sameDay' :
|
||
diff < 2 ? 'nextDay' :
|
||
diff < 7 ? 'nextWeek' : 'sameElse';
|
||
|
||
var output = formats && (isFunction(formats[format]) ? formats[format]() : formats[format]);
|
||
|
||
return this.format(output || this.localeData().calendar(format, this, local__createLocal(now)));
|
||
}
|
||
|
||
function clone () {
|
||
return new Moment(this);
|
||
}
|
||
|
||
function isAfter (input, units) {
|
||
var localInput = isMoment(input) ? input : local__createLocal(input);
|
||
if (!(this.isValid() && localInput.isValid())) {
|
||
return false;
|
||
}
|
||
units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
|
||
if (units === 'millisecond') {
|
||
return +this > +localInput;
|
||
} else {
|
||
return +localInput < +this.clone().startOf(units);
|
||
}
|
||
}
|
||
|
||
function isBefore (input, units) {
|
||
var localInput = isMoment(input) ? input : local__createLocal(input);
|
||
if (!(this.isValid() && localInput.isValid())) {
|
||
return false;
|
||
}
|
||
units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
|
||
if (units === 'millisecond') {
|
||
return +this < +localInput;
|
||
} else {
|
||
return +this.clone().endOf(units) < +localInput;
|
||
}
|
||
}
|
||
|
||
function isBetween (from, to, units) {
|
||
return this.isAfter(from, units) && this.isBefore(to, units);
|
||
}
|
||
|
||
function isSame (input, units) {
|
||
var localInput = isMoment(input) ? input : local__createLocal(input),
|
||
inputMs;
|
||
if (!(this.isValid() && localInput.isValid())) {
|
||
return false;
|
||
}
|
||
units = normalizeUnits(units || 'millisecond');
|
||
if (units === 'millisecond') {
|
||
return +this === +localInput;
|
||
} else {
|
||
inputMs = +localInput;
|
||
return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units));
|
||
}
|
||
}
|
||
|
||
function isSameOrAfter (input, units) {
|
||
return this.isSame(input, units) || this.isAfter(input,units);
|
||
}
|
||
|
||
function isSameOrBefore (input, units) {
|
||
return this.isSame(input, units) || this.isBefore(input,units);
|
||
}
|
||
|
||
function diff (input, units, asFloat) {
|
||
var that,
|
||
zoneDelta,
|
||
delta, output;
|
||
|
||
if (!this.isValid()) {
|
||
return NaN;
|
||
}
|
||
|
||
that = cloneWithOffset(input, this);
|
||
|
||
if (!that.isValid()) {
|
||
return NaN;
|
||
}
|
||
|
||
zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
|
||
|
||
units = normalizeUnits(units);
|
||
|
||
if (units === 'year' || units === 'month' || units === 'quarter') {
|
||
output = monthDiff(this, that);
|
||
if (units === 'quarter') {
|
||
output = output / 3;
|
||
} else if (units === 'year') {
|
||
output = output / 12;
|
||
}
|
||
} else {
|
||
delta = this - that;
|
||
output = units === 'second' ? delta / 1e3 : // 1000
|
||
units === 'minute' ? delta / 6e4 : // 1000 * 60
|
||
units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
|
||
units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
|
||
units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
|
||
delta;
|
||
}
|
||
return asFloat ? output : absFloor(output);
|
||
}
|
||
|
||
function monthDiff (a, b) {
|
||
// difference in months
|
||
var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
|
||
// b is in (anchor - 1 month, anchor + 1 month)
|
||
anchor = a.clone().add(wholeMonthDiff, 'months'),
|
||
anchor2, adjust;
|
||
|
||
if (b - anchor < 0) {
|
||
anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
|
||
// linear across the month
|
||
adjust = (b - anchor) / (anchor - anchor2);
|
||
} else {
|
||
anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
|
||
// linear across the month
|
||
adjust = (b - anchor) / (anchor2 - anchor);
|
||
}
|
||
|
||
return -(wholeMonthDiff + adjust);
|
||
}
|
||
|
||
utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
|
||
|
||
function toString () {
|
||
return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
|
||
}
|
||
|
||
function moment_format__toISOString () {
|
||
var m = this.clone().utc();
|
||
if (0 < m.year() && m.year() <= 9999) {
|
||
if (isFunction(Date.prototype.toISOString)) {
|
||
// native implementation is ~50x faster, use it when we can
|
||
return this.toDate().toISOString();
|
||
} else {
|
||
return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
|
||
}
|
||
} else {
|
||
return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
|
||
}
|
||
}
|
||
|
||
function format (inputString) {
|
||
var output = formatMoment(this, inputString || utils_hooks__hooks.defaultFormat);
|
||
return this.localeData().postformat(output);
|
||
}
|
||
|
||
function from (time, withoutSuffix) {
|
||
if (this.isValid() &&
|
||
((isMoment(time) && time.isValid()) ||
|
||
local__createLocal(time).isValid())) {
|
||
return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
|
||
} else {
|
||
return this.localeData().invalidDate();
|
||
}
|
||
}
|
||
|
||
function fromNow (withoutSuffix) {
|
||
return this.from(local__createLocal(), withoutSuffix);
|
||
}
|
||
|
||
function to (time, withoutSuffix) {
|
||
if (this.isValid() &&
|
||
((isMoment(time) && time.isValid()) ||
|
||
local__createLocal(time).isValid())) {
|
||
return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
|
||
} else {
|
||
return this.localeData().invalidDate();
|
||
}
|
||
}
|
||
|
||
function toNow (withoutSuffix) {
|
||
return this.to(local__createLocal(), withoutSuffix);
|
||
}
|
||
|
||
// If passed a locale key, it will set the locale for this
|
||
// instance. Otherwise, it will return the locale configuration
|
||
// variables for this instance.
|
||
function locale (key) {
|
||
var newLocaleData;
|
||
|
||
if (key === undefined) {
|
||
return this._locale._abbr;
|
||
} else {
|
||
newLocaleData = locale_locales__getLocale(key);
|
||
if (newLocaleData != null) {
|
||
this._locale = newLocaleData;
|
||
}
|
||
return this;
|
||
}
|
||
}
|
||
|
||
var lang = deprecate(
|
||
'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
|
||
function (key) {
|
||
if (key === undefined) {
|
||
return this.localeData();
|
||
} else {
|
||
return this.locale(key);
|
||
}
|
||
}
|
||
);
|
||
|
||
function localeData () {
|
||
return this._locale;
|
||
}
|
||
|
||
function startOf (units) {
|
||
units = normalizeUnits(units);
|
||
// the following switch intentionally omits break keywords
|
||
// to utilize falling through the cases.
|
||
switch (units) {
|
||
case 'year':
|
||
this.month(0);
|
||
/* falls through */
|
||
case 'quarter':
|
||
case 'month':
|
||
this.date(1);
|
||
/* falls through */
|
||
case 'week':
|
||
case 'isoWeek':
|
||
case 'day':
|
||
this.hours(0);
|
||
/* falls through */
|
||
case 'hour':
|
||
this.minutes(0);
|
||
/* falls through */
|
||
case 'minute':
|
||
this.seconds(0);
|
||
/* falls through */
|
||
case 'second':
|
||
this.milliseconds(0);
|
||
}
|
||
|
||
// weeks are a special case
|
||
if (units === 'week') {
|
||
this.weekday(0);
|
||
}
|
||
if (units === 'isoWeek') {
|
||
this.isoWeekday(1);
|
||
}
|
||
|
||
// quarters are also special
|
||
if (units === 'quarter') {
|
||
this.month(Math.floor(this.month() / 3) * 3);
|
||
}
|
||
|
||
return this;
|
||
}
|
||
|
||
function endOf (units) {
|
||
units = normalizeUnits(units);
|
||
if (units === undefined || units === 'millisecond') {
|
||
return this;
|
||
}
|
||
return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
|
||
}
|
||
|
||
function to_type__valueOf () {
|
||
return +this._d - ((this._offset || 0) * 60000);
|
||
}
|
||
|
||
function unix () {
|
||
return Math.floor(+this / 1000);
|
||
}
|
||
|
||
function toDate () {
|
||
return this._offset ? new Date(+this) : this._d;
|
||
}
|
||
|
||
function toArray () {
|
||
var m = this;
|
||
return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
|
||
}
|
||
|
||
function toObject () {
|
||
var m = this;
|
||
return {
|
||
years: m.year(),
|
||
months: m.month(),
|
||
date: m.date(),
|
||
hours: m.hours(),
|
||
minutes: m.minutes(),
|
||
seconds: m.seconds(),
|
||
milliseconds: m.milliseconds()
|
||
};
|
||
}
|
||
|
||
function toJSON () {
|
||
// JSON.stringify(new Date(NaN)) === 'null'
|
||
return this.isValid() ? this.toISOString() : 'null';
|
||
}
|
||
|
||
function moment_valid__isValid () {
|
||
return valid__isValid(this);
|
||
}
|
||
|
||
function parsingFlags () {
|
||
return extend({}, getParsingFlags(this));
|
||
}
|
||
|
||
function invalidAt () {
|
||
return getParsingFlags(this).overflow;
|
||
}
|
||
|
||
function creationData() {
|
||
return {
|
||
input: this._i,
|
||
format: this._f,
|
||
locale: this._locale,
|
||
isUTC: this._isUTC,
|
||
strict: this._strict
|
||
};
|
||
}
|
||
|
||
// FORMATTING
|
||
|
||
addFormatToken(0, ['gg', 2], 0, function () {
|
||
return this.weekYear() % 100;
|
||
});
|
||
|
||
addFormatToken(0, ['GG', 2], 0, function () {
|
||
return this.isoWeekYear() % 100;
|
||
});
|
||
|
||
function addWeekYearFormatToken (token, getter) {
|
||
addFormatToken(0, [token, token.length], 0, getter);
|
||
}
|
||
|
||
addWeekYearFormatToken('gggg', 'weekYear');
|
||
addWeekYearFormatToken('ggggg', 'weekYear');
|
||
addWeekYearFormatToken('GGGG', 'isoWeekYear');
|
||
addWeekYearFormatToken('GGGGG', 'isoWeekYear');
|
||
|
||
// ALIASES
|
||
|
||
addUnitAlias('weekYear', 'gg');
|
||
addUnitAlias('isoWeekYear', 'GG');
|
||
|
||
// PARSING
|
||
|
||
addRegexToken('G', matchSigned);
|
||
addRegexToken('g', matchSigned);
|
||
addRegexToken('GG', match1to2, match2);
|
||
addRegexToken('gg', match1to2, match2);
|
||
addRegexToken('GGGG', match1to4, match4);
|
||
addRegexToken('gggg', match1to4, match4);
|
||
addRegexToken('GGGGG', match1to6, match6);
|
||
addRegexToken('ggggg', match1to6, match6);
|
||
|
||
addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
|
||
week[token.substr(0, 2)] = toInt(input);
|
||
});
|
||
|
||
addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
|
||
week[token] = utils_hooks__hooks.parseTwoDigitYear(input);
|
||
});
|
||
|
||
// MOMENTS
|
||
|
||
function getSetWeekYear (input) {
|
||
return getSetWeekYearHelper.call(this,
|
||
input,
|
||
this.week(),
|
||
this.weekday(),
|
||
this.localeData()._week.dow,
|
||
this.localeData()._week.doy);
|
||
}
|
||
|
||
function getSetISOWeekYear (input) {
|
||
return getSetWeekYearHelper.call(this,
|
||
input, this.isoWeek(), this.isoWeekday(), 1, 4);
|
||
}
|
||
|
||
function getISOWeeksInYear () {
|
||
return weeksInYear(this.year(), 1, 4);
|
||
}
|
||
|
||
function getWeeksInYear () {
|
||
var weekInfo = this.localeData()._week;
|
||
return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
|
||
}
|
||
|
||
function getSetWeekYearHelper(input, week, weekday, dow, doy) {
|
||
var weeksTarget;
|
||
if (input == null) {
|
||
return weekOfYear(this, dow, doy).year;
|
||
} else {
|
||
weeksTarget = weeksInYear(input, dow, doy);
|
||
if (week > weeksTarget) {
|
||
week = weeksTarget;
|
||
}
|
||
return setWeekAll.call(this, input, week, weekday, dow, doy);
|
||
}
|
||
}
|
||
|
||
function setWeekAll(weekYear, week, weekday, dow, doy) {
|
||
var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
|
||
date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
|
||
|
||
// console.log("got", weekYear, week, weekday, "set", date.toISOString());
|
||
this.year(date.getUTCFullYear());
|
||
this.month(date.getUTCMonth());
|
||
this.date(date.getUTCDate());
|
||
return this;
|
||
}
|
||
|
||
// FORMATTING
|
||
|
||
addFormatToken('Q', 0, 'Qo', 'quarter');
|
||
|
||
// ALIASES
|
||
|
||
addUnitAlias('quarter', 'Q');
|
||
|
||
// PARSING
|
||
|
||
addRegexToken('Q', match1);
|
||
addParseToken('Q', function (input, array) {
|
||
array[MONTH] = (toInt(input) - 1) * 3;
|
||
});
|
||
|
||
// MOMENTS
|
||
|
||
function getSetQuarter (input) {
|
||
return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
|
||
}
|
||
|
||
// FORMATTING
|
||
|
||
addFormatToken('w', ['ww', 2], 'wo', 'week');
|
||
addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
|
||
|
||
// ALIASES
|
||
|
||
addUnitAlias('week', 'w');
|
||
addUnitAlias('isoWeek', 'W');
|
||
|
||
// PARSING
|
||
|
||
addRegexToken('w', match1to2);
|
||
addRegexToken('ww', match1to2, match2);
|
||
addRegexToken('W', match1to2);
|
||
addRegexToken('WW', match1to2, match2);
|
||
|
||
addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
|
||
week[token.substr(0, 1)] = toInt(input);
|
||
});
|
||
|
||
// HELPERS
|
||
|
||
// LOCALES
|
||
|
||
function localeWeek (mom) {
|
||
return weekOfYear(mom, this._week.dow, this._week.doy).week;
|
||
}
|
||
|
||
var defaultLocaleWeek = {
|
||
dow : 0, // Sunday is the first day of the week.
|
||
doy : 6 // The week that contains Jan 1st is the first week of the year.
|
||
};
|
||
|
||
function localeFirstDayOfWeek () {
|
||
return this._week.dow;
|
||
}
|
||
|
||
function localeFirstDayOfYear () {
|
||
return this._week.doy;
|
||
}
|
||
|
||
// MOMENTS
|
||
|
||
function getSetWeek (input) {
|
||
var week = this.localeData().week(this);
|
||
return input == null ? week : this.add((input - week) * 7, 'd');
|
||
}
|
||
|
||
function getSetISOWeek (input) {
|
||
var week = weekOfYear(this, 1, 4).week;
|
||
return input == null ? week : this.add((input - week) * 7, 'd');
|
||
}
|
||
|
||
// FORMATTING
|
||
|
||
addFormatToken('D', ['DD', 2], 'Do', 'date');
|
||
|
||
// ALIASES
|
||
|
||
addUnitAlias('date', 'D');
|
||
|
||
// PARSING
|
||
|
||
addRegexToken('D', match1to2);
|
||
addRegexToken('DD', match1to2, match2);
|
||
addRegexToken('Do', function (isStrict, locale) {
|
||
return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;
|
||
});
|
||
|
||
addParseToken(['D', 'DD'], DATE);
|
||
addParseToken('Do', function (input, array) {
|
||
array[DATE] = toInt(input.match(match1to2)[0], 10);
|
||
});
|
||
|
||
// MOMENTS
|
||
|
||
var getSetDayOfMonth = makeGetSet('Date', true);
|
||
|
||
// FORMATTING
|
||
|
||
addFormatToken('d', 0, 'do', 'day');
|
||
|
||
addFormatToken('dd', 0, 0, function (format) {
|
||
return this.localeData().weekdaysMin(this, format);
|
||
});
|
||
|
||
addFormatToken('ddd', 0, 0, function (format) {
|
||
return this.localeData().weekdaysShort(this, format);
|
||
});
|
||
|
||
addFormatToken('dddd', 0, 0, function (format) {
|
||
return this.localeData().weekdays(this, format);
|
||
});
|
||
|
||
addFormatToken('e', 0, 0, 'weekday');
|
||
addFormatToken('E', 0, 0, 'isoWeekday');
|
||
|
||
// ALIASES
|
||
|
||
addUnitAlias('day', 'd');
|
||
addUnitAlias('weekday', 'e');
|
||
addUnitAlias('isoWeekday', 'E');
|
||
|
||
// PARSING
|
||
|
||
addRegexToken('d', match1to2);
|
||
addRegexToken('e', match1to2);
|
||
addRegexToken('E', match1to2);
|
||
addRegexToken('dd', matchWord);
|
||
addRegexToken('ddd', matchWord);
|
||
addRegexToken('dddd', matchWord);
|
||
|
||
addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
|
||
var weekday = config._locale.weekdaysParse(input, token, config._strict);
|
||
// if we didn't get a weekday name, mark the date as invalid
|
||
if (weekday != null) {
|
||
week.d = weekday;
|
||
} else {
|
||
getParsingFlags(config).invalidWeekday = input;
|
||
}
|
||
});
|
||
|
||
addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
|
||
week[token] = toInt(input);
|
||
});
|
||
|
||
// HELPERS
|
||
|
||
function parseWeekday(input, locale) {
|
||
if (typeof input !== 'string') {
|
||
return input;
|
||
}
|
||
|
||
if (!isNaN(input)) {
|
||
return parseInt(input, 10);
|
||
}
|
||
|
||
input = locale.weekdaysParse(input);
|
||
if (typeof input === 'number') {
|
||
return input;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
// LOCALES
|
||
|
||
var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
|
||
function localeWeekdays (m, format) {
|
||
return isArray(this._weekdays) ? this._weekdays[m.day()] :
|
||
this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
|
||
}
|
||
|
||
var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
|
||
function localeWeekdaysShort (m) {
|
||
return this._weekdaysShort[m.day()];
|
||
}
|
||
|
||
var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
|
||
function localeWeekdaysMin (m) {
|
||
return this._weekdaysMin[m.day()];
|
||
}
|
||
|
||
function localeWeekdaysParse (weekdayName, format, strict) {
|
||
var i, mom, regex;
|
||
|
||
if (!this._weekdaysParse) {
|
||
this._weekdaysParse = [];
|
||
this._minWeekdaysParse = [];
|
||
this._shortWeekdaysParse = [];
|
||
this._fullWeekdaysParse = [];
|
||
}
|
||
|
||
for (i = 0; i < 7; i++) {
|
||
// make the regex if we don't have it already
|
||
|
||
mom = local__createLocal([2000, 1]).day(i);
|
||
if (strict && !this._fullWeekdaysParse[i]) {
|
||
this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i');
|
||
this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i');
|
||
this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i');
|
||
}
|
||
if (!this._weekdaysParse[i]) {
|
||
regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
|
||
this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
|
||
}
|
||
// test the regex
|
||
if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
|
||
return i;
|
||
} else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
|
||
return i;
|
||
} else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
|
||
return i;
|
||
} else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
|
||
return i;
|
||
}
|
||
}
|
||
}
|
||
|
||
// MOMENTS
|
||
|
||
function getSetDayOfWeek (input) {
|
||
if (!this.isValid()) {
|
||
return input != null ? this : NaN;
|
||
}
|
||
var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
|
||
if (input != null) {
|
||
input = parseWeekday(input, this.localeData());
|
||
return this.add(input - day, 'd');
|
||
} else {
|
||
return day;
|
||
}
|
||
}
|
||
|
||
function getSetLocaleDayOfWeek (input) {
|
||
if (!this.isValid()) {
|
||
return input != null ? this : NaN;
|
||
}
|
||
var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
|
||
return input == null ? weekday : this.add(input - weekday, 'd');
|
||
}
|
||
|
||
function getSetISODayOfWeek (input) {
|
||
if (!this.isValid()) {
|
||
return input != null ? this : NaN;
|
||
}
|
||
// behaves the same as moment#day except
|
||
// as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
|
||
// as a setter, sunday should belong to the previous week.
|
||
return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
|
||
}
|
||
|
||
// FORMATTING
|
||
|
||
addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
|
||
|
||
// ALIASES
|
||
|
||
addUnitAlias('dayOfYear', 'DDD');
|
||
|
||
// PARSING
|
||
|
||
addRegexToken('DDD', match1to3);
|
||
addRegexToken('DDDD', match3);
|
||
addParseToken(['DDD', 'DDDD'], function (input, array, config) {
|
||
config._dayOfYear = toInt(input);
|
||
});
|
||
|
||
// HELPERS
|
||
|
||
// MOMENTS
|
||
|
||
function getSetDayOfYear (input) {
|
||
var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
|
||
return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
|
||
}
|
||
|
||
// FORMATTING
|
||
|
||
function hFormat() {
|
||
return this.hours() % 12 || 12;
|
||
}
|
||
|
||
addFormatToken('H', ['HH', 2], 0, 'hour');
|
||
addFormatToken('h', ['hh', 2], 0, hFormat);
|
||
|
||
addFormatToken('hmm', 0, 0, function () {
|
||
return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
|
||
});
|
||
|
||
addFormatToken('hmmss', 0, 0, function () {
|
||
return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
|
||
zeroFill(this.seconds(), 2);
|
||
});
|
||
|
||
addFormatToken('Hmm', 0, 0, function () {
|
||
return '' + this.hours() + zeroFill(this.minutes(), 2);
|
||
});
|
||
|
||
addFormatToken('Hmmss', 0, 0, function () {
|
||
return '' + this.hours() + zeroFill(this.minutes(), 2) +
|
||
zeroFill(this.seconds(), 2);
|
||
});
|
||
|
||
function meridiem (token, lowercase) {
|
||
addFormatToken(token, 0, 0, function () {
|
||
return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
|
||
});
|
||
}
|
||
|
||
meridiem('a', true);
|
||
meridiem('A', false);
|
||
|
||
// ALIASES
|
||
|
||
addUnitAlias('hour', 'h');
|
||
|
||
// PARSING
|
||
|
||
function matchMeridiem (isStrict, locale) {
|
||
return locale._meridiemParse;
|
||
}
|
||
|
||
addRegexToken('a', matchMeridiem);
|
||
addRegexToken('A', matchMeridiem);
|
||
addRegexToken('H', match1to2);
|
||
addRegexToken('h', match1to2);
|
||
addRegexToken('HH', match1to2, match2);
|
||
addRegexToken('hh', match1to2, match2);
|
||
|
||
addRegexToken('hmm', match3to4);
|
||
addRegexToken('hmmss', match5to6);
|
||
addRegexToken('Hmm', match3to4);
|
||
addRegexToken('Hmmss', match5to6);
|
||
|
||
addParseToken(['H', 'HH'], HOUR);
|
||
addParseToken(['a', 'A'], function (input, array, config) {
|
||
config._isPm = config._locale.isPM(input);
|
||
config._meridiem = input;
|
||
});
|
||
addParseToken(['h', 'hh'], function (input, array, config) {
|
||
array[HOUR] = toInt(input);
|
||
getParsingFlags(config).bigHour = true;
|
||
});
|
||
addParseToken('hmm', function (input, array, config) {
|
||
var pos = input.length - 2;
|
||
array[HOUR] = toInt(input.substr(0, pos));
|
||
array[MINUTE] = toInt(input.substr(pos));
|
||
getParsingFlags(config).bigHour = true;
|
||
});
|
||
addParseToken('hmmss', function (input, array, config) {
|
||
var pos1 = input.length - 4;
|
||
var pos2 = input.length - 2;
|
||
array[HOUR] = toInt(input.substr(0, pos1));
|
||
array[MINUTE] = toInt(input.substr(pos1, 2));
|
||
array[SECOND] = toInt(input.substr(pos2));
|
||
getParsingFlags(config).bigHour = true;
|
||
});
|
||
addParseToken('Hmm', function (input, array, config) {
|
||
var pos = input.length - 2;
|
||
array[HOUR] = toInt(input.substr(0, pos));
|
||
array[MINUTE] = toInt(input.substr(pos));
|
||
});
|
||
addParseToken('Hmmss', function (input, array, config) {
|
||
var pos1 = input.length - 4;
|
||
var pos2 = input.length - 2;
|
||
array[HOUR] = toInt(input.substr(0, pos1));
|
||
array[MINUTE] = toInt(input.substr(pos1, 2));
|
||
array[SECOND] = toInt(input.substr(pos2));
|
||
});
|
||
|
||
// LOCALES
|
||
|
||
function localeIsPM (input) {
|
||
// IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
|
||
// Using charAt should be more compatible.
|
||
return ((input + '').toLowerCase().charAt(0) === 'p');
|
||
}
|
||
|
||
var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
|
||
function localeMeridiem (hours, minutes, isLower) {
|
||
if (hours > 11) {
|
||
return isLower ? 'pm' : 'PM';
|
||
} else {
|
||
return isLower ? 'am' : 'AM';
|
||
}
|
||
}
|
||
|
||
|
||
// MOMENTS
|
||
|
||
// Setting the hour should keep the time, because the user explicitly
|
||
// specified which hour he wants. So trying to maintain the same hour (in
|
||
// a new timezone) makes sense. Adding/subtracting hours does not follow
|
||
// this rule.
|
||
var getSetHour = makeGetSet('Hours', true);
|
||
|
||
// FORMATTING
|
||
|
||
addFormatToken('m', ['mm', 2], 0, 'minute');
|
||
|
||
// ALIASES
|
||
|
||
addUnitAlias('minute', 'm');
|
||
|
||
// PARSING
|
||
|
||
addRegexToken('m', match1to2);
|
||
addRegexToken('mm', match1to2, match2);
|
||
addParseToken(['m', 'mm'], MINUTE);
|
||
|
||
// MOMENTS
|
||
|
||
var getSetMinute = makeGetSet('Minutes', false);
|
||
|
||
// FORMATTING
|
||
|
||
addFormatToken('s', ['ss', 2], 0, 'second');
|
||
|
||
// ALIASES
|
||
|
||
addUnitAlias('second', 's');
|
||
|
||
// PARSING
|
||
|
||
addRegexToken('s', match1to2);
|
||
addRegexToken('ss', match1to2, match2);
|
||
addParseToken(['s', 'ss'], SECOND);
|
||
|
||
// MOMENTS
|
||
|
||
var getSetSecond = makeGetSet('Seconds', false);
|
||
|
||
// FORMATTING
|
||
|
||
addFormatToken('S', 0, 0, function () {
|
||
return ~~(this.millisecond() / 100);
|
||
});
|
||
|
||
addFormatToken(0, ['SS', 2], 0, function () {
|
||
return ~~(this.millisecond() / 10);
|
||
});
|
||
|
||
addFormatToken(0, ['SSS', 3], 0, 'millisecond');
|
||
addFormatToken(0, ['SSSS', 4], 0, function () {
|
||
return this.millisecond() * 10;
|
||
});
|
||
addFormatToken(0, ['SSSSS', 5], 0, function () {
|
||
return this.millisecond() * 100;
|
||
});
|
||
addFormatToken(0, ['SSSSSS', 6], 0, function () {
|
||
return this.millisecond() * 1000;
|
||
});
|
||
addFormatToken(0, ['SSSSSSS', 7], 0, function () {
|
||
return this.millisecond() * 10000;
|
||
});
|
||
addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
|
||
return this.millisecond() * 100000;
|
||
});
|
||
addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
|
||
return this.millisecond() * 1000000;
|
||
});
|
||
|
||
|
||
// ALIASES
|
||
|
||
addUnitAlias('millisecond', 'ms');
|
||
|
||
// PARSING
|
||
|
||
addRegexToken('S', match1to3, match1);
|
||
addRegexToken('SS', match1to3, match2);
|
||
addRegexToken('SSS', match1to3, match3);
|
||
|
||
var token;
|
||
for (token = 'SSSS'; token.length <= 9; token += 'S') {
|
||
addRegexToken(token, matchUnsigned);
|
||
}
|
||
|
||
function parseMs(input, array) {
|
||
array[MILLISECOND] = toInt(('0.' + input) * 1000);
|
||
}
|
||
|
||
for (token = 'S'; token.length <= 9; token += 'S') {
|
||
addParseToken(token, parseMs);
|
||
}
|
||
// MOMENTS
|
||
|
||
var getSetMillisecond = makeGetSet('Milliseconds', false);
|
||
|
||
// FORMATTING
|
||
|
||
addFormatToken('z', 0, 0, 'zoneAbbr');
|
||
addFormatToken('zz', 0, 0, 'zoneName');
|
||
|
||
// MOMENTS
|
||
|
||
function getZoneAbbr () {
|
||
return this._isUTC ? 'UTC' : '';
|
||
}
|
||
|
||
function getZoneName () {
|
||
return this._isUTC ? 'Coordinated Universal Time' : '';
|
||
}
|
||
|
||
var momentPrototype__proto = Moment.prototype;
|
||
|
||
momentPrototype__proto.add = add_subtract__add;
|
||
momentPrototype__proto.calendar = moment_calendar__calendar;
|
||
momentPrototype__proto.clone = clone;
|
||
momentPrototype__proto.diff = diff;
|
||
momentPrototype__proto.endOf = endOf;
|
||
momentPrototype__proto.format = format;
|
||
momentPrototype__proto.from = from;
|
||
momentPrototype__proto.fromNow = fromNow;
|
||
momentPrototype__proto.to = to;
|
||
momentPrototype__proto.toNow = toNow;
|
||
momentPrototype__proto.get = getSet;
|
||
momentPrototype__proto.invalidAt = invalidAt;
|
||
momentPrototype__proto.isAfter = isAfter;
|
||
momentPrototype__proto.isBefore = isBefore;
|
||
momentPrototype__proto.isBetween = isBetween;
|
||
momentPrototype__proto.isSame = isSame;
|
||
momentPrototype__proto.isSameOrAfter = isSameOrAfter;
|
||
momentPrototype__proto.isSameOrBefore = isSameOrBefore;
|
||
momentPrototype__proto.isValid = moment_valid__isValid;
|
||
momentPrototype__proto.lang = lang;
|
||
momentPrototype__proto.locale = locale;
|
||
momentPrototype__proto.localeData = localeData;
|
||
momentPrototype__proto.max = prototypeMax;
|
||
momentPrototype__proto.min = prototypeMin;
|
||
momentPrototype__proto.parsingFlags = parsingFlags;
|
||
momentPrototype__proto.set = getSet;
|
||
momentPrototype__proto.startOf = startOf;
|
||
momentPrototype__proto.subtract = add_subtract__subtract;
|
||
momentPrototype__proto.toArray = toArray;
|
||
momentPrototype__proto.toObject = toObject;
|
||
momentPrototype__proto.toDate = toDate;
|
||
momentPrototype__proto.toISOString = moment_format__toISOString;
|
||
momentPrototype__proto.toJSON = toJSON;
|
||
momentPrototype__proto.toString = toString;
|
||
momentPrototype__proto.unix = unix;
|
||
momentPrototype__proto.valueOf = to_type__valueOf;
|
||
momentPrototype__proto.creationData = creationData;
|
||
|
||
// Year
|
||
momentPrototype__proto.year = getSetYear;
|
||
momentPrototype__proto.isLeapYear = getIsLeapYear;
|
||
|
||
// Week Year
|
||
momentPrototype__proto.weekYear = getSetWeekYear;
|
||
momentPrototype__proto.isoWeekYear = getSetISOWeekYear;
|
||
|
||
// Quarter
|
||
momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter;
|
||
|
||
// Month
|
||
momentPrototype__proto.month = getSetMonth;
|
||
momentPrototype__proto.daysInMonth = getDaysInMonth;
|
||
|
||
// Week
|
||
momentPrototype__proto.week = momentPrototype__proto.weeks = getSetWeek;
|
||
momentPrototype__proto.isoWeek = momentPrototype__proto.isoWeeks = getSetISOWeek;
|
||
momentPrototype__proto.weeksInYear = getWeeksInYear;
|
||
momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear;
|
||
|
||
// Day
|
||
momentPrototype__proto.date = getSetDayOfMonth;
|
||
momentPrototype__proto.day = momentPrototype__proto.days = getSetDayOfWeek;
|
||
momentPrototype__proto.weekday = getSetLocaleDayOfWeek;
|
||
momentPrototype__proto.isoWeekday = getSetISODayOfWeek;
|
||
momentPrototype__proto.dayOfYear = getSetDayOfYear;
|
||
|
||
// Hour
|
||
momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour;
|
||
|
||
// Minute
|
||
momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute;
|
||
|
||
// Second
|
||
momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond;
|
||
|
||
// Millisecond
|
||
momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond;
|
||
|
||
// Offset
|
||
momentPrototype__proto.utcOffset = getSetOffset;
|
||
momentPrototype__proto.utc = setOffsetToUTC;
|
||
momentPrototype__proto.local = setOffsetToLocal;
|
||
momentPrototype__proto.parseZone = setOffsetToParsedOffset;
|
||
momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset;
|
||
momentPrototype__proto.isDST = isDaylightSavingTime;
|
||
momentPrototype__proto.isDSTShifted = isDaylightSavingTimeShifted;
|
||
momentPrototype__proto.isLocal = isLocal;
|
||
momentPrototype__proto.isUtcOffset = isUtcOffset;
|
||
momentPrototype__proto.isUtc = isUtc;
|
||
momentPrototype__proto.isUTC = isUtc;
|
||
|
||
// Timezone
|
||
momentPrototype__proto.zoneAbbr = getZoneAbbr;
|
||
momentPrototype__proto.zoneName = getZoneName;
|
||
|
||
// Deprecations
|
||
momentPrototype__proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
|
||
momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
|
||
momentPrototype__proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear);
|
||
momentPrototype__proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone);
|
||
|
||
var momentPrototype = momentPrototype__proto;
|
||
|
||
function moment__createUnix (input) {
|
||
return local__createLocal(input * 1000);
|
||
}
|
||
|
||
function moment__createInZone () {
|
||
return local__createLocal.apply(null, arguments).parseZone();
|
||
}
|
||
|
||
var defaultCalendar = {
|
||
sameDay : '[Today at] LT',
|
||
nextDay : '[Tomorrow at] LT',
|
||
nextWeek : 'dddd [at] LT',
|
||
lastDay : '[Yesterday at] LT',
|
||
lastWeek : '[Last] dddd [at] LT',
|
||
sameElse : 'L'
|
||
};
|
||
|
||
function locale_calendar__calendar (key, mom, now) {
|
||
var output = this._calendar[key];
|
||
return isFunction(output) ? output.call(mom, now) : output;
|
||
}
|
||
|
||
var defaultLongDateFormat = {
|
||
LTS : 'h:mm:ss A',
|
||
LT : 'h:mm A',
|
||
L : 'MM/DD/YYYY',
|
||
LL : 'MMMM D, YYYY',
|
||
LLL : 'MMMM D, YYYY h:mm A',
|
||
LLLL : 'dddd, MMMM D, YYYY h:mm A'
|
||
};
|
||
|
||
function longDateFormat (key) {
|
||
var format = this._longDateFormat[key],
|
||
formatUpper = this._longDateFormat[key.toUpperCase()];
|
||
|
||
if (format || !formatUpper) {
|
||
return format;
|
||
}
|
||
|
||
this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
|
||
return val.slice(1);
|
||
});
|
||
|
||
return this._longDateFormat[key];
|
||
}
|
||
|
||
var defaultInvalidDate = 'Invalid date';
|
||
|
||
function invalidDate () {
|
||
return this._invalidDate;
|
||
}
|
||
|
||
var defaultOrdinal = '%d';
|
||
var defaultOrdinalParse = /\d{1,2}/;
|
||
|
||
function ordinal (number) {
|
||
return this._ordinal.replace('%d', number);
|
||
}
|
||
|
||
function preParsePostFormat (string) {
|
||
return string;
|
||
}
|
||
|
||
var defaultRelativeTime = {
|
||
future : 'in %s',
|
||
past : '%s ago',
|
||
s : 'a few seconds',
|
||
m : 'a minute',
|
||
mm : '%d minutes',
|
||
h : 'an hour',
|
||
hh : '%d hours',
|
||
d : 'a day',
|
||
dd : '%d days',
|
||
M : 'a month',
|
||
MM : '%d months',
|
||
y : 'a year',
|
||
yy : '%d years'
|
||
};
|
||
|
||
function relative__relativeTime (number, withoutSuffix, string, isFuture) {
|
||
var output = this._relativeTime[string];
|
||
return (isFunction(output)) ?
|
||
output(number, withoutSuffix, string, isFuture) :
|
||
output.replace(/%d/i, number);
|
||
}
|
||
|
||
function pastFuture (diff, output) {
|
||
var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
|
||
return isFunction(format) ? format(output) : format.replace(/%s/i, output);
|
||
}
|
||
|
||
function locale_set__set (config) {
|
||
var prop, i;
|
||
for (i in config) {
|
||
prop = config[i];
|
||
if (isFunction(prop)) {
|
||
this[i] = prop;
|
||
} else {
|
||
this['_' + i] = prop;
|
||
}
|
||
}
|
||
// Lenient ordinal parsing accepts just a number in addition to
|
||
// number + (possibly) stuff coming from _ordinalParseLenient.
|
||
this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source);
|
||
}
|
||
|
||
var prototype__proto = Locale.prototype;
|
||
|
||
prototype__proto._calendar = defaultCalendar;
|
||
prototype__proto.calendar = locale_calendar__calendar;
|
||
prototype__proto._longDateFormat = defaultLongDateFormat;
|
||
prototype__proto.longDateFormat = longDateFormat;
|
||
prototype__proto._invalidDate = defaultInvalidDate;
|
||
prototype__proto.invalidDate = invalidDate;
|
||
prototype__proto._ordinal = defaultOrdinal;
|
||
prototype__proto.ordinal = ordinal;
|
||
prototype__proto._ordinalParse = defaultOrdinalParse;
|
||
prototype__proto.preparse = preParsePostFormat;
|
||
prototype__proto.postformat = preParsePostFormat;
|
||
prototype__proto._relativeTime = defaultRelativeTime;
|
||
prototype__proto.relativeTime = relative__relativeTime;
|
||
prototype__proto.pastFuture = pastFuture;
|
||
prototype__proto.set = locale_set__set;
|
||
|
||
// Month
|
||
prototype__proto.months = localeMonths;
|
||
prototype__proto._months = defaultLocaleMonths;
|
||
prototype__proto.monthsShort = localeMonthsShort;
|
||
prototype__proto._monthsShort = defaultLocaleMonthsShort;
|
||
prototype__proto.monthsParse = localeMonthsParse;
|
||
prototype__proto._monthsRegex = defaultMonthsRegex;
|
||
prototype__proto.monthsRegex = monthsRegex;
|
||
prototype__proto._monthsShortRegex = defaultMonthsShortRegex;
|
||
prototype__proto.monthsShortRegex = monthsShortRegex;
|
||
|
||
// Week
|
||
prototype__proto.week = localeWeek;
|
||
prototype__proto._week = defaultLocaleWeek;
|
||
prototype__proto.firstDayOfYear = localeFirstDayOfYear;
|
||
prototype__proto.firstDayOfWeek = localeFirstDayOfWeek;
|
||
|
||
// Day of Week
|
||
prototype__proto.weekdays = localeWeekdays;
|
||
prototype__proto._weekdays = defaultLocaleWeekdays;
|
||
prototype__proto.weekdaysMin = localeWeekdaysMin;
|
||
prototype__proto._weekdaysMin = defaultLocaleWeekdaysMin;
|
||
prototype__proto.weekdaysShort = localeWeekdaysShort;
|
||
prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort;
|
||
prototype__proto.weekdaysParse = localeWeekdaysParse;
|
||
|
||
// Hours
|
||
prototype__proto.isPM = localeIsPM;
|
||
prototype__proto._meridiemParse = defaultLocaleMeridiemParse;
|
||
prototype__proto.meridiem = localeMeridiem;
|
||
|
||
function lists__get (format, index, field, setter) {
|
||
var locale = locale_locales__getLocale();
|
||
var utc = create_utc__createUTC().set(setter, index);
|
||
return locale[field](utc, format);
|
||
}
|
||
|
||
function list (format, index, field, count, setter) {
|
||
if (typeof format === 'number') {
|
||
index = format;
|
||
format = undefined;
|
||
}
|
||
|
||
format = format || '';
|
||
|
||
if (index != null) {
|
||
return lists__get(format, index, field, setter);
|
||
}
|
||
|
||
var i;
|
||
var out = [];
|
||
for (i = 0; i < count; i++) {
|
||
out[i] = lists__get(format, i, field, setter);
|
||
}
|
||
return out;
|
||
}
|
||
|
||
function lists__listMonths (format, index) {
|
||
return list(format, index, 'months', 12, 'month');
|
||
}
|
||
|
||
function lists__listMonthsShort (format, index) {
|
||
return list(format, index, 'monthsShort', 12, 'month');
|
||
}
|
||
|
||
function lists__listWeekdays (format, index) {
|
||
return list(format, index, 'weekdays', 7, 'day');
|
||
}
|
||
|
||
function lists__listWeekdaysShort (format, index) {
|
||
return list(format, index, 'weekdaysShort', 7, 'day');
|
||
}
|
||
|
||
function lists__listWeekdaysMin (format, index) {
|
||
return list(format, index, 'weekdaysMin', 7, 'day');
|
||
}
|
||
|
||
locale_locales__getSetGlobalLocale('en', {
|
||
ordinalParse: /\d{1,2}(th|st|nd|rd)/,
|
||
ordinal : function (number) {
|
||
var b = number % 10,
|
||
output = (toInt(number % 100 / 10) === 1) ? 'th' :
|
||
(b === 1) ? 'st' :
|
||
(b === 2) ? 'nd' :
|
||
(b === 3) ? 'rd' : 'th';
|
||
return number + output;
|
||
}
|
||
});
|
||
|
||
// Side effect imports
|
||
utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale);
|
||
utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale);
|
||
|
||
var mathAbs = Math.abs;
|
||
|
||
function duration_abs__abs () {
|
||
var data = this._data;
|
||
|
||
this._milliseconds = mathAbs(this._milliseconds);
|
||
this._days = mathAbs(this._days);
|
||
this._months = mathAbs(this._months);
|
||
|
||
data.milliseconds = mathAbs(data.milliseconds);
|
||
data.seconds = mathAbs(data.seconds);
|
||
data.minutes = mathAbs(data.minutes);
|
||
data.hours = mathAbs(data.hours);
|
||
data.months = mathAbs(data.months);
|
||
data.years = mathAbs(data.years);
|
||
|
||
return this;
|
||
}
|
||
|
||
function duration_add_subtract__addSubtract (duration, input, value, direction) {
|
||
var other = create__createDuration(input, value);
|
||
|
||
duration._milliseconds += direction * other._milliseconds;
|
||
duration._days += direction * other._days;
|
||
duration._months += direction * other._months;
|
||
|
||
return duration._bubble();
|
||
}
|
||
|
||
// supports only 2.0-style add(1, 's') or add(duration)
|
||
function duration_add_subtract__add (input, value) {
|
||
return duration_add_subtract__addSubtract(this, input, value, 1);
|
||
}
|
||
|
||
// supports only 2.0-style subtract(1, 's') or subtract(duration)
|
||
function duration_add_subtract__subtract (input, value) {
|
||
return duration_add_subtract__addSubtract(this, input, value, -1);
|
||
}
|
||
|
||
function absCeil (number) {
|
||
if (number < 0) {
|
||
return Math.floor(number);
|
||
} else {
|
||
return Math.ceil(number);
|
||
}
|
||
}
|
||
|
||
function bubble () {
|
||
var milliseconds = this._milliseconds;
|
||
var days = this._days;
|
||
var months = this._months;
|
||
var data = this._data;
|
||
var seconds, minutes, hours, years, monthsFromDays;
|
||
|
||
// if we have a mix of positive and negative values, bubble down first
|
||
// check: https://github.com/moment/moment/issues/2166
|
||
if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
|
||
(milliseconds <= 0 && days <= 0 && months <= 0))) {
|
||
milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
|
||
days = 0;
|
||
months = 0;
|
||
}
|
||
|
||
// The following code bubbles up values, see the tests for
|
||
// examples of what that means.
|
||
data.milliseconds = milliseconds % 1000;
|
||
|
||
seconds = absFloor(milliseconds / 1000);
|
||
data.seconds = seconds % 60;
|
||
|
||
minutes = absFloor(seconds / 60);
|
||
data.minutes = minutes % 60;
|
||
|
||
hours = absFloor(minutes / 60);
|
||
data.hours = hours % 24;
|
||
|
||
days += absFloor(hours / 24);
|
||
|
||
// convert days to months
|
||
monthsFromDays = absFloor(daysToMonths(days));
|
||
months += monthsFromDays;
|
||
days -= absCeil(monthsToDays(monthsFromDays));
|
||
|
||
// 12 months -> 1 year
|
||
years = absFloor(months / 12);
|
||
months %= 12;
|
||
|
||
data.days = days;
|
||
data.months = months;
|
||
data.years = years;
|
||
|
||
return this;
|
||
}
|
||
|
||
function daysToMonths (days) {
|
||
// 400 years have 146097 days (taking into account leap year rules)
|
||
// 400 years have 12 months === 4800
|
||
return days * 4800 / 146097;
|
||
}
|
||
|
||
function monthsToDays (months) {
|
||
// the reverse of daysToMonths
|
||
return months * 146097 / 4800;
|
||
}
|
||
|
||
function as (units) {
|
||
var days;
|
||
var months;
|
||
var milliseconds = this._milliseconds;
|
||
|
||
units = normalizeUnits(units);
|
||
|
||
if (units === 'month' || units === 'year') {
|
||
days = this._days + milliseconds / 864e5;
|
||
months = this._months + daysToMonths(days);
|
||
return units === 'month' ? months : months / 12;
|
||
} else {
|
||
// handle milliseconds separately because of floating point math errors (issue #1867)
|
||
days = this._days + Math.round(monthsToDays(this._months));
|
||
switch (units) {
|
||
case 'week' : return days / 7 + milliseconds / 6048e5;
|
||
case 'day' : return days + milliseconds / 864e5;
|
||
case 'hour' : return days * 24 + milliseconds / 36e5;
|
||
case 'minute' : return days * 1440 + milliseconds / 6e4;
|
||
case 'second' : return days * 86400 + milliseconds / 1000;
|
||
// Math.floor prevents floating point math errors here
|
||
case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
|
||
default: throw new Error('Unknown unit ' + units);
|
||
}
|
||
}
|
||
}
|
||
|
||
// TODO: Use this.as('ms')?
|
||
function duration_as__valueOf () {
|
||
return (
|
||
this._milliseconds +
|
||
this._days * 864e5 +
|
||
(this._months % 12) * 2592e6 +
|
||
toInt(this._months / 12) * 31536e6
|
||
);
|
||
}
|
||
|
||
function makeAs (alias) {
|
||
return function () {
|
||
return this.as(alias);
|
||
};
|
||
}
|
||
|
||
var asMilliseconds = makeAs('ms');
|
||
var asSeconds = makeAs('s');
|
||
var asMinutes = makeAs('m');
|
||
var asHours = makeAs('h');
|
||
var asDays = makeAs('d');
|
||
var asWeeks = makeAs('w');
|
||
var asMonths = makeAs('M');
|
||
var asYears = makeAs('y');
|
||
|
||
function duration_get__get (units) {
|
||
units = normalizeUnits(units);
|
||
return this[units + 's']();
|
||
}
|
||
|
||
function makeGetter(name) {
|
||
return function () {
|
||
return this._data[name];
|
||
};
|
||
}
|
||
|
||
var milliseconds = makeGetter('milliseconds');
|
||
var seconds = makeGetter('seconds');
|
||
var minutes = makeGetter('minutes');
|
||
var hours = makeGetter('hours');
|
||
var days = makeGetter('days');
|
||
var months = makeGetter('months');
|
||
var years = makeGetter('years');
|
||
|
||
function weeks () {
|
||
return absFloor(this.days() / 7);
|
||
}
|
||
|
||
var round = Math.round;
|
||
var thresholds = {
|
||
s: 45, // seconds to minute
|
||
m: 45, // minutes to hour
|
||
h: 22, // hours to day
|
||
d: 26, // days to month
|
||
M: 11 // months to year
|
||
};
|
||
|
||
// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
|
||
function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
|
||
return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
|
||
}
|
||
|
||
function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) {
|
||
var duration = create__createDuration(posNegDuration).abs();
|
||
var seconds = round(duration.as('s'));
|
||
var minutes = round(duration.as('m'));
|
||
var hours = round(duration.as('h'));
|
||
var days = round(duration.as('d'));
|
||
var months = round(duration.as('M'));
|
||
var years = round(duration.as('y'));
|
||
|
||
var a = seconds < thresholds.s && ['s', seconds] ||
|
||
minutes <= 1 && ['m'] ||
|
||
minutes < thresholds.m && ['mm', minutes] ||
|
||
hours <= 1 && ['h'] ||
|
||
hours < thresholds.h && ['hh', hours] ||
|
||
days <= 1 && ['d'] ||
|
||
days < thresholds.d && ['dd', days] ||
|
||
months <= 1 && ['M'] ||
|
||
months < thresholds.M && ['MM', months] ||
|
||
years <= 1 && ['y'] || ['yy', years];
|
||
|
||
a[2] = withoutSuffix;
|
||
a[3] = +posNegDuration > 0;
|
||
a[4] = locale;
|
||
return substituteTimeAgo.apply(null, a);
|
||
}
|
||
|
||
// This function allows you to set a threshold for relative time strings
|
||
function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) {
|
||
if (thresholds[threshold] === undefined) {
|
||
return false;
|
||
}
|
||
if (limit === undefined) {
|
||
return thresholds[threshold];
|
||
}
|
||
thresholds[threshold] = limit;
|
||
return true;
|
||
}
|
||
|
||
function humanize (withSuffix) {
|
||
var locale = this.localeData();
|
||
var output = duration_humanize__relativeTime(this, !withSuffix, locale);
|
||
|
||
if (withSuffix) {
|
||
output = locale.pastFuture(+this, output);
|
||
}
|
||
|
||
return locale.postformat(output);
|
||
}
|
||
|
||
var iso_string__abs = Math.abs;
|
||
|
||
function iso_string__toISOString() {
|
||
// for ISO strings we do not use the normal bubbling rules:
|
||
// * milliseconds bubble up until they become hours
|
||
// * days do not bubble at all
|
||
// * months bubble up until they become years
|
||
// This is because there is no context-free conversion between hours and days
|
||
// (think of clock changes)
|
||
// and also not between days and months (28-31 days per month)
|
||
var seconds = iso_string__abs(this._milliseconds) / 1000;
|
||
var days = iso_string__abs(this._days);
|
||
var months = iso_string__abs(this._months);
|
||
var minutes, hours, years;
|
||
|
||
// 3600 seconds -> 60 minutes -> 1 hour
|
||
minutes = absFloor(seconds / 60);
|
||
hours = absFloor(minutes / 60);
|
||
seconds %= 60;
|
||
minutes %= 60;
|
||
|
||
// 12 months -> 1 year
|
||
years = absFloor(months / 12);
|
||
months %= 12;
|
||
|
||
|
||
// inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
|
||
var Y = years;
|
||
var M = months;
|
||
var D = days;
|
||
var h = hours;
|
||
var m = minutes;
|
||
var s = seconds;
|
||
var total = this.asSeconds();
|
||
|
||
if (!total) {
|
||
// this is the same as C#'s (Noda) and python (isodate)...
|
||
// but not other JS (goog.date)
|
||
return 'P0D';
|
||
}
|
||
|
||
return (total < 0 ? '-' : '') +
|
||
'P' +
|
||
(Y ? Y + 'Y' : '') +
|
||
(M ? M + 'M' : '') +
|
||
(D ? D + 'D' : '') +
|
||
((h || m || s) ? 'T' : '') +
|
||
(h ? h + 'H' : '') +
|
||
(m ? m + 'M' : '') +
|
||
(s ? s + 'S' : '');
|
||
}
|
||
|
||
var duration_prototype__proto = Duration.prototype;
|
||
|
||
duration_prototype__proto.abs = duration_abs__abs;
|
||
duration_prototype__proto.add = duration_add_subtract__add;
|
||
duration_prototype__proto.subtract = duration_add_subtract__subtract;
|
||
duration_prototype__proto.as = as;
|
||
duration_prototype__proto.asMilliseconds = asMilliseconds;
|
||
duration_prototype__proto.asSeconds = asSeconds;
|
||
duration_prototype__proto.asMinutes = asMinutes;
|
||
duration_prototype__proto.asHours = asHours;
|
||
duration_prototype__proto.asDays = asDays;
|
||
duration_prototype__proto.asWeeks = asWeeks;
|
||
duration_prototype__proto.asMonths = asMonths;
|
||
duration_prototype__proto.asYears = asYears;
|
||
duration_prototype__proto.valueOf = duration_as__valueOf;
|
||
duration_prototype__proto._bubble = bubble;
|
||
duration_prototype__proto.get = duration_get__get;
|
||
duration_prototype__proto.milliseconds = milliseconds;
|
||
duration_prototype__proto.seconds = seconds;
|
||
duration_prototype__proto.minutes = minutes;
|
||
duration_prototype__proto.hours = hours;
|
||
duration_prototype__proto.days = days;
|
||
duration_prototype__proto.weeks = weeks;
|
||
duration_prototype__proto.months = months;
|
||
duration_prototype__proto.years = years;
|
||
duration_prototype__proto.humanize = humanize;
|
||
duration_prototype__proto.toISOString = iso_string__toISOString;
|
||
duration_prototype__proto.toString = iso_string__toISOString;
|
||
duration_prototype__proto.toJSON = iso_string__toISOString;
|
||
duration_prototype__proto.locale = locale;
|
||
duration_prototype__proto.localeData = localeData;
|
||
|
||
// Deprecations
|
||
duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString);
|
||
duration_prototype__proto.lang = lang;
|
||
|
||
// Side effect imports
|
||
|
||
// FORMATTING
|
||
|
||
addFormatToken('X', 0, 0, 'unix');
|
||
addFormatToken('x', 0, 0, 'valueOf');
|
||
|
||
// PARSING
|
||
|
||
addRegexToken('x', matchSigned);
|
||
addRegexToken('X', matchTimestamp);
|
||
addParseToken('X', function (input, array, config) {
|
||
config._d = new Date(parseFloat(input, 10) * 1000);
|
||
});
|
||
addParseToken('x', function (input, array, config) {
|
||
config._d = new Date(toInt(input));
|
||
});
|
||
|
||
// Side effect imports
|
||
|
||
|
||
utils_hooks__hooks.version = '2.11.1';
|
||
|
||
setHookCallback(local__createLocal);
|
||
|
||
utils_hooks__hooks.fn = momentPrototype;
|
||
utils_hooks__hooks.min = min;
|
||
utils_hooks__hooks.max = max;
|
||
utils_hooks__hooks.now = now;
|
||
utils_hooks__hooks.utc = create_utc__createUTC;
|
||
utils_hooks__hooks.unix = moment__createUnix;
|
||
utils_hooks__hooks.months = lists__listMonths;
|
||
utils_hooks__hooks.isDate = isDate;
|
||
utils_hooks__hooks.locale = locale_locales__getSetGlobalLocale;
|
||
utils_hooks__hooks.invalid = valid__createInvalid;
|
||
utils_hooks__hooks.duration = create__createDuration;
|
||
utils_hooks__hooks.isMoment = isMoment;
|
||
utils_hooks__hooks.weekdays = lists__listWeekdays;
|
||
utils_hooks__hooks.parseZone = moment__createInZone;
|
||
utils_hooks__hooks.localeData = locale_locales__getLocale;
|
||
utils_hooks__hooks.isDuration = isDuration;
|
||
utils_hooks__hooks.monthsShort = lists__listMonthsShort;
|
||
utils_hooks__hooks.weekdaysMin = lists__listWeekdaysMin;
|
||
utils_hooks__hooks.defineLocale = defineLocale;
|
||
utils_hooks__hooks.weekdaysShort = lists__listWeekdaysShort;
|
||
utils_hooks__hooks.normalizeUnits = normalizeUnits;
|
||
utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold;
|
||
utils_hooks__hooks.prototype = momentPrototype;
|
||
|
||
var _moment = utils_hooks__hooks;
|
||
|
||
return _moment;
|
||
|
||
}));
|
||
},{}],106:[function(require,module,exports){
|
||
module.exports={
|
||
"name": "mermaid",
|
||
"version": "0.5.8",
|
||
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams and gantt charts.",
|
||
"main": "src/mermaid.js",
|
||
"keywords": [
|
||
"diagram",
|
||
"markdown",
|
||
"flowchart",
|
||
"sequence diagram",
|
||
"gantt"
|
||
],
|
||
"bin": {
|
||
"mermaid": "./bin/mermaid.js"
|
||
},
|
||
"scripts": {
|
||
"live": "live-server ./test/examples",
|
||
"lint": "node node_modules/eslint/bin/eslint.js src",
|
||
"jison": "gulp jison_legacy",
|
||
"karma": "node node_modules/karma/bin/karma start karma.conf.js --single-run",
|
||
"watch": "source ./scripts/watch.sh",
|
||
"doc": "rm -r build;rm -r dist/www;gulp vartree;cp dist/www/all.html ../mermaid-pages/index.html;cp dist/mermaid.js ../mermaid-pages/javascripts/lib;cp dist/mermaid.forest.css ../mermaid-pages/stylesheets",
|
||
"tape": "node node_modules/tape/bin/tape test/cli_test-*.js",
|
||
"jasmine": "npm run jison &&node node_modules/jasmine-es6/bin/jasmine.js",
|
||
"pretest": "npm run jison",
|
||
"test": "npm run dist && npm run karma && npm run tape",
|
||
"dist-slim-mermaid": "node node_modules/browserify/bin/cmd.js src/mermaid.js -t babelify -s mermaid -o dist/mermaid.slim.js -x d3 && cat dist/mermaid.slim.js | node node_modules/uglifyjs/bin/uglifyjs -mc > dist/mermaid.slim.min.js",
|
||
"dist-slim-mermaidAPI": "node node_modules/browserify/bin/cmd.js src/mermaidAPI.js -t babelify -s mermaidAPI -o dist/mermaidAPI.slim.js -x d3 && cat dist/mermaidAPI.slim.js | node node_modules/uglifyjs/bin/uglifyjs -mc > dist/mermaidAPI.slim.min.js",
|
||
"dist-mermaid": "node node_modules/browserify/bin/cmd.js src/mermaid.js -t babelify -s mermaid -o dist/mermaid.js && cat dist/mermaid.js | node node_modules/uglifyjs/bin/uglifyjs -mc > dist/mermaid.min.js",
|
||
"dist-mermaidAPI": "node node_modules/browserify/bin/cmd.js src/mermaidAPI.js -t babelify -s mermaidAPI -o dist/mermaidAPI.js && cat dist/mermaidAPI.js | node node_modules/uglifyjs/bin/uglifyjs -mc > dist/mermaidAPI.min.js",
|
||
"dist": "npm run dist-slim-mermaid && npm run dist-slim-mermaidAPI && npm run dist-mermaid && npm run dist-mermaidAPI"
|
||
},
|
||
"repository": {
|
||
"type": "git",
|
||
"url": "https://github.com/knsv/mermaid"
|
||
},
|
||
"author": "Knut Sveidqvist",
|
||
"license": "MIT",
|
||
"dependencies": {
|
||
"chalk": "^0.5.1",
|
||
"d3": "3.5.6",
|
||
"dagre": "^0.7.4",
|
||
"dagre-d3": "0.4.10",
|
||
"he": "^0.5.0",
|
||
"minimist": "^1.1.0",
|
||
"mkdirp": "^0.5.0",
|
||
"moment": "^2.9.0",
|
||
"semver": "^4.1.1",
|
||
"which": "^1.0.8"
|
||
},
|
||
"devDependencies": {
|
||
"async": "^0.9.0",
|
||
"babel-eslint": "^4.1.3",
|
||
"babelify": "^6.4.0",
|
||
"browserify": "~6.2.0",
|
||
"clone": "^0.2.0",
|
||
"codeclimate-test-reporter": "0.0.4",
|
||
"dateformat": "^1.0.11",
|
||
"dox": "^0.8.0",
|
||
"eslint": "^1.6.0",
|
||
"eslint-watch": "^2.1.2",
|
||
"event-stream": "^3.2.0",
|
||
"foundation": "^4.2.1-1",
|
||
"front-matter": "^0.2.0",
|
||
"gulp": "~3.9.0",
|
||
"gulp-bower": "0.0.10",
|
||
"gulp-browserify": "^0.5.0",
|
||
"gulp-bump": "^0.1.11",
|
||
"gulp-concat": "~2.4.1",
|
||
"gulp-data": "^1.1.1",
|
||
"gulp-dox": "^0.1.6",
|
||
"gulp-ext-replace": "^0.2.0",
|
||
"gulp-filelog": "^0.4.1",
|
||
"gulp-front-matter": "^1.2.3",
|
||
"gulp-hogan": "^1.1.0",
|
||
"gulp-if": "^1.2.5",
|
||
"gulp-insert": "^0.4.0",
|
||
"gulp-istanbul": "^0.4.0",
|
||
"gulp-jasmine": "~2.1.0",
|
||
"gulp-jasmine-browser": "^0.2.3",
|
||
"gulp-jison": "~1.2.0",
|
||
"gulp-jshint": "^1.9.0",
|
||
"gulp-less": "^3.0.1",
|
||
"gulp-livereload": "^3.8.0",
|
||
"gulp-marked": "^1.0.0",
|
||
"gulp-mdvars": "^2.0.0",
|
||
"gulp-qunit": "~1.2.1",
|
||
"gulp-rename": "~1.2.0",
|
||
"gulp-shell": "^0.2.10",
|
||
"gulp-tag-version": "^1.2.1",
|
||
"gulp-uglify": "~1.0.1",
|
||
"gulp-util": "^3.0.7",
|
||
"gulp-vartree": "^2.0.1",
|
||
"hogan.js": "^3.0.2",
|
||
"jasmine": "2.3.2",
|
||
"jasmine-es6": "0.0.18",
|
||
"jison": "zaach/jison",
|
||
"jsdom": "^7.0.2",
|
||
"jshint-stylish": "^2.0.1",
|
||
"karma": "^0.13.15",
|
||
"karma-babel-preprocessor": "^6.0.1",
|
||
"karma-browserify": "^4.4.0",
|
||
"karma-jasmine": "^0.3.6",
|
||
"karma-phantomjs-launcher": "^0.2.1",
|
||
"live-server": "^0.9.0",
|
||
"map-stream": "0.0.6",
|
||
"marked": "^0.3.2",
|
||
"mock-browser": "^0.91.34",
|
||
"path": "^0.4.9",
|
||
"phantomjs": "^1.9.18",
|
||
"proxyquire": "^1.7.3",
|
||
"proxyquire-universal": "^1.0.8",
|
||
"proxyquireify": "^3.0.0",
|
||
"require-dir": "^0.3.0",
|
||
"rewire": "^2.1.3",
|
||
"rimraf": "^2.2.8",
|
||
"tape": "^3.0.3",
|
||
"testdom": "^2.0.0",
|
||
"uglifyjs": "^2.4.10",
|
||
"vinyl-source-stream": "^1.1.0",
|
||
"watchify": "^3.6.1"
|
||
}
|
||
}
|
||
|
||
},{}],107:[function(require,module,exports){
|
||
/* global window */
|
||
//log.debug('Setting up d3');
|
||
'use strict';
|
||
|
||
var d3;
|
||
|
||
if (require) {
|
||
try {
|
||
d3 = require('d3');
|
||
} catch (e) {
|
||
//log.debug('Exception ... but ok');
|
||
//log.debug(e);
|
||
}
|
||
}
|
||
|
||
//log.debug(d3);
|
||
|
||
if (!d3) {
|
||
//if(typeof window !== 'undefined')
|
||
d3 = window.d3;
|
||
}
|
||
|
||
//if(typeof window === 'undefined'){
|
||
// window = {};
|
||
// window.d3 = d3;
|
||
//}
|
||
//log.debug('window');
|
||
//log.debug(window);
|
||
module.exports = d3;
|
||
/* jshint ignore:start */
|
||
/*
|
||
|
||
D3 Text Wrap
|
||
By Vijith Assar
|
||
http://www.vijithassar.com
|
||
http://www.github.com/vijithassar
|
||
@vijithassar
|
||
|
||
Detailed instructions at http://www.github.com/vijithassar/d3textwrap
|
||
|
||
*/
|
||
|
||
(function () {
|
||
|
||
// set this variable to a string value to always force a particular
|
||
// wrap method for development purposes, for example to check tspan
|
||
// rendering using a foreignobject-enabled browser. set to 'tspan' to
|
||
// use tspans and 'foreignobject' to use foreignobject
|
||
var force_wrap_method = false; // by default no wrap method is forced
|
||
force_wrap_method = 'tspans'; // uncomment this statement to force tspans
|
||
// force_wrap_method = 'foreignobjects'; // uncomment this statement to force foreignobjects
|
||
|
||
// exit immediately if something in this location
|
||
// has already been defined; the plugin will defer to whatever
|
||
// else you're doing in your code
|
||
if (d3.selection.prototype.textwrap) {
|
||
return false;
|
||
}
|
||
|
||
// double check the force_wrap_method flag
|
||
// and reset if someone screwed up the above
|
||
// settings
|
||
if (typeof force_wrap_method == 'undefined') {
|
||
var force_wrap_method = false;
|
||
}
|
||
|
||
// create the plugin method twice, both for regular use
|
||
// and again for use inside the enter() selection
|
||
d3.selection.prototype.textwrap = d3.selection.enter.prototype.textwrap = function (bounds, padding) {
|
||
|
||
// default value of padding is zero if it's undefined
|
||
var padding = parseInt(padding) || 0;
|
||
|
||
// save callee into a variable so we can continue to refer to it
|
||
// as the function scope changes
|
||
var selection = this;
|
||
|
||
// create a variable to store desired return values in
|
||
var return_value;
|
||
|
||
// extract wrap boundaries from any d3-selected rect and return them
|
||
// in a format that matches the simpler object argument option
|
||
var extract_bounds = function extract_bounds(bounds) {
|
||
// discard the nested array wrappers added by d3
|
||
var bounding_rect = bounds[0][0];
|
||
// sanitize the svg element name so we can test against it
|
||
var element_type = bounding_rect.tagName.toString();
|
||
// if it's not a rect, exit
|
||
if (element_type !== 'rect') {
|
||
return false;
|
||
// if it's a rect, proceed to extracting the position attributes
|
||
} else {
|
||
var bounds_extracted = {};
|
||
bounds_extracted.x = d3.select(bounding_rect).attr('x') || 0;
|
||
bounds_extracted.y = d3.select(bounding_rect).attr('y') || 0;
|
||
bounds_extracted.width = d3.select(bounding_rect).attr('width') || 0;
|
||
bounds_extracted.height = d3.select(bounding_rect).attr('height') || 0;
|
||
// also pass along the getter function
|
||
bounds_extracted.attr = bounds.attr;
|
||
}
|
||
return bounds_extracted;
|
||
};
|
||
|
||
// double check the input argument for the wrapping
|
||
// boundaries to make sure it actually contains all
|
||
// the information we'll need in order to wrap successfully
|
||
var verify_bounds = function verify_bounds(bounds) {
|
||
// quickly add a simple getter method so you can use either
|
||
// bounds.x or bounds.attr('x') as your notation,
|
||
// the latter being a common convention among D3
|
||
// developers
|
||
if (!bounds.attr) {
|
||
bounds.attr = function (property) {
|
||
if (this[property]) {
|
||
return this[property];
|
||
}
|
||
};
|
||
}
|
||
// if it's an associative array, make sure it has all the
|
||
// necessary properties represented directly
|
||
if (typeof bounds == 'object' && typeof bounds.x !== 'undefined' && typeof bounds.y !== 'undefined' && typeof bounds.width !== 'undefined' && typeof bounds.height !== 'undefined'
|
||
// if that's the case, then the bounds are fine
|
||
) {
|
||
// return the lightly modified bounds
|
||
return bounds;
|
||
// if it's a numerically indexed array, assume it's a
|
||
// d3-selected rect and try to extract the positions
|
||
} else if (
|
||
// first try to make sure it's an array using Array.isArray
|
||
typeof Array.isArray == 'function' && Array.isArray(bounds) ||
|
||
// but since Array.isArray isn't always supported, fall
|
||
// back to casting to the object to string when it's not
|
||
Object.prototype.toString.call(bounds) === '[object Array]') {
|
||
// once you're sure it's an array, extract the boundaries
|
||
// from the rect
|
||
var extracted_bounds = extract_bounds(bounds);
|
||
return extracted_bounds;
|
||
} else {
|
||
// but if the bounds are neither an object nor a numerical
|
||
// array, then the bounds argument is invalid and you'll
|
||
// need to fix it
|
||
return false;
|
||
}
|
||
};
|
||
|
||
var apply_padding = function apply_padding(bounds, padding) {
|
||
var padded_bounds = bounds;
|
||
if (padding !== 0) {
|
||
padded_bounds.x = parseInt(padded_bounds.x) + padding;
|
||
padded_bounds.y = parseInt(padded_bounds.y) + padding;
|
||
padded_bounds.width -= padding * 2;
|
||
padded_bounds.height -= padding * 2;
|
||
}
|
||
return padded_bounds;
|
||
};
|
||
|
||
// verify bounds
|
||
var verified_bounds = verify_bounds(bounds);
|
||
|
||
// modify bounds if a padding value is provided
|
||
if (padding) {
|
||
verified_bounds = apply_padding(verified_bounds, padding);
|
||
}
|
||
|
||
// check that we have the necessary conditions for this function to operate properly
|
||
if (
|
||
// selection it's operating on cannot be not empty
|
||
selection.length == 0 ||
|
||
// d3 must be available
|
||
!d3 ||
|
||
// desired wrapping bounds must be provided as an input argument
|
||
!bounds ||
|
||
// input bounds must validate
|
||
!verified_bounds) {
|
||
// try to return the calling selection if possible
|
||
// so as not to interfere with methods downstream in the
|
||
// chain
|
||
if (selection) {
|
||
return selection;
|
||
// if all else fails, just return false. if you hit this point then you're
|
||
// almost certainly trying to call the textwrap() method on something that
|
||
// doesn't make sense!
|
||
} else {
|
||
return false;
|
||
}
|
||
// if we've validated everything then we can finally proceed
|
||
// to the meat of this operation
|
||
} else {
|
||
|
||
// reassign the verified bounds as the set we want
|
||
// to work with from here on; this ensures that we're
|
||
// using the same data structure for our bounds regardless
|
||
// of whether the input argument was a simple object or
|
||
// a d3 selection
|
||
bounds = verified_bounds;
|
||
|
||
// wrap using html and foreignObjects if they are supported
|
||
var wrap_with_foreignobjects = function wrap_with_foreignobjects(item) {
|
||
// establish variables to quickly reference target nodes later
|
||
var parent = d3.select(item[0].parentNode);
|
||
var text_node = parent.select('text');
|
||
var styled_line_height = text_node.style('line-height');
|
||
// extract our desired content from the single text element
|
||
var text_to_wrap = text_node.text();
|
||
// remove the text node and replace with a foreign object
|
||
text_node.remove();
|
||
var foreign_object = parent.append('foreignObject');
|
||
// add foreign object and set dimensions, position, etc
|
||
foreign_object.attr('requiredFeatures', 'http://www.w3.org/TR/SVG11/feature#Extensibility').attr('x', bounds.x).attr('y', bounds.y).attr('width', bounds.width).attr('height', bounds.height);
|
||
// insert an HTML div
|
||
var wrap_div = foreign_object.append('xhtml:div')
|
||
// this class is currently hardcoded
|
||
// probably not necessary but easy to
|
||
// override using .classed() and for now
|
||
// it's nice to avoid a litany of input
|
||
// arguments
|
||
.attr('class', 'wrapped');
|
||
// set div to same dimensions as foreign object
|
||
wrap_div.style('height', bounds.height).style('width', bounds.width)
|
||
// insert text content
|
||
.html(text_to_wrap);
|
||
if (styled_line_height) {
|
||
wrap_div.style('line-height', styled_line_height);
|
||
}
|
||
return_value = parent.select('foreignObject');
|
||
};
|
||
|
||
// wrap with tspans if foreignObject is undefined
|
||
var wrap_with_tspans = function wrap_with_tspans(item) {
|
||
// operate on the first text item in the selection
|
||
var text_node = item[0];
|
||
var parent = text_node.parentNode;
|
||
var text_node_selected = d3.select(text_node);
|
||
// measure initial size of the text node as rendered
|
||
var text_node_height = text_node.getBBox().height;
|
||
var text_node_width = text_node.getBBox().width;
|
||
// figure out the line height, either from rendered height
|
||
// of the font or attached styling
|
||
var line_height;
|
||
var rendered_line_height = text_node_height;
|
||
var styled_line_height = text_node_selected.style('line-height');
|
||
if (styled_line_height && parseInt(styled_line_height)) {
|
||
line_height = parseInt(styled_line_height.replace('px', ''));
|
||
} else {
|
||
line_height = rendered_line_height;
|
||
}
|
||
// only fire the rest of this if the text content
|
||
// overflows the desired dimensions
|
||
if (text_node_width > bounds.width) {
|
||
// store whatever is inside the text node
|
||
// in a variable and then zero out the
|
||
// initial content; we'll reinsert in a moment
|
||
// using tspan elements.
|
||
var text_to_wrap = text_node_selected.text();
|
||
text_node_selected.text('');
|
||
if (text_to_wrap) {
|
||
// keep track of whether we are splitting by spaces
|
||
// so we know whether to reinsert those spaces later
|
||
var break_delimiter;
|
||
// split at spaces to create an array of individual words
|
||
var text_to_wrap_array;
|
||
if (text_to_wrap.indexOf(' ') !== -1) {
|
||
var break_delimiter = ' ';
|
||
text_to_wrap_array = text_to_wrap.split(' ');
|
||
} else {
|
||
// if there are no spaces, figure out the split
|
||
// points by comparing rendered text width against
|
||
// bounds and translating that into character position
|
||
// cuts
|
||
break_delimiter = '';
|
||
var string_length = text_to_wrap.length;
|
||
var number_of_substrings = Math.ceil(text_node_width / bounds.width);
|
||
var splice_interval = Math.floor(string_length / number_of_substrings);
|
||
if (!(splice_interval * number_of_substrings >= string_length)) {
|
||
number_of_substrings++;
|
||
}
|
||
var text_to_wrap_array = [];
|
||
var substring;
|
||
var start_position;
|
||
for (var i = 0; i < number_of_substrings; i++) {
|
||
start_position = i * splice_interval;
|
||
substring = text_to_wrap.substr(start_position, splice_interval);
|
||
text_to_wrap_array.push(substring);
|
||
}
|
||
}
|
||
|
||
// new array where we'll store the words re-assembled into
|
||
// substrings that have been tested against the desired
|
||
// maximum wrapping width
|
||
var substrings = [];
|
||
// computed text length is arguably incorrectly reported for
|
||
// all tspans after the first one, in that they will include
|
||
// the width of previous separate tspans. to compensate we need
|
||
// to manually track the computed text length of all those
|
||
// previous tspans and substrings, and then use that to offset
|
||
// the miscalculation. this then gives us the actual correct
|
||
// position we want to use in rendering the text in the SVG.
|
||
var total_offset = 0;
|
||
// object for storing the results of text length computations later
|
||
var temp = {};
|
||
// loop through the words and test the computed text length
|
||
// of the string against the maximum desired wrapping width
|
||
for (var i = 0; i < text_to_wrap_array.length; i++) {
|
||
var word = text_to_wrap_array[i];
|
||
var previous_string = text_node_selected.text();
|
||
var previous_width = text_node.getComputedTextLength();
|
||
// initialize the current word as the first word
|
||
// or append to the previous string if one exists
|
||
var new_string;
|
||
if (previous_string) {
|
||
new_string = previous_string + break_delimiter + word;
|
||
} else {
|
||
new_string = word;
|
||
}
|
||
// add the newest substring back to the text node and
|
||
// measure the length
|
||
text_node_selected.text(new_string);
|
||
var new_width = text_node.getComputedTextLength();
|
||
// adjust the length by the offset we've tracked
|
||
// due to the misreported length discussed above
|
||
var test_width = new_width - total_offset;
|
||
// if our latest version of the string is too
|
||
// big for the bounds, use the previous
|
||
// version of the string (without the newest word
|
||
// added) and use the latest word to restart the
|
||
// process with a new tspan
|
||
if (new_width > bounds.width) {
|
||
if (previous_string && previous_string !== '') {
|
||
total_offset = total_offset + previous_width;
|
||
temp = { string: previous_string, width: previous_width, offset: total_offset };
|
||
substrings.push(temp);
|
||
text_node_selected.text('');
|
||
text_node_selected.text(word);
|
||
// Handle case where there is just one more word to be wrapped
|
||
if (i == text_to_wrap_array.length - 1) {
|
||
new_string = word;
|
||
text_node_selected.text(new_string);
|
||
new_width = text_node.getComputedTextLength();
|
||
}
|
||
}
|
||
}
|
||
// if we're up to the last word in the array,
|
||
// get the computed length as is without
|
||
// appending anything further to it
|
||
if (i == text_to_wrap_array.length - 1) {
|
||
text_node_selected.text('');
|
||
var final_string = new_string;
|
||
if (final_string && final_string !== '') {
|
||
if (new_width - total_offset > 0) {
|
||
new_width = new_width - total_offset;
|
||
}
|
||
temp = { string: final_string, width: new_width, offset: total_offset };
|
||
substrings.push(temp);
|
||
}
|
||
}
|
||
}
|
||
|
||
// append each substring as a tspan
|
||
var current_tspan;
|
||
var tspan_count;
|
||
// double check that the text content has been removed
|
||
// before we start appending tspans
|
||
text_node_selected.text('');
|
||
for (var i = 0; i < substrings.length; i++) {
|
||
var substring = substrings[i].string;
|
||
if (i > 0) {
|
||
var previous_substring = substrings[i - 1];
|
||
}
|
||
// only append if we're sure it won't make the tspans
|
||
// overflow the bounds.
|
||
if (i * line_height < bounds.height - line_height * 1.5) {
|
||
current_tspan = text_node_selected.append('tspan').text(substring);
|
||
// vertical shift to all tspans after the first one
|
||
current_tspan.attr('dy', function (d) {
|
||
if (i > 0) {
|
||
return line_height;
|
||
}
|
||
});
|
||
// shift left from default position, which
|
||
// is probably based on the full length of the
|
||
// text string until we make this adjustment
|
||
current_tspan.attr('x', function () {
|
||
var x_offset = bounds.x;
|
||
if (padding) {
|
||
x_offset += padding;
|
||
}
|
||
return x_offset;
|
||
});
|
||
// .attr('dx', function() {
|
||
// if(i == 0) {
|
||
// var render_offset = 0;
|
||
// } else if(i > 0) {
|
||
// render_offset = substrings[i - 1].width;
|
||
// render_offset = render_offset * -1;
|
||
// }
|
||
// return render_offset;
|
||
// });
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// position the overall text node, whether wrapped or not
|
||
text_node_selected.attr('y', function () {
|
||
var y_offset = bounds.y;
|
||
// shift by line-height to move the baseline into
|
||
// the bounds – otherwise the text baseline would be
|
||
// at the top of the bounds
|
||
if (line_height) {
|
||
y_offset += line_height;
|
||
}
|
||
// shift by padding, if it's there
|
||
if (padding) {
|
||
y_offset += padding;
|
||
}
|
||
return y_offset;
|
||
});
|
||
// shift to the right by the padding value
|
||
text_node_selected.attr('x', function () {
|
||
var x_offset = bounds.x;
|
||
if (padding) {
|
||
x_offset += padding;
|
||
}
|
||
return x_offset;
|
||
});
|
||
|
||
// assign our modified text node with tspans
|
||
// to the return value
|
||
return_value = d3.select(parent).selectAll('text');
|
||
};
|
||
|
||
// variable used to hold the functions that let us
|
||
// switch between the wrap methods
|
||
var wrap_method;
|
||
|
||
// if a wrap method if being forced, assign that
|
||
// function
|
||
if (force_wrap_method) {
|
||
if (force_wrap_method == 'foreignobjects') {
|
||
wrap_method = wrap_with_foreignobjects;
|
||
} else if (force_wrap_method == 'tspans') {
|
||
wrap_method = wrap_with_tspans;
|
||
}
|
||
}
|
||
|
||
// if no wrap method is being forced, then instead
|
||
// test for browser support of foreignobject and
|
||
// use whichever wrap method makes sense accordingly
|
||
if (!force_wrap_method) {
|
||
if (typeof SVGForeignObjectElement !== 'undefined') {
|
||
wrap_method = wrap_with_foreignobjects;
|
||
} else {
|
||
wrap_method = wrap_with_tspans;
|
||
}
|
||
}
|
||
|
||
// run the desired wrap function for each item
|
||
// in the d3 selection that called .textwrap()
|
||
for (var i = 0; i < selection.length; i++) {
|
||
var item = selection[i];
|
||
wrap_method(item);
|
||
}
|
||
|
||
// return the modified nodes so we can chain other
|
||
// methods to them.
|
||
return return_value;
|
||
}
|
||
};
|
||
})();
|
||
/* jshint ignore:end */
|
||
|
||
},{"d3":4}],108:[function(require,module,exports){
|
||
'use strict';
|
||
|
||
var Logger = require('../../logger');
|
||
var log = new Logger.Log();
|
||
|
||
var relations = [];
|
||
|
||
var classes;
|
||
var idCache;
|
||
classes = {};
|
||
|
||
// Functions to be run after graph rendering
|
||
var funs = [];
|
||
/**
|
||
* Function called by parser when a node definition has been found.
|
||
* @param id
|
||
* @param text
|
||
* @param type
|
||
* @param style
|
||
*/
|
||
exports.addClass = function (id) {
|
||
if (typeof classes[id] === 'undefined') {
|
||
classes[id] = {
|
||
id: id,
|
||
methods: [],
|
||
members: []
|
||
};
|
||
}
|
||
};
|
||
|
||
exports.clear = function () {
|
||
relations = [];
|
||
classes = {};
|
||
};
|
||
|
||
module.exports.getClass = function (id) {
|
||
return classes[id];
|
||
};
|
||
module.exports.getClasses = function () {
|
||
return classes;
|
||
};
|
||
|
||
module.exports.getRelations = function () {
|
||
return relations;
|
||
};
|
||
|
||
exports.addRelation = function (relation) {
|
||
log.warn('Adding relation: ' + JSON.stringify(relation));
|
||
exports.addClass(relation.id1);
|
||
exports.addClass(relation.id2);
|
||
|
||
relations.push(relation);
|
||
};
|
||
|
||
exports.addMembers = function (className, MembersArr) {
|
||
var theClass = classes[className];
|
||
if (typeof MembersArr === 'string') {
|
||
if (MembersArr.substr(-1) === ')') {
|
||
theClass.methods.push(MembersArr);
|
||
} else {
|
||
theClass.members.push(MembersArr);
|
||
}
|
||
}
|
||
};
|
||
|
||
exports.cleanupLabel = function (label) {
|
||
|
||
if (label.substring(0, 1) === ':') {
|
||
return label.substr(2).trim();
|
||
} else {
|
||
return label.trim();
|
||
}
|
||
};
|
||
|
||
exports.lineType = {
|
||
LINE: 0,
|
||
DOTTED_LINE: 1
|
||
};
|
||
|
||
exports.relationType = {
|
||
AGGREGATION: 0,
|
||
EXTENSION: 1,
|
||
COMPOSITION: 2,
|
||
DEPENDENCY: 3
|
||
};
|
||
|
||
},{"../../logger":126}],109:[function(require,module,exports){
|
||
/**
|
||
* Created by knut on 14-11-23.
|
||
*/
|
||
|
||
'use strict';
|
||
|
||
var cd = require('./parser/classDiagram').parser;
|
||
var cDDb = require('./classDb');
|
||
cd.yy = cDDb;
|
||
var d3 = require('../../d3');
|
||
var Logger = require('../../logger');
|
||
var dagre = require('dagre');
|
||
var log = new Logger.Log();
|
||
|
||
var idCache;
|
||
idCache = {};
|
||
|
||
var classCnt = 0;
|
||
var conf = {
|
||
dividerMargin: 10,
|
||
padding: 5,
|
||
textHeight: 14
|
||
};
|
||
|
||
// Todo optimize
|
||
var getGraphId = function getGraphId(label) {
|
||
var keys = Object.keys(idCache);
|
||
|
||
var i;
|
||
for (i = 0; i < keys.length; i++) {
|
||
if (idCache[keys[i]].label === label) {
|
||
return keys[i];
|
||
}
|
||
}
|
||
|
||
return undefined;
|
||
};
|
||
|
||
/**
|
||
* Setup arrow head and define the marker. The result is appended to the svg.
|
||
*/
|
||
var insertMarkers = function insertMarkers(elem) {
|
||
elem.append('defs').append('marker').attr('id', 'extensionStart').attr('class', 'extension').attr('refX', 0).attr('refY', 7).attr('markerWidth', 190).attr('markerHeight', 240).attr('orient', 'auto').append('path').attr('d', 'M 1,7 L18,13 V 1 Z');
|
||
|
||
elem.append('defs').append('marker').attr('id', 'extensionEnd').attr('refX', 19).attr('refY', 7).attr('markerWidth', 20).attr('markerHeight', 28).attr('orient', 'auto').append('path').attr('d', 'M 1,1 V 13 L18,7 Z'); //this is actual shape for arrowhead
|
||
|
||
elem.append('defs').append('marker').attr('id', 'compositionStart').attr('class', 'extension').attr('refX', 0).attr('refY', 7).attr('markerWidth', 190).attr('markerHeight', 240).attr('orient', 'auto').append('path').attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z');
|
||
|
||
elem.append('defs').append('marker').attr('id', 'compositionEnd').attr('refX', 19).attr('refY', 7).attr('markerWidth', 20).attr('markerHeight', 28).attr('orient', 'auto').append('path').attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z');
|
||
|
||
elem.append('defs').append('marker').attr('id', 'aggregationStart').attr('class', 'extension').attr('refX', 0).attr('refY', 7).attr('markerWidth', 190).attr('markerHeight', 240).attr('orient', 'auto').append('path').attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z');
|
||
|
||
elem.append('defs').append('marker').attr('id', 'aggregationEnd').attr('refX', 19).attr('refY', 7).attr('markerWidth', 20).attr('markerHeight', 28).attr('orient', 'auto').append('path').attr('d', 'M 18,7 L9,13 L1,7 L9,1 Z');
|
||
|
||
elem.append('defs').append('marker').attr('id', 'dependencyStart').attr('class', 'extension').attr('refX', 0).attr('refY', 7).attr('markerWidth', 190).attr('markerHeight', 240).attr('orient', 'auto').append('path').attr('d', 'M 5,7 L9,13 L1,7 L9,1 Z');
|
||
|
||
elem.append('defs').append('marker').attr('id', 'dependencyEnd').attr('refX', 19).attr('refY', 7).attr('markerWidth', 20).attr('markerHeight', 28).attr('orient', 'auto').append('path').attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z');
|
||
};
|
||
|
||
var edgeCount = 0;
|
||
var drawEdge = function drawEdge(elem, path, relation) {
|
||
var getRelationType = function getRelationType(type) {
|
||
switch (type) {
|
||
case cDDb.relationType.AGGREGATION:
|
||
return 'aggregation';
|
||
case cDDb.relationType.EXTENSION:
|
||
return 'extension';
|
||
case cDDb.relationType.COMPOSITION:
|
||
return 'composition';
|
||
case cDDb.relationType.DEPENDENCY:
|
||
return 'dependency';
|
||
}
|
||
};
|
||
|
||
//The data for our line
|
||
var lineData = path.points;
|
||
|
||
//This is the accessor function we talked about above
|
||
var lineFunction = d3.svg.line().x(function (d) {
|
||
return d.x;
|
||
}).y(function (d) {
|
||
return d.y;
|
||
})
|
||
//.interpolate('cardinal');
|
||
.interpolate('basis');
|
||
|
||
var svgPath = elem.append('path').attr('d', lineFunction(lineData)).attr('id', 'edge' + edgeCount).attr('class', 'relation');
|
||
var url = '';
|
||
if (conf.arrowMarkerAbsolute) {
|
||
url = window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search;
|
||
url = url.replace(/\(/g, '\\(');
|
||
url = url.replace(/\)/g, '\\)');
|
||
}
|
||
|
||
//console.log(relation.relation.type1);
|
||
if (relation.relation.type1 !== 'none') {
|
||
svgPath.attr('marker-start', 'url(' + url + '#' + getRelationType(relation.relation.type1) + 'Start' + ')');
|
||
}
|
||
if (relation.relation.type2 !== 'none') {
|
||
svgPath.attr('marker-end', 'url(' + url + '#' + getRelationType(relation.relation.type2) + 'End' + ')');
|
||
}
|
||
|
||
//var bbox = svgPath[0][0].getBBox();
|
||
//var x = Math.floor(bbox.x + bbox.width/2.0);
|
||
//var y = Math.floor(bbox.y + bbox.height/2.0);
|
||
var x, y;
|
||
var l = path.points.length;
|
||
if (l % 2 !== 0) {
|
||
var p1 = path.points[Math.floor(l / 2)];
|
||
var p2 = path.points[Math.ceil(l / 2)];
|
||
x = (p1.x + p2.x) / 2;
|
||
y = (p1.y + p2.y) / 2;
|
||
} else {
|
||
var p = path.points[Math.floor(l / 2)];
|
||
x = p.x;
|
||
y = p.y;
|
||
}
|
||
|
||
if (typeof relation.title !== 'undefined') {
|
||
var g = elem.append('g').attr('class', 'classLabel');
|
||
var label = g.append('text').attr('class', 'label').attr('x', x).attr('y', y).attr('fill', 'red').attr('text-anchor', 'middle').text(relation.title);
|
||
|
||
window.label = label;
|
||
var bounds = label.node().getBBox();
|
||
|
||
g.insert('rect', ':first-child').attr('class', 'box').attr('x', bounds.x - conf.padding / 2).attr('y', bounds.y - conf.padding / 2).attr('width', bounds.width + 2 * conf.padding / 2).attr('height', bounds.height + 2 * conf.padding / 2);
|
||
//.append('textpath')
|
||
//.attr('xlink:href','#edge'+edgeCount)
|
||
//.attr('text-anchor','middle')
|
||
//.attr('startOffset','50%')
|
||
}
|
||
|
||
edgeCount++;
|
||
};
|
||
|
||
var drawClass = function drawClass(elem, classDef) {
|
||
log.info('Rendering class ' + classDef);
|
||
|
||
var addTspan = function addTspan(textEl, txt, isFirst) {
|
||
var tSpan = textEl.append('tspan').attr('x', conf.padding).text(txt);
|
||
if (!isFirst) {
|
||
tSpan.attr('dy', conf.textHeight);
|
||
}
|
||
};
|
||
|
||
var id = 'classId' + classCnt;
|
||
var classInfo = {
|
||
id: id,
|
||
label: classDef.id,
|
||
width: 0,
|
||
height: 0
|
||
};
|
||
|
||
var g = elem.append('g').attr('id', id).attr('class', 'classGroup');
|
||
var title = g.append('text').attr('x', conf.padding).attr('y', conf.textHeight + conf.padding).text(classDef.id);
|
||
|
||
var titleHeight = title.node().getBBox().height;
|
||
|
||
var membersLine = g.append('line') // text label for the x axis
|
||
.attr('x1', 0).attr('y1', conf.padding + titleHeight + conf.dividerMargin / 2).attr('y2', conf.padding + titleHeight + conf.dividerMargin / 2);
|
||
|
||
var members = g.append('text') // text label for the x axis
|
||
.attr('x', conf.padding).attr('y', titleHeight + conf.dividerMargin + conf.textHeight).attr('fill', 'white').attr('class', 'classText');
|
||
|
||
var isFirst = true;
|
||
|
||
classDef.members.forEach(function (member) {
|
||
addTspan(members, member, isFirst);
|
||
isFirst = false;
|
||
});
|
||
//for (var member of classDef.members) {
|
||
// addTspan(members, member, isFirst);
|
||
// isFirst = false;
|
||
//}
|
||
|
||
var membersBox = members.node().getBBox();
|
||
|
||
var methodsLine = g.append('line') // text label for the x axis
|
||
.attr('x1', 0).attr('y1', conf.padding + titleHeight + 3 * conf.dividerMargin / 2 + membersBox.height).attr('y2', conf.padding + titleHeight + 3 * conf.dividerMargin / 2 + membersBox.height);
|
||
|
||
var methods = g.append('text') // text label for the x axis
|
||
.attr('x', conf.padding).attr('y', titleHeight + 2 * conf.dividerMargin + membersBox.height + conf.textHeight).attr('fill', 'white').attr('class', 'classText');
|
||
|
||
isFirst = true;
|
||
|
||
classDef.methods.forEach(function (method) {
|
||
addTspan(methods, method, isFirst);
|
||
isFirst = false;
|
||
});
|
||
//for (var method of classDef.methods) {
|
||
// addTspan(methods, method, isFirst);
|
||
// isFirst = false;
|
||
//}
|
||
|
||
var classBox = g.node().getBBox();
|
||
g.insert('rect', ':first-child').attr('x', 0).attr('y', 0).attr('width', classBox.width + 2 * conf.padding).attr('height', classBox.height + conf.padding + 0.5 * conf.dividerMargin);
|
||
|
||
membersLine.attr('x2', classBox.width + 2 * conf.padding);
|
||
methodsLine.attr('x2', classBox.width + 2 * conf.padding);
|
||
|
||
classInfo.width = classBox.width + 2 * conf.padding;
|
||
classInfo.height = classBox.height + conf.padding + 0.5 * conf.dividerMargin;
|
||
|
||
idCache[id] = classInfo;
|
||
classCnt++;
|
||
return classInfo;
|
||
};
|
||
|
||
module.exports.setConf = function (cnf) {
|
||
var keys = Object.keys(cnf);
|
||
|
||
keys.forEach(function (key) {
|
||
conf[key] = cnf[key];
|
||
});
|
||
};
|
||
/**
|
||
* Draws a flowchart in the tag with id: id based on the graph definition in text.
|
||
* @param text
|
||
* @param id
|
||
*/
|
||
module.exports.draw = function (text, id) {
|
||
cd.yy.clear();
|
||
cd.parse(text);
|
||
|
||
log.info('Rendering diagram ' + text);
|
||
|
||
//// Fetch the default direction, use TD if none was found
|
||
var diagram = d3.select('#' + id);
|
||
insertMarkers(diagram);
|
||
//var svg = diagram.append('svg');
|
||
|
||
// Layout graph, Create a new directed graph
|
||
var g = new dagre.graphlib.Graph({
|
||
multigraph: true
|
||
});
|
||
|
||
// Set an object for the graph label
|
||
g.setGraph({
|
||
isMultiGraph: true
|
||
});
|
||
|
||
// Default to assigning a new object as a label for each new edge.
|
||
g.setDefaultEdgeLabel(function () {
|
||
return {};
|
||
});
|
||
|
||
var classes = cDDb.getClasses();
|
||
var keys = Object.keys(classes);
|
||
var i;
|
||
for (i = 0; i < keys.length; i++) {
|
||
var classDef = classes[keys[i]];
|
||
var node = drawClass(diagram, classDef);
|
||
// Add nodes to the graph. The first argument is the node id. The second is
|
||
// metadata about the node. In this case we're going to add labels to each of
|
||
// our nodes.
|
||
g.setNode(node.id, node);
|
||
log.info('Org height: ' + node.height);
|
||
//g.setNode("swilliams", { label: "Saul Williams", width: 160, height: 100 });
|
||
//g.setNode("bpitt", { label: "Brad Pitt", width: 108, height: 100 });
|
||
//g.setNode("hford", { label: "Harrison Ford", width: 168, height: 100 });
|
||
//g.setNode("lwilson", { label: "Luke Wilson", width: 144, height: 100 });
|
||
//g.setNode("kbacon", { label: "Kevin Bacon", width: 121, height: 100 });
|
||
}
|
||
|
||
var relations = cDDb.getRelations();
|
||
var i = 0;
|
||
relations.forEach(function (relation) {
|
||
i = i + 1;
|
||
log.info('tjoho' + getGraphId(relation.id1) + getGraphId(relation.id2) + JSON.stringify(relation));
|
||
g.setEdge(getGraphId(relation.id1), getGraphId(relation.id2), { relation: relation });
|
||
});
|
||
//for (var relation of relations) {
|
||
// i = i + 1;
|
||
// log.info('tjoho' + getGraphId(relation.id1) + getGraphId(relation.id2) + JSON.stringify(relation));
|
||
// g.setEdge(getGraphId(relation.id1), getGraphId(relation.id2), {relation: relation});
|
||
//}
|
||
dagre.layout(g);
|
||
g.nodes().forEach(function (v) {
|
||
if (typeof v !== 'undefined') {
|
||
log.debug('Node ' + v + ': ' + JSON.stringify(g.node(v)));
|
||
d3.select('#' + v).attr('transform', 'translate(' + (g.node(v).x - g.node(v).width / 2) + ',' + (g.node(v).y - g.node(v).height / 2) + ' )');
|
||
//d3.select('#' +v +' rect').attr('x',(g.node(v).x-(g.node(v).width/2)))
|
||
//.attr('y',(g.node(v).y-(g.node(v).height/2)));
|
||
}
|
||
});
|
||
g.edges().forEach(function (e) {
|
||
log.debug('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(g.edge(e)));
|
||
drawEdge(diagram, g.edge(e), g.edge(e).relation);
|
||
});
|
||
|
||
//
|
||
diagram.attr('height', '100%');
|
||
diagram.attr('width', '100%');
|
||
//
|
||
//
|
||
//
|
||
//
|
||
//if(conf.useMaxWidth) {
|
||
// diagram.attr('height', '100%');
|
||
// diagram.attr('width', '100%');
|
||
// diagram.attr('style', 'max-width:' + (width) + 'px;');
|
||
//}else{
|
||
// diagram.attr('height',height);
|
||
// diagram.attr('width', width );
|
||
//}
|
||
//diagram.attr('viewBox', (box.startx-conf.diagramMarginX) + ' -' +conf.diagramMarginY + ' ' + width + ' ' + height);
|
||
};
|
||
|
||
},{"../../d3":107,"../../logger":126,"./classDb":108,"./parser/classDiagram":110,"dagre":54}],110:[function(require,module,exports){
|
||
(function (process){
|
||
/* parser generated by jison 0.4.15 */
|
||
/*
|
||
Returns a Parser object of the following structure:
|
||
|
||
Parser: {
|
||
yy: {}
|
||
}
|
||
|
||
Parser.prototype: {
|
||
yy: {},
|
||
trace: function(),
|
||
symbols_: {associative list: name ==> number},
|
||
terminals_: {associative list: number ==> name},
|
||
productions_: [...],
|
||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
|
||
table: [...],
|
||
defaultActions: {...},
|
||
parseError: function(str, hash),
|
||
parse: function(input),
|
||
|
||
lexer: {
|
||
EOF: 1,
|
||
parseError: function(str, hash),
|
||
setInput: function(input),
|
||
input: function(),
|
||
unput: function(str),
|
||
more: function(),
|
||
less: function(n),
|
||
pastInput: function(),
|
||
upcomingInput: function(),
|
||
showPosition: function(),
|
||
test_match: function(regex_match_array, rule_index),
|
||
next: function(),
|
||
lex: function(),
|
||
begin: function(condition),
|
||
popState: function(),
|
||
_currentRules: function(),
|
||
topState: function(),
|
||
pushState: function(condition),
|
||
|
||
options: {
|
||
ranges: boolean (optional: true ==> token location info will include a .range[] member)
|
||
flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
|
||
backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
|
||
},
|
||
|
||
performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
|
||
rules: [...],
|
||
conditions: {associative list: name ==> set},
|
||
}
|
||
}
|
||
|
||
|
||
token location info (@$, _$, etc.): {
|
||
first_line: n,
|
||
last_line: n,
|
||
first_column: n,
|
||
last_column: n,
|
||
range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
|
||
}
|
||
|
||
|
||
the parseError function receives a 'hash' object with these members for lexer and parser errors: {
|
||
text: (matched text)
|
||
token: (the produced terminal token, if any)
|
||
line: (yylineno)
|
||
}
|
||
while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
|
||
loc: (yylloc)
|
||
expected: (string describing the set of expected tokens)
|
||
recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
|
||
}
|
||
*/
|
||
"use strict";
|
||
|
||
var classDiagram = (function () {
|
||
var o = function o(k, v, _o, l) {
|
||
for (_o = _o || {}, l = k.length; l--; _o[k[l]] = v);return _o;
|
||
},
|
||
$V0 = [1, 11],
|
||
$V1 = [1, 12],
|
||
$V2 = [1, 13],
|
||
$V3 = [1, 15],
|
||
$V4 = [1, 16],
|
||
$V5 = [1, 17],
|
||
$V6 = [6, 8],
|
||
$V7 = [1, 26],
|
||
$V8 = [1, 27],
|
||
$V9 = [1, 28],
|
||
$Va = [1, 29],
|
||
$Vb = [1, 30],
|
||
$Vc = [1, 31],
|
||
$Vd = [6, 8, 13, 17, 23, 26, 27, 28, 29, 30, 31],
|
||
$Ve = [6, 8, 13, 17, 23, 26, 27, 28, 29, 30, 31, 45, 46, 47],
|
||
$Vf = [23, 45, 46, 47],
|
||
$Vg = [23, 30, 31, 45, 46, 47],
|
||
$Vh = [23, 26, 27, 28, 29, 45, 46, 47],
|
||
$Vi = [6, 8, 13],
|
||
$Vj = [1, 46];
|
||
var parser = { trace: function trace() {},
|
||
yy: {},
|
||
symbols_: { "error": 2, "mermaidDoc": 3, "graphConfig": 4, "CLASS_DIAGRAM": 5, "NEWLINE": 6, "statements": 7, "EOF": 8, "statement": 9, "className": 10, "alphaNumToken": 11, "relationStatement": 12, "LABEL": 13, "classStatement": 14, "methodStatement": 15, "CLASS": 16, "STRUCT_START": 17, "members": 18, "STRUCT_STOP": 19, "MEMBER": 20, "SEPARATOR": 21, "relation": 22, "STR": 23, "relationType": 24, "lineType": 25, "AGGREGATION": 26, "EXTENSION": 27, "COMPOSITION": 28, "DEPENDENCY": 29, "LINE": 30, "DOTTED_LINE": 31, "commentToken": 32, "textToken": 33, "graphCodeTokens": 34, "textNoTagsToken": 35, "TAGSTART": 36, "TAGEND": 37, "==": 38, "--": 39, "PCT": 40, "DEFAULT": 41, "SPACE": 42, "MINUS": 43, "keywords": 44, "UNICODE_TEXT": 45, "NUM": 46, "ALPHA": 47, "$accept": 0, "$end": 1 },
|
||
terminals_: { 2: "error", 5: "CLASS_DIAGRAM", 6: "NEWLINE", 8: "EOF", 13: "LABEL", 16: "CLASS", 17: "STRUCT_START", 19: "STRUCT_STOP", 20: "MEMBER", 21: "SEPARATOR", 23: "STR", 26: "AGGREGATION", 27: "EXTENSION", 28: "COMPOSITION", 29: "DEPENDENCY", 30: "LINE", 31: "DOTTED_LINE", 34: "graphCodeTokens", 36: "TAGSTART", 37: "TAGEND", 38: "==", 39: "--", 40: "PCT", 41: "DEFAULT", 42: "SPACE", 43: "MINUS", 44: "keywords", 45: "UNICODE_TEXT", 46: "NUM", 47: "ALPHA" },
|
||
productions_: [0, [3, 1], [4, 4], [7, 1], [7, 3], [10, 2], [10, 1], [9, 1], [9, 2], [9, 1], [9, 1], [14, 2], [14, 5], [18, 1], [18, 2], [15, 1], [15, 2], [15, 1], [15, 1], [12, 3], [12, 4], [12, 4], [12, 5], [22, 3], [22, 2], [22, 2], [22, 1], [24, 1], [24, 1], [24, 1], [24, 1], [25, 1], [25, 1], [32, 1], [32, 1], [33, 1], [33, 1], [33, 1], [33, 1], [33, 1], [33, 1], [33, 1], [35, 1], [35, 1], [35, 1], [35, 1], [11, 1], [11, 1], [11, 1]],
|
||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, /* action[1] */$$, /* vstack */_$ /* lstack */) {
|
||
/* this == yyval */
|
||
|
||
var $0 = $$.length - 1;
|
||
switch (yystate) {
|
||
case 5:
|
||
this.$ = $$[$0 - 1] + $$[$0];
|
||
break;
|
||
case 6:
|
||
this.$ = $$[$0];
|
||
break;
|
||
case 7:
|
||
yy.addRelation($$[$0]);
|
||
break;
|
||
case 8:
|
||
$$[$0 - 1].title = yy.cleanupLabel($$[$0]);yy.addRelation($$[$0 - 1]);
|
||
break;
|
||
case 12:
|
||
/*console.log($$[$0-3],JSON.stringify($$[$0-1]));*/yy.addMembers($$[$0 - 3], $$[$0 - 1]);
|
||
break;
|
||
case 13:
|
||
this.$ = [$$[$0]];
|
||
break;
|
||
case 14:
|
||
$$[$0].push($$[$0 - 1]);this.$ = $$[$0];
|
||
break;
|
||
case 15:
|
||
/*console.log('Rel found',$$[$0]);*/
|
||
break;
|
||
case 16:
|
||
yy.addMembers($$[$0 - 1], yy.cleanupLabel($$[$0]));
|
||
break;
|
||
case 17:
|
||
console.warn('Member', $$[$0]);
|
||
break;
|
||
case 18:
|
||
/*console.log('sep found',$$[$0]);*/
|
||
break;
|
||
case 19:
|
||
this.$ = { 'id1': $$[$0 - 2], 'id2': $$[$0], relation: $$[$0 - 1], relationTitle1: 'none', relationTitle2: 'none' };
|
||
break;
|
||
case 20:
|
||
this.$ = { id1: $$[$0 - 3], id2: $$[$0], relation: $$[$0 - 1], relationTitle1: $$[$0 - 2], relationTitle2: 'none' };
|
||
break;
|
||
case 21:
|
||
this.$ = { id1: $$[$0 - 3], id2: $$[$0], relation: $$[$0 - 2], relationTitle1: 'none', relationTitle2: $$[$0 - 1] };
|
||
break;
|
||
case 22:
|
||
this.$ = { id1: $$[$0 - 4], id2: $$[$0], relation: $$[$0 - 2], relationTitle1: $$[$0 - 3], relationTitle2: $$[$0 - 1] };
|
||
break;
|
||
case 23:
|
||
this.$ = { type1: $$[$0 - 2], type2: $$[$0], lineType: $$[$0 - 1] };
|
||
break;
|
||
case 24:
|
||
this.$ = { type1: 'none', type2: $$[$0], lineType: $$[$0 - 1] };
|
||
break;
|
||
case 25:
|
||
this.$ = { type1: $$[$0 - 1], type2: 'none', lineType: $$[$0] };
|
||
break;
|
||
case 26:
|
||
this.$ = { type1: 'none', type2: 'none', lineType: $$[$0] };
|
||
break;
|
||
case 27:
|
||
this.$ = yy.relationType.AGGREGATION;
|
||
break;
|
||
case 28:
|
||
this.$ = yy.relationType.EXTENSION;
|
||
break;
|
||
case 29:
|
||
this.$ = yy.relationType.COMPOSITION;
|
||
break;
|
||
case 30:
|
||
this.$ = yy.relationType.DEPENDENCY;
|
||
break;
|
||
case 31:
|
||
this.$ = yy.lineType.LINE;
|
||
break;
|
||
case 32:
|
||
this.$ = yy.lineType.DOTTED_LINE;
|
||
break;
|
||
}
|
||
},
|
||
table: [{ 3: 1, 4: 2, 5: [1, 3] }, { 1: [3] }, { 1: [2, 1] }, { 6: [1, 4] }, { 7: 5, 9: 6, 10: 10, 11: 14, 12: 7, 14: 8, 15: 9, 16: $V0, 20: $V1, 21: $V2, 45: $V3, 46: $V4, 47: $V5 }, { 8: [1, 18] }, { 6: [1, 19], 8: [2, 3] }, o($V6, [2, 7], { 13: [1, 20] }), o($V6, [2, 9]), o($V6, [2, 10]), o($V6, [2, 15], { 22: 21, 24: 24, 25: 25, 13: [1, 23], 23: [1, 22], 26: $V7, 27: $V8, 28: $V9, 29: $Va, 30: $Vb, 31: $Vc }), { 10: 32, 11: 14, 45: $V3, 46: $V4, 47: $V5 }, o($V6, [2, 17]), o($V6, [2, 18]), o($Vd, [2, 6], { 11: 14, 10: 33, 45: $V3, 46: $V4, 47: $V5 }), o($Ve, [2, 46]), o($Ve, [2, 47]), o($Ve, [2, 48]), { 1: [2, 2] }, { 7: 34, 9: 6, 10: 10, 11: 14, 12: 7, 14: 8, 15: 9, 16: $V0, 20: $V1, 21: $V2, 45: $V3, 46: $V4, 47: $V5 }, o($V6, [2, 8]), { 10: 35, 11: 14, 23: [1, 36], 45: $V3, 46: $V4, 47: $V5 }, { 22: 37, 24: 24, 25: 25, 26: $V7, 27: $V8, 28: $V9, 29: $Va, 30: $Vb, 31: $Vc }, o($V6, [2, 16]), { 25: 38, 30: $Vb, 31: $Vc }, o($Vf, [2, 26], { 24: 39, 26: $V7, 27: $V8, 28: $V9, 29: $Va }), o($Vg, [2, 27]), o($Vg, [2, 28]), o($Vg, [2, 29]), o($Vg, [2, 30]), o($Vh, [2, 31]), o($Vh, [2, 32]), o($V6, [2, 11], { 17: [1, 40] }), o($Vd, [2, 5]), { 8: [2, 4] }, o($Vi, [2, 19]), { 10: 41, 11: 14, 45: $V3, 46: $V4, 47: $V5 }, { 10: 42, 11: 14, 23: [1, 43], 45: $V3, 46: $V4, 47: $V5 }, o($Vf, [2, 25], { 24: 44, 26: $V7, 27: $V8, 28: $V9, 29: $Va }), o($Vf, [2, 24]), { 18: 45, 20: $Vj }, o($Vi, [2, 21]), o($Vi, [2, 20]), { 10: 47, 11: 14, 45: $V3, 46: $V4, 47: $V5 }, o($Vf, [2, 23]), { 19: [1, 48] }, { 18: 49, 19: [2, 13], 20: $Vj }, o($Vi, [2, 22]), o($V6, [2, 12]), { 19: [2, 14] }],
|
||
defaultActions: { 2: [2, 1], 18: [2, 2], 34: [2, 4], 49: [2, 14] },
|
||
parseError: function parseError(str, hash) {
|
||
if (hash.recoverable) {
|
||
this.trace(str);
|
||
} else {
|
||
var _parseError = function _parseError(msg, hash) {
|
||
this.message = msg;
|
||
this.hash = hash;
|
||
};
|
||
|
||
_parseError.prototype = new Error();
|
||
|
||
throw new _parseError(str, hash);
|
||
}
|
||
},
|
||
parse: function parse(input) {
|
||
var self = this,
|
||
stack = [0],
|
||
tstack = [],
|
||
vstack = [null],
|
||
lstack = [],
|
||
table = this.table,
|
||
yytext = '',
|
||
yylineno = 0,
|
||
yyleng = 0,
|
||
recovering = 0,
|
||
TERROR = 2,
|
||
EOF = 1;
|
||
var args = lstack.slice.call(arguments, 1);
|
||
var lexer = Object.create(this.lexer);
|
||
var sharedState = { yy: {} };
|
||
for (var k in this.yy) {
|
||
if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
|
||
sharedState.yy[k] = this.yy[k];
|
||
}
|
||
}
|
||
lexer.setInput(input, sharedState.yy);
|
||
sharedState.yy.lexer = lexer;
|
||
sharedState.yy.parser = this;
|
||
if (typeof lexer.yylloc == 'undefined') {
|
||
lexer.yylloc = {};
|
||
}
|
||
var yyloc = lexer.yylloc;
|
||
lstack.push(yyloc);
|
||
var ranges = lexer.options && lexer.options.ranges;
|
||
if (typeof sharedState.yy.parseError === 'function') {
|
||
this.parseError = sharedState.yy.parseError;
|
||
} else {
|
||
this.parseError = Object.getPrototypeOf(this).parseError;
|
||
}
|
||
function popStack(n) {
|
||
stack.length = stack.length - 2 * n;
|
||
vstack.length = vstack.length - n;
|
||
lstack.length = lstack.length - n;
|
||
}
|
||
_token_stack: var lex = function lex() {
|
||
var token;
|
||
token = lexer.lex() || EOF;
|
||
if (typeof token !== 'number') {
|
||
token = self.symbols_[token] || token;
|
||
}
|
||
return token;
|
||
};
|
||
var symbol,
|
||
preErrorSymbol,
|
||
state,
|
||
action,
|
||
a,
|
||
r,
|
||
yyval = {},
|
||
p,
|
||
len,
|
||
newState,
|
||
expected;
|
||
while (true) {
|
||
state = stack[stack.length - 1];
|
||
if (this.defaultActions[state]) {
|
||
action = this.defaultActions[state];
|
||
} else {
|
||
if (symbol === null || typeof symbol == 'undefined') {
|
||
symbol = lex();
|
||
}
|
||
action = table[state] && table[state][symbol];
|
||
}
|
||
if (typeof action === 'undefined' || !action.length || !action[0]) {
|
||
var errStr = '';
|
||
expected = [];
|
||
for (p in table[state]) {
|
||
if (this.terminals_[p] && p > TERROR) {
|
||
expected.push('\'' + this.terminals_[p] + '\'');
|
||
}
|
||
}
|
||
if (lexer.showPosition) {
|
||
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
|
||
} else {
|
||
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
|
||
}
|
||
this.parseError(errStr, {
|
||
text: lexer.match,
|
||
token: this.terminals_[symbol] || symbol,
|
||
line: lexer.yylineno,
|
||
loc: yyloc,
|
||
expected: expected
|
||
});
|
||
}
|
||
if (action[0] instanceof Array && action.length > 1) {
|
||
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
|
||
}
|
||
switch (action[0]) {
|
||
case 1:
|
||
stack.push(symbol);
|
||
vstack.push(lexer.yytext);
|
||
lstack.push(lexer.yylloc);
|
||
stack.push(action[1]);
|
||
symbol = null;
|
||
if (!preErrorSymbol) {
|
||
yyleng = lexer.yyleng;
|
||
yytext = lexer.yytext;
|
||
yylineno = lexer.yylineno;
|
||
yyloc = lexer.yylloc;
|
||
if (recovering > 0) {
|
||
recovering--;
|
||
}
|
||
} else {
|
||
symbol = preErrorSymbol;
|
||
preErrorSymbol = null;
|
||
}
|
||
break;
|
||
case 2:
|
||
len = this.productions_[action[1]][1];
|
||
yyval.$ = vstack[vstack.length - len];
|
||
yyval._$ = {
|
||
first_line: lstack[lstack.length - (len || 1)].first_line,
|
||
last_line: lstack[lstack.length - 1].last_line,
|
||
first_column: lstack[lstack.length - (len || 1)].first_column,
|
||
last_column: lstack[lstack.length - 1].last_column
|
||
};
|
||
if (ranges) {
|
||
yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
|
||
}
|
||
r = this.performAction.apply(yyval, [yytext, yyleng, yylineno, sharedState.yy, action[1], vstack, lstack].concat(args));
|
||
if (typeof r !== 'undefined') {
|
||
return r;
|
||
}
|
||
if (len) {
|
||
stack = stack.slice(0, -1 * len * 2);
|
||
vstack = vstack.slice(0, -1 * len);
|
||
lstack = lstack.slice(0, -1 * len);
|
||
}
|
||
stack.push(this.productions_[action[1]][0]);
|
||
vstack.push(yyval.$);
|
||
lstack.push(yyval._$);
|
||
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
|
||
stack.push(newState);
|
||
break;
|
||
case 3:
|
||
return true;
|
||
}
|
||
}
|
||
return true;
|
||
} };
|
||
|
||
/* generated by jison-lex 0.3.4 */
|
||
var lexer = (function () {
|
||
var lexer = {
|
||
|
||
EOF: 1,
|
||
|
||
parseError: function parseError(str, hash) {
|
||
if (this.yy.parser) {
|
||
this.yy.parser.parseError(str, hash);
|
||
} else {
|
||
throw new Error(str);
|
||
}
|
||
},
|
||
|
||
// resets the lexer, sets new input
|
||
setInput: function setInput(input, yy) {
|
||
this.yy = yy || this.yy || {};
|
||
this._input = input;
|
||
this._more = this._backtrack = this.done = false;
|
||
this.yylineno = this.yyleng = 0;
|
||
this.yytext = this.matched = this.match = '';
|
||
this.conditionStack = ['INITIAL'];
|
||
this.yylloc = {
|
||
first_line: 1,
|
||
first_column: 0,
|
||
last_line: 1,
|
||
last_column: 0
|
||
};
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [0, 0];
|
||
}
|
||
this.offset = 0;
|
||
return this;
|
||
},
|
||
|
||
// consumes and returns one char from the input
|
||
input: function input() {
|
||
var ch = this._input[0];
|
||
this.yytext += ch;
|
||
this.yyleng++;
|
||
this.offset++;
|
||
this.match += ch;
|
||
this.matched += ch;
|
||
var lines = ch.match(/(?:\r\n?|\n).*/g);
|
||
if (lines) {
|
||
this.yylineno++;
|
||
this.yylloc.last_line++;
|
||
} else {
|
||
this.yylloc.last_column++;
|
||
}
|
||
if (this.options.ranges) {
|
||
this.yylloc.range[1]++;
|
||
}
|
||
|
||
this._input = this._input.slice(1);
|
||
return ch;
|
||
},
|
||
|
||
// unshifts one char (or a string) into the input
|
||
unput: function unput(ch) {
|
||
var len = ch.length;
|
||
var lines = ch.split(/(?:\r\n?|\n)/g);
|
||
|
||
this._input = ch + this._input;
|
||
this.yytext = this.yytext.substr(0, this.yytext.length - len);
|
||
//this.yyleng -= len;
|
||
this.offset -= len;
|
||
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
|
||
this.match = this.match.substr(0, this.match.length - 1);
|
||
this.matched = this.matched.substr(0, this.matched.length - 1);
|
||
|
||
if (lines.length - 1) {
|
||
this.yylineno -= lines.length - 1;
|
||
}
|
||
var r = this.yylloc.range;
|
||
|
||
this.yylloc = {
|
||
first_line: this.yylloc.first_line,
|
||
last_line: this.yylineno + 1,
|
||
first_column: this.yylloc.first_column,
|
||
last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
|
||
};
|
||
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
|
||
}
|
||
this.yyleng = this.yytext.length;
|
||
return this;
|
||
},
|
||
|
||
// When called from action, caches matched text and appends it on next action
|
||
more: function more() {
|
||
this._more = true;
|
||
return this;
|
||
},
|
||
|
||
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
|
||
reject: function reject() {
|
||
if (this.options.backtrack_lexer) {
|
||
this._backtrack = true;
|
||
} else {
|
||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
|
||
text: "",
|
||
token: null,
|
||
line: this.yylineno
|
||
});
|
||
}
|
||
return this;
|
||
},
|
||
|
||
// retain first n characters of the match
|
||
less: function less(n) {
|
||
this.unput(this.match.slice(n));
|
||
},
|
||
|
||
// displays already matched input, i.e. for error messages
|
||
pastInput: function pastInput() {
|
||
var past = this.matched.substr(0, this.matched.length - this.match.length);
|
||
return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
|
||
},
|
||
|
||
// displays upcoming input, i.e. for error messages
|
||
upcomingInput: function upcomingInput() {
|
||
var next = this.match;
|
||
if (next.length < 20) {
|
||
next += this._input.substr(0, 20 - next.length);
|
||
}
|
||
return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
|
||
},
|
||
|
||
// displays the character position where the lexing error occurred, i.e. for error messages
|
||
showPosition: function showPosition() {
|
||
var pre = this.pastInput();
|
||
var c = new Array(pre.length + 1).join("-");
|
||
return pre + this.upcomingInput() + "\n" + c + "^";
|
||
},
|
||
|
||
// test the lexed token: return FALSE when not a match, otherwise return token
|
||
test_match: function test_match(match, indexed_rule) {
|
||
var token, lines, backup;
|
||
|
||
if (this.options.backtrack_lexer) {
|
||
// save context
|
||
backup = {
|
||
yylineno: this.yylineno,
|
||
yylloc: {
|
||
first_line: this.yylloc.first_line,
|
||
last_line: this.last_line,
|
||
first_column: this.yylloc.first_column,
|
||
last_column: this.yylloc.last_column
|
||
},
|
||
yytext: this.yytext,
|
||
match: this.match,
|
||
matches: this.matches,
|
||
matched: this.matched,
|
||
yyleng: this.yyleng,
|
||
offset: this.offset,
|
||
_more: this._more,
|
||
_input: this._input,
|
||
yy: this.yy,
|
||
conditionStack: this.conditionStack.slice(0),
|
||
done: this.done
|
||
};
|
||
if (this.options.ranges) {
|
||
backup.yylloc.range = this.yylloc.range.slice(0);
|
||
}
|
||
}
|
||
|
||
lines = match[0].match(/(?:\r\n?|\n).*/g);
|
||
if (lines) {
|
||
this.yylineno += lines.length;
|
||
}
|
||
this.yylloc = {
|
||
first_line: this.yylloc.last_line,
|
||
last_line: this.yylineno + 1,
|
||
first_column: this.yylloc.last_column,
|
||
last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length
|
||
};
|
||
this.yytext += match[0];
|
||
this.match += match[0];
|
||
this.matches = match;
|
||
this.yyleng = this.yytext.length;
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [this.offset, this.offset += this.yyleng];
|
||
}
|
||
this._more = false;
|
||
this._backtrack = false;
|
||
this._input = this._input.slice(match[0].length);
|
||
this.matched += match[0];
|
||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
|
||
if (this.done && this._input) {
|
||
this.done = false;
|
||
}
|
||
if (token) {
|
||
return token;
|
||
} else if (this._backtrack) {
|
||
// recover context
|
||
for (var k in backup) {
|
||
this[k] = backup[k];
|
||
}
|
||
return false; // rule action called reject() implying the next rule should be tested instead.
|
||
}
|
||
return false;
|
||
},
|
||
|
||
// return next match in input
|
||
next: function next() {
|
||
if (this.done) {
|
||
return this.EOF;
|
||
}
|
||
if (!this._input) {
|
||
this.done = true;
|
||
}
|
||
|
||
var token, match, tempMatch, index;
|
||
if (!this._more) {
|
||
this.yytext = '';
|
||
this.match = '';
|
||
}
|
||
var rules = this._currentRules();
|
||
for (var i = 0; i < rules.length; i++) {
|
||
tempMatch = this._input.match(this.rules[rules[i]]);
|
||
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
|
||
match = tempMatch;
|
||
index = i;
|
||
if (this.options.backtrack_lexer) {
|
||
token = this.test_match(tempMatch, rules[i]);
|
||
if (token !== false) {
|
||
return token;
|
||
} else if (this._backtrack) {
|
||
match = false;
|
||
continue; // rule action called reject() implying a rule MISmatch.
|
||
} else {
|
||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||
return false;
|
||
}
|
||
} else if (!this.options.flex) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (match) {
|
||
token = this.test_match(match, rules[index]);
|
||
if (token !== false) {
|
||
return token;
|
||
}
|
||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||
return false;
|
||
}
|
||
if (this._input === "") {
|
||
return this.EOF;
|
||
} else {
|
||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
|
||
text: "",
|
||
token: null,
|
||
line: this.yylineno
|
||
});
|
||
}
|
||
},
|
||
|
||
// return next match that has a token
|
||
lex: function lex() {
|
||
var r = this.next();
|
||
if (r) {
|
||
return r;
|
||
} else {
|
||
return this.lex();
|
||
}
|
||
},
|
||
|
||
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
|
||
begin: function begin(condition) {
|
||
this.conditionStack.push(condition);
|
||
},
|
||
|
||
// pop the previously active lexer condition state off the condition stack
|
||
popState: function popState() {
|
||
var n = this.conditionStack.length - 1;
|
||
if (n > 0) {
|
||
return this.conditionStack.pop();
|
||
} else {
|
||
return this.conditionStack[0];
|
||
}
|
||
},
|
||
|
||
// produce the lexer rule set which is active for the currently active lexer condition state
|
||
_currentRules: function _currentRules() {
|
||
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
|
||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
|
||
} else {
|
||
return this.conditions["INITIAL"].rules;
|
||
}
|
||
},
|
||
|
||
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
|
||
topState: function topState(n) {
|
||
n = this.conditionStack.length - 1 - Math.abs(n || 0);
|
||
if (n >= 0) {
|
||
return this.conditionStack[n];
|
||
} else {
|
||
return "INITIAL";
|
||
}
|
||
},
|
||
|
||
// alias for begin(condition)
|
||
pushState: function pushState(condition) {
|
||
this.begin(condition);
|
||
},
|
||
|
||
// return the number of states currently on the stack
|
||
stateStackSize: function stateStackSize() {
|
||
return this.conditionStack.length;
|
||
},
|
||
options: {},
|
||
performAction: function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
|
||
var YYSTATE = YY_START;
|
||
switch ($avoiding_name_collisions) {
|
||
case 0:
|
||
/* do nothing */
|
||
break;
|
||
case 1:
|
||
return 6;
|
||
break;
|
||
case 2:
|
||
/* skip whitespace */
|
||
break;
|
||
case 3:
|
||
return 5;
|
||
break;
|
||
case 4:
|
||
this.begin("struct"); /*console.log('Starting struct');*/return 17;
|
||
break;
|
||
case 5:
|
||
/*console.log('Ending struct');*/this.popState();return 19;
|
||
break;
|
||
case 6:
|
||
/* nothing */
|
||
break;
|
||
case 7:
|
||
/*console.log('lex-member: ' + yy_.yytext);*/return "MEMBER";
|
||
break;
|
||
case 8:
|
||
return 16;
|
||
break;
|
||
case 9:
|
||
this.begin("string");
|
||
break;
|
||
case 10:
|
||
this.popState();
|
||
break;
|
||
case 11:
|
||
return "STR";
|
||
break;
|
||
case 12:
|
||
return 27;
|
||
break;
|
||
case 13:
|
||
return 27;
|
||
break;
|
||
case 14:
|
||
return 29;
|
||
break;
|
||
case 15:
|
||
return 29;
|
||
break;
|
||
case 16:
|
||
return 28;
|
||
break;
|
||
case 17:
|
||
return 26;
|
||
break;
|
||
case 18:
|
||
return 30;
|
||
break;
|
||
case 19:
|
||
return 31;
|
||
break;
|
||
case 20:
|
||
return 13;
|
||
break;
|
||
case 21:
|
||
return 43;
|
||
break;
|
||
case 22:
|
||
return 'DOT';
|
||
break;
|
||
case 23:
|
||
return 'PLUS';
|
||
break;
|
||
case 24:
|
||
return 40;
|
||
break;
|
||
case 25:
|
||
return 'EQUALS';
|
||
break;
|
||
case 26:
|
||
return 'EQUALS';
|
||
break;
|
||
case 27:
|
||
return 47;
|
||
break;
|
||
case 28:
|
||
return 'PUNCTUATION';
|
||
break;
|
||
case 29:
|
||
return 46;
|
||
break;
|
||
case 30:
|
||
return 45;
|
||
break;
|
||
case 31:
|
||
return 42;
|
||
break;
|
||
case 32:
|
||
return 8;
|
||
break;
|
||
}
|
||
},
|
||
rules: [/^(?:%%[^\n]*)/, /^(?:\n+)/, /^(?:\s+)/, /^(?:classDiagram\b)/, /^(?:[\{])/, /^(?:\})/, /^(?:[\n])/, /^(?:[^\{\}\n]*)/, /^(?:class\b)/, /^(?:["])/, /^(?:["])/, /^(?:[^"]*)/, /^(?:\s*<\|)/, /^(?:\s*\|>)/, /^(?:\s*>)/, /^(?:\s*<)/, /^(?:\s*\*)/, /^(?:\s*o\b)/, /^(?:--)/, /^(?:\.\.)/, /^(?::[^#\n;]+)/, /^(?:-)/, /^(?:\.)/, /^(?:\+)/, /^(?:%)/, /^(?:=)/, /^(?:=)/, /^(?:[A-Za-z]+)/, /^(?:[!"#$%&'*+,-.`?\\_\/])/, /^(?:[0-9]+)/, /^(?:[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]|[\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE]|[\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA]|[\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0]|[\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977]|[\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2]|[\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A]|[\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39]|[\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8]|[\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C]|[\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C]|[\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99]|[\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0]|[\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D]|[\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3]|[\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10]|[\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1]|[\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81]|[\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3]|[\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6]|[\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A]|[\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081]|[\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D]|[\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0]|[\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310]|[\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C]|[\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711]|[\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7]|[\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C]|[\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16]|[\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF]|[\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC]|[\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D]|[\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D]|[\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3]|[\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F]|[\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128]|[\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184]|[\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3]|[\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6]|[\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE]|[\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C]|[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D]|[\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC]|[\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B]|[\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788]|[\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805]|[\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB]|[\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28]|[\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5]|[\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4]|[\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E]|[\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D]|[\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36]|[\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D]|[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|[\uFFD2-\uFFD7\uFFDA-\uFFDC])/, /^(?:\s)/, /^(?:$)/],
|
||
conditions: { "string": { "rules": [10, 11], "inclusive": false }, "struct": { "rules": [5, 6, 7], "inclusive": false }, "INITIAL": { "rules": [0, 1, 2, 3, 4, 8, 9, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32], "inclusive": true } }
|
||
};
|
||
return lexer;
|
||
})();
|
||
parser.lexer = lexer;
|
||
function Parser() {
|
||
this.yy = {};
|
||
}
|
||
Parser.prototype = parser;parser.Parser = Parser;
|
||
return new Parser();
|
||
})();
|
||
|
||
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
|
||
exports.parser = classDiagram;
|
||
exports.Parser = classDiagram.Parser;
|
||
exports.parse = function () {
|
||
return classDiagram.parse.apply(classDiagram, arguments);
|
||
};
|
||
exports.main = function commonjsMain(args) {
|
||
if (!args[1]) {
|
||
console.log('Usage: ' + args[0] + ' FILE');
|
||
process.exit(1);
|
||
}
|
||
var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
|
||
return exports.parser.parse(source);
|
||
};
|
||
if (typeof module !== 'undefined' && require.main === module) {
|
||
exports.main(process.argv.slice(1));
|
||
}
|
||
}
|
||
|
||
}).call(this,require('_process'))
|
||
},{"_process":3,"fs":1,"path":2}],111:[function(require,module,exports){
|
||
(function (global){
|
||
/**
|
||
* Created by knut on 15-01-14.
|
||
*/
|
||
'use strict';
|
||
|
||
var Logger = require('../../logger');
|
||
var log = new Logger.Log();
|
||
|
||
var message = '';
|
||
var info = false;
|
||
|
||
exports.setMessage = function (txt) {
|
||
log.debug('Setting message to: ' + txt);
|
||
message = txt;
|
||
};
|
||
|
||
exports.getMessage = function () {
|
||
return message;
|
||
};
|
||
|
||
exports.setInfo = function (inf) {
|
||
info = inf;
|
||
};
|
||
|
||
exports.getInfo = function () {
|
||
return info;
|
||
};
|
||
|
||
exports.parseError = function (err, hash) {
|
||
global.mermaidAPI.parseError(err, hash);
|
||
};
|
||
|
||
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"../../logger":126}],112:[function(require,module,exports){
|
||
/**
|
||
* Created by knut on 14-12-11.
|
||
*/
|
||
'use strict';
|
||
|
||
var db = require('./exampleDb');
|
||
var exampleParser = require('./parser/example.js');
|
||
var d3 = require('../../d3');
|
||
var Logger = require('../../logger');
|
||
var log = new Logger.Log();
|
||
|
||
/**
|
||
* Draws a an info picture in the tag with id: id based on the graph definition in text.
|
||
* @param text
|
||
* @param id
|
||
*/
|
||
exports.draw = function (txt, id, ver) {
|
||
var parser;
|
||
parser = exampleParser.parser;
|
||
parser.yy = db;
|
||
log.debug('Renering example diagram');
|
||
// Parse the graph definition
|
||
parser.parse(txt);
|
||
|
||
// Fetch the default direction, use TD if none was found
|
||
var svg = d3.select('#' + id);
|
||
|
||
var g = svg.append('g');
|
||
|
||
g.append('text') // text label for the x axis
|
||
.attr('x', 100).attr('y', 40).attr('class', 'version').attr('font-size', '32px').style('text-anchor', 'middle').text('mermaid ' + ver);
|
||
|
||
/*
|
||
var box = exports.bounds.getBounds();
|
||
var height = box.stopy-box.starty+2*conf.diagramMarginY;
|
||
var width = box.stopx-box.startx+2*conf.diagramMarginX;*/
|
||
|
||
svg.attr('height', 100);
|
||
svg.attr('width', 400);
|
||
//svg.attr('viewBox', '0 0 300 150');
|
||
};
|
||
|
||
},{"../../d3":107,"../../logger":126,"./exampleDb":111,"./parser/example.js":113}],113:[function(require,module,exports){
|
||
(function (process){
|
||
/* parser generated by jison 0.4.15 */
|
||
/*
|
||
Returns a Parser object of the following structure:
|
||
|
||
Parser: {
|
||
yy: {}
|
||
}
|
||
|
||
Parser.prototype: {
|
||
yy: {},
|
||
trace: function(),
|
||
symbols_: {associative list: name ==> number},
|
||
terminals_: {associative list: number ==> name},
|
||
productions_: [...],
|
||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
|
||
table: [...],
|
||
defaultActions: {...},
|
||
parseError: function(str, hash),
|
||
parse: function(input),
|
||
|
||
lexer: {
|
||
EOF: 1,
|
||
parseError: function(str, hash),
|
||
setInput: function(input),
|
||
input: function(),
|
||
unput: function(str),
|
||
more: function(),
|
||
less: function(n),
|
||
pastInput: function(),
|
||
upcomingInput: function(),
|
||
showPosition: function(),
|
||
test_match: function(regex_match_array, rule_index),
|
||
next: function(),
|
||
lex: function(),
|
||
begin: function(condition),
|
||
popState: function(),
|
||
_currentRules: function(),
|
||
topState: function(),
|
||
pushState: function(condition),
|
||
|
||
options: {
|
||
ranges: boolean (optional: true ==> token location info will include a .range[] member)
|
||
flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
|
||
backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
|
||
},
|
||
|
||
performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
|
||
rules: [...],
|
||
conditions: {associative list: name ==> set},
|
||
}
|
||
}
|
||
|
||
|
||
token location info (@$, _$, etc.): {
|
||
first_line: n,
|
||
last_line: n,
|
||
first_column: n,
|
||
last_column: n,
|
||
range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
|
||
}
|
||
|
||
|
||
the parseError function receives a 'hash' object with these members for lexer and parser errors: {
|
||
text: (matched text)
|
||
token: (the produced terminal token, if any)
|
||
line: (yylineno)
|
||
}
|
||
while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
|
||
loc: (yylloc)
|
||
expected: (string describing the set of expected tokens)
|
||
recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
|
||
}
|
||
*/
|
||
"use strict";
|
||
|
||
var example = (function () {
|
||
var o = function o(k, v, _o, l) {
|
||
for (_o = _o || {}, l = k.length; l--; _o[k[l]] = v);return _o;
|
||
},
|
||
$V0 = [6, 9, 10, 12];
|
||
var parser = { trace: function trace() {},
|
||
yy: {},
|
||
symbols_: { "error": 2, "start": 3, "info": 4, "document": 5, "EOF": 6, "line": 7, "statement": 8, "NL": 9, "showInfo": 10, "message": 11, "say": 12, "TXT": 13, "$accept": 0, "$end": 1 },
|
||
terminals_: { 2: "error", 4: "info", 6: "EOF", 9: "NL", 10: "showInfo", 12: "say", 13: "TXT" },
|
||
productions_: [0, [3, 3], [5, 0], [5, 2], [7, 1], [7, 1], [8, 1], [8, 1], [11, 2]],
|
||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, /* action[1] */$$, /* vstack */_$ /* lstack */) {
|
||
/* this == yyval */
|
||
|
||
var $0 = $$.length - 1;
|
||
switch (yystate) {
|
||
case 1:
|
||
return yy;
|
||
break;
|
||
case 4:
|
||
|
||
break;
|
||
case 6:
|
||
yy.setInfo(true);
|
||
break;
|
||
case 7:
|
||
yy.setMessage($$[$0]);
|
||
break;
|
||
case 8:
|
||
this.$ = $$[$0 - 1].substring(1).trim().replace(/\\n/gm, "\n");
|
||
break;
|
||
}
|
||
},
|
||
table: [{ 3: 1, 4: [1, 2] }, { 1: [3] }, o($V0, [2, 2], { 5: 3 }), { 6: [1, 4], 7: 5, 8: 6, 9: [1, 7], 10: [1, 8], 11: 9, 12: [1, 10] }, { 1: [2, 1] }, o($V0, [2, 3]), o($V0, [2, 4]), o($V0, [2, 5]), o($V0, [2, 6]), o($V0, [2, 7]), { 13: [1, 11] }, o($V0, [2, 8])],
|
||
defaultActions: { 4: [2, 1] },
|
||
parseError: function parseError(str, hash) {
|
||
if (hash.recoverable) {
|
||
this.trace(str);
|
||
} else {
|
||
var _parseError = function _parseError(msg, hash) {
|
||
this.message = msg;
|
||
this.hash = hash;
|
||
};
|
||
|
||
_parseError.prototype = new Error();
|
||
|
||
throw new _parseError(str, hash);
|
||
}
|
||
},
|
||
parse: function parse(input) {
|
||
var self = this,
|
||
stack = [0],
|
||
tstack = [],
|
||
vstack = [null],
|
||
lstack = [],
|
||
table = this.table,
|
||
yytext = '',
|
||
yylineno = 0,
|
||
yyleng = 0,
|
||
recovering = 0,
|
||
TERROR = 2,
|
||
EOF = 1;
|
||
var args = lstack.slice.call(arguments, 1);
|
||
var lexer = Object.create(this.lexer);
|
||
var sharedState = { yy: {} };
|
||
for (var k in this.yy) {
|
||
if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
|
||
sharedState.yy[k] = this.yy[k];
|
||
}
|
||
}
|
||
lexer.setInput(input, sharedState.yy);
|
||
sharedState.yy.lexer = lexer;
|
||
sharedState.yy.parser = this;
|
||
if (typeof lexer.yylloc == 'undefined') {
|
||
lexer.yylloc = {};
|
||
}
|
||
var yyloc = lexer.yylloc;
|
||
lstack.push(yyloc);
|
||
var ranges = lexer.options && lexer.options.ranges;
|
||
if (typeof sharedState.yy.parseError === 'function') {
|
||
this.parseError = sharedState.yy.parseError;
|
||
} else {
|
||
this.parseError = Object.getPrototypeOf(this).parseError;
|
||
}
|
||
function popStack(n) {
|
||
stack.length = stack.length - 2 * n;
|
||
vstack.length = vstack.length - n;
|
||
lstack.length = lstack.length - n;
|
||
}
|
||
_token_stack: var lex = function lex() {
|
||
var token;
|
||
token = lexer.lex() || EOF;
|
||
if (typeof token !== 'number') {
|
||
token = self.symbols_[token] || token;
|
||
}
|
||
return token;
|
||
};
|
||
var symbol,
|
||
preErrorSymbol,
|
||
state,
|
||
action,
|
||
a,
|
||
r,
|
||
yyval = {},
|
||
p,
|
||
len,
|
||
newState,
|
||
expected;
|
||
while (true) {
|
||
state = stack[stack.length - 1];
|
||
if (this.defaultActions[state]) {
|
||
action = this.defaultActions[state];
|
||
} else {
|
||
if (symbol === null || typeof symbol == 'undefined') {
|
||
symbol = lex();
|
||
}
|
||
action = table[state] && table[state][symbol];
|
||
}
|
||
if (typeof action === 'undefined' || !action.length || !action[0]) {
|
||
var errStr = '';
|
||
expected = [];
|
||
for (p in table[state]) {
|
||
if (this.terminals_[p] && p > TERROR) {
|
||
expected.push('\'' + this.terminals_[p] + '\'');
|
||
}
|
||
}
|
||
if (lexer.showPosition) {
|
||
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
|
||
} else {
|
||
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
|
||
}
|
||
this.parseError(errStr, {
|
||
text: lexer.match,
|
||
token: this.terminals_[symbol] || symbol,
|
||
line: lexer.yylineno,
|
||
loc: yyloc,
|
||
expected: expected
|
||
});
|
||
}
|
||
if (action[0] instanceof Array && action.length > 1) {
|
||
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
|
||
}
|
||
switch (action[0]) {
|
||
case 1:
|
||
stack.push(symbol);
|
||
vstack.push(lexer.yytext);
|
||
lstack.push(lexer.yylloc);
|
||
stack.push(action[1]);
|
||
symbol = null;
|
||
if (!preErrorSymbol) {
|
||
yyleng = lexer.yyleng;
|
||
yytext = lexer.yytext;
|
||
yylineno = lexer.yylineno;
|
||
yyloc = lexer.yylloc;
|
||
if (recovering > 0) {
|
||
recovering--;
|
||
}
|
||
} else {
|
||
symbol = preErrorSymbol;
|
||
preErrorSymbol = null;
|
||
}
|
||
break;
|
||
case 2:
|
||
len = this.productions_[action[1]][1];
|
||
yyval.$ = vstack[vstack.length - len];
|
||
yyval._$ = {
|
||
first_line: lstack[lstack.length - (len || 1)].first_line,
|
||
last_line: lstack[lstack.length - 1].last_line,
|
||
first_column: lstack[lstack.length - (len || 1)].first_column,
|
||
last_column: lstack[lstack.length - 1].last_column
|
||
};
|
||
if (ranges) {
|
||
yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
|
||
}
|
||
r = this.performAction.apply(yyval, [yytext, yyleng, yylineno, sharedState.yy, action[1], vstack, lstack].concat(args));
|
||
if (typeof r !== 'undefined') {
|
||
return r;
|
||
}
|
||
if (len) {
|
||
stack = stack.slice(0, -1 * len * 2);
|
||
vstack = vstack.slice(0, -1 * len);
|
||
lstack = lstack.slice(0, -1 * len);
|
||
}
|
||
stack.push(this.productions_[action[1]][0]);
|
||
vstack.push(yyval.$);
|
||
lstack.push(yyval._$);
|
||
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
|
||
stack.push(newState);
|
||
break;
|
||
case 3:
|
||
return true;
|
||
}
|
||
}
|
||
return true;
|
||
} };
|
||
/* generated by jison-lex 0.3.4 */
|
||
var lexer = (function () {
|
||
var lexer = {
|
||
|
||
EOF: 1,
|
||
|
||
parseError: function parseError(str, hash) {
|
||
if (this.yy.parser) {
|
||
this.yy.parser.parseError(str, hash);
|
||
} else {
|
||
throw new Error(str);
|
||
}
|
||
},
|
||
|
||
// resets the lexer, sets new input
|
||
setInput: function setInput(input, yy) {
|
||
this.yy = yy || this.yy || {};
|
||
this._input = input;
|
||
this._more = this._backtrack = this.done = false;
|
||
this.yylineno = this.yyleng = 0;
|
||
this.yytext = this.matched = this.match = '';
|
||
this.conditionStack = ['INITIAL'];
|
||
this.yylloc = {
|
||
first_line: 1,
|
||
first_column: 0,
|
||
last_line: 1,
|
||
last_column: 0
|
||
};
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [0, 0];
|
||
}
|
||
this.offset = 0;
|
||
return this;
|
||
},
|
||
|
||
// consumes and returns one char from the input
|
||
input: function input() {
|
||
var ch = this._input[0];
|
||
this.yytext += ch;
|
||
this.yyleng++;
|
||
this.offset++;
|
||
this.match += ch;
|
||
this.matched += ch;
|
||
var lines = ch.match(/(?:\r\n?|\n).*/g);
|
||
if (lines) {
|
||
this.yylineno++;
|
||
this.yylloc.last_line++;
|
||
} else {
|
||
this.yylloc.last_column++;
|
||
}
|
||
if (this.options.ranges) {
|
||
this.yylloc.range[1]++;
|
||
}
|
||
|
||
this._input = this._input.slice(1);
|
||
return ch;
|
||
},
|
||
|
||
// unshifts one char (or a string) into the input
|
||
unput: function unput(ch) {
|
||
var len = ch.length;
|
||
var lines = ch.split(/(?:\r\n?|\n)/g);
|
||
|
||
this._input = ch + this._input;
|
||
this.yytext = this.yytext.substr(0, this.yytext.length - len);
|
||
//this.yyleng -= len;
|
||
this.offset -= len;
|
||
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
|
||
this.match = this.match.substr(0, this.match.length - 1);
|
||
this.matched = this.matched.substr(0, this.matched.length - 1);
|
||
|
||
if (lines.length - 1) {
|
||
this.yylineno -= lines.length - 1;
|
||
}
|
||
var r = this.yylloc.range;
|
||
|
||
this.yylloc = {
|
||
first_line: this.yylloc.first_line,
|
||
last_line: this.yylineno + 1,
|
||
first_column: this.yylloc.first_column,
|
||
last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
|
||
};
|
||
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
|
||
}
|
||
this.yyleng = this.yytext.length;
|
||
return this;
|
||
},
|
||
|
||
// When called from action, caches matched text and appends it on next action
|
||
more: function more() {
|
||
this._more = true;
|
||
return this;
|
||
},
|
||
|
||
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
|
||
reject: function reject() {
|
||
if (this.options.backtrack_lexer) {
|
||
this._backtrack = true;
|
||
} else {
|
||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
|
||
text: "",
|
||
token: null,
|
||
line: this.yylineno
|
||
});
|
||
}
|
||
return this;
|
||
},
|
||
|
||
// retain first n characters of the match
|
||
less: function less(n) {
|
||
this.unput(this.match.slice(n));
|
||
},
|
||
|
||
// displays already matched input, i.e. for error messages
|
||
pastInput: function pastInput() {
|
||
var past = this.matched.substr(0, this.matched.length - this.match.length);
|
||
return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
|
||
},
|
||
|
||
// displays upcoming input, i.e. for error messages
|
||
upcomingInput: function upcomingInput() {
|
||
var next = this.match;
|
||
if (next.length < 20) {
|
||
next += this._input.substr(0, 20 - next.length);
|
||
}
|
||
return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
|
||
},
|
||
|
||
// displays the character position where the lexing error occurred, i.e. for error messages
|
||
showPosition: function showPosition() {
|
||
var pre = this.pastInput();
|
||
var c = new Array(pre.length + 1).join("-");
|
||
return pre + this.upcomingInput() + "\n" + c + "^";
|
||
},
|
||
|
||
// test the lexed token: return FALSE when not a match, otherwise return token
|
||
test_match: function test_match(match, indexed_rule) {
|
||
var token, lines, backup;
|
||
|
||
if (this.options.backtrack_lexer) {
|
||
// save context
|
||
backup = {
|
||
yylineno: this.yylineno,
|
||
yylloc: {
|
||
first_line: this.yylloc.first_line,
|
||
last_line: this.last_line,
|
||
first_column: this.yylloc.first_column,
|
||
last_column: this.yylloc.last_column
|
||
},
|
||
yytext: this.yytext,
|
||
match: this.match,
|
||
matches: this.matches,
|
||
matched: this.matched,
|
||
yyleng: this.yyleng,
|
||
offset: this.offset,
|
||
_more: this._more,
|
||
_input: this._input,
|
||
yy: this.yy,
|
||
conditionStack: this.conditionStack.slice(0),
|
||
done: this.done
|
||
};
|
||
if (this.options.ranges) {
|
||
backup.yylloc.range = this.yylloc.range.slice(0);
|
||
}
|
||
}
|
||
|
||
lines = match[0].match(/(?:\r\n?|\n).*/g);
|
||
if (lines) {
|
||
this.yylineno += lines.length;
|
||
}
|
||
this.yylloc = {
|
||
first_line: this.yylloc.last_line,
|
||
last_line: this.yylineno + 1,
|
||
first_column: this.yylloc.last_column,
|
||
last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length
|
||
};
|
||
this.yytext += match[0];
|
||
this.match += match[0];
|
||
this.matches = match;
|
||
this.yyleng = this.yytext.length;
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [this.offset, this.offset += this.yyleng];
|
||
}
|
||
this._more = false;
|
||
this._backtrack = false;
|
||
this._input = this._input.slice(match[0].length);
|
||
this.matched += match[0];
|
||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
|
||
if (this.done && this._input) {
|
||
this.done = false;
|
||
}
|
||
if (token) {
|
||
return token;
|
||
} else if (this._backtrack) {
|
||
// recover context
|
||
for (var k in backup) {
|
||
this[k] = backup[k];
|
||
}
|
||
return false; // rule action called reject() implying the next rule should be tested instead.
|
||
}
|
||
return false;
|
||
},
|
||
|
||
// return next match in input
|
||
next: function next() {
|
||
if (this.done) {
|
||
return this.EOF;
|
||
}
|
||
if (!this._input) {
|
||
this.done = true;
|
||
}
|
||
|
||
var token, match, tempMatch, index;
|
||
if (!this._more) {
|
||
this.yytext = '';
|
||
this.match = '';
|
||
}
|
||
var rules = this._currentRules();
|
||
for (var i = 0; i < rules.length; i++) {
|
||
tempMatch = this._input.match(this.rules[rules[i]]);
|
||
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
|
||
match = tempMatch;
|
||
index = i;
|
||
if (this.options.backtrack_lexer) {
|
||
token = this.test_match(tempMatch, rules[i]);
|
||
if (token !== false) {
|
||
return token;
|
||
} else if (this._backtrack) {
|
||
match = false;
|
||
continue; // rule action called reject() implying a rule MISmatch.
|
||
} else {
|
||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||
return false;
|
||
}
|
||
} else if (!this.options.flex) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (match) {
|
||
token = this.test_match(match, rules[index]);
|
||
if (token !== false) {
|
||
return token;
|
||
}
|
||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||
return false;
|
||
}
|
||
if (this._input === "") {
|
||
return this.EOF;
|
||
} else {
|
||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
|
||
text: "",
|
||
token: null,
|
||
line: this.yylineno
|
||
});
|
||
}
|
||
},
|
||
|
||
// return next match that has a token
|
||
lex: function lex() {
|
||
var r = this.next();
|
||
if (r) {
|
||
return r;
|
||
} else {
|
||
return this.lex();
|
||
}
|
||
},
|
||
|
||
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
|
||
begin: function begin(condition) {
|
||
this.conditionStack.push(condition);
|
||
},
|
||
|
||
// pop the previously active lexer condition state off the condition stack
|
||
popState: function popState() {
|
||
var n = this.conditionStack.length - 1;
|
||
if (n > 0) {
|
||
return this.conditionStack.pop();
|
||
} else {
|
||
return this.conditionStack[0];
|
||
}
|
||
},
|
||
|
||
// produce the lexer rule set which is active for the currently active lexer condition state
|
||
_currentRules: function _currentRules() {
|
||
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
|
||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
|
||
} else {
|
||
return this.conditions["INITIAL"].rules;
|
||
}
|
||
},
|
||
|
||
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
|
||
topState: function topState(n) {
|
||
n = this.conditionStack.length - 1 - Math.abs(n || 0);
|
||
if (n >= 0) {
|
||
return this.conditionStack[n];
|
||
} else {
|
||
return "INITIAL";
|
||
}
|
||
},
|
||
|
||
// alias for begin(condition)
|
||
pushState: function pushState(condition) {
|
||
this.begin(condition);
|
||
},
|
||
|
||
// return the number of states currently on the stack
|
||
stateStackSize: function stateStackSize() {
|
||
return this.conditionStack.length;
|
||
},
|
||
options: { "case-insensitive": true },
|
||
performAction: function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
|
||
// Pre-lexer code can go here
|
||
|
||
var YYSTATE = YY_START;
|
||
switch ($avoiding_name_collisions) {
|
||
case 0:
|
||
return 9;
|
||
break;
|
||
case 1:
|
||
return 10;
|
||
break;
|
||
case 2:
|
||
return 4;
|
||
break;
|
||
case 3:
|
||
return 12;
|
||
break;
|
||
case 4:
|
||
return 13;
|
||
break;
|
||
case 5:
|
||
return 6;
|
||
break;
|
||
case 6:
|
||
return 'INVALID';
|
||
break;
|
||
}
|
||
},
|
||
rules: [/^(?:[\n]+)/i, /^(?:showInfo\b)/i, /^(?:info\b)/i, /^(?:say\b)/i, /^(?::[^#\n;]+)/i, /^(?:$)/i, /^(?:.)/i],
|
||
conditions: { "INITIAL": { "rules": [0, 1, 2, 3, 4, 5, 6], "inclusive": true } }
|
||
};
|
||
return lexer;
|
||
})();
|
||
parser.lexer = lexer;
|
||
function Parser() {
|
||
this.yy = {};
|
||
}
|
||
Parser.prototype = parser;parser.Parser = Parser;
|
||
return new Parser();
|
||
})();
|
||
|
||
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
|
||
exports.parser = example;
|
||
exports.Parser = example.Parser;
|
||
exports.parse = function () {
|
||
return example.parse.apply(example, arguments);
|
||
};
|
||
exports.main = function commonjsMain(args) {
|
||
if (!args[1]) {
|
||
console.log('Usage: ' + args[0] + ' FILE');
|
||
process.exit(1);
|
||
}
|
||
var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
|
||
return exports.parser.parse(source);
|
||
};
|
||
if (typeof module !== 'undefined' && require.main === module) {
|
||
exports.main(process.argv.slice(1));
|
||
}
|
||
}
|
||
|
||
}).call(this,require('_process'))
|
||
},{"_process":3,"fs":1,"path":2}],114:[function(require,module,exports){
|
||
/* global window */
|
||
'use strict';
|
||
|
||
var Logger = require('../../logger');
|
||
var log = new Logger.Log();
|
||
|
||
var dagreD3;
|
||
//log.debug('setting up dagre-d3');
|
||
if (require) {
|
||
try {
|
||
dagreD3 = require('dagre-d3');
|
||
//log.debug('Got it (dagre-d3)');
|
||
} catch (e) {
|
||
log.debug('Could not load dagre-d3');
|
||
}
|
||
}
|
||
|
||
if (!dagreD3) {
|
||
dagreD3 = window.dagreD3;
|
||
}
|
||
|
||
module.exports = dagreD3;
|
||
|
||
},{"../../logger":126,"dagre-d3":5}],115:[function(require,module,exports){
|
||
/**
|
||
* Created by knut on 14-12-11.
|
||
*/
|
||
'use strict';
|
||
|
||
var graph = require('./graphDb');
|
||
var flow = require('./parser/flow');
|
||
var dot = require('./parser/dot');
|
||
var d3 = require('../../d3');
|
||
var dagreD3 = require('./dagre-d3');
|
||
var Logger = require('../../logger');
|
||
var log = new Logger.Log();
|
||
|
||
var conf = {};
|
||
module.exports.setConf = function (cnf) {
|
||
var keys = Object.keys(cnf);
|
||
var i;
|
||
for (i = 0; i < keys.length; i++) {
|
||
conf[keys[i]] = cnf[keys[i]];
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Function that adds the vertices found in the graph definition to the graph to be rendered.
|
||
* @param vert Object containing the vertices.
|
||
* @param g The graph that is to be drawn.
|
||
*/
|
||
exports.addVertices = function (vert, g) {
|
||
var keys = Object.keys(vert);
|
||
|
||
var styleFromStyleArr = function styleFromStyleArr(styleStr, arr) {
|
||
var i;
|
||
// Create a compound style definition from the style definitions found for the node in the graph definition
|
||
for (i = 0; i < arr.length; i++) {
|
||
if (typeof arr[i] !== 'undefined') {
|
||
styleStr = styleStr + arr[i] + ';';
|
||
}
|
||
}
|
||
|
||
return styleStr;
|
||
};
|
||
|
||
// Iterate through each item in the vertice object (containing all the vertices found) in the graph definition
|
||
keys.forEach(function (id) {
|
||
var vertice = vert[id];
|
||
var verticeText;
|
||
|
||
/**
|
||
* Variable for storing the classes for the vertice
|
||
* @type {string}
|
||
*/
|
||
var classStr = '';
|
||
|
||
//log.debug(vertice.classes);
|
||
|
||
if (vertice.classes.length > 0) {
|
||
classStr = vertice.classes.join(' ');
|
||
}
|
||
|
||
/**
|
||
* Variable for storing the extracted style for the vertice
|
||
* @type {string}
|
||
*/
|
||
var style = '';
|
||
// Create a compound style definition from the style definitions found for the node in the graph definition
|
||
style = styleFromStyleArr(style, vertice.styles);
|
||
|
||
// Use vertice id as text in the box if no text is provided by the graph definition
|
||
if (typeof vertice.text === 'undefined') {
|
||
verticeText = vertice.id;
|
||
} else {
|
||
verticeText = vertice.text;
|
||
}
|
||
|
||
var labelTypeStr = '';
|
||
if (conf.htmlLabels) {
|
||
labelTypeStr = 'html';
|
||
verticeText = verticeText.replace(/fa:fa[\w\-]+/g, function (s) {
|
||
return '<i class="fa ' + s.substring(3) + '"></i>';
|
||
});
|
||
} else {
|
||
verticeText = verticeText.replace(/<br>/g, '\n');
|
||
labelTypeStr = 'text';
|
||
}
|
||
|
||
var radious = 0;
|
||
var _shape = '';
|
||
|
||
// Set the shape based parameters
|
||
switch (vertice.type) {
|
||
case 'round':
|
||
radious = 5;
|
||
_shape = 'rect';
|
||
break;
|
||
case 'square':
|
||
_shape = 'rect';
|
||
break;
|
||
case 'diamond':
|
||
_shape = 'question';
|
||
break;
|
||
case 'odd':
|
||
_shape = 'rect_left_inv_arrow';
|
||
break;
|
||
case 'odd_right':
|
||
_shape = 'rect_left_inv_arrow';
|
||
break;
|
||
case 'circle':
|
||
_shape = 'circle';
|
||
break;
|
||
case 'ellipse':
|
||
_shape = 'ellipse';
|
||
break;
|
||
case 'group':
|
||
_shape = 'rect';
|
||
verticeText = '';
|
||
break;
|
||
default:
|
||
_shape = 'rect';
|
||
}
|
||
// Add the node
|
||
g.setNode(vertice.id, { labelType: labelTypeStr, shape: _shape, label: verticeText, rx: radious, ry: radious, 'class': classStr, style: style, id: vertice.id });
|
||
});
|
||
};
|
||
|
||
/**
|
||
* Add edges to graph based on parsed graph defninition
|
||
* @param {Object} edges The edges to add to the graph
|
||
* @param {Object} g The graph object
|
||
*/
|
||
exports.addEdges = function (edges, g) {
|
||
var cnt = 0;
|
||
var aHead;
|
||
|
||
var defaultStyle;
|
||
if (typeof edges.defaultStyle !== 'undefined') {
|
||
defaultStyle = edges.defaultStyle.toString().replace(/,/g, ';');
|
||
}
|
||
|
||
edges.forEach(function (edge) {
|
||
cnt++;
|
||
|
||
// Set link type for rendering
|
||
if (edge.type === 'arrow_open') {
|
||
aHead = 'none';
|
||
} else {
|
||
aHead = 'normal';
|
||
}
|
||
|
||
var style = '';
|
||
|
||
if (typeof edge.style !== 'undefined') {
|
||
edge.style.forEach(function (s) {
|
||
style = style + s + ';';
|
||
});
|
||
} else {
|
||
switch (edge.stroke) {
|
||
case 'normal':
|
||
style = 'fill:none';
|
||
if (typeof defaultStyle !== 'undefined') {
|
||
style = defaultStyle;
|
||
}
|
||
break;
|
||
case 'dotted':
|
||
style = 'stroke: #333; fill:none;stroke-width:2px;stroke-dasharray:3;';
|
||
break;
|
||
case 'thick':
|
||
style = 'stroke: #333; stroke-width: 3.5px;fill:none';
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Add the edge to the graph
|
||
if (typeof edge.text === 'undefined') {
|
||
if (typeof edge.style === 'undefined') {
|
||
g.setEdge(edge.start, edge.end, { style: style, arrowhead: aHead }, cnt);
|
||
} else {
|
||
g.setEdge(edge.start, edge.end, {
|
||
style: style, arrowheadStyle: 'fill: #333', arrowhead: aHead
|
||
}, cnt);
|
||
}
|
||
}
|
||
// Edge with text
|
||
else {
|
||
var edgeText = edge.text.replace(/<br>/g, '\n');
|
||
if (typeof edge.style === 'undefined') {
|
||
if (conf.htmlLabels) {
|
||
g.setEdge(edge.start, edge.end, { labelType: 'html', style: style, labelpos: 'c', label: '<span class="edgeLabel">' + edge.text + '</span>', arrowheadStyle: 'fill: #333', arrowhead: aHead }, cnt);
|
||
} else {
|
||
g.setEdge(edge.start, edge.end, { labelType: 'text', style: 'stroke: #333; stroke-width: 1.5px;fill:none', labelpos: 'c', label: edgeText, arrowheadStyle: 'fill: #333', arrowhead: aHead }, cnt);
|
||
}
|
||
} else {
|
||
g.setEdge(edge.start, edge.end, {
|
||
labelType: 'text', style: style, arrowheadStyle: 'fill: #333', label: edgeText, arrowhead: aHead
|
||
}, cnt);
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
/**
|
||
* Returns the all the styles from classDef statements in the graph definition.
|
||
* @returns {object} classDef styles
|
||
*/
|
||
exports.getClasses = function (text, isDot) {
|
||
var parser;
|
||
graph.clear();
|
||
if (isDot) {
|
||
parser = dot.parser;
|
||
} else {
|
||
parser = flow.parser;
|
||
}
|
||
parser.yy = graph;
|
||
|
||
// Parse the graph definition
|
||
parser.parse(text);
|
||
|
||
var classes = graph.getClasses();
|
||
|
||
// Add default class if undefined
|
||
if (typeof classes['default'] === 'undefined') {
|
||
classes['default'] = { id: 'default' };
|
||
//classes.default.styles = ['fill:#ffa','stroke:#666','stroke-width:3px'];
|
||
classes['default'].styles = [];
|
||
classes['default'].clusterStyles = ['rx:4px', 'fill: rgb(255, 255, 222)', 'rx: 4px', 'stroke: rgb(170, 170, 51)', 'stroke-width: 1px'];
|
||
classes['default'].nodeLabelStyles = ['fill:#000', 'stroke:none', 'font-weight:300', 'font-family:"Helvetica Neue",Helvetica,Arial,sans-serf', 'font-size:14px'];
|
||
classes['default'].edgeLabelStyles = ['fill:#000', 'stroke:none', 'font-weight:300', 'font-family:"Helvetica Neue",Helvetica,Arial,sans-serf', 'font-size:14px'];
|
||
}
|
||
return classes;
|
||
};
|
||
|
||
/**
|
||
* Draws a flowchart in the tag with id: id based on the graph definition in text.
|
||
* @param text
|
||
* @param id
|
||
*/
|
||
exports.draw = function (text, id, isDot) {
|
||
log.debug('Drawing flowchart');
|
||
var parser;
|
||
graph.clear();
|
||
if (isDot) {
|
||
parser = dot.parser;
|
||
} else {
|
||
parser = flow.parser;
|
||
}
|
||
parser.yy = graph;
|
||
|
||
// Parse the graph definition
|
||
try {
|
||
|
||
parser.parse(text);
|
||
} catch (err) {
|
||
log.debug('Parsing failed');
|
||
}
|
||
|
||
// Fetch the default direction, use TD if none was found
|
||
var dir;
|
||
dir = graph.getDirection();
|
||
if (typeof dir === 'undefined') {
|
||
dir = 'TD';
|
||
}
|
||
|
||
// Create the input mermaid.graph
|
||
var g = new dagreD3.graphlib.Graph({
|
||
multigraph: true,
|
||
compound: true
|
||
}).setGraph({
|
||
rankdir: dir,
|
||
marginx: 20,
|
||
marginy: 20
|
||
|
||
}).setDefaultEdgeLabel(function () {
|
||
return {};
|
||
});
|
||
|
||
var subG;
|
||
var subGraphs = graph.getSubGraphs();
|
||
var i = 0;
|
||
for (i = subGraphs.length - 1; i >= 0; i--) {
|
||
subG = subGraphs[i];
|
||
graph.addVertex(subG.id, subG.title, 'group', undefined);
|
||
}
|
||
|
||
// Fetch the verices/nodes and edges/links from the parsed graph definition
|
||
var vert = graph.getVertices();
|
||
|
||
//log.debug(vert);
|
||
var edges = graph.getEdges();
|
||
|
||
i = 0;
|
||
var j;
|
||
for (i = subGraphs.length - 1; i >= 0; i--) {
|
||
subG = subGraphs[i];
|
||
|
||
d3.selectAll('cluster').append('text');
|
||
|
||
for (j = 0; j < subG.nodes.length; j++) {
|
||
//log.debug('Setting node',subG.nodes[j],' to subgraph '+id);
|
||
g.setParent(subG.nodes[j], subG.id);
|
||
}
|
||
}
|
||
exports.addVertices(vert, g);
|
||
exports.addEdges(edges, g);
|
||
|
||
// Create the renderer
|
||
var render = new dagreD3.render();
|
||
|
||
// Add custom shape for rhombus type of boc (decision)
|
||
render.shapes().question = function (parent, bbox, node) {
|
||
var w = bbox.width,
|
||
h = bbox.height,
|
||
s = (w + h) * 0.8,
|
||
points = [{ x: s / 2, y: 0 }, { x: s, y: -s / 2 }, { x: s / 2, y: -s }, { x: 0, y: -s / 2 }];
|
||
var shapeSvg = parent.insert('polygon', ':first-child').attr('points', points.map(function (d) {
|
||
return d.x + ',' + d.y;
|
||
}).join(' ')).attr('rx', 5).attr('ry', 5).attr('transform', 'translate(' + -s / 2 + ',' + s * 2 / 4 + ')');
|
||
node.intersect = function (point) {
|
||
return dagreD3.intersect.polygon(node, points, point);
|
||
};
|
||
return shapeSvg;
|
||
};
|
||
|
||
// Add custom shape for box with inverted arrow on left side
|
||
render.shapes().rect_left_inv_arrow = function (parent, bbox, node) {
|
||
var w = bbox.width,
|
||
h = bbox.height,
|
||
points = [{ x: -h / 2, y: 0 }, { x: w, y: 0 }, { x: w, y: -h }, { x: -h / 2, y: -h }, { x: 0, y: -h / 2 }];
|
||
var shapeSvg = parent.insert('polygon', ':first-child').attr('points', points.map(function (d) {
|
||
return d.x + ',' + d.y;
|
||
}).join(' ')).attr('transform', 'translate(' + -w / 2 + ',' + h * 2 / 4 + ')');
|
||
node.intersect = function (point) {
|
||
return dagreD3.intersect.polygon(node, points, point);
|
||
};
|
||
return shapeSvg;
|
||
};
|
||
|
||
// Add custom shape for box with inverted arrow on right side
|
||
render.shapes().rect_right_inv_arrow = function (parent, bbox, node) {
|
||
var w = bbox.width,
|
||
h = bbox.height,
|
||
points = [{ x: 0, y: 0 }, { x: w + h / 2, y: 0 }, { x: w, y: -h / 2 }, { x: w + h / 2, y: -h }, { x: 0, y: -h }];
|
||
var shapeSvg = parent.insert('polygon', ':first-child').attr('points', points.map(function (d) {
|
||
return d.x + ',' + d.y;
|
||
}).join(' ')).attr('transform', 'translate(' + -w / 2 + ',' + h * 2 / 4 + ')');
|
||
node.intersect = function (point) {
|
||
return dagreD3.intersect.polygon(node, points, point);
|
||
};
|
||
return shapeSvg;
|
||
};
|
||
|
||
// Add our custom arrow - an empty arrowhead
|
||
render.arrows().none = function normal(parent, id, edge, type) {
|
||
var marker = parent.append('marker').attr('id', id).attr('viewBox', '0 0 10 10').attr('refX', 9).attr('refY', 5).attr('markerUnits', 'strokeWidth').attr('markerWidth', 8).attr('markerHeight', 6).attr('orient', 'auto');
|
||
|
||
var path = marker.append('path').attr('d', 'M 0 0 L 0 0 L 0 0 z');
|
||
dagreD3.util.applyStyle(path, edge[type + 'Style']);
|
||
};
|
||
|
||
// Set up an SVG group so that we can translate the final graph.
|
||
var svg = d3.select('#' + id);
|
||
//svgGroup = d3.select('#' + id + ' g');
|
||
|
||
// Run the renderer. This is what draws the final graph.
|
||
var element = d3.select('#' + id + ' g');
|
||
render(element, g);
|
||
|
||
//var tip = d3.tip().html(function(d) { return d; });
|
||
element.selectAll('g.node').attr('title', function () {
|
||
return graph.getTooltip(this.id);
|
||
});
|
||
|
||
/*
|
||
var xPos = document.querySelectorAll('.clusters rect')[0].x.baseVal.value;
|
||
var width = document.querySelectorAll('.clusters rect')[0].width.baseVal.value;
|
||
var cluster = d3.selectAll('.cluster');
|
||
var te = cluster.append('text');
|
||
te.attr('x', xPos+width/2);
|
||
te.attr('y', 12);
|
||
//te.stroke('black');
|
||
te.attr('id', 'apa12');
|
||
te.style('text-anchor', 'middle');
|
||
te.text('Title for cluster');
|
||
*/
|
||
if (conf.useMaxWidth) {
|
||
// Center the graph
|
||
svg.attr('height', '100%');
|
||
svg.attr('width', conf.width);
|
||
//svg.attr('viewBox', svgb.getBBox().x + ' 0 '+ g.graph().width+' '+ g.graph().height);
|
||
svg.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20));
|
||
svg.attr('style', 'max-width:' + (g.graph().width + 20) + 'px;');
|
||
} else {
|
||
// Center the graph
|
||
svg.attr('height', g.graph().height);
|
||
if (typeof conf.width === 'undefined') {
|
||
svg.attr('width', g.graph().width);
|
||
} else {
|
||
svg.attr('width', conf.width);
|
||
}
|
||
//svg.attr('viewBox', svgb.getBBox().x + ' 0 '+ g.graph().width+' '+ g.graph().height);
|
||
svg.attr('viewBox', '0 0 ' + (g.graph().width + 20) + ' ' + (g.graph().height + 20));
|
||
}
|
||
|
||
// Index nodes
|
||
graph.indexNodes('subGraph' + i);
|
||
|
||
for (i = 0; i < subGraphs.length; i++) {
|
||
subG = subGraphs[i];
|
||
|
||
if (subG.title !== 'undefined') {
|
||
var clusterRects = document.querySelectorAll('#' + id + ' #' + subG.id + ' rect');
|
||
//log.debug('looking up: #' + id + ' #' + subG.id)
|
||
var clusterEl = document.querySelectorAll('#' + id + ' #' + subG.id);
|
||
|
||
var xPos = clusterRects[0].x.baseVal.value;
|
||
var yPos = clusterRects[0].y.baseVal.value;
|
||
var width = clusterRects[0].width.baseVal.value;
|
||
var cluster = d3.select(clusterEl[0]);
|
||
var te = cluster.append('text');
|
||
te.attr('x', xPos + width / 2);
|
||
te.attr('y', yPos + 14);
|
||
te.attr('fill', 'black');
|
||
te.attr('stroke', 'none');
|
||
te.attr('id', id + 'Text');
|
||
te.style('text-anchor', 'middle');
|
||
|
||
if (typeof subG.title === 'undefined') {
|
||
te.text('Undef');
|
||
} else {
|
||
//te.text(subGraphs[subGraphs.length-i-1].title);
|
||
te.text(subG.title);
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
},{"../../d3":107,"../../logger":126,"./dagre-d3":114,"./graphDb":116,"./parser/dot":117,"./parser/flow":118}],116:[function(require,module,exports){
|
||
(function (global){
|
||
/**
|
||
* Created by knut on 14-11-03.
|
||
*/
|
||
'use strict';
|
||
|
||
var Logger = require('../../logger');
|
||
var log = new Logger.Log();
|
||
|
||
var d3 = require('../../d3');
|
||
var vertices = {};
|
||
var edges = [];
|
||
var classes = [];
|
||
var subGraphs = [];
|
||
var tooltips = {};
|
||
var subCount = 0;
|
||
var direction;
|
||
// Functions to be run after graph rendering
|
||
var funs = [];
|
||
/**
|
||
* Function called by parser when a node definition has been found
|
||
* @param id
|
||
* @param text
|
||
* @param type
|
||
* @param style
|
||
*/
|
||
exports.addVertex = function (id, text, type, style) {
|
||
var txt;
|
||
|
||
if (typeof id === 'undefined') {
|
||
return;
|
||
}
|
||
if (id.trim().length === 0) {
|
||
return;
|
||
}
|
||
|
||
if (typeof vertices[id] === 'undefined') {
|
||
vertices[id] = { id: id, styles: [], classes: [] };
|
||
}
|
||
if (typeof text !== 'undefined') {
|
||
txt = text.trim();
|
||
|
||
// strip quotes if string starts and exnds with a quote
|
||
if (txt[0] === '"' && txt[txt.length - 1] === '"') {
|
||
txt = txt.substring(1, txt.length - 1);
|
||
}
|
||
|
||
vertices[id].text = txt;
|
||
}
|
||
if (typeof type !== 'undefined') {
|
||
vertices[id].type = type;
|
||
}
|
||
if (typeof type !== 'undefined') {
|
||
vertices[id].type = type;
|
||
}
|
||
if (typeof style !== 'undefined') {
|
||
if (style !== null) {
|
||
style.forEach(function (s) {
|
||
vertices[id].styles.push(s);
|
||
});
|
||
}
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Function called by parser when a link/edge definition has been found
|
||
* @param start
|
||
* @param end
|
||
* @param type
|
||
* @param linktext
|
||
*/
|
||
exports.addLink = function (start, end, type, linktext) {
|
||
log.debug('Got edge', start, end);
|
||
var edge = { start: start, end: end, type: undefined, text: '' };
|
||
linktext = type.text;
|
||
|
||
if (typeof linktext !== 'undefined') {
|
||
edge.text = linktext.trim();
|
||
|
||
// strip quotes if string starts and exnds with a quote
|
||
if (edge.text[0] === '"' && edge.text[edge.text.length - 1] === '"') {
|
||
edge.text = edge.text.substring(1, edge.text.length - 1);
|
||
}
|
||
}
|
||
|
||
if (typeof type !== 'undefined') {
|
||
edge.type = type.type;
|
||
edge.stroke = type.stroke;
|
||
}
|
||
edges.push(edge);
|
||
};
|
||
/**
|
||
* Updates a link with a style
|
||
* @param pos
|
||
* @param style
|
||
*/
|
||
exports.updateLink = function (pos, style) {
|
||
if (pos === 'default') {
|
||
edges.defaultStyle = style;
|
||
} else {
|
||
edges[pos].style = style;
|
||
}
|
||
};
|
||
|
||
exports.addClass = function (id, style) {
|
||
if (typeof classes[id] === 'undefined') {
|
||
classes[id] = { id: id, styles: [] };
|
||
}
|
||
|
||
if (typeof style !== 'undefined') {
|
||
if (style !== null) {
|
||
style.forEach(function (s) {
|
||
classes[id].styles.push(s);
|
||
});
|
||
}
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Called by parser when a graph definition is found, stores the direction of the chart.
|
||
* @param dir
|
||
*/
|
||
exports.setDirection = function (dir) {
|
||
direction = dir;
|
||
};
|
||
|
||
/**
|
||
* Called by parser when a graph definition is found, stores the direction of the chart.
|
||
* @param dir
|
||
*/
|
||
exports.setClass = function (id, className) {
|
||
if (id.indexOf(',') > 0) {
|
||
id.split(',').forEach(function (id2) {
|
||
if (typeof vertices[id2] !== 'undefined') {
|
||
vertices[id2].classes.push(className);
|
||
}
|
||
});
|
||
} else {
|
||
if (typeof vertices[id] !== 'undefined') {
|
||
vertices[id].classes.push(className);
|
||
}
|
||
}
|
||
};
|
||
|
||
var setTooltip = function setTooltip(id, tooltip) {
|
||
if (typeof tooltip !== 'undefined') {
|
||
tooltips[id] = tooltip;
|
||
}
|
||
};
|
||
|
||
var setClickFun = function setClickFun(id, functionName) {
|
||
if (typeof functionName === 'undefined') {
|
||
return;
|
||
}
|
||
if (typeof vertices[id] !== 'undefined') {
|
||
funs.push(function (element) {
|
||
var elem = d3.select(element).select('#' + id);
|
||
if (elem !== null) {
|
||
elem.on('click', function () {
|
||
eval(functionName + '(\'' + id + '\')'); // jshint ignore:line
|
||
});
|
||
}
|
||
});
|
||
}
|
||
};
|
||
|
||
var setLink = function setLink(id, linkStr) {
|
||
if (typeof linkStr === 'undefined') {
|
||
return;
|
||
}
|
||
if (typeof vertices[id] !== 'undefined') {
|
||
funs.push(function (element) {
|
||
var elem = d3.select(element).select('#' + id);
|
||
if (elem !== null) {
|
||
elem.on('click', function () {
|
||
window.open(linkStr, 'newTab'); // jshint ignore:line
|
||
});
|
||
}
|
||
});
|
||
}
|
||
};
|
||
exports.getTooltip = function (id) {
|
||
return tooltips[id];
|
||
};
|
||
|
||
/**
|
||
* Called by parser when a graph definition is found, stores the direction of the chart.
|
||
* @param dir
|
||
*/
|
||
exports.setClickEvent = function (id, functionName, link, tooltip) {
|
||
if (id.indexOf(',') > 0) {
|
||
id.split(',').forEach(function (id2) {
|
||
setTooltip(id2, tooltip);
|
||
setClickFun(id2, functionName);
|
||
setLink(id2, link);
|
||
});
|
||
} else {
|
||
setTooltip(id, tooltip);
|
||
setClickFun(id, functionName);
|
||
setLink(id, link);
|
||
}
|
||
};
|
||
|
||
exports.bindFunctions = function (element) {
|
||
funs.forEach(function (fun) {
|
||
fun(element);
|
||
});
|
||
};
|
||
exports.getDirection = function () {
|
||
return direction;
|
||
};
|
||
/**
|
||
* Retrieval function for fetching the found nodes after parsing has completed.
|
||
* @returns {{}|*|vertices}
|
||
*/
|
||
exports.getVertices = function () {
|
||
return vertices;
|
||
};
|
||
|
||
/**
|
||
* Retrieval function for fetching the found links after parsing has completed.
|
||
* @returns {{}|*|edges}
|
||
*/
|
||
exports.getEdges = function () {
|
||
return edges;
|
||
};
|
||
|
||
/**
|
||
* Retrieval function for fetching the found class definitions after parsing has completed.
|
||
* @returns {{}|*|classes}
|
||
*/
|
||
exports.getClasses = function () {
|
||
return classes;
|
||
};
|
||
|
||
var setupToolTips = function setupToolTips(element) {
|
||
|
||
var tooltipElem = d3.select('.mermaidTooltip');
|
||
if (tooltipElem[0][0] === null) {
|
||
tooltipElem = d3.select('body').append('div').attr('class', 'mermaidTooltip').style('opacity', 0);
|
||
}
|
||
|
||
var svg = d3.select(element).select('svg');
|
||
|
||
var nodes = svg.selectAll('g.node');
|
||
nodes.on('mouseover', function () {
|
||
var el = d3.select(this);
|
||
var title = el.attr('title');
|
||
// Dont try to draw a tooltip if no data is provided
|
||
if (title === null) {
|
||
return;
|
||
}
|
||
var rect = this.getBoundingClientRect();
|
||
|
||
tooltipElem.transition().duration(200).style('opacity', '.9');
|
||
tooltipElem.html(el.attr('title')).style('left', rect.left + (rect.right - rect.left) / 2 + 'px').style('top', rect.top - 14 + document.body.scrollTop + 'px');
|
||
el.classed('hover', true);
|
||
}).on('mouseout', function () {
|
||
tooltipElem.transition().duration(500).style('opacity', 0);
|
||
var el = d3.select(this);
|
||
el.classed('hover', false);
|
||
});
|
||
};
|
||
funs.push(setupToolTips);
|
||
|
||
/**
|
||
* Clears the internal graph db so that a new graph can be parsed.
|
||
*/
|
||
exports.clear = function () {
|
||
vertices = {};
|
||
classes = {};
|
||
edges = [];
|
||
funs = [];
|
||
funs.push(setupToolTips);
|
||
subGraphs = [];
|
||
subCount = 0;
|
||
tooltips = [];
|
||
};
|
||
/**
|
||
*
|
||
* @returns {string}
|
||
*/
|
||
exports.defaultStyle = function () {
|
||
return 'fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;';
|
||
};
|
||
|
||
/**
|
||
* Clears the internal graph db so that a new graph can be parsed.
|
||
*/
|
||
exports.addSubGraph = function (list, title) {
|
||
function uniq(a) {
|
||
var prims = { 'boolean': {}, 'number': {}, 'string': {} },
|
||
objs = [];
|
||
|
||
return a.filter(function (item) {
|
||
var type = typeof item;
|
||
if (item === ' ') {
|
||
return false;
|
||
}
|
||
if (type in prims) return prims[type].hasOwnProperty(item) ? false : prims[type][item] = true;else return objs.indexOf(item) >= 0 ? false : objs.push(item);
|
||
});
|
||
}
|
||
|
||
var nodeList = [];
|
||
|
||
nodeList = uniq(nodeList.concat.apply(nodeList, list));
|
||
|
||
var subGraph = { id: 'subGraph' + subCount, nodes: nodeList, title: title };
|
||
//log.debug('subGraph:' + subGraph.title + subGraph.id);
|
||
//log.debug(subGraph.nodes);
|
||
subGraphs.push(subGraph);
|
||
subCount = subCount + 1;
|
||
return subGraph.id;
|
||
};
|
||
|
||
var getPosForId = function getPosForId(id) {
|
||
var i;
|
||
for (i = 0; i < subGraphs.length; i++) {
|
||
if (subGraphs[i].id === id) {
|
||
//log.debug('Found pos for ',id,' ',i);
|
||
return i;
|
||
}
|
||
}
|
||
//log.debug('No pos found for ',id,' ',i);
|
||
return -1;
|
||
};
|
||
var secCount = -1;
|
||
var posCrossRef = [];
|
||
var indexNodes = function indexNodes(id, pos) {
|
||
var nodes = subGraphs[pos].nodes;
|
||
secCount = secCount + 1;
|
||
if (secCount > 2000) {
|
||
return;
|
||
}
|
||
//var nPos = getPosForId(subGraphs[pos].id);
|
||
posCrossRef[secCount] = pos;
|
||
// Check if match
|
||
if (subGraphs[pos].id === id) {
|
||
return {
|
||
result: true,
|
||
count: 0
|
||
};
|
||
}
|
||
|
||
var count = 0;
|
||
var posCount = 1;
|
||
while (count < nodes.length) {
|
||
var childPos = getPosForId(nodes[count]);
|
||
// Ignore regular nodes (pos will be -1)
|
||
if (childPos >= 0) {
|
||
var res = indexNodes(id, childPos);
|
||
if (res.result) {
|
||
return {
|
||
result: true,
|
||
count: posCount + res.count
|
||
};
|
||
} else {
|
||
posCount = posCount + res.count;
|
||
}
|
||
}
|
||
count = count + 1;
|
||
}
|
||
|
||
return {
|
||
result: false,
|
||
count: posCount
|
||
};
|
||
};
|
||
|
||
exports.getDepthFirstPos = function (pos) {
|
||
return posCrossRef[pos];
|
||
};
|
||
exports.indexNodes = function () {
|
||
secCount = -1;
|
||
if (subGraphs.length > 0) {
|
||
indexNodes('none', subGraphs.length - 1, 0);
|
||
}
|
||
};
|
||
|
||
exports.getSubGraphs = function () {
|
||
return subGraphs;
|
||
};
|
||
|
||
exports.parseError = function (err, hash) {
|
||
global.mermaidAPI.parseError(err, hash);
|
||
};
|
||
|
||
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"../../d3":107,"../../logger":126}],117:[function(require,module,exports){
|
||
(function (process){
|
||
/* parser generated by jison 0.4.15 */
|
||
/*
|
||
Returns a Parser object of the following structure:
|
||
|
||
Parser: {
|
||
yy: {}
|
||
}
|
||
|
||
Parser.prototype: {
|
||
yy: {},
|
||
trace: function(),
|
||
symbols_: {associative list: name ==> number},
|
||
terminals_: {associative list: number ==> name},
|
||
productions_: [...],
|
||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
|
||
table: [...],
|
||
defaultActions: {...},
|
||
parseError: function(str, hash),
|
||
parse: function(input),
|
||
|
||
lexer: {
|
||
EOF: 1,
|
||
parseError: function(str, hash),
|
||
setInput: function(input),
|
||
input: function(),
|
||
unput: function(str),
|
||
more: function(),
|
||
less: function(n),
|
||
pastInput: function(),
|
||
upcomingInput: function(),
|
||
showPosition: function(),
|
||
test_match: function(regex_match_array, rule_index),
|
||
next: function(),
|
||
lex: function(),
|
||
begin: function(condition),
|
||
popState: function(),
|
||
_currentRules: function(),
|
||
topState: function(),
|
||
pushState: function(condition),
|
||
|
||
options: {
|
||
ranges: boolean (optional: true ==> token location info will include a .range[] member)
|
||
flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
|
||
backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
|
||
},
|
||
|
||
performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
|
||
rules: [...],
|
||
conditions: {associative list: name ==> set},
|
||
}
|
||
}
|
||
|
||
|
||
token location info (@$, _$, etc.): {
|
||
first_line: n,
|
||
last_line: n,
|
||
first_column: n,
|
||
last_column: n,
|
||
range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
|
||
}
|
||
|
||
|
||
the parseError function receives a 'hash' object with these members for lexer and parser errors: {
|
||
text: (matched text)
|
||
token: (the produced terminal token, if any)
|
||
line: (yylineno)
|
||
}
|
||
while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
|
||
loc: (yylloc)
|
||
expected: (string describing the set of expected tokens)
|
||
recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
|
||
}
|
||
*/
|
||
"use strict";
|
||
|
||
var dot = (function () {
|
||
var o = function o(k, v, _o, l) {
|
||
for (_o = _o || {}, l = k.length; l--; _o[k[l]] = v);return _o;
|
||
},
|
||
$V0 = [1, 5],
|
||
$V1 = [1, 6],
|
||
$V2 = [1, 12],
|
||
$V3 = [1, 13],
|
||
$V4 = [1, 14],
|
||
$V5 = [1, 15],
|
||
$V6 = [1, 16],
|
||
$V7 = [1, 17],
|
||
$V8 = [1, 18],
|
||
$V9 = [1, 19],
|
||
$Va = [1, 20],
|
||
$Vb = [1, 21],
|
||
$Vc = [1, 22],
|
||
$Vd = [8, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26],
|
||
$Ve = [1, 37],
|
||
$Vf = [1, 33],
|
||
$Vg = [1, 34],
|
||
$Vh = [1, 35],
|
||
$Vi = [1, 36],
|
||
$Vj = [8, 10, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 32, 37, 39, 40, 45, 57, 58],
|
||
$Vk = [10, 28],
|
||
$Vl = [10, 28, 37, 57, 58],
|
||
$Vm = [2, 49],
|
||
$Vn = [1, 45],
|
||
$Vo = [1, 48],
|
||
$Vp = [1, 49],
|
||
$Vq = [1, 52],
|
||
$Vr = [2, 65],
|
||
$Vs = [1, 65],
|
||
$Vt = [1, 66],
|
||
$Vu = [1, 67],
|
||
$Vv = [1, 68],
|
||
$Vw = [1, 69],
|
||
$Vx = [1, 70],
|
||
$Vy = [1, 71],
|
||
$Vz = [1, 72],
|
||
$VA = [1, 73],
|
||
$VB = [8, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 47],
|
||
$VC = [10, 28, 37];
|
||
var parser = { trace: function trace() {},
|
||
yy: {},
|
||
symbols_: { "error": 2, "expressions": 3, "graph": 4, "EOF": 5, "graphStatement": 6, "idStatement": 7, "{": 8, "stmt_list": 9, "}": 10, "strict": 11, "GRAPH": 12, "DIGRAPH": 13, "textNoTags": 14, "textNoTagsToken": 15, "ALPHA": 16, "NUM": 17, "COLON": 18, "PLUS": 19, "EQUALS": 20, "MULT": 21, "DOT": 22, "BRKT": 23, "SPACE": 24, "MINUS": 25, "keywords": 26, "stmt": 27, ";": 28, "node_stmt": 29, "edge_stmt": 30, "attr_stmt": 31, "=": 32, "subgraph": 33, "attr_list": 34, "NODE": 35, "EDGE": 36, "[": 37, "a_list": 38, "]": 39, ",": 40, "edgeRHS": 41, "node_id": 42, "edgeop": 43, "port": 44, ":": 45, "compass_pt": 46, "SUBGRAPH": 47, "n": 48, "ne": 49, "e": 50, "se": 51, "s": 52, "sw": 53, "w": 54, "nw": 55, "c": 56, "ARROW_POINT": 57, "ARROW_OPEN": 58, "$accept": 0, "$end": 1 },
|
||
terminals_: { 2: "error", 5: "EOF", 8: "{", 10: "}", 11: "strict", 12: "GRAPH", 13: "DIGRAPH", 16: "ALPHA", 17: "NUM", 18: "COLON", 19: "PLUS", 20: "EQUALS", 21: "MULT", 22: "DOT", 23: "BRKT", 24: "SPACE", 25: "MINUS", 26: "keywords", 28: ";", 32: "=", 35: "NODE", 36: "EDGE", 37: "[", 39: "]", 40: ",", 45: ":", 47: "SUBGRAPH", 48: "n", 49: "ne", 50: "e", 51: "se", 52: "s", 53: "sw", 54: "w", 55: "nw", 56: "c", 57: "ARROW_POINT", 58: "ARROW_OPEN" },
|
||
productions_: [0, [3, 2], [4, 5], [4, 6], [4, 4], [6, 1], [6, 1], [7, 1], [14, 1], [14, 2], [15, 1], [15, 1], [15, 1], [15, 1], [15, 1], [15, 1], [15, 1], [15, 1], [15, 1], [15, 1], [15, 1], [9, 1], [9, 3], [27, 1], [27, 1], [27, 1], [27, 3], [27, 1], [31, 2], [31, 2], [31, 2], [34, 4], [34, 3], [34, 3], [34, 2], [38, 5], [38, 5], [38, 3], [30, 3], [30, 3], [30, 2], [30, 2], [41, 3], [41, 3], [41, 2], [41, 2], [29, 2], [29, 1], [42, 2], [42, 1], [44, 4], [44, 2], [44, 2], [33, 5], [33, 4], [33, 3], [46, 1], [46, 1], [46, 1], [46, 1], [46, 1], [46, 1], [46, 1], [46, 1], [46, 1], [46, 0], [43, 1], [43, 1]],
|
||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, /* action[1] */$$, /* vstack */_$ /* lstack */) {
|
||
/* this == yyval */
|
||
|
||
var $0 = $$.length - 1;
|
||
switch (yystate) {
|
||
case 1:
|
||
this.$ = $$[$0 - 1];
|
||
break;
|
||
case 2:
|
||
this.$ = $$[$0 - 4];
|
||
break;
|
||
case 3:
|
||
this.$ = $$[$0 - 5];
|
||
break;
|
||
case 4:
|
||
this.$ = $$[$0 - 3];
|
||
break;
|
||
case 8:case 10:case 11:
|
||
this.$ = $$[$0];
|
||
break;
|
||
case 9:
|
||
this.$ = $$[$0 - 1] + '' + $$[$0];
|
||
break;
|
||
case 12:case 13:case 14:case 15:case 16:case 18:case 19:case 20:
|
||
this.$ = $$[$0];
|
||
break;
|
||
case 17:
|
||
this.$ = '<br>';
|
||
break;
|
||
case 39:
|
||
this.$ = 'oy';
|
||
break;
|
||
case 40:
|
||
|
||
yy.addLink($$[$0 - 1], $$[$0].id, $$[$0].op);
|
||
this.$ = 'oy';
|
||
break;
|
||
case 42:
|
||
|
||
yy.addLink($$[$0 - 1], $$[$0].id, $$[$0].op);
|
||
this.$ = { op: $$[$0 - 2], id: $$[$0 - 1] };
|
||
|
||
break;
|
||
case 44:
|
||
|
||
this.$ = { op: $$[$0 - 1], id: $$[$0] };
|
||
|
||
break;
|
||
case 48:
|
||
yy.addVertex($$[$0 - 1]);this.$ = $$[$0 - 1];
|
||
break;
|
||
case 49:
|
||
yy.addVertex($$[$0]);this.$ = $$[$0];
|
||
break;
|
||
case 66:
|
||
this.$ = 'arrow';
|
||
break;
|
||
case 67:
|
||
this.$ = 'arrow_open';
|
||
break;
|
||
}
|
||
},
|
||
table: [{ 3: 1, 4: 2, 6: 3, 11: [1, 4], 12: $V0, 13: $V1 }, { 1: [3] }, { 5: [1, 7] }, { 7: 8, 8: [1, 9], 14: 10, 15: 11, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc }, { 6: 23, 12: $V0, 13: $V1 }, o($Vd, [2, 5]), o($Vd, [2, 6]), { 1: [2, 1] }, { 8: [1, 24] }, { 7: 30, 8: $Ve, 9: 25, 12: $Vf, 14: 10, 15: 11, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc, 27: 26, 29: 27, 30: 28, 31: 29, 33: 31, 35: $Vg, 36: $Vh, 42: 32, 47: $Vi }, o([8, 10, 28, 32, 37, 39, 40, 45, 57, 58], [2, 7], { 15: 38, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc }), o($Vj, [2, 8]), o($Vj, [2, 10]), o($Vj, [2, 11]), o($Vj, [2, 12]), o($Vj, [2, 13]), o($Vj, [2, 14]), o($Vj, [2, 15]), o($Vj, [2, 16]), o($Vj, [2, 17]), o($Vj, [2, 18]), o($Vj, [2, 19]), o($Vj, [2, 20]), { 7: 39, 14: 10, 15: 11, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc }, { 7: 30, 8: $Ve, 9: 40, 12: $Vf, 14: 10, 15: 11, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc, 27: 26, 29: 27, 30: 28, 31: 29, 33: 31, 35: $Vg, 36: $Vh, 42: 32, 47: $Vi }, { 10: [1, 41] }, { 10: [2, 21], 28: [1, 42] }, o($Vk, [2, 23]), o($Vk, [2, 24]), o($Vk, [2, 25]), o($Vl, $Vm, { 44: 44, 32: [1, 43], 45: $Vn }), o($Vk, [2, 27], { 41: 46, 43: 47, 57: $Vo, 58: $Vp }), o($Vk, [2, 47], { 43: 47, 34: 50, 41: 51, 37: $Vq, 57: $Vo, 58: $Vp }), { 34: 53, 37: $Vq }, { 34: 54, 37: $Vq }, { 34: 55, 37: $Vq }, { 7: 56, 8: [1, 57], 14: 10, 15: 11, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc }, { 7: 30, 8: $Ve, 9: 58, 12: $Vf, 14: 10, 15: 11, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc, 27: 26, 29: 27, 30: 28, 31: 29, 33: 31, 35: $Vg, 36: $Vh, 42: 32, 47: $Vi }, o($Vj, [2, 9]), { 8: [1, 59] }, { 10: [1, 60] }, { 5: [2, 4] }, { 7: 30, 8: $Ve, 9: 61, 12: $Vf, 14: 10, 15: 11, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc, 27: 26, 29: 27, 30: 28, 31: 29, 33: 31, 35: $Vg, 36: $Vh, 42: 32, 47: $Vi }, { 7: 62, 14: 10, 15: 11, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc }, o($Vl, [2, 48]), o($Vl, $Vr, { 14: 10, 15: 11, 7: 63, 46: 64, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc, 48: $Vs, 49: $Vt, 50: $Vu, 51: $Vv, 52: $Vw, 53: $Vx, 54: $Vy, 55: $Vz, 56: $VA }), o($Vk, [2, 41], { 34: 74, 37: $Vq }), { 7: 77, 8: $Ve, 14: 10, 15: 11, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc, 33: 76, 42: 75, 47: $Vi }, o($VB, [2, 66]), o($VB, [2, 67]), o($Vk, [2, 46]), o($Vk, [2, 40], { 34: 78, 37: $Vq }), { 7: 81, 14: 10, 15: 11, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc, 38: 79, 39: [1, 80] }, o($Vk, [2, 28]), o($Vk, [2, 29]), o($Vk, [2, 30]), { 8: [1, 82] }, { 7: 30, 8: $Ve, 9: 83, 12: $Vf, 14: 10, 15: 11, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc, 27: 26, 29: 27, 30: 28, 31: 29, 33: 31, 35: $Vg, 36: $Vh, 42: 32, 47: $Vi }, { 10: [1, 84] }, { 7: 30, 8: $Ve, 9: 85, 12: $Vf, 14: 10, 15: 11, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc, 27: 26, 29: 27, 30: 28, 31: 29, 33: 31, 35: $Vg, 36: $Vh, 42: 32, 47: $Vi }, { 5: [2, 2] }, { 10: [2, 22] }, o($Vk, [2, 26]), o($Vl, [2, 51], { 45: [1, 86] }), o($Vl, [2, 52]), o($Vl, [2, 56]), o($Vl, [2, 57]), o($Vl, [2, 58]), o($Vl, [2, 59]), o($Vl, [2, 60]), o($Vl, [2, 61]), o($Vl, [2, 62]), o($Vl, [2, 63]), o($Vl, [2, 64]), o($Vk, [2, 38]), o($VC, [2, 44], { 43: 47, 41: 87, 57: $Vo, 58: $Vp }), o($VC, [2, 45], { 43: 47, 41: 88, 57: $Vo, 58: $Vp }), o($Vl, $Vm, { 44: 44, 45: $Vn }), o($Vk, [2, 39]), { 39: [1, 89] }, o($Vk, [2, 34], { 34: 90, 37: $Vq }), { 32: [1, 91] }, { 7: 30, 8: $Ve, 9: 92, 12: $Vf, 14: 10, 15: 11, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc, 27: 26, 29: 27, 30: 28, 31: 29, 33: 31, 35: $Vg, 36: $Vh, 42: 32, 47: $Vi }, { 10: [1, 93] }, o($Vl, [2, 55]), { 10: [1, 94] }, o($Vl, $Vr, { 46: 95, 48: $Vs, 49: $Vt, 50: $Vu, 51: $Vv, 52: $Vw, 53: $Vx, 54: $Vy, 55: $Vz, 56: $VA }), o($VC, [2, 42]), o($VC, [2, 43]), o($Vk, [2, 33], { 34: 96, 37: $Vq }), o($Vk, [2, 32]), { 7: 97, 14: 10, 15: 11, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc }, { 10: [1, 98] }, o($Vl, [2, 54]), { 5: [2, 3] }, o($Vl, [2, 50]), o($Vk, [2, 31]), { 28: [1, 99], 39: [2, 37], 40: [1, 100] }, o($Vl, [2, 53]), { 7: 81, 14: 10, 15: 11, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc, 38: 101 }, { 7: 81, 14: 10, 15: 11, 16: $V2, 17: $V3, 18: $V4, 19: $V5, 20: $V6, 21: $V7, 22: $V8, 23: $V9, 24: $Va, 25: $Vb, 26: $Vc, 38: 102 }, { 39: [2, 35] }, { 39: [2, 36] }],
|
||
defaultActions: { 7: [2, 1], 41: [2, 4], 60: [2, 2], 61: [2, 22], 94: [2, 3], 101: [2, 35], 102: [2, 36] },
|
||
parseError: function parseError(str, hash) {
|
||
if (hash.recoverable) {
|
||
this.trace(str);
|
||
} else {
|
||
var _parseError = function _parseError(msg, hash) {
|
||
this.message = msg;
|
||
this.hash = hash;
|
||
};
|
||
|
||
_parseError.prototype = new Error();
|
||
|
||
throw new _parseError(str, hash);
|
||
}
|
||
},
|
||
parse: function parse(input) {
|
||
var self = this,
|
||
stack = [0],
|
||
tstack = [],
|
||
vstack = [null],
|
||
lstack = [],
|
||
table = this.table,
|
||
yytext = '',
|
||
yylineno = 0,
|
||
yyleng = 0,
|
||
recovering = 0,
|
||
TERROR = 2,
|
||
EOF = 1;
|
||
var args = lstack.slice.call(arguments, 1);
|
||
var lexer = Object.create(this.lexer);
|
||
var sharedState = { yy: {} };
|
||
for (var k in this.yy) {
|
||
if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
|
||
sharedState.yy[k] = this.yy[k];
|
||
}
|
||
}
|
||
lexer.setInput(input, sharedState.yy);
|
||
sharedState.yy.lexer = lexer;
|
||
sharedState.yy.parser = this;
|
||
if (typeof lexer.yylloc == 'undefined') {
|
||
lexer.yylloc = {};
|
||
}
|
||
var yyloc = lexer.yylloc;
|
||
lstack.push(yyloc);
|
||
var ranges = lexer.options && lexer.options.ranges;
|
||
if (typeof sharedState.yy.parseError === 'function') {
|
||
this.parseError = sharedState.yy.parseError;
|
||
} else {
|
||
this.parseError = Object.getPrototypeOf(this).parseError;
|
||
}
|
||
function popStack(n) {
|
||
stack.length = stack.length - 2 * n;
|
||
vstack.length = vstack.length - n;
|
||
lstack.length = lstack.length - n;
|
||
}
|
||
_token_stack: var lex = function lex() {
|
||
var token;
|
||
token = lexer.lex() || EOF;
|
||
if (typeof token !== 'number') {
|
||
token = self.symbols_[token] || token;
|
||
}
|
||
return token;
|
||
};
|
||
var symbol,
|
||
preErrorSymbol,
|
||
state,
|
||
action,
|
||
a,
|
||
r,
|
||
yyval = {},
|
||
p,
|
||
len,
|
||
newState,
|
||
expected;
|
||
while (true) {
|
||
state = stack[stack.length - 1];
|
||
if (this.defaultActions[state]) {
|
||
action = this.defaultActions[state];
|
||
} else {
|
||
if (symbol === null || typeof symbol == 'undefined') {
|
||
symbol = lex();
|
||
}
|
||
action = table[state] && table[state][symbol];
|
||
}
|
||
if (typeof action === 'undefined' || !action.length || !action[0]) {
|
||
var errStr = '';
|
||
expected = [];
|
||
for (p in table[state]) {
|
||
if (this.terminals_[p] && p > TERROR) {
|
||
expected.push('\'' + this.terminals_[p] + '\'');
|
||
}
|
||
}
|
||
if (lexer.showPosition) {
|
||
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
|
||
} else {
|
||
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
|
||
}
|
||
this.parseError(errStr, {
|
||
text: lexer.match,
|
||
token: this.terminals_[symbol] || symbol,
|
||
line: lexer.yylineno,
|
||
loc: yyloc,
|
||
expected: expected
|
||
});
|
||
}
|
||
if (action[0] instanceof Array && action.length > 1) {
|
||
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
|
||
}
|
||
switch (action[0]) {
|
||
case 1:
|
||
stack.push(symbol);
|
||
vstack.push(lexer.yytext);
|
||
lstack.push(lexer.yylloc);
|
||
stack.push(action[1]);
|
||
symbol = null;
|
||
if (!preErrorSymbol) {
|
||
yyleng = lexer.yyleng;
|
||
yytext = lexer.yytext;
|
||
yylineno = lexer.yylineno;
|
||
yyloc = lexer.yylloc;
|
||
if (recovering > 0) {
|
||
recovering--;
|
||
}
|
||
} else {
|
||
symbol = preErrorSymbol;
|
||
preErrorSymbol = null;
|
||
}
|
||
break;
|
||
case 2:
|
||
len = this.productions_[action[1]][1];
|
||
yyval.$ = vstack[vstack.length - len];
|
||
yyval._$ = {
|
||
first_line: lstack[lstack.length - (len || 1)].first_line,
|
||
last_line: lstack[lstack.length - 1].last_line,
|
||
first_column: lstack[lstack.length - (len || 1)].first_column,
|
||
last_column: lstack[lstack.length - 1].last_column
|
||
};
|
||
if (ranges) {
|
||
yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
|
||
}
|
||
r = this.performAction.apply(yyval, [yytext, yyleng, yylineno, sharedState.yy, action[1], vstack, lstack].concat(args));
|
||
if (typeof r !== 'undefined') {
|
||
return r;
|
||
}
|
||
if (len) {
|
||
stack = stack.slice(0, -1 * len * 2);
|
||
vstack = vstack.slice(0, -1 * len);
|
||
lstack = lstack.slice(0, -1 * len);
|
||
}
|
||
stack.push(this.productions_[action[1]][0]);
|
||
vstack.push(yyval.$);
|
||
lstack.push(yyval._$);
|
||
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
|
||
stack.push(newState);
|
||
break;
|
||
case 3:
|
||
return true;
|
||
}
|
||
}
|
||
return true;
|
||
} };
|
||
|
||
/* generated by jison-lex 0.3.4 */
|
||
var lexer = (function () {
|
||
var lexer = {
|
||
|
||
EOF: 1,
|
||
|
||
parseError: function parseError(str, hash) {
|
||
if (this.yy.parser) {
|
||
this.yy.parser.parseError(str, hash);
|
||
} else {
|
||
throw new Error(str);
|
||
}
|
||
},
|
||
|
||
// resets the lexer, sets new input
|
||
setInput: function setInput(input, yy) {
|
||
this.yy = yy || this.yy || {};
|
||
this._input = input;
|
||
this._more = this._backtrack = this.done = false;
|
||
this.yylineno = this.yyleng = 0;
|
||
this.yytext = this.matched = this.match = '';
|
||
this.conditionStack = ['INITIAL'];
|
||
this.yylloc = {
|
||
first_line: 1,
|
||
first_column: 0,
|
||
last_line: 1,
|
||
last_column: 0
|
||
};
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [0, 0];
|
||
}
|
||
this.offset = 0;
|
||
return this;
|
||
},
|
||
|
||
// consumes and returns one char from the input
|
||
input: function input() {
|
||
var ch = this._input[0];
|
||
this.yytext += ch;
|
||
this.yyleng++;
|
||
this.offset++;
|
||
this.match += ch;
|
||
this.matched += ch;
|
||
var lines = ch.match(/(?:\r\n?|\n).*/g);
|
||
if (lines) {
|
||
this.yylineno++;
|
||
this.yylloc.last_line++;
|
||
} else {
|
||
this.yylloc.last_column++;
|
||
}
|
||
if (this.options.ranges) {
|
||
this.yylloc.range[1]++;
|
||
}
|
||
|
||
this._input = this._input.slice(1);
|
||
return ch;
|
||
},
|
||
|
||
// unshifts one char (or a string) into the input
|
||
unput: function unput(ch) {
|
||
var len = ch.length;
|
||
var lines = ch.split(/(?:\r\n?|\n)/g);
|
||
|
||
this._input = ch + this._input;
|
||
this.yytext = this.yytext.substr(0, this.yytext.length - len);
|
||
//this.yyleng -= len;
|
||
this.offset -= len;
|
||
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
|
||
this.match = this.match.substr(0, this.match.length - 1);
|
||
this.matched = this.matched.substr(0, this.matched.length - 1);
|
||
|
||
if (lines.length - 1) {
|
||
this.yylineno -= lines.length - 1;
|
||
}
|
||
var r = this.yylloc.range;
|
||
|
||
this.yylloc = {
|
||
first_line: this.yylloc.first_line,
|
||
last_line: this.yylineno + 1,
|
||
first_column: this.yylloc.first_column,
|
||
last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
|
||
};
|
||
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
|
||
}
|
||
this.yyleng = this.yytext.length;
|
||
return this;
|
||
},
|
||
|
||
// When called from action, caches matched text and appends it on next action
|
||
more: function more() {
|
||
this._more = true;
|
||
return this;
|
||
},
|
||
|
||
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
|
||
reject: function reject() {
|
||
if (this.options.backtrack_lexer) {
|
||
this._backtrack = true;
|
||
} else {
|
||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
|
||
text: "",
|
||
token: null,
|
||
line: this.yylineno
|
||
});
|
||
}
|
||
return this;
|
||
},
|
||
|
||
// retain first n characters of the match
|
||
less: function less(n) {
|
||
this.unput(this.match.slice(n));
|
||
},
|
||
|
||
// displays already matched input, i.e. for error messages
|
||
pastInput: function pastInput() {
|
||
var past = this.matched.substr(0, this.matched.length - this.match.length);
|
||
return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
|
||
},
|
||
|
||
// displays upcoming input, i.e. for error messages
|
||
upcomingInput: function upcomingInput() {
|
||
var next = this.match;
|
||
if (next.length < 20) {
|
||
next += this._input.substr(0, 20 - next.length);
|
||
}
|
||
return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
|
||
},
|
||
|
||
// displays the character position where the lexing error occurred, i.e. for error messages
|
||
showPosition: function showPosition() {
|
||
var pre = this.pastInput();
|
||
var c = new Array(pre.length + 1).join("-");
|
||
return pre + this.upcomingInput() + "\n" + c + "^";
|
||
},
|
||
|
||
// test the lexed token: return FALSE when not a match, otherwise return token
|
||
test_match: function test_match(match, indexed_rule) {
|
||
var token, lines, backup;
|
||
|
||
if (this.options.backtrack_lexer) {
|
||
// save context
|
||
backup = {
|
||
yylineno: this.yylineno,
|
||
yylloc: {
|
||
first_line: this.yylloc.first_line,
|
||
last_line: this.last_line,
|
||
first_column: this.yylloc.first_column,
|
||
last_column: this.yylloc.last_column
|
||
},
|
||
yytext: this.yytext,
|
||
match: this.match,
|
||
matches: this.matches,
|
||
matched: this.matched,
|
||
yyleng: this.yyleng,
|
||
offset: this.offset,
|
||
_more: this._more,
|
||
_input: this._input,
|
||
yy: this.yy,
|
||
conditionStack: this.conditionStack.slice(0),
|
||
done: this.done
|
||
};
|
||
if (this.options.ranges) {
|
||
backup.yylloc.range = this.yylloc.range.slice(0);
|
||
}
|
||
}
|
||
|
||
lines = match[0].match(/(?:\r\n?|\n).*/g);
|
||
if (lines) {
|
||
this.yylineno += lines.length;
|
||
}
|
||
this.yylloc = {
|
||
first_line: this.yylloc.last_line,
|
||
last_line: this.yylineno + 1,
|
||
first_column: this.yylloc.last_column,
|
||
last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length
|
||
};
|
||
this.yytext += match[0];
|
||
this.match += match[0];
|
||
this.matches = match;
|
||
this.yyleng = this.yytext.length;
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [this.offset, this.offset += this.yyleng];
|
||
}
|
||
this._more = false;
|
||
this._backtrack = false;
|
||
this._input = this._input.slice(match[0].length);
|
||
this.matched += match[0];
|
||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
|
||
if (this.done && this._input) {
|
||
this.done = false;
|
||
}
|
||
if (token) {
|
||
return token;
|
||
} else if (this._backtrack) {
|
||
// recover context
|
||
for (var k in backup) {
|
||
this[k] = backup[k];
|
||
}
|
||
return false; // rule action called reject() implying the next rule should be tested instead.
|
||
}
|
||
return false;
|
||
},
|
||
|
||
// return next match in input
|
||
next: function next() {
|
||
if (this.done) {
|
||
return this.EOF;
|
||
}
|
||
if (!this._input) {
|
||
this.done = true;
|
||
}
|
||
|
||
var token, match, tempMatch, index;
|
||
if (!this._more) {
|
||
this.yytext = '';
|
||
this.match = '';
|
||
}
|
||
var rules = this._currentRules();
|
||
for (var i = 0; i < rules.length; i++) {
|
||
tempMatch = this._input.match(this.rules[rules[i]]);
|
||
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
|
||
match = tempMatch;
|
||
index = i;
|
||
if (this.options.backtrack_lexer) {
|
||
token = this.test_match(tempMatch, rules[i]);
|
||
if (token !== false) {
|
||
return token;
|
||
} else if (this._backtrack) {
|
||
match = false;
|
||
continue; // rule action called reject() implying a rule MISmatch.
|
||
} else {
|
||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||
return false;
|
||
}
|
||
} else if (!this.options.flex) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (match) {
|
||
token = this.test_match(match, rules[index]);
|
||
if (token !== false) {
|
||
return token;
|
||
}
|
||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||
return false;
|
||
}
|
||
if (this._input === "") {
|
||
return this.EOF;
|
||
} else {
|
||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
|
||
text: "",
|
||
token: null,
|
||
line: this.yylineno
|
||
});
|
||
}
|
||
},
|
||
|
||
// return next match that has a token
|
||
lex: function lex() {
|
||
var r = this.next();
|
||
if (r) {
|
||
return r;
|
||
} else {
|
||
return this.lex();
|
||
}
|
||
},
|
||
|
||
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
|
||
begin: function begin(condition) {
|
||
this.conditionStack.push(condition);
|
||
},
|
||
|
||
// pop the previously active lexer condition state off the condition stack
|
||
popState: function popState() {
|
||
var n = this.conditionStack.length - 1;
|
||
if (n > 0) {
|
||
return this.conditionStack.pop();
|
||
} else {
|
||
return this.conditionStack[0];
|
||
}
|
||
},
|
||
|
||
// produce the lexer rule set which is active for the currently active lexer condition state
|
||
_currentRules: function _currentRules() {
|
||
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
|
||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
|
||
} else {
|
||
return this.conditions["INITIAL"].rules;
|
||
}
|
||
},
|
||
|
||
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
|
||
topState: function topState(n) {
|
||
n = this.conditionStack.length - 1 - Math.abs(n || 0);
|
||
if (n >= 0) {
|
||
return this.conditionStack[n];
|
||
} else {
|
||
return "INITIAL";
|
||
}
|
||
},
|
||
|
||
// alias for begin(condition)
|
||
pushState: function pushState(condition) {
|
||
this.begin(condition);
|
||
},
|
||
|
||
// return the number of states currently on the stack
|
||
stateStackSize: function stateStackSize() {
|
||
return this.conditionStack.length;
|
||
},
|
||
options: {},
|
||
performAction: function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
|
||
var YYSTATE = YY_START;
|
||
switch ($avoiding_name_collisions) {
|
||
case 0:
|
||
return 'STYLE';
|
||
break;
|
||
case 1:
|
||
return 'LINKSTYLE';
|
||
break;
|
||
case 2:
|
||
return 'CLASSDEF';
|
||
break;
|
||
case 3:
|
||
return 'CLASS';
|
||
break;
|
||
case 4:
|
||
return 'CLICK';
|
||
break;
|
||
case 5:
|
||
return 12;
|
||
break;
|
||
case 6:
|
||
return 13;
|
||
break;
|
||
case 7:
|
||
return 47;
|
||
break;
|
||
case 8:
|
||
return 35;
|
||
break;
|
||
case 9:
|
||
return 36;
|
||
break;
|
||
case 10:
|
||
return 'DIR';
|
||
break;
|
||
case 11:
|
||
return 'DIR';
|
||
break;
|
||
case 12:
|
||
return 'DIR';
|
||
break;
|
||
case 13:
|
||
return 'DIR';
|
||
break;
|
||
case 14:
|
||
return 'DIR';
|
||
break;
|
||
case 15:
|
||
return 'DIR';
|
||
break;
|
||
case 16:
|
||
return 17;
|
||
break;
|
||
case 17:
|
||
return 23;
|
||
break;
|
||
case 18:
|
||
return 18;
|
||
break;
|
||
case 19:
|
||
return 28;
|
||
break;
|
||
case 20:
|
||
return 40;
|
||
break;
|
||
case 21:
|
||
return 32;
|
||
break;
|
||
case 22:
|
||
return 21;
|
||
break;
|
||
case 23:
|
||
return 22;
|
||
break;
|
||
case 24:
|
||
return 'ARROW_CROSS';
|
||
break;
|
||
case 25:
|
||
return 57;
|
||
break;
|
||
case 26:
|
||
return 'ARROW_CIRCLE';
|
||
break;
|
||
case 27:
|
||
return 58;
|
||
break;
|
||
case 28:
|
||
return 25;
|
||
break;
|
||
case 29:
|
||
return 19;
|
||
break;
|
||
case 30:
|
||
return 20;
|
||
break;
|
||
case 31:
|
||
return 16;
|
||
break;
|
||
case 32:
|
||
return 'PIPE';
|
||
break;
|
||
case 33:
|
||
return 'PS';
|
||
break;
|
||
case 34:
|
||
return 'PE';
|
||
break;
|
||
case 35:
|
||
return 37;
|
||
break;
|
||
case 36:
|
||
return 39;
|
||
break;
|
||
case 37:
|
||
return 8;
|
||
break;
|
||
case 38:
|
||
return 10;
|
||
break;
|
||
case 39:
|
||
return 'QUOTE';
|
||
break;
|
||
case 40:
|
||
return 24;
|
||
break;
|
||
case 41:
|
||
return 'NEWLINE';
|
||
break;
|
||
case 42:
|
||
return 5;
|
||
break;
|
||
}
|
||
},
|
||
rules: [/^(?:style\b)/, /^(?:linkStyle\b)/, /^(?:classDef\b)/, /^(?:class\b)/, /^(?:click\b)/, /^(?:graph\b)/, /^(?:digraph\b)/, /^(?:subgraph\b)/, /^(?:node\b)/, /^(?:edge\b)/, /^(?:LR\b)/, /^(?:RL\b)/, /^(?:TB\b)/, /^(?:BT\b)/, /^(?:TD\b)/, /^(?:BR\b)/, /^(?:[0-9])/, /^(?:#)/, /^(?::)/, /^(?:;)/, /^(?:,)/, /^(?:=)/, /^(?:\*)/, /^(?:\.)/, /^(?:--[x])/, /^(?:->)/, /^(?:--[o])/, /^(?:--)/, /^(?:-)/, /^(?:\+)/, /^(?:=)/, /^(?:[\u0021-\u0027\u002A-\u002E\u003F\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]|[\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE]|[\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA]|[\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0]|[\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977]|[\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2]|[\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A]|[\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39]|[\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8]|[\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C]|[\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C]|[\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99]|[\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0]|[\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D]|[\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3]|[\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10]|[\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1]|[\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81]|[\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3]|[\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6]|[\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A]|[\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081]|[\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D]|[\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0]|[\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310]|[\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C]|[\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711]|[\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7]|[\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C]|[\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16]|[\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF]|[\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC]|[\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D]|[\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D]|[\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3]|[\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F]|[\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128]|[\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184]|[\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3]|[\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6]|[\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE]|[\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C]|[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D]|[\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC]|[\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B]|[\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788]|[\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805]|[\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB]|[\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28]|[\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5]|[\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4]|[\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E]|[\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D]|[\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36]|[\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D]|[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|[\uFFD2-\uFFD7\uFFDA-\uFFDC_])/, /^(?:\|)/, /^(?:\()/, /^(?:\))/, /^(?:\[)/, /^(?:\])/, /^(?:\{)/, /^(?:\})/, /^(?:")/, /^(?:\s)/, /^(?:\n)/, /^(?:$)/],
|
||
conditions: { "INITIAL": { "rules": [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, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42], "inclusive": true } }
|
||
};
|
||
return lexer;
|
||
})();
|
||
parser.lexer = lexer;
|
||
function Parser() {
|
||
this.yy = {};
|
||
}
|
||
Parser.prototype = parser;parser.Parser = Parser;
|
||
return new Parser();
|
||
})();
|
||
|
||
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
|
||
exports.parser = dot;
|
||
exports.Parser = dot.Parser;
|
||
exports.parse = function () {
|
||
return dot.parse.apply(dot, arguments);
|
||
};
|
||
exports.main = function commonjsMain(args) {
|
||
if (!args[1]) {
|
||
console.log('Usage: ' + args[0] + ' FILE');
|
||
process.exit(1);
|
||
}
|
||
var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
|
||
return exports.parser.parse(source);
|
||
};
|
||
if (typeof module !== 'undefined' && require.main === module) {
|
||
exports.main(process.argv.slice(1));
|
||
}
|
||
}
|
||
|
||
}).call(this,require('_process'))
|
||
},{"_process":3,"fs":1,"path":2}],118:[function(require,module,exports){
|
||
(function (process){
|
||
/* parser generated by jison 0.4.15 */
|
||
/*
|
||
Returns a Parser object of the following structure:
|
||
|
||
Parser: {
|
||
yy: {}
|
||
}
|
||
|
||
Parser.prototype: {
|
||
yy: {},
|
||
trace: function(),
|
||
symbols_: {associative list: name ==> number},
|
||
terminals_: {associative list: number ==> name},
|
||
productions_: [...],
|
||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
|
||
table: [...],
|
||
defaultActions: {...},
|
||
parseError: function(str, hash),
|
||
parse: function(input),
|
||
|
||
lexer: {
|
||
EOF: 1,
|
||
parseError: function(str, hash),
|
||
setInput: function(input),
|
||
input: function(),
|
||
unput: function(str),
|
||
more: function(),
|
||
less: function(n),
|
||
pastInput: function(),
|
||
upcomingInput: function(),
|
||
showPosition: function(),
|
||
test_match: function(regex_match_array, rule_index),
|
||
next: function(),
|
||
lex: function(),
|
||
begin: function(condition),
|
||
popState: function(),
|
||
_currentRules: function(),
|
||
topState: function(),
|
||
pushState: function(condition),
|
||
|
||
options: {
|
||
ranges: boolean (optional: true ==> token location info will include a .range[] member)
|
||
flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
|
||
backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
|
||
},
|
||
|
||
performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
|
||
rules: [...],
|
||
conditions: {associative list: name ==> set},
|
||
}
|
||
}
|
||
|
||
|
||
token location info (@$, _$, etc.): {
|
||
first_line: n,
|
||
last_line: n,
|
||
first_column: n,
|
||
last_column: n,
|
||
range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
|
||
}
|
||
|
||
|
||
the parseError function receives a 'hash' object with these members for lexer and parser errors: {
|
||
text: (matched text)
|
||
token: (the produced terminal token, if any)
|
||
line: (yylineno)
|
||
}
|
||
while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
|
||
loc: (yylloc)
|
||
expected: (string describing the set of expected tokens)
|
||
recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
|
||
}
|
||
*/
|
||
"use strict";
|
||
|
||
var flow = (function () {
|
||
var o = function o(k, v, _o, l) {
|
||
for (_o = _o || {}, l = k.length; l--; _o[k[l]] = v);return _o;
|
||
},
|
||
$V0 = [1, 4],
|
||
$V1 = [1, 3],
|
||
$V2 = [1, 5],
|
||
$V3 = [1, 8, 9, 10, 11, 13, 18, 30, 46, 71, 72, 73, 74, 75, 81, 85, 87, 88, 90, 91, 93, 94, 95, 96, 97],
|
||
$V4 = [2, 2],
|
||
$V5 = [1, 12],
|
||
$V6 = [1, 13],
|
||
$V7 = [1, 14],
|
||
$V8 = [1, 15],
|
||
$V9 = [1, 31],
|
||
$Va = [1, 33],
|
||
$Vb = [1, 22],
|
||
$Vc = [1, 34],
|
||
$Vd = [1, 24],
|
||
$Ve = [1, 25],
|
||
$Vf = [1, 26],
|
||
$Vg = [1, 27],
|
||
$Vh = [1, 28],
|
||
$Vi = [1, 38],
|
||
$Vj = [1, 40],
|
||
$Vk = [1, 35],
|
||
$Vl = [1, 39],
|
||
$Vm = [1, 45],
|
||
$Vn = [1, 44],
|
||
$Vo = [1, 36],
|
||
$Vp = [1, 37],
|
||
$Vq = [1, 41],
|
||
$Vr = [1, 42],
|
||
$Vs = [1, 43],
|
||
$Vt = [1, 8, 9, 10, 11, 13, 18, 30, 32, 46, 71, 72, 73, 74, 75, 81, 85, 87, 88, 90, 91, 93, 94, 95, 96, 97],
|
||
$Vu = [1, 53],
|
||
$Vv = [1, 52],
|
||
$Vw = [1, 54],
|
||
$Vx = [1, 72],
|
||
$Vy = [1, 80],
|
||
$Vz = [1, 81],
|
||
$VA = [1, 66],
|
||
$VB = [1, 65],
|
||
$VC = [1, 85],
|
||
$VD = [1, 84],
|
||
$VE = [1, 82],
|
||
$VF = [1, 83],
|
||
$VG = [1, 73],
|
||
$VH = [1, 68],
|
||
$VI = [1, 67],
|
||
$VJ = [1, 63],
|
||
$VK = [1, 75],
|
||
$VL = [1, 76],
|
||
$VM = [1, 77],
|
||
$VN = [1, 78],
|
||
$VO = [1, 79],
|
||
$VP = [1, 70],
|
||
$VQ = [1, 69],
|
||
$VR = [8, 9, 11],
|
||
$VS = [8, 9, 11, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64],
|
||
$VT = [1, 115],
|
||
$VU = [8, 9, 10, 11, 13, 15, 18, 36, 38, 40, 42, 46, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 81, 85, 87, 88, 90, 91, 93, 94, 95, 96, 97],
|
||
$VV = [8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 30, 32, 36, 37, 38, 39, 40, 41, 42, 43, 46, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 71, 72, 73, 74, 75, 78, 81, 83, 85, 87, 88, 90, 91, 93, 94, 95, 96, 97],
|
||
$VW = [1, 117],
|
||
$VX = [1, 118],
|
||
$VY = [8, 9, 10, 11, 13, 18, 30, 32, 46, 71, 72, 73, 74, 75, 81, 85, 87, 88, 90, 91, 93, 94, 95, 96, 97],
|
||
$VZ = [8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 30, 32, 37, 39, 41, 43, 46, 50, 51, 52, 53, 54, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 71, 72, 73, 74, 75, 78, 81, 83, 85, 87, 88, 90, 91, 93, 94, 95, 96, 97],
|
||
$V_ = [13, 18, 46, 81, 85, 87, 88, 90, 91, 93, 94, 95, 96, 97],
|
||
$V$ = [13, 18, 46, 49, 65, 81, 85, 87, 88, 90, 91, 93, 94, 95, 96, 97],
|
||
$V01 = [1, 191],
|
||
$V11 = [1, 188],
|
||
$V21 = [1, 195],
|
||
$V31 = [1, 192],
|
||
$V41 = [1, 189],
|
||
$V51 = [1, 196],
|
||
$V61 = [1, 186],
|
||
$V71 = [1, 187],
|
||
$V81 = [1, 190],
|
||
$V91 = [1, 193],
|
||
$Va1 = [1, 194],
|
||
$Vb1 = [1, 211],
|
||
$Vc1 = [8, 9, 11, 85],
|
||
$Vd1 = [8, 9, 10, 11, 46, 71, 80, 81, 83, 85, 87, 88, 89, 90, 91];
|
||
var parser = { trace: function trace() {},
|
||
yy: {},
|
||
symbols_: { "error": 2, "mermaidDoc": 3, "graphConfig": 4, "document": 5, "line": 6, "statement": 7, "SEMI": 8, "NEWLINE": 9, "SPACE": 10, "EOF": 11, "GRAPH": 12, "DIR": 13, "FirstStmtSeperator": 14, "TAGEND": 15, "TAGSTART": 16, "UP": 17, "DOWN": 18, "ending": 19, "endToken": 20, "spaceList": 21, "spaceListNewline": 22, "verticeStatement": 23, "separator": 24, "styleStatement": 25, "linkStyleStatement": 26, "classDefStatement": 27, "classStatement": 28, "clickStatement": 29, "subgraph": 30, "text": 31, "end": 32, "vertex": 33, "link": 34, "alphaNum": 35, "SQS": 36, "SQE": 37, "PS": 38, "PE": 39, "(-": 40, "-)": 41, "DIAMOND_START": 42, "DIAMOND_STOP": 43, "alphaNumStatement": 44, "alphaNumToken": 45, "MINUS": 46, "linkStatement": 47, "arrowText": 48, "TESTSTR": 49, "--": 50, "ARROW_POINT": 51, "ARROW_CIRCLE": 52, "ARROW_CROSS": 53, "ARROW_OPEN": 54, "-.": 55, "DOTTED_ARROW_POINT": 56, "DOTTED_ARROW_CIRCLE": 57, "DOTTED_ARROW_CROSS": 58, "DOTTED_ARROW_OPEN": 59, "==": 60, "THICK_ARROW_POINT": 61, "THICK_ARROW_CIRCLE": 62, "THICK_ARROW_CROSS": 63, "THICK_ARROW_OPEN": 64, "PIPE": 65, "textToken": 66, "STR": 67, "commentText": 68, "commentToken": 69, "keywords": 70, "STYLE": 71, "LINKSTYLE": 72, "CLASSDEF": 73, "CLASS": 74, "CLICK": 75, "textNoTags": 76, "textNoTagsToken": 77, "DEFAULT": 78, "stylesOpt": 79, "HEX": 80, "NUM": 81, "commentStatement": 82, "PCT": 83, "style": 84, "COMMA": 85, "styleComponent": 86, "ALPHA": 87, "COLON": 88, "UNIT": 89, "BRKT": 90, "DOT": 91, "graphCodeTokens": 92, "PUNCTUATION": 93, "UNICODE_TEXT": 94, "PLUS": 95, "EQUALS": 96, "MULT": 97, "TAG_START": 98, "TAG_END": 99, "QUOTE": 100, "$accept": 0, "$end": 1 },
|
||
terminals_: { 2: "error", 8: "SEMI", 9: "NEWLINE", 10: "SPACE", 11: "EOF", 12: "GRAPH", 13: "DIR", 15: "TAGEND", 16: "TAGSTART", 17: "UP", 18: "DOWN", 30: "subgraph", 32: "end", 36: "SQS", 37: "SQE", 38: "PS", 39: "PE", 40: "(-", 41: "-)", 42: "DIAMOND_START", 43: "DIAMOND_STOP", 46: "MINUS", 49: "TESTSTR", 50: "--", 51: "ARROW_POINT", 52: "ARROW_CIRCLE", 53: "ARROW_CROSS", 54: "ARROW_OPEN", 55: "-.", 56: "DOTTED_ARROW_POINT", 57: "DOTTED_ARROW_CIRCLE", 58: "DOTTED_ARROW_CROSS", 59: "DOTTED_ARROW_OPEN", 60: "==", 61: "THICK_ARROW_POINT", 62: "THICK_ARROW_CIRCLE", 63: "THICK_ARROW_CROSS", 64: "THICK_ARROW_OPEN", 65: "PIPE", 67: "STR", 71: "STYLE", 72: "LINKSTYLE", 73: "CLASSDEF", 74: "CLASS", 75: "CLICK", 78: "DEFAULT", 80: "HEX", 81: "NUM", 83: "PCT", 85: "COMMA", 87: "ALPHA", 88: "COLON", 89: "UNIT", 90: "BRKT", 91: "DOT", 93: "PUNCTUATION", 94: "UNICODE_TEXT", 95: "PLUS", 96: "EQUALS", 97: "MULT", 98: "TAG_START", 99: "TAG_END", 100: "QUOTE" },
|
||
productions_: [0, [3, 2], [5, 0], [5, 2], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [4, 2], [4, 2], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [19, 2], [19, 1], [20, 1], [20, 1], [20, 1], [14, 1], [14, 1], [14, 2], [22, 2], [22, 2], [22, 1], [22, 1], [21, 2], [21, 1], [7, 2], [7, 2], [7, 2], [7, 2], [7, 2], [7, 2], [7, 5], [7, 4], [24, 1], [24, 1], [24, 1], [23, 3], [23, 1], [33, 4], [33, 5], [33, 6], [33, 7], [33, 4], [33, 5], [33, 4], [33, 5], [33, 4], [33, 5], [33, 4], [33, 5], [33, 1], [33, 2], [35, 1], [35, 2], [44, 1], [44, 1], [44, 1], [44, 1], [34, 2], [34, 3], [34, 3], [34, 1], [34, 3], [34, 3], [34, 3], [34, 3], [34, 3], [34, 3], [34, 3], [34, 3], [34, 3], [34, 3], [34, 3], [34, 3], [47, 1], [47, 1], [47, 1], [47, 1], [47, 1], [47, 1], [47, 1], [47, 1], [47, 1], [47, 1], [47, 1], [47, 1], [48, 3], [31, 1], [31, 2], [31, 1], [68, 1], [68, 2], [70, 1], [70, 1], [70, 1], [70, 1], [70, 1], [70, 1], [70, 1], [70, 1], [70, 1], [70, 1], [70, 1], [76, 1], [76, 2], [27, 5], [27, 5], [28, 5], [29, 5], [29, 7], [29, 5], [29, 7], [25, 5], [25, 5], [26, 5], [26, 5], [82, 3], [79, 1], [79, 3], [84, 1], [84, 2], [86, 1], [86, 1], [86, 1], [86, 1], [86, 1], [86, 1], [86, 1], [86, 1], [86, 1], [86, 1], [86, 1], [69, 1], [69, 1], [66, 1], [66, 1], [66, 1], [66, 1], [66, 1], [66, 1], [66, 1], [77, 1], [77, 1], [77, 1], [77, 1], [45, 1], [45, 1], [45, 1], [45, 1], [45, 1], [45, 1], [45, 1], [45, 1], [45, 1], [45, 1], [45, 1], [92, 1], [92, 1], [92, 1], [92, 1], [92, 1], [92, 1], [92, 1], [92, 1], [92, 1], [92, 1], [92, 1], [92, 1], [92, 1], [92, 1], [92, 1]],
|
||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, /* action[1] */$$, /* vstack */_$ /* lstack */) {
|
||
/* this == yyval */
|
||
|
||
var $0 = $$.length - 1;
|
||
switch (yystate) {
|
||
case 2:
|
||
this.$ = [];
|
||
break;
|
||
case 3:
|
||
|
||
if ($$[$0] !== []) {
|
||
$$[$0 - 1].push($$[$0]);
|
||
}
|
||
this.$ = $$[$0 - 1];
|
||
break;
|
||
case 4:case 57:case 59:case 60:case 92:case 94:case 95:case 108:
|
||
this.$ = $$[$0];
|
||
break;
|
||
case 11:
|
||
yy.setDirection($$[$0 - 1]);this.$ = $$[$0 - 1];
|
||
break;
|
||
case 12:
|
||
yy.setDirection("LR");this.$ = $$[$0 - 1];
|
||
break;
|
||
case 13:
|
||
yy.setDirection("RL");this.$ = $$[$0 - 1];
|
||
break;
|
||
case 14:
|
||
yy.setDirection("BT");this.$ = $$[$0 - 1];
|
||
break;
|
||
case 15:
|
||
yy.setDirection("TB");this.$ = $$[$0 - 1];
|
||
break;
|
||
case 30:
|
||
this.$ = $$[$0 - 1];
|
||
break;
|
||
case 31:case 32:case 33:case 34:case 35:
|
||
this.$ = [];
|
||
break;
|
||
case 36:
|
||
this.$ = yy.addSubGraph($$[$0 - 1], $$[$0 - 3]);
|
||
break;
|
||
case 37:
|
||
this.$ = yy.addSubGraph($$[$0 - 1], undefined);
|
||
break;
|
||
case 41:
|
||
yy.addLink($$[$0 - 2], $$[$0], $$[$0 - 1]);this.$ = [$$[$0 - 2], $$[$0]];
|
||
break;
|
||
case 42:
|
||
this.$ = [$$[$0]];
|
||
break;
|
||
case 43:
|
||
this.$ = $$[$0 - 3];yy.addVertex($$[$0 - 3], $$[$0 - 1], 'square');
|
||
break;
|
||
case 44:
|
||
this.$ = $$[$0 - 4];yy.addVertex($$[$0 - 4], $$[$0 - 2], 'square');
|
||
break;
|
||
case 45:
|
||
this.$ = $$[$0 - 5];yy.addVertex($$[$0 - 5], $$[$0 - 2], 'circle');
|
||
break;
|
||
case 46:
|
||
this.$ = $$[$0 - 6];yy.addVertex($$[$0 - 6], $$[$0 - 3], 'circle');
|
||
break;
|
||
case 47:
|
||
this.$ = $$[$0 - 3];yy.addVertex($$[$0 - 3], $$[$0 - 1], 'ellipse');
|
||
break;
|
||
case 48:
|
||
this.$ = $$[$0 - 4];yy.addVertex($$[$0 - 4], $$[$0 - 2], 'ellipse');
|
||
break;
|
||
case 49:
|
||
this.$ = $$[$0 - 3];yy.addVertex($$[$0 - 3], $$[$0 - 1], 'round');
|
||
break;
|
||
case 50:
|
||
this.$ = $$[$0 - 4];yy.addVertex($$[$0 - 4], $$[$0 - 2], 'round');
|
||
break;
|
||
case 51:
|
||
this.$ = $$[$0 - 3];yy.addVertex($$[$0 - 3], $$[$0 - 1], 'diamond');
|
||
break;
|
||
case 52:
|
||
this.$ = $$[$0 - 4];yy.addVertex($$[$0 - 4], $$[$0 - 2], 'diamond');
|
||
break;
|
||
case 53:
|
||
this.$ = $$[$0 - 3];yy.addVertex($$[$0 - 3], $$[$0 - 1], 'odd');
|
||
break;
|
||
case 54:
|
||
this.$ = $$[$0 - 4];yy.addVertex($$[$0 - 4], $$[$0 - 2], 'odd');
|
||
break;
|
||
case 55:
|
||
this.$ = $$[$0];yy.addVertex($$[$0]);
|
||
break;
|
||
case 56:
|
||
this.$ = $$[$0 - 1];yy.addVertex($$[$0 - 1]);
|
||
break;
|
||
case 58:case 93:case 96:case 109:
|
||
this.$ = $$[$0 - 1] + '' + $$[$0];
|
||
break;
|
||
case 61:
|
||
this.$ = 'v';
|
||
break;
|
||
case 62:
|
||
this.$ = '-';
|
||
break;
|
||
case 63:
|
||
$$[$0 - 1].text = $$[$0];this.$ = $$[$0 - 1];
|
||
break;
|
||
case 64:case 65:
|
||
$$[$0 - 2].text = $$[$0 - 1];this.$ = $$[$0 - 2];
|
||
break;
|
||
case 66:
|
||
this.$ = $$[$0];
|
||
break;
|
||
case 67:
|
||
this.$ = { "type": "arrow", "stroke": "normal", "text": $$[$0 - 1] };
|
||
break;
|
||
case 68:
|
||
this.$ = { "type": "arrow_circle", "stroke": "normal", "text": $$[$0 - 1] };
|
||
break;
|
||
case 69:
|
||
this.$ = { "type": "arrow_cross", "stroke": "normal", "text": $$[$0 - 1] };
|
||
break;
|
||
case 70:
|
||
this.$ = { "type": "arrow_open", "stroke": "normal", "text": $$[$0 - 1] };
|
||
break;
|
||
case 71:
|
||
this.$ = { "type": "arrow", "stroke": "dotted", "text": $$[$0 - 1] };
|
||
break;
|
||
case 72:
|
||
this.$ = { "type": "arrow_circle", "stroke": "dotted", "text": $$[$0 - 1] };
|
||
break;
|
||
case 73:
|
||
this.$ = { "type": "arrow_cross", "stroke": "dotted", "text": $$[$0 - 1] };
|
||
break;
|
||
case 74:
|
||
this.$ = { "type": "arrow_open", "stroke": "dotted", "text": $$[$0 - 1] };
|
||
break;
|
||
case 75:
|
||
this.$ = { "type": "arrow", "stroke": "thick", "text": $$[$0 - 1] };
|
||
break;
|
||
case 76:
|
||
this.$ = { "type": "arrow_circle", "stroke": "thick", "text": $$[$0 - 1] };
|
||
break;
|
||
case 77:
|
||
this.$ = { "type": "arrow_cross", "stroke": "thick", "text": $$[$0 - 1] };
|
||
break;
|
||
case 78:
|
||
this.$ = { "type": "arrow_open", "stroke": "thick", "text": $$[$0 - 1] };
|
||
break;
|
||
case 79:
|
||
this.$ = { "type": "arrow", "stroke": "normal" };
|
||
break;
|
||
case 80:
|
||
this.$ = { "type": "arrow_circle", "stroke": "normal" };
|
||
break;
|
||
case 81:
|
||
this.$ = { "type": "arrow_cross", "stroke": "normal" };
|
||
break;
|
||
case 82:
|
||
this.$ = { "type": "arrow_open", "stroke": "normal" };
|
||
break;
|
||
case 83:
|
||
this.$ = { "type": "arrow", "stroke": "dotted" };
|
||
break;
|
||
case 84:
|
||
this.$ = { "type": "arrow_circle", "stroke": "dotted" };
|
||
break;
|
||
case 85:
|
||
this.$ = { "type": "arrow_cross", "stroke": "dotted" };
|
||
break;
|
||
case 86:
|
||
this.$ = { "type": "arrow_open", "stroke": "dotted" };
|
||
break;
|
||
case 87:
|
||
this.$ = { "type": "arrow", "stroke": "thick" };
|
||
break;
|
||
case 88:
|
||
this.$ = { "type": "arrow_circle", "stroke": "thick" };
|
||
break;
|
||
case 89:
|
||
this.$ = { "type": "arrow_cross", "stroke": "thick" };
|
||
break;
|
||
case 90:
|
||
this.$ = { "type": "arrow_open", "stroke": "thick" };
|
||
break;
|
||
case 91:
|
||
this.$ = $$[$0 - 1];
|
||
break;
|
||
case 110:case 111:
|
||
this.$ = $$[$0 - 4];yy.addClass($$[$0 - 2], $$[$0]);
|
||
break;
|
||
case 112:
|
||
this.$ = $$[$0 - 4];yy.setClass($$[$0 - 2], $$[$0]);
|
||
break;
|
||
case 113:
|
||
this.$ = $$[$0 - 4];yy.setClickEvent($$[$0 - 2], $$[$0], undefined, undefined);
|
||
break;
|
||
case 114:
|
||
this.$ = $$[$0 - 6];yy.setClickEvent($$[$0 - 4], $$[$0 - 2], undefined, $$[$0]);
|
||
break;
|
||
case 115:
|
||
this.$ = $$[$0 - 4];yy.setClickEvent($$[$0 - 2], undefined, $$[$0], undefined);
|
||
break;
|
||
case 116:
|
||
this.$ = $$[$0 - 6];yy.setClickEvent($$[$0 - 4], undefined, $$[$0 - 2], $$[$0]);
|
||
break;
|
||
case 117:
|
||
this.$ = $$[$0 - 4];yy.addVertex($$[$0 - 2], undefined, undefined, $$[$0]);
|
||
break;
|
||
case 118:case 119:case 120:
|
||
this.$ = $$[$0 - 4];yy.updateLink($$[$0 - 2], $$[$0]);
|
||
break;
|
||
case 122:
|
||
this.$ = [$$[$0]];
|
||
break;
|
||
case 123:
|
||
$$[$0 - 2].push($$[$0]);this.$ = $$[$0 - 2];
|
||
break;
|
||
case 125:
|
||
this.$ = $$[$0 - 1] + $$[$0];
|
||
break;
|
||
}
|
||
},
|
||
table: [{ 3: 1, 4: 2, 9: $V0, 10: $V1, 12: $V2 }, { 1: [3] }, o($V3, $V4, { 5: 6 }), { 4: 7, 9: $V0, 10: $V1, 12: $V2 }, { 4: 8, 9: $V0, 10: $V1, 12: $V2 }, { 10: [1, 9] }, { 1: [2, 1], 6: 10, 7: 11, 8: $V5, 9: $V6, 10: $V7, 11: $V8, 13: $V9, 18: $Va, 23: 16, 25: 17, 26: 18, 27: 19, 28: 20, 29: 21, 30: $Vb, 33: 23, 35: 29, 44: 30, 45: 32, 46: $Vc, 71: $Vd, 72: $Ve, 73: $Vf, 74: $Vg, 75: $Vh, 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, o($V3, [2, 9]), o($V3, [2, 10]), { 13: [1, 46], 15: [1, 47], 16: [1, 48], 17: [1, 49], 18: [1, 50] }, o($Vt, [2, 3]), o($Vt, [2, 4]), o($Vt, [2, 5]), o($Vt, [2, 6]), o($Vt, [2, 7]), o($Vt, [2, 8]), { 8: $Vu, 9: $Vv, 11: $Vw, 24: 51 }, { 8: $Vu, 9: $Vv, 11: $Vw, 24: 55 }, { 8: $Vu, 9: $Vv, 11: $Vw, 24: 56 }, { 8: $Vu, 9: $Vv, 11: $Vw, 24: 57 }, { 8: $Vu, 9: $Vv, 11: $Vw, 24: 58 }, { 8: $Vu, 9: $Vv, 11: $Vw, 24: 59 }, { 8: $Vu, 9: $Vv, 10: $Vx, 11: $Vw, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 24: 61, 30: $VE, 31: 60, 32: $VF, 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 62, 67: $VJ, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, o($VR, [2, 42], { 34: 86, 47: 87, 50: [1, 88], 51: [1, 91], 52: [1, 92], 53: [1, 93], 54: [1, 94], 55: [1, 89], 56: [1, 95], 57: [1, 96], 58: [1, 97], 59: [1, 98], 60: [1, 90], 61: [1, 99], 62: [1, 100], 63: [1, 101], 64: [1, 102] }), { 10: [1, 103] }, { 10: [1, 104] }, { 10: [1, 105] }, { 10: [1, 106] }, { 10: [1, 107] }, o($VS, [2, 55], { 45: 32, 21: 113, 44: 114, 10: $VT, 13: $V9, 15: [1, 112], 18: $Va, 36: [1, 108], 38: [1, 109], 40: [1, 110], 42: [1, 111], 46: $Vc, 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }), o($VU, [2, 57]), o($VU, [2, 59]), o($VU, [2, 60]), o($VU, [2, 61]), o($VU, [2, 62]), o($VV, [2, 150]), o($VV, [2, 151]), o($VV, [2, 152]), o($VV, [2, 153]), o($VV, [2, 154]), o($VV, [2, 155]), o($VV, [2, 156]), o($VV, [2, 157]), o($VV, [2, 158]), o($VV, [2, 159]), o($VV, [2, 160]), { 8: $VW, 9: $VX, 10: $VT, 14: 116, 21: 119 }, { 8: $VW, 9: $VX, 10: $VT, 14: 120, 21: 119 }, { 8: $VW, 9: $VX, 10: $VT, 14: 121, 21: 119 }, { 8: $VW, 9: $VX, 10: $VT, 14: 122, 21: 119 }, { 8: $VW, 9: $VX, 10: $VT, 14: 123, 21: 119 }, o($Vt, [2, 30]), o($Vt, [2, 38]), o($Vt, [2, 39]), o($Vt, [2, 40]), o($Vt, [2, 31]), o($Vt, [2, 32]), o($Vt, [2, 33]), o($Vt, [2, 34]), o($Vt, [2, 35]), { 8: $Vu, 9: $Vv, 10: $Vx, 11: $Vw, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 24: 124, 30: $VE, 32: $VF, 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 125, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, o($VY, $V4, { 5: 126 }), o($VZ, [2, 92]), o($VZ, [2, 94]), o($VZ, [2, 139]), o($VZ, [2, 140]), o($VZ, [2, 141]), o($VZ, [2, 142]), o($VZ, [2, 143]), o($VZ, [2, 144]), o($VZ, [2, 145]), o($VZ, [2, 146]), o($VZ, [2, 147]), o($VZ, [2, 148]), o($VZ, [2, 149]), o($VZ, [2, 97]), o($VZ, [2, 98]), o($VZ, [2, 99]), o($VZ, [2, 100]), o($VZ, [2, 101]), o($VZ, [2, 102]), o($VZ, [2, 103]), o($VZ, [2, 104]), o($VZ, [2, 105]), o($VZ, [2, 106]), o($VZ, [2, 107]), { 13: $V9, 18: $Va, 33: 127, 35: 29, 44: 30, 45: 32, 46: $Vc, 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, o($V_, [2, 66], { 48: 128, 49: [1, 129], 65: [1, 130] }), { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 31: 131, 32: $VF, 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 62, 67: $VJ, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 31: 132, 32: $VF, 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 62, 67: $VJ, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 31: 133, 32: $VF, 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 62, 67: $VJ, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, o($V$, [2, 79]), o($V$, [2, 80]), o($V$, [2, 81]), o($V$, [2, 82]), o($V$, [2, 83]), o($V$, [2, 84]), o($V$, [2, 85]), o($V$, [2, 86]), o($V$, [2, 87]), o($V$, [2, 88]), o($V$, [2, 89]), o($V$, [2, 90]), { 13: $V9, 18: $Va, 35: 134, 44: 30, 45: 32, 46: $Vc, 80: [1, 135], 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 78: [1, 136], 81: [1, 137] }, { 13: $V9, 18: $Va, 35: 139, 44: 30, 45: 32, 46: $Vc, 78: [1, 138], 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 13: $V9, 18: $Va, 35: 140, 44: 30, 45: 32, 46: $Vc, 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 13: $V9, 18: $Va, 35: 141, 44: 30, 45: 32, 46: $Vc, 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 31: 142, 32: $VF, 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 62, 67: $VJ, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 31: 144, 32: $VF, 38: [1, 143], 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 62, 67: $VJ, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 31: 145, 32: $VF, 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 62, 67: $VJ, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 31: 146, 32: $VF, 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 62, 67: $VJ, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 31: 147, 32: $VF, 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 62, 67: $VJ, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, o($VS, [2, 56]), o($VU, [2, 58]), o($VS, [2, 29], { 21: 148, 10: $VT }), o($V3, [2, 11]), o($V3, [2, 21]), o($V3, [2, 22]), { 9: [1, 149] }, o($V3, [2, 12]), o($V3, [2, 13]), o($V3, [2, 14]), o($V3, [2, 15]), o($VY, $V4, { 5: 150 }), o($VZ, [2, 93]), { 6: 10, 7: 11, 8: $V5, 9: $V6, 10: $V7, 11: $V8, 13: $V9, 18: $Va, 23: 16, 25: 17, 26: 18, 27: 19, 28: 20, 29: 21, 30: $Vb, 32: [1, 151], 33: 23, 35: 29, 44: 30, 45: 32, 46: $Vc, 71: $Vd, 72: $Ve, 73: $Vf, 74: $Vg, 75: $Vh, 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, o($VR, [2, 41]), o($V_, [2, 63], { 10: [1, 152] }), { 10: [1, 153] }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 31: 154, 32: $VF, 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 62, 67: $VJ, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 32: $VF, 45: 71, 46: $VG, 50: $VH, 51: [1, 155], 52: [1, 156], 53: [1, 157], 54: [1, 158], 60: $VI, 66: 125, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 32: $VF, 45: 71, 46: $VG, 50: $VH, 56: [1, 159], 57: [1, 160], 58: [1, 161], 59: [1, 162], 60: $VI, 66: 125, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 32: $VF, 45: 71, 46: $VG, 50: $VH, 60: $VI, 61: [1, 163], 62: [1, 164], 63: [1, 165], 64: [1, 166], 66: 125, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: [1, 167], 13: $V9, 18: $Va, 44: 114, 45: 32, 46: $Vc, 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: [1, 168] }, { 10: [1, 169] }, { 10: [1, 170] }, { 10: [1, 171] }, { 10: [1, 172], 13: $V9, 18: $Va, 44: 114, 45: 32, 46: $Vc, 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: [1, 173], 13: $V9, 18: $Va, 44: 114, 45: 32, 46: $Vc, 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: [1, 174], 13: $V9, 18: $Va, 44: 114, 45: 32, 46: $Vc, 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 32: $VF, 37: [1, 175], 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 125, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 31: 176, 32: $VF, 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 62, 67: $VJ, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 32: $VF, 39: [1, 177], 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 125, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 32: $VF, 41: [1, 178], 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 125, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 32: $VF, 43: [1, 179], 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 125, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 32: $VF, 37: [1, 180], 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 125, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, o($VS, [2, 28]), o($V3, [2, 23]), { 6: 10, 7: 11, 8: $V5, 9: $V6, 10: $V7, 11: $V8, 13: $V9, 18: $Va, 23: 16, 25: 17, 26: 18, 27: 19, 28: 20, 29: 21, 30: $Vb, 32: [1, 181], 33: 23, 35: 29, 44: 30, 45: 32, 46: $Vc, 71: $Vd, 72: $Ve, 73: $Vf, 74: $Vg, 75: $Vh, 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, o($Vt, [2, 37]), o($V_, [2, 65]), o($V_, [2, 64]), { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 32: $VF, 45: 71, 46: $VG, 50: $VH, 60: $VI, 65: [1, 182], 66: 125, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, o($V_, [2, 67]), o($V_, [2, 68]), o($V_, [2, 69]), o($V_, [2, 70]), o($V_, [2, 71]), o($V_, [2, 72]), o($V_, [2, 73]), o($V_, [2, 74]), o($V_, [2, 75]), o($V_, [2, 76]), o($V_, [2, 77]), o($V_, [2, 78]), { 10: $V01, 46: $V11, 71: $V21, 79: 183, 80: $V31, 81: $V41, 83: $V51, 84: 184, 86: 185, 87: $V61, 88: $V71, 89: $V81, 90: $V91, 91: $Va1 }, { 10: $V01, 46: $V11, 71: $V21, 79: 197, 80: $V31, 81: $V41, 83: $V51, 84: 184, 86: 185, 87: $V61, 88: $V71, 89: $V81, 90: $V91, 91: $Va1 }, { 10: $V01, 46: $V11, 71: $V21, 79: 198, 80: $V31, 81: $V41, 83: $V51, 84: 184, 86: 185, 87: $V61, 88: $V71, 89: $V81, 90: $V91, 91: $Va1 }, { 10: $V01, 46: $V11, 71: $V21, 79: 199, 80: $V31, 81: $V41, 83: $V51, 84: 184, 86: 185, 87: $V61, 88: $V71, 89: $V81, 90: $V91, 91: $Va1 }, { 10: $V01, 46: $V11, 71: $V21, 79: 200, 80: $V31, 81: $V41, 83: $V51, 84: 184, 86: 185, 87: $V61, 88: $V71, 89: $V81, 90: $V91, 91: $Va1 }, { 10: $V01, 46: $V11, 71: $V21, 79: 201, 80: $V31, 81: $V41, 83: $V51, 84: 184, 86: 185, 87: $V61, 88: $V71, 89: $V81, 90: $V91, 91: $Va1 }, { 13: $V9, 18: $Va, 35: 202, 44: 30, 45: 32, 46: $Vc, 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, { 13: $V9, 18: $Va, 35: 203, 44: 30, 45: 32, 46: $Vc, 67: [1, 204], 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, o($VS, [2, 43], { 21: 205, 10: $VT }), { 10: $Vx, 12: $Vy, 13: $Vz, 15: $VA, 16: $VB, 17: $VC, 18: $VD, 30: $VE, 32: $VF, 39: [1, 206], 45: 71, 46: $VG, 50: $VH, 60: $VI, 66: 125, 70: 74, 71: $VK, 72: $VL, 73: $VM, 74: $VN, 75: $VO, 77: 64, 78: $VP, 81: $Vi, 83: $VQ, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }, o($VS, [2, 49], { 21: 207, 10: $VT }), o($VS, [2, 47], { 21: 208, 10: $VT }), o($VS, [2, 51], { 21: 209, 10: $VT }), o($VS, [2, 53], { 21: 210, 10: $VT }), o($Vt, [2, 36]), o([10, 13, 18, 46, 81, 85, 87, 88, 90, 91, 93, 94, 95, 96, 97], [2, 91]), o($VR, [2, 117], { 85: $Vb1 }), o($Vc1, [2, 122], { 86: 212, 10: $V01, 46: $V11, 71: $V21, 80: $V31, 81: $V41, 83: $V51, 87: $V61, 88: $V71, 89: $V81, 90: $V91, 91: $Va1 }), o($Vd1, [2, 124]), o($Vd1, [2, 126]), o($Vd1, [2, 127]), o($Vd1, [2, 128]), o($Vd1, [2, 129]), o($Vd1, [2, 130]), o($Vd1, [2, 131]), o($Vd1, [2, 132]), o($Vd1, [2, 133]), o($Vd1, [2, 134]), o($Vd1, [2, 135]), o($Vd1, [2, 136]), o($VR, [2, 118], { 85: $Vb1 }), o($VR, [2, 119], { 85: $Vb1 }), o($VR, [2, 120], { 85: $Vb1 }), o($VR, [2, 110], { 85: $Vb1 }), o($VR, [2, 111], { 85: $Vb1 }), o($VR, [2, 112], { 45: 32, 44: 114, 13: $V9, 18: $Va, 46: $Vc, 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }), o($VR, [2, 113], { 45: 32, 44: 114, 10: [1, 213], 13: $V9, 18: $Va, 46: $Vc, 81: $Vi, 85: $Vj, 87: $Vk, 88: $Vl, 90: $Vm, 91: $Vn, 93: $Vo, 94: $Vp, 95: $Vq, 96: $Vr, 97: $Vs }), o($VR, [2, 115], { 10: [1, 214] }), o($VS, [2, 44]), { 39: [1, 215] }, o($VS, [2, 50]), o($VS, [2, 48]), o($VS, [2, 52]), o($VS, [2, 54]), { 10: $V01, 46: $V11, 71: $V21, 80: $V31, 81: $V41, 83: $V51, 84: 216, 86: 185, 87: $V61, 88: $V71, 89: $V81, 90: $V91, 91: $Va1 }, o($Vd1, [2, 125]), { 67: [1, 217] }, { 67: [1, 218] }, o($VS, [2, 45], { 21: 219, 10: $VT }), o($Vc1, [2, 123], { 86: 212, 10: $V01, 46: $V11, 71: $V21, 80: $V31, 81: $V41, 83: $V51, 87: $V61, 88: $V71, 89: $V81, 90: $V91, 91: $Va1 }), o($VR, [2, 114]), o($VR, [2, 116]), o($VS, [2, 46])],
|
||
defaultActions: {},
|
||
parseError: function parseError(str, hash) {
|
||
if (hash.recoverable) {
|
||
this.trace(str);
|
||
} else {
|
||
var _parseError = function _parseError(msg, hash) {
|
||
this.message = msg;
|
||
this.hash = hash;
|
||
};
|
||
|
||
_parseError.prototype = new Error();
|
||
|
||
throw new _parseError(str, hash);
|
||
}
|
||
},
|
||
parse: function parse(input) {
|
||
var self = this,
|
||
stack = [0],
|
||
tstack = [],
|
||
vstack = [null],
|
||
lstack = [],
|
||
table = this.table,
|
||
yytext = '',
|
||
yylineno = 0,
|
||
yyleng = 0,
|
||
recovering = 0,
|
||
TERROR = 2,
|
||
EOF = 1;
|
||
var args = lstack.slice.call(arguments, 1);
|
||
var lexer = Object.create(this.lexer);
|
||
var sharedState = { yy: {} };
|
||
for (var k in this.yy) {
|
||
if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
|
||
sharedState.yy[k] = this.yy[k];
|
||
}
|
||
}
|
||
lexer.setInput(input, sharedState.yy);
|
||
sharedState.yy.lexer = lexer;
|
||
sharedState.yy.parser = this;
|
||
if (typeof lexer.yylloc == 'undefined') {
|
||
lexer.yylloc = {};
|
||
}
|
||
var yyloc = lexer.yylloc;
|
||
lstack.push(yyloc);
|
||
var ranges = lexer.options && lexer.options.ranges;
|
||
if (typeof sharedState.yy.parseError === 'function') {
|
||
this.parseError = sharedState.yy.parseError;
|
||
} else {
|
||
this.parseError = Object.getPrototypeOf(this).parseError;
|
||
}
|
||
function popStack(n) {
|
||
stack.length = stack.length - 2 * n;
|
||
vstack.length = vstack.length - n;
|
||
lstack.length = lstack.length - n;
|
||
}
|
||
_token_stack: var lex = function lex() {
|
||
var token;
|
||
token = lexer.lex() || EOF;
|
||
if (typeof token !== 'number') {
|
||
token = self.symbols_[token] || token;
|
||
}
|
||
return token;
|
||
};
|
||
var symbol,
|
||
preErrorSymbol,
|
||
state,
|
||
action,
|
||
a,
|
||
r,
|
||
yyval = {},
|
||
p,
|
||
len,
|
||
newState,
|
||
expected;
|
||
while (true) {
|
||
state = stack[stack.length - 1];
|
||
if (this.defaultActions[state]) {
|
||
action = this.defaultActions[state];
|
||
} else {
|
||
if (symbol === null || typeof symbol == 'undefined') {
|
||
symbol = lex();
|
||
}
|
||
action = table[state] && table[state][symbol];
|
||
}
|
||
if (typeof action === 'undefined' || !action.length || !action[0]) {
|
||
var errStr = '';
|
||
expected = [];
|
||
for (p in table[state]) {
|
||
if (this.terminals_[p] && p > TERROR) {
|
||
expected.push('\'' + this.terminals_[p] + '\'');
|
||
}
|
||
}
|
||
if (lexer.showPosition) {
|
||
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
|
||
} else {
|
||
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
|
||
}
|
||
this.parseError(errStr, {
|
||
text: lexer.match,
|
||
token: this.terminals_[symbol] || symbol,
|
||
line: lexer.yylineno,
|
||
loc: yyloc,
|
||
expected: expected
|
||
});
|
||
}
|
||
if (action[0] instanceof Array && action.length > 1) {
|
||
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
|
||
}
|
||
switch (action[0]) {
|
||
case 1:
|
||
stack.push(symbol);
|
||
vstack.push(lexer.yytext);
|
||
lstack.push(lexer.yylloc);
|
||
stack.push(action[1]);
|
||
symbol = null;
|
||
if (!preErrorSymbol) {
|
||
yyleng = lexer.yyleng;
|
||
yytext = lexer.yytext;
|
||
yylineno = lexer.yylineno;
|
||
yyloc = lexer.yylloc;
|
||
if (recovering > 0) {
|
||
recovering--;
|
||
}
|
||
} else {
|
||
symbol = preErrorSymbol;
|
||
preErrorSymbol = null;
|
||
}
|
||
break;
|
||
case 2:
|
||
len = this.productions_[action[1]][1];
|
||
yyval.$ = vstack[vstack.length - len];
|
||
yyval._$ = {
|
||
first_line: lstack[lstack.length - (len || 1)].first_line,
|
||
last_line: lstack[lstack.length - 1].last_line,
|
||
first_column: lstack[lstack.length - (len || 1)].first_column,
|
||
last_column: lstack[lstack.length - 1].last_column
|
||
};
|
||
if (ranges) {
|
||
yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
|
||
}
|
||
r = this.performAction.apply(yyval, [yytext, yyleng, yylineno, sharedState.yy, action[1], vstack, lstack].concat(args));
|
||
if (typeof r !== 'undefined') {
|
||
return r;
|
||
}
|
||
if (len) {
|
||
stack = stack.slice(0, -1 * len * 2);
|
||
vstack = vstack.slice(0, -1 * len);
|
||
lstack = lstack.slice(0, -1 * len);
|
||
}
|
||
stack.push(this.productions_[action[1]][0]);
|
||
vstack.push(yyval.$);
|
||
lstack.push(yyval._$);
|
||
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
|
||
stack.push(newState);
|
||
break;
|
||
case 3:
|
||
return true;
|
||
}
|
||
}
|
||
return true;
|
||
} };
|
||
|
||
/* generated by jison-lex 0.3.4 */
|
||
var lexer = (function () {
|
||
var lexer = {
|
||
|
||
EOF: 1,
|
||
|
||
parseError: function parseError(str, hash) {
|
||
if (this.yy.parser) {
|
||
this.yy.parser.parseError(str, hash);
|
||
} else {
|
||
throw new Error(str);
|
||
}
|
||
},
|
||
|
||
// resets the lexer, sets new input
|
||
setInput: function setInput(input, yy) {
|
||
this.yy = yy || this.yy || {};
|
||
this._input = input;
|
||
this._more = this._backtrack = this.done = false;
|
||
this.yylineno = this.yyleng = 0;
|
||
this.yytext = this.matched = this.match = '';
|
||
this.conditionStack = ['INITIAL'];
|
||
this.yylloc = {
|
||
first_line: 1,
|
||
first_column: 0,
|
||
last_line: 1,
|
||
last_column: 0
|
||
};
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [0, 0];
|
||
}
|
||
this.offset = 0;
|
||
return this;
|
||
},
|
||
|
||
// consumes and returns one char from the input
|
||
input: function input() {
|
||
var ch = this._input[0];
|
||
this.yytext += ch;
|
||
this.yyleng++;
|
||
this.offset++;
|
||
this.match += ch;
|
||
this.matched += ch;
|
||
var lines = ch.match(/(?:\r\n?|\n).*/g);
|
||
if (lines) {
|
||
this.yylineno++;
|
||
this.yylloc.last_line++;
|
||
} else {
|
||
this.yylloc.last_column++;
|
||
}
|
||
if (this.options.ranges) {
|
||
this.yylloc.range[1]++;
|
||
}
|
||
|
||
this._input = this._input.slice(1);
|
||
return ch;
|
||
},
|
||
|
||
// unshifts one char (or a string) into the input
|
||
unput: function unput(ch) {
|
||
var len = ch.length;
|
||
var lines = ch.split(/(?:\r\n?|\n)/g);
|
||
|
||
this._input = ch + this._input;
|
||
this.yytext = this.yytext.substr(0, this.yytext.length - len);
|
||
//this.yyleng -= len;
|
||
this.offset -= len;
|
||
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
|
||
this.match = this.match.substr(0, this.match.length - 1);
|
||
this.matched = this.matched.substr(0, this.matched.length - 1);
|
||
|
||
if (lines.length - 1) {
|
||
this.yylineno -= lines.length - 1;
|
||
}
|
||
var r = this.yylloc.range;
|
||
|
||
this.yylloc = {
|
||
first_line: this.yylloc.first_line,
|
||
last_line: this.yylineno + 1,
|
||
first_column: this.yylloc.first_column,
|
||
last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
|
||
};
|
||
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
|
||
}
|
||
this.yyleng = this.yytext.length;
|
||
return this;
|
||
},
|
||
|
||
// When called from action, caches matched text and appends it on next action
|
||
more: function more() {
|
||
this._more = true;
|
||
return this;
|
||
},
|
||
|
||
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
|
||
reject: function reject() {
|
||
if (this.options.backtrack_lexer) {
|
||
this._backtrack = true;
|
||
} else {
|
||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
|
||
text: "",
|
||
token: null,
|
||
line: this.yylineno
|
||
});
|
||
}
|
||
return this;
|
||
},
|
||
|
||
// retain first n characters of the match
|
||
less: function less(n) {
|
||
this.unput(this.match.slice(n));
|
||
},
|
||
|
||
// displays already matched input, i.e. for error messages
|
||
pastInput: function pastInput() {
|
||
var past = this.matched.substr(0, this.matched.length - this.match.length);
|
||
return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
|
||
},
|
||
|
||
// displays upcoming input, i.e. for error messages
|
||
upcomingInput: function upcomingInput() {
|
||
var next = this.match;
|
||
if (next.length < 20) {
|
||
next += this._input.substr(0, 20 - next.length);
|
||
}
|
||
return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
|
||
},
|
||
|
||
// displays the character position where the lexing error occurred, i.e. for error messages
|
||
showPosition: function showPosition() {
|
||
var pre = this.pastInput();
|
||
var c = new Array(pre.length + 1).join("-");
|
||
return pre + this.upcomingInput() + "\n" + c + "^";
|
||
},
|
||
|
||
// test the lexed token: return FALSE when not a match, otherwise return token
|
||
test_match: function test_match(match, indexed_rule) {
|
||
var token, lines, backup;
|
||
|
||
if (this.options.backtrack_lexer) {
|
||
// save context
|
||
backup = {
|
||
yylineno: this.yylineno,
|
||
yylloc: {
|
||
first_line: this.yylloc.first_line,
|
||
last_line: this.last_line,
|
||
first_column: this.yylloc.first_column,
|
||
last_column: this.yylloc.last_column
|
||
},
|
||
yytext: this.yytext,
|
||
match: this.match,
|
||
matches: this.matches,
|
||
matched: this.matched,
|
||
yyleng: this.yyleng,
|
||
offset: this.offset,
|
||
_more: this._more,
|
||
_input: this._input,
|
||
yy: this.yy,
|
||
conditionStack: this.conditionStack.slice(0),
|
||
done: this.done
|
||
};
|
||
if (this.options.ranges) {
|
||
backup.yylloc.range = this.yylloc.range.slice(0);
|
||
}
|
||
}
|
||
|
||
lines = match[0].match(/(?:\r\n?|\n).*/g);
|
||
if (lines) {
|
||
this.yylineno += lines.length;
|
||
}
|
||
this.yylloc = {
|
||
first_line: this.yylloc.last_line,
|
||
last_line: this.yylineno + 1,
|
||
first_column: this.yylloc.last_column,
|
||
last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length
|
||
};
|
||
this.yytext += match[0];
|
||
this.match += match[0];
|
||
this.matches = match;
|
||
this.yyleng = this.yytext.length;
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [this.offset, this.offset += this.yyleng];
|
||
}
|
||
this._more = false;
|
||
this._backtrack = false;
|
||
this._input = this._input.slice(match[0].length);
|
||
this.matched += match[0];
|
||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
|
||
if (this.done && this._input) {
|
||
this.done = false;
|
||
}
|
||
if (token) {
|
||
return token;
|
||
} else if (this._backtrack) {
|
||
// recover context
|
||
for (var k in backup) {
|
||
this[k] = backup[k];
|
||
}
|
||
return false; // rule action called reject() implying the next rule should be tested instead.
|
||
}
|
||
return false;
|
||
},
|
||
|
||
// return next match in input
|
||
next: function next() {
|
||
if (this.done) {
|
||
return this.EOF;
|
||
}
|
||
if (!this._input) {
|
||
this.done = true;
|
||
}
|
||
|
||
var token, match, tempMatch, index;
|
||
if (!this._more) {
|
||
this.yytext = '';
|
||
this.match = '';
|
||
}
|
||
var rules = this._currentRules();
|
||
for (var i = 0; i < rules.length; i++) {
|
||
tempMatch = this._input.match(this.rules[rules[i]]);
|
||
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
|
||
match = tempMatch;
|
||
index = i;
|
||
if (this.options.backtrack_lexer) {
|
||
token = this.test_match(tempMatch, rules[i]);
|
||
if (token !== false) {
|
||
return token;
|
||
} else if (this._backtrack) {
|
||
match = false;
|
||
continue; // rule action called reject() implying a rule MISmatch.
|
||
} else {
|
||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||
return false;
|
||
}
|
||
} else if (!this.options.flex) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (match) {
|
||
token = this.test_match(match, rules[index]);
|
||
if (token !== false) {
|
||
return token;
|
||
}
|
||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||
return false;
|
||
}
|
||
if (this._input === "") {
|
||
return this.EOF;
|
||
} else {
|
||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
|
||
text: "",
|
||
token: null,
|
||
line: this.yylineno
|
||
});
|
||
}
|
||
},
|
||
|
||
// return next match that has a token
|
||
lex: function lex() {
|
||
var r = this.next();
|
||
if (r) {
|
||
return r;
|
||
} else {
|
||
return this.lex();
|
||
}
|
||
},
|
||
|
||
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
|
||
begin: function begin(condition) {
|
||
this.conditionStack.push(condition);
|
||
},
|
||
|
||
// pop the previously active lexer condition state off the condition stack
|
||
popState: function popState() {
|
||
var n = this.conditionStack.length - 1;
|
||
if (n > 0) {
|
||
return this.conditionStack.pop();
|
||
} else {
|
||
return this.conditionStack[0];
|
||
}
|
||
},
|
||
|
||
// produce the lexer rule set which is active for the currently active lexer condition state
|
||
_currentRules: function _currentRules() {
|
||
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
|
||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
|
||
} else {
|
||
return this.conditions["INITIAL"].rules;
|
||
}
|
||
},
|
||
|
||
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
|
||
topState: function topState(n) {
|
||
n = this.conditionStack.length - 1 - Math.abs(n || 0);
|
||
if (n >= 0) {
|
||
return this.conditionStack[n];
|
||
} else {
|
||
return "INITIAL";
|
||
}
|
||
},
|
||
|
||
// alias for begin(condition)
|
||
pushState: function pushState(condition) {
|
||
this.begin(condition);
|
||
},
|
||
|
||
// return the number of states currently on the stack
|
||
stateStackSize: function stateStackSize() {
|
||
return this.conditionStack.length;
|
||
},
|
||
options: {},
|
||
performAction: function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
|
||
var YYSTATE = YY_START;
|
||
switch ($avoiding_name_collisions) {
|
||
case 0:
|
||
/* do nothing */
|
||
break;
|
||
case 1:
|
||
this.begin("string");
|
||
break;
|
||
case 2:
|
||
this.popState();
|
||
break;
|
||
case 3:
|
||
return "STR";
|
||
break;
|
||
case 4:
|
||
return 71;
|
||
break;
|
||
case 5:
|
||
return 78;
|
||
break;
|
||
case 6:
|
||
return 72;
|
||
break;
|
||
case 7:
|
||
return 73;
|
||
break;
|
||
case 8:
|
||
return 74;
|
||
break;
|
||
case 9:
|
||
return 75;
|
||
break;
|
||
case 10:
|
||
return 12;
|
||
break;
|
||
case 11:
|
||
return 30;
|
||
break;
|
||
case 12:
|
||
return 32;
|
||
break;
|
||
case 13:
|
||
return 13;
|
||
break;
|
||
case 14:
|
||
return 13;
|
||
break;
|
||
case 15:
|
||
return 13;
|
||
break;
|
||
case 16:
|
||
return 13;
|
||
break;
|
||
case 17:
|
||
return 13;
|
||
break;
|
||
case 18:
|
||
return 13;
|
||
break;
|
||
case 19:
|
||
return 81;
|
||
break;
|
||
case 20:
|
||
return 90;
|
||
break;
|
||
case 21:
|
||
return 88;
|
||
break;
|
||
case 22:
|
||
return 8;
|
||
break;
|
||
case 23:
|
||
return 85;
|
||
break;
|
||
case 24:
|
||
return 97;
|
||
break;
|
||
case 25:
|
||
return 16;
|
||
break;
|
||
case 26:
|
||
return 15;
|
||
break;
|
||
case 27:
|
||
return 17;
|
||
break;
|
||
case 28:
|
||
return 18;
|
||
break;
|
||
case 29:
|
||
return 53;
|
||
break;
|
||
case 30:
|
||
return 51;
|
||
break;
|
||
case 31:
|
||
return 52;
|
||
break;
|
||
case 32:
|
||
return 54;
|
||
break;
|
||
case 33:
|
||
return 58;
|
||
break;
|
||
case 34:
|
||
return 56;
|
||
break;
|
||
case 35:
|
||
return 57;
|
||
break;
|
||
case 36:
|
||
return 59;
|
||
break;
|
||
case 37:
|
||
return 58;
|
||
break;
|
||
case 38:
|
||
return 56;
|
||
break;
|
||
case 39:
|
||
return 57;
|
||
break;
|
||
case 40:
|
||
return 59;
|
||
break;
|
||
case 41:
|
||
return 63;
|
||
break;
|
||
case 42:
|
||
return 61;
|
||
break;
|
||
case 43:
|
||
return 62;
|
||
break;
|
||
case 44:
|
||
return 64;
|
||
break;
|
||
case 45:
|
||
return 50;
|
||
break;
|
||
case 46:
|
||
return 55;
|
||
break;
|
||
case 47:
|
||
return 60;
|
||
break;
|
||
case 48:
|
||
return 40;
|
||
break;
|
||
case 49:
|
||
return 41;
|
||
break;
|
||
case 50:
|
||
return 46;
|
||
break;
|
||
case 51:
|
||
return 91;
|
||
break;
|
||
case 52:
|
||
return 95;
|
||
break;
|
||
case 53:
|
||
return 83;
|
||
break;
|
||
case 54:
|
||
return 96;
|
||
break;
|
||
case 55:
|
||
return 96;
|
||
break;
|
||
case 56:
|
||
return 87;
|
||
break;
|
||
case 57:
|
||
return 93;
|
||
break;
|
||
case 58:
|
||
return 94;
|
||
break;
|
||
case 59:
|
||
return 65;
|
||
break;
|
||
case 60:
|
||
return 38;
|
||
break;
|
||
case 61:
|
||
return 39;
|
||
break;
|
||
case 62:
|
||
return 36;
|
||
break;
|
||
case 63:
|
||
return 37;
|
||
break;
|
||
case 64:
|
||
return 42;
|
||
break;
|
||
case 65:
|
||
return 43;
|
||
break;
|
||
case 66:
|
||
return 100;
|
||
break;
|
||
case 67:
|
||
return 9;
|
||
break;
|
||
case 68:
|
||
return 10;
|
||
break;
|
||
case 69:
|
||
return 11;
|
||
break;
|
||
}
|
||
},
|
||
rules: [/^(?:%%[^\n]*)/, /^(?:["])/, /^(?:["])/, /^(?:[^"]*)/, /^(?:style\b)/, /^(?:default\b)/, /^(?:linkStyle\b)/, /^(?:classDef\b)/, /^(?:class\b)/, /^(?:click\b)/, /^(?:graph\b)/, /^(?:subgraph\b)/, /^(?:end\b\s*)/, /^(?:LR\b)/, /^(?:RL\b)/, /^(?:TB\b)/, /^(?:BT\b)/, /^(?:TD\b)/, /^(?:BR\b)/, /^(?:[0-9]+)/, /^(?:#)/, /^(?::)/, /^(?:;)/, /^(?:,)/, /^(?:\*)/, /^(?:<)/, /^(?:>)/, /^(?:\^)/, /^(?:v\b)/, /^(?:\s*--[x]\s*)/, /^(?:\s*-->\s*)/, /^(?:\s*--[o]\s*)/, /^(?:\s*---\s*)/, /^(?:\s*-\.-[x]\s*)/, /^(?:\s*-\.->\s*)/, /^(?:\s*-\.-[o]\s*)/, /^(?:\s*-\.-\s*)/, /^(?:\s*.-[x]\s*)/, /^(?:\s*\.->\s*)/, /^(?:\s*\.-[o]\s*)/, /^(?:\s*\.-\s*)/, /^(?:\s*==[x]\s*)/, /^(?:\s*==>\s*)/, /^(?:\s*==[o]\s*)/, /^(?:\s*==[\=]\s*)/, /^(?:\s*--\s*)/, /^(?:\s*-\.\s*)/, /^(?:\s*==\s*)/, /^(?:\(-)/, /^(?:-\))/, /^(?:-)/, /^(?:\.)/, /^(?:\+)/, /^(?:%)/, /^(?:=)/, /^(?:=)/, /^(?:[A-Za-z]+)/, /^(?:[!"#$%&'*+,-.`?\\_\/])/, /^(?:[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]|[\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE]|[\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA]|[\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0]|[\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977]|[\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2]|[\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A]|[\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39]|[\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8]|[\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C]|[\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C]|[\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99]|[\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0]|[\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D]|[\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3]|[\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10]|[\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1]|[\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81]|[\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3]|[\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6]|[\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A]|[\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081]|[\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D]|[\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0]|[\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310]|[\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C]|[\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711]|[\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7]|[\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C]|[\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16]|[\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF]|[\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC]|[\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D]|[\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D]|[\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3]|[\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F]|[\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128]|[\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184]|[\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3]|[\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6]|[\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE]|[\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C]|[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D]|[\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC]|[\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B]|[\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788]|[\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805]|[\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB]|[\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28]|[\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5]|[\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4]|[\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E]|[\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D]|[\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36]|[\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D]|[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|[\uFFD2-\uFFD7\uFFDA-\uFFDC])/, /^(?:\|)/, /^(?:\()/, /^(?:\))/, /^(?:\[)/, /^(?:\])/, /^(?:\{)/, /^(?:\})/, /^(?:")/, /^(?:\n+)/, /^(?:\s)/, /^(?:$)/],
|
||
conditions: { "string": { "rules": [2, 3], "inclusive": false }, "INITIAL": { "rules": [0, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 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, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69], "inclusive": true } }
|
||
};
|
||
return lexer;
|
||
})();
|
||
parser.lexer = lexer;
|
||
function Parser() {
|
||
this.yy = {};
|
||
}
|
||
Parser.prototype = parser;parser.Parser = Parser;
|
||
return new Parser();
|
||
})();
|
||
|
||
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
|
||
exports.parser = flow;
|
||
exports.Parser = flow.Parser;
|
||
exports.parse = function () {
|
||
return flow.parse.apply(flow, arguments);
|
||
};
|
||
exports.main = function commonjsMain(args) {
|
||
if (!args[1]) {
|
||
console.log('Usage: ' + args[0] + ' FILE');
|
||
process.exit(1);
|
||
}
|
||
var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
|
||
return exports.parser.parse(source);
|
||
};
|
||
if (typeof module !== 'undefined' && require.main === module) {
|
||
exports.main(process.argv.slice(1));
|
||
}
|
||
}
|
||
|
||
}).call(this,require('_process'))
|
||
},{"_process":3,"fs":1,"path":2}],119:[function(require,module,exports){
|
||
(function (global){
|
||
/**
|
||
* Created by knut on 15-01-14.
|
||
*/
|
||
'use strict';
|
||
|
||
var moment = require('moment');
|
||
var Logger = require('../../logger');
|
||
var log = new Logger.Log();
|
||
|
||
var dateFormat = '';
|
||
var title = '';
|
||
var sections = [];
|
||
var tasks = [];
|
||
var currentSection = '';
|
||
|
||
exports.clear = function () {
|
||
sections = [];
|
||
tasks = [];
|
||
currentSection = '';
|
||
title = '';
|
||
taskCnt = 0;
|
||
lastTask = undefined;
|
||
lastTaskID = undefined;
|
||
rawTasks = [];
|
||
};
|
||
|
||
exports.setDateFormat = function (txt) {
|
||
dateFormat = txt;
|
||
};
|
||
|
||
exports.getDateFormat = function () {
|
||
return dateFormat;
|
||
};
|
||
exports.setTitle = function (txt) {
|
||
title = txt;
|
||
};
|
||
|
||
exports.getTitle = function () {
|
||
return title;
|
||
};
|
||
|
||
exports.addSection = function (txt) {
|
||
currentSection = txt;
|
||
sections.push(txt);
|
||
};
|
||
|
||
exports.getTasks = function () {
|
||
var allItemsPricessed = compileTasks();
|
||
var maxDepth = 10;
|
||
var iterationCount = 0;
|
||
while (!allItemsPricessed && iterationCount < maxDepth) {
|
||
allItemsPricessed = compileTasks();
|
||
iterationCount++;
|
||
}
|
||
|
||
tasks = rawTasks;
|
||
|
||
//var i;
|
||
//for(i=10000;i<tasks.length;i++){
|
||
// tasks[i].startTime = moment(tasks[i].startTime).format(dateFormat);
|
||
// tasks[i].endTime = moment(tasks[i].endTime).format(dateFormat);
|
||
//}
|
||
|
||
return tasks;
|
||
};
|
||
|
||
var getStartDate = function getStartDate(prevTime, dateFormat, str) {
|
||
//console.log('Deciding start date:'+JSON.stringify(str));
|
||
//log.debug('Deciding start date:'+str);
|
||
//log.debug('with dateformat:'+dateFormat);
|
||
|
||
str = str.trim();
|
||
|
||
// Test for after
|
||
var re = /^after\s+([\d\w\-]+)/;
|
||
var afterStatement = re.exec(str.trim());
|
||
|
||
if (afterStatement !== null) {
|
||
var task = exports.findTaskById(afterStatement[1]);
|
||
|
||
if (typeof task === 'undefined') {
|
||
var dt = new Date();
|
||
dt.setHours(0, 0, 0, 0);
|
||
return dt;
|
||
//return undefined;
|
||
}
|
||
return task.endTime;
|
||
}
|
||
|
||
// Check for actual date set
|
||
if (moment(str, dateFormat.trim(), true).isValid()) {
|
||
return moment(str, dateFormat.trim(), true).toDate();
|
||
} else {
|
||
log.debug('Invalid date:' + str);
|
||
log.debug('With date format:' + dateFormat.trim());
|
||
//log.debug('----');
|
||
}
|
||
|
||
// Default date - now
|
||
return new Date();
|
||
};
|
||
|
||
var getEndDate = function getEndDate(prevTime, dateFormat, str) {
|
||
str = str.trim();
|
||
|
||
// Check for actual date
|
||
if (moment(str, dateFormat.trim(), true).isValid()) {
|
||
|
||
return moment(str, dateFormat.trim()).toDate();
|
||
}
|
||
|
||
var d = moment(prevTime);
|
||
// Check for length
|
||
var re = /^([\d]+)([wdhms])/;
|
||
var durationStatement = re.exec(str.trim());
|
||
|
||
if (durationStatement !== null) {
|
||
switch (durationStatement[2]) {
|
||
case 's':
|
||
d.add(durationStatement[1], 'seconds');
|
||
break;
|
||
case 'm':
|
||
d.add(durationStatement[1], 'minutes');
|
||
break;
|
||
case 'h':
|
||
d.add(durationStatement[1], 'hours');
|
||
break;
|
||
case 'd':
|
||
d.add(durationStatement[1], 'days');
|
||
break;
|
||
case 'w':
|
||
d.add(durationStatement[1], 'weeks');
|
||
break;
|
||
}
|
||
return d.toDate();
|
||
}
|
||
// Default date - now
|
||
return d.toDate();
|
||
};
|
||
|
||
var taskCnt = 0;
|
||
var parseId = function parseId(idStr) {
|
||
if (typeof idStr === 'undefined') {
|
||
taskCnt = taskCnt + 1;
|
||
return 'task' + taskCnt;
|
||
}
|
||
return idStr;
|
||
};
|
||
// id, startDate, endDate
|
||
// id, startDate, length
|
||
// id, after x, endDate
|
||
// id, after x, length
|
||
// startDate, endDate
|
||
// startDate, length
|
||
// after x, endDate
|
||
// after x, length
|
||
// endDate
|
||
// length
|
||
|
||
var compileData = function compileData(prevTask, dataStr) {
|
||
var ds;
|
||
|
||
if (dataStr.substr(0, 1) === ':') {
|
||
ds = dataStr.substr(1, dataStr.length);
|
||
} else {
|
||
ds = dataStr;
|
||
}
|
||
|
||
var data = ds.split(',');
|
||
|
||
var task = {};
|
||
var df = exports.getDateFormat();
|
||
|
||
// Get tags like active, done cand crit
|
||
var matchFound = true;
|
||
while (matchFound) {
|
||
matchFound = false;
|
||
if (data[0].match(/^\s*active\s*$/)) {
|
||
task.active = true;
|
||
data.shift(1);
|
||
matchFound = true;
|
||
}
|
||
if (data[0].match(/^\s*done\s*$/)) {
|
||
task.done = true;
|
||
data.shift(1);
|
||
matchFound = true;
|
||
}
|
||
if (data[0].match(/^\s*crit\s*$/)) {
|
||
task.crit = true;
|
||
data.shift(1);
|
||
matchFound = true;
|
||
}
|
||
}
|
||
var i;
|
||
for (i = 0; i < data.length; i++) {
|
||
data[i] = data[i].trim();
|
||
}
|
||
|
||
switch (data.length) {
|
||
case 1:
|
||
task.id = parseId();
|
||
task.startTime = prevTask.endTime;
|
||
task.endTime = getEndDate(task.startTime, df, data[0]);
|
||
break;
|
||
case 2:
|
||
task.id = parseId();
|
||
task.startTime = getStartDate(undefined, df, data[0]);
|
||
task.endTime = getEndDate(task.startTime, df, data[1]);
|
||
break;
|
||
case 3:
|
||
task.id = parseId(data[0]);
|
||
task.startTime = getStartDate(undefined, df, data[1]);
|
||
task.endTime = getEndDate(task.startTime, df, data[2]);
|
||
break;
|
||
default:
|
||
|
||
}
|
||
|
||
return task;
|
||
};
|
||
|
||
var parseData = function parseData(prevTaskId, dataStr) {
|
||
var ds;
|
||
|
||
if (dataStr.substr(0, 1) === ':') {
|
||
ds = dataStr.substr(1, dataStr.length);
|
||
} else {
|
||
ds = dataStr;
|
||
}
|
||
|
||
var data = ds.split(',');
|
||
|
||
var task = {};
|
||
|
||
// Get tags like active, done cand crit
|
||
var matchFound = true;
|
||
while (matchFound) {
|
||
matchFound = false;
|
||
if (data[0].match(/^\s*active\s*$/)) {
|
||
task.active = true;
|
||
data.shift(1);
|
||
matchFound = true;
|
||
}
|
||
if (data[0].match(/^\s*done\s*$/)) {
|
||
task.done = true;
|
||
data.shift(1);
|
||
matchFound = true;
|
||
}
|
||
if (data[0].match(/^\s*crit\s*$/)) {
|
||
task.crit = true;
|
||
data.shift(1);
|
||
matchFound = true;
|
||
}
|
||
}
|
||
var i;
|
||
for (i = 0; i < data.length; i++) {
|
||
data[i] = data[i].trim();
|
||
}
|
||
|
||
switch (data.length) {
|
||
case 1:
|
||
task.id = parseId();
|
||
task.startTime = { type: 'prevTaskEnd', id: prevTaskId };
|
||
task.endTime = { data: data[0] };
|
||
break;
|
||
case 2:
|
||
task.id = parseId();
|
||
task.startTime = { type: 'getStartDate', startData: data[0] };
|
||
task.endTime = { data: data[1] };
|
||
break;
|
||
case 3:
|
||
task.id = parseId(data[0]);
|
||
task.startTime = { type: 'getStartDate', startData: data[1] };
|
||
task.endTime = { data: data[2] };
|
||
break;
|
||
default:
|
||
|
||
}
|
||
|
||
return task;
|
||
};
|
||
|
||
var lastTask;
|
||
var lastTaskID;
|
||
var rawTasks = [];
|
||
var taskDb = {};
|
||
exports.addTask = function (descr, data) {
|
||
var rawTask = {
|
||
section: currentSection,
|
||
type: currentSection,
|
||
processed: false,
|
||
raw: { data: data },
|
||
task: descr
|
||
};
|
||
var taskInfo = parseData(lastTaskID, data);
|
||
rawTask.raw.startTime = taskInfo.startTime;
|
||
rawTask.raw.endTime = taskInfo.endTime;
|
||
rawTask.id = taskInfo.id;
|
||
rawTask.prevTaskId = lastTaskID;
|
||
rawTask.active = taskInfo.active;
|
||
rawTask.done = taskInfo.done;
|
||
rawTask.crit = taskInfo.crit;
|
||
|
||
var pos = rawTasks.push(rawTask);
|
||
|
||
lastTaskID = rawTask.id;
|
||
// Store cross ref
|
||
taskDb[rawTask.id] = pos - 1;
|
||
};
|
||
|
||
exports.findTaskById = function (id) {
|
||
//var i;
|
||
//for(i=0;i<tasks.length;i++){
|
||
// if(tasks[i].id === id){
|
||
// return tasks[i];
|
||
// }
|
||
//}
|
||
|
||
var pos = taskDb[id];
|
||
return rawTasks[pos];
|
||
};
|
||
|
||
exports.addTaskOrg = function (descr, data) {
|
||
|
||
var newTask = {
|
||
section: currentSection,
|
||
type: currentSection,
|
||
description: descr,
|
||
task: descr
|
||
};
|
||
var taskInfo = compileData(lastTask, data);
|
||
newTask.startTime = taskInfo.startTime;
|
||
newTask.endTime = taskInfo.endTime;
|
||
newTask.id = taskInfo.id;
|
||
newTask.active = taskInfo.active;
|
||
newTask.done = taskInfo.done;
|
||
newTask.crit = taskInfo.crit;
|
||
lastTask = newTask;
|
||
tasks.push(newTask);
|
||
};
|
||
|
||
var compileTasks = function compileTasks() {
|
||
var df = exports.getDateFormat();
|
||
|
||
var compileTask = function compileTask(pos) {
|
||
var task = rawTasks[pos];
|
||
var startTime = '';
|
||
switch (rawTasks[pos].raw.startTime.type) {
|
||
case 'prevTaskEnd':
|
||
var prevTask = exports.findTaskById(task.prevTaskId);
|
||
task.startTime = prevTask.endTime;
|
||
break;
|
||
case 'getStartDate':
|
||
startTime = getStartDate(undefined, df, rawTasks[pos].raw.startTime.startData);
|
||
if (startTime) {
|
||
rawTasks[pos].startTime = startTime;
|
||
}
|
||
break;
|
||
}
|
||
|
||
if (rawTasks[pos].startTime) {
|
||
rawTasks[pos].endTime = getEndDate(rawTasks[pos].startTime, df, rawTasks[pos].raw.endTime.data);
|
||
if (rawTasks[pos].endTime) {
|
||
rawTasks[pos].processed = true;
|
||
}
|
||
}
|
||
|
||
return rawTasks[pos].processed;
|
||
};
|
||
|
||
var i;
|
||
var allProcessed = true;
|
||
for (i = 0; i < rawTasks.length; i++) {
|
||
compileTask(i);
|
||
|
||
allProcessed = allProcessed && rawTasks[i].processed;
|
||
}
|
||
return allProcessed;
|
||
};
|
||
|
||
exports.parseError = function (err, hash) {
|
||
global.mermaidAPI.parseError(err, hash);
|
||
};
|
||
|
||
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"../../logger":126,"moment":105}],120:[function(require,module,exports){
|
||
'use strict';
|
||
|
||
var gantt = require('./parser/gantt').parser;
|
||
gantt.yy = require('./ganttDb');
|
||
var d3 = require('../../d3');
|
||
var moment = require('moment');
|
||
//var log = require('../../logger').create();
|
||
|
||
var daysInChart;
|
||
var conf = {
|
||
titleTopMargin: 25,
|
||
barHeight: 20,
|
||
barGap: 4,
|
||
topPadding: 50,
|
||
sidePadding: 75,
|
||
gridLineStartPadding: 35,
|
||
fontSize: 11,
|
||
fontFamily: '"Open-Sans", "sans-serif"'
|
||
};
|
||
module.exports.setConf = function (cnf) {
|
||
var keys = Object.keys(cnf);
|
||
|
||
keys.forEach(function (key) {
|
||
conf[key] = cnf[key];
|
||
});
|
||
};
|
||
var w;
|
||
module.exports.draw = function (text, id) {
|
||
gantt.yy.clear();
|
||
gantt.parse(text);
|
||
|
||
var elem = document.getElementById(id);
|
||
w = elem.parentElement.offsetWidth;
|
||
|
||
if (typeof w === 'undefined') {
|
||
w = 1200;
|
||
}
|
||
|
||
if (typeof conf.useWidth !== 'undefined') {
|
||
w = conf.useWidth;
|
||
}
|
||
|
||
var taskArray = gantt.yy.getTasks();
|
||
|
||
// Set height based on number of tasks
|
||
var h = taskArray.length * (conf.barHeight + conf.barGap) + 2 * conf.topPadding;
|
||
|
||
elem.setAttribute('height', '100%');
|
||
// Set viewBox
|
||
elem.setAttribute('viewBox', '0 0 ' + w + ' ' + h);
|
||
var svg = d3.select('#' + id);
|
||
|
||
//var dateFormat = d3.time.format('%Y-%m-%d');
|
||
|
||
var startDate = d3.min(taskArray, function (d) {
|
||
return d.startTime;
|
||
});
|
||
var endDate = d3.max(taskArray, function (d) {
|
||
return d.endTime;
|
||
});
|
||
|
||
// Set timescale
|
||
var timeScale = d3.time.scale().domain([d3.min(taskArray, function (d) {
|
||
return d.startTime;
|
||
}), d3.max(taskArray, function (d) {
|
||
return d.endTime;
|
||
})]).rangeRound([0, w - 150]);
|
||
//.nice(d3.time.monday);
|
||
|
||
var categories = [];
|
||
|
||
daysInChart = moment.duration(endDate - startDate).asDays();
|
||
|
||
for (var i = 0; i < taskArray.length; i++) {
|
||
categories.push(taskArray[i].type);
|
||
}
|
||
|
||
var catsUnfiltered = categories; //for vert labels
|
||
|
||
categories = checkUnique(categories);
|
||
|
||
makeGant(taskArray, w, h);
|
||
if (typeof conf.useWidth !== 'undefined') {
|
||
elem.setAttribute('width', w);
|
||
}
|
||
|
||
svg.append('text').text(gantt.yy.getTitle()).attr('x', w / 2).attr('y', conf.titleTopMargin).attr('class', 'titleText');
|
||
|
||
function makeGant(tasks, pageWidth, pageHeight) {
|
||
|
||
var barHeight = conf.barHeight;
|
||
var gap = barHeight + conf.barGap;
|
||
var topPadding = conf.topPadding;
|
||
var sidePadding = conf.sidePadding;
|
||
|
||
var colorScale = d3.scale.linear().domain([0, categories.length]).range(['#00B9FA', '#F95002']).interpolate(d3.interpolateHcl);
|
||
|
||
makeGrid(sidePadding, topPadding, pageWidth, pageHeight);
|
||
drawRects(tasks, gap, topPadding, sidePadding, barHeight, colorScale, pageWidth, pageHeight);
|
||
vertLabels(gap, topPadding, sidePadding, barHeight, colorScale);
|
||
drawToday(sidePadding, topPadding, pageWidth, pageHeight);
|
||
}
|
||
|
||
function drawRects(theArray, theGap, theTopPad, theSidePad, theBarHeight, theColorScale, w, h) {
|
||
//eslint-disable-line no-unused-vars
|
||
|
||
svg.append('g').selectAll('rect').data(theArray).enter().append('rect').attr('x', 0).attr('y', function (d, i) {
|
||
return i * theGap + theTopPad - 2;
|
||
}).attr('width', function () {
|
||
return w - theSidePad / 2;
|
||
}).attr('height', theGap).attr('class', function (d) {
|
||
//eslint-disable-line no-unused-vars
|
||
for (var i = 0; i < categories.length; i++) {
|
||
if (d.type === categories[i]) {
|
||
return 'section section' + i % conf.numberSectionStyles;
|
||
}
|
||
}
|
||
return 'section section0';
|
||
});
|
||
|
||
var rectangles = svg.append('g').selectAll('rect').data(theArray).enter();
|
||
|
||
rectangles.append('rect').attr('rx', 3).attr('ry', 3).attr('x', function (d) {
|
||
return timeScale(d.startTime) + theSidePad;
|
||
}).attr('y', function (d, i) {
|
||
return i * theGap + theTopPad;
|
||
}).attr('width', function (d) {
|
||
return timeScale(d.endTime) - timeScale(d.startTime);
|
||
}).attr('height', theBarHeight).attr('class', function (d) {
|
||
var res = 'task ';
|
||
|
||
var secNum = 0;
|
||
for (var i = 0; i < categories.length; i++) {
|
||
if (d.type === categories[i]) {
|
||
secNum = i % conf.numberSectionStyles;
|
||
}
|
||
}
|
||
|
||
if (d.active) {
|
||
if (d.crit) {
|
||
return res + ' activeCrit' + secNum;
|
||
} else {
|
||
return res + ' active' + secNum;
|
||
}
|
||
}
|
||
|
||
if (d.done) {
|
||
if (d.crit) {
|
||
return res + ' doneCrit' + secNum;
|
||
} else {
|
||
return res + ' done' + secNum;
|
||
}
|
||
}
|
||
|
||
if (d.crit) {
|
||
return res + ' crit' + secNum;
|
||
}
|
||
|
||
return res + ' task' + secNum;
|
||
});
|
||
|
||
rectangles.append('text').text(function (d) {
|
||
return d.task;
|
||
}).attr('font-size', conf.fontSize)
|
||
//.attr('font-family',conf.fontFamily)
|
||
.attr('x', function (d) {
|
||
var startX = timeScale(d.startTime),
|
||
endX = timeScale(d.endTime),
|
||
textWidth = this.getBBox().width;
|
||
|
||
// Check id text width > width of rectangle
|
||
if (textWidth > endX - startX) {
|
||
if (endX + textWidth + 1.5 * conf.sidePadding > w) {
|
||
return startX + theSidePad - 5;
|
||
} else {
|
||
return endX + theSidePad + 5;
|
||
}
|
||
} else {
|
||
return (endX - startX) / 2 + startX + theSidePad;
|
||
}
|
||
}).attr('y', function (d, i) {
|
||
return i * theGap + conf.barHeight / 2 + (conf.fontSize / 2 - 2) + theTopPad;
|
||
})
|
||
//.attr('text-anchor', 'middle')
|
||
.attr('text-height', theBarHeight).attr('class', function (d) {
|
||
var startX = timeScale(d.startTime),
|
||
endX = timeScale(d.endTime),
|
||
textWidth = this.getBBox().width;
|
||
var secNum = 0;
|
||
for (var i = 0; i < categories.length; i++) {
|
||
if (d.type === categories[i]) {
|
||
secNum = i % conf.numberSectionStyles;
|
||
}
|
||
}
|
||
|
||
var taskType = '';
|
||
if (d.active) {
|
||
if (d.crit) {
|
||
taskType = 'activeCritText' + secNum;
|
||
} else {
|
||
taskType = 'activeText' + secNum;
|
||
}
|
||
}
|
||
|
||
if (d.done) {
|
||
if (d.crit) {
|
||
taskType = taskType + ' doneCritText' + secNum;
|
||
} else {
|
||
taskType = taskType + ' doneText' + secNum;
|
||
}
|
||
} else {
|
||
if (d.crit) {
|
||
taskType = taskType + ' critText' + secNum;
|
||
}
|
||
}
|
||
|
||
// Check id text width > width of rectangle
|
||
if (textWidth > endX - startX) {
|
||
if (endX + textWidth + 1.5 * conf.sidePadding > w) {
|
||
return 'taskTextOutsideLeft taskTextOutside' + secNum + ' ' + taskType;
|
||
} else {
|
||
return 'taskTextOutsideRight taskTextOutside' + secNum + ' ' + taskType;
|
||
}
|
||
} else {
|
||
return 'taskText taskText' + secNum + ' ' + taskType;
|
||
}
|
||
});
|
||
}
|
||
|
||
function makeGrid(theSidePad, theTopPad, w, h) {
|
||
|
||
var pre = [['.%L', function (d) {
|
||
return d.getMilliseconds();
|
||
}], [':%S', function (d) {
|
||
return d.getSeconds();
|
||
}],
|
||
// Within a hour
|
||
['h1 %I:%M', function (d) {
|
||
return d.getMinutes();
|
||
}]];
|
||
var post = [['%Y', function () {
|
||
return true;
|
||
}]];
|
||
|
||
var mid = [
|
||
// Within a day
|
||
['%I:%M', function (d) {
|
||
return d.getHours();
|
||
}],
|
||
// Day within a week (not monday)
|
||
['%a %d', function (d) {
|
||
//return d.getDay() ==1;
|
||
return d.getDay() && d.getDate() != 1;
|
||
}],
|
||
// within a month
|
||
['%b %d', function (d) {
|
||
return d.getDate() != 1;
|
||
}],
|
||
// Month
|
||
['%B', function (d) {
|
||
return d.getMonth();
|
||
}]];
|
||
var formatter;
|
||
if (typeof conf.axisFormatter !== 'undefined') {
|
||
mid = [];
|
||
conf.axisFormatter.forEach(function (item) {
|
||
var n = [];
|
||
n[0] = item[0];
|
||
n[1] = item[1];
|
||
mid.push(n);
|
||
});
|
||
}
|
||
formatter = pre.concat(mid).concat(post);
|
||
|
||
var xAxis = d3.svg.axis().scale(timeScale).orient('bottom').tickSize(-h + theTopPad + conf.gridLineStartPadding, 0, 0).tickFormat(d3.time.format.multi(formatter));
|
||
|
||
if (daysInChart > 7 && daysInChart < 230) {
|
||
xAxis = xAxis.ticks(d3.time.monday.range);
|
||
}
|
||
|
||
svg.append('g').attr('class', 'grid').attr('transform', 'translate(' + theSidePad + ', ' + (h - 50) + ')').call(xAxis).selectAll('text').style('text-anchor', 'middle').attr('fill', '#000').attr('stroke', 'none').attr('font-size', 10).attr('dy', '1em');
|
||
}
|
||
|
||
function vertLabels(theGap, theTopPad) {
|
||
var numOccurances = [];
|
||
var prevGap = 0;
|
||
|
||
for (var i = 0; i < categories.length; i++) {
|
||
numOccurances[i] = [categories[i], getCount(categories[i], catsUnfiltered)];
|
||
}
|
||
|
||
svg.append('g') //without doing this, impossible to put grid lines behind text
|
||
.selectAll('text').data(numOccurances).enter().append('text').text(function (d) {
|
||
return d[0];
|
||
}).attr('x', 10).attr('y', function (d, i) {
|
||
if (i > 0) {
|
||
for (var j = 0; j < i; j++) {
|
||
prevGap += numOccurances[i - 1][1];
|
||
// log.debug(prevGap);
|
||
return d[1] * theGap / 2 + prevGap * theGap + theTopPad;
|
||
}
|
||
} else {
|
||
return d[1] * theGap / 2 + theTopPad;
|
||
}
|
||
}).attr('class', function (d) {
|
||
for (var i = 0; i < categories.length; i++) {
|
||
if (d[0] === categories[i]) {
|
||
return 'sectionTitle sectionTitle' + i % conf.numberSectionStyles;
|
||
}
|
||
}
|
||
return 'sectionTitle';
|
||
});
|
||
}
|
||
|
||
function drawToday(theSidePad, theTopPad, w, h) {
|
||
var todayG = svg.append('g').attr('class', 'today');
|
||
|
||
var today = new Date();
|
||
|
||
todayG.append('line').attr('x1', timeScale(today) + theSidePad).attr('x2', timeScale(today) + theSidePad).attr('y1', conf.titleTopMargin).attr('y2', h - conf.titleTopMargin).attr('class', 'today');
|
||
}
|
||
|
||
//from this stackexchange question: http://stackoverflow.com/questions/1890203/unique-for-arrays-in-javascript
|
||
function checkUnique(arr) {
|
||
var hash = {},
|
||
result = [];
|
||
for (var i = 0, l = arr.length; i < l; ++i) {
|
||
if (!hash.hasOwnProperty(arr[i])) {
|
||
//it works with objects! in FF, at least
|
||
hash[arr[i]] = true;
|
||
result.push(arr[i]);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
//from this stackexchange question: http://stackoverflow.com/questions/14227981/count-how-many-strings-in-an-array-have-duplicates-in-the-same-array
|
||
function getCounts(arr) {
|
||
var i = arr.length,
|
||
// var to loop over
|
||
obj = {}; // obj to store results
|
||
while (i) {
|
||
obj[arr[--i]] = (obj[arr[i]] || 0) + 1; // count occurrences
|
||
}
|
||
return obj;
|
||
}
|
||
|
||
// get specific from everything
|
||
function getCount(word, arr) {
|
||
return getCounts(arr)[word] || 0;
|
||
}
|
||
};
|
||
|
||
},{"../../d3":107,"./ganttDb":119,"./parser/gantt":121,"moment":105}],121:[function(require,module,exports){
|
||
(function (process){
|
||
/* parser generated by jison 0.4.15 */
|
||
/*
|
||
Returns a Parser object of the following structure:
|
||
|
||
Parser: {
|
||
yy: {}
|
||
}
|
||
|
||
Parser.prototype: {
|
||
yy: {},
|
||
trace: function(),
|
||
symbols_: {associative list: name ==> number},
|
||
terminals_: {associative list: number ==> name},
|
||
productions_: [...],
|
||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
|
||
table: [...],
|
||
defaultActions: {...},
|
||
parseError: function(str, hash),
|
||
parse: function(input),
|
||
|
||
lexer: {
|
||
EOF: 1,
|
||
parseError: function(str, hash),
|
||
setInput: function(input),
|
||
input: function(),
|
||
unput: function(str),
|
||
more: function(),
|
||
less: function(n),
|
||
pastInput: function(),
|
||
upcomingInput: function(),
|
||
showPosition: function(),
|
||
test_match: function(regex_match_array, rule_index),
|
||
next: function(),
|
||
lex: function(),
|
||
begin: function(condition),
|
||
popState: function(),
|
||
_currentRules: function(),
|
||
topState: function(),
|
||
pushState: function(condition),
|
||
|
||
options: {
|
||
ranges: boolean (optional: true ==> token location info will include a .range[] member)
|
||
flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
|
||
backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
|
||
},
|
||
|
||
performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
|
||
rules: [...],
|
||
conditions: {associative list: name ==> set},
|
||
}
|
||
}
|
||
|
||
|
||
token location info (@$, _$, etc.): {
|
||
first_line: n,
|
||
last_line: n,
|
||
first_column: n,
|
||
last_column: n,
|
||
range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
|
||
}
|
||
|
||
|
||
the parseError function receives a 'hash' object with these members for lexer and parser errors: {
|
||
text: (matched text)
|
||
token: (the produced terminal token, if any)
|
||
line: (yylineno)
|
||
}
|
||
while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
|
||
loc: (yylloc)
|
||
expected: (string describing the set of expected tokens)
|
||
recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
|
||
}
|
||
*/
|
||
"use strict";
|
||
|
||
var gantt = (function () {
|
||
var o = function o(k, v, _o, l) {
|
||
for (_o = _o || {}, l = k.length; l--; _o[k[l]] = v);return _o;
|
||
},
|
||
$V0 = [6, 8, 10, 11, 12, 13, 14],
|
||
$V1 = [1, 9],
|
||
$V2 = [1, 10],
|
||
$V3 = [1, 11],
|
||
$V4 = [1, 12];
|
||
var parser = { trace: function trace() {},
|
||
yy: {},
|
||
symbols_: { "error": 2, "start": 3, "gantt": 4, "document": 5, "EOF": 6, "line": 7, "SPACE": 8, "statement": 9, "NL": 10, "dateFormat": 11, "title": 12, "section": 13, "taskTxt": 14, "taskData": 15, "$accept": 0, "$end": 1 },
|
||
terminals_: { 2: "error", 4: "gantt", 6: "EOF", 8: "SPACE", 10: "NL", 11: "dateFormat", 12: "title", 13: "section", 14: "taskTxt", 15: "taskData" },
|
||
productions_: [0, [3, 3], [5, 0], [5, 2], [7, 2], [7, 1], [7, 1], [7, 1], [9, 1], [9, 1], [9, 1], [9, 2]],
|
||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, /* action[1] */$$, /* vstack */_$ /* lstack */) {
|
||
/* this == yyval */
|
||
|
||
var $0 = $$.length - 1;
|
||
switch (yystate) {
|
||
case 1:
|
||
return $$[$0 - 1];
|
||
break;
|
||
case 2:
|
||
this.$ = [];
|
||
break;
|
||
case 3:
|
||
$$[$0 - 1].push($$[$0]);this.$ = $$[$0 - 1];
|
||
break;
|
||
case 4:case 5:
|
||
this.$ = $$[$0];
|
||
break;
|
||
case 6:case 7:
|
||
this.$ = [];
|
||
break;
|
||
case 8:
|
||
yy.setDateFormat($$[$0].substr(11));this.$ = $$[$0].substr(11);
|
||
break;
|
||
case 9:
|
||
yy.setTitle($$[$0].substr(6));this.$ = $$[$0].substr(6);
|
||
break;
|
||
case 10:
|
||
yy.addSection($$[$0].substr(8));this.$ = $$[$0].substr(8);
|
||
break;
|
||
case 11:
|
||
yy.addTask($$[$0 - 1], $$[$0]);this.$ = 'task';
|
||
break;
|
||
}
|
||
},
|
||
table: [{ 3: 1, 4: [1, 2] }, { 1: [3] }, o($V0, [2, 2], { 5: 3 }), { 6: [1, 4], 7: 5, 8: [1, 6], 9: 7, 10: [1, 8], 11: $V1, 12: $V2, 13: $V3, 14: $V4 }, o($V0, [2, 7], { 1: [2, 1] }), o($V0, [2, 3]), { 9: 13, 11: $V1, 12: $V2, 13: $V3, 14: $V4 }, o($V0, [2, 5]), o($V0, [2, 6]), o($V0, [2, 8]), o($V0, [2, 9]), o($V0, [2, 10]), { 15: [1, 14] }, o($V0, [2, 4]), o($V0, [2, 11])],
|
||
defaultActions: {},
|
||
parseError: function parseError(str, hash) {
|
||
if (hash.recoverable) {
|
||
this.trace(str);
|
||
} else {
|
||
var _parseError = function _parseError(msg, hash) {
|
||
this.message = msg;
|
||
this.hash = hash;
|
||
};
|
||
|
||
_parseError.prototype = new Error();
|
||
|
||
throw new _parseError(str, hash);
|
||
}
|
||
},
|
||
parse: function parse(input) {
|
||
var self = this,
|
||
stack = [0],
|
||
tstack = [],
|
||
vstack = [null],
|
||
lstack = [],
|
||
table = this.table,
|
||
yytext = '',
|
||
yylineno = 0,
|
||
yyleng = 0,
|
||
recovering = 0,
|
||
TERROR = 2,
|
||
EOF = 1;
|
||
var args = lstack.slice.call(arguments, 1);
|
||
var lexer = Object.create(this.lexer);
|
||
var sharedState = { yy: {} };
|
||
for (var k in this.yy) {
|
||
if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
|
||
sharedState.yy[k] = this.yy[k];
|
||
}
|
||
}
|
||
lexer.setInput(input, sharedState.yy);
|
||
sharedState.yy.lexer = lexer;
|
||
sharedState.yy.parser = this;
|
||
if (typeof lexer.yylloc == 'undefined') {
|
||
lexer.yylloc = {};
|
||
}
|
||
var yyloc = lexer.yylloc;
|
||
lstack.push(yyloc);
|
||
var ranges = lexer.options && lexer.options.ranges;
|
||
if (typeof sharedState.yy.parseError === 'function') {
|
||
this.parseError = sharedState.yy.parseError;
|
||
} else {
|
||
this.parseError = Object.getPrototypeOf(this).parseError;
|
||
}
|
||
function popStack(n) {
|
||
stack.length = stack.length - 2 * n;
|
||
vstack.length = vstack.length - n;
|
||
lstack.length = lstack.length - n;
|
||
}
|
||
_token_stack: var lex = function lex() {
|
||
var token;
|
||
token = lexer.lex() || EOF;
|
||
if (typeof token !== 'number') {
|
||
token = self.symbols_[token] || token;
|
||
}
|
||
return token;
|
||
};
|
||
var symbol,
|
||
preErrorSymbol,
|
||
state,
|
||
action,
|
||
a,
|
||
r,
|
||
yyval = {},
|
||
p,
|
||
len,
|
||
newState,
|
||
expected;
|
||
while (true) {
|
||
state = stack[stack.length - 1];
|
||
if (this.defaultActions[state]) {
|
||
action = this.defaultActions[state];
|
||
} else {
|
||
if (symbol === null || typeof symbol == 'undefined') {
|
||
symbol = lex();
|
||
}
|
||
action = table[state] && table[state][symbol];
|
||
}
|
||
if (typeof action === 'undefined' || !action.length || !action[0]) {
|
||
var errStr = '';
|
||
expected = [];
|
||
for (p in table[state]) {
|
||
if (this.terminals_[p] && p > TERROR) {
|
||
expected.push('\'' + this.terminals_[p] + '\'');
|
||
}
|
||
}
|
||
if (lexer.showPosition) {
|
||
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
|
||
} else {
|
||
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
|
||
}
|
||
this.parseError(errStr, {
|
||
text: lexer.match,
|
||
token: this.terminals_[symbol] || symbol,
|
||
line: lexer.yylineno,
|
||
loc: yyloc,
|
||
expected: expected
|
||
});
|
||
}
|
||
if (action[0] instanceof Array && action.length > 1) {
|
||
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
|
||
}
|
||
switch (action[0]) {
|
||
case 1:
|
||
stack.push(symbol);
|
||
vstack.push(lexer.yytext);
|
||
lstack.push(lexer.yylloc);
|
||
stack.push(action[1]);
|
||
symbol = null;
|
||
if (!preErrorSymbol) {
|
||
yyleng = lexer.yyleng;
|
||
yytext = lexer.yytext;
|
||
yylineno = lexer.yylineno;
|
||
yyloc = lexer.yylloc;
|
||
if (recovering > 0) {
|
||
recovering--;
|
||
}
|
||
} else {
|
||
symbol = preErrorSymbol;
|
||
preErrorSymbol = null;
|
||
}
|
||
break;
|
||
case 2:
|
||
len = this.productions_[action[1]][1];
|
||
yyval.$ = vstack[vstack.length - len];
|
||
yyval._$ = {
|
||
first_line: lstack[lstack.length - (len || 1)].first_line,
|
||
last_line: lstack[lstack.length - 1].last_line,
|
||
first_column: lstack[lstack.length - (len || 1)].first_column,
|
||
last_column: lstack[lstack.length - 1].last_column
|
||
};
|
||
if (ranges) {
|
||
yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
|
||
}
|
||
r = this.performAction.apply(yyval, [yytext, yyleng, yylineno, sharedState.yy, action[1], vstack, lstack].concat(args));
|
||
if (typeof r !== 'undefined') {
|
||
return r;
|
||
}
|
||
if (len) {
|
||
stack = stack.slice(0, -1 * len * 2);
|
||
vstack = vstack.slice(0, -1 * len);
|
||
lstack = lstack.slice(0, -1 * len);
|
||
}
|
||
stack.push(this.productions_[action[1]][0]);
|
||
vstack.push(yyval.$);
|
||
lstack.push(yyval._$);
|
||
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
|
||
stack.push(newState);
|
||
break;
|
||
case 3:
|
||
return true;
|
||
}
|
||
}
|
||
return true;
|
||
} };
|
||
/* generated by jison-lex 0.3.4 */
|
||
var lexer = (function () {
|
||
var lexer = {
|
||
|
||
EOF: 1,
|
||
|
||
parseError: function parseError(str, hash) {
|
||
if (this.yy.parser) {
|
||
this.yy.parser.parseError(str, hash);
|
||
} else {
|
||
throw new Error(str);
|
||
}
|
||
},
|
||
|
||
// resets the lexer, sets new input
|
||
setInput: function setInput(input, yy) {
|
||
this.yy = yy || this.yy || {};
|
||
this._input = input;
|
||
this._more = this._backtrack = this.done = false;
|
||
this.yylineno = this.yyleng = 0;
|
||
this.yytext = this.matched = this.match = '';
|
||
this.conditionStack = ['INITIAL'];
|
||
this.yylloc = {
|
||
first_line: 1,
|
||
first_column: 0,
|
||
last_line: 1,
|
||
last_column: 0
|
||
};
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [0, 0];
|
||
}
|
||
this.offset = 0;
|
||
return this;
|
||
},
|
||
|
||
// consumes and returns one char from the input
|
||
input: function input() {
|
||
var ch = this._input[0];
|
||
this.yytext += ch;
|
||
this.yyleng++;
|
||
this.offset++;
|
||
this.match += ch;
|
||
this.matched += ch;
|
||
var lines = ch.match(/(?:\r\n?|\n).*/g);
|
||
if (lines) {
|
||
this.yylineno++;
|
||
this.yylloc.last_line++;
|
||
} else {
|
||
this.yylloc.last_column++;
|
||
}
|
||
if (this.options.ranges) {
|
||
this.yylloc.range[1]++;
|
||
}
|
||
|
||
this._input = this._input.slice(1);
|
||
return ch;
|
||
},
|
||
|
||
// unshifts one char (or a string) into the input
|
||
unput: function unput(ch) {
|
||
var len = ch.length;
|
||
var lines = ch.split(/(?:\r\n?|\n)/g);
|
||
|
||
this._input = ch + this._input;
|
||
this.yytext = this.yytext.substr(0, this.yytext.length - len);
|
||
//this.yyleng -= len;
|
||
this.offset -= len;
|
||
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
|
||
this.match = this.match.substr(0, this.match.length - 1);
|
||
this.matched = this.matched.substr(0, this.matched.length - 1);
|
||
|
||
if (lines.length - 1) {
|
||
this.yylineno -= lines.length - 1;
|
||
}
|
||
var r = this.yylloc.range;
|
||
|
||
this.yylloc = {
|
||
first_line: this.yylloc.first_line,
|
||
last_line: this.yylineno + 1,
|
||
first_column: this.yylloc.first_column,
|
||
last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
|
||
};
|
||
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
|
||
}
|
||
this.yyleng = this.yytext.length;
|
||
return this;
|
||
},
|
||
|
||
// When called from action, caches matched text and appends it on next action
|
||
more: function more() {
|
||
this._more = true;
|
||
return this;
|
||
},
|
||
|
||
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
|
||
reject: function reject() {
|
||
if (this.options.backtrack_lexer) {
|
||
this._backtrack = true;
|
||
} else {
|
||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
|
||
text: "",
|
||
token: null,
|
||
line: this.yylineno
|
||
});
|
||
}
|
||
return this;
|
||
},
|
||
|
||
// retain first n characters of the match
|
||
less: function less(n) {
|
||
this.unput(this.match.slice(n));
|
||
},
|
||
|
||
// displays already matched input, i.e. for error messages
|
||
pastInput: function pastInput() {
|
||
var past = this.matched.substr(0, this.matched.length - this.match.length);
|
||
return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
|
||
},
|
||
|
||
// displays upcoming input, i.e. for error messages
|
||
upcomingInput: function upcomingInput() {
|
||
var next = this.match;
|
||
if (next.length < 20) {
|
||
next += this._input.substr(0, 20 - next.length);
|
||
}
|
||
return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
|
||
},
|
||
|
||
// displays the character position where the lexing error occurred, i.e. for error messages
|
||
showPosition: function showPosition() {
|
||
var pre = this.pastInput();
|
||
var c = new Array(pre.length + 1).join("-");
|
||
return pre + this.upcomingInput() + "\n" + c + "^";
|
||
},
|
||
|
||
// test the lexed token: return FALSE when not a match, otherwise return token
|
||
test_match: function test_match(match, indexed_rule) {
|
||
var token, lines, backup;
|
||
|
||
if (this.options.backtrack_lexer) {
|
||
// save context
|
||
backup = {
|
||
yylineno: this.yylineno,
|
||
yylloc: {
|
||
first_line: this.yylloc.first_line,
|
||
last_line: this.last_line,
|
||
first_column: this.yylloc.first_column,
|
||
last_column: this.yylloc.last_column
|
||
},
|
||
yytext: this.yytext,
|
||
match: this.match,
|
||
matches: this.matches,
|
||
matched: this.matched,
|
||
yyleng: this.yyleng,
|
||
offset: this.offset,
|
||
_more: this._more,
|
||
_input: this._input,
|
||
yy: this.yy,
|
||
conditionStack: this.conditionStack.slice(0),
|
||
done: this.done
|
||
};
|
||
if (this.options.ranges) {
|
||
backup.yylloc.range = this.yylloc.range.slice(0);
|
||
}
|
||
}
|
||
|
||
lines = match[0].match(/(?:\r\n?|\n).*/g);
|
||
if (lines) {
|
||
this.yylineno += lines.length;
|
||
}
|
||
this.yylloc = {
|
||
first_line: this.yylloc.last_line,
|
||
last_line: this.yylineno + 1,
|
||
first_column: this.yylloc.last_column,
|
||
last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length
|
||
};
|
||
this.yytext += match[0];
|
||
this.match += match[0];
|
||
this.matches = match;
|
||
this.yyleng = this.yytext.length;
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [this.offset, this.offset += this.yyleng];
|
||
}
|
||
this._more = false;
|
||
this._backtrack = false;
|
||
this._input = this._input.slice(match[0].length);
|
||
this.matched += match[0];
|
||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
|
||
if (this.done && this._input) {
|
||
this.done = false;
|
||
}
|
||
if (token) {
|
||
return token;
|
||
} else if (this._backtrack) {
|
||
// recover context
|
||
for (var k in backup) {
|
||
this[k] = backup[k];
|
||
}
|
||
return false; // rule action called reject() implying the next rule should be tested instead.
|
||
}
|
||
return false;
|
||
},
|
||
|
||
// return next match in input
|
||
next: function next() {
|
||
if (this.done) {
|
||
return this.EOF;
|
||
}
|
||
if (!this._input) {
|
||
this.done = true;
|
||
}
|
||
|
||
var token, match, tempMatch, index;
|
||
if (!this._more) {
|
||
this.yytext = '';
|
||
this.match = '';
|
||
}
|
||
var rules = this._currentRules();
|
||
for (var i = 0; i < rules.length; i++) {
|
||
tempMatch = this._input.match(this.rules[rules[i]]);
|
||
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
|
||
match = tempMatch;
|
||
index = i;
|
||
if (this.options.backtrack_lexer) {
|
||
token = this.test_match(tempMatch, rules[i]);
|
||
if (token !== false) {
|
||
return token;
|
||
} else if (this._backtrack) {
|
||
match = false;
|
||
continue; // rule action called reject() implying a rule MISmatch.
|
||
} else {
|
||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||
return false;
|
||
}
|
||
} else if (!this.options.flex) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (match) {
|
||
token = this.test_match(match, rules[index]);
|
||
if (token !== false) {
|
||
return token;
|
||
}
|
||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||
return false;
|
||
}
|
||
if (this._input === "") {
|
||
return this.EOF;
|
||
} else {
|
||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
|
||
text: "",
|
||
token: null,
|
||
line: this.yylineno
|
||
});
|
||
}
|
||
},
|
||
|
||
// return next match that has a token
|
||
lex: function lex() {
|
||
var r = this.next();
|
||
if (r) {
|
||
return r;
|
||
} else {
|
||
return this.lex();
|
||
}
|
||
},
|
||
|
||
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
|
||
begin: function begin(condition) {
|
||
this.conditionStack.push(condition);
|
||
},
|
||
|
||
// pop the previously active lexer condition state off the condition stack
|
||
popState: function popState() {
|
||
var n = this.conditionStack.length - 1;
|
||
if (n > 0) {
|
||
return this.conditionStack.pop();
|
||
} else {
|
||
return this.conditionStack[0];
|
||
}
|
||
},
|
||
|
||
// produce the lexer rule set which is active for the currently active lexer condition state
|
||
_currentRules: function _currentRules() {
|
||
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
|
||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
|
||
} else {
|
||
return this.conditions["INITIAL"].rules;
|
||
}
|
||
},
|
||
|
||
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
|
||
topState: function topState(n) {
|
||
n = this.conditionStack.length - 1 - Math.abs(n || 0);
|
||
if (n >= 0) {
|
||
return this.conditionStack[n];
|
||
} else {
|
||
return "INITIAL";
|
||
}
|
||
},
|
||
|
||
// alias for begin(condition)
|
||
pushState: function pushState(condition) {
|
||
this.begin(condition);
|
||
},
|
||
|
||
// return the number of states currently on the stack
|
||
stateStackSize: function stateStackSize() {
|
||
return this.conditionStack.length;
|
||
},
|
||
options: { "case-insensitive": true },
|
||
performAction: function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
|
||
// Pre-lexer code can go here
|
||
|
||
var YYSTATE = YY_START;
|
||
switch ($avoiding_name_collisions) {
|
||
case 0:
|
||
return 10;
|
||
break;
|
||
case 1:
|
||
/* skip whitespace */
|
||
break;
|
||
case 2:
|
||
/* skip comments */
|
||
break;
|
||
case 3:
|
||
/* skip comments */
|
||
break;
|
||
case 4:
|
||
return 4;
|
||
break;
|
||
case 5:
|
||
return 11;
|
||
break;
|
||
case 6:
|
||
return 'date';
|
||
break;
|
||
case 7:
|
||
return 12;
|
||
break;
|
||
case 8:
|
||
return 13;
|
||
break;
|
||
case 9:
|
||
return 14;
|
||
break;
|
||
case 10:
|
||
return 15;
|
||
break;
|
||
case 11:
|
||
return ':';
|
||
break;
|
||
case 12:
|
||
return 6;
|
||
break;
|
||
case 13:
|
||
return 'INVALID';
|
||
break;
|
||
}
|
||
},
|
||
rules: [/^(?:[\n]+)/i, /^(?:\s+)/i, /^(?:#[^\n]*)/i, /^(?:%[^\n]*)/i, /^(?:gantt\b)/i, /^(?:dateFormat\s[^#\n;]+)/i, /^(?:\d\d\d\d-\d\d-\d\d\b)/i, /^(?:title\s[^#\n;]+)/i, /^(?:section\s[^#:\n;]+)/i, /^(?:[^#:\n;]+)/i, /^(?::[^#\n;]+)/i, /^(?::)/i, /^(?:$)/i, /^(?:.)/i],
|
||
conditions: { "INITIAL": { "rules": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], "inclusive": true } }
|
||
};
|
||
return lexer;
|
||
})();
|
||
parser.lexer = lexer;
|
||
function Parser() {
|
||
this.yy = {};
|
||
}
|
||
Parser.prototype = parser;parser.Parser = Parser;
|
||
return new Parser();
|
||
})();
|
||
|
||
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
|
||
exports.parser = gantt;
|
||
exports.Parser = gantt.Parser;
|
||
exports.parse = function () {
|
||
return gantt.parse.apply(gantt, arguments);
|
||
};
|
||
exports.main = function commonjsMain(args) {
|
||
if (!args[1]) {
|
||
console.log('Usage: ' + args[0] + ' FILE');
|
||
process.exit(1);
|
||
}
|
||
var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
|
||
return exports.parser.parse(source);
|
||
};
|
||
if (typeof module !== 'undefined' && require.main === module) {
|
||
exports.main(process.argv.slice(1));
|
||
}
|
||
}
|
||
|
||
}).call(this,require('_process'))
|
||
},{"_process":3,"fs":1,"path":2}],122:[function(require,module,exports){
|
||
(function (process){
|
||
/* parser generated by jison 0.4.15 */
|
||
/*
|
||
Returns a Parser object of the following structure:
|
||
|
||
Parser: {
|
||
yy: {}
|
||
}
|
||
|
||
Parser.prototype: {
|
||
yy: {},
|
||
trace: function(),
|
||
symbols_: {associative list: name ==> number},
|
||
terminals_: {associative list: number ==> name},
|
||
productions_: [...],
|
||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
|
||
table: [...],
|
||
defaultActions: {...},
|
||
parseError: function(str, hash),
|
||
parse: function(input),
|
||
|
||
lexer: {
|
||
EOF: 1,
|
||
parseError: function(str, hash),
|
||
setInput: function(input),
|
||
input: function(),
|
||
unput: function(str),
|
||
more: function(),
|
||
less: function(n),
|
||
pastInput: function(),
|
||
upcomingInput: function(),
|
||
showPosition: function(),
|
||
test_match: function(regex_match_array, rule_index),
|
||
next: function(),
|
||
lex: function(),
|
||
begin: function(condition),
|
||
popState: function(),
|
||
_currentRules: function(),
|
||
topState: function(),
|
||
pushState: function(condition),
|
||
|
||
options: {
|
||
ranges: boolean (optional: true ==> token location info will include a .range[] member)
|
||
flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
|
||
backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
|
||
},
|
||
|
||
performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
|
||
rules: [...],
|
||
conditions: {associative list: name ==> set},
|
||
}
|
||
}
|
||
|
||
|
||
token location info (@$, _$, etc.): {
|
||
first_line: n,
|
||
last_line: n,
|
||
first_column: n,
|
||
last_column: n,
|
||
range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
|
||
}
|
||
|
||
|
||
the parseError function receives a 'hash' object with these members for lexer and parser errors: {
|
||
text: (matched text)
|
||
token: (the produced terminal token, if any)
|
||
line: (yylineno)
|
||
}
|
||
while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
|
||
loc: (yylloc)
|
||
expected: (string describing the set of expected tokens)
|
||
recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
|
||
}
|
||
*/
|
||
"use strict";
|
||
|
||
var sequenceDiagram = (function () {
|
||
var o = function o(k, v, _o, l) {
|
||
for (_o = _o || {}, l = k.length; l--; _o[k[l]] = v);return _o;
|
||
},
|
||
$V0 = [2, 2],
|
||
$V1 = [1, 5],
|
||
$V2 = [1, 7],
|
||
$V3 = [1, 8],
|
||
$V4 = [1, 11],
|
||
$V5 = [1, 12],
|
||
$V6 = [1, 13],
|
||
$V7 = [1, 14],
|
||
$V8 = [1, 16],
|
||
$V9 = [1, 17],
|
||
$Va = [1, 7, 9, 10, 16, 18, 19, 20, 21, 22, 23, 33],
|
||
$Vb = [7, 9, 10, 16, 18, 19, 20, 21, 23, 33],
|
||
$Vc = [1, 53];
|
||
var parser = { trace: function trace() {},
|
||
yy: {},
|
||
symbols_: { "error": 2, "start": 3, "SD": 4, "document": 5, "line": 6, "SPACE": 7, "statement": 8, "NL": 9, "participant": 10, "actor": 11, "AS": 12, "restOfLine": 13, "signal": 14, "note_statement": 15, "title": 16, "text": 17, "loop": 18, "end": 19, "opt": 20, "alt": 21, "else": 22, "note": 23, "placement": 24, "text2": 25, "over": 26, "actor_pair": 27, "spaceList": 28, ",": 29, "left_of": 30, "right_of": 31, "signaltype": 32, "ACTOR": 33, "SOLID_OPEN_ARROW": 34, "DOTTED_OPEN_ARROW": 35, "SOLID_ARROW": 36, "DOTTED_ARROW": 37, "SOLID_CROSS": 38, "DOTTED_CROSS": 39, "TXT": 40, "$accept": 0, "$end": 1 },
|
||
terminals_: { 2: "error", 4: "SD", 7: "SPACE", 9: "NL", 10: "participant", 12: "AS", 13: "restOfLine", 16: "title", 17: "text", 18: "loop", 19: "end", 20: "opt", 21: "alt", 22: "else", 23: "note", 26: "over", 29: ",", 30: "left_of", 31: "right_of", 33: "ACTOR", 34: "SOLID_OPEN_ARROW", 35: "DOTTED_OPEN_ARROW", 36: "SOLID_ARROW", 37: "DOTTED_ARROW", 38: "SOLID_CROSS", 39: "DOTTED_CROSS", 40: "TXT" },
|
||
productions_: [0, [3, 2], [5, 0], [5, 2], [6, 2], [6, 1], [6, 1], [8, 5], [8, 3], [8, 2], [8, 2], [8, 4], [8, 4], [8, 4], [8, 7], [15, 4], [15, 4], [28, 2], [28, 1], [27, 3], [27, 1], [24, 1], [24, 1], [14, 4], [11, 1], [32, 1], [32, 1], [32, 1], [32, 1], [32, 1], [32, 1], [25, 1]],
|
||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, /* action[1] */$$, /* vstack */_$ /* lstack */) {
|
||
/* this == yyval */
|
||
|
||
var $0 = $$.length - 1;
|
||
switch (yystate) {
|
||
case 1:
|
||
yy.apply($$[$0]);return $$[$0];
|
||
break;
|
||
case 2:
|
||
this.$ = [];
|
||
break;
|
||
case 3:
|
||
$$[$0 - 1].push($$[$0]);this.$ = $$[$0 - 1];
|
||
break;
|
||
case 4:case 5:
|
||
this.$ = $$[$0];
|
||
break;
|
||
case 6:
|
||
this.$ = [];
|
||
break;
|
||
case 7:
|
||
$$[$0 - 3].description = $$[$0 - 1];this.$ = $$[$0 - 3];
|
||
break;
|
||
case 8:
|
||
this.$ = $$[$0 - 1];
|
||
break;
|
||
case 12:
|
||
|
||
$$[$0 - 1].unshift({ type: 'loopStart', loopText: $$[$0 - 2], signalType: yy.LINETYPE.LOOP_START });
|
||
$$[$0 - 1].push({ type: 'loopEnd', loopText: $$[$0 - 2], signalType: yy.LINETYPE.LOOP_END });
|
||
this.$ = $$[$0 - 1];
|
||
break;
|
||
case 13:
|
||
|
||
$$[$0 - 1].unshift({ type: 'optStart', optText: $$[$0 - 2], signalType: yy.LINETYPE.OPT_START });
|
||
$$[$0 - 1].push({ type: 'optEnd', optText: $$[$0 - 2], signalType: yy.LINETYPE.OPT_END });
|
||
this.$ = $$[$0 - 1];
|
||
break;
|
||
case 14:
|
||
|
||
// Alt start
|
||
$$[$0 - 4].unshift({ type: 'altStart', altText: $$[$0 - 5], signalType: yy.LINETYPE.ALT_START });
|
||
// Content in alt is already in $$[$0-4]
|
||
// Else
|
||
$$[$0 - 4].push({ type: 'else', altText: $$[$0 - 2], signalType: yy.LINETYPE.ALT_ELSE });
|
||
// Content in other alt
|
||
$$[$0 - 4] = $$[$0 - 4].concat($$[$0 - 1]);
|
||
// End
|
||
$$[$0 - 4].push({ type: 'altEnd', signalType: yy.LINETYPE.ALT_END });
|
||
|
||
this.$ = $$[$0 - 4];
|
||
break;
|
||
case 15:
|
||
|
||
this.$ = [$$[$0 - 1], { type: 'addNote', placement: $$[$0 - 2], actor: $$[$0 - 1].actor, text: $$[$0] }];
|
||
break;
|
||
case 16:
|
||
|
||
// Coerce actor_pair into a [to, from, ...] array
|
||
$$[$0 - 2] = [].concat($$[$0 - 1], $$[$0 - 1]).slice(0, 2);
|
||
$$[$0 - 2][0] = $$[$0 - 2][0].actor;
|
||
$$[$0 - 2][1] = $$[$0 - 2][1].actor;
|
||
this.$ = [$$[$0 - 1], { type: 'addNote', placement: yy.PLACEMENT.OVER, actor: $$[$0 - 2].slice(0, 2), text: $$[$0] }];
|
||
break;
|
||
case 19:
|
||
this.$ = [$$[$0 - 2], $$[$0]];
|
||
break;
|
||
case 20:
|
||
this.$ = $$[$0];
|
||
break;
|
||
case 21:
|
||
this.$ = yy.PLACEMENT.LEFTOF;
|
||
break;
|
||
case 22:
|
||
this.$ = yy.PLACEMENT.RIGHTOF;
|
||
break;
|
||
case 23:
|
||
this.$ = [$$[$0 - 3], $$[$0 - 1], { type: 'addMessage', from: $$[$0 - 3].actor, to: $$[$0 - 1].actor, signalType: $$[$0 - 2], msg: $$[$0] }];
|
||
break;
|
||
case 24:
|
||
this.$ = { type: 'addActor', actor: $$[$0] };
|
||
break;
|
||
case 25:
|
||
this.$ = yy.LINETYPE.SOLID_OPEN;
|
||
break;
|
||
case 26:
|
||
this.$ = yy.LINETYPE.DOTTED_OPEN;
|
||
break;
|
||
case 27:
|
||
this.$ = yy.LINETYPE.SOLID;
|
||
break;
|
||
case 28:
|
||
this.$ = yy.LINETYPE.DOTTED;
|
||
break;
|
||
case 29:
|
||
this.$ = yy.LINETYPE.SOLID_CROSS;
|
||
break;
|
||
case 30:
|
||
this.$ = yy.LINETYPE.DOTTED_CROSS;
|
||
break;
|
||
case 31:
|
||
this.$ = $$[$0].substring(1).trim().replace(/\\n/gm, "\n");
|
||
break;
|
||
}
|
||
},
|
||
table: [{ 3: 1, 4: [1, 2] }, { 1: [3] }, o([1, 7, 9, 10, 16, 18, 20, 21, 23, 33], $V0, { 5: 3 }), { 1: [2, 1], 6: 4, 7: $V1, 8: 6, 9: $V2, 10: $V3, 11: 15, 14: 9, 15: 10, 16: $V4, 18: $V5, 20: $V6, 21: $V7, 23: $V8, 33: $V9 }, o($Va, [2, 3]), { 8: 18, 10: $V3, 11: 15, 14: 9, 15: 10, 16: $V4, 18: $V5, 20: $V6, 21: $V7, 23: $V8, 33: $V9 }, o($Va, [2, 5]), o($Va, [2, 6]), { 11: 19, 33: $V9 }, { 9: [1, 20] }, { 9: [1, 21] }, { 7: [1, 22] }, { 13: [1, 23] }, { 13: [1, 24] }, { 13: [1, 25] }, { 32: 26, 34: [1, 27], 35: [1, 28], 36: [1, 29], 37: [1, 30], 38: [1, 31], 39: [1, 32] }, { 24: 33, 26: [1, 34], 30: [1, 35], 31: [1, 36] }, o([9, 12, 29, 34, 35, 36, 37, 38, 39, 40], [2, 24]), o($Va, [2, 4]), { 9: [1, 38], 12: [1, 37] }, o($Va, [2, 9]), o($Va, [2, 10]), { 17: [1, 39] }, o($Vb, $V0, { 5: 40 }), o($Vb, $V0, { 5: 41 }), o([7, 9, 10, 16, 18, 20, 21, 22, 23, 33], $V0, { 5: 42 }), { 11: 43, 33: $V9 }, { 33: [2, 25] }, { 33: [2, 26] }, { 33: [2, 27] }, { 33: [2, 28] }, { 33: [2, 29] }, { 33: [2, 30] }, { 11: 44, 33: $V9 }, { 11: 46, 27: 45, 33: $V9 }, { 33: [2, 21] }, { 33: [2, 22] }, { 13: [1, 47] }, o($Va, [2, 8]), { 9: [1, 48] }, { 6: 4, 7: $V1, 8: 6, 9: $V2, 10: $V3, 11: 15, 14: 9, 15: 10, 16: $V4, 18: $V5, 19: [1, 49], 20: $V6, 21: $V7, 23: $V8, 33: $V9 }, { 6: 4, 7: $V1, 8: 6, 9: $V2, 10: $V3, 11: 15, 14: 9, 15: 10, 16: $V4, 18: $V5, 19: [1, 50], 20: $V6, 21: $V7, 23: $V8, 33: $V9 }, { 6: 4, 7: $V1, 8: 6, 9: $V2, 10: $V3, 11: 15, 14: 9, 15: 10, 16: $V4, 18: $V5, 20: $V6, 21: $V7, 22: [1, 51], 23: $V8, 33: $V9 }, { 25: 52, 40: $Vc }, { 25: 54, 40: $Vc }, { 25: 55, 40: $Vc }, { 29: [1, 56], 40: [2, 20] }, { 9: [1, 57] }, o($Va, [2, 11]), o($Va, [2, 12]), o($Va, [2, 13]), { 13: [1, 58] }, { 9: [2, 23] }, { 9: [2, 31] }, { 9: [2, 15] }, { 9: [2, 16] }, { 11: 59, 33: $V9 }, o($Va, [2, 7]), o($Vb, $V0, { 5: 60 }), { 40: [2, 19] }, { 6: 4, 7: $V1, 8: 6, 9: $V2, 10: $V3, 11: 15, 14: 9, 15: 10, 16: $V4, 18: $V5, 19: [1, 61], 20: $V6, 21: $V7, 23: $V8, 33: $V9 }, o($Va, [2, 14])],
|
||
defaultActions: { 27: [2, 25], 28: [2, 26], 29: [2, 27], 30: [2, 28], 31: [2, 29], 32: [2, 30], 35: [2, 21], 36: [2, 22], 52: [2, 23], 53: [2, 31], 54: [2, 15], 55: [2, 16], 59: [2, 19] },
|
||
parseError: function parseError(str, hash) {
|
||
if (hash.recoverable) {
|
||
this.trace(str);
|
||
} else {
|
||
var _parseError = function _parseError(msg, hash) {
|
||
this.message = msg;
|
||
this.hash = hash;
|
||
};
|
||
|
||
_parseError.prototype = new Error();
|
||
|
||
throw new _parseError(str, hash);
|
||
}
|
||
},
|
||
parse: function parse(input) {
|
||
var self = this,
|
||
stack = [0],
|
||
tstack = [],
|
||
vstack = [null],
|
||
lstack = [],
|
||
table = this.table,
|
||
yytext = '',
|
||
yylineno = 0,
|
||
yyleng = 0,
|
||
recovering = 0,
|
||
TERROR = 2,
|
||
EOF = 1;
|
||
var args = lstack.slice.call(arguments, 1);
|
||
var lexer = Object.create(this.lexer);
|
||
var sharedState = { yy: {} };
|
||
for (var k in this.yy) {
|
||
if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
|
||
sharedState.yy[k] = this.yy[k];
|
||
}
|
||
}
|
||
lexer.setInput(input, sharedState.yy);
|
||
sharedState.yy.lexer = lexer;
|
||
sharedState.yy.parser = this;
|
||
if (typeof lexer.yylloc == 'undefined') {
|
||
lexer.yylloc = {};
|
||
}
|
||
var yyloc = lexer.yylloc;
|
||
lstack.push(yyloc);
|
||
var ranges = lexer.options && lexer.options.ranges;
|
||
if (typeof sharedState.yy.parseError === 'function') {
|
||
this.parseError = sharedState.yy.parseError;
|
||
} else {
|
||
this.parseError = Object.getPrototypeOf(this).parseError;
|
||
}
|
||
function popStack(n) {
|
||
stack.length = stack.length - 2 * n;
|
||
vstack.length = vstack.length - n;
|
||
lstack.length = lstack.length - n;
|
||
}
|
||
_token_stack: var lex = function lex() {
|
||
var token;
|
||
token = lexer.lex() || EOF;
|
||
if (typeof token !== 'number') {
|
||
token = self.symbols_[token] || token;
|
||
}
|
||
return token;
|
||
};
|
||
var symbol,
|
||
preErrorSymbol,
|
||
state,
|
||
action,
|
||
a,
|
||
r,
|
||
yyval = {},
|
||
p,
|
||
len,
|
||
newState,
|
||
expected;
|
||
while (true) {
|
||
state = stack[stack.length - 1];
|
||
if (this.defaultActions[state]) {
|
||
action = this.defaultActions[state];
|
||
} else {
|
||
if (symbol === null || typeof symbol == 'undefined') {
|
||
symbol = lex();
|
||
}
|
||
action = table[state] && table[state][symbol];
|
||
}
|
||
if (typeof action === 'undefined' || !action.length || !action[0]) {
|
||
var errStr = '';
|
||
expected = [];
|
||
for (p in table[state]) {
|
||
if (this.terminals_[p] && p > TERROR) {
|
||
expected.push('\'' + this.terminals_[p] + '\'');
|
||
}
|
||
}
|
||
if (lexer.showPosition) {
|
||
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
|
||
} else {
|
||
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
|
||
}
|
||
this.parseError(errStr, {
|
||
text: lexer.match,
|
||
token: this.terminals_[symbol] || symbol,
|
||
line: lexer.yylineno,
|
||
loc: yyloc,
|
||
expected: expected
|
||
});
|
||
}
|
||
if (action[0] instanceof Array && action.length > 1) {
|
||
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
|
||
}
|
||
switch (action[0]) {
|
||
case 1:
|
||
stack.push(symbol);
|
||
vstack.push(lexer.yytext);
|
||
lstack.push(lexer.yylloc);
|
||
stack.push(action[1]);
|
||
symbol = null;
|
||
if (!preErrorSymbol) {
|
||
yyleng = lexer.yyleng;
|
||
yytext = lexer.yytext;
|
||
yylineno = lexer.yylineno;
|
||
yyloc = lexer.yylloc;
|
||
if (recovering > 0) {
|
||
recovering--;
|
||
}
|
||
} else {
|
||
symbol = preErrorSymbol;
|
||
preErrorSymbol = null;
|
||
}
|
||
break;
|
||
case 2:
|
||
len = this.productions_[action[1]][1];
|
||
yyval.$ = vstack[vstack.length - len];
|
||
yyval._$ = {
|
||
first_line: lstack[lstack.length - (len || 1)].first_line,
|
||
last_line: lstack[lstack.length - 1].last_line,
|
||
first_column: lstack[lstack.length - (len || 1)].first_column,
|
||
last_column: lstack[lstack.length - 1].last_column
|
||
};
|
||
if (ranges) {
|
||
yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
|
||
}
|
||
r = this.performAction.apply(yyval, [yytext, yyleng, yylineno, sharedState.yy, action[1], vstack, lstack].concat(args));
|
||
if (typeof r !== 'undefined') {
|
||
return r;
|
||
}
|
||
if (len) {
|
||
stack = stack.slice(0, -1 * len * 2);
|
||
vstack = vstack.slice(0, -1 * len);
|
||
lstack = lstack.slice(0, -1 * len);
|
||
}
|
||
stack.push(this.productions_[action[1]][0]);
|
||
vstack.push(yyval.$);
|
||
lstack.push(yyval._$);
|
||
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
|
||
stack.push(newState);
|
||
break;
|
||
case 3:
|
||
return true;
|
||
}
|
||
}
|
||
return true;
|
||
} };
|
||
|
||
/* generated by jison-lex 0.3.4 */
|
||
var lexer = (function () {
|
||
var lexer = {
|
||
|
||
EOF: 1,
|
||
|
||
parseError: function parseError(str, hash) {
|
||
if (this.yy.parser) {
|
||
this.yy.parser.parseError(str, hash);
|
||
} else {
|
||
throw new Error(str);
|
||
}
|
||
},
|
||
|
||
// resets the lexer, sets new input
|
||
setInput: function setInput(input, yy) {
|
||
this.yy = yy || this.yy || {};
|
||
this._input = input;
|
||
this._more = this._backtrack = this.done = false;
|
||
this.yylineno = this.yyleng = 0;
|
||
this.yytext = this.matched = this.match = '';
|
||
this.conditionStack = ['INITIAL'];
|
||
this.yylloc = {
|
||
first_line: 1,
|
||
first_column: 0,
|
||
last_line: 1,
|
||
last_column: 0
|
||
};
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [0, 0];
|
||
}
|
||
this.offset = 0;
|
||
return this;
|
||
},
|
||
|
||
// consumes and returns one char from the input
|
||
input: function input() {
|
||
var ch = this._input[0];
|
||
this.yytext += ch;
|
||
this.yyleng++;
|
||
this.offset++;
|
||
this.match += ch;
|
||
this.matched += ch;
|
||
var lines = ch.match(/(?:\r\n?|\n).*/g);
|
||
if (lines) {
|
||
this.yylineno++;
|
||
this.yylloc.last_line++;
|
||
} else {
|
||
this.yylloc.last_column++;
|
||
}
|
||
if (this.options.ranges) {
|
||
this.yylloc.range[1]++;
|
||
}
|
||
|
||
this._input = this._input.slice(1);
|
||
return ch;
|
||
},
|
||
|
||
// unshifts one char (or a string) into the input
|
||
unput: function unput(ch) {
|
||
var len = ch.length;
|
||
var lines = ch.split(/(?:\r\n?|\n)/g);
|
||
|
||
this._input = ch + this._input;
|
||
this.yytext = this.yytext.substr(0, this.yytext.length - len);
|
||
//this.yyleng -= len;
|
||
this.offset -= len;
|
||
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
|
||
this.match = this.match.substr(0, this.match.length - 1);
|
||
this.matched = this.matched.substr(0, this.matched.length - 1);
|
||
|
||
if (lines.length - 1) {
|
||
this.yylineno -= lines.length - 1;
|
||
}
|
||
var r = this.yylloc.range;
|
||
|
||
this.yylloc = {
|
||
first_line: this.yylloc.first_line,
|
||
last_line: this.yylineno + 1,
|
||
first_column: this.yylloc.first_column,
|
||
last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
|
||
};
|
||
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
|
||
}
|
||
this.yyleng = this.yytext.length;
|
||
return this;
|
||
},
|
||
|
||
// When called from action, caches matched text and appends it on next action
|
||
more: function more() {
|
||
this._more = true;
|
||
return this;
|
||
},
|
||
|
||
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
|
||
reject: function reject() {
|
||
if (this.options.backtrack_lexer) {
|
||
this._backtrack = true;
|
||
} else {
|
||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
|
||
text: "",
|
||
token: null,
|
||
line: this.yylineno
|
||
});
|
||
}
|
||
return this;
|
||
},
|
||
|
||
// retain first n characters of the match
|
||
less: function less(n) {
|
||
this.unput(this.match.slice(n));
|
||
},
|
||
|
||
// displays already matched input, i.e. for error messages
|
||
pastInput: function pastInput() {
|
||
var past = this.matched.substr(0, this.matched.length - this.match.length);
|
||
return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
|
||
},
|
||
|
||
// displays upcoming input, i.e. for error messages
|
||
upcomingInput: function upcomingInput() {
|
||
var next = this.match;
|
||
if (next.length < 20) {
|
||
next += this._input.substr(0, 20 - next.length);
|
||
}
|
||
return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
|
||
},
|
||
|
||
// displays the character position where the lexing error occurred, i.e. for error messages
|
||
showPosition: function showPosition() {
|
||
var pre = this.pastInput();
|
||
var c = new Array(pre.length + 1).join("-");
|
||
return pre + this.upcomingInput() + "\n" + c + "^";
|
||
},
|
||
|
||
// test the lexed token: return FALSE when not a match, otherwise return token
|
||
test_match: function test_match(match, indexed_rule) {
|
||
var token, lines, backup;
|
||
|
||
if (this.options.backtrack_lexer) {
|
||
// save context
|
||
backup = {
|
||
yylineno: this.yylineno,
|
||
yylloc: {
|
||
first_line: this.yylloc.first_line,
|
||
last_line: this.last_line,
|
||
first_column: this.yylloc.first_column,
|
||
last_column: this.yylloc.last_column
|
||
},
|
||
yytext: this.yytext,
|
||
match: this.match,
|
||
matches: this.matches,
|
||
matched: this.matched,
|
||
yyleng: this.yyleng,
|
||
offset: this.offset,
|
||
_more: this._more,
|
||
_input: this._input,
|
||
yy: this.yy,
|
||
conditionStack: this.conditionStack.slice(0),
|
||
done: this.done
|
||
};
|
||
if (this.options.ranges) {
|
||
backup.yylloc.range = this.yylloc.range.slice(0);
|
||
}
|
||
}
|
||
|
||
lines = match[0].match(/(?:\r\n?|\n).*/g);
|
||
if (lines) {
|
||
this.yylineno += lines.length;
|
||
}
|
||
this.yylloc = {
|
||
first_line: this.yylloc.last_line,
|
||
last_line: this.yylineno + 1,
|
||
first_column: this.yylloc.last_column,
|
||
last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length
|
||
};
|
||
this.yytext += match[0];
|
||
this.match += match[0];
|
||
this.matches = match;
|
||
this.yyleng = this.yytext.length;
|
||
if (this.options.ranges) {
|
||
this.yylloc.range = [this.offset, this.offset += this.yyleng];
|
||
}
|
||
this._more = false;
|
||
this._backtrack = false;
|
||
this._input = this._input.slice(match[0].length);
|
||
this.matched += match[0];
|
||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
|
||
if (this.done && this._input) {
|
||
this.done = false;
|
||
}
|
||
if (token) {
|
||
return token;
|
||
} else if (this._backtrack) {
|
||
// recover context
|
||
for (var k in backup) {
|
||
this[k] = backup[k];
|
||
}
|
||
return false; // rule action called reject() implying the next rule should be tested instead.
|
||
}
|
||
return false;
|
||
},
|
||
|
||
// return next match in input
|
||
next: function next() {
|
||
if (this.done) {
|
||
return this.EOF;
|
||
}
|
||
if (!this._input) {
|
||
this.done = true;
|
||
}
|
||
|
||
var token, match, tempMatch, index;
|
||
if (!this._more) {
|
||
this.yytext = '';
|
||
this.match = '';
|
||
}
|
||
var rules = this._currentRules();
|
||
for (var i = 0; i < rules.length; i++) {
|
||
tempMatch = this._input.match(this.rules[rules[i]]);
|
||
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
|
||
match = tempMatch;
|
||
index = i;
|
||
if (this.options.backtrack_lexer) {
|
||
token = this.test_match(tempMatch, rules[i]);
|
||
if (token !== false) {
|
||
return token;
|
||
} else if (this._backtrack) {
|
||
match = false;
|
||
continue; // rule action called reject() implying a rule MISmatch.
|
||
} else {
|
||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||
return false;
|
||
}
|
||
} else if (!this.options.flex) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (match) {
|
||
token = this.test_match(match, rules[index]);
|
||
if (token !== false) {
|
||
return token;
|
||
}
|
||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||
return false;
|
||
}
|
||
if (this._input === "") {
|
||
return this.EOF;
|
||
} else {
|
||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
|
||
text: "",
|
||
token: null,
|
||
line: this.yylineno
|
||
});
|
||
}
|
||
},
|
||
|
||
// return next match that has a token
|
||
lex: function lex() {
|
||
var r = this.next();
|
||
if (r) {
|
||
return r;
|
||
} else {
|
||
return this.lex();
|
||
}
|
||
},
|
||
|
||
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
|
||
begin: function begin(condition) {
|
||
this.conditionStack.push(condition);
|
||
},
|
||
|
||
// pop the previously active lexer condition state off the condition stack
|
||
popState: function popState() {
|
||
var n = this.conditionStack.length - 1;
|
||
if (n > 0) {
|
||
return this.conditionStack.pop();
|
||
} else {
|
||
return this.conditionStack[0];
|
||
}
|
||
},
|
||
|
||
// produce the lexer rule set which is active for the currently active lexer condition state
|
||
_currentRules: function _currentRules() {
|
||
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
|
||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
|
||
} else {
|
||
return this.conditions["INITIAL"].rules;
|
||
}
|
||
},
|
||
|
||
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
|
||
topState: function topState(n) {
|
||
n = this.conditionStack.length - 1 - Math.abs(n || 0);
|
||
if (n >= 0) {
|
||
return this.conditionStack[n];
|
||
} else {
|
||
return "INITIAL";
|
||
}
|
||
},
|
||
|
||
// alias for begin(condition)
|
||
pushState: function pushState(condition) {
|
||
this.begin(condition);
|
||
},
|
||
|
||
// return the number of states currently on the stack
|
||
stateStackSize: function stateStackSize() {
|
||
return this.conditionStack.length;
|
||
},
|
||
options: { "case-insensitive": true },
|
||
performAction: function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
|
||
var YYSTATE = YY_START;
|
||
switch ($avoiding_name_collisions) {
|
||
case 0:
|
||
return 9;
|
||
break;
|
||
case 1:
|
||
/* skip all whitespace */
|
||
break;
|
||
case 2:
|
||
/* skip same-line whitespace */
|
||
break;
|
||
case 3:
|
||
/* skip comments */
|
||
break;
|
||
case 4:
|
||
/* skip comments */
|
||
break;
|
||
case 5:
|
||
this.begin('ID');return 10;
|
||
break;
|
||
case 6:
|
||
this.begin('ALIAS');return 33;
|
||
break;
|
||
case 7:
|
||
this.popState();this.popState();this.begin('LINE');return 12;
|
||
break;
|
||
case 8:
|
||
this.popState();this.popState();return 9;
|
||
break;
|
||
case 9:
|
||
this.begin('LINE');return 18;
|
||
break;
|
||
case 10:
|
||
this.begin('LINE');return 20;
|
||
break;
|
||
case 11:
|
||
this.begin('LINE');return 21;
|
||
break;
|
||
case 12:
|
||
this.begin('LINE');return 22;
|
||
break;
|
||
case 13:
|
||
this.popState();return 13;
|
||
break;
|
||
case 14:
|
||
return 19;
|
||
break;
|
||
case 15:
|
||
return 30;
|
||
break;
|
||
case 16:
|
||
return 31;
|
||
break;
|
||
case 17:
|
||
return 26;
|
||
break;
|
||
case 18:
|
||
return 23;
|
||
break;
|
||
case 19:
|
||
return 16;
|
||
break;
|
||
case 20:
|
||
return 4;
|
||
break;
|
||
case 21:
|
||
return 29;
|
||
break;
|
||
case 22:
|
||
return 9;
|
||
break;
|
||
case 23:
|
||
return 33;
|
||
break;
|
||
case 24:
|
||
return 36;
|
||
break;
|
||
case 25:
|
||
return 37;
|
||
break;
|
||
case 26:
|
||
return 34;
|
||
break;
|
||
case 27:
|
||
return 35;
|
||
break;
|
||
case 28:
|
||
return 38;
|
||
break;
|
||
case 29:
|
||
return 39;
|
||
break;
|
||
case 30:
|
||
return 40;
|
||
break;
|
||
case 31:
|
||
return 9;
|
||
break;
|
||
case 32:
|
||
return 'INVALID';
|
||
break;
|
||
}
|
||
},
|
||
rules: [/^(?:[\n]+)/i, /^(?:\s+)/i, /^(?:((?!\n)\s)+)/i, /^(?:#[^\n]*)/i, /^(?:%[^\n]*)/i, /^(?:participant\b)/i, /^(?:[^\->:\n,;]+?(?=((?!\n)\s)+as(?!\n)\s|[#\n;]|$))/i, /^(?:as\b)/i, /^(?:(?:))/i, /^(?:loop\b)/i, /^(?:opt\b)/i, /^(?:alt\b)/i, /^(?:else\b)/i, /^(?:[^#\n;]*)/i, /^(?:end\b)/i, /^(?:left of\b)/i, /^(?:right of\b)/i, /^(?:over\b)/i, /^(?:note\b)/i, /^(?:title\b)/i, /^(?:sequenceDiagram\b)/i, /^(?:,)/i, /^(?:;)/i, /^(?:[^\->:\n,;]+)/i, /^(?:->>)/i, /^(?:-->>)/i, /^(?:->)/i, /^(?:-->)/i, /^(?:-[x])/i, /^(?:--[x])/i, /^(?::[^#\n;]+)/i, /^(?:$)/i, /^(?:.)/i],
|
||
conditions: { "LINE": { "rules": [2, 3, 13], "inclusive": false }, "ALIAS": { "rules": [2, 3, 7, 8], "inclusive": false }, "ID": { "rules": [2, 3, 6], "inclusive": false }, "INITIAL": { "rules": [0, 1, 3, 4, 5, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32], "inclusive": true } }
|
||
};
|
||
return lexer;
|
||
})();
|
||
parser.lexer = lexer;
|
||
function Parser() {
|
||
this.yy = {};
|
||
}
|
||
Parser.prototype = parser;parser.Parser = Parser;
|
||
return new Parser();
|
||
})();
|
||
|
||
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
|
||
exports.parser = sequenceDiagram;
|
||
exports.Parser = sequenceDiagram.Parser;
|
||
exports.parse = function () {
|
||
return sequenceDiagram.parse.apply(sequenceDiagram, arguments);
|
||
};
|
||
exports.main = function commonjsMain(args) {
|
||
if (!args[1]) {
|
||
console.log('Usage: ' + args[0] + ' FILE');
|
||
process.exit(1);
|
||
}
|
||
var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
|
||
return exports.parser.parse(source);
|
||
};
|
||
if (typeof module !== 'undefined' && require.main === module) {
|
||
exports.main(process.argv.slice(1));
|
||
}
|
||
}
|
||
|
||
}).call(this,require('_process'))
|
||
},{"_process":3,"fs":1,"path":2}],123:[function(require,module,exports){
|
||
(function (global){
|
||
/**
|
||
* Created by knut on 14-11-19.
|
||
*/
|
||
'use strict';
|
||
|
||
var actors = {};
|
||
var messages = [];
|
||
var notes = [];
|
||
var Logger = require('../../logger');
|
||
var log = new Logger.Log();
|
||
|
||
exports.addActor = function (id, name, description) {
|
||
// Don't allow description nulling
|
||
var old = actors[id];
|
||
if (old && name === old.name && description == null) return;
|
||
|
||
// Don't allow null descriptions, either
|
||
if (description == null) description = name;
|
||
|
||
actors[id] = { name: name, description: description };
|
||
};
|
||
|
||
exports.addMessage = function (idFrom, idTo, message, answer) {
|
||
messages.push({ from: idFrom, to: idTo, message: message, answer: answer });
|
||
};
|
||
|
||
/**
|
||
*
|
||
*/
|
||
exports.addSignal = function (idFrom, idTo, message, messageType) {
|
||
log.debug('Adding message from=' + idFrom + ' to=' + idTo + ' message=' + message + ' type=' + messageType);
|
||
messages.push({ from: idFrom, to: idTo, message: message, type: messageType });
|
||
};
|
||
|
||
exports.getMessages = function () {
|
||
return messages;
|
||
};
|
||
|
||
exports.getActors = function () {
|
||
return actors;
|
||
};
|
||
exports.getActor = function (id) {
|
||
return actors[id];
|
||
};
|
||
exports.getActorKeys = function () {
|
||
return Object.keys(actors);
|
||
};
|
||
|
||
exports.clear = function () {
|
||
actors = {};
|
||
messages = [];
|
||
};
|
||
|
||
exports.LINETYPE = {
|
||
SOLID: 0,
|
||
DOTTED: 1,
|
||
NOTE: 2,
|
||
SOLID_CROSS: 3,
|
||
DOTTED_CROSS: 4,
|
||
SOLID_OPEN: 5,
|
||
DOTTED_OPEN: 6,
|
||
LOOP_START: 10,
|
||
LOOP_END: 11,
|
||
ALT_START: 12,
|
||
ALT_ELSE: 13,
|
||
ALT_END: 14,
|
||
OPT_START: 15,
|
||
OPT_END: 16
|
||
};
|
||
|
||
exports.ARROWTYPE = {
|
||
FILLED: 0,
|
||
OPEN: 1
|
||
};
|
||
|
||
exports.PLACEMENT = {
|
||
LEFTOF: 0,
|
||
RIGHTOF: 1,
|
||
OVER: 2
|
||
};
|
||
|
||
exports.addNote = function (actor, placement, message) {
|
||
var note = { actor: actor, placement: placement, message: message };
|
||
|
||
// Coerce actor into a [to, from, ...] array
|
||
var actors = [].concat(actor, actor);
|
||
|
||
notes.push(note);
|
||
messages.push({ from: actors[0], to: actors[1], message: message, type: exports.LINETYPE.NOTE, placement: placement });
|
||
};
|
||
|
||
exports.parseError = function (err, hash) {
|
||
global.mermaidAPI.parseError(err, hash);
|
||
};
|
||
|
||
exports.apply = function (param) {
|
||
if (param instanceof Array) {
|
||
param.forEach(function (item) {
|
||
exports.apply(item);
|
||
});
|
||
} else {
|
||
// log.debug(param);
|
||
switch (param.type) {
|
||
case 'addActor':
|
||
exports.addActor(param.actor, param.actor, param.description);
|
||
break;
|
||
case 'addNote':
|
||
exports.addNote(param.actor, param.placement, param.text);
|
||
break;
|
||
case 'addMessage':
|
||
exports.addSignal(param.from, param.to, param.msg, param.signalType);
|
||
break;
|
||
case 'loopStart':
|
||
//log.debug('Loop text: ',param.loopText);
|
||
exports.addSignal(undefined, undefined, param.loopText, param.signalType);
|
||
//yy.addSignal(undefined, undefined, $2, yy.LINETYPE.LOOP_START);
|
||
break;
|
||
case 'loopEnd':
|
||
exports.addSignal(undefined, undefined, undefined, param.signalType);
|
||
break;
|
||
case 'optStart':
|
||
//log.debug('Loop text: ',param.loopText);
|
||
exports.addSignal(undefined, undefined, param.optText, param.signalType);
|
||
//yy.addSignal(undefined, undefined, $2, yy.LINETYPE.LOOP_START);
|
||
break;
|
||
case 'optEnd':
|
||
exports.addSignal(undefined, undefined, undefined, param.signalType);
|
||
break;
|
||
case 'altStart':
|
||
//log.debug('Loop text: ',param.loopText);
|
||
exports.addSignal(undefined, undefined, param.altText, param.signalType);
|
||
//yy.addSignal(undefined, undefined, $2, yy.LINETYPE.LOOP_START);
|
||
break;
|
||
case 'else':
|
||
exports.addSignal(undefined, undefined, param.altText, param.signalType);
|
||
break;
|
||
case 'altEnd':
|
||
exports.addSignal(undefined, undefined, undefined, param.signalType);
|
||
break;
|
||
}
|
||
}
|
||
};
|
||
|
||
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"../../logger":126}],124:[function(require,module,exports){
|
||
/**
|
||
* Created by knut on 14-11-23.
|
||
*/
|
||
|
||
'use strict';
|
||
|
||
var sq = require('./parser/sequenceDiagram').parser;
|
||
sq.yy = require('./sequenceDb');
|
||
var svgDraw = require('./svgDraw');
|
||
var d3 = require('../../d3');
|
||
var Logger = require('../../logger');
|
||
var log = new Logger.Log();
|
||
|
||
var conf = {
|
||
|
||
diagramMarginX: 50,
|
||
diagramMarginY: 10,
|
||
// Margin between actors
|
||
actorMargin: 50,
|
||
// Width of actor moxes
|
||
width: 150,
|
||
// Height of actor boxes
|
||
height: 65,
|
||
// Margin around loop boxes
|
||
boxMargin: 10,
|
||
boxTextMargin: 5,
|
||
noteMargin: 10,
|
||
// Space between messages
|
||
messageMargin: 35,
|
||
//mirror actors under diagram
|
||
mirrorActors: false,
|
||
// Depending on css styling this might need adjustment
|
||
// Prolongs the edge of the diagram downwards
|
||
bottomMarginAdj: 1
|
||
};
|
||
|
||
//var bb = getBBox('path');
|
||
exports.bounds = {
|
||
data: {
|
||
startx: undefined,
|
||
stopx: undefined,
|
||
starty: undefined,
|
||
stopy: undefined
|
||
},
|
||
verticalPos: 0,
|
||
|
||
list: [],
|
||
init: function init() {
|
||
this.list = [];
|
||
this.data = {
|
||
startx: undefined,
|
||
stopx: undefined,
|
||
starty: undefined,
|
||
stopy: undefined
|
||
};
|
||
this.verticalPos = 0;
|
||
},
|
||
updateVal: function updateVal(obj, key, val, fun) {
|
||
if (typeof obj[key] === 'undefined') {
|
||
obj[key] = val;
|
||
} else {
|
||
obj[key] = fun(val, obj[key]);
|
||
}
|
||
},
|
||
updateLoops: function updateLoops(startx, starty, stopx, stopy) {
|
||
var _self = this;
|
||
var cnt = 0;
|
||
this.list.forEach(function (loop) {
|
||
cnt++;
|
||
// The loop list is a stack so the biggest margins in the beginning of the list
|
||
var n = _self.list.length - cnt + 1;
|
||
|
||
_self.updateVal(loop, 'startx', startx - n * conf.boxMargin, Math.min);
|
||
_self.updateVal(loop, 'starty', starty - n * conf.boxMargin, Math.min);
|
||
_self.updateVal(loop, 'stopx', stopx + n * conf.boxMargin, Math.max);
|
||
_self.updateVal(loop, 'stopy', stopy + n * conf.boxMargin, Math.max);
|
||
|
||
_self.updateVal(exports.bounds.data, 'startx', startx - n * conf.boxMargin, Math.min);
|
||
_self.updateVal(exports.bounds.data, 'starty', starty - n * conf.boxMargin, Math.min);
|
||
_self.updateVal(exports.bounds.data, 'stopx', stopx + n * conf.boxMargin, Math.max);
|
||
_self.updateVal(exports.bounds.data, 'stopy', stopy + n * conf.boxMargin, Math.max);
|
||
});
|
||
},
|
||
insert: function insert(startx, starty, stopx, stopy) {
|
||
|
||
var _startx, _starty, _stopx, _stopy;
|
||
|
||
_startx = Math.min(startx, stopx);
|
||
_stopx = Math.max(startx, stopx);
|
||
_starty = Math.min(starty, stopy);
|
||
_stopy = Math.max(starty, stopy);
|
||
|
||
this.updateVal(exports.bounds.data, 'startx', _startx, Math.min);
|
||
this.updateVal(exports.bounds.data, 'starty', _starty, Math.min);
|
||
this.updateVal(exports.bounds.data, 'stopx', _stopx, Math.max);
|
||
this.updateVal(exports.bounds.data, 'stopy', _stopy, Math.max);
|
||
|
||
this.updateLoops(_startx, _starty, _stopx, _stopy);
|
||
},
|
||
newLoop: function newLoop(title) {
|
||
this.list.push({ startx: undefined, starty: this.verticalPos, stopx: undefined, stopy: undefined, title: title });
|
||
},
|
||
endLoop: function endLoop() {
|
||
var loop = this.list.pop();
|
||
//loop.stopy = exports.bounds.getVerticalPos();
|
||
return loop;
|
||
},
|
||
addElseToLoop: function addElseToLoop(message) {
|
||
var loop = this.list.pop();
|
||
loop.elsey = exports.bounds.getVerticalPos();
|
||
loop.elseText = message;
|
||
this.list.push(loop);
|
||
},
|
||
bumpVerticalPos: function bumpVerticalPos(bump) {
|
||
this.verticalPos = this.verticalPos + bump;
|
||
this.data.stopy = this.verticalPos;
|
||
},
|
||
getVerticalPos: function getVerticalPos() {
|
||
return this.verticalPos;
|
||
},
|
||
getBounds: function getBounds() {
|
||
return this.data;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Draws an actor in the diagram with the attaced line
|
||
* @param center - The center of the the actor
|
||
* @param pos The position if the actor in the liost of actors
|
||
* @param description The text in the box
|
||
*/
|
||
var drawNote = function drawNote(elem, startx, verticalPos, msg, forceWidth) {
|
||
var rect = svgDraw.getNoteRect();
|
||
rect.x = startx;
|
||
rect.y = verticalPos;
|
||
rect.width = forceWidth || conf.width;
|
||
rect['class'] = 'note';
|
||
|
||
var g = elem.append('g');
|
||
var rectElem = svgDraw.drawRect(g, rect);
|
||
|
||
var textObj = svgDraw.getTextObj();
|
||
textObj.x = startx - 4;
|
||
textObj.y = verticalPos - 13;
|
||
textObj.textMargin = conf.noteMargin;
|
||
textObj.dy = '1em';
|
||
textObj.text = msg.message;
|
||
textObj['class'] = 'noteText';
|
||
|
||
var textElem = svgDraw.drawText(g, textObj, rect.width - conf.noteMargin);
|
||
|
||
var textHeight = textElem[0][0].getBBox().height;
|
||
if (!forceWidth && textHeight > conf.width) {
|
||
textElem.remove();
|
||
g = elem.append('g');
|
||
|
||
textElem = svgDraw.drawText(g, textObj, 2 * rect.width - conf.noteMargin);
|
||
textHeight = textElem[0][0].getBBox().height;
|
||
rectElem.attr('width', 2 * rect.width);
|
||
exports.bounds.insert(startx, verticalPos, startx + 2 * rect.width, verticalPos + 2 * conf.noteMargin + textHeight);
|
||
} else {
|
||
exports.bounds.insert(startx, verticalPos, startx + rect.width, verticalPos + 2 * conf.noteMargin + textHeight);
|
||
}
|
||
|
||
rectElem.attr('height', textHeight + 2 * conf.noteMargin);
|
||
exports.bounds.bumpVerticalPos(textHeight + 2 * conf.noteMargin);
|
||
};
|
||
|
||
/**
|
||
* Draws a message
|
||
* @param elem
|
||
* @param startx
|
||
* @param stopx
|
||
* @param verticalPos
|
||
* @param txtCenter
|
||
* @param msg
|
||
*/
|
||
var drawMessage = function drawMessage(elem, startx, stopx, verticalPos, msg) {
|
||
var g = elem.append('g');
|
||
var txtCenter = startx + (stopx - startx) / 2;
|
||
|
||
var textElem = g.append('text') // text label for the x axis
|
||
.attr('x', txtCenter).attr('y', verticalPos - 7).style('text-anchor', 'middle').attr('class', 'messageText').text(msg.message);
|
||
|
||
var textWidth;
|
||
|
||
if (typeof textElem[0][0].getBBox !== 'undefined') {
|
||
textWidth = textElem[0][0].getBBox().width;
|
||
} else {
|
||
//textWidth = getBBox(textElem).width; //.getComputedTextLength()
|
||
textWidth = textElem[0][0].getBoundingClientRect();
|
||
//textWidth = textElem[0][0].getComputedTextLength();
|
||
}
|
||
|
||
var line;
|
||
|
||
if (startx === stopx) {
|
||
line = g.append('path').attr('d', 'M ' + startx + ',' + verticalPos + ' C ' + (startx + 60) + ',' + (verticalPos - 10) + ' ' + (startx + 60) + ',' + (verticalPos + 30) + ' ' + startx + ',' + (verticalPos + 20));
|
||
|
||
exports.bounds.bumpVerticalPos(30);
|
||
var dx = Math.max(textWidth / 2, 100);
|
||
exports.bounds.insert(startx - dx, exports.bounds.getVerticalPos() - 10, stopx + dx, exports.bounds.getVerticalPos());
|
||
} else {
|
||
line = g.append('line');
|
||
line.attr('x1', startx);
|
||
line.attr('y1', verticalPos);
|
||
line.attr('x2', stopx);
|
||
line.attr('y2', verticalPos);
|
||
exports.bounds.insert(startx, exports.bounds.getVerticalPos() - 10, stopx, exports.bounds.getVerticalPos());
|
||
}
|
||
//Make an SVG Container
|
||
//Draw the line
|
||
if (msg.type === sq.yy.LINETYPE.DOTTED || msg.type === sq.yy.LINETYPE.DOTTED_CROSS || msg.type === sq.yy.LINETYPE.DOTTED_OPEN) {
|
||
line.style('stroke-dasharray', '3, 3');
|
||
line.attr('class', 'messageLine1');
|
||
} else {
|
||
line.attr('class', 'messageLine0');
|
||
}
|
||
|
||
var url = '';
|
||
if (conf.arrowMarkerAbsolute) {
|
||
url = window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search;
|
||
url = url.replace(/\(/g, '\\(');
|
||
url = url.replace(/\)/g, '\\)');
|
||
}
|
||
|
||
line.attr('stroke-width', 2);
|
||
line.attr('stroke', 'black');
|
||
line.style('fill', 'none'); // remove any fill colour
|
||
if (msg.type === sq.yy.LINETYPE.SOLID || msg.type === sq.yy.LINETYPE.DOTTED) {
|
||
line.attr('marker-end', 'url(' + url + '#arrowhead)');
|
||
}
|
||
|
||
if (msg.type === sq.yy.LINETYPE.SOLID_CROSS || msg.type === sq.yy.LINETYPE.DOTTED_CROSS) {
|
||
line.attr('marker-end', 'url(' + url + '#crosshead)');
|
||
}
|
||
};
|
||
|
||
module.exports.drawActors = function (diagram, actors, actorKeys, verticalPos) {
|
||
var i;
|
||
// Draw the actors
|
||
for (i = 0; i < actorKeys.length; i++) {
|
||
var key = actorKeys[i];
|
||
|
||
// Add some rendering data to the object
|
||
actors[key].x = i * conf.actorMargin + i * conf.width;
|
||
actors[key].y = verticalPos;
|
||
actors[key].width = conf.diagramMarginY;
|
||
actors[key].height = conf.diagramMarginY;
|
||
|
||
// Draw the box with the attached line
|
||
svgDraw.drawActor(diagram, actors[key].x, verticalPos, actors[key].description, conf);
|
||
exports.bounds.insert(actors[key].x, verticalPos, actors[key].x + conf.width, conf.height);
|
||
}
|
||
|
||
// Add a margin between the actor boxes and the first arrow
|
||
//exports.bounds.bumpVerticalPos(conf.height+conf.messageMargin);
|
||
exports.bounds.bumpVerticalPos(conf.height);
|
||
};
|
||
|
||
module.exports.setConf = function (cnf) {
|
||
var keys = Object.keys(cnf);
|
||
|
||
keys.forEach(function (key) {
|
||
conf[key] = cnf[key];
|
||
});
|
||
};
|
||
/**
|
||
* Draws a flowchart in the tag with id: id based on the graph definition in text.
|
||
* @param text
|
||
* @param id
|
||
*/
|
||
module.exports.draw = function (text, id) {
|
||
sq.yy.clear();
|
||
sq.parse(text + '\n');
|
||
|
||
exports.bounds.init();
|
||
var diagram = d3.select('#' + id);
|
||
|
||
var startx;
|
||
var stopx;
|
||
var forceWidth;
|
||
|
||
// Fetch data from the parsing
|
||
var actors = sq.yy.getActors();
|
||
var actorKeys = sq.yy.getActorKeys();
|
||
var messages = sq.yy.getMessages();
|
||
module.exports.drawActors(diagram, actors, actorKeys, 0);
|
||
|
||
// The arrow head definition is attached to the svg once
|
||
svgDraw.insertArrowHead(diagram);
|
||
svgDraw.insertArrowCrossHead(diagram);
|
||
|
||
// Draw the messages/signals
|
||
messages.forEach(function (msg) {
|
||
var loopData;
|
||
|
||
switch (msg.type) {
|
||
case sq.yy.LINETYPE.NOTE:
|
||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||
|
||
startx = actors[msg.from].x;
|
||
stopx = actors[msg.to].x;
|
||
|
||
if (msg.placement === sq.yy.PLACEMENT.RIGHTOF) {
|
||
drawNote(diagram, startx + (conf.width + conf.actorMargin) / 2, exports.bounds.getVerticalPos(), msg);
|
||
} else if (msg.placement === sq.yy.PLACEMENT.LEFTOF) {
|
||
drawNote(diagram, startx - (conf.width + conf.actorMargin) / 2, exports.bounds.getVerticalPos(), msg);
|
||
} else if (msg.to === msg.from) {
|
||
// Single-actor over
|
||
drawNote(diagram, startx, exports.bounds.getVerticalPos(), msg);
|
||
} else {
|
||
// Multi-actor over
|
||
forceWidth = Math.abs(startx - stopx) + conf.actorMargin;
|
||
drawNote(diagram, (startx + stopx + conf.width - forceWidth) / 2, exports.bounds.getVerticalPos(), msg, forceWidth);
|
||
}
|
||
break;
|
||
case sq.yy.LINETYPE.LOOP_START:
|
||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||
exports.bounds.newLoop(msg.message);
|
||
exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin);
|
||
break;
|
||
case sq.yy.LINETYPE.LOOP_END:
|
||
loopData = exports.bounds.endLoop();
|
||
|
||
svgDraw.drawLoop(diagram, loopData, 'loop', conf);
|
||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||
break;
|
||
case sq.yy.LINETYPE.OPT_START:
|
||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||
exports.bounds.newLoop(msg.message);
|
||
exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin);
|
||
break;
|
||
case sq.yy.LINETYPE.OPT_END:
|
||
loopData = exports.bounds.endLoop();
|
||
|
||
svgDraw.drawLoop(diagram, loopData, 'opt', conf);
|
||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||
break;
|
||
case sq.yy.LINETYPE.ALT_START:
|
||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||
exports.bounds.newLoop(msg.message);
|
||
exports.bounds.bumpVerticalPos(conf.boxMargin + conf.boxTextMargin);
|
||
break;
|
||
case sq.yy.LINETYPE.ALT_ELSE:
|
||
|
||
//exports.drawLoop(diagram, loopData);
|
||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||
loopData = exports.bounds.addElseToLoop(msg.message);
|
||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||
break;
|
||
case sq.yy.LINETYPE.ALT_END:
|
||
loopData = exports.bounds.endLoop();
|
||
|
||
svgDraw.drawLoop(diagram, loopData, 'alt', conf);
|
||
exports.bounds.bumpVerticalPos(conf.boxMargin);
|
||
break;
|
||
default:
|
||
exports.bounds.bumpVerticalPos(conf.messageMargin);
|
||
startx = actors[msg.from].x + conf.width / 2;
|
||
stopx = actors[msg.to].x + conf.width / 2;
|
||
|
||
drawMessage(diagram, startx, stopx, exports.bounds.getVerticalPos(), msg);
|
||
|
||
}
|
||
});
|
||
|
||
if (conf.mirrorActors) {
|
||
// Draw actors below diagram
|
||
exports.bounds.bumpVerticalPos(conf.boxMargin * 2);
|
||
module.exports.drawActors(diagram, actors, actorKeys, exports.bounds.getVerticalPos());
|
||
}
|
||
|
||
var box = exports.bounds.getBounds();
|
||
|
||
// Adjust line height of actor lines now that the height of the diagram is known
|
||
log.debug('For line height fix Querying: #' + id + ' .actor-line');
|
||
var actorLines = d3.selectAll('#' + id + ' .actor-line');
|
||
actorLines.attr('y2', box.stopy);
|
||
|
||
var height = box.stopy - box.starty + 2 * conf.diagramMarginY;
|
||
|
||
if (conf.mirrorActors) {
|
||
height = height - conf.boxMargin + conf.bottomMarginAdj;
|
||
}
|
||
|
||
var width = box.stopx - box.startx + 2 * conf.diagramMarginX;
|
||
if (conf.useMaxWidth) {
|
||
diagram.attr('height', '100%');
|
||
diagram.attr('width', '100%');
|
||
diagram.attr('style', 'max-width:' + width + 'px;');
|
||
} else {
|
||
diagram.attr('height', height);
|
||
diagram.attr('width', width);
|
||
}
|
||
diagram.attr('viewBox', box.startx - conf.diagramMarginX + ' -' + conf.diagramMarginY + ' ' + width + ' ' + height);
|
||
};
|
||
|
||
},{"../../d3":107,"../../logger":126,"./parser/sequenceDiagram":122,"./sequenceDb":123,"./svgDraw":125}],125:[function(require,module,exports){
|
||
/**
|
||
* Created by knut on 14-12-20.
|
||
*/
|
||
//var log = require('../../logger').create();
|
||
'use strict';
|
||
|
||
exports.drawRect = function (elem, rectData) {
|
||
var rectElem = elem.append('rect');
|
||
rectElem.attr('x', rectData.x);
|
||
rectElem.attr('y', rectData.y);
|
||
rectElem.attr('fill', rectData.fill);
|
||
rectElem.attr('stroke', rectData.stroke);
|
||
rectElem.attr('width', rectData.width);
|
||
rectElem.attr('height', rectData.height);
|
||
rectElem.attr('rx', rectData.rx);
|
||
rectElem.attr('ry', rectData.ry);
|
||
|
||
if (typeof rectData['class'] !== 'undefined') {
|
||
rectElem.attr('class', rectData['class']);
|
||
}
|
||
|
||
return rectElem;
|
||
};
|
||
|
||
exports.drawText = function (elem, textData, width) {
|
||
// Remove and ignore br:s
|
||
var nText = textData.text.replace(/<br\/?>/ig, ' ');
|
||
|
||
var textElem = elem.append('text');
|
||
textElem.attr('x', textData.x);
|
||
textElem.attr('y', textData.y);
|
||
textElem.style('text-anchor', textData.anchor);
|
||
textElem.attr('fill', textData.fill);
|
||
if (typeof textData['class'] !== 'undefined') {
|
||
textElem.attr('class', textData['class']);
|
||
}
|
||
/* textData.text.split(/<br\/?>/ig).forEach(function(rowText){
|
||
var span = textElem.append('tspan');
|
||
span.attr('x', textData.x +textData.textMargin);
|
||
span.attr('dy', textData.dy);
|
||
span.text(rowText);
|
||
});*/
|
||
|
||
var span = textElem.append('tspan');
|
||
//span.attr('x', textData.x);
|
||
span.attr('x', textData.x + textData.textMargin * 2);
|
||
//span.attr('dy', textData.dy);
|
||
span.text(nText);
|
||
if (typeof textElem.textwrap !== 'undefined') {
|
||
|
||
textElem.textwrap({
|
||
x: textData.x, // bounding box is 300 pixels from the left
|
||
y: textData.y, // bounding box is 400 pixels from the top
|
||
width: width, // bounding box is 500 pixels across
|
||
height: 1800 // bounding box is 600 pixels tall
|
||
}, textData.textMargin);
|
||
}
|
||
|
||
return textElem;
|
||
};
|
||
|
||
exports.drawLabel = function (elem, txtObject) {
|
||
var rectData = exports.getNoteRect();
|
||
rectData.x = txtObject.x;
|
||
rectData.y = txtObject.y;
|
||
rectData.width = 50;
|
||
rectData.height = 20;
|
||
rectData.fill = '#526e52';
|
||
rectData.stroke = 'none';
|
||
rectData['class'] = 'labelBox';
|
||
//rectData.color = 'white';
|
||
|
||
exports.drawRect(elem, rectData);
|
||
|
||
txtObject.y = txtObject.y + txtObject.labelMargin;
|
||
txtObject.x = txtObject.x + 0.5 * txtObject.labelMargin;
|
||
txtObject.fill = 'white';
|
||
exports.drawText(elem, txtObject);
|
||
|
||
//return textElem;
|
||
};
|
||
var actorCnt = -1;
|
||
/**
|
||
* Draws an actor in the diagram with the attaced line
|
||
* @param center - The center of the the actor
|
||
* @param pos The position if the actor in the liost of actors
|
||
* @param description The text in the box
|
||
*/
|
||
exports.drawActor = function (elem, left, verticalPos, description, conf) {
|
||
var center = left + conf.width / 2;
|
||
var g = elem.append('g');
|
||
if (verticalPos === 0) {
|
||
actorCnt++;
|
||
g.append('line').attr('id', 'actor' + actorCnt).attr('x1', center).attr('y1', 5).attr('x2', center).attr('y2', 2000).attr('class', 'actor-line').attr('stroke-width', '0.5px').attr('stroke', '#999');
|
||
}
|
||
|
||
var rect = exports.getNoteRect();
|
||
rect.x = left;
|
||
rect.y = verticalPos;
|
||
rect.fill = '#eaeaea';
|
||
rect.width = conf.width;
|
||
rect.height = conf.height;
|
||
rect['class'] = 'actor';
|
||
rect.rx = 3;
|
||
rect.ry = 3;
|
||
exports.drawRect(g, rect);
|
||
|
||
g.append('text') // text label for the x axis
|
||
.attr('x', center).attr('y', verticalPos + conf.height / 2 + 5).attr('class', 'actor').style('text-anchor', 'middle').text(description);
|
||
};
|
||
|
||
/**
|
||
* Draws an actor in the diagram with the attaced line
|
||
* @param center - The center of the the actor
|
||
* @param pos The position if the actor in the list of actors
|
||
* @param description The text in the box
|
||
*/
|
||
exports.drawLoop = function (elem, bounds, labelText, conf) {
|
||
var g = elem.append('g');
|
||
var drawLoopLine = function drawLoopLine(startx, starty, stopx, stopy) {
|
||
g.append('line').attr('x1', startx).attr('y1', starty).attr('x2', stopx).attr('y2', stopy).attr('stroke-width', 2).attr('stroke', '#526e52').attr('class', 'loopLine');
|
||
};
|
||
drawLoopLine(bounds.startx, bounds.starty, bounds.stopx, bounds.starty);
|
||
drawLoopLine(bounds.stopx, bounds.starty, bounds.stopx, bounds.stopy);
|
||
drawLoopLine(bounds.startx, bounds.stopy, bounds.stopx, bounds.stopy);
|
||
drawLoopLine(bounds.startx, bounds.starty, bounds.startx, bounds.stopy);
|
||
if (typeof bounds.elsey !== 'undefined') {
|
||
drawLoopLine(bounds.startx, bounds.elsey, bounds.stopx, bounds.elsey);
|
||
}
|
||
|
||
var txt = exports.getTextObj();
|
||
txt.text = labelText;
|
||
txt.x = bounds.startx;
|
||
txt.y = bounds.starty;
|
||
txt.labelMargin = 1.5 * conf.boxMargin;
|
||
txt['class'] = 'labelText';
|
||
txt.fill = 'white';
|
||
|
||
exports.drawLabel(g, txt);
|
||
|
||
txt = exports.getTextObj();
|
||
txt.text = '[ ' + bounds.title + ' ]';
|
||
txt.x = bounds.startx + (bounds.stopx - bounds.startx) / 2;
|
||
txt.y = bounds.starty + 1.5 * conf.boxMargin;
|
||
txt.anchor = 'middle';
|
||
txt['class'] = 'loopText';
|
||
|
||
exports.drawText(g, txt);
|
||
|
||
if (typeof bounds.elseText !== 'undefined') {
|
||
txt.text = '[ ' + bounds.elseText + ' ]';
|
||
txt.y = bounds.elsey + 1.5 * conf.boxMargin;
|
||
exports.drawText(g, txt);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Setup arrow head and define the marker. The result is appended to the svg.
|
||
*/
|
||
exports.insertArrowHead = function (elem) {
|
||
elem.append('defs').append('marker').attr('id', 'arrowhead').attr('refX', 5).attr('refY', 2).attr('markerWidth', 6).attr('markerHeight', 4).attr('orient', 'auto').append('path').attr('d', 'M 0,0 V 4 L6,2 Z'); //this is actual shape for arrowhead
|
||
};
|
||
/**
|
||
* Setup arrow head and define the marker. The result is appended to the svg.
|
||
*/
|
||
exports.insertArrowCrossHead = function (elem) {
|
||
var defs = elem.append('defs');
|
||
var marker = defs.append('marker').attr('id', 'crosshead').attr('markerWidth', 15).attr('markerHeight', 8).attr('orient', 'auto').attr('refX', 16).attr('refY', 4);
|
||
|
||
// The arrow
|
||
marker.append('path').attr('fill', 'black').attr('stroke', '#000000').style('stroke-dasharray', '0, 0').attr('stroke-width', '1px').attr('d', 'M 9,2 V 6 L16,4 Z');
|
||
|
||
// The cross
|
||
marker.append('path').attr('fill', 'none').attr('stroke', '#000000').style('stroke-dasharray', '0, 0').attr('stroke-width', '1px').attr('d', 'M 0,1 L 6,7 M 6,1 L 0,7'); //this is actual shape for arrowhead
|
||
};
|
||
|
||
exports.getTextObj = function () {
|
||
var txt = {
|
||
x: 0,
|
||
y: 0,
|
||
'fill': 'black',
|
||
'text-anchor': 'start',
|
||
style: '#666',
|
||
width: 100,
|
||
height: 100,
|
||
textMargin: 0,
|
||
rx: 0,
|
||
ry: 0
|
||
};
|
||
return txt;
|
||
};
|
||
|
||
exports.getNoteRect = function () {
|
||
var rect = {
|
||
x: 0,
|
||
y: 0,
|
||
fill: '#EDF2AE',
|
||
stroke: '#666',
|
||
width: 100,
|
||
anchor: 'start',
|
||
height: 100,
|
||
rx: 0,
|
||
ry: 0
|
||
};
|
||
return rect;
|
||
};
|
||
|
||
},{}],126:[function(require,module,exports){
|
||
/**
|
||
* #logger
|
||
* logger = require('logger').create()
|
||
* logger.info("blah")
|
||
* => [2011-3-3T20:24:4.810 info (5021)] blah
|
||
* logger.debug("boom")
|
||
* =>
|
||
* logger.level = Logger.levels.debug
|
||
* logger.debug(function() { return "booom" })
|
||
* => [2011-3-3T20:24:4.810 error (5021)] booom
|
||
*/
|
||
|
||
'use strict';
|
||
|
||
var LEVELS = {
|
||
debug: 1,
|
||
info: 2,
|
||
warn: 3,
|
||
error: 4,
|
||
fatal: 5,
|
||
'default': 5
|
||
};
|
||
|
||
var defaultLevel = LEVELS.error;
|
||
|
||
exports.setLogLevel = function (level) {
|
||
defaultLevel = level;
|
||
};
|
||
|
||
function formatTime(timestamp) {
|
||
var hh = timestamp.getUTCHours();
|
||
var mm = timestamp.getUTCMinutes();
|
||
var ss = timestamp.getSeconds();
|
||
var ms = timestamp.getMilliseconds();
|
||
// If you were building a timestamp instead of a duration, you would uncomment the following line to get 12-hour (not 24) time
|
||
// if (hh > 12) {hh = hh % 12;}
|
||
// These lines ensure you have two-digits
|
||
if (hh < 10) {
|
||
hh = '0' + hh;
|
||
}
|
||
if (mm < 10) {
|
||
mm = '0' + mm;
|
||
}
|
||
if (ss < 10) {
|
||
ss = '0' + ss;
|
||
}
|
||
if (ms < 100) {
|
||
ms = '0' + ms;
|
||
}
|
||
if (ms < 10) {
|
||
ms = '00' + ms;
|
||
}
|
||
// This formats your string to HH:MM:SS
|
||
var t = hh + ':' + mm + ':' + ss + ' (' + ms + ')';
|
||
return t;
|
||
}
|
||
|
||
function Log(level) {
|
||
this.level = level;
|
||
|
||
this.log = function (str, level) {
|
||
var logLevel = this.level;
|
||
if (typeof logLevel === 'undefined') {
|
||
logLevel = defaultLevel;
|
||
}
|
||
if (logLevel <= level) {
|
||
if (typeof console !== 'undefined') {
|
||
//eslint-disable-line no-console
|
||
if (typeof console.log !== 'undefined') {
|
||
//eslint-disable-line no-console
|
||
return console.log('[' + formatTime(new Date()) + '] ' + str); //eslint-disable-line no-console
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
this.trace = function (str) {
|
||
this.log(str, LEVELS.trace);
|
||
};
|
||
|
||
this.debug = function (str) {
|
||
this.log(str, LEVELS.debug);
|
||
};
|
||
|
||
this.info = function (str) {
|
||
this.log(str, LEVELS.info);
|
||
};
|
||
|
||
this.warn = function (str) {
|
||
this.log(str, LEVELS.warn);
|
||
};
|
||
|
||
this.error = function (str) {
|
||
this.log(str, LEVELS.error);
|
||
};
|
||
}
|
||
|
||
exports.Log = Log;
|
||
|
||
},{}],127:[function(require,module,exports){
|
||
(function (global){
|
||
/**
|
||
* ---
|
||
* title: mermaidAPI
|
||
* order: 5
|
||
* ---
|
||
* # mermaidAPI
|
||
* This is the api to be used when handling the integration with the web page instead of using the default integration
|
||
* (mermaid.js).
|
||
*
|
||
* The core of this api is the **render** function that given a graph definitionas text renders the graph/diagram and
|
||
* returns a svg element for the graph. It is is then up to the user of the API to make use of the svg, either insert it
|
||
* somewhere in the page or something completely different.
|
||
*/
|
||
'use strict';
|
||
|
||
var Logger = require('./logger');
|
||
var log = new Logger.Log();
|
||
|
||
var graph = require('./diagrams/flowchart/graphDb');
|
||
var utils = require('./utils');
|
||
var flowRenderer = require('./diagrams/flowchart/flowRenderer');
|
||
var seq = require('./diagrams/sequenceDiagram/sequenceRenderer');
|
||
var info = require('./diagrams/example/exampleRenderer');
|
||
var infoParser = require('./diagrams/example/parser/example');
|
||
var flowParser = require('./diagrams/flowchart/parser/flow');
|
||
var dotParser = require('./diagrams/flowchart/parser/dot');
|
||
var sequenceParser = require('./diagrams/sequenceDiagram/parser/sequenceDiagram');
|
||
var sequenceDb = require('./diagrams/sequenceDiagram/sequenceDb');
|
||
var infoDb = require('./diagrams/example/exampleDb');
|
||
var gantt = require('./diagrams/gantt/ganttRenderer');
|
||
var ganttParser = require('./diagrams/gantt/parser/gantt');
|
||
var ganttDb = require('./diagrams/gantt/ganttDb');
|
||
var classParser = require('./diagrams/classDiagram/parser/classDiagram');
|
||
var classRenderer = require('./diagrams/classDiagram/classRenderer');
|
||
var classDb = require('./diagrams/classDiagram/classDb');
|
||
var d3 = require('./d3');
|
||
|
||
SVGElement.prototype.getTransformToElement = SVGElement.prototype.getTransformToElement || function (toElement) {
|
||
return toElement.getScreenCTM().inverse().multiply(this.getScreenCTM());
|
||
};
|
||
/**
|
||
* ## Configuration
|
||
* These are the default options which can be overridden with the initialization call as in the example below:
|
||
* ```
|
||
* mermaid.initialize({
|
||
* flowchart:{
|
||
* htmlLabels: false
|
||
* }
|
||
* });
|
||
* ```
|
||
*/
|
||
var config = {
|
||
/**
|
||
* logLevel , decides the amount of logging to be used.
|
||
* * debug: 1
|
||
* * info: 2
|
||
* * warn: 3
|
||
* * error: 4
|
||
* * fatal: 5
|
||
*/
|
||
logLevel: 5,
|
||
/**
|
||
* **cloneCssStyles** - This options controls whether or not the css rules should be copied into the generated svg
|
||
*/
|
||
cloneCssStyles: true,
|
||
|
||
/**
|
||
* **startOnLoad** - This options controls whether or mermaid starts when the page loads
|
||
*/
|
||
startOnLoad: true,
|
||
|
||
/**
|
||
* **arrowMarkerAbsolute** - This options controls whether or arrow markers in html code will be absolute pats or
|
||
* an anchor, #. This matters if you are using base tag settings.
|
||
*/
|
||
arrowMarkerAbsolute: false,
|
||
|
||
/**
|
||
* ### flowchart
|
||
* *The object containing configurations specific for flowcharts*
|
||
*/
|
||
flowchart: {
|
||
/**
|
||
* **htmlLabels** - Flag for setting whether or not a html tag should be used for rendering labels
|
||
* on the edges
|
||
*/
|
||
htmlLabels: true,
|
||
/**
|
||
* **useMaxWidth** - Flag for setting whether or not a all available width should be used for
|
||
* the diagram.
|
||
*/
|
||
useMaxWidth: true
|
||
},
|
||
|
||
/**
|
||
* ### sequenceDiagram
|
||
* The object containing configurations specific for sequence diagrams
|
||
*/
|
||
sequenceDiagram: {
|
||
|
||
/**
|
||
* **diagramMarginX** - margin to the right and left of the sequence diagram
|
||
*/
|
||
diagramMarginX: 50,
|
||
|
||
/**
|
||
* **diagramMarginY** - margin to the over and under the sequence diagram
|
||
*/
|
||
diagramMarginY: 10,
|
||
|
||
/**
|
||
* **actorMargin** - Margin between actors
|
||
*/
|
||
actorMargin: 50,
|
||
|
||
/**
|
||
* **width** - Width of actor boxes
|
||
*/
|
||
width: 150,
|
||
|
||
/**
|
||
* **height** - Height of actor boxes
|
||
*/
|
||
height: 65,
|
||
|
||
/**
|
||
* **boxMargin** - Margin around loop boxes
|
||
*/
|
||
boxMargin: 10,
|
||
|
||
/**
|
||
* **boxTextMargin** - margin around the text in loop/alt/opt boxes
|
||
*/
|
||
boxTextMargin: 5,
|
||
|
||
/**
|
||
* **noteMargin** - margin around notes
|
||
*/
|
||
noteMargin: 10,
|
||
|
||
/**
|
||
* **messageMargin** - Space between messages
|
||
*/
|
||
messageMargin: 35,
|
||
|
||
/**
|
||
* **mirrorActors** - mirror actors under diagram
|
||
*/
|
||
mirrorActors: true,
|
||
|
||
/**
|
||
* **bottomMarginAdj** - Depending on css styling this might need adjustment.
|
||
* Prolongs the edge of the diagram downwards
|
||
*/
|
||
bottomMarginAdj: 1,
|
||
|
||
/**
|
||
* **useMaxWidth** - when this flag is set the height and width is set to 100% and is then scaling with the
|
||
* available space if not the absolute space required is used
|
||
*/
|
||
useMaxWidth: true
|
||
},
|
||
|
||
/** ### gantt
|
||
* The object containing configurations specific for gantt diagrams*
|
||
*/
|
||
gantt: {
|
||
/**
|
||
* **titleTopMargin** - margin top for the text over the gantt diagram
|
||
*/
|
||
titleTopMargin: 25,
|
||
|
||
/**
|
||
* **barHeight** - the height of the bars in the graph
|
||
*/
|
||
barHeight: 20,
|
||
|
||
/**
|
||
* **barGap** - the margin between the different activities in the gantt diagram
|
||
*/
|
||
barGap: 4,
|
||
|
||
/**
|
||
* **topPadding** - margin between title and gantt diagram and between axis and gantt diagram.
|
||
*/
|
||
topPadding: 50,
|
||
|
||
/**
|
||
* **sidePadding** - the space allocated for the section name to the left of the activities.
|
||
*/
|
||
sidePadding: 75,
|
||
|
||
/**
|
||
* **gridLineStartPadding** - Vertical starting position of the grid lines
|
||
*/
|
||
gridLineStartPadding: 35,
|
||
|
||
/**
|
||
* **fontSize** - font size ...
|
||
*/
|
||
fontSize: 11,
|
||
|
||
/**
|
||
* **fontFamily** - font family ...
|
||
*/
|
||
fontFamily: '"Open-Sans", "sans-serif"',
|
||
|
||
/**
|
||
* **numberSectionStyles** - the number of alternating section styles
|
||
*/
|
||
numberSectionStyles: 3,
|
||
|
||
/**
|
||
* **axisFormatter** - formatting of the axis, this might need adjustment to match your locale and preferences
|
||
*/
|
||
axisFormatter: [
|
||
|
||
// Within a day
|
||
['%I:%M', function (d) {
|
||
return d.getHours();
|
||
}],
|
||
// Monday a week
|
||
['w. %U', function (d) {
|
||
return d.getDay() == 1;
|
||
}],
|
||
// Day within a week (not monday)
|
||
['%a %d', function (d) {
|
||
return d.getDay() && d.getDate() != 1;
|
||
}],
|
||
// within a month
|
||
['%b %d', function (d) {
|
||
return d.getDate() != 1;
|
||
}],
|
||
// Month
|
||
['%m-%y', function (d) {
|
||
return d.getMonth();
|
||
}]]
|
||
},
|
||
classDiagram: {},
|
||
info: {}
|
||
};
|
||
|
||
Logger.setLogLevel(config.logLevel);
|
||
|
||
/**
|
||
* ## parse
|
||
* Function that parses a mermaid diagram definition. If parsing fails the parseError callback is called and an error is
|
||
* thrown and
|
||
* @param text
|
||
*/
|
||
var parse = function parse(text) {
|
||
var graphType = utils.detectType(text);
|
||
var parser;
|
||
|
||
switch (graphType) {
|
||
case 'graph':
|
||
parser = flowParser;
|
||
parser.parser.yy = graph;
|
||
break;
|
||
case 'dotGraph':
|
||
parser = dotParser;
|
||
parser.parser.yy = graph;
|
||
break;
|
||
case 'sequenceDiagram':
|
||
parser = sequenceParser;
|
||
parser.parser.yy = sequenceDb;
|
||
break;
|
||
case 'info':
|
||
parser = infoParser;
|
||
parser.parser.yy = infoDb;
|
||
break;
|
||
case 'gantt':
|
||
parser = ganttParser;
|
||
parser.parser.yy = ganttDb;
|
||
break;
|
||
case 'classDiagram':
|
||
parser = classParser;
|
||
parser.parser.yy = classDb;
|
||
break;
|
||
}
|
||
|
||
try {
|
||
parser.parse(text);
|
||
return true;
|
||
} catch (err) {
|
||
return false;
|
||
}
|
||
};
|
||
exports.parse = parse;
|
||
|
||
/**
|
||
* ## version
|
||
* Function returning version information
|
||
* @returns {string} A string containing the version info
|
||
*/
|
||
exports.version = function () {
|
||
return require('../package.json').version;
|
||
};
|
||
|
||
exports.encodeEntities = function (text) {
|
||
var txt = text;
|
||
|
||
txt = txt.replace(/style.*:\S*#.*;/g, function (s) {
|
||
var innerTxt = s.substring(0, s.length - 1);
|
||
return innerTxt;
|
||
});
|
||
txt = txt.replace(/classDef.*:\S*#.*;/g, function (s) {
|
||
var innerTxt = s.substring(0, s.length - 1);
|
||
return innerTxt;
|
||
});
|
||
|
||
txt = txt.replace(/#\w+\;/g, function (s) {
|
||
var innerTxt = s.substring(1, s.length - 1);
|
||
|
||
var isInt = /^\+?\d+$/.test(innerTxt);
|
||
if (isInt) {
|
||
return 'fl°°' + innerTxt + '¶ß';
|
||
} else {
|
||
return 'fl°' + innerTxt + '¶ß';
|
||
}
|
||
});
|
||
|
||
return txt;
|
||
};
|
||
|
||
exports.decodeEntities = function (text) {
|
||
var txt = text;
|
||
|
||
txt = txt.replace(/\fl\°\°/g, function () {
|
||
return '&#';
|
||
});
|
||
txt = txt.replace(/\fl\°/g, function () {
|
||
return '&';
|
||
});
|
||
txt = txt.replace(/¶ß/g, function () {
|
||
return ';';
|
||
});
|
||
|
||
return txt;
|
||
};
|
||
/**
|
||
* ##render
|
||
* Function that renders an svg with a graph from a chart definition. Usage example below.
|
||
*
|
||
* ```
|
||
* mermaidAPI.initialize({
|
||
* startOnLoad:true
|
||
* });
|
||
* $(function(){
|
||
* var graphDefinition = 'graph TB\na-->b';
|
||
* var cb = function(svgGraph){
|
||
* console.log(svgGraph);
|
||
* };
|
||
* mermaidAPI.render('id1',graphDefinition,cb);
|
||
* });
|
||
*```
|
||
* @param id the id of the element to be rendered
|
||
* @param txt the graph definition
|
||
* @param cb callback which is called after rendering is finished with the svg code as inparam.
|
||
* @param container selector to element in which a div with the graph temporarily will be inserted. In one is
|
||
* provided a hidden div will be inserted in the body of the page instead. The element will be removed when rendering is
|
||
* completed.
|
||
*/
|
||
var render = function render(id, txt, cb, container) {
|
||
|
||
if (typeof container !== 'undefined') {
|
||
d3.select(container).append('div').attr('id', 'd' + id).append('svg').attr('id', id).attr('width', '100%').attr('xmlns', 'http://www.w3.org/2000/svg').append('g');
|
||
} else {
|
||
d3.select('body').append('div').attr('id', 'd' + id).append('svg').attr('id', id).attr('width', '100%').attr('xmlns', 'http://www.w3.org/2000/svg').append('g');
|
||
}
|
||
|
||
window.txt = txt;
|
||
txt = exports.encodeEntities(txt);
|
||
//console.warn('mermaid encode: ');
|
||
//console.warn(txt);
|
||
|
||
var element = d3.select('#d' + id).node();
|
||
var graphType = utils.detectType(txt);
|
||
var classes = {};
|
||
switch (graphType) {
|
||
case 'graph':
|
||
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||
flowRenderer.setConf(config.flowchart);
|
||
flowRenderer.draw(txt, id, false);
|
||
if (config.cloneCssStyles) {
|
||
classes = flowRenderer.getClasses(txt, false);
|
||
utils.cloneCssStyles(element.firstChild, classes);
|
||
}
|
||
break;
|
||
case 'dotGraph':
|
||
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||
flowRenderer.setConf(config.flowchart);
|
||
flowRenderer.draw(txt, id, true);
|
||
if (config.cloneCssStyles) {
|
||
classes = flowRenderer.getClasses(txt, true);
|
||
utils.cloneCssStyles(element.firstChild, classes);
|
||
}
|
||
break;
|
||
case 'sequenceDiagram':
|
||
config.sequenceDiagram.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||
seq.setConf(config.sequenceDiagram);
|
||
seq.draw(txt, id);
|
||
if (config.cloneCssStyles) {
|
||
utils.cloneCssStyles(element.firstChild, []);
|
||
}
|
||
break;
|
||
case 'gantt':
|
||
config.gantt.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||
gantt.setConf(config.gantt);
|
||
gantt.draw(txt, id);
|
||
if (config.cloneCssStyles) {
|
||
utils.cloneCssStyles(element.firstChild, []);
|
||
}
|
||
break;
|
||
case 'classDiagram':
|
||
config.classDiagram.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||
classRenderer.setConf(config.classDiagram);
|
||
classRenderer.draw(txt, id);
|
||
if (config.cloneCssStyles) {
|
||
utils.cloneCssStyles(element.firstChild, []);
|
||
}
|
||
break;
|
||
case 'info':
|
||
config.info.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||
info.draw(txt, id, exports.version());
|
||
if (config.cloneCssStyles) {
|
||
utils.cloneCssStyles(element.firstChild, []);
|
||
}
|
||
break;
|
||
}
|
||
|
||
d3.select('#d' + id).selectAll('foreignobject div').attr('xmlns', 'http://www.w3.org/1999/xhtml');
|
||
|
||
var url = '';
|
||
if (config.arrowMarkerAbsolute) {
|
||
url = window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search;
|
||
url = url.replace(/\(/g, '\\(');
|
||
url = url.replace(/\)/g, '\\)');
|
||
}
|
||
|
||
// Fix for when the base tag is used
|
||
var svgCode = d3.select('#d' + id).node().innerHTML.replace(/url\(#arrowhead/g, 'url(' + url + '#arrowhead', 'g');
|
||
|
||
svgCode = exports.decodeEntities(svgCode);
|
||
|
||
//console.warn('mermaid decode: ');
|
||
//console.warn(svgCode);
|
||
//var he = require('he');
|
||
//svgCode = he.decode(svgCode);
|
||
if (typeof cb !== 'undefined') {
|
||
cb(svgCode, graph.bindFunctions);
|
||
} else {
|
||
log.warn('CB = undefined!');
|
||
}
|
||
|
||
var node = d3.select('#d' + id).node();
|
||
if (node !== null && typeof node.remove === 'function') {
|
||
d3.select('#d' + id).node().remove();
|
||
}
|
||
|
||
return svgCode;
|
||
};
|
||
|
||
exports.render = function (id, text, cb, containerElement) {
|
||
try {
|
||
if (arguments.length === 1) {
|
||
text = id;
|
||
id = 'mermaidId0';
|
||
}
|
||
|
||
if (typeof document === 'undefined') {
|
||
// Todo handle rendering serverside using phantomjs
|
||
} else {
|
||
// In browser
|
||
return render(id, text, cb, containerElement);
|
||
}
|
||
} catch (e) {
|
||
log.warn(e);
|
||
}
|
||
};
|
||
|
||
var setConf = function setConf(cnf) {
|
||
// Top level initially mermaid, gflow, sequenceDiagram and gantt
|
||
var lvl1Keys = Object.keys(cnf);
|
||
var i;
|
||
for (i = 0; i < lvl1Keys.length; i++) {
|
||
|
||
if (typeof cnf[lvl1Keys[i]] === 'object') {
|
||
var lvl2Keys = Object.keys(cnf[lvl1Keys[i]]);
|
||
|
||
var j;
|
||
for (j = 0; j < lvl2Keys.length; j++) {
|
||
log.debug('Setting conf ', lvl1Keys[i], '-', lvl2Keys[j]);
|
||
if (typeof config[lvl1Keys[i]] === 'undefined') {
|
||
|
||
config[lvl1Keys[i]] = {};
|
||
}
|
||
log.debug('Setting config: ' + lvl1Keys[i] + ' ' + lvl2Keys[j] + ' to ' + cnf[lvl1Keys[i]][lvl2Keys[j]]);
|
||
config[lvl1Keys[i]][lvl2Keys[j]] = cnf[lvl1Keys[i]][lvl2Keys[j]];
|
||
}
|
||
} else {
|
||
config[lvl1Keys[i]] = cnf[lvl1Keys[i]];
|
||
}
|
||
}
|
||
};
|
||
exports.initialize = function (options) {
|
||
log.debug('Initializing mermaidAPI');
|
||
// Update default config with options supplied at initialization
|
||
if (typeof options === 'object') {
|
||
setConf(options);
|
||
}
|
||
Logger.setLogLevel(config.logLevel);
|
||
};
|
||
exports.getConfig = function () {
|
||
return config;
|
||
};
|
||
|
||
exports.parseError = function (err, hash) {
|
||
if (typeof mermaid !== 'undefined') {
|
||
global.mermaid.parseError(err, hash);
|
||
} else {
|
||
log.debug('Mermaid Syntax error:');
|
||
log.debug(err);
|
||
}
|
||
};
|
||
global.mermaidAPI = {
|
||
render: exports.render,
|
||
parse: exports.parse,
|
||
initialize: exports.initialize,
|
||
detectType: utils.detectType,
|
||
parseError: exports.parseError,
|
||
getConfig: exports.getConfig
|
||
};
|
||
|
||
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"../package.json":106,"./d3":107,"./diagrams/classDiagram/classDb":108,"./diagrams/classDiagram/classRenderer":109,"./diagrams/classDiagram/parser/classDiagram":110,"./diagrams/example/exampleDb":111,"./diagrams/example/exampleRenderer":112,"./diagrams/example/parser/example":113,"./diagrams/flowchart/flowRenderer":115,"./diagrams/flowchart/graphDb":116,"./diagrams/flowchart/parser/dot":117,"./diagrams/flowchart/parser/flow":118,"./diagrams/gantt/ganttDb":119,"./diagrams/gantt/ganttRenderer":120,"./diagrams/gantt/parser/gantt":121,"./diagrams/sequenceDiagram/parser/sequenceDiagram":122,"./diagrams/sequenceDiagram/sequenceDb":123,"./diagrams/sequenceDiagram/sequenceRenderer":124,"./logger":126,"./utils":128}],128:[function(require,module,exports){
|
||
/**
|
||
* Created by knut on 14-11-23.
|
||
*/
|
||
'use strict';
|
||
|
||
var Logger = require('./logger');
|
||
var log = new Logger.Log();
|
||
|
||
/**
|
||
* @function detectType
|
||
* Detects the type of the graph text.
|
||
* ```mermaid
|
||
* graph LR
|
||
* a-->b
|
||
* b-->c
|
||
* c-->d
|
||
* d-->e
|
||
* e-->f
|
||
* f-->g
|
||
* g-->h
|
||
* ```
|
||
*
|
||
* @param {string} text The text defining the graph
|
||
* @returns {string} A graph definition key
|
||
*/
|
||
var detectType = function detectType(text) {
|
||
text = text.replace(/^\s*%%.*\n/g, '\n');
|
||
if (text.match(/^\s*sequenceDiagram/)) {
|
||
return 'sequenceDiagram';
|
||
}
|
||
|
||
if (text.match(/^\s*digraph/)) {
|
||
//log.debug('Detected dot syntax');
|
||
return 'dotGraph';
|
||
}
|
||
|
||
if (text.match(/^\s*info/)) {
|
||
//log.debug('Detected info syntax');
|
||
return 'info';
|
||
}
|
||
|
||
if (text.match(/^\s*gantt/)) {
|
||
//log.debug('Detected info syntax');
|
||
return 'gantt';
|
||
}
|
||
|
||
if (text.match(/^\s*classDiagram/)) {
|
||
log.debug('Detected classDiagram syntax');
|
||
return 'classDiagram';
|
||
}
|
||
|
||
return 'graph';
|
||
};
|
||
exports.detectType = detectType;
|
||
|
||
/**
|
||
* Copies all relevant CSS content into the graph SVG.
|
||
* This allows the SVG to be copied as is while keeping class based styling
|
||
* @param {element} svg The root element of the SVG
|
||
* @param {object} Hash table of class definitions from the graph definition
|
||
*/
|
||
var cloneCssStyles = function cloneCssStyles(svg, classes) {
|
||
var usedStyles = '';
|
||
var sheets = document.styleSheets;
|
||
var rule;
|
||
for (var i = 0; i < sheets.length; i++) {
|
||
// Avoid multiple inclusion on pages with multiple graphs
|
||
if (sheets[i].title !== 'mermaid-svg-internal-css') {
|
||
try {
|
||
|
||
var rules = sheets[i].cssRules;
|
||
if (rules !== null) {
|
||
for (var j = 0; j < rules.length; j++) {
|
||
rule = rules[j];
|
||
if (typeof rule.style !== 'undefined') {
|
||
var elems;
|
||
elems = svg.querySelectorAll(rule.selectorText);
|
||
if (elems.length > 0) {
|
||
usedStyles += rule.selectorText + ' { ' + rule.style.cssText + '}\n';
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} catch (err) {
|
||
if (typeof rule !== 'undefined') {
|
||
log.warn('Invalid CSS selector "' + rule.selectorText + '"', err);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
var defaultStyles = '';
|
||
var embeddedStyles = '';
|
||
|
||
for (var className in classes) {
|
||
if (classes.hasOwnProperty(className) && typeof className != 'undefined') {
|
||
if (className === 'default') {
|
||
if (classes['default'].styles instanceof Array) {
|
||
defaultStyles += '#' + svg.id.trim() + ' .node' + '>rect { ' + classes[className].styles.join('; ') + '; }\n';
|
||
}
|
||
if (classes['default'].nodeLabelStyles instanceof Array) {
|
||
defaultStyles += '#' + svg.id.trim() + ' .node text ' + ' { ' + classes[className].nodeLabelStyles.join('; ') + '; }\n';
|
||
}
|
||
if (classes['default'].edgeLabelStyles instanceof Array) {
|
||
defaultStyles += '#' + svg.id.trim() + ' .edgeLabel text ' + ' { ' + classes[className].edgeLabelStyles.join('; ') + '; }\n';
|
||
}
|
||
if (classes['default'].clusterStyles instanceof Array) {
|
||
defaultStyles += '#' + svg.id.trim() + ' .cluster rect ' + ' { ' + classes[className].clusterStyles.join('; ') + '; }\n';
|
||
}
|
||
} else {
|
||
if (classes[className].styles instanceof Array) {
|
||
embeddedStyles += '#' + svg.id.trim() + ' .' + className + '>rect, .' + className + '>polygon, .' + className + '>ellipse { ' + classes[className].styles.join('; ') + '; }\n';
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (usedStyles !== '' || defaultStyles !== '' || embeddedStyles !== '') {
|
||
var s = document.createElement('style');
|
||
s.setAttribute('type', 'text/css');
|
||
s.setAttribute('title', 'mermaid-svg-internal-css');
|
||
s.innerHTML = '/* <![CDATA[ */\n';
|
||
// Make this CSS local to this SVG
|
||
if (defaultStyles !== '') {
|
||
s.innerHTML += defaultStyles;
|
||
}
|
||
if (usedStyles !== '') {
|
||
s.innerHTML += usedStyles;
|
||
}
|
||
if (embeddedStyles !== '') {
|
||
s.innerHTML += embeddedStyles;
|
||
}
|
||
s.innerHTML += '/* ]]> */\n';
|
||
svg.insertBefore(s, svg.firstChild);
|
||
}
|
||
};
|
||
|
||
exports.cloneCssStyles = cloneCssStyles;
|
||
|
||
},{"./logger":126}]},{},[127])(127)
|
||
}); |