!(function (e) { if (typeof exports === 'object')module.exports = e(); else if (typeof define === 'function' && define.amd)define(e); else { var f; typeof window !== 'undefined' ? f = window : typeof global !== 'undefined' ? f = global : typeof self !== 'undefined' && (f = self), f.mermaid = 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); throw new Error("Cannot find module '" + o + "'") } var f = n[o] = {exports: {}}; t[o][0].call(f.exports, function (e) { var n = t[o][1][e]; return s(n || e) }, f, f.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 (_dereq_, 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), 0.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() * 0.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(0.7, arguments.length ? k : 1) return new d3_hsl(this.h, this.s, this.l / k) } d3_hslPrototype.darker = function (k) { k = Math.pow(0.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 <= 0.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 = 0.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 - 0.4985314 * z), d3_xyz_rgb(-0.969266 * x + 1.8760108 * y + 0.041556 * z), d3_xyz_rgb(0.0556434 * x - 0.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 > 0.206893034 ? x * x * x : (x - 4 / 29) / 7.787037 } function d3_xyz_lab (x) { return x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29 } function d3_xyz_rgb (r) { return Math.round(255 * (r <= 0.00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - 0.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(0.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(0.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 < 0.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((0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / d3_lab_X), y = d3_xyz_lab((0.2126729 * r + 0.7151522 * g + 0.072175 * b) / d3_lab_Y), z = d3_xyz_lab((0.0193339 * r + 0.119192 * g + 0.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) <= 0.04045 ? r / 12.92 : Math.pow((r + 0.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([ -0.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 >= 0.12 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.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(_ * 0.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 - 0.455 * k, y - 0.238 * k ], [ x + 0.455 * k, y + 0.238 * k ] ]).stream(pointStream).point alaskaPoint = alaska.translate([ x - 0.307 * k, y + 0.201 * k ]).clipExtent([ [ x - 0.425 * k + ε, y + 0.12 * k + ε ], [ x - 0.214 * k - ε, y + 0.234 * k - ε ] ]).stream(pointStream).point hawaiiPoint = hawaii.translate([ x - 0.205 * k, y + 0.212 * k ]).clipExtent([ [ x - 0.214 * k + ε, y + 0.166 * k + ε ], [ x - 0.115 * k - ε, y + 0.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 = 0.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 - 0.5) > 0.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 - 0.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 * 0.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) < 0.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) * 0.5, ym = (y1 + y2) * 0.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) * 0.5, sy = (y1 + y2) * 0.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) * 0.5, ym = (y1 + y2) * 0.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 0.5 * (t < 0.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 < 0.5 ? t3 : 3 * (t - t2) + t3 - 0.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 = 0.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 + 0.75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + 0.9375 : 7.5625 * (t -= 2.625 / 2.75) * t + 0.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 = 0.9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = 0.1, theta2 = 0.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 *= 0.99) < 0.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(0.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() - 0.5 quad.point.y += Math.random() - 0.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 0.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 = 0.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 = 0.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 <= 0.15) step *= 10; else if (err <= 0.35) step *= 5; else if (err <= 0.75) step *= 2 extent[0] = Math.ceil(extent[0] / step) * step extent[1] = Math.floor(extent[1] / step) * step + step * 0.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 + 0.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(0.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(0.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([ 0.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))) > 0.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 = 0.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 = 0.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 += 0.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 }()) }, {}], 2: [function (_dereq_, 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: _dereq_('./lib/graphlib'), dagre: _dereq_('./lib/dagre'), intersect: _dereq_('./lib/intersect'), render: _dereq_('./lib/render'), util: _dereq_('./lib/util'), version: _dereq_('./lib/version') } }, {'./lib/dagre': 9, './lib/graphlib': 10, './lib/intersect': 11, './lib/render': 26, './lib/util': 28, './lib/version': 29}], 3: [function (_dereq_, module, exports) { var util = _dereq_('./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': 28}], 4: [function (_dereq_, module, exports) { var util = _dereq_('./util'), addLabel = _dereq_('./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': 19, './util': 28}], 5: [function (_dereq_, module, exports) { 'use strict' var _ = _dereq_('./lodash'), addLabel = _dereq_('./label/add-label'), util = _dereq_('./util'), d3 = _dereq_('./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': 8, './label/add-label': 19, './lodash': 22, './util': 28}], 6: [function (_dereq_, module, exports) { 'use strict' var _ = _dereq_('./lodash'), intersectNode = _dereq_('./intersect/intersect-node'), util = _dereq_('./util'), d3 = _dereq_('./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': 8, './intersect/intersect-node': 15, './lodash': 22, './util': 28}], 7: [function (_dereq_, module, exports) { 'use strict' var _ = _dereq_('./lodash'), addLabel = _dereq_('./label/add-label'), util = _dereq_('./util'), d3 = _dereq_('./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': 8, './label/add-label': 19, './lodash': 22, './util': 28}], 8: [function (_dereq_, module, exports) { // Stub to get D3 either via NPM or from the global object module.exports = window.d3 }, {}], 9: [function (_dereq_, module, exports) { /* global window */ var dagre if (_dereq_) { try { dagre = _dereq_('dagre') } catch (e) {} } if (!dagre) { dagre = window.dagre } module.exports = dagre }, {'dagre': 51}], 10: [function (_dereq_, module, exports) { /* global window */ var graphlib if (_dereq_) { try { graphlib = _dereq_('graphlib') } catch (e) {} } if (!graphlib) { graphlib = window.graphlib } module.exports = graphlib }, {'graphlib': 30}], 11: [function (_dereq_, module, exports) { module.exports = { node: _dereq_('./intersect-node'), circle: _dereq_('./intersect-circle'), ellipse: _dereq_('./intersect-ellipse'), polygon: _dereq_('./intersect-polygon'), rect: _dereq_('./intersect-rect') } }, {'./intersect-circle': 12, './intersect-ellipse': 13, './intersect-node': 15, './intersect-polygon': 16, './intersect-rect': 17}], 12: [function (_dereq_, module, exports) { var intersectEllipse = _dereq_('./intersect-ellipse') module.exports = intersectCircle function intersectCircle (node, rx, point) { return intersectEllipse(node, rx, rx, point) } }, {'./intersect-ellipse': 13}], 13: [function (_dereq_, 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} } }, {}], 14: [function (_dereq_, 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 } }, {}], 15: [function (_dereq_, module, exports) { module.exports = intersectNode function intersectNode (node, point) { return node.intersect(point) } }, {}], 16: [function (_dereq_, module, exports) { var intersectLine = _dereq_('./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': 14}], 17: [function (_dereq_, 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} } }, {}], 18: [function (_dereq_, module, exports) { var util = _dereq_('../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': 28}], 19: [function (_dereq_, module, exports) { var addTextLabel = _dereq_('./add-text-label'), addHtmlLabel = _dereq_('./add-html-label'), addSVGLabel = _dereq_('./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': 18, './add-svg-label': 20, './add-text-label': 21}], 20: [function (_dereq_, module, exports) { var util = _dereq_('../util') module.exports = addSVGLabel function addSVGLabel (root, node) { var domNode = root domNode.node().appendChild(node.label) util.applyStyle(domNode, node.labelStyle) return domNode } }, {'../util': 28}], 21: [function (_dereq_, module, exports) { var util = _dereq_('../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': 28}], 22: [function (_dereq_, module, exports) { /* global window */ var lodash if (_dereq_) { try { lodash = _dereq_('lodash') } catch (e) {} } if (!lodash) { lodash = window._ } module.exports = lodash }, {'lodash': 50}], 23: [function (_dereq_, module, exports) { 'use strict' var util = _dereq_('./util'), d3 = _dereq_('./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': 8, './util': 28}], 24: [function (_dereq_, module, exports) { 'use strict' var util = _dereq_('./util'), d3 = _dereq_('./d3'), _ = _dereq_('./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': 8, './lodash': 22, './util': 28}], 25: [function (_dereq_, module, exports) { 'use strict' var util = _dereq_('./util'), d3 = _dereq_('./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': 8, './util': 28}], 26: [function (_dereq_, module, exports) { var _ = _dereq_('./lodash'), layout = _dereq_('./dagre').layout module.exports = render // This design is based on http://bost.ocks.org/mike/chart/. function render () { var createNodes = _dereq_('./create-nodes'), createClusters = _dereq_('./create-clusters'), createEdgeLabels = _dereq_('./create-edge-labels'), createEdgePaths = _dereq_('./create-edge-paths'), positionNodes = _dereq_('./position-nodes'), positionEdgeLabels = _dereq_('./position-edge-labels'), positionClusters = _dereq_('./position-clusters'), shapes = _dereq_('./shapes'), arrows = _dereq_('./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': 3, './create-clusters': 4, './create-edge-labels': 5, './create-edge-paths': 6, './create-nodes': 7, './dagre': 9, './lodash': 22, './position-clusters': 23, './position-edge-labels': 24, './position-nodes': 25, './shapes': 27}], 27: [function (_dereq_, module, exports) { 'use strict' var intersectRect = _dereq_('./intersect/intersect-rect'), intersectEllipse = _dereq_('./intersect/intersect-ellipse'), intersectCircle = _dereq_('./intersect/intersect-circle'), intersectPolygon = _dereq_('./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': 12, './intersect/intersect-ellipse': 13, './intersect/intersect-polygon': 16, './intersect/intersect-rect': 17}], 28: [function (_dereq_, module, exports) { var _ = _dereq_('./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': 22}], 29: [function (_dereq_, module, exports) { module.exports = '0.4.10' }, {}], 30: [function (_dereq_, 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 = _dereq_('./lib') module.exports = { Graph: lib.Graph, json: _dereq_('./lib/json'), alg: _dereq_('./lib/alg'), version: lib.version } }, {'./lib': 46, './lib/alg': 37, './lib/json': 47}], 31: [function (_dereq_, module, exports) { var _ = _dereq_('../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': 48}], 32: [function (_dereq_, module, exports) { var _ = _dereq_('../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': 48}], 33: [function (_dereq_, module, exports) { var dijkstra = _dereq_('./dijkstra'), _ = _dereq_('../lodash') module.exports = dijkstraAll function dijkstraAll (g, weightFunc, edgeFunc) { return _.transform(g.nodes(), function (acc, v) { acc[v] = dijkstra(g, v, weightFunc, edgeFunc) }, {}) } }, {'../lodash': 48, './dijkstra': 34}], 34: [function (_dereq_, module, exports) { var _ = _dereq_('../lodash'), PriorityQueue = _dereq_('../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': 44, '../lodash': 48}], 35: [function (_dereq_, module, exports) { var _ = _dereq_('../lodash'), tarjan = _dereq_('./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': 48, './tarjan': 42}], 36: [function (_dereq_, module, exports) { var _ = _dereq_('../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': 48}], 37: [function (_dereq_, module, exports) { module.exports = { components: _dereq_('./components'), dijkstra: _dereq_('./dijkstra'), dijkstraAll: _dereq_('./dijkstra-all'), findCycles: _dereq_('./find-cycles'), floydWarshall: _dereq_('./floyd-warshall'), isAcyclic: _dereq_('./is-acyclic'), postorder: _dereq_('./postorder'), preorder: _dereq_('./preorder'), prim: _dereq_('./prim'), tarjan: _dereq_('./tarjan'), topsort: _dereq_('./topsort') } }, {'./components': 31, './dijkstra': 34, './dijkstra-all': 33, './find-cycles': 35, './floyd-warshall': 36, './is-acyclic': 38, './postorder': 39, './preorder': 40, './prim': 41, './tarjan': 42, './topsort': 43}], 38: [function (_dereq_, module, exports) { var topsort = _dereq_('./topsort') module.exports = isAcyclic function isAcyclic (g) { try { topsort(g) } catch (e) { if (e instanceof topsort.CycleException) { return false } throw e } return true } }, {'./topsort': 43}], 39: [function (_dereq_, module, exports) { var dfs = _dereq_('./dfs') module.exports = postorder function postorder (g, vs) { return dfs(g, vs, 'post') } }, {'./dfs': 32}], 40: [function (_dereq_, module, exports) { var dfs = _dereq_('./dfs') module.exports = preorder function preorder (g, vs) { return dfs(g, vs, 'pre') } }, {'./dfs': 32}], 41: [function (_dereq_, module, exports) { var _ = _dereq_('../lodash'), Graph = _dereq_('../graph'), PriorityQueue = _dereq_('../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': 44, '../graph': 45, '../lodash': 48}], 42: [function (_dereq_, module, exports) { var _ = _dereq_('../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': 48}], 43: [function (_dereq_, module, exports) { var _ = _dereq_('../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': 48}], 44: [function (_dereq_, module, exports) { var _ = _dereq_('../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': 48}], 45: [function (_dereq_, module, exports) { 'use strict' var _ = _dereq_('./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': 48}], 46: [function (_dereq_, module, exports) { // Includes only the "core" of graphlib module.exports = { Graph: _dereq_('./graph'), version: _dereq_('./version') } }, {'./graph': 45, './version': 49}], 47: [function (_dereq_, module, exports) { var _ = _dereq_('./lodash'), Graph = _dereq_('./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': 45, './lodash': 48}], 48: [function (_dereq_, module, exports) { /* global window */ var lodash if (typeof _dereq_ === 'function') { try { lodash = _dereq_('lodash') } catch (e) {} } if (!lodash) { lodash = window._ } module.exports = lodash }, {'lodash': 50}], 49: [function (_dereq_, module, exports) { module.exports = '1.0.7' }, {}], 50: [function (_dereq_, module, exports) { (function (global) { /** * @license * lodash 3.10.1 (Custom Build) * Build: `lodash modern -d -o ./index.js` * Copyright 2012-2015 The Dojo Foundation * Based on Underscore.js 1.8.3 * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT 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 '

' + func(text) + '

'; * }); * * p('fred, barney, & pebbles'); * // => '

fred, barney, & pebbles

' */ 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(''); * // => 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 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('<%- value %>'); * compiled({ 'value': '