!(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': '