11c0c24c7441325f1823730a87ed3266e67215b3
kate
  Wed Oct 21 11:37:11 2015 -0700
Checking in graph exploratory work (JS D3) to save it (in a branch) before whacking. refs #15645

diff --git src/hg/js/d3plus.gtex.js src/hg/js/d3plus.gtex.js
new file mode 100644
index 0000000..4f2ec98
--- /dev/null
+++ src/hg/js/d3plus.gtex.js
@@ -0,0 +1,33973 @@
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+/*!
+ * The buffer module from node.js, for the browser.
+ *
+ * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
+ * @license  MIT
+ */
+
+var base64 = require('base64-js')
+var ieee754 = require('ieee754')
+var isArray = require('is-array')
+
+exports.Buffer = Buffer
+exports.SlowBuffer = SlowBuffer
+exports.INSPECT_MAX_BYTES = 50
+Buffer.poolSize = 8192 // not used by this implementation
+
+var rootParent = {}
+
+/**
+ * If `Buffer.TYPED_ARRAY_SUPPORT`:
+ *   === true    Use Uint8Array implementation (fastest)
+ *   === false   Use Object implementation (most compatible, even IE6)
+ *
+ * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
+ * Opera 11.6+, iOS 4.2+.
+ *
+ * Due to various browser bugs, sometimes the Object implementation will be used even
+ * when the browser supports typed arrays.
+ *
+ * Note:
+ *
+ *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
+ *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
+ *
+ *   - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property
+ *     on objects.
+ *
+ *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
+ *
+ *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
+ *     incorrect length in some situations.
+
+ * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
+ * get the Object implementation, which is slower but behaves correctly.
+ */
+Buffer.TYPED_ARRAY_SUPPORT = (function () {
+  function Bar () {}
+  try {
+    var arr = new Uint8Array(1)
+    arr.foo = function () { return 42 }
+    arr.constructor = Bar
+    return arr.foo() === 42 && // typed array instances can be augmented
+        arr.constructor === Bar && // constructor can be set
+        typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
+        arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
+  } catch (e) {
+    return false
+  }
+})()
+
+function kMaxLength () {
+  return Buffer.TYPED_ARRAY_SUPPORT
+    ? 0x7fffffff
+    : 0x3fffffff
+}
+
+/**
+ * Class: Buffer
+ * =============
+ *
+ * The Buffer constructor returns instances of `Uint8Array` that are augmented
+ * with function properties for all the node `Buffer` API functions. We use
+ * `Uint8Array` so that square bracket notation works as expected -- it returns
+ * a single octet.
+ *
+ * By augmenting the instances, we can avoid modifying the `Uint8Array`
+ * prototype.
+ */
+function Buffer (arg) {
+  if (!(this instanceof Buffer)) {
+    // Avoid going through an ArgumentsAdaptorTrampoline in the common case.
+    if (arguments.length > 1) return new Buffer(arg, arguments[1])
+    return new Buffer(arg)
+  }
+
+  this.length = 0
+  this.parent = undefined
+
+  // Common case.
+  if (typeof arg === 'number') {
+    return fromNumber(this, arg)
+  }
+
+  // Slightly less common case.
+  if (typeof arg === 'string') {
+    return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8')
+  }
+
+  // Unusual.
+  return fromObject(this, arg)
+}
+
+function fromNumber (that, length) {
+  that = allocate(that, length < 0 ? 0 : checked(length) | 0)
+  if (!Buffer.TYPED_ARRAY_SUPPORT) {
+    for (var i = 0; i < length; i++) {
+      that[i] = 0
+    }
+  }
+  return that
+}
+
+function fromString (that, string, encoding) {
+  if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8'
+
+  // Assumption: byteLength() return value is always < kMaxLength.
+  var length = byteLength(string, encoding) | 0
+  that = allocate(that, length)
+
+  that.write(string, encoding)
+  return that
+}
+
+function fromObject (that, object) {
+  if (Buffer.isBuffer(object)) return fromBuffer(that, object)
+
+  if (isArray(object)) return fromArray(that, object)
+
+  if (object == null) {
+    throw new TypeError('must start with number, buffer, array or string')
+  }
+
+  if (typeof ArrayBuffer !== 'undefined') {
+    if (object.buffer instanceof ArrayBuffer) {
+      return fromTypedArray(that, object)
+    }
+    if (object instanceof ArrayBuffer) {
+      return fromArrayBuffer(that, object)
+    }
+  }
+
+  if (object.length) return fromArrayLike(that, object)
+
+  return fromJsonObject(that, object)
+}
+
+function fromBuffer (that, buffer) {
+  var length = checked(buffer.length) | 0
+  that = allocate(that, length)
+  buffer.copy(that, 0, 0, length)
+  return that
+}
+
+function fromArray (that, array) {
+  var length = checked(array.length) | 0
+  that = allocate(that, length)
+  for (var i = 0; i < length; i += 1) {
+    that[i] = array[i] & 255
+  }
+  return that
+}
+
+// Duplicate of fromArray() to keep fromArray() monomorphic.
+function fromTypedArray (that, array) {
+  var length = checked(array.length) | 0
+  that = allocate(that, length)
+  // Truncating the elements is probably not what people expect from typed
+  // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior
+  // of the old Buffer constructor.
+  for (var i = 0; i < length; i += 1) {
+    that[i] = array[i] & 255
+  }
+  return that
+}
+
+function fromArrayBuffer (that, array) {
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    // Return an augmented `Uint8Array` instance, for best performance
+    array.byteLength
+    that = Buffer._augment(new Uint8Array(array))
+  } else {
+    // Fallback: Return an object instance of the Buffer class
+    that = fromTypedArray(that, new Uint8Array(array))
+  }
+  return that
+}
+
+function fromArrayLike (that, array) {
+  var length = checked(array.length) | 0
+  that = allocate(that, length)
+  for (var i = 0; i < length; i += 1) {
+    that[i] = array[i] & 255
+  }
+  return that
+}
+
+// Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object.
+// Returns a zero-length buffer for inputs that don't conform to the spec.
+function fromJsonObject (that, object) {
+  var array
+  var length = 0
+
+  if (object.type === 'Buffer' && isArray(object.data)) {
+    array = object.data
+    length = checked(array.length) | 0
+  }
+  that = allocate(that, length)
+
+  for (var i = 0; i < length; i += 1) {
+    that[i] = array[i] & 255
+  }
+  return that
+}
+
+function allocate (that, length) {
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    // Return an augmented `Uint8Array` instance, for best performance
+    that = Buffer._augment(new Uint8Array(length))
+  } else {
+    // Fallback: Return an object instance of the Buffer class
+    that.length = length
+    that._isBuffer = true
+  }
+
+  var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1
+  if (fromPool) that.parent = rootParent
+
+  return that
+}
+
+function checked (length) {
+  // Note: cannot use `length < kMaxLength` here because that fails when
+  // length is NaN (which is otherwise coerced to zero.)
+  if (length >= kMaxLength()) {
+    throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
+                         'size: 0x' + kMaxLength().toString(16) + ' bytes')
+  }
+  return length | 0
+}
+
+function SlowBuffer (subject, encoding) {
+  if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding)
+
+  var buf = new Buffer(subject, encoding)
+  delete buf.parent
+  return buf
+}
+
+Buffer.isBuffer = function isBuffer (b) {
+  return !!(b != null && b._isBuffer)
+}
+
+Buffer.compare = function compare (a, b) {
+  if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
+    throw new TypeError('Arguments must be Buffers')
+  }
+
+  if (a === b) return 0
+
+  var x = a.length
+  var y = b.length
+
+  var i = 0
+  var len = Math.min(x, y)
+  while (i < len) {
+    if (a[i] !== b[i]) break
+
+    ++i
+  }
+
+  if (i !== len) {
+    x = a[i]
+    y = b[i]
+  }
+
+  if (x < y) return -1
+  if (y < x) return 1
+  return 0
+}
+
+Buffer.isEncoding = function isEncoding (encoding) {
+  switch (String(encoding).toLowerCase()) {
+    case 'hex':
+    case 'utf8':
+    case 'utf-8':
+    case 'ascii':
+    case 'binary':
+    case 'base64':
+    case 'raw':
+    case 'ucs2':
+    case 'ucs-2':
+    case 'utf16le':
+    case 'utf-16le':
+      return true
+    default:
+      return false
+  }
+}
+
+Buffer.concat = function concat (list, length) {
+  if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.')
+
+  if (list.length === 0) {
+    return new Buffer(0)
+  }
+
+  var i
+  if (length === undefined) {
+    length = 0
+    for (i = 0; i < list.length; i++) {
+      length += list[i].length
+    }
+  }
+
+  var buf = new Buffer(length)
+  var pos = 0
+  for (i = 0; i < list.length; i++) {
+    var item = list[i]
+    item.copy(buf, pos)
+    pos += item.length
+  }
+  return buf
+}
+
+function byteLength (string, encoding) {
+  if (typeof string !== 'string') string = '' + string
+
+  var len = string.length
+  if (len === 0) return 0
+
+  // Use a for loop to avoid recursion
+  var loweredCase = false
+  for (;;) {
+    switch (encoding) {
+      case 'ascii':
+      case 'binary':
+      // Deprecated
+      case 'raw':
+      case 'raws':
+        return len
+      case 'utf8':
+      case 'utf-8':
+        return utf8ToBytes(string).length
+      case 'ucs2':
+      case 'ucs-2':
+      case 'utf16le':
+      case 'utf-16le':
+        return len * 2
+      case 'hex':
+        return len >>> 1
+      case 'base64':
+        return base64ToBytes(string).length
+      default:
+        if (loweredCase) return utf8ToBytes(string).length // assume utf8
+        encoding = ('' + encoding).toLowerCase()
+        loweredCase = true
+    }
+  }
+}
+Buffer.byteLength = byteLength
+
+// pre-set for values that may exist in the future
+Buffer.prototype.length = undefined
+Buffer.prototype.parent = undefined
+
+function slowToString (encoding, start, end) {
+  var loweredCase = false
+
+  start = start | 0
+  end = end === undefined || end === Infinity ? this.length : end | 0
+
+  if (!encoding) encoding = 'utf8'
+  if (start < 0) start = 0
+  if (end > this.length) end = this.length
+  if (end <= start) return ''
+
+  while (true) {
+    switch (encoding) {
+      case 'hex':
+        return hexSlice(this, start, end)
+
+      case 'utf8':
+      case 'utf-8':
+        return utf8Slice(this, start, end)
+
+      case 'ascii':
+        return asciiSlice(this, start, end)
+
+      case 'binary':
+        return binarySlice(this, start, end)
+
+      case 'base64':
+        return base64Slice(this, start, end)
+
+      case 'ucs2':
+      case 'ucs-2':
+      case 'utf16le':
+      case 'utf-16le':
+        return utf16leSlice(this, start, end)
+
+      default:
+        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
+        encoding = (encoding + '').toLowerCase()
+        loweredCase = true
+    }
+  }
+}
+
+Buffer.prototype.toString = function toString () {
+  var length = this.length | 0
+  if (length === 0) return ''
+  if (arguments.length === 0) return utf8Slice(this, 0, length)
+  return slowToString.apply(this, arguments)
+}
+
+Buffer.prototype.equals = function equals (b) {
+  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
+  if (this === b) return true
+  return Buffer.compare(this, b) === 0
+}
+
+Buffer.prototype.inspect = function inspect () {
+  var str = ''
+  var max = exports.INSPECT_MAX_BYTES
+  if (this.length > 0) {
+    str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
+    if (this.length > max) str += ' ... '
+  }
+  return '<Buffer ' + str + '>'
+}
+
+Buffer.prototype.compare = function compare (b) {
+  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
+  if (this === b) return 0
+  return Buffer.compare(this, b)
+}
+
+Buffer.prototype.indexOf = function indexOf (val, byteOffset) {
+  if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff
+  else if (byteOffset < -0x80000000) byteOffset = -0x80000000
+  byteOffset >>= 0
+
+  if (this.length === 0) return -1
+  if (byteOffset >= this.length) return -1
+
+  // Negative offsets start from the end of the buffer
+  if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0)
+
+  if (typeof val === 'string') {
+    if (val.length === 0) return -1 // special case: looking for empty string always fails
+    return String.prototype.indexOf.call(this, val, byteOffset)
+  }
+  if (Buffer.isBuffer(val)) {
+    return arrayIndexOf(this, val, byteOffset)
+  }
+  if (typeof val === 'number') {
+    if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') {
+      return Uint8Array.prototype.indexOf.call(this, val, byteOffset)
+    }
+    return arrayIndexOf(this, [ val ], byteOffset)
+  }
+
+  function arrayIndexOf (arr, val, byteOffset) {
+    var foundIndex = -1
+    for (var i = 0; byteOffset + i < arr.length; i++) {
+      if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) {
+        if (foundIndex === -1) foundIndex = i
+        if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex
+      } else {
+        foundIndex = -1
+      }
+    }
+    return -1
+  }
+
+  throw new TypeError('val must be string, number or Buffer')
+}
+
+// `get` is deprecated
+Buffer.prototype.get = function get (offset) {
+  console.log('.get() is deprecated. Access using array indexes instead.')
+  return this.readUInt8(offset)
+}
+
+// `set` is deprecated
+Buffer.prototype.set = function set (v, offset) {
+  console.log('.set() is deprecated. Access using array indexes instead.')
+  return this.writeUInt8(v, offset)
+}
+
+function hexWrite (buf, string, offset, length) {
+  offset = Number(offset) || 0
+  var remaining = buf.length - offset
+  if (!length) {
+    length = remaining
+  } else {
+    length = Number(length)
+    if (length > remaining) {
+      length = remaining
+    }
+  }
+
+  // must be an even number of digits
+  var strLen = string.length
+  if (strLen % 2 !== 0) throw new Error('Invalid hex string')
+
+  if (length > strLen / 2) {
+    length = strLen / 2
+  }
+  for (var i = 0; i < length; i++) {
+    var parsed = parseInt(string.substr(i * 2, 2), 16)
+    if (isNaN(parsed)) throw new Error('Invalid hex string')
+    buf[offset + i] = parsed
+  }
+  return i
+}
+
+function utf8Write (buf, string, offset, length) {
+  return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
+}
+
+function asciiWrite (buf, string, offset, length) {
+  return blitBuffer(asciiToBytes(string), buf, offset, length)
+}
+
+function binaryWrite (buf, string, offset, length) {
+  return asciiWrite(buf, string, offset, length)
+}
+
+function base64Write (buf, string, offset, length) {
+  return blitBuffer(base64ToBytes(string), buf, offset, length)
+}
+
+function ucs2Write (buf, string, offset, length) {
+  return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
+}
+
+Buffer.prototype.write = function write (string, offset, length, encoding) {
+  // Buffer#write(string)
+  if (offset === undefined) {
+    encoding = 'utf8'
+    length = this.length
+    offset = 0
+  // Buffer#write(string, encoding)
+  } else if (length === undefined && typeof offset === 'string') {
+    encoding = offset
+    length = this.length
+    offset = 0
+  // Buffer#write(string, offset[, length][, encoding])
+  } else if (isFinite(offset)) {
+    offset = offset | 0
+    if (isFinite(length)) {
+      length = length | 0
+      if (encoding === undefined) encoding = 'utf8'
+    } else {
+      encoding = length
+      length = undefined
+    }
+  // legacy write(string, encoding, offset, length) - remove in v0.13
+  } else {
+    var swap = encoding
+    encoding = offset
+    offset = length | 0
+    length = swap
+  }
+
+  var remaining = this.length - offset
+  if (length === undefined || length > remaining) length = remaining
+
+  if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
+    throw new RangeError('attempt to write outside buffer bounds')
+  }
+
+  if (!encoding) encoding = 'utf8'
+
+  var loweredCase = false
+  for (;;) {
+    switch (encoding) {
+      case 'hex':
+        return hexWrite(this, string, offset, length)
+
+      case 'utf8':
+      case 'utf-8':
+        return utf8Write(this, string, offset, length)
+
+      case 'ascii':
+        return asciiWrite(this, string, offset, length)
+
+      case 'binary':
+        return binaryWrite(this, string, offset, length)
+
+      case 'base64':
+        // Warning: maxLength not taken into account in base64Write
+        return base64Write(this, string, offset, length)
+
+      case 'ucs2':
+      case 'ucs-2':
+      case 'utf16le':
+      case 'utf-16le':
+        return ucs2Write(this, string, offset, length)
+
+      default:
+        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
+        encoding = ('' + encoding).toLowerCase()
+        loweredCase = true
+    }
+  }
+}
+
+Buffer.prototype.toJSON = function toJSON () {
+  return {
+    type: 'Buffer',
+    data: Array.prototype.slice.call(this._arr || this, 0)
+  }
+}
+
+function base64Slice (buf, start, end) {
+  if (start === 0 && end === buf.length) {
+    return base64.fromByteArray(buf)
+  } else {
+    return base64.fromByteArray(buf.slice(start, end))
+  }
+}
+
+function utf8Slice (buf, start, end) {
+  end = Math.min(buf.length, end)
+  var firstByte
+  var secondByte
+  var thirdByte
+  var fourthByte
+  var bytesPerSequence
+  var tempCodePoint
+  var codePoint
+  var res = []
+  var i = start
+
+  for (; i < end; i += bytesPerSequence) {
+    firstByte = buf[i]
+    codePoint = 0xFFFD
+
+    if (firstByte > 0xEF) {
+      bytesPerSequence = 4
+    } else if (firstByte > 0xDF) {
+      bytesPerSequence = 3
+    } else if (firstByte > 0xBF) {
+      bytesPerSequence = 2
+    } else {
+      bytesPerSequence = 1
+    }
+
+    if (i + bytesPerSequence <= end) {
+      switch (bytesPerSequence) {
+        case 1:
+          if (firstByte < 0x80) {
+            codePoint = firstByte
+          }
+          break
+        case 2:
+          secondByte = buf[i + 1]
+          if ((secondByte & 0xC0) === 0x80) {
+            tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
+            if (tempCodePoint > 0x7F) {
+              codePoint = tempCodePoint
+            }
+          }
+          break
+        case 3:
+          secondByte = buf[i + 1]
+          thirdByte = buf[i + 2]
+          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
+            tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
+            if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
+              codePoint = tempCodePoint
+            }
+          }
+          break
+        case 4:
+          secondByte = buf[i + 1]
+          thirdByte = buf[i + 2]
+          fourthByte = buf[i + 3]
+          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
+            tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
+            if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
+              codePoint = tempCodePoint
+            }
+          }
+      }
+    }
+
+    if (codePoint === 0xFFFD) {
+      // we generated an invalid codePoint so make sure to only advance by 1 byte
+      bytesPerSequence = 1
+    } else if (codePoint > 0xFFFF) {
+      // encode to utf16 (surrogate pair dance)
+      codePoint -= 0x10000
+      res.push(codePoint >>> 10 & 0x3FF | 0xD800)
+      codePoint = 0xDC00 | codePoint & 0x3FF
+    }
+
+    res.push(codePoint)
+  }
+
+  return String.fromCharCode.apply(String, res)
+}
+
+function asciiSlice (buf, start, end) {
+  var ret = ''
+  end = Math.min(buf.length, end)
+
+  for (var i = start; i < end; i++) {
+    ret += String.fromCharCode(buf[i] & 0x7F)
+  }
+  return ret
+}
+
+function binarySlice (buf, start, end) {
+  var ret = ''
+  end = Math.min(buf.length, end)
+
+  for (var i = start; i < end; i++) {
+    ret += String.fromCharCode(buf[i])
+  }
+  return ret
+}
+
+function hexSlice (buf, start, end) {
+  var len = buf.length
+
+  if (!start || start < 0) start = 0
+  if (!end || end < 0 || end > len) end = len
+
+  var out = ''
+  for (var i = start; i < end; i++) {
+    out += toHex(buf[i])
+  }
+  return out
+}
+
+function utf16leSlice (buf, start, end) {
+  var bytes = buf.slice(start, end)
+  var res = ''
+  for (var i = 0; i < bytes.length; i += 2) {
+    res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
+  }
+  return res
+}
+
+Buffer.prototype.slice = function slice (start, end) {
+  var len = this.length
+  start = ~~start
+  end = end === undefined ? len : ~~end
+
+  if (start < 0) {
+    start += len
+    if (start < 0) start = 0
+  } else if (start > len) {
+    start = len
+  }
+
+  if (end < 0) {
+    end += len
+    if (end < 0) end = 0
+  } else if (end > len) {
+    end = len
+  }
+
+  if (end < start) end = start
+
+  var newBuf
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    newBuf = Buffer._augment(this.subarray(start, end))
+  } else {
+    var sliceLen = end - start
+    newBuf = new Buffer(sliceLen, undefined)
+    for (var i = 0; i < sliceLen; i++) {
+      newBuf[i] = this[i + start]
+    }
+  }
+
+  if (newBuf.length) newBuf.parent = this.parent || this
+
+  return newBuf
+}
+
+/*
+ * Need to make sure that buffer isn't trying to write out of bounds.
+ */
+function checkOffset (offset, ext, length) {
+  if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
+  if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
+}
+
+Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
+  offset = offset | 0
+  byteLength = byteLength | 0
+  if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+  var val = this[offset]
+  var mul = 1
+  var i = 0
+  while (++i < byteLength && (mul *= 0x100)) {
+    val += this[offset + i] * mul
+  }
+
+  return val
+}
+
+Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
+  offset = offset | 0
+  byteLength = byteLength | 0
+  if (!noAssert) {
+    checkOffset(offset, byteLength, this.length)
+  }
+
+  var val = this[offset + --byteLength]
+  var mul = 1
+  while (byteLength > 0 && (mul *= 0x100)) {
+    val += this[offset + --byteLength] * mul
+  }
+
+  return val
+}
+
+Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 1, this.length)
+  return this[offset]
+}
+
+Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 2, this.length)
+  return this[offset] | (this[offset + 1] << 8)
+}
+
+Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 2, this.length)
+  return (this[offset] << 8) | this[offset + 1]
+}
+
+Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 4, this.length)
+
+  return ((this[offset]) |
+      (this[offset + 1] << 8) |
+      (this[offset + 2] << 16)) +
+      (this[offset + 3] * 0x1000000)
+}
+
+Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 4, this.length)
+
+  return (this[offset] * 0x1000000) +
+    ((this[offset + 1] << 16) |
+    (this[offset + 2] << 8) |
+    this[offset + 3])
+}
+
+Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
+  offset = offset | 0
+  byteLength = byteLength | 0
+  if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+  var val = this[offset]
+  var mul = 1
+  var i = 0
+  while (++i < byteLength && (mul *= 0x100)) {
+    val += this[offset + i] * mul
+  }
+  mul *= 0x80
+
+  if (val >= mul) val -= Math.pow(2, 8 * byteLength)
+
+  return val
+}
+
+Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
+  offset = offset | 0
+  byteLength = byteLength | 0
+  if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+  var i = byteLength
+  var mul = 1
+  var val = this[offset + --i]
+  while (i > 0 && (mul *= 0x100)) {
+    val += this[offset + --i] * mul
+  }
+  mul *= 0x80
+
+  if (val >= mul) val -= Math.pow(2, 8 * byteLength)
+
+  return val
+}
+
+Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 1, this.length)
+  if (!(this[offset] & 0x80)) return (this[offset])
+  return ((0xff - this[offset] + 1) * -1)
+}
+
+Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 2, this.length)
+  var val = this[offset] | (this[offset + 1] << 8)
+  return (val & 0x8000) ? val | 0xFFFF0000 : val
+}
+
+Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 2, this.length)
+  var val = this[offset + 1] | (this[offset] << 8)
+  return (val & 0x8000) ? val | 0xFFFF0000 : val
+}
+
+Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 4, this.length)
+
+  return (this[offset]) |
+    (this[offset + 1] << 8) |
+    (this[offset + 2] << 16) |
+    (this[offset + 3] << 24)
+}
+
+Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 4, this.length)
+
+  return (this[offset] << 24) |
+    (this[offset + 1] << 16) |
+    (this[offset + 2] << 8) |
+    (this[offset + 3])
+}
+
+Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 4, this.length)
+  return ieee754.read(this, offset, true, 23, 4)
+}
+
+Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 4, this.length)
+  return ieee754.read(this, offset, false, 23, 4)
+}
+
+Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 8, this.length)
+  return ieee754.read(this, offset, true, 52, 8)
+}
+
+Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
+  if (!noAssert) checkOffset(offset, 8, this.length)
+  return ieee754.read(this, offset, false, 52, 8)
+}
+
+function checkInt (buf, value, offset, ext, max, min) {
+  if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
+  if (value > max || value < min) throw new RangeError('value is out of bounds')
+  if (offset + ext > buf.length) throw new RangeError('index out of range')
+}
+
+Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
+  value = +value
+  offset = offset | 0
+  byteLength = byteLength | 0
+  if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
+
+  var mul = 1
+  var i = 0
+  this[offset] = value & 0xFF
+  while (++i < byteLength && (mul *= 0x100)) {
+    this[offset + i] = (value / mul) & 0xFF
+  }
+
+  return offset + byteLength
+}
+
+Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
+  value = +value
+  offset = offset | 0
+  byteLength = byteLength | 0
+  if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
+
+  var i = byteLength - 1
+  var mul = 1
+  this[offset + i] = value & 0xFF
+  while (--i >= 0 && (mul *= 0x100)) {
+    this[offset + i] = (value / mul) & 0xFF
+  }
+
+  return offset + byteLength
+}
+
+Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
+  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
+  this[offset] = value
+  return offset + 1
+}
+
+function objectWriteUInt16 (buf, value, offset, littleEndian) {
+  if (value < 0) value = 0xffff + value + 1
+  for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
+    buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
+      (littleEndian ? i : 1 - i) * 8
+  }
+}
+
+Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    this[offset] = value
+    this[offset + 1] = (value >>> 8)
+  } else {
+    objectWriteUInt16(this, value, offset, true)
+  }
+  return offset + 2
+}
+
+Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    this[offset] = (value >>> 8)
+    this[offset + 1] = value
+  } else {
+    objectWriteUInt16(this, value, offset, false)
+  }
+  return offset + 2
+}
+
+function objectWriteUInt32 (buf, value, offset, littleEndian) {
+  if (value < 0) value = 0xffffffff + value + 1
+  for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
+    buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
+  }
+}
+
+Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    this[offset + 3] = (value >>> 24)
+    this[offset + 2] = (value >>> 16)
+    this[offset + 1] = (value >>> 8)
+    this[offset] = value
+  } else {
+    objectWriteUInt32(this, value, offset, true)
+  }
+  return offset + 4
+}
+
+Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    this[offset] = (value >>> 24)
+    this[offset + 1] = (value >>> 16)
+    this[offset + 2] = (value >>> 8)
+    this[offset + 3] = value
+  } else {
+    objectWriteUInt32(this, value, offset, false)
+  }
+  return offset + 4
+}
+
+Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) {
+    var limit = Math.pow(2, 8 * byteLength - 1)
+
+    checkInt(this, value, offset, byteLength, limit - 1, -limit)
+  }
+
+  var i = 0
+  var mul = 1
+  var sub = value < 0 ? 1 : 0
+  this[offset] = value & 0xFF
+  while (++i < byteLength && (mul *= 0x100)) {
+    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
+  }
+
+  return offset + byteLength
+}
+
+Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) {
+    var limit = Math.pow(2, 8 * byteLength - 1)
+
+    checkInt(this, value, offset, byteLength, limit - 1, -limit)
+  }
+
+  var i = byteLength - 1
+  var mul = 1
+  var sub = value < 0 ? 1 : 0
+  this[offset + i] = value & 0xFF
+  while (--i >= 0 && (mul *= 0x100)) {
+    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
+  }
+
+  return offset + byteLength
+}
+
+Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
+  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
+  if (value < 0) value = 0xff + value + 1
+  this[offset] = value
+  return offset + 1
+}
+
+Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    this[offset] = value
+    this[offset + 1] = (value >>> 8)
+  } else {
+    objectWriteUInt16(this, value, offset, true)
+  }
+  return offset + 2
+}
+
+Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    this[offset] = (value >>> 8)
+    this[offset + 1] = value
+  } else {
+    objectWriteUInt16(this, value, offset, false)
+  }
+  return offset + 2
+}
+
+Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    this[offset] = value
+    this[offset + 1] = (value >>> 8)
+    this[offset + 2] = (value >>> 16)
+    this[offset + 3] = (value >>> 24)
+  } else {
+    objectWriteUInt32(this, value, offset, true)
+  }
+  return offset + 4
+}
+
+Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
+  value = +value
+  offset = offset | 0
+  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
+  if (value < 0) value = 0xffffffff + value + 1
+  if (Buffer.TYPED_ARRAY_SUPPORT) {
+    this[offset] = (value >>> 24)
+    this[offset + 1] = (value >>> 16)
+    this[offset + 2] = (value >>> 8)
+    this[offset + 3] = value
+  } else {
+    objectWriteUInt32(this, value, offset, false)
+  }
+  return offset + 4
+}
+
+function checkIEEE754 (buf, value, offset, ext, max, min) {
+  if (value > max || value < min) throw new RangeError('value is out of bounds')
+  if (offset + ext > buf.length) throw new RangeError('index out of range')
+  if (offset < 0) throw new RangeError('index out of range')
+}
+
+function writeFloat (buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
+  }
+  ieee754.write(buf, value, offset, littleEndian, 23, 4)
+  return offset + 4
+}
+
+Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
+  return writeFloat(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
+  return writeFloat(this, value, offset, false, noAssert)
+}
+
+function writeDouble (buf, value, offset, littleEndian, noAssert) {
+  if (!noAssert) {
+    checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
+  }
+  ieee754.write(buf, value, offset, littleEndian, 52, 8)
+  return offset + 8
+}
+
+Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
+  return writeDouble(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
+  return writeDouble(this, value, offset, false, noAssert)
+}
+
+// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
+Buffer.prototype.copy = function copy (target, targetStart, start, end) {
+  if (!start) start = 0
+  if (!end && end !== 0) end = this.length
+  if (targetStart >= target.length) targetStart = target.length
+  if (!targetStart) targetStart = 0
+  if (end > 0 && end < start) end = start
+
+  // Copy 0 bytes; we're done
+  if (end === start) return 0
+  if (target.length === 0 || this.length === 0) return 0
+
+  // Fatal error conditions
+  if (targetStart < 0) {
+    throw new RangeError('targetStart out of bounds')
+  }
+  if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
+  if (end < 0) throw new RangeError('sourceEnd out of bounds')
+
+  // Are we oob?
+  if (end > this.length) end = this.length
+  if (target.length - targetStart < end - start) {
+    end = target.length - targetStart + start
+  }
+
+  var len = end - start
+  var i
+
+  if (this === target && start < targetStart && targetStart < end) {
+    // descending copy from end
+    for (i = len - 1; i >= 0; i--) {
+      target[i + targetStart] = this[i + start]
+    }
+  } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
+    // ascending copy from start
+    for (i = 0; i < len; i++) {
+      target[i + targetStart] = this[i + start]
+    }
+  } else {
+    target._set(this.subarray(start, start + len), targetStart)
+  }
+
+  return len
+}
+
+// fill(value, start=0, end=buffer.length)
+Buffer.prototype.fill = function fill (value, start, end) {
+  if (!value) value = 0
+  if (!start) start = 0
+  if (!end) end = this.length
+
+  if (end < start) throw new RangeError('end < start')
+
+  // Fill 0 bytes; we're done
+  if (end === start) return
+  if (this.length === 0) return
+
+  if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
+  if (end < 0 || end > this.length) throw new RangeError('end out of bounds')
+
+  var i
+  if (typeof value === 'number') {
+    for (i = start; i < end; i++) {
+      this[i] = value
+    }
+  } else {
+    var bytes = utf8ToBytes(value.toString())
+    var len = bytes.length
+    for (i = start; i < end; i++) {
+      this[i] = bytes[i % len]
+    }
+  }
+
+  return this
+}
+
+/**
+ * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
+ * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
+ */
+Buffer.prototype.toArrayBuffer = function toArrayBuffer () {
+  if (typeof Uint8Array !== 'undefined') {
+    if (Buffer.TYPED_ARRAY_SUPPORT) {
+      return (new Buffer(this)).buffer
+    } else {
+      var buf = new Uint8Array(this.length)
+      for (var i = 0, len = buf.length; i < len; i += 1) {
+        buf[i] = this[i]
+      }
+      return buf.buffer
+    }
+  } else {
+    throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
+  }
+}
+
+// HELPER FUNCTIONS
+// ================
+
+var BP = Buffer.prototype
+
+/**
+ * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
+ */
+Buffer._augment = function _augment (arr) {
+  arr.constructor = Buffer
+  arr._isBuffer = true
+
+  // save reference to original Uint8Array set method before overwriting
+  arr._set = arr.set
+
+  // deprecated
+  arr.get = BP.get
+  arr.set = BP.set
+
+  arr.write = BP.write
+  arr.toString = BP.toString
+  arr.toLocaleString = BP.toString
+  arr.toJSON = BP.toJSON
+  arr.equals = BP.equals
+  arr.compare = BP.compare
+  arr.indexOf = BP.indexOf
+  arr.copy = BP.copy
+  arr.slice = BP.slice
+  arr.readUIntLE = BP.readUIntLE
+  arr.readUIntBE = BP.readUIntBE
+  arr.readUInt8 = BP.readUInt8
+  arr.readUInt16LE = BP.readUInt16LE
+  arr.readUInt16BE = BP.readUInt16BE
+  arr.readUInt32LE = BP.readUInt32LE
+  arr.readUInt32BE = BP.readUInt32BE
+  arr.readIntLE = BP.readIntLE
+  arr.readIntBE = BP.readIntBE
+  arr.readInt8 = BP.readInt8
+  arr.readInt16LE = BP.readInt16LE
+  arr.readInt16BE = BP.readInt16BE
+  arr.readInt32LE = BP.readInt32LE
+  arr.readInt32BE = BP.readInt32BE
+  arr.readFloatLE = BP.readFloatLE
+  arr.readFloatBE = BP.readFloatBE
+  arr.readDoubleLE = BP.readDoubleLE
+  arr.readDoubleBE = BP.readDoubleBE
+  arr.writeUInt8 = BP.writeUInt8
+  arr.writeUIntLE = BP.writeUIntLE
+  arr.writeUIntBE = BP.writeUIntBE
+  arr.writeUInt16LE = BP.writeUInt16LE
+  arr.writeUInt16BE = BP.writeUInt16BE
+  arr.writeUInt32LE = BP.writeUInt32LE
+  arr.writeUInt32BE = BP.writeUInt32BE
+  arr.writeIntLE = BP.writeIntLE
+  arr.writeIntBE = BP.writeIntBE
+  arr.writeInt8 = BP.writeInt8
+  arr.writeInt16LE = BP.writeInt16LE
+  arr.writeInt16BE = BP.writeInt16BE
+  arr.writeInt32LE = BP.writeInt32LE
+  arr.writeInt32BE = BP.writeInt32BE
+  arr.writeFloatLE = BP.writeFloatLE
+  arr.writeFloatBE = BP.writeFloatBE
+  arr.writeDoubleLE = BP.writeDoubleLE
+  arr.writeDoubleBE = BP.writeDoubleBE
+  arr.fill = BP.fill
+  arr.inspect = BP.inspect
+  arr.toArrayBuffer = BP.toArrayBuffer
+
+  return arr
+}
+
+var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
+
+function base64clean (str) {
+  // Node strips out invalid characters like \n and \t from the string, base64-js does not
+  str = stringtrim(str).replace(INVALID_BASE64_RE, '')
+  // Node converts strings with length < 2 to ''
+  if (str.length < 2) return ''
+  // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
+  while (str.length % 4 !== 0) {
+    str = str + '='
+  }
+  return str
+}
+
+function stringtrim (str) {
+  if (str.trim) return str.trim()
+  return str.replace(/^\s+|\s+$/g, '')
+}
+
+function toHex (n) {
+  if (n < 16) return '0' + n.toString(16)
+  return n.toString(16)
+}
+
+function utf8ToBytes (string, units) {
+  units = units || Infinity
+  var codePoint
+  var length = string.length
+  var leadSurrogate = null
+  var bytes = []
+
+  for (var i = 0; i < length; i++) {
+    codePoint = string.charCodeAt(i)
+
+    // is surrogate component
+    if (codePoint > 0xD7FF && codePoint < 0xE000) {
+      // last char was a lead
+      if (!leadSurrogate) {
+        // no lead yet
+        if (codePoint > 0xDBFF) {
+          // unexpected trail
+          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+          continue
+
+        } else if (i + 1 === length) {
+          // unpaired lead
+          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+          continue
+        }
+
+        // valid lead
+        leadSurrogate = codePoint
+
+        continue
+      }
+
+      // 2 leads in a row
+      if (codePoint < 0xDC00) {
+        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+        leadSurrogate = codePoint
+        continue
+      }
+
+      // valid surrogate pair
+      codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000
+
+    } else if (leadSurrogate) {
+      // valid bmp char, but last char was a lead
+      if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+    }
+
+    leadSurrogate = null
+
+    // encode utf8
+    if (codePoint < 0x80) {
+      if ((units -= 1) < 0) break
+      bytes.push(codePoint)
+    } else if (codePoint < 0x800) {
+      if ((units -= 2) < 0) break
+      bytes.push(
+        codePoint >> 0x6 | 0xC0,
+        codePoint & 0x3F | 0x80
+      )
+    } else if (codePoint < 0x10000) {
+      if ((units -= 3) < 0) break
+      bytes.push(
+        codePoint >> 0xC | 0xE0,
+        codePoint >> 0x6 & 0x3F | 0x80,
+        codePoint & 0x3F | 0x80
+      )
+    } else if (codePoint < 0x110000) {
+      if ((units -= 4) < 0) break
+      bytes.push(
+        codePoint >> 0x12 | 0xF0,
+        codePoint >> 0xC & 0x3F | 0x80,
+        codePoint >> 0x6 & 0x3F | 0x80,
+        codePoint & 0x3F | 0x80
+      )
+    } else {
+      throw new Error('Invalid code point')
+    }
+  }
+
+  return bytes
+}
+
+function asciiToBytes (str) {
+  var byteArray = []
+  for (var i = 0; i < str.length; i++) {
+    // Node's code seems to be doing this and not & 0x7F..
+    byteArray.push(str.charCodeAt(i) & 0xFF)
+  }
+  return byteArray
+}
+
+function utf16leToBytes (str, units) {
+  var c, hi, lo
+  var byteArray = []
+  for (var i = 0; i < str.length; i++) {
+    if ((units -= 2) < 0) break
+
+    c = str.charCodeAt(i)
+    hi = c >> 8
+    lo = c % 256
+    byteArray.push(lo)
+    byteArray.push(hi)
+  }
+
+  return byteArray
+}
+
+function base64ToBytes (str) {
+  return base64.toByteArray(base64clean(str))
+}
+
+function blitBuffer (src, dst, offset, length) {
+  for (var i = 0; i < length; i++) {
+    if ((i + offset >= dst.length) || (i >= src.length)) break
+    dst[i + offset] = src[i]
+  }
+  return i
+}
+
+},{"base64-js":2,"ieee754":3,"is-array":4}],2:[function(require,module,exports){
+var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+
+;(function (exports) {
+	'use strict';
+
+  var Arr = (typeof Uint8Array !== 'undefined')
+    ? Uint8Array
+    : Array
+
+	var PLUS   = '+'.charCodeAt(0)
+	var SLASH  = '/'.charCodeAt(0)
+	var NUMBER = '0'.charCodeAt(0)
+	var LOWER  = 'a'.charCodeAt(0)
+	var UPPER  = 'A'.charCodeAt(0)
+	var PLUS_URL_SAFE = '-'.charCodeAt(0)
+	var SLASH_URL_SAFE = '_'.charCodeAt(0)
+
+	function decode (elt) {
+		var code = elt.charCodeAt(0)
+		if (code === PLUS ||
+		    code === PLUS_URL_SAFE)
+			return 62 // '+'
+		if (code === SLASH ||
+		    code === SLASH_URL_SAFE)
+			return 63 // '/'
+		if (code < NUMBER)
+			return -1 //no match
+		if (code < NUMBER + 10)
+			return code - NUMBER + 26 + 26
+		if (code < UPPER + 26)
+			return code - UPPER
+		if (code < LOWER + 26)
+			return code - LOWER + 26
+	}
+
+	function b64ToByteArray (b64) {
+		var i, j, l, tmp, placeHolders, arr
+
+		if (b64.length % 4 > 0) {
+			throw new Error('Invalid string. Length must be a multiple of 4')
+		}
+
+		// the number of equal signs (place holders)
+		// if there are two placeholders, than the two characters before it
+		// represent one byte
+		// if there is only one, then the three characters before it represent 2 bytes
+		// this is just a cheap hack to not do indexOf twice
+		var len = b64.length
+		placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
+
+		// base64 is 4/3 + up to two characters of the original data
+		arr = new Arr(b64.length * 3 / 4 - placeHolders)
+
+		// if there are placeholders, only get up to the last complete 4 chars
+		l = placeHolders > 0 ? b64.length - 4 : b64.length
+
+		var L = 0
+
+		function push (v) {
+			arr[L++] = v
+		}
+
+		for (i = 0, j = 0; i < l; i += 4, j += 3) {
+			tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
+			push((tmp & 0xFF0000) >> 16)
+			push((tmp & 0xFF00) >> 8)
+			push(tmp & 0xFF)
+		}
+
+		if (placeHolders === 2) {
+			tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
+			push(tmp & 0xFF)
+		} else if (placeHolders === 1) {
+			tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
+			push((tmp >> 8) & 0xFF)
+			push(tmp & 0xFF)
+		}
+
+		return arr
+	}
+
+	function uint8ToBase64 (uint8) {
+		var i,
+			extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
+			output = "",
+			temp, length
+
+		function encode (num) {
+			return lookup.charAt(num)
+		}
+
+		function tripletToBase64 (num) {
+			return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
+		}
+
+		// go through the array every three bytes, we'll deal with trailing stuff later
+		for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
+			temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
+			output += tripletToBase64(temp)
+		}
+
+		// pad the end with zeros, but make sure to not forget the extra bytes
+		switch (extraBytes) {
+			case 1:
+				temp = uint8[uint8.length - 1]
+				output += encode(temp >> 2)
+				output += encode((temp << 4) & 0x3F)
+				output += '=='
+				break
+			case 2:
+				temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
+				output += encode(temp >> 10)
+				output += encode((temp >> 4) & 0x3F)
+				output += encode((temp << 2) & 0x3F)
+				output += '='
+				break
+		}
+
+		return output
+	}
+
+	exports.toByteArray = b64ToByteArray
+	exports.fromByteArray = uint8ToBase64
+}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
+
+},{}],3:[function(require,module,exports){
+exports.read = function (buffer, offset, isLE, mLen, nBytes) {
+  var e, m
+  var eLen = nBytes * 8 - mLen - 1
+  var eMax = (1 << eLen) - 1
+  var eBias = eMax >> 1
+  var nBits = -7
+  var i = isLE ? (nBytes - 1) : 0
+  var d = isLE ? -1 : 1
+  var s = buffer[offset + i]
+
+  i += d
+
+  e = s & ((1 << (-nBits)) - 1)
+  s >>= (-nBits)
+  nBits += eLen
+  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
+
+  m = e & ((1 << (-nBits)) - 1)
+  e >>= (-nBits)
+  nBits += mLen
+  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
+
+  if (e === 0) {
+    e = 1 - eBias
+  } else if (e === eMax) {
+    return m ? NaN : ((s ? -1 : 1) * Infinity)
+  } else {
+    m = m + Math.pow(2, mLen)
+    e = e - eBias
+  }
+  return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
+}
+
+exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
+  var e, m, c
+  var eLen = nBytes * 8 - mLen - 1
+  var eMax = (1 << eLen) - 1
+  var eBias = eMax >> 1
+  var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
+  var i = isLE ? 0 : (nBytes - 1)
+  var d = isLE ? 1 : -1
+  var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
+
+  value = Math.abs(value)
+
+  if (isNaN(value) || value === Infinity) {
+    m = isNaN(value) ? 1 : 0
+    e = eMax
+  } else {
+    e = Math.floor(Math.log(value) / Math.LN2)
+    if (value * (c = Math.pow(2, -e)) < 1) {
+      e--
+      c *= 2
+    }
+    if (e + eBias >= 1) {
+      value += rt / c
+    } else {
+      value += rt * Math.pow(2, 1 - eBias)
+    }
+    if (value * c >= 2) {
+      e++
+      c /= 2
+    }
+
+    if (e + eBias >= eMax) {
+      m = 0
+      e = eMax
+    } else if (e + eBias >= 1) {
+      m = (value * c - 1) * Math.pow(2, mLen)
+      e = e + eBias
+    } else {
+      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
+      e = 0
+    }
+  }
+
+  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
+
+  e = (e << mLen) | m
+  eLen += mLen
+  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
+
+  buffer[offset + i - d] |= s * 128
+}
+
+},{}],4:[function(require,module,exports){
+
+/**
+ * isArray
+ */
+
+var isArray = Array.isArray;
+
+/**
+ * toString
+ */
+
+var str = Object.prototype.toString;
+
+/**
+ * Whether or not the given `val`
+ * is an array.
+ *
+ * example:
+ *
+ *        isArray([]);
+ *        // > true
+ *        isArray(arguments);
+ *        // > false
+ *        isArray('');
+ *        // > false
+ *
+ * @param {mixed} val
+ * @return {bool}
+ */
+
+module.exports = isArray || function (val) {
+  return !! val && '[object Array]' == str.call(val);
+};
+
+},{}],5:[function(require,module,exports){
+module.exports = require('./lib/heap');
+
+},{"./lib/heap":6}],6:[function(require,module,exports){
+// Generated by CoffeeScript 1.8.0
+(function() {
+  var Heap, defaultCmp, floor, heapify, heappop, heappush, heappushpop, heapreplace, insort, min, nlargest, nsmallest, updateItem, _siftdown, _siftup;
+
+  floor = Math.floor, min = Math.min;
+
+
+  /*
+  Default comparison function to be used
+   */
+
+  defaultCmp = function(x, y) {
+    if (x < y) {
+      return -1;
+    }
+    if (x > y) {
+      return 1;
+    }
+    return 0;
+  };
+
+
+  /*
+  Insert item x in list a, and keep it sorted assuming a is sorted.
+  
+  If x is already in a, insert it to the right of the rightmost x.
+  
+  Optional args lo (default 0) and hi (default a.length) bound the slice
+  of a to be searched.
+   */
+
+  insort = function(a, x, lo, hi, cmp) {
+    var mid;
+    if (lo == null) {
+      lo = 0;
+    }
+    if (cmp == null) {
+      cmp = defaultCmp;
+    }
+    if (lo < 0) {
+      throw new Error('lo must be non-negative');
+    }
+    if (hi == null) {
+      hi = a.length;
+    }
+    while (lo < hi) {
+      mid = floor((lo + hi) / 2);
+      if (cmp(x, a[mid]) < 0) {
+        hi = mid;
+      } else {
+        lo = mid + 1;
+      }
+    }
+    return ([].splice.apply(a, [lo, lo - lo].concat(x)), x);
+  };
+
+
+  /*
+  Push item onto heap, maintaining the heap invariant.
+   */
+
+  heappush = function(array, item, cmp) {
+    if (cmp == null) {
+      cmp = defaultCmp;
+    }
+    array.push(item);
+    return _siftdown(array, 0, array.length - 1, cmp);
+  };
+
+
+  /*
+  Pop the smallest item off the heap, maintaining the heap invariant.
+   */
+
+  heappop = function(array, cmp) {
+    var lastelt, returnitem;
+    if (cmp == null) {
+      cmp = defaultCmp;
+    }
+    lastelt = array.pop();
+    if (array.length) {
+      returnitem = array[0];
+      array[0] = lastelt;
+      _siftup(array, 0, cmp);
+    } else {
+      returnitem = lastelt;
+    }
+    return returnitem;
+  };
+
+
+  /*
+  Pop and return the current smallest value, and add the new item.
+  
+  This is more efficient than heappop() followed by heappush(), and can be
+  more appropriate when using a fixed size heap. Note that the value
+  returned may be larger than item! That constrains reasonable use of
+  this routine unless written as part of a conditional replacement:
+      if item > array[0]
+        item = heapreplace(array, item)
+   */
+
+  heapreplace = function(array, item, cmp) {
+    var returnitem;
+    if (cmp == null) {
+      cmp = defaultCmp;
+    }
+    returnitem = array[0];
+    array[0] = item;
+    _siftup(array, 0, cmp);
+    return returnitem;
+  };
+
+
+  /*
+  Fast version of a heappush followed by a heappop.
+   */
+
+  heappushpop = function(array, item, cmp) {
+    var _ref;
+    if (cmp == null) {
+      cmp = defaultCmp;
+    }
+    if (array.length && cmp(array[0], item) < 0) {
+      _ref = [array[0], item], item = _ref[0], array[0] = _ref[1];
+      _siftup(array, 0, cmp);
+    }
+    return item;
+  };
+
+
+  /*
+  Transform list into a heap, in-place, in O(array.length) time.
+   */
+
+  heapify = function(array, cmp) {
+    var i, _i, _j, _len, _ref, _ref1, _results, _results1;
+    if (cmp == null) {
+      cmp = defaultCmp;
+    }
+    _ref1 = (function() {
+      _results1 = [];
+      for (var _j = 0, _ref = floor(array.length / 2); 0 <= _ref ? _j < _ref : _j > _ref; 0 <= _ref ? _j++ : _j--){ _results1.push(_j); }
+      return _results1;
+    }).apply(this).reverse();
+    _results = [];
+    for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+      i = _ref1[_i];
+      _results.push(_siftup(array, i, cmp));
+    }
+    return _results;
+  };
+
+
+  /*
+  Update the position of the given item in the heap.
+  This function should be called every time the item is being modified.
+   */
+
+  updateItem = function(array, item, cmp) {
+    var pos;
+    if (cmp == null) {
+      cmp = defaultCmp;
+    }
+    pos = array.indexOf(item);
+    if (pos === -1) {
+      return;
+    }
+    _siftdown(array, 0, pos, cmp);
+    return _siftup(array, pos, cmp);
+  };
+
+
+  /*
+  Find the n largest elements in a dataset.
+   */
+
+  nlargest = function(array, n, cmp) {
+    var elem, result, _i, _len, _ref;
+    if (cmp == null) {
+      cmp = defaultCmp;
+    }
+    result = array.slice(0, n);
+    if (!result.length) {
+      return result;
+    }
+    heapify(result, cmp);
+    _ref = array.slice(n);
+    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+      elem = _ref[_i];
+      heappushpop(result, elem, cmp);
+    }
+    return result.sort(cmp).reverse();
+  };
+
+
+  /*
+  Find the n smallest elements in a dataset.
+   */
+
+  nsmallest = function(array, n, cmp) {
+    var elem, i, los, result, _i, _j, _len, _ref, _ref1, _results;
+    if (cmp == null) {
+      cmp = defaultCmp;
+    }
+    if (n * 10 <= array.length) {
+      result = array.slice(0, n).sort(cmp);
+      if (!result.length) {
+        return result;
+      }
+      los = result[result.length - 1];
+      _ref = array.slice(n);
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        elem = _ref[_i];
+        if (cmp(elem, los) < 0) {
+          insort(result, elem, 0, null, cmp);
+          result.pop();
+          los = result[result.length - 1];
+        }
+      }
+      return result;
+    }
+    heapify(array, cmp);
+    _results = [];
+    for (i = _j = 0, _ref1 = min(n, array.length); 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
+      _results.push(heappop(array, cmp));
+    }
+    return _results;
+  };
+
+  _siftdown = function(array, startpos, pos, cmp) {
+    var newitem, parent, parentpos;
+    if (cmp == null) {
+      cmp = defaultCmp;
+    }
+    newitem = array[pos];
+    while (pos > startpos) {
+      parentpos = (pos - 1) >> 1;
+      parent = array[parentpos];
+      if (cmp(newitem, parent) < 0) {
+        array[pos] = parent;
+        pos = parentpos;
+        continue;
+      }
+      break;
+    }
+    return array[pos] = newitem;
+  };
+
+  _siftup = function(array, pos, cmp) {
+    var childpos, endpos, newitem, rightpos, startpos;
+    if (cmp == null) {
+      cmp = defaultCmp;
+    }
+    endpos = array.length;
+    startpos = pos;
+    newitem = array[pos];
+    childpos = 2 * pos + 1;
+    while (childpos < endpos) {
+      rightpos = childpos + 1;
+      if (rightpos < endpos && !(cmp(array[childpos], array[rightpos]) < 0)) {
+        childpos = rightpos;
+      }
+      array[pos] = array[childpos];
+      pos = childpos;
+      childpos = 2 * pos + 1;
+    }
+    array[pos] = newitem;
+    return _siftdown(array, startpos, pos, cmp);
+  };
+
+  Heap = (function() {
+    Heap.push = heappush;
+
+    Heap.pop = heappop;
+
+    Heap.replace = heapreplace;
+
+    Heap.pushpop = heappushpop;
+
+    Heap.heapify = heapify;
+
+    Heap.updateItem = updateItem;
+
+    Heap.nlargest = nlargest;
+
+    Heap.nsmallest = nsmallest;
+
+    function Heap(cmp) {
+      this.cmp = cmp != null ? cmp : defaultCmp;
+      this.nodes = [];
+    }
+
+    Heap.prototype.push = function(x) {
+      return heappush(this.nodes, x, this.cmp);
+    };
+
+    Heap.prototype.pop = function() {
+      return heappop(this.nodes, this.cmp);
+    };
+
+    Heap.prototype.peek = function() {
+      return this.nodes[0];
+    };
+
+    Heap.prototype.contains = function(x) {
+      return this.nodes.indexOf(x) !== -1;
+    };
+
+    Heap.prototype.replace = function(x) {
+      return heapreplace(this.nodes, x, this.cmp);
+    };
+
+    Heap.prototype.pushpop = function(x) {
+      return heappushpop(this.nodes, x, this.cmp);
+    };
+
+    Heap.prototype.heapify = function() {
+      return heapify(this.nodes, this.cmp);
+    };
+
+    Heap.prototype.updateItem = function(x) {
+      return updateItem(this.nodes, x, this.cmp);
+    };
+
+    Heap.prototype.clear = function() {
+      return this.nodes = [];
+    };
+
+    Heap.prototype.empty = function() {
+      return this.nodes.length === 0;
+    };
+
+    Heap.prototype.size = function() {
+      return this.nodes.length;
+    };
+
+    Heap.prototype.clone = function() {
+      var heap;
+      heap = new Heap();
+      heap.nodes = this.nodes.slice(0);
+      return heap;
+    };
+
+    Heap.prototype.toArray = function() {
+      return this.nodes.slice(0);
+    };
+
+    Heap.prototype.insert = Heap.prototype.push;
+
+    Heap.prototype.top = Heap.prototype.peek;
+
+    Heap.prototype.front = Heap.prototype.peek;
+
+    Heap.prototype.has = Heap.prototype.contains;
+
+    Heap.prototype.copy = Heap.prototype.clone;
+
+    return Heap;
+
+  })();
+
+  (function(root, factory) {
+    if (typeof define === 'function' && define.amd) {
+      return define([], factory);
+    } else if (typeof exports === 'object') {
+      return module.exports = factory();
+    } else {
+      return root.Heap = factory();
+    }
+  })(this, function() {
+    return Heap;
+  });
+
+}).call(this);
+
+},{}],7:[function(require,module,exports){
+(function (global){
+"use strict";
+
+var numeric = (typeof exports === "undefined")?(function numeric() {}):(exports);
+if(typeof global !== "undefined") { global.numeric = numeric; }
+
+numeric.version = "1.2.6";
+
+// 1. Utility functions
+numeric.bench = function bench (f,interval) {
+    var t1,t2,n,i;
+    if(typeof interval === "undefined") { interval = 15; }
+    n = 0.5;
+    t1 = new Date();
+    while(1) {
+        n*=2;
+        for(i=n;i>3;i-=4) { f(); f(); f(); f(); }
+        while(i>0) { f(); i--; }
+        t2 = new Date();
+        if(t2-t1 > interval) break;
+    }
+    for(i=n;i>3;i-=4) { f(); f(); f(); f(); }
+    while(i>0) { f(); i--; }
+    t2 = new Date();
+    return 1000*(3*n-1)/(t2-t1);
+}
+
+numeric._myIndexOf = (function _myIndexOf(w) {
+    var n = this.length,k;
+    for(k=0;k<n;++k) if(this[k]===w) return k;
+    return -1;
+});
+numeric.myIndexOf = (Array.prototype.indexOf)?Array.prototype.indexOf:numeric._myIndexOf;
+
+numeric.Function = Function;
+numeric.precision = 4;
+numeric.largeArray = 50;
+
+numeric.prettyPrint = function prettyPrint(x) {
+    function fmtnum(x) {
+        if(x === 0) { return '0'; }
+        if(isNaN(x)) { return 'NaN'; }
+        if(x<0) { return '-'+fmtnum(-x); }
+        if(isFinite(x)) {
+            var scale = Math.floor(Math.log(x) / Math.log(10));
+            var normalized = x / Math.pow(10,scale);
+            var basic = normalized.toPrecision(numeric.precision);
+            if(parseFloat(basic) === 10) { scale++; normalized = 1; basic = normalized.toPrecision(numeric.precision); }
+            return parseFloat(basic).toString()+'e'+scale.toString();
+        }
+        return 'Infinity';
+    }
+    var ret = [];
+    function foo(x) {
+        var k;
+        if(typeof x === "undefined") { ret.push(Array(numeric.precision+8).join(' ')); return false; }
+        if(typeof x === "string") { ret.push('"'+x+'"'); return false; }
+        if(typeof x === "boolean") { ret.push(x.toString()); return false; }
+        if(typeof x === "number") {
+            var a = fmtnum(x);
+            var b = x.toPrecision(numeric.precision);
+            var c = parseFloat(x.toString()).toString();
+            var d = [a,b,c,parseFloat(b).toString(),parseFloat(c).toString()];
+            for(k=1;k<d.length;k++) { if(d[k].length < a.length) a = d[k]; }
+            ret.push(Array(numeric.precision+8-a.length).join(' ')+a);
+            return false;
+        }
+        if(x === null) { ret.push("null"); return false; }
+        if(typeof x === "function") { 
+            ret.push(x.toString());
+            var flag = false;
+            for(k in x) { if(x.hasOwnProperty(k)) { 
+                if(flag) ret.push(',\n');
+                else ret.push('\n{');
+                flag = true; 
+                ret.push(k); 
+                ret.push(': \n'); 
+                foo(x[k]); 
+            } }
+            if(flag) ret.push('}\n');
+            return true;
+        }
+        if(x instanceof Array) {
+            if(x.length > numeric.largeArray) { ret.push('...Large Array...'); return true; }
+            var flag = false;
+            ret.push('[');
+            for(k=0;k<x.length;k++) { if(k>0) { ret.push(','); if(flag) ret.push('\n '); } flag = foo(x[k]); }
+            ret.push(']');
+            return true;
+        }
+        ret.push('{');
+        var flag = false;
+        for(k in x) { if(x.hasOwnProperty(k)) { if(flag) ret.push(',\n'); flag = true; ret.push(k); ret.push(': \n'); foo(x[k]); } }
+        ret.push('}');
+        return true;
+    }
+    foo(x);
+    return ret.join('');
+}
+
+numeric.parseDate = function parseDate(d) {
+    function foo(d) {
+        if(typeof d === 'string') { return Date.parse(d.replace(/-/g,'/')); }
+        if(!(d instanceof Array)) { throw new Error("parseDate: parameter must be arrays of strings"); }
+        var ret = [],k;
+        for(k=0;k<d.length;k++) { ret[k] = foo(d[k]); }
+        return ret;
+    }
+    return foo(d);
+}
+
+numeric.parseFloat = function parseFloat_(d) {
+    function foo(d) {
+        if(typeof d === 'string') { return parseFloat(d); }
+        if(!(d instanceof Array)) { throw new Error("parseFloat: parameter must be arrays of strings"); }
+        var ret = [],k;
+        for(k=0;k<d.length;k++) { ret[k] = foo(d[k]); }
+        return ret;
+    }
+    return foo(d);
+}
+
+numeric.parseCSV = function parseCSV(t) {
+    var foo = t.split('\n');
+    var j,k;
+    var ret = [];
+    var pat = /(([^'",]*)|('[^']*')|("[^"]*")),/g;
+    var patnum = /^\s*(([+-]?[0-9]+(\.[0-9]*)?(e[+-]?[0-9]+)?)|([+-]?[0-9]*(\.[0-9]+)?(e[+-]?[0-9]+)?))\s*$/;
+    var stripper = function(n) { return n.substr(0,n.length-1); }
+    var count = 0;
+    for(k=0;k<foo.length;k++) {
+      var bar = (foo[k]+",").match(pat),baz;
+      if(bar.length>0) {
+          ret[count] = [];
+          for(j=0;j<bar.length;j++) {
+              baz = stripper(bar[j]);
+              if(patnum.test(baz)) { ret[count][j] = parseFloat(baz); }
+              else ret[count][j] = baz;
+          }
+          count++;
+      }
+    }
+    return ret;
+}
+
+numeric.toCSV = function toCSV(A) {
+    var s = numeric.dim(A);
+    var i,j,m,n,row,ret;
+    m = s[0];
+    n = s[1];
+    ret = [];
+    for(i=0;i<m;i++) {
+        row = [];
+        for(j=0;j<m;j++) { row[j] = A[i][j].toString(); }
+        ret[i] = row.join(', ');
+    }
+    return ret.join('\n')+'\n';
+}
+
+numeric.getURL = function getURL(url) {
+    var client = new XMLHttpRequest();
+    client.open("GET",url,false);
+    client.send();
+    return client;
+}
+
+numeric.imageURL = function imageURL(img) {
+    function base64(A) {
+        var n = A.length, i,x,y,z,p,q,r,s;
+        var key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+        var ret = "";
+        for(i=0;i<n;i+=3) {
+            x = A[i];
+            y = A[i+1];
+            z = A[i+2];
+            p = x >> 2;
+            q = ((x & 3) << 4) + (y >> 4);
+            r = ((y & 15) << 2) + (z >> 6);
+            s = z & 63;
+            if(i+1>=n) { r = s = 64; }
+            else if(i+2>=n) { s = 64; }
+            ret += key.charAt(p) + key.charAt(q) + key.charAt(r) + key.charAt(s);
+            }
+        return ret;
+    }
+    function crc32Array (a,from,to) {
+        if(typeof from === "undefined") { from = 0; }
+        if(typeof to === "undefined") { to = a.length; }
+        var table = [0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+                     0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 
+                     0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+                     0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 
+                     0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 
+                     0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 
+                     0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+                     0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+                     0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+                     0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 
+                     0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 
+                     0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 
+                     0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 
+                     0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 
+                     0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 
+                     0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 
+                     0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 
+                     0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 
+                     0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 
+                     0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 
+                     0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 
+                     0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 
+                     0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 
+                     0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 
+                     0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 
+                     0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 
+                     0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 
+                     0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 
+                     0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 
+                     0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 
+                     0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 
+                     0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D];
+     
+        var crc = -1, y = 0, n = a.length,i;
+
+        for (i = from; i < to; i++) {
+            y = (crc ^ a[i]) & 0xFF;
+            crc = (crc >>> 8) ^ table[y];
+        }
+     
+        return crc ^ (-1);
+    }
+
+    var h = img[0].length, w = img[0][0].length, s1, s2, next,k,length,a,b,i,j,adler32,crc32;
+    var stream = [
+                  137, 80, 78, 71, 13, 10, 26, 10,                           //  0: PNG signature
+                  0,0,0,13,                                                  //  8: IHDR Chunk length
+                  73, 72, 68, 82,                                            // 12: "IHDR" 
+                  (w >> 24) & 255, (w >> 16) & 255, (w >> 8) & 255, w&255,   // 16: Width
+                  (h >> 24) & 255, (h >> 16) & 255, (h >> 8) & 255, h&255,   // 20: Height
+                  8,                                                         // 24: bit depth
+                  2,                                                         // 25: RGB
+                  0,                                                         // 26: deflate
+                  0,                                                         // 27: no filter
+                  0,                                                         // 28: no interlace
+                  -1,-2,-3,-4,                                               // 29: CRC
+                  -5,-6,-7,-8,                                               // 33: IDAT Chunk length
+                  73, 68, 65, 84,                                            // 37: "IDAT"
+                  // RFC 1950 header starts here
+                  8,                                                         // 41: RFC1950 CMF
+                  29                                                         // 42: RFC1950 FLG
+                  ];
+    crc32 = crc32Array(stream,12,29);
+    stream[29] = (crc32>>24)&255;
+    stream[30] = (crc32>>16)&255;
+    stream[31] = (crc32>>8)&255;
+    stream[32] = (crc32)&255;
+    s1 = 1;
+    s2 = 0;
+    for(i=0;i<h;i++) {
+        if(i<h-1) { stream.push(0); }
+        else { stream.push(1); }
+        a = (3*w+1+(i===0))&255; b = ((3*w+1+(i===0))>>8)&255;
+        stream.push(a); stream.push(b);
+        stream.push((~a)&255); stream.push((~b)&255);
+        if(i===0) stream.push(0);
+        for(j=0;j<w;j++) {
+            for(k=0;k<3;k++) {
+                a = img[k][i][j];
+                if(a>255) a = 255;
+                else if(a<0) a=0;
+                else a = Math.round(a);
+                s1 = (s1 + a )%65521;
+                s2 = (s2 + s1)%65521;
+                stream.push(a);
+            }
+        }
+        stream.push(0);
+    }
+    adler32 = (s2<<16)+s1;
+    stream.push((adler32>>24)&255);
+    stream.push((adler32>>16)&255);
+    stream.push((adler32>>8)&255);
+    stream.push((adler32)&255);
+    length = stream.length - 41;
+    stream[33] = (length>>24)&255;
+    stream[34] = (length>>16)&255;
+    stream[35] = (length>>8)&255;
+    stream[36] = (length)&255;
+    crc32 = crc32Array(stream,37);
+    stream.push((crc32>>24)&255);
+    stream.push((crc32>>16)&255);
+    stream.push((crc32>>8)&255);
+    stream.push((crc32)&255);
+    stream.push(0);
+    stream.push(0);
+    stream.push(0);
+    stream.push(0);
+//    a = stream.length;
+    stream.push(73);  // I
+    stream.push(69);  // E
+    stream.push(78);  // N
+    stream.push(68);  // D
+    stream.push(174); // CRC1
+    stream.push(66);  // CRC2
+    stream.push(96);  // CRC3
+    stream.push(130); // CRC4
+    return 'data:image/png;base64,'+base64(stream);
+}
+
+// 2. Linear algebra with Arrays.
+numeric._dim = function _dim(x) {
+    var ret = [];
+    while(typeof x === "object") { ret.push(x.length); x = x[0]; }
+    return ret;
+}
+
+numeric.dim = function dim(x) {
+    var y,z;
+    if(typeof x === "object") {
+        y = x[0];
+        if(typeof y === "object") {
+            z = y[0];
+            if(typeof z === "object") {
+                return numeric._dim(x);
+            }
+            return [x.length,y.length];
+        }
+        return [x.length];
+    }
+    return [];
+}
+
+numeric.mapreduce = function mapreduce(body,init) {
+    return Function('x','accum','_s','_k',
+            'if(typeof accum === "undefined") accum = '+init+';\n'+
+            'if(typeof x === "number") { var xi = x; '+body+'; return accum; }\n'+
+            'if(typeof _s === "undefined") _s = numeric.dim(x);\n'+
+            'if(typeof _k === "undefined") _k = 0;\n'+
+            'var _n = _s[_k];\n'+
+            'var i,xi;\n'+
+            'if(_k < _s.length-1) {\n'+
+            '    for(i=_n-1;i>=0;i--) {\n'+
+            '        accum = arguments.callee(x[i],accum,_s,_k+1);\n'+
+            '    }'+
+            '    return accum;\n'+
+            '}\n'+
+            'for(i=_n-1;i>=1;i-=2) { \n'+
+            '    xi = x[i];\n'+
+            '    '+body+';\n'+
+            '    xi = x[i-1];\n'+
+            '    '+body+';\n'+
+            '}\n'+
+            'if(i === 0) {\n'+
+            '    xi = x[i];\n'+
+            '    '+body+'\n'+
+            '}\n'+
+            'return accum;'
+            );
+}
+numeric.mapreduce2 = function mapreduce2(body,setup) {
+    return Function('x',
+            'var n = x.length;\n'+
+            'var i,xi;\n'+setup+';\n'+
+            'for(i=n-1;i!==-1;--i) { \n'+
+            '    xi = x[i];\n'+
+            '    '+body+';\n'+
+            '}\n'+
+            'return accum;'
+            );
+}
+
+
+numeric.same = function same(x,y) {
+    var i,n;
+    if(!(x instanceof Array) || !(y instanceof Array)) { return false; }
+    n = x.length;
+    if(n !== y.length) { return false; }
+    for(i=0;i<n;i++) {
+        if(x[i] === y[i]) { continue; }
+        if(typeof x[i] === "object") { if(!same(x[i],y[i])) return false; }
+        else { return false; }
+    }
+    return true;
+}
+
+numeric.rep = function rep(s,v,k) {
+    if(typeof k === "undefined") { k=0; }
+    var n = s[k], ret = Array(n), i;
+    if(k === s.length-1) {
+        for(i=n-2;i>=0;i-=2) { ret[i+1] = v; ret[i] = v; }
+        if(i===-1) { ret[0] = v; }
+        return ret;
+    }
+    for(i=n-1;i>=0;i--) { ret[i] = numeric.rep(s,v,k+1); }
+    return ret;
+}
+
+
+numeric.dotMMsmall = function dotMMsmall(x,y) {
+    var i,j,k,p,q,r,ret,foo,bar,woo,i0,k0,p0,r0;
+    p = x.length; q = y.length; r = y[0].length;
+    ret = Array(p);
+    for(i=p-1;i>=0;i--) {
+        foo = Array(r);
+        bar = x[i];
+        for(k=r-1;k>=0;k--) {
+            woo = bar[q-1]*y[q-1][k];
+            for(j=q-2;j>=1;j-=2) {
+                i0 = j-1;
+                woo += bar[j]*y[j][k] + bar[i0]*y[i0][k];
+            }
+            if(j===0) { woo += bar[0]*y[0][k]; }
+            foo[k] = woo;
+        }
+        ret[i] = foo;
+    }
+    return ret;
+}
+numeric._getCol = function _getCol(A,j,x) {
+    var n = A.length, i;
+    for(i=n-1;i>0;--i) {
+        x[i] = A[i][j];
+        --i;
+        x[i] = A[i][j];
+    }
+    if(i===0) x[0] = A[0][j];
+}
+numeric.dotMMbig = function dotMMbig(x,y){
+    var gc = numeric._getCol, p = y.length, v = Array(p);
+    var m = x.length, n = y[0].length, A = new Array(m), xj;
+    var VV = numeric.dotVV;
+    var i,j,k,z;
+    --p;
+    --m;
+    for(i=m;i!==-1;--i) A[i] = Array(n);
+    --n;
+    for(i=n;i!==-1;--i) {
+        gc(y,i,v);
+        for(j=m;j!==-1;--j) {
+            z=0;
+            xj = x[j];
+            A[j][i] = VV(xj,v);
+        }
+    }
+    return A;
+}
+
+numeric.dotMV = function dotMV(x,y) {
+    var p = x.length, q = y.length,i;
+    var ret = Array(p), dotVV = numeric.dotVV;
+    for(i=p-1;i>=0;i--) { ret[i] = dotVV(x[i],y); }
+    return ret;
+}
+
+numeric.dotVM = function dotVM(x,y) {
+    var i,j,k,p,q,r,ret,foo,bar,woo,i0,k0,p0,r0,s1,s2,s3,baz,accum;
+    p = x.length; q = y[0].length;
+    ret = Array(q);
+    for(k=q-1;k>=0;k--) {
+        woo = x[p-1]*y[p-1][k];
+        for(j=p-2;j>=1;j-=2) {
+            i0 = j-1;
+            woo += x[j]*y[j][k] + x[i0]*y[i0][k];
+        }
+        if(j===0) { woo += x[0]*y[0][k]; }
+        ret[k] = woo;
+    }
+    return ret;
+}
+
+numeric.dotVV = function dotVV(x,y) {
+    var i,n=x.length,i1,ret = x[n-1]*y[n-1];
+    for(i=n-2;i>=1;i-=2) {
+        i1 = i-1;
+        ret += x[i]*y[i] + x[i1]*y[i1];
+    }
+    if(i===0) { ret += x[0]*y[0]; }
+    return ret;
+}
+
+numeric.dot = function dot(x,y) {
+    var d = numeric.dim;
+    switch(d(x).length*1000+d(y).length) {
+    case 2002:
+        if(y.length < 10) return numeric.dotMMsmall(x,y);
+        else return numeric.dotMMbig(x,y);
+    case 2001: return numeric.dotMV(x,y);
+    case 1002: return numeric.dotVM(x,y);
+    case 1001: return numeric.dotVV(x,y);
+    case 1000: return numeric.mulVS(x,y);
+    case 1: return numeric.mulSV(x,y);
+    case 0: return x*y;
+    default: throw new Error('numeric.dot only works on vectors and matrices');
+    }
+}
+
+numeric.diag = function diag(d) {
+    var i,i1,j,n = d.length, A = Array(n), Ai;
+    for(i=n-1;i>=0;i--) {
+        Ai = Array(n);
+        i1 = i+2;
+        for(j=n-1;j>=i1;j-=2) {
+            Ai[j] = 0;
+            Ai[j-1] = 0;
+        }
+        if(j>i) { Ai[j] = 0; }
+        Ai[i] = d[i];
+        for(j=i-1;j>=1;j-=2) {
+            Ai[j] = 0;
+            Ai[j-1] = 0;
+        }
+        if(j===0) { Ai[0] = 0; }
+        A[i] = Ai;
+    }
+    return A;
+}
+numeric.getDiag = function(A) {
+    var n = Math.min(A.length,A[0].length),i,ret = Array(n);
+    for(i=n-1;i>=1;--i) {
+        ret[i] = A[i][i];
+        --i;
+        ret[i] = A[i][i];
+    }
+    if(i===0) {
+        ret[0] = A[0][0];
+    }
+    return ret;
+}
+
+numeric.identity = function identity(n) { return numeric.diag(numeric.rep([n],1)); }
+numeric.pointwise = function pointwise(params,body,setup) {
+    if(typeof setup === "undefined") { setup = ""; }
+    var fun = [];
+    var k;
+    var avec = /\[i\]$/,p,thevec = '';
+    var haveret = false;
+    for(k=0;k<params.length;k++) {
+        if(avec.test(params[k])) {
+            p = params[k].substring(0,params[k].length-3);
+            thevec = p;
+        } else { p = params[k]; }
+        if(p==='ret') haveret = true;
+        fun.push(p);
+    }
+    fun[params.length] = '_s';
+    fun[params.length+1] = '_k';
+    fun[params.length+2] = (
+            'if(typeof _s === "undefined") _s = numeric.dim('+thevec+');\n'+
+            'if(typeof _k === "undefined") _k = 0;\n'+
+            'var _n = _s[_k];\n'+
+            'var i'+(haveret?'':', ret = Array(_n)')+';\n'+
+            'if(_k < _s.length-1) {\n'+
+            '    for(i=_n-1;i>=0;i--) ret[i] = arguments.callee('+params.join(',')+',_s,_k+1);\n'+
+            '    return ret;\n'+
+            '}\n'+
+            setup+'\n'+
+            'for(i=_n-1;i!==-1;--i) {\n'+
+            '    '+body+'\n'+
+            '}\n'+
+            'return ret;'
+            );
+    return Function.apply(null,fun);
+}
+numeric.pointwise2 = function pointwise2(params,body,setup) {
+    if(typeof setup === "undefined") { setup = ""; }
+    var fun = [];
+    var k;
+    var avec = /\[i\]$/,p,thevec = '';
+    var haveret = false;
+    for(k=0;k<params.length;k++) {
+        if(avec.test(params[k])) {
+            p = params[k].substring(0,params[k].length-3);
+            thevec = p;
+        } else { p = params[k]; }
+        if(p==='ret') haveret = true;
+        fun.push(p);
+    }
+    fun[params.length] = (
+            'var _n = '+thevec+'.length;\n'+
+            'var i'+(haveret?'':', ret = Array(_n)')+';\n'+
+            setup+'\n'+
+            'for(i=_n-1;i!==-1;--i) {\n'+
+            body+'\n'+
+            '}\n'+
+            'return ret;'
+            );
+    return Function.apply(null,fun);
+}
+numeric._biforeach = (function _biforeach(x,y,s,k,f) {
+    if(k === s.length-1) { f(x,y); return; }
+    var i,n=s[k];
+    for(i=n-1;i>=0;i--) { _biforeach(typeof x==="object"?x[i]:x,typeof y==="object"?y[i]:y,s,k+1,f); }
+});
+numeric._biforeach2 = (function _biforeach2(x,y,s,k,f) {
+    if(k === s.length-1) { return f(x,y); }
+    var i,n=s[k],ret = Array(n);
+    for(i=n-1;i>=0;--i) { ret[i] = _biforeach2(typeof x==="object"?x[i]:x,typeof y==="object"?y[i]:y,s,k+1,f); }
+    return ret;
+});
+numeric._foreach = (function _foreach(x,s,k,f) {
+    if(k === s.length-1) { f(x); return; }
+    var i,n=s[k];
+    for(i=n-1;i>=0;i--) { _foreach(x[i],s,k+1,f); }
+});
+numeric._foreach2 = (function _foreach2(x,s,k,f) {
+    if(k === s.length-1) { return f(x); }
+    var i,n=s[k], ret = Array(n);
+    for(i=n-1;i>=0;i--) { ret[i] = _foreach2(x[i],s,k+1,f); }
+    return ret;
+});
+
+/*numeric.anyV = numeric.mapreduce('if(xi) return true;','false');
+numeric.allV = numeric.mapreduce('if(!xi) return false;','true');
+numeric.any = function(x) { if(typeof x.length === "undefined") return x; return numeric.anyV(x); }
+numeric.all = function(x) { if(typeof x.length === "undefined") return x; return numeric.allV(x); }*/
+
+numeric.ops2 = {
+        add: '+',
+        sub: '-',
+        mul: '*',
+        div: '/',
+        mod: '%',
+        and: '&&',
+        or:  '||',
+        eq:  '===',
+        neq: '!==',
+        lt:  '<',
+        gt:  '>',
+        leq: '<=',
+        geq: '>=',
+        band: '&',
+        bor: '|',
+        bxor: '^',
+        lshift: '<<',
+        rshift: '>>',
+        rrshift: '>>>'
+};
+numeric.opseq = {
+        addeq: '+=',
+        subeq: '-=',
+        muleq: '*=',
+        diveq: '/=',
+        modeq: '%=',
+        lshifteq: '<<=',
+        rshifteq: '>>=',
+        rrshifteq: '>>>=',
+        bandeq: '&=',
+        boreq: '|=',
+        bxoreq: '^='
+};
+numeric.mathfuns = ['abs','acos','asin','atan','ceil','cos',
+                    'exp','floor','log','round','sin','sqrt','tan',
+                    'isNaN','isFinite'];
+numeric.mathfuns2 = ['atan2','pow','max','min'];
+numeric.ops1 = {
+        neg: '-',
+        not: '!',
+        bnot: '~',
+        clone: ''
+};
+numeric.mapreducers = {
+        any: ['if(xi) return true;','var accum = false;'],
+        all: ['if(!xi) return false;','var accum = true;'],
+        sum: ['accum += xi;','var accum = 0;'],
+        prod: ['accum *= xi;','var accum = 1;'],
+        norm2Squared: ['accum += xi*xi;','var accum = 0;'],
+        norminf: ['accum = max(accum,abs(xi));','var accum = 0, max = Math.max, abs = Math.abs;'],
+        norm1: ['accum += abs(xi)','var accum = 0, abs = Math.abs;'],
+        sup: ['accum = max(accum,xi);','var accum = -Infinity, max = Math.max;'],
+        inf: ['accum = min(accum,xi);','var accum = Infinity, min = Math.min;']
+};
+
+(function () {
+    var i,o;
+    for(i=0;i<numeric.mathfuns2.length;++i) {
+        o = numeric.mathfuns2[i];
+        numeric.ops2[o] = o;
+    }
+    for(i in numeric.ops2) {
+        if(numeric.ops2.hasOwnProperty(i)) {
+            o = numeric.ops2[i];
+            var code, codeeq, setup = '';
+            if(numeric.myIndexOf.call(numeric.mathfuns2,i)!==-1) {
+                setup = 'var '+o+' = Math.'+o+';\n';
+                code = function(r,x,y) { return r+' = '+o+'('+x+','+y+')'; };
+                codeeq = function(x,y) { return x+' = '+o+'('+x+','+y+')'; };
+            } else {
+                code = function(r,x,y) { return r+' = '+x+' '+o+' '+y; };
+                if(numeric.opseq.hasOwnProperty(i+'eq')) {
+                    codeeq = function(x,y) { return x+' '+o+'= '+y; };
+                } else {
+                    codeeq = function(x,y) { return x+' = '+x+' '+o+' '+y; };                    
+                }
+            }
+            numeric[i+'VV'] = numeric.pointwise2(['x[i]','y[i]'],code('ret[i]','x[i]','y[i]'),setup);
+            numeric[i+'SV'] = numeric.pointwise2(['x','y[i]'],code('ret[i]','x','y[i]'),setup);
+            numeric[i+'VS'] = numeric.pointwise2(['x[i]','y'],code('ret[i]','x[i]','y'),setup);
+            numeric[i] = Function(
+                    'var n = arguments.length, i, x = arguments[0], y;\n'+
+                    'var VV = numeric.'+i+'VV, VS = numeric.'+i+'VS, SV = numeric.'+i+'SV;\n'+
+                    'var dim = numeric.dim;\n'+
+                    'for(i=1;i!==n;++i) { \n'+
+                    '  y = arguments[i];\n'+
+                    '  if(typeof x === "object") {\n'+
+                    '      if(typeof y === "object") x = numeric._biforeach2(x,y,dim(x),0,VV);\n'+
+                    '      else x = numeric._biforeach2(x,y,dim(x),0,VS);\n'+
+                    '  } else if(typeof y === "object") x = numeric._biforeach2(x,y,dim(y),0,SV);\n'+
+                    '  else '+codeeq('x','y')+'\n'+
+                    '}\nreturn x;\n');
+            numeric[o] = numeric[i];
+            numeric[i+'eqV'] = numeric.pointwise2(['ret[i]','x[i]'], codeeq('ret[i]','x[i]'),setup);
+            numeric[i+'eqS'] = numeric.pointwise2(['ret[i]','x'], codeeq('ret[i]','x'),setup);
+            numeric[i+'eq'] = Function(
+                    'var n = arguments.length, i, x = arguments[0], y;\n'+
+                    'var V = numeric.'+i+'eqV, S = numeric.'+i+'eqS\n'+
+                    'var s = numeric.dim(x);\n'+
+                    'for(i=1;i!==n;++i) { \n'+
+                    '  y = arguments[i];\n'+
+                    '  if(typeof y === "object") numeric._biforeach(x,y,s,0,V);\n'+
+                    '  else numeric._biforeach(x,y,s,0,S);\n'+
+                    '}\nreturn x;\n');
+        }
+    }
+    for(i=0;i<numeric.mathfuns2.length;++i) {
+        o = numeric.mathfuns2[i];
+        delete numeric.ops2[o];
+    }
+    for(i=0;i<numeric.mathfuns.length;++i) {
+        o = numeric.mathfuns[i];
+        numeric.ops1[o] = o;
+    }
+    for(i in numeric.ops1) {
+        if(numeric.ops1.hasOwnProperty(i)) {
+            setup = '';
+            o = numeric.ops1[i];
+            if(numeric.myIndexOf.call(numeric.mathfuns,i)!==-1) {
+                if(Math.hasOwnProperty(o)) setup = 'var '+o+' = Math.'+o+';\n';
+            }
+            numeric[i+'eqV'] = numeric.pointwise2(['ret[i]'],'ret[i] = '+o+'(ret[i]);',setup);
+            numeric[i+'eq'] = Function('x',
+                    'if(typeof x !== "object") return '+o+'x\n'+
+                    'var i;\n'+
+                    'var V = numeric.'+i+'eqV;\n'+
+                    'var s = numeric.dim(x);\n'+
+                    'numeric._foreach(x,s,0,V);\n'+
+                    'return x;\n');
+            numeric[i+'V'] = numeric.pointwise2(['x[i]'],'ret[i] = '+o+'(x[i]);',setup);
+            numeric[i] = Function('x',
+                    'if(typeof x !== "object") return '+o+'(x)\n'+
+                    'var i;\n'+
+                    'var V = numeric.'+i+'V;\n'+
+                    'var s = numeric.dim(x);\n'+
+                    'return numeric._foreach2(x,s,0,V);\n');
+        }
+    }
+    for(i=0;i<numeric.mathfuns.length;++i) {
+        o = numeric.mathfuns[i];
+        delete numeric.ops1[o];
+    }
+    for(i in numeric.mapreducers) {
+        if(numeric.mapreducers.hasOwnProperty(i)) {
+            o = numeric.mapreducers[i];
+            numeric[i+'V'] = numeric.mapreduce2(o[0],o[1]);
+            numeric[i] = Function('x','s','k',
+                    o[1]+
+                    'if(typeof x !== "object") {'+
+                    '    xi = x;\n'+
+                    o[0]+';\n'+
+                    '    return accum;\n'+
+                    '}'+
+                    'if(typeof s === "undefined") s = numeric.dim(x);\n'+
+                    'if(typeof k === "undefined") k = 0;\n'+
+                    'if(k === s.length-1) return numeric.'+i+'V(x);\n'+
+                    'var xi;\n'+
+                    'var n = x.length, i;\n'+
+                    'for(i=n-1;i!==-1;--i) {\n'+
+                    '   xi = arguments.callee(x[i]);\n'+
+                    o[0]+';\n'+
+                    '}\n'+
+                    'return accum;\n');
+        }
+    }
+}());
+
+numeric.truncVV = numeric.pointwise(['x[i]','y[i]'],'ret[i] = round(x[i]/y[i])*y[i];','var round = Math.round;');
+numeric.truncVS = numeric.pointwise(['x[i]','y'],'ret[i] = round(x[i]/y)*y;','var round = Math.round;');
+numeric.truncSV = numeric.pointwise(['x','y[i]'],'ret[i] = round(x/y[i])*y[i];','var round = Math.round;');
+numeric.trunc = function trunc(x,y) {
+    if(typeof x === "object") {
+        if(typeof y === "object") return numeric.truncVV(x,y);
+        return numeric.truncVS(x,y);
+    }
+    if (typeof y === "object") return numeric.truncSV(x,y);
+    return Math.round(x/y)*y;
+}
+
+numeric.inv = function inv(x) {
+    var s = numeric.dim(x), abs = Math.abs, m = s[0], n = s[1];
+    var A = numeric.clone(x), Ai, Aj;
+    var I = numeric.identity(m), Ii, Ij;
+    var i,j,k,x;
+    for(j=0;j<n;++j) {
+        var i0 = -1;
+        var v0 = -1;
+        for(i=j;i!==m;++i) { k = abs(A[i][j]); if(k>v0) { i0 = i; v0 = k; } }
+        Aj = A[i0]; A[i0] = A[j]; A[j] = Aj;
+        Ij = I[i0]; I[i0] = I[j]; I[j] = Ij;
+        x = Aj[j];
+        for(k=j;k!==n;++k)    Aj[k] /= x; 
+        for(k=n-1;k!==-1;--k) Ij[k] /= x;
+        for(i=m-1;i!==-1;--i) {
+            if(i!==j) {
+                Ai = A[i];
+                Ii = I[i];
+                x = Ai[j];
+                for(k=j+1;k!==n;++k)  Ai[k] -= Aj[k]*x;
+                for(k=n-1;k>0;--k) { Ii[k] -= Ij[k]*x; --k; Ii[k] -= Ij[k]*x; }
+                if(k===0) Ii[0] -= Ij[0]*x;
+            }
+        }
+    }
+    return I;
+}
+
+numeric.det = function det(x) {
+    var s = numeric.dim(x);
+    if(s.length !== 2 || s[0] !== s[1]) { throw new Error('numeric: det() only works on square matrices'); }
+    var n = s[0], ret = 1,i,j,k,A = numeric.clone(x),Aj,Ai,alpha,temp,k1,k2,k3;
+    for(j=0;j<n-1;j++) {
+        k=j;
+        for(i=j+1;i<n;i++) { if(Math.abs(A[i][j]) > Math.abs(A[k][j])) { k = i; } }
+        if(k !== j) {
+            temp = A[k]; A[k] = A[j]; A[j] = temp;
+            ret *= -1;
+        }
+        Aj = A[j];
+        for(i=j+1;i<n;i++) {
+            Ai = A[i];
+            alpha = Ai[j]/Aj[j];
+            for(k=j+1;k<n-1;k+=2) {
+                k1 = k+1;
+                Ai[k] -= Aj[k]*alpha;
+                Ai[k1] -= Aj[k1]*alpha;
+            }
+            if(k!==n) { Ai[k] -= Aj[k]*alpha; }
+        }
+        if(Aj[j] === 0) { return 0; }
+        ret *= Aj[j];
+    }
+    return ret*A[j][j];
+}
+
+numeric.transpose = function transpose(x) {
+    var i,j,m = x.length,n = x[0].length, ret=Array(n),A0,A1,Bj;
+    for(j=0;j<n;j++) ret[j] = Array(m);
+    for(i=m-1;i>=1;i-=2) {
+        A1 = x[i];
+        A0 = x[i-1];
+        for(j=n-1;j>=1;--j) {
+            Bj = ret[j]; Bj[i] = A1[j]; Bj[i-1] = A0[j];
+            --j;
+            Bj = ret[j]; Bj[i] = A1[j]; Bj[i-1] = A0[j];
+        }
+        if(j===0) {
+            Bj = ret[0]; Bj[i] = A1[0]; Bj[i-1] = A0[0];
+        }
+    }
+    if(i===0) {
+        A0 = x[0];
+        for(j=n-1;j>=1;--j) {
+            ret[j][0] = A0[j];
+            --j;
+            ret[j][0] = A0[j];
+        }
+        if(j===0) { ret[0][0] = A0[0]; }
+    }
+    return ret;
+}
+numeric.negtranspose = function negtranspose(x) {
+    var i,j,m = x.length,n = x[0].length, ret=Array(n),A0,A1,Bj;
+    for(j=0;j<n;j++) ret[j] = Array(m);
+    for(i=m-1;i>=1;i-=2) {
+        A1 = x[i];
+        A0 = x[i-1];
+        for(j=n-1;j>=1;--j) {
+            Bj = ret[j]; Bj[i] = -A1[j]; Bj[i-1] = -A0[j];
+            --j;
+            Bj = ret[j]; Bj[i] = -A1[j]; Bj[i-1] = -A0[j];
+        }
+        if(j===0) {
+            Bj = ret[0]; Bj[i] = -A1[0]; Bj[i-1] = -A0[0];
+        }
+    }
+    if(i===0) {
+        A0 = x[0];
+        for(j=n-1;j>=1;--j) {
+            ret[j][0] = -A0[j];
+            --j;
+            ret[j][0] = -A0[j];
+        }
+        if(j===0) { ret[0][0] = -A0[0]; }
+    }
+    return ret;
+}
+
+numeric._random = function _random(s,k) {
+    var i,n=s[k],ret=Array(n), rnd;
+    if(k === s.length-1) {
+        rnd = Math.random;
+        for(i=n-1;i>=1;i-=2) {
+            ret[i] = rnd();
+            ret[i-1] = rnd();
+        }
+        if(i===0) { ret[0] = rnd(); }
+        return ret;
+    }
+    for(i=n-1;i>=0;i--) ret[i] = _random(s,k+1);
+    return ret;
+}
+numeric.random = function random(s) { return numeric._random(s,0); }
+
+numeric.norm2 = function norm2(x) { return Math.sqrt(numeric.norm2Squared(x)); }
+
+numeric.linspace = function linspace(a,b,n) {
+    if(typeof n === "undefined") n = Math.max(Math.round(b-a)+1,1);
+    if(n<2) { return n===1?[a]:[]; }
+    var i,ret = Array(n);
+    n--;
+    for(i=n;i>=0;i--) { ret[i] = (i*b+(n-i)*a)/n; }
+    return ret;
+}
+
+numeric.getBlock = function getBlock(x,from,to) {
+    var s = numeric.dim(x);
+    function foo(x,k) {
+        var i,a = from[k], n = to[k]-a, ret = Array(n);
+        if(k === s.length-1) {
+            for(i=n;i>=0;i--) { ret[i] = x[i+a]; }
+            return ret;
+        }
+        for(i=n;i>=0;i--) { ret[i] = foo(x[i+a],k+1); }
+        return ret;
+    }
+    return foo(x,0);
+}
+
+numeric.setBlock = function setBlock(x,from,to,B) {
+    var s = numeric.dim(x);
+    function foo(x,y,k) {
+        var i,a = from[k], n = to[k]-a;
+        if(k === s.length-1) { for(i=n;i>=0;i--) { x[i+a] = y[i]; } }
+        for(i=n;i>=0;i--) { foo(x[i+a],y[i],k+1); }
+    }
+    foo(x,B,0);
+    return x;
+}
+
+numeric.getRange = function getRange(A,I,J) {
+    var m = I.length, n = J.length;
+    var i,j;
+    var B = Array(m), Bi, AI;
+    for(i=m-1;i!==-1;--i) {
+        B[i] = Array(n);
+        Bi = B[i];
+        AI = A[I[i]];
+        for(j=n-1;j!==-1;--j) Bi[j] = AI[J[j]];
+    }
+    return B;
+}
+
+numeric.blockMatrix = function blockMatrix(X) {
+    var s = numeric.dim(X);
+    if(s.length<4) return numeric.blockMatrix([X]);
+    var m=s[0],n=s[1],M,N,i,j,Xij;
+    M = 0; N = 0;
+    for(i=0;i<m;++i) M+=X[i][0].length;
+    for(j=0;j<n;++j) N+=X[0][j][0].length;
+    var Z = Array(M);
+    for(i=0;i<M;++i) Z[i] = Array(N);
+    var I=0,J,ZI,k,l,Xijk;
+    for(i=0;i<m;++i) {
+        J=N;
+        for(j=n-1;j!==-1;--j) {
+            Xij = X[i][j];
+            J -= Xij[0].length;
+            for(k=Xij.length-1;k!==-1;--k) {
+                Xijk = Xij[k];
+                ZI = Z[I+k];
+                for(l = Xijk.length-1;l!==-1;--l) ZI[J+l] = Xijk[l];
+            }
+        }
+        I += X[i][0].length;
+    }
+    return Z;
+}
+
+numeric.tensor = function tensor(x,y) {
+    if(typeof x === "number" || typeof y === "number") return numeric.mul(x,y);
+    var s1 = numeric.dim(x), s2 = numeric.dim(y);
+    if(s1.length !== 1 || s2.length !== 1) {
+        throw new Error('numeric: tensor product is only defined for vectors');
+    }
+    var m = s1[0], n = s2[0], A = Array(m), Ai, i,j,xi;
+    for(i=m-1;i>=0;i--) {
+        Ai = Array(n);
+        xi = x[i];
+        for(j=n-1;j>=3;--j) {
+            Ai[j] = xi * y[j];
+            --j;
+            Ai[j] = xi * y[j];
+            --j;
+            Ai[j] = xi * y[j];
+            --j;
+            Ai[j] = xi * y[j];
+        }
+        while(j>=0) { Ai[j] = xi * y[j]; --j; }
+        A[i] = Ai;
+    }
+    return A;
+}
+
+// 3. The Tensor type T
+numeric.T = function T(x,y) { this.x = x; this.y = y; }
+numeric.t = function t(x,y) { return new numeric.T(x,y); }
+
+numeric.Tbinop = function Tbinop(rr,rc,cr,cc,setup) {
+    var io = numeric.indexOf;
+    if(typeof setup !== "string") {
+        var k;
+        setup = '';
+        for(k in numeric) {
+            if(numeric.hasOwnProperty(k) && (rr.indexOf(k)>=0 || rc.indexOf(k)>=0 || cr.indexOf(k)>=0 || cc.indexOf(k)>=0) && k.length>1) {
+                setup += 'var '+k+' = numeric.'+k+';\n';
+            }
+        }
+    }
+    return Function(['y'],
+            'var x = this;\n'+
+            'if(!(y instanceof numeric.T)) { y = new numeric.T(y); }\n'+
+            setup+'\n'+
+            'if(x.y) {'+
+            '  if(y.y) {'+
+            '    return new numeric.T('+cc+');\n'+
+            '  }\n'+
+            '  return new numeric.T('+cr+');\n'+
+            '}\n'+
+            'if(y.y) {\n'+
+            '  return new numeric.T('+rc+');\n'+
+            '}\n'+
+            'return new numeric.T('+rr+');\n'
+    );
+}
+
+numeric.T.prototype.add = numeric.Tbinop(
+        'add(x.x,y.x)',
+        'add(x.x,y.x),y.y',
+        'add(x.x,y.x),x.y',
+        'add(x.x,y.x),add(x.y,y.y)');
+numeric.T.prototype.sub = numeric.Tbinop(
+        'sub(x.x,y.x)',
+        'sub(x.x,y.x),neg(y.y)',
+        'sub(x.x,y.x),x.y',
+        'sub(x.x,y.x),sub(x.y,y.y)');
+numeric.T.prototype.mul = numeric.Tbinop(
+        'mul(x.x,y.x)',
+        'mul(x.x,y.x),mul(x.x,y.y)',
+        'mul(x.x,y.x),mul(x.y,y.x)',
+        'sub(mul(x.x,y.x),mul(x.y,y.y)),add(mul(x.x,y.y),mul(x.y,y.x))');
+
+numeric.T.prototype.reciprocal = function reciprocal() {
+    var mul = numeric.mul, div = numeric.div;
+    if(this.y) {
+        var d = numeric.add(mul(this.x,this.x),mul(this.y,this.y));
+        return new numeric.T(div(this.x,d),div(numeric.neg(this.y),d));
+    }
+    return new T(div(1,this.x));
+}
+numeric.T.prototype.div = function div(y) {
+    if(!(y instanceof numeric.T)) y = new numeric.T(y);
+    if(y.y) { return this.mul(y.reciprocal()); }
+    var div = numeric.div;
+    if(this.y) { return new numeric.T(div(this.x,y.x),div(this.y,y.x)); }
+    return new numeric.T(div(this.x,y.x));
+}
+numeric.T.prototype.dot = numeric.Tbinop(
+        'dot(x.x,y.x)',
+        'dot(x.x,y.x),dot(x.x,y.y)',
+        'dot(x.x,y.x),dot(x.y,y.x)',
+        'sub(dot(x.x,y.x),dot(x.y,y.y)),add(dot(x.x,y.y),dot(x.y,y.x))'
+        );
+numeric.T.prototype.transpose = function transpose() {
+    var t = numeric.transpose, x = this.x, y = this.y;
+    if(y) { return new numeric.T(t(x),t(y)); }
+    return new numeric.T(t(x));
+}
+numeric.T.prototype.transjugate = function transjugate() {
+    var t = numeric.transpose, x = this.x, y = this.y;
+    if(y) { return new numeric.T(t(x),numeric.negtranspose(y)); }
+    return new numeric.T(t(x));
+}
+numeric.Tunop = function Tunop(r,c,s) {
+    if(typeof s !== "string") { s = ''; }
+    return Function(
+            'var x = this;\n'+
+            s+'\n'+
+            'if(x.y) {'+
+            '  '+c+';\n'+
+            '}\n'+
+            r+';\n'
+    );
+}
+
+numeric.T.prototype.exp = numeric.Tunop(
+        'return new numeric.T(ex)',
+        'return new numeric.T(mul(cos(x.y),ex),mul(sin(x.y),ex))',
+        'var ex = numeric.exp(x.x), cos = numeric.cos, sin = numeric.sin, mul = numeric.mul;');
+numeric.T.prototype.conj = numeric.Tunop(
+        'return new numeric.T(x.x);',
+        'return new numeric.T(x.x,numeric.neg(x.y));');
+numeric.T.prototype.neg = numeric.Tunop(
+        'return new numeric.T(neg(x.x));',
+        'return new numeric.T(neg(x.x),neg(x.y));',
+        'var neg = numeric.neg;');
+numeric.T.prototype.sin = numeric.Tunop(
+        'return new numeric.T(numeric.sin(x.x))',
+        'return x.exp().sub(x.neg().exp()).div(new numeric.T(0,2));');
+numeric.T.prototype.cos = numeric.Tunop(
+        'return new numeric.T(numeric.cos(x.x))',
+        'return x.exp().add(x.neg().exp()).div(2);');
+numeric.T.prototype.abs = numeric.Tunop(
+        'return new numeric.T(numeric.abs(x.x));',
+        'return new numeric.T(numeric.sqrt(numeric.add(mul(x.x,x.x),mul(x.y,x.y))));',
+        'var mul = numeric.mul;');
+numeric.T.prototype.log = numeric.Tunop(
+        'return new numeric.T(numeric.log(x.x));',
+        'var theta = new numeric.T(numeric.atan2(x.y,x.x)), r = x.abs();\n'+
+        'return new numeric.T(numeric.log(r.x),theta.x);');
+numeric.T.prototype.norm2 = numeric.Tunop(
+        'return numeric.norm2(x.x);',
+        'var f = numeric.norm2Squared;\n'+
+        'return Math.sqrt(f(x.x)+f(x.y));');
+numeric.T.prototype.inv = function inv() {
+    var A = this;
+    if(typeof A.y === "undefined") { return new numeric.T(numeric.inv(A.x)); }
+    var n = A.x.length, i, j, k;
+    var Rx = numeric.identity(n),Ry = numeric.rep([n,n],0);
+    var Ax = numeric.clone(A.x), Ay = numeric.clone(A.y);
+    var Aix, Aiy, Ajx, Ajy, Rix, Riy, Rjx, Rjy;
+    var i,j,k,d,d1,ax,ay,bx,by,temp;
+    for(i=0;i<n;i++) {
+        ax = Ax[i][i]; ay = Ay[i][i];
+        d = ax*ax+ay*ay;
+        k = i;
+        for(j=i+1;j<n;j++) {
+            ax = Ax[j][i]; ay = Ay[j][i];
+            d1 = ax*ax+ay*ay;
+            if(d1 > d) { k=j; d = d1; }
+        }
+        if(k!==i) {
+            temp = Ax[i]; Ax[i] = Ax[k]; Ax[k] = temp;
+            temp = Ay[i]; Ay[i] = Ay[k]; Ay[k] = temp;
+            temp = Rx[i]; Rx[i] = Rx[k]; Rx[k] = temp;
+            temp = Ry[i]; Ry[i] = Ry[k]; Ry[k] = temp;
+        }
+        Aix = Ax[i]; Aiy = Ay[i];
+        Rix = Rx[i]; Riy = Ry[i];
+        ax = Aix[i]; ay = Aiy[i];
+        for(j=i+1;j<n;j++) {
+            bx = Aix[j]; by = Aiy[j];
+            Aix[j] = (bx*ax+by*ay)/d;
+            Aiy[j] = (by*ax-bx*ay)/d;
+        }
+        for(j=0;j<n;j++) {
+            bx = Rix[j]; by = Riy[j];
+            Rix[j] = (bx*ax+by*ay)/d;
+            Riy[j] = (by*ax-bx*ay)/d;
+        }
+        for(j=i+1;j<n;j++) {
+            Ajx = Ax[j]; Ajy = Ay[j];
+            Rjx = Rx[j]; Rjy = Ry[j];
+            ax = Ajx[i]; ay = Ajy[i];
+            for(k=i+1;k<n;k++) {
+                bx = Aix[k]; by = Aiy[k];
+                Ajx[k] -= bx*ax-by*ay;
+                Ajy[k] -= by*ax+bx*ay;
+            }
+            for(k=0;k<n;k++) {
+                bx = Rix[k]; by = Riy[k];
+                Rjx[k] -= bx*ax-by*ay;
+                Rjy[k] -= by*ax+bx*ay;
+            }
+        }
+    }
+    for(i=n-1;i>0;i--) {
+        Rix = Rx[i]; Riy = Ry[i];
+        for(j=i-1;j>=0;j--) {
+            Rjx = Rx[j]; Rjy = Ry[j];
+            ax = Ax[j][i]; ay = Ay[j][i];
+            for(k=n-1;k>=0;k--) {
+                bx = Rix[k]; by = Riy[k];
+                Rjx[k] -= ax*bx - ay*by;
+                Rjy[k] -= ax*by + ay*bx;
+            }
+        }
+    }
+    return new numeric.T(Rx,Ry);
+}
+numeric.T.prototype.get = function get(i) {
+    var x = this.x, y = this.y, k = 0, ik, n = i.length;
+    if(y) {
+        while(k<n) {
+            ik = i[k];
+            x = x[ik];
+            y = y[ik];
+            k++;
+        }
+        return new numeric.T(x,y);
+    }
+    while(k<n) {
+        ik = i[k];
+        x = x[ik];
+        k++;
+    }
+    return new numeric.T(x);
+}
+numeric.T.prototype.set = function set(i,v) {
+    var x = this.x, y = this.y, k = 0, ik, n = i.length, vx = v.x, vy = v.y;
+    if(n===0) {
+        if(vy) { this.y = vy; }
+        else if(y) { this.y = undefined; }
+        this.x = x;
+        return this;
+    }
+    if(vy) {
+        if(y) { /* ok */ }
+        else {
+            y = numeric.rep(numeric.dim(x),0);
+            this.y = y;
+        }
+        while(k<n-1) {
+            ik = i[k];
+            x = x[ik];
+            y = y[ik];
+            k++;
+        }
+        ik = i[k];
+        x[ik] = vx;
+        y[ik] = vy;
+        return this;
+    }
+    if(y) {
+        while(k<n-1) {
+            ik = i[k];
+            x = x[ik];
+            y = y[ik];
+            k++;
+        }
+        ik = i[k];
+        x[ik] = vx;
+        if(vx instanceof Array) y[ik] = numeric.rep(numeric.dim(vx),0);
+        else y[ik] = 0;
+        return this;
+    }
+    while(k<n-1) {
+        ik = i[k];
+        x = x[ik];
+        k++;
+    }
+    ik = i[k];
+    x[ik] = vx;
+    return this;
+}
+numeric.T.prototype.getRows = function getRows(i0,i1) {
+    var n = i1-i0+1, j;
+    var rx = Array(n), ry, x = this.x, y = this.y;
+    for(j=i0;j<=i1;j++) { rx[j-i0] = x[j]; }
+    if(y) {
+        ry = Array(n);
+        for(j=i0;j<=i1;j++) { ry[j-i0] = y[j]; }
+        return new numeric.T(rx,ry);
+    }
+    return new numeric.T(rx);
+}
+numeric.T.prototype.setRows = function setRows(i0,i1,A) {
+    var j;
+    var rx = this.x, ry = this.y, x = A.x, y = A.y;
+    for(j=i0;j<=i1;j++) { rx[j] = x[j-i0]; }
+    if(y) {
+        if(!ry) { ry = numeric.rep(numeric.dim(rx),0); this.y = ry; }
+        for(j=i0;j<=i1;j++) { ry[j] = y[j-i0]; }
+    } else if(ry) {
+        for(j=i0;j<=i1;j++) { ry[j] = numeric.rep([x[j-i0].length],0); }
+    }
+    return this;
+}
+numeric.T.prototype.getRow = function getRow(k) {
+    var x = this.x, y = this.y;
+    if(y) { return new numeric.T(x[k],y[k]); }
+    return new numeric.T(x[k]);
+}
+numeric.T.prototype.setRow = function setRow(i,v) {
+    var rx = this.x, ry = this.y, x = v.x, y = v.y;
+    rx[i] = x;
+    if(y) {
+        if(!ry) { ry = numeric.rep(numeric.dim(rx),0); this.y = ry; }
+        ry[i] = y;
+    } else if(ry) {
+        ry = numeric.rep([x.length],0);
+    }
+    return this;
+}
+
+numeric.T.prototype.getBlock = function getBlock(from,to) {
+    var x = this.x, y = this.y, b = numeric.getBlock;
+    if(y) { return new numeric.T(b(x,from,to),b(y,from,to)); }
+    return new numeric.T(b(x,from,to));
+}
+numeric.T.prototype.setBlock = function setBlock(from,to,A) {
+    if(!(A instanceof numeric.T)) A = new numeric.T(A);
+    var x = this.x, y = this.y, b = numeric.setBlock, Ax = A.x, Ay = A.y;
+    if(Ay) {
+        if(!y) { this.y = numeric.rep(numeric.dim(this),0); y = this.y; }
+        b(x,from,to,Ax);
+        b(y,from,to,Ay);
+        return this;
+    }
+    b(x,from,to,Ax);
+    if(y) b(y,from,to,numeric.rep(numeric.dim(Ax),0));
+}
+numeric.T.rep = function rep(s,v) {
+    var T = numeric.T;
+    if(!(v instanceof T)) v = new T(v);
+    var x = v.x, y = v.y, r = numeric.rep;
+    if(y) return new T(r(s,x),r(s,y));
+    return new T(r(s,x));
+}
+numeric.T.diag = function diag(d) {
+    if(!(d instanceof numeric.T)) d = new numeric.T(d);
+    var x = d.x, y = d.y, diag = numeric.diag;
+    if(y) return new numeric.T(diag(x),diag(y));
+    return new numeric.T(diag(x));
+}
+numeric.T.eig = function eig() {
+    if(this.y) { throw new Error('eig: not implemented for complex matrices.'); }
+    return numeric.eig(this.x);
+}
+numeric.T.identity = function identity(n) { return new numeric.T(numeric.identity(n)); }
+numeric.T.prototype.getDiag = function getDiag() {
+    var n = numeric;
+    var x = this.x, y = this.y;
+    if(y) { return new n.T(n.getDiag(x),n.getDiag(y)); }
+    return new n.T(n.getDiag(x));
+}
+
+// 4. Eigenvalues of real matrices
+
+numeric.house = function house(x) {
+    var v = numeric.clone(x);
+    var s = x[0] >= 0 ? 1 : -1;
+    var alpha = s*numeric.norm2(x);
+    v[0] += alpha;
+    var foo = numeric.norm2(v);
+    if(foo === 0) { /* this should not happen */ throw new Error('eig: internal error'); }
+    return numeric.div(v,foo);
+}
+
+numeric.toUpperHessenberg = function toUpperHessenberg(me) {
+    var s = numeric.dim(me);
+    if(s.length !== 2 || s[0] !== s[1]) { throw new Error('numeric: toUpperHessenberg() only works on square matrices'); }
+    var m = s[0], i,j,k,x,v,A = numeric.clone(me),B,C,Ai,Ci,Q = numeric.identity(m),Qi;
+    for(j=0;j<m-2;j++) {
+        x = Array(m-j-1);
+        for(i=j+1;i<m;i++) { x[i-j-1] = A[i][j]; }
+        if(numeric.norm2(x)>0) {
+            v = numeric.house(x);
+            B = numeric.getBlock(A,[j+1,j],[m-1,m-1]);
+            C = numeric.tensor(v,numeric.dot(v,B));
+            for(i=j+1;i<m;i++) { Ai = A[i]; Ci = C[i-j-1]; for(k=j;k<m;k++) Ai[k] -= 2*Ci[k-j]; }
+            B = numeric.getBlock(A,[0,j+1],[m-1,m-1]);
+            C = numeric.tensor(numeric.dot(B,v),v);
+            for(i=0;i<m;i++) { Ai = A[i]; Ci = C[i]; for(k=j+1;k<m;k++) Ai[k] -= 2*Ci[k-j-1]; }
+            B = Array(m-j-1);
+            for(i=j+1;i<m;i++) B[i-j-1] = Q[i];
+            C = numeric.tensor(v,numeric.dot(v,B));
+            for(i=j+1;i<m;i++) { Qi = Q[i]; Ci = C[i-j-1]; for(k=0;k<m;k++) Qi[k] -= 2*Ci[k]; }
+        }
+    }
+    return {H:A, Q:Q};
+}
+
+numeric.epsilon = 2.220446049250313e-16;
+
+numeric.QRFrancis = function(H,maxiter) {
+    if(typeof maxiter === "undefined") { maxiter = 10000; }
+    H = numeric.clone(H);
+    var H0 = numeric.clone(H);
+    var s = numeric.dim(H),m=s[0],x,v,a,b,c,d,det,tr, Hloc, Q = numeric.identity(m), Qi, Hi, B, C, Ci,i,j,k,iter;
+    if(m<3) { return {Q:Q, B:[ [0,m-1] ]}; }
+    var epsilon = numeric.epsilon;
+    for(iter=0;iter<maxiter;iter++) {
+        for(j=0;j<m-1;j++) {
+            if(Math.abs(H[j+1][j]) < epsilon*(Math.abs(H[j][j])+Math.abs(H[j+1][j+1]))) {
+                var QH1 = numeric.QRFrancis(numeric.getBlock(H,[0,0],[j,j]),maxiter);
+                var QH2 = numeric.QRFrancis(numeric.getBlock(H,[j+1,j+1],[m-1,m-1]),maxiter);
+                B = Array(j+1);
+                for(i=0;i<=j;i++) { B[i] = Q[i]; }
+                C = numeric.dot(QH1.Q,B);
+                for(i=0;i<=j;i++) { Q[i] = C[i]; }
+                B = Array(m-j-1);
+                for(i=j+1;i<m;i++) { B[i-j-1] = Q[i]; }
+                C = numeric.dot(QH2.Q,B);
+                for(i=j+1;i<m;i++) { Q[i] = C[i-j-1]; }
+                return {Q:Q,B:QH1.B.concat(numeric.add(QH2.B,j+1))};
+            }
+        }
+        a = H[m-2][m-2]; b = H[m-2][m-1];
+        c = H[m-1][m-2]; d = H[m-1][m-1];
+        tr = a+d;
+        det = (a*d-b*c);
+        Hloc = numeric.getBlock(H, [0,0], [2,2]);
+        if(tr*tr>=4*det) {
+            var s1,s2;
+            s1 = 0.5*(tr+Math.sqrt(tr*tr-4*det));
+            s2 = 0.5*(tr-Math.sqrt(tr*tr-4*det));
+            Hloc = numeric.add(numeric.sub(numeric.dot(Hloc,Hloc),
+                                           numeric.mul(Hloc,s1+s2)),
+                               numeric.diag(numeric.rep([3],s1*s2)));
+        } else {
+            Hloc = numeric.add(numeric.sub(numeric.dot(Hloc,Hloc),
+                                           numeric.mul(Hloc,tr)),
+                               numeric.diag(numeric.rep([3],det)));
+        }
+        x = [Hloc[0][0],Hloc[1][0],Hloc[2][0]];
+        v = numeric.house(x);
+        B = [H[0],H[1],H[2]];
+        C = numeric.tensor(v,numeric.dot(v,B));
+        for(i=0;i<3;i++) { Hi = H[i]; Ci = C[i]; for(k=0;k<m;k++) Hi[k] -= 2*Ci[k]; }
+        B = numeric.getBlock(H, [0,0],[m-1,2]);
+        C = numeric.tensor(numeric.dot(B,v),v);
+        for(i=0;i<m;i++) { Hi = H[i]; Ci = C[i]; for(k=0;k<3;k++) Hi[k] -= 2*Ci[k]; }
+        B = [Q[0],Q[1],Q[2]];
+        C = numeric.tensor(v,numeric.dot(v,B));
+        for(i=0;i<3;i++) { Qi = Q[i]; Ci = C[i]; for(k=0;k<m;k++) Qi[k] -= 2*Ci[k]; }
+        var J;
+        for(j=0;j<m-2;j++) {
+            for(k=j;k<=j+1;k++) {
+                if(Math.abs(H[k+1][k]) < epsilon*(Math.abs(H[k][k])+Math.abs(H[k+1][k+1]))) {
+                    var QH1 = numeric.QRFrancis(numeric.getBlock(H,[0,0],[k,k]),maxiter);
+                    var QH2 = numeric.QRFrancis(numeric.getBlock(H,[k+1,k+1],[m-1,m-1]),maxiter);
+                    B = Array(k+1);
+                    for(i=0;i<=k;i++) { B[i] = Q[i]; }
+                    C = numeric.dot(QH1.Q,B);
+                    for(i=0;i<=k;i++) { Q[i] = C[i]; }
+                    B = Array(m-k-1);
+                    for(i=k+1;i<m;i++) { B[i-k-1] = Q[i]; }
+                    C = numeric.dot(QH2.Q,B);
+                    for(i=k+1;i<m;i++) { Q[i] = C[i-k-1]; }
+                    return {Q:Q,B:QH1.B.concat(numeric.add(QH2.B,k+1))};
+                }
+            }
+            J = Math.min(m-1,j+3);
+            x = Array(J-j);
+            for(i=j+1;i<=J;i++) { x[i-j-1] = H[i][j]; }
+            v = numeric.house(x);
+            B = numeric.getBlock(H, [j+1,j],[J,m-1]);
+            C = numeric.tensor(v,numeric.dot(v,B));
+            for(i=j+1;i<=J;i++) { Hi = H[i]; Ci = C[i-j-1]; for(k=j;k<m;k++) Hi[k] -= 2*Ci[k-j]; }
+            B = numeric.getBlock(H, [0,j+1],[m-1,J]);
+            C = numeric.tensor(numeric.dot(B,v),v);
+            for(i=0;i<m;i++) { Hi = H[i]; Ci = C[i]; for(k=j+1;k<=J;k++) Hi[k] -= 2*Ci[k-j-1]; }
+            B = Array(J-j);
+            for(i=j+1;i<=J;i++) B[i-j-1] = Q[i];
+            C = numeric.tensor(v,numeric.dot(v,B));
+            for(i=j+1;i<=J;i++) { Qi = Q[i]; Ci = C[i-j-1]; for(k=0;k<m;k++) Qi[k] -= 2*Ci[k]; }
+        }
+    }
+    throw new Error('numeric: eigenvalue iteration does not converge -- increase maxiter?');
+}
+
+numeric.eig = function eig(A,maxiter) {
+    var QH = numeric.toUpperHessenberg(A);
+    var QB = numeric.QRFrancis(QH.H,maxiter);
+    var T = numeric.T;
+    var n = A.length,i,k,flag = false,B = QB.B,H = numeric.dot(QB.Q,numeric.dot(QH.H,numeric.transpose(QB.Q)));
+    var Q = new T(numeric.dot(QB.Q,QH.Q)),Q0;
+    var m = B.length,j;
+    var a,b,c,d,p1,p2,disc,x,y,p,q,n1,n2;
+    var sqrt = Math.sqrt;
+    for(k=0;k<m;k++) {
+        i = B[k][0];
+        if(i === B[k][1]) {
+            // nothing
+        } else {
+            j = i+1;
+            a = H[i][i];
+            b = H[i][j];
+            c = H[j][i];
+            d = H[j][j];
+            if(b === 0 && c === 0) continue;
+            p1 = -a-d;
+            p2 = a*d-b*c;
+            disc = p1*p1-4*p2;
+            if(disc>=0) {
+                if(p1<0) x = -0.5*(p1-sqrt(disc));
+                else     x = -0.5*(p1+sqrt(disc));
+                n1 = (a-x)*(a-x)+b*b;
+                n2 = c*c+(d-x)*(d-x);
+                if(n1>n2) {
+                    n1 = sqrt(n1);
+                    p = (a-x)/n1;
+                    q = b/n1;
+                } else {
+                    n2 = sqrt(n2);
+                    p = c/n2;
+                    q = (d-x)/n2;
+                }
+                Q0 = new T([[q,-p],[p,q]]);
+                Q.setRows(i,j,Q0.dot(Q.getRows(i,j)));
+            } else {
+                x = -0.5*p1;
+                y = 0.5*sqrt(-disc);
+                n1 = (a-x)*(a-x)+b*b;
+                n2 = c*c+(d-x)*(d-x);
+                if(n1>n2) {
+                    n1 = sqrt(n1+y*y);
+                    p = (a-x)/n1;
+                    q = b/n1;
+                    x = 0;
+                    y /= n1;
+                } else {
+                    n2 = sqrt(n2+y*y);
+                    p = c/n2;
+                    q = (d-x)/n2;
+                    x = y/n2;
+                    y = 0;
+                }
+                Q0 = new T([[q,-p],[p,q]],[[x,y],[y,-x]]);
+                Q.setRows(i,j,Q0.dot(Q.getRows(i,j)));
+            }
+        }
+    }
+    var R = Q.dot(A).dot(Q.transjugate()), n = A.length, E = numeric.T.identity(n);
+    for(j=0;j<n;j++) {
+        if(j>0) {
+            for(k=j-1;k>=0;k--) {
+                var Rk = R.get([k,k]), Rj = R.get([j,j]);
+                if(numeric.neq(Rk.x,Rj.x) || numeric.neq(Rk.y,Rj.y)) {
+                    x = R.getRow(k).getBlock([k],[j-1]);
+                    y = E.getRow(j).getBlock([k],[j-1]);
+                    E.set([j,k],(R.get([k,j]).neg().sub(x.dot(y))).div(Rk.sub(Rj)));
+                } else {
+                    E.setRow(j,E.getRow(k));
+                    continue;
+                }
+            }
+        }
+    }
+    for(j=0;j<n;j++) {
+        x = E.getRow(j);
+        E.setRow(j,x.div(x.norm2()));
+    }
+    E = E.transpose();
+    E = Q.transjugate().dot(E);
+    return { lambda:R.getDiag(), E:E };
+};
+
+// 5. Compressed Column Storage matrices
+numeric.ccsSparse = function ccsSparse(A) {
+    var m = A.length,n,foo, i,j, counts = [];
+    for(i=m-1;i!==-1;--i) {
+        foo = A[i];
+        for(j in foo) {
+            j = parseInt(j);
+            while(j>=counts.length) counts[counts.length] = 0;
+            if(foo[j]!==0) counts[j]++;
+        }
+    }
+    var n = counts.length;
+    var Ai = Array(n+1);
+    Ai[0] = 0;
+    for(i=0;i<n;++i) Ai[i+1] = Ai[i] + counts[i];
+    var Aj = Array(Ai[n]), Av = Array(Ai[n]);
+    for(i=m-1;i!==-1;--i) {
+        foo = A[i];
+        for(j in foo) {
+            if(foo[j]!==0) {
+                counts[j]--;
+                Aj[Ai[j]+counts[j]] = i;
+                Av[Ai[j]+counts[j]] = foo[j];
+            }
+        }
+    }
+    return [Ai,Aj,Av];
+}
+numeric.ccsFull = function ccsFull(A) {
+    var Ai = A[0], Aj = A[1], Av = A[2], s = numeric.ccsDim(A), m = s[0], n = s[1], i,j,j0,j1,k;
+    var B = numeric.rep([m,n],0);
+    for(i=0;i<n;i++) {
+        j0 = Ai[i];
+        j1 = Ai[i+1];
+        for(j=j0;j<j1;++j) { B[Aj[j]][i] = Av[j]; }
+    }
+    return B;
+}
+numeric.ccsTSolve = function ccsTSolve(A,b,x,bj,xj) {
+    var Ai = A[0], Aj = A[1], Av = A[2],m = Ai.length-1, max = Math.max,n=0;
+    if(typeof bj === "undefined") x = numeric.rep([m],0);
+    if(typeof bj === "undefined") bj = numeric.linspace(0,x.length-1);
+    if(typeof xj === "undefined") xj = [];
+    function dfs(j) {
+        var k;
+        if(x[j] !== 0) return;
+        x[j] = 1;
+        for(k=Ai[j];k<Ai[j+1];++k) dfs(Aj[k]);
+        xj[n] = j;
+        ++n;
+    }
+    var i,j,j0,j1,k,l,l0,l1,a;
+    for(i=bj.length-1;i!==-1;--i) { dfs(bj[i]); }
+    xj.length = n;
+    for(i=xj.length-1;i!==-1;--i) { x[xj[i]] = 0; }
+    for(i=bj.length-1;i!==-1;--i) { j = bj[i]; x[j] = b[j]; }
+    for(i=xj.length-1;i!==-1;--i) {
+        j = xj[i];
+        j0 = Ai[j];
+        j1 = max(Ai[j+1],j0);
+        for(k=j0;k!==j1;++k) { if(Aj[k] === j) { x[j] /= Av[k]; break; } }
+        a = x[j];
+        for(k=j0;k!==j1;++k) {
+            l = Aj[k];
+            if(l !== j) x[l] -= a*Av[k];
+        }
+    }
+    return x;
+}
+numeric.ccsDFS = function ccsDFS(n) {
+    this.k = Array(n);
+    this.k1 = Array(n);
+    this.j = Array(n);
+}
+numeric.ccsDFS.prototype.dfs = function dfs(J,Ai,Aj,x,xj,Pinv) {
+    var m = 0,foo,n=xj.length;
+    var k = this.k, k1 = this.k1, j = this.j,km,k11;
+    if(x[J]!==0) return;
+    x[J] = 1;
+    j[0] = J;
+    k[0] = km = Ai[J];
+    k1[0] = k11 = Ai[J+1];
+    while(1) {
+        if(km >= k11) {
+            xj[n] = j[m];
+            if(m===0) return;
+            ++n;
+            --m;
+            km = k[m];
+            k11 = k1[m];
+        } else {
+            foo = Pinv[Aj[km]];
+            if(x[foo] === 0) {
+                x[foo] = 1;
+                k[m] = km;
+                ++m;
+                j[m] = foo;
+                km = Ai[foo];
+                k1[m] = k11 = Ai[foo+1];
+            } else ++km;
+        }
+    }
+}
+numeric.ccsLPSolve = function ccsLPSolve(A,B,x,xj,I,Pinv,dfs) {
+    var Ai = A[0], Aj = A[1], Av = A[2],m = Ai.length-1, n=0;
+    var Bi = B[0], Bj = B[1], Bv = B[2];
+    
+    var i,i0,i1,j,J,j0,j1,k,l,l0,l1,a;
+    i0 = Bi[I];
+    i1 = Bi[I+1];
+    xj.length = 0;
+    for(i=i0;i<i1;++i) { dfs.dfs(Pinv[Bj[i]],Ai,Aj,x,xj,Pinv); }
+    for(i=xj.length-1;i!==-1;--i) { x[xj[i]] = 0; }
+    for(i=i0;i!==i1;++i) { j = Pinv[Bj[i]]; x[j] = Bv[i]; }
+    for(i=xj.length-1;i!==-1;--i) {
+        j = xj[i];
+        j0 = Ai[j];
+        j1 = Ai[j+1];
+        for(k=j0;k<j1;++k) { if(Pinv[Aj[k]] === j) { x[j] /= Av[k]; break; } }
+        a = x[j];
+        for(k=j0;k<j1;++k) {
+            l = Pinv[Aj[k]];
+            if(l !== j) x[l] -= a*Av[k];
+        }
+    }
+    return x;
+}
+numeric.ccsLUP1 = function ccsLUP1(A,threshold) {
+    var m = A[0].length-1;
+    var L = [numeric.rep([m+1],0),[],[]], U = [numeric.rep([m+1], 0),[],[]];
+    var Li = L[0], Lj = L[1], Lv = L[2], Ui = U[0], Uj = U[1], Uv = U[2];
+    var x = numeric.rep([m],0), xj = numeric.rep([m],0);
+    var i,j,k,j0,j1,a,e,c,d,K;
+    var sol = numeric.ccsLPSolve, max = Math.max, abs = Math.abs;
+    var P = numeric.linspace(0,m-1),Pinv = numeric.linspace(0,m-1);
+    var dfs = new numeric.ccsDFS(m);
+    if(typeof threshold === "undefined") { threshold = 1; }
+    for(i=0;i<m;++i) {
+        sol(L,A,x,xj,i,Pinv,dfs);
+        a = -1;
+        e = -1;
+        for(j=xj.length-1;j!==-1;--j) {
+            k = xj[j];
+            if(k <= i) continue;
+            c = abs(x[k]);
+            if(c > a) { e = k; a = c; }
+        }
+        if(abs(x[i])<threshold*a) {
+            j = P[i];
+            a = P[e];
+            P[i] = a; Pinv[a] = i;
+            P[e] = j; Pinv[j] = e;
+            a = x[i]; x[i] = x[e]; x[e] = a;
+        }
+        a = Li[i];
+        e = Ui[i];
+        d = x[i];
+        Lj[a] = P[i];
+        Lv[a] = 1;
+        ++a;
+        for(j=xj.length-1;j!==-1;--j) {
+            k = xj[j];
+            c = x[k];
+            xj[j] = 0;
+            x[k] = 0;
+            if(k<=i) { Uj[e] = k; Uv[e] = c;   ++e; }
+            else     { Lj[a] = P[k]; Lv[a] = c/d; ++a; }
+        }
+        Li[i+1] = a;
+        Ui[i+1] = e;
+    }
+    for(j=Lj.length-1;j!==-1;--j) { Lj[j] = Pinv[Lj[j]]; }
+    return {L:L, U:U, P:P, Pinv:Pinv};
+}
+numeric.ccsDFS0 = function ccsDFS0(n) {
+    this.k = Array(n);
+    this.k1 = Array(n);
+    this.j = Array(n);
+}
+numeric.ccsDFS0.prototype.dfs = function dfs(J,Ai,Aj,x,xj,Pinv,P) {
+    var m = 0,foo,n=xj.length;
+    var k = this.k, k1 = this.k1, j = this.j,km,k11;
+    if(x[J]!==0) return;
+    x[J] = 1;
+    j[0] = J;
+    k[0] = km = Ai[Pinv[J]];
+    k1[0] = k11 = Ai[Pinv[J]+1];
+    while(1) {
+        if(isNaN(km)) throw new Error("Ow!");
+        if(km >= k11) {
+            xj[n] = Pinv[j[m]];
+            if(m===0) return;
+            ++n;
+            --m;
+            km = k[m];
+            k11 = k1[m];
+        } else {
+            foo = Aj[km];
+            if(x[foo] === 0) {
+                x[foo] = 1;
+                k[m] = km;
+                ++m;
+                j[m] = foo;
+                foo = Pinv[foo];
+                km = Ai[foo];
+                k1[m] = k11 = Ai[foo+1];
+            } else ++km;
+        }
+    }
+}
+numeric.ccsLPSolve0 = function ccsLPSolve0(A,B,y,xj,I,Pinv,P,dfs) {
+    var Ai = A[0], Aj = A[1], Av = A[2],m = Ai.length-1, n=0;
+    var Bi = B[0], Bj = B[1], Bv = B[2];
+    
+    var i,i0,i1,j,J,j0,j1,k,l,l0,l1,a;
+    i0 = Bi[I];
+    i1 = Bi[I+1];
+    xj.length = 0;
+    for(i=i0;i<i1;++i) { dfs.dfs(Bj[i],Ai,Aj,y,xj,Pinv,P); }
+    for(i=xj.length-1;i!==-1;--i) { j = xj[i]; y[P[j]] = 0; }
+    for(i=i0;i!==i1;++i) { j = Bj[i]; y[j] = Bv[i]; }
+    for(i=xj.length-1;i!==-1;--i) {
+        j = xj[i];
+        l = P[j];
+        j0 = Ai[j];
+        j1 = Ai[j+1];
+        for(k=j0;k<j1;++k) { if(Aj[k] === l) { y[l] /= Av[k]; break; } }
+        a = y[l];
+        for(k=j0;k<j1;++k) y[Aj[k]] -= a*Av[k];
+        y[l] = a;
+    }
+}
+numeric.ccsLUP0 = function ccsLUP0(A,threshold) {
+    var m = A[0].length-1;
+    var L = [numeric.rep([m+1],0),[],[]], U = [numeric.rep([m+1], 0),[],[]];
+    var Li = L[0], Lj = L[1], Lv = L[2], Ui = U[0], Uj = U[1], Uv = U[2];
+    var y = numeric.rep([m],0), xj = numeric.rep([m],0);
+    var i,j,k,j0,j1,a,e,c,d,K;
+    var sol = numeric.ccsLPSolve0, max = Math.max, abs = Math.abs;
+    var P = numeric.linspace(0,m-1),Pinv = numeric.linspace(0,m-1);
+    var dfs = new numeric.ccsDFS0(m);
+    if(typeof threshold === "undefined") { threshold = 1; }
+    for(i=0;i<m;++i) {
+        sol(L,A,y,xj,i,Pinv,P,dfs);
+        a = -1;
+        e = -1;
+        for(j=xj.length-1;j!==-1;--j) {
+            k = xj[j];
+            if(k <= i) continue;
+            c = abs(y[P[k]]);
+            if(c > a) { e = k; a = c; }
+        }
+        if(abs(y[P[i]])<threshold*a) {
+            j = P[i];
+            a = P[e];
+            P[i] = a; Pinv[a] = i;
+            P[e] = j; Pinv[j] = e;
+        }
+        a = Li[i];
+        e = Ui[i];
+        d = y[P[i]];
+        Lj[a] = P[i];
+        Lv[a] = 1;
+        ++a;
+        for(j=xj.length-1;j!==-1;--j) {
+            k = xj[j];
+            c = y[P[k]];
+            xj[j] = 0;
+            y[P[k]] = 0;
+            if(k<=i) { Uj[e] = k; Uv[e] = c;   ++e; }
+            else     { Lj[a] = P[k]; Lv[a] = c/d; ++a; }
+        }
+        Li[i+1] = a;
+        Ui[i+1] = e;
+    }
+    for(j=Lj.length-1;j!==-1;--j) { Lj[j] = Pinv[Lj[j]]; }
+    return {L:L, U:U, P:P, Pinv:Pinv};
+}
+numeric.ccsLUP = numeric.ccsLUP0;
+
+numeric.ccsDim = function ccsDim(A) { return [numeric.sup(A[1])+1,A[0].length-1]; }
+numeric.ccsGetBlock = function ccsGetBlock(A,i,j) {
+    var s = numeric.ccsDim(A),m=s[0],n=s[1];
+    if(typeof i === "undefined") { i = numeric.linspace(0,m-1); }
+    else if(typeof i === "number") { i = [i]; }
+    if(typeof j === "undefined") { j = numeric.linspace(0,n-1); }
+    else if(typeof j === "number") { j = [j]; }
+    var p,p0,p1,P = i.length,q,Q = j.length,r,jq,ip;
+    var Bi = numeric.rep([n],0), Bj=[], Bv=[], B = [Bi,Bj,Bv];
+    var Ai = A[0], Aj = A[1], Av = A[2];
+    var x = numeric.rep([m],0),count=0,flags = numeric.rep([m],0);
+    for(q=0;q<Q;++q) {
+        jq = j[q];
+        var q0 = Ai[jq];
+        var q1 = Ai[jq+1];
+        for(p=q0;p<q1;++p) {
+            r = Aj[p];
+            flags[r] = 1;
+            x[r] = Av[p];
+        }
+        for(p=0;p<P;++p) {
+            ip = i[p];
+            if(flags[ip]) {
+                Bj[count] = p;
+                Bv[count] = x[i[p]];
+                ++count;
+            }
+        }
+        for(p=q0;p<q1;++p) {
+            r = Aj[p];
+            flags[r] = 0;
+        }
+        Bi[q+1] = count;
+    }
+    return B;
+}
+
+numeric.ccsDot = function ccsDot(A,B) {
+    var Ai = A[0], Aj = A[1], Av = A[2];
+    var Bi = B[0], Bj = B[1], Bv = B[2];
+    var sA = numeric.ccsDim(A), sB = numeric.ccsDim(B);
+    var m = sA[0], n = sA[1], o = sB[1];
+    var x = numeric.rep([m],0), flags = numeric.rep([m],0), xj = Array(m);
+    var Ci = numeric.rep([o],0), Cj = [], Cv = [], C = [Ci,Cj,Cv];
+    var i,j,k,j0,j1,i0,i1,l,p,a,b;
+    for(k=0;k!==o;++k) {
+        j0 = Bi[k];
+        j1 = Bi[k+1];
+        p = 0;
+        for(j=j0;j<j1;++j) {
+            a = Bj[j];
+            b = Bv[j];
+            i0 = Ai[a];
+            i1 = Ai[a+1];
+            for(i=i0;i<i1;++i) {
+                l = Aj[i];
+                if(flags[l]===0) {
+                    xj[p] = l;
+                    flags[l] = 1;
+                    p = p+1;
+                }
+                x[l] = x[l] + Av[i]*b;
+            }
+        }
+        j0 = Ci[k];
+        j1 = j0+p;
+        Ci[k+1] = j1;
+        for(j=p-1;j!==-1;--j) {
+            b = j0+j;
+            i = xj[j];
+            Cj[b] = i;
+            Cv[b] = x[i];
+            flags[i] = 0;
+            x[i] = 0;
+        }
+        Ci[k+1] = Ci[k]+p;
+    }
+    return C;
+}
+
+numeric.ccsLUPSolve = function ccsLUPSolve(LUP,B) {
+    var L = LUP.L, U = LUP.U, P = LUP.P;
+    var Bi = B[0];
+    var flag = false;
+    if(typeof Bi !== "object") { B = [[0,B.length],numeric.linspace(0,B.length-1),B]; Bi = B[0]; flag = true; }
+    var Bj = B[1], Bv = B[2];
+    var n = L[0].length-1, m = Bi.length-1;
+    var x = numeric.rep([n],0), xj = Array(n);
+    var b = numeric.rep([n],0), bj = Array(n);
+    var Xi = numeric.rep([m+1],0), Xj = [], Xv = [];
+    var sol = numeric.ccsTSolve;
+    var i,j,j0,j1,k,J,N=0;
+    for(i=0;i<m;++i) {
+        k = 0;
+        j0 = Bi[i];
+        j1 = Bi[i+1];
+        for(j=j0;j<j1;++j) { 
+            J = LUP.Pinv[Bj[j]];
+            bj[k] = J;
+            b[J] = Bv[j];
+            ++k;
+        }
+        bj.length = k;
+        sol(L,b,x,bj,xj);
+        for(j=bj.length-1;j!==-1;--j) b[bj[j]] = 0;
+        sol(U,x,b,xj,bj);
+        if(flag) return b;
+        for(j=xj.length-1;j!==-1;--j) x[xj[j]] = 0;
+        for(j=bj.length-1;j!==-1;--j) {
+            J = bj[j];
+            Xj[N] = J;
+            Xv[N] = b[J];
+            b[J] = 0;
+            ++N;
+        }
+        Xi[i+1] = N;
+    }
+    return [Xi,Xj,Xv];
+}
+
+numeric.ccsbinop = function ccsbinop(body,setup) {
+    if(typeof setup === "undefined") setup='';
+    return Function('X','Y',
+            'var Xi = X[0], Xj = X[1], Xv = X[2];\n'+
+            'var Yi = Y[0], Yj = Y[1], Yv = Y[2];\n'+
+            'var n = Xi.length-1,m = Math.max(numeric.sup(Xj),numeric.sup(Yj))+1;\n'+
+            'var Zi = numeric.rep([n+1],0), Zj = [], Zv = [];\n'+
+            'var x = numeric.rep([m],0),y = numeric.rep([m],0);\n'+
+            'var xk,yk,zk;\n'+
+            'var i,j,j0,j1,k,p=0;\n'+
+            setup+
+            'for(i=0;i<n;++i) {\n'+
+            '  j0 = Xi[i]; j1 = Xi[i+1];\n'+
+            '  for(j=j0;j!==j1;++j) {\n'+
+            '    k = Xj[j];\n'+
+            '    x[k] = 1;\n'+
+            '    Zj[p] = k;\n'+
+            '    ++p;\n'+
+            '  }\n'+
+            '  j0 = Yi[i]; j1 = Yi[i+1];\n'+
+            '  for(j=j0;j!==j1;++j) {\n'+
+            '    k = Yj[j];\n'+
+            '    y[k] = Yv[j];\n'+
+            '    if(x[k] === 0) {\n'+
+            '      Zj[p] = k;\n'+
+            '      ++p;\n'+
+            '    }\n'+
+            '  }\n'+
+            '  Zi[i+1] = p;\n'+
+            '  j0 = Xi[i]; j1 = Xi[i+1];\n'+
+            '  for(j=j0;j!==j1;++j) x[Xj[j]] = Xv[j];\n'+
+            '  j0 = Zi[i]; j1 = Zi[i+1];\n'+
+            '  for(j=j0;j!==j1;++j) {\n'+
+            '    k = Zj[j];\n'+
+            '    xk = x[k];\n'+
+            '    yk = y[k];\n'+
+            body+'\n'+
+            '    Zv[j] = zk;\n'+
+            '  }\n'+
+            '  j0 = Xi[i]; j1 = Xi[i+1];\n'+
+            '  for(j=j0;j!==j1;++j) x[Xj[j]] = 0;\n'+
+            '  j0 = Yi[i]; j1 = Yi[i+1];\n'+
+            '  for(j=j0;j!==j1;++j) y[Yj[j]] = 0;\n'+
+            '}\n'+
+            'return [Zi,Zj,Zv];'
+            );
+};
+
+(function() {
+    var k,A,B,C;
+    for(k in numeric.ops2) {
+        if(isFinite(eval('1'+numeric.ops2[k]+'0'))) A = '[Y[0],Y[1],numeric.'+k+'(X,Y[2])]';
+        else A = 'NaN';
+        if(isFinite(eval('0'+numeric.ops2[k]+'1'))) B = '[X[0],X[1],numeric.'+k+'(X[2],Y)]';
+        else B = 'NaN';
+        if(isFinite(eval('1'+numeric.ops2[k]+'0')) && isFinite(eval('0'+numeric.ops2[k]+'1'))) C = 'numeric.ccs'+k+'MM(X,Y)';
+        else C = 'NaN';
+        numeric['ccs'+k+'MM'] = numeric.ccsbinop('zk = xk '+numeric.ops2[k]+'yk;');
+        numeric['ccs'+k] = Function('X','Y',
+                'if(typeof X === "number") return '+A+';\n'+
+                'if(typeof Y === "number") return '+B+';\n'+
+                'return '+C+';\n'
+                );
+    }
+}());
+
+numeric.ccsScatter = function ccsScatter(A) {
+    var Ai = A[0], Aj = A[1], Av = A[2];
+    var n = numeric.sup(Aj)+1,m=Ai.length;
+    var Ri = numeric.rep([n],0),Rj=Array(m), Rv = Array(m);
+    var counts = numeric.rep([n],0),i;
+    for(i=0;i<m;++i) counts[Aj[i]]++;
+    for(i=0;i<n;++i) Ri[i+1] = Ri[i] + counts[i];
+    var ptr = Ri.slice(0),k,Aii;
+    for(i=0;i<m;++i) {
+        Aii = Aj[i];
+        k = ptr[Aii];
+        Rj[k] = Ai[i];
+        Rv[k] = Av[i];
+        ptr[Aii]=ptr[Aii]+1;
+    }
+    return [Ri,Rj,Rv];
+}
+
+numeric.ccsGather = function ccsGather(A) {
+    var Ai = A[0], Aj = A[1], Av = A[2];
+    var n = Ai.length-1,m = Aj.length;
+    var Ri = Array(m), Rj = Array(m), Rv = Array(m);
+    var i,j,j0,j1,p;
+    p=0;
+    for(i=0;i<n;++i) {
+        j0 = Ai[i];
+        j1 = Ai[i+1];
+        for(j=j0;j!==j1;++j) {
+            Rj[p] = i;
+            Ri[p] = Aj[j];
+            Rv[p] = Av[j];
+            ++p;
+        }
+    }
+    return [Ri,Rj,Rv];
+}
+
+// The following sparse linear algebra routines are deprecated.
+
+numeric.sdim = function dim(A,ret,k) {
+    if(typeof ret === "undefined") { ret = []; }
+    if(typeof A !== "object") return ret;
+    if(typeof k === "undefined") { k=0; }
+    if(!(k in ret)) { ret[k] = 0; }
+    if(A.length > ret[k]) ret[k] = A.length;
+    var i;
+    for(i in A) {
+        if(A.hasOwnProperty(i)) dim(A[i],ret,k+1);
+    }
+    return ret;
+};
+
+numeric.sclone = function clone(A,k,n) {
+    if(typeof k === "undefined") { k=0; }
+    if(typeof n === "undefined") { n = numeric.sdim(A).length; }
+    var i,ret = Array(A.length);
+    if(k === n-1) {
+        for(i in A) { if(A.hasOwnProperty(i)) ret[i] = A[i]; }
+        return ret;
+    }
+    for(i in A) {
+        if(A.hasOwnProperty(i)) ret[i] = clone(A[i],k+1,n);
+    }
+    return ret;
+}
+
+numeric.sdiag = function diag(d) {
+    var n = d.length,i,ret = Array(n),i1,i2,i3;
+    for(i=n-1;i>=1;i-=2) {
+        i1 = i-1;
+        ret[i] = []; ret[i][i] = d[i];
+        ret[i1] = []; ret[i1][i1] = d[i1];
+    }
+    if(i===0) { ret[0] = []; ret[0][0] = d[i]; }
+    return ret;
+}
+
+numeric.sidentity = function identity(n) { return numeric.sdiag(numeric.rep([n],1)); }
+
+numeric.stranspose = function transpose(A) {
+    var ret = [], n = A.length, i,j,Ai;
+    for(i in A) {
+        if(!(A.hasOwnProperty(i))) continue;
+        Ai = A[i];
+        for(j in Ai) {
+            if(!(Ai.hasOwnProperty(j))) continue;
+            if(typeof ret[j] !== "object") { ret[j] = []; }
+            ret[j][i] = Ai[j];
+        }
+    }
+    return ret;
+}
+
+numeric.sLUP = function LUP(A,tol) {
+    throw new Error("The function numeric.sLUP had a bug in it and has been removed. Please use the new numeric.ccsLUP function instead.");
+};
+
+numeric.sdotMM = function dotMM(A,B) {
+    var p = A.length, q = B.length, BT = numeric.stranspose(B), r = BT.length, Ai, BTk;
+    var i,j,k,accum;
+    var ret = Array(p),reti;
+    for(i=p-1;i>=0;i--) {
+        reti = [];
+        Ai = A[i];
+        for(k=r-1;k>=0;k--) {
+            accum = 0;
+            BTk = BT[k];
+            for(j in Ai) {
+                if(!(Ai.hasOwnProperty(j))) continue;
+                if(j in BTk) { accum += Ai[j]*BTk[j]; }
+            }
+            if(accum) reti[k] = accum;
+        }
+        ret[i] = reti;
+    }
+    return ret;
+}
+
+numeric.sdotMV = function dotMV(A,x) {
+    var p = A.length, Ai, i,j;
+    var ret = Array(p), accum;
+    for(i=p-1;i>=0;i--) {
+        Ai = A[i];
+        accum = 0;
+        for(j in Ai) {
+            if(!(Ai.hasOwnProperty(j))) continue;
+            if(x[j]) accum += Ai[j]*x[j];
+        }
+        if(accum) ret[i] = accum;
+    }
+    return ret;
+}
+
+numeric.sdotVM = function dotMV(x,A) {
+    var i,j,Ai,alpha;
+    var ret = [], accum;
+    for(i in x) {
+        if(!x.hasOwnProperty(i)) continue;
+        Ai = A[i];
+        alpha = x[i];
+        for(j in Ai) {
+            if(!Ai.hasOwnProperty(j)) continue;
+            if(!ret[j]) { ret[j] = 0; }
+            ret[j] += alpha*Ai[j];
+        }
+    }
+    return ret;
+}
+
+numeric.sdotVV = function dotVV(x,y) {
+    var i,ret=0;
+    for(i in x) { if(x[i] && y[i]) ret+= x[i]*y[i]; }
+    return ret;
+}
+
+numeric.sdot = function dot(A,B) {
+    var m = numeric.sdim(A).length, n = numeric.sdim(B).length;
+    var k = m*1000+n;
+    switch(k) {
+    case 0: return A*B;
+    case 1001: return numeric.sdotVV(A,B);
+    case 2001: return numeric.sdotMV(A,B);
+    case 1002: return numeric.sdotVM(A,B);
+    case 2002: return numeric.sdotMM(A,B);
+    default: throw new Error('numeric.sdot not implemented for tensors of order '+m+' and '+n);
+    }
+}
+
+numeric.sscatter = function scatter(V) {
+    var n = V[0].length, Vij, i, j, m = V.length, A = [], Aj;
+    for(i=n-1;i>=0;--i) {
+        if(!V[m-1][i]) continue;
+        Aj = A;
+        for(j=0;j<m-2;j++) {
+            Vij = V[j][i];
+            if(!Aj[Vij]) Aj[Vij] = [];
+            Aj = Aj[Vij];
+        }
+        Aj[V[j][i]] = V[j+1][i];
+    }
+    return A;
+}
+
+numeric.sgather = function gather(A,ret,k) {
+    if(typeof ret === "undefined") ret = [];
+    if(typeof k === "undefined") k = [];
+    var n,i,Ai;
+    n = k.length;
+    for(i in A) {
+        if(A.hasOwnProperty(i)) {
+            k[n] = parseInt(i);
+            Ai = A[i];
+            if(typeof Ai === "number") {
+                if(Ai) {
+                    if(ret.length === 0) {
+                        for(i=n+1;i>=0;--i) ret[i] = [];
+                    }
+                    for(i=n;i>=0;--i) ret[i].push(k[i]);
+                    ret[n+1].push(Ai);
+                }
+            } else gather(Ai,ret,k);
+        }
+    }
+    if(k.length>n) k.pop();
+    return ret;
+}
+
+// 6. Coordinate matrices
+numeric.cLU = function LU(A) {
+    var I = A[0], J = A[1], V = A[2];
+    var p = I.length, m=0, i,j,k,a,b,c;
+    for(i=0;i<p;i++) if(I[i]>m) m=I[i];
+    m++;
+    var L = Array(m), U = Array(m), left = numeric.rep([m],Infinity), right = numeric.rep([m],-Infinity);
+    var Ui, Uj,alpha;
+    for(k=0;k<p;k++) {
+        i = I[k];
+        j = J[k];
+        if(j<left[i]) left[i] = j;
+        if(j>right[i]) right[i] = j;
+    }
+    for(i=0;i<m-1;i++) { if(right[i] > right[i+1]) right[i+1] = right[i]; }
+    for(i=m-1;i>=1;i--) { if(left[i]<left[i-1]) left[i-1] = left[i]; }
+    var countL = 0, countU = 0;
+    for(i=0;i<m;i++) {
+        U[i] = numeric.rep([right[i]-left[i]+1],0);
+        L[i] = numeric.rep([i-left[i]],0);
+        countL += i-left[i]+1;
+        countU += right[i]-i+1;
+    }
+    for(k=0;k<p;k++) { i = I[k]; U[i][J[k]-left[i]] = V[k]; }
+    for(i=0;i<m-1;i++) {
+        a = i-left[i];
+        Ui = U[i];
+        for(j=i+1;left[j]<=i && j<m;j++) {
+            b = i-left[j];
+            c = right[i]-i;
+            Uj = U[j];
+            alpha = Uj[b]/Ui[a];
+            if(alpha) {
+                for(k=1;k<=c;k++) { Uj[k+b] -= alpha*Ui[k+a]; }
+                L[j][i-left[j]] = alpha;
+            }
+        }
+    }
+    var Ui = [], Uj = [], Uv = [], Li = [], Lj = [], Lv = [];
+    var p,q,foo;
+    p=0; q=0;
+    for(i=0;i<m;i++) {
+        a = left[i];
+        b = right[i];
+        foo = U[i];
+        for(j=i;j<=b;j++) {
+            if(foo[j-a]) {
+                Ui[p] = i;
+                Uj[p] = j;
+                Uv[p] = foo[j-a];
+                p++;
+            }
+        }
+        foo = L[i];
+        for(j=a;j<i;j++) {
+            if(foo[j-a]) {
+                Li[q] = i;
+                Lj[q] = j;
+                Lv[q] = foo[j-a];
+                q++;
+            }
+        }
+        Li[q] = i;
+        Lj[q] = i;
+        Lv[q] = 1;
+        q++;
+    }
+    return {U:[Ui,Uj,Uv], L:[Li,Lj,Lv]};
+};
+
+numeric.cLUsolve = function LUsolve(lu,b) {
+    var L = lu.L, U = lu.U, ret = numeric.clone(b);
+    var Li = L[0], Lj = L[1], Lv = L[2];
+    var Ui = U[0], Uj = U[1], Uv = U[2];
+    var p = Ui.length, q = Li.length;
+    var m = ret.length,i,j,k;
+    k = 0;
+    for(i=0;i<m;i++) {
+        while(Lj[k] < i) {
+            ret[i] -= Lv[k]*ret[Lj[k]];
+            k++;
+        }
+        k++;
+    }
+    k = p-1;
+    for(i=m-1;i>=0;i--) {
+        while(Uj[k] > i) {
+            ret[i] -= Uv[k]*ret[Uj[k]];
+            k--;
+        }
+        ret[i] /= Uv[k];
+        k--;
+    }
+    return ret;
+};
+
+numeric.cgrid = function grid(n,shape) {
+    if(typeof n === "number") n = [n,n];
+    var ret = numeric.rep(n,-1);
+    var i,j,count;
+    if(typeof shape !== "function") {
+        switch(shape) {
+        case 'L':
+            shape = function(i,j) { return (i>=n[0]/2 || j<n[1]/2); }
+            break;
+        default:
+            shape = function(i,j) { return true; };
+            break;
+        }
+    }
+    count=0;
+    for(i=1;i<n[0]-1;i++) for(j=1;j<n[1]-1;j++) 
+        if(shape(i,j)) {
+            ret[i][j] = count;
+            count++;
+        }
+    return ret;
+}
+
+numeric.cdelsq = function delsq(g) {
+    var dir = [[-1,0],[0,-1],[0,1],[1,0]];
+    var s = numeric.dim(g), m = s[0], n = s[1], i,j,k,p,q;
+    var Li = [], Lj = [], Lv = [];
+    for(i=1;i<m-1;i++) for(j=1;j<n-1;j++) {
+        if(g[i][j]<0) continue;
+        for(k=0;k<4;k++) {
+            p = i+dir[k][0];
+            q = j+dir[k][1];
+            if(g[p][q]<0) continue;
+            Li.push(g[i][j]);
+            Lj.push(g[p][q]);
+            Lv.push(-1);
+        }
+        Li.push(g[i][j]);
+        Lj.push(g[i][j]);
+        Lv.push(4);
+    }
+    return [Li,Lj,Lv];
+}
+
+numeric.cdotMV = function dotMV(A,x) {
+    var ret, Ai = A[0], Aj = A[1], Av = A[2],k,p=Ai.length,N;
+    N=0;
+    for(k=0;k<p;k++) { if(Ai[k]>N) N = Ai[k]; }
+    N++;
+    ret = numeric.rep([N],0);
+    for(k=0;k<p;k++) { ret[Ai[k]]+=Av[k]*x[Aj[k]]; }
+    return ret;
+}
+
+// 7. Splines
+
+numeric.Spline = function Spline(x,yl,yr,kl,kr) { this.x = x; this.yl = yl; this.yr = yr; this.kl = kl; this.kr = kr; }
+numeric.Spline.prototype._at = function _at(x1,p) {
+    var x = this.x;
+    var yl = this.yl;
+    var yr = this.yr;
+    var kl = this.kl;
+    var kr = this.kr;
+    var x1,a,b,t;
+    var add = numeric.add, sub = numeric.sub, mul = numeric.mul;
+    a = sub(mul(kl[p],x[p+1]-x[p]),sub(yr[p+1],yl[p]));
+    b = add(mul(kr[p+1],x[p]-x[p+1]),sub(yr[p+1],yl[p]));
+    t = (x1-x[p])/(x[p+1]-x[p]);
+    var s = t*(1-t);
+    return add(add(add(mul(1-t,yl[p]),mul(t,yr[p+1])),mul(a,s*(1-t))),mul(b,s*t));
+}
+numeric.Spline.prototype.at = function at(x0) {
+    if(typeof x0 === "number") {
+        var x = this.x;
+        var n = x.length;
+        var p,q,mid,floor = Math.floor,a,b,t;
+        p = 0;
+        q = n-1;
+        while(q-p>1) {
+            mid = floor((p+q)/2);
+            if(x[mid] <= x0) p = mid;
+            else q = mid;
+        }
+        return this._at(x0,p);
+    }
+    var n = x0.length, i, ret = Array(n);
+    for(i=n-1;i!==-1;--i) ret[i] = this.at(x0[i]);
+    return ret;
+}
+numeric.Spline.prototype.diff = function diff() {
+    var x = this.x;
+    var yl = this.yl;
+    var yr = this.yr;
+    var kl = this.kl;
+    var kr = this.kr;
+    var n = yl.length;
+    var i,dx,dy;
+    var zl = kl, zr = kr, pl = Array(n), pr = Array(n);
+    var add = numeric.add, mul = numeric.mul, div = numeric.div, sub = numeric.sub;
+    for(i=n-1;i!==-1;--i) {
+        dx = x[i+1]-x[i];
+        dy = sub(yr[i+1],yl[i]);
+        pl[i] = div(add(mul(dy, 6),mul(kl[i],-4*dx),mul(kr[i+1],-2*dx)),dx*dx);
+        pr[i+1] = div(add(mul(dy,-6),mul(kl[i], 2*dx),mul(kr[i+1], 4*dx)),dx*dx);
+    }
+    return new numeric.Spline(x,zl,zr,pl,pr);
+}
+numeric.Spline.prototype.roots = function roots() {
+    function sqr(x) { return x*x; }
+    function heval(y0,y1,k0,k1,x) {
+        var A = k0*2-(y1-y0);
+        var B = -k1*2+(y1-y0);
+        var t = (x+1)*0.5;
+        var s = t*(1-t);
+        return (1-t)*y0+t*y1+A*s*(1-t)+B*s*t;
+    }
+    var ret = [];
+    var x = this.x, yl = this.yl, yr = this.yr, kl = this.kl, kr = this.kr;
+    if(typeof yl[0] === "number") {
+        yl = [yl];
+        yr = [yr];
+        kl = [kl];
+        kr = [kr];
+    }
+    var m = yl.length,n=x.length-1,i,j,k,y,s,t;
+    var ai,bi,ci,di, ret = Array(m),ri,k0,k1,y0,y1,A,B,D,dx,cx,stops,z0,z1,zm,t0,t1,tm;
+    var sqrt = Math.sqrt;
+    for(i=0;i!==m;++i) {
+        ai = yl[i];
+        bi = yr[i];
+        ci = kl[i];
+        di = kr[i];
+        ri = [];
+        for(j=0;j!==n;j++) {
+            if(j>0 && bi[j]*ai[j]<0) ri.push(x[j]);
+            dx = (x[j+1]-x[j]);
+            cx = x[j];
+            y0 = ai[j];
+            y1 = bi[j+1];
+            k0 = ci[j]/dx;
+            k1 = di[j+1]/dx;
+            D = sqr(k0-k1+3*(y0-y1)) + 12*k1*y0;
+            A = k1+3*y0+2*k0-3*y1;
+            B = 3*(k1+k0+2*(y0-y1));
+            if(D<=0) {
+                z0 = A/B;
+                if(z0>x[j] && z0<x[j+1]) stops = [x[j],z0,x[j+1]];
+                else stops = [x[j],x[j+1]];
+            } else {
+                z0 = (A-sqrt(D))/B;
+                z1 = (A+sqrt(D))/B;
+                stops = [x[j]];
+                if(z0>x[j] && z0<x[j+1]) stops.push(z0);
+                if(z1>x[j] && z1<x[j+1]) stops.push(z1);
+                stops.push(x[j+1]);
+            }
+            t0 = stops[0];
+            z0 = this._at(t0,j);
+            for(k=0;k<stops.length-1;k++) {
+                t1 = stops[k+1];
+                z1 = this._at(t1,j);
+                if(z0 === 0) {
+                    ri.push(t0); 
+                    t0 = t1;
+                    z0 = z1;
+                    continue;
+                }
+                if(z1 === 0 || z0*z1>0) {
+                    t0 = t1;
+                    z0 = z1;
+                    continue;
+                }
+                var side = 0;
+                while(1) {
+                    tm = (z0*t1-z1*t0)/(z0-z1);
+                    if(tm <= t0 || tm >= t1) { break; }
+                    zm = this._at(tm,j);
+                    if(zm*z1>0) {
+                        t1 = tm;
+                        z1 = zm;
+                        if(side === -1) z0*=0.5;
+                        side = -1;
+                    } else if(zm*z0>0) {
+                        t0 = tm;
+                        z0 = zm;
+                        if(side === 1) z1*=0.5;
+                        side = 1;
+                    } else break;
+                }
+                ri.push(tm);
+                t0 = stops[k+1];
+                z0 = this._at(t0, j);
+            }
+            if(z1 === 0) ri.push(t1);
+        }
+        ret[i] = ri;
+    }
+    if(typeof this.yl[0] === "number") return ret[0];
+    return ret;
+}
+numeric.spline = function spline(x,y,k1,kn) {
+    var n = x.length, b = [], dx = [], dy = [];
+    var i;
+    var sub = numeric.sub,mul = numeric.mul,add = numeric.add;
+    for(i=n-2;i>=0;i--) { dx[i] = x[i+1]-x[i]; dy[i] = sub(y[i+1],y[i]); }
+    if(typeof k1 === "string" || typeof kn === "string") { 
+        k1 = kn = "periodic";
+    }
+    // Build sparse tridiagonal system
+    var T = [[],[],[]];
+    switch(typeof k1) {
+    case "undefined":
+        b[0] = mul(3/(dx[0]*dx[0]),dy[0]);
+        T[0].push(0,0);
+        T[1].push(0,1);
+        T[2].push(2/dx[0],1/dx[0]);
+        break;
+    case "string":
+        b[0] = add(mul(3/(dx[n-2]*dx[n-2]),dy[n-2]),mul(3/(dx[0]*dx[0]),dy[0]));
+        T[0].push(0,0,0);
+        T[1].push(n-2,0,1);
+        T[2].push(1/dx[n-2],2/dx[n-2]+2/dx[0],1/dx[0]);
+        break;
+    default:
+        b[0] = k1;
+        T[0].push(0);
+        T[1].push(0);
+        T[2].push(1);
+        break;
+    }
+    for(i=1;i<n-1;i++) {
+        b[i] = add(mul(3/(dx[i-1]*dx[i-1]),dy[i-1]),mul(3/(dx[i]*dx[i]),dy[i]));
+        T[0].push(i,i,i);
+        T[1].push(i-1,i,i+1);
+        T[2].push(1/dx[i-1],2/dx[i-1]+2/dx[i],1/dx[i]);
+    }
+    switch(typeof kn) {
+    case "undefined":
+        b[n-1] = mul(3/(dx[n-2]*dx[n-2]),dy[n-2]);
+        T[0].push(n-1,n-1);
+        T[1].push(n-2,n-1);
+        T[2].push(1/dx[n-2],2/dx[n-2]);
+        break;
+    case "string":
+        T[1][T[1].length-1] = 0;
+        break;
+    default:
+        b[n-1] = kn;
+        T[0].push(n-1);
+        T[1].push(n-1);
+        T[2].push(1);
+        break;
+    }
+    if(typeof b[0] !== "number") b = numeric.transpose(b);
+    else b = [b];
+    var k = Array(b.length);
+    if(typeof k1 === "string") {
+        for(i=k.length-1;i!==-1;--i) {
+            k[i] = numeric.ccsLUPSolve(numeric.ccsLUP(numeric.ccsScatter(T)),b[i]);
+            k[i][n-1] = k[i][0];
+        }
+    } else {
+        for(i=k.length-1;i!==-1;--i) {
+            k[i] = numeric.cLUsolve(numeric.cLU(T),b[i]);
+        }
+    }
+    if(typeof y[0] === "number") k = k[0];
+    else k = numeric.transpose(k);
+    return new numeric.Spline(x,y,y,k,k);
+}
+
+// 8. FFT
+numeric.fftpow2 = function fftpow2(x,y) {
+    var n = x.length;
+    if(n === 1) return;
+    var cos = Math.cos, sin = Math.sin, i,j;
+    var xe = Array(n/2), ye = Array(n/2), xo = Array(n/2), yo = Array(n/2);
+    j = n/2;
+    for(i=n-1;i!==-1;--i) {
+        --j;
+        xo[j] = x[i];
+        yo[j] = y[i];
+        --i;
+        xe[j] = x[i];
+        ye[j] = y[i];
+    }
+    fftpow2(xe,ye);
+    fftpow2(xo,yo);
+    j = n/2;
+    var t,k = (-6.2831853071795864769252867665590057683943387987502116419/n),ci,si;
+    for(i=n-1;i!==-1;--i) {
+        --j;
+        if(j === -1) j = n/2-1;
+        t = k*i;
+        ci = cos(t);
+        si = sin(t);
+        x[i] = xe[j] + ci*xo[j] - si*yo[j];
+        y[i] = ye[j] + ci*yo[j] + si*xo[j];
+    }
+}
+numeric._ifftpow2 = function _ifftpow2(x,y) {
+    var n = x.length;
+    if(n === 1) return;
+    var cos = Math.cos, sin = Math.sin, i,j;
+    var xe = Array(n/2), ye = Array(n/2), xo = Array(n/2), yo = Array(n/2);
+    j = n/2;
+    for(i=n-1;i!==-1;--i) {
+        --j;
+        xo[j] = x[i];
+        yo[j] = y[i];
+        --i;
+        xe[j] = x[i];
+        ye[j] = y[i];
+    }
+    _ifftpow2(xe,ye);
+    _ifftpow2(xo,yo);
+    j = n/2;
+    var t,k = (6.2831853071795864769252867665590057683943387987502116419/n),ci,si;
+    for(i=n-1;i!==-1;--i) {
+        --j;
+        if(j === -1) j = n/2-1;
+        t = k*i;
+        ci = cos(t);
+        si = sin(t);
+        x[i] = xe[j] + ci*xo[j] - si*yo[j];
+        y[i] = ye[j] + ci*yo[j] + si*xo[j];
+    }
+}
+numeric.ifftpow2 = function ifftpow2(x,y) {
+    numeric._ifftpow2(x,y);
+    numeric.diveq(x,x.length);
+    numeric.diveq(y,y.length);
+}
+numeric.convpow2 = function convpow2(ax,ay,bx,by) {
+    numeric.fftpow2(ax,ay);
+    numeric.fftpow2(bx,by);
+    var i,n = ax.length,axi,bxi,ayi,byi;
+    for(i=n-1;i!==-1;--i) {
+        axi = ax[i]; ayi = ay[i]; bxi = bx[i]; byi = by[i];
+        ax[i] = axi*bxi-ayi*byi;
+        ay[i] = axi*byi+ayi*bxi;
+    }
+    numeric.ifftpow2(ax,ay);
+}
+numeric.T.prototype.fft = function fft() {
+    var x = this.x, y = this.y;
+    var n = x.length, log = Math.log, log2 = log(2),
+        p = Math.ceil(log(2*n-1)/log2), m = Math.pow(2,p);
+    var cx = numeric.rep([m],0), cy = numeric.rep([m],0), cos = Math.cos, sin = Math.sin;
+    var k, c = (-3.141592653589793238462643383279502884197169399375105820/n),t;
+    var a = numeric.rep([m],0), b = numeric.rep([m],0),nhalf = Math.floor(n/2);
+    for(k=0;k<n;k++) a[k] = x[k];
+    if(typeof y !== "undefined") for(k=0;k<n;k++) b[k] = y[k];
+    cx[0] = 1;
+    for(k=1;k<=m/2;k++) {
+        t = c*k*k;
+        cx[k] = cos(t);
+        cy[k] = sin(t);
+        cx[m-k] = cos(t);
+        cy[m-k] = sin(t)
+    }
+    var X = new numeric.T(a,b), Y = new numeric.T(cx,cy);
+    X = X.mul(Y);
+    numeric.convpow2(X.x,X.y,numeric.clone(Y.x),numeric.neg(Y.y));
+    X = X.mul(Y);
+    X.x.length = n;
+    X.y.length = n;
+    return X;
+}
+numeric.T.prototype.ifft = function ifft() {
+    var x = this.x, y = this.y;
+    var n = x.length, log = Math.log, log2 = log(2),
+        p = Math.ceil(log(2*n-1)/log2), m = Math.pow(2,p);
+    var cx = numeric.rep([m],0), cy = numeric.rep([m],0), cos = Math.cos, sin = Math.sin;
+    var k, c = (3.141592653589793238462643383279502884197169399375105820/n),t;
+    var a = numeric.rep([m],0), b = numeric.rep([m],0),nhalf = Math.floor(n/2);
+    for(k=0;k<n;k++) a[k] = x[k];
+    if(typeof y !== "undefined") for(k=0;k<n;k++) b[k] = y[k];
+    cx[0] = 1;
+    for(k=1;k<=m/2;k++) {
+        t = c*k*k;
+        cx[k] = cos(t);
+        cy[k] = sin(t);
+        cx[m-k] = cos(t);
+        cy[m-k] = sin(t)
+    }
+    var X = new numeric.T(a,b), Y = new numeric.T(cx,cy);
+    X = X.mul(Y);
+    numeric.convpow2(X.x,X.y,numeric.clone(Y.x),numeric.neg(Y.y));
+    X = X.mul(Y);
+    X.x.length = n;
+    X.y.length = n;
+    return X.div(n);
+}
+
+//9. Unconstrained optimization
+numeric.gradient = function gradient(f,x) {
+    var n = x.length;
+    var f0 = f(x);
+    if(isNaN(f0)) throw new Error('gradient: f(x) is a NaN!');
+    var max = Math.max;
+    var i,x0 = numeric.clone(x),f1,f2, J = Array(n);
+    var div = numeric.div, sub = numeric.sub,errest,roundoff,max = Math.max,eps = 1e-3,abs = Math.abs, min = Math.min;
+    var t0,t1,t2,it=0,d1,d2,N;
+    for(i=0;i<n;i++) {
+        var h = max(1e-6*f0,1e-8);
+        while(1) {
+            ++it;
+            if(it>20) { throw new Error("Numerical gradient fails"); }
+            x0[i] = x[i]+h;
+            f1 = f(x0);
+            x0[i] = x[i]-h;
+            f2 = f(x0);
+            x0[i] = x[i];
+            if(isNaN(f1) || isNaN(f2)) { h/=16; continue; }
+            J[i] = (f1-f2)/(2*h);
+            t0 = x[i]-h;
+            t1 = x[i];
+            t2 = x[i]+h;
+            d1 = (f1-f0)/h;
+            d2 = (f0-f2)/h;
+            N = max(abs(J[i]),abs(f0),abs(f1),abs(f2),abs(t0),abs(t1),abs(t2),1e-8);
+            errest = min(max(abs(d1-J[i]),abs(d2-J[i]),abs(d1-d2))/N,h/N);
+            if(errest>eps) { h/=16; }
+            else break;
+            }
+    }
+    return J;
+}
+
+numeric.uncmin = function uncmin(f,x0,tol,gradient,maxit,callback,options) {
+    var grad = numeric.gradient;
+    if(typeof options === "undefined") { options = {}; }
+    if(typeof tol === "undefined") { tol = 1e-8; }
+    if(typeof gradient === "undefined") { gradient = function(x) { return grad(f,x); }; }
+    if(typeof maxit === "undefined") maxit = 1000;
+    x0 = numeric.clone(x0);
+    var n = x0.length;
+    var f0 = f(x0),f1,df0;
+    if(isNaN(f0)) throw new Error('uncmin: f(x0) is a NaN!');
+    var max = Math.max, norm2 = numeric.norm2;
+    tol = max(tol,numeric.epsilon);
+    var step,g0,g1,H1 = options.Hinv || numeric.identity(n);
+    var dot = numeric.dot, inv = numeric.inv, sub = numeric.sub, add = numeric.add, ten = numeric.tensor, div = numeric.div, mul = numeric.mul;
+    var all = numeric.all, isfinite = numeric.isFinite, neg = numeric.neg;
+    var it=0,i,s,x1,y,Hy,Hs,ys,i0,t,nstep,t1,t2;
+    var msg = "";
+    g0 = gradient(x0);
+    while(it<maxit) {
+        if(typeof callback === "function") { if(callback(it,x0,f0,g0,H1)) { msg = "Callback returned true"; break; } }
+        if(!all(isfinite(g0))) { msg = "Gradient has Infinity or NaN"; break; }
+        step = neg(dot(H1,g0));
+        if(!all(isfinite(step))) { msg = "Search direction has Infinity or NaN"; break; }
+        nstep = norm2(step);
+        if(nstep < tol) { msg="Newton step smaller than tol"; break; }
+        t = 1;
+        df0 = dot(g0,step);
+        // line search
+        x1 = x0;
+        while(it < maxit) {
+            if(t*nstep < tol) { break; }
+            s = mul(step,t);
+            x1 = add(x0,s);
+            f1 = f(x1);
+            if(f1-f0 >= 0.1*t*df0 || isNaN(f1)) {
+                t *= 0.5;
+                ++it;
+                continue;
+            }
+            break;
+        }
+        if(t*nstep < tol) { msg = "Line search step size smaller than tol"; break; }
+        if(it === maxit) { msg = "maxit reached during line search"; break; }
+        g1 = gradient(x1);
+        y = sub(g1,g0);
+        ys = dot(y,s);
+        Hy = dot(H1,y);
+        H1 = sub(add(H1,
+                mul(
+                        (ys+dot(y,Hy))/(ys*ys),
+                        ten(s,s)    )),
+                div(add(ten(Hy,s),ten(s,Hy)),ys));
+        x0 = x1;
+        f0 = f1;
+        g0 = g1;
+        ++it;
+    }
+    return {solution: x0, f: f0, gradient: g0, invHessian: H1, iterations:it, message: msg};
+}
+
+// 10. Ode solver (Dormand-Prince)
+numeric.Dopri = function Dopri(x,y,f,ymid,iterations,msg,events) {
+    this.x = x;
+    this.y = y;
+    this.f = f;
+    this.ymid = ymid;
+    this.iterations = iterations;
+    this.events = events;
+    this.message = msg;
+}
+numeric.Dopri.prototype._at = function _at(xi,j) {
+    function sqr(x) { return x*x; }
+    var sol = this;
+    var xs = sol.x;
+    var ys = sol.y;
+    var k1 = sol.f;
+    var ymid = sol.ymid;
+    var n = xs.length;
+    var x0,x1,xh,y0,y1,yh,xi;
+    var floor = Math.floor,h;
+    var c = 0.5;
+    var add = numeric.add, mul = numeric.mul,sub = numeric.sub, p,q,w;
+    x0 = xs[j];
+    x1 = xs[j+1];
+    y0 = ys[j];
+    y1 = ys[j+1];
+    h  = x1-x0;
+    xh = x0+c*h;
+    yh = ymid[j];
+    p = sub(k1[j  ],mul(y0,1/(x0-xh)+2/(x0-x1)));
+    q = sub(k1[j+1],mul(y1,1/(x1-xh)+2/(x1-x0)));
+    w = [sqr(xi - x1) * (xi - xh) / sqr(x0 - x1) / (x0 - xh),
+         sqr(xi - x0) * sqr(xi - x1) / sqr(x0 - xh) / sqr(x1 - xh),
+         sqr(xi - x0) * (xi - xh) / sqr(x1 - x0) / (x1 - xh),
+         (xi - x0) * sqr(xi - x1) * (xi - xh) / sqr(x0-x1) / (x0 - xh),
+         (xi - x1) * sqr(xi - x0) * (xi - xh) / sqr(x0-x1) / (x1 - xh)];
+    return add(add(add(add(mul(y0,w[0]),
+                           mul(yh,w[1])),
+                           mul(y1,w[2])),
+                           mul( p,w[3])),
+                           mul( q,w[4]));
+}
+numeric.Dopri.prototype.at = function at(x) {
+    var i,j,k,floor = Math.floor;
+    if(typeof x !== "number") {
+        var n = x.length, ret = Array(n);
+        for(i=n-1;i!==-1;--i) {
+            ret[i] = this.at(x[i]);
+        }
+        return ret;
+    }
+    var x0 = this.x;
+    i = 0; j = x0.length-1;
+    while(j-i>1) {
+        k = floor(0.5*(i+j));
+        if(x0[k] <= x) i = k;
+        else j = k;
+    }
+    return this._at(x,i);
+}
+
+numeric.dopri = function dopri(x0,x1,y0,f,tol,maxit,event) {
+    if(typeof tol === "undefined") { tol = 1e-6; }
+    if(typeof maxit === "undefined") { maxit = 1000; }
+    var xs = [x0], ys = [y0], k1 = [f(x0,y0)], k2,k3,k4,k5,k6,k7, ymid = [];
+    var A2 = 1/5;
+    var A3 = [3/40,9/40];
+    var A4 = [44/45,-56/15,32/9];
+    var A5 = [19372/6561,-25360/2187,64448/6561,-212/729];
+    var A6 = [9017/3168,-355/33,46732/5247,49/176,-5103/18656];
+    var b = [35/384,0,500/1113,125/192,-2187/6784,11/84];
+    var bm = [0.5*6025192743/30085553152,
+              0,
+              0.5*51252292925/65400821598,
+              0.5*-2691868925/45128329728,
+              0.5*187940372067/1594534317056,
+              0.5*-1776094331/19743644256,
+              0.5*11237099/235043384];
+    var c = [1/5,3/10,4/5,8/9,1,1];
+    var e = [-71/57600,0,71/16695,-71/1920,17253/339200,-22/525,1/40];
+    var i = 0,er,j;
+    var h = (x1-x0)/10;
+    var it = 0;
+    var add = numeric.add, mul = numeric.mul, y1,erinf;
+    var max = Math.max, min = Math.min, abs = Math.abs, norminf = numeric.norminf,pow = Math.pow;
+    var any = numeric.any, lt = numeric.lt, and = numeric.and, sub = numeric.sub;
+    var e0, e1, ev;
+    var ret = new numeric.Dopri(xs,ys,k1,ymid,-1,"");
+    if(typeof event === "function") e0 = event(x0,y0);
+    while(x0<x1 && it<maxit) {
+        ++it;
+        if(x0+h>x1) h = x1-x0;
+        k2 = f(x0+c[0]*h,                add(y0,mul(   A2*h,k1[i])));
+        k3 = f(x0+c[1]*h,            add(add(y0,mul(A3[0]*h,k1[i])),mul(A3[1]*h,k2)));
+        k4 = f(x0+c[2]*h,        add(add(add(y0,mul(A4[0]*h,k1[i])),mul(A4[1]*h,k2)),mul(A4[2]*h,k3)));
+        k5 = f(x0+c[3]*h,    add(add(add(add(y0,mul(A5[0]*h,k1[i])),mul(A5[1]*h,k2)),mul(A5[2]*h,k3)),mul(A5[3]*h,k4)));
+        k6 = f(x0+c[4]*h,add(add(add(add(add(y0,mul(A6[0]*h,k1[i])),mul(A6[1]*h,k2)),mul(A6[2]*h,k3)),mul(A6[3]*h,k4)),mul(A6[4]*h,k5)));
+        y1 = add(add(add(add(add(y0,mul(k1[i],h*b[0])),mul(k3,h*b[2])),mul(k4,h*b[3])),mul(k5,h*b[4])),mul(k6,h*b[5]));
+        k7 = f(x0+h,y1);
+        er = add(add(add(add(add(mul(k1[i],h*e[0]),mul(k3,h*e[2])),mul(k4,h*e[3])),mul(k5,h*e[4])),mul(k6,h*e[5])),mul(k7,h*e[6]));
+        if(typeof er === "number") erinf = abs(er);
+        else erinf = norminf(er);
+        if(erinf > tol) { // reject
+            h = 0.2*h*pow(tol/erinf,0.25);
+            if(x0+h === x0) {
+                ret.msg = "Step size became too small";
+                break;
+            }
+            continue;
+        }
+        ymid[i] = add(add(add(add(add(add(y0,
+                mul(k1[i],h*bm[0])),
+                mul(k3   ,h*bm[2])),
+                mul(k4   ,h*bm[3])),
+                mul(k5   ,h*bm[4])),
+                mul(k6   ,h*bm[5])),
+                mul(k7   ,h*bm[6]));
+        ++i;
+        xs[i] = x0+h;
+        ys[i] = y1;
+        k1[i] = k7;
+        if(typeof event === "function") {
+            var yi,xl = x0,xr = x0+0.5*h,xi;
+            e1 = event(xr,ymid[i-1]);
+            ev = and(lt(e0,0),lt(0,e1));
+            if(!any(ev)) { xl = xr; xr = x0+h; e0 = e1; e1 = event(xr,y1); ev = and(lt(e0,0),lt(0,e1)); }
+            if(any(ev)) {
+                var xc, yc, en,ei;
+                var side=0, sl = 1.0, sr = 1.0;
+                while(1) {
+                    if(typeof e0 === "number") xi = (sr*e1*xl-sl*e0*xr)/(sr*e1-sl*e0);
+                    else {
+                        xi = xr;
+                        for(j=e0.length-1;j!==-1;--j) {
+                            if(e0[j]<0 && e1[j]>0) xi = min(xi,(sr*e1[j]*xl-sl*e0[j]*xr)/(sr*e1[j]-sl*e0[j]));
+                        }
+                    }
+                    if(xi <= xl || xi >= xr) break;
+                    yi = ret._at(xi, i-1);
+                    ei = event(xi,yi);
+                    en = and(lt(e0,0),lt(0,ei));
+                    if(any(en)) {
+                        xr = xi;
+                        e1 = ei;
+                        ev = en;
+                        sr = 1.0;
+                        if(side === -1) sl *= 0.5;
+                        else sl = 1.0;
+                        side = -1;
+                    } else {
+                        xl = xi;
+                        e0 = ei;
+                        sl = 1.0;
+                        if(side === 1) sr *= 0.5;
+                        else sr = 1.0;
+                        side = 1;
+                    }
+                }
+                y1 = ret._at(0.5*(x0+xi),i-1);
+                ret.f[i] = f(xi,yi);
+                ret.x[i] = xi;
+                ret.y[i] = yi;
+                ret.ymid[i-1] = y1;
+                ret.events = ev;
+                ret.iterations = it;
+                return ret;
+            }
+        }
+        x0 += h;
+        y0 = y1;
+        e0 = e1;
+        h = min(0.8*h*pow(tol/erinf,0.25),4*h);
+    }
+    ret.iterations = it;
+    return ret;
+}
+
+// 11. Ax = b
+numeric.LU = function(A, fast) {
+  fast = fast || false;
+
+  var abs = Math.abs;
+  var i, j, k, absAjk, Akk, Ak, Pk, Ai;
+  var max;
+  var n = A.length, n1 = n-1;
+  var P = new Array(n);
+  if(!fast) A = numeric.clone(A);
+
+  for (k = 0; k < n; ++k) {
+    Pk = k;
+    Ak = A[k];
+    max = abs(Ak[k]);
+    for (j = k + 1; j < n; ++j) {
+      absAjk = abs(A[j][k]);
+      if (max < absAjk) {
+        max = absAjk;
+        Pk = j;
+      }
+    }
+    P[k] = Pk;
+
+    if (Pk != k) {
+      A[k] = A[Pk];
+      A[Pk] = Ak;
+      Ak = A[k];
+    }
+
+    Akk = Ak[k];
+
+    for (i = k + 1; i < n; ++i) {
+      A[i][k] /= Akk;
+    }
+
+    for (i = k + 1; i < n; ++i) {
+      Ai = A[i];
+      for (j = k + 1; j < n1; ++j) {
+        Ai[j] -= Ai[k] * Ak[j];
+        ++j;
+        Ai[j] -= Ai[k] * Ak[j];
+      }
+      if(j===n1) Ai[j] -= Ai[k] * Ak[j];
+    }
+  }
+
+  return {
+    LU: A,
+    P:  P
+  };
+}
+
+numeric.LUsolve = function LUsolve(LUP, b) {
+  var i, j;
+  var LU = LUP.LU;
+  var n   = LU.length;
+  var x = numeric.clone(b);
+  var P   = LUP.P;
+  var Pi, LUi, LUii, tmp;
+
+  for (i=n-1;i!==-1;--i) x[i] = b[i];
+  for (i = 0; i < n; ++i) {
+    Pi = P[i];
+    if (P[i] !== i) {
+      tmp = x[i];
+      x[i] = x[Pi];
+      x[Pi] = tmp;
+    }
+
+    LUi = LU[i];
+    for (j = 0; j < i; ++j) {
+      x[i] -= x[j] * LUi[j];
+    }
+  }
+
+  for (i = n - 1; i >= 0; --i) {
+    LUi = LU[i];
+    for (j = i + 1; j < n; ++j) {
+      x[i] -= x[j] * LUi[j];
+    }
+
+    x[i] /= LUi[i];
+  }
+
+  return x;
+}
+
+numeric.solve = function solve(A,b,fast) { return numeric.LUsolve(numeric.LU(A,fast), b); }
+
+// 12. Linear programming
+numeric.echelonize = function echelonize(A) {
+    var s = numeric.dim(A), m = s[0], n = s[1];
+    var I = numeric.identity(m);
+    var P = Array(m);
+    var i,j,k,l,Ai,Ii,Z,a;
+    var abs = Math.abs;
+    var diveq = numeric.diveq;
+    A = numeric.clone(A);
+    for(i=0;i<m;++i) {
+        k = 0;
+        Ai = A[i];
+        Ii = I[i];
+        for(j=1;j<n;++j) if(abs(Ai[k])<abs(Ai[j])) k=j;
+        P[i] = k;
+        diveq(Ii,Ai[k]);
+        diveq(Ai,Ai[k]);
+        for(j=0;j<m;++j) if(j!==i) {
+            Z = A[j]; a = Z[k];
+            for(l=n-1;l!==-1;--l) Z[l] -= Ai[l]*a;
+            Z = I[j];
+            for(l=m-1;l!==-1;--l) Z[l] -= Ii[l]*a;
+        }
+    }
+    return {I:I, A:A, P:P};
+}
+
+numeric.__solveLP = function __solveLP(c,A,b,tol,maxit,x,flag) {
+    var sum = numeric.sum, log = numeric.log, mul = numeric.mul, sub = numeric.sub, dot = numeric.dot, div = numeric.div, add = numeric.add;
+    var m = c.length, n = b.length,y;
+    var unbounded = false, cb,i0=0;
+    var alpha = 1.0;
+    var f0,df0,AT = numeric.transpose(A), svd = numeric.svd,transpose = numeric.transpose,leq = numeric.leq, sqrt = Math.sqrt, abs = Math.abs;
+    var muleq = numeric.muleq;
+    var norm = numeric.norminf, any = numeric.any,min = Math.min;
+    var all = numeric.all, gt = numeric.gt;
+    var p = Array(m), A0 = Array(n),e=numeric.rep([n],1), H;
+    var solve = numeric.solve, z = sub(b,dot(A,x)),count;
+    var dotcc = dot(c,c);
+    var g;
+    for(count=i0;count<maxit;++count) {
+        var i,j,d;
+        for(i=n-1;i!==-1;--i) A0[i] = div(A[i],z[i]);
+        var A1 = transpose(A0);
+        for(i=m-1;i!==-1;--i) p[i] = (/*x[i]+*/sum(A1[i]));
+        alpha = 0.25*abs(dotcc/dot(c,p));
+        var a1 = 100*sqrt(dotcc/dot(p,p));
+        if(!isFinite(alpha) || alpha>a1) alpha = a1;
+        g = add(c,mul(alpha,p));
+        H = dot(A1,A0);
+        for(i=m-1;i!==-1;--i) H[i][i] += 1;
+        d = solve(H,div(g,alpha),true);
+        var t0 = div(z,dot(A,d));
+        var t = 1.0;
+        for(i=n-1;i!==-1;--i) if(t0[i]<0) t = min(t,-0.999*t0[i]);
+        y = sub(x,mul(d,t));
+        z = sub(b,dot(A,y));
+        if(!all(gt(z,0))) return { solution: x, message: "", iterations: count };
+        x = y;
+        if(alpha<tol) return { solution: y, message: "", iterations: count };
+        if(flag) {
+            var s = dot(c,g), Ag = dot(A,g);
+            unbounded = true;
+            for(i=n-1;i!==-1;--i) if(s*Ag[i]<0) { unbounded = false; break; }
+        } else {
+            if(x[m-1]>=0) unbounded = false;
+            else unbounded = true;
+        }
+        if(unbounded) return { solution: y, message: "Unbounded", iterations: count };
+    }
+    return { solution: x, message: "maximum iteration count exceeded", iterations:count };
+}
+
+numeric._solveLP = function _solveLP(c,A,b,tol,maxit) {
+    var m = c.length, n = b.length,y;
+    var sum = numeric.sum, log = numeric.log, mul = numeric.mul, sub = numeric.sub, dot = numeric.dot, div = numeric.div, add = numeric.add;
+    var c0 = numeric.rep([m],0).concat([1]);
+    var J = numeric.rep([n,1],-1);
+    var A0 = numeric.blockMatrix([[A                   ,   J  ]]);
+    var b0 = b;
+    var y = numeric.rep([m],0).concat(Math.max(0,numeric.sup(numeric.neg(b)))+1);
+    var x0 = numeric.__solveLP(c0,A0,b0,tol,maxit,y,false);
+    var x = numeric.clone(x0.solution);
+    x.length = m;
+    var foo = numeric.inf(sub(b,dot(A,x)));
+    if(foo<0) { return { solution: NaN, message: "Infeasible", iterations: x0.iterations }; }
+    var ret = numeric.__solveLP(c, A, b, tol, maxit-x0.iterations, x, true);
+    ret.iterations += x0.iterations;
+    return ret;
+};
+
+numeric.solveLP = function solveLP(c,A,b,Aeq,beq,tol,maxit) {
+    if(typeof maxit === "undefined") maxit = 1000;
+    if(typeof tol === "undefined") tol = numeric.epsilon;
+    if(typeof Aeq === "undefined") return numeric._solveLP(c,A,b,tol,maxit);
+    var m = Aeq.length, n = Aeq[0].length, o = A.length;
+    var B = numeric.echelonize(Aeq);
+    var flags = numeric.rep([n],0);
+    var P = B.P;
+    var Q = [];
+    var i;
+    for(i=P.length-1;i!==-1;--i) flags[P[i]] = 1;
+    for(i=n-1;i!==-1;--i) if(flags[i]===0) Q.push(i);
+    var g = numeric.getRange;
+    var I = numeric.linspace(0,m-1), J = numeric.linspace(0,o-1);
+    var Aeq2 = g(Aeq,I,Q), A1 = g(A,J,P), A2 = g(A,J,Q), dot = numeric.dot, sub = numeric.sub;
+    var A3 = dot(A1,B.I);
+    var A4 = sub(A2,dot(A3,Aeq2)), b4 = sub(b,dot(A3,beq));
+    var c1 = Array(P.length), c2 = Array(Q.length);
+    for(i=P.length-1;i!==-1;--i) c1[i] = c[P[i]];
+    for(i=Q.length-1;i!==-1;--i) c2[i] = c[Q[i]];
+    var c4 = sub(c2,dot(c1,dot(B.I,Aeq2)));
+    var S = numeric._solveLP(c4,A4,b4,tol,maxit);
+    var x2 = S.solution;
+    if(x2!==x2) return S;
+    var x1 = dot(B.I,sub(beq,dot(Aeq2,x2)));
+    var x = Array(c.length);
+    for(i=P.length-1;i!==-1;--i) x[P[i]] = x1[i];
+    for(i=Q.length-1;i!==-1;--i) x[Q[i]] = x2[i];
+    return { solution: x, message:S.message, iterations: S.iterations };
+}
+
+numeric.MPStoLP = function MPStoLP(MPS) {
+    if(MPS instanceof String) { MPS.split('\n'); }
+    var state = 0;
+    var states = ['Initial state','NAME','ROWS','COLUMNS','RHS','BOUNDS','ENDATA'];
+    var n = MPS.length;
+    var i,j,z,N=0,rows = {}, sign = [], rl = 0, vars = {}, nv = 0;
+    var name;
+    var c = [], A = [], b = [];
+    function err(e) { throw new Error('MPStoLP: '+e+'\nLine '+i+': '+MPS[i]+'\nCurrent state: '+states[state]+'\n'); }
+    for(i=0;i<n;++i) {
+        z = MPS[i];
+        var w0 = z.match(/\S*/g);
+        var w = [];
+        for(j=0;j<w0.length;++j) if(w0[j]!=="") w.push(w0[j]);
+        if(w.length === 0) continue;
+        for(j=0;j<states.length;++j) if(z.substr(0,states[j].length) === states[j]) break;
+        if(j<states.length) {
+            state = j;
+            if(j===1) { name = w[1]; }
+            if(j===6) return { name:name, c:c, A:numeric.transpose(A), b:b, rows:rows, vars:vars };
+            continue;
+        }
+        switch(state) {
+        case 0: case 1: err('Unexpected line');
+        case 2: 
+            switch(w[0]) {
+            case 'N': if(N===0) N = w[1]; else err('Two or more N rows'); break;
+            case 'L': rows[w[1]] = rl; sign[rl] = 1; b[rl] = 0; ++rl; break;
+            case 'G': rows[w[1]] = rl; sign[rl] = -1;b[rl] = 0; ++rl; break;
+            case 'E': rows[w[1]] = rl; sign[rl] = 0;b[rl] = 0; ++rl; break;
+            default: err('Parse error '+numeric.prettyPrint(w));
+            }
+            break;
+        case 3:
+            if(!vars.hasOwnProperty(w[0])) { vars[w[0]] = nv; c[nv] = 0; A[nv] = numeric.rep([rl],0); ++nv; }
+            var p = vars[w[0]];
+            for(j=1;j<w.length;j+=2) {
+                if(w[j] === N) { c[p] = parseFloat(w[j+1]); continue; }
+                var q = rows[w[j]];
+                A[p][q] = (sign[q]<0?-1:1)*parseFloat(w[j+1]);
+            }
+            break;
+        case 4:
+            for(j=1;j<w.length;j+=2) b[rows[w[j]]] = (sign[rows[w[j]]]<0?-1:1)*parseFloat(w[j+1]);
+            break;
+        case 5: /*FIXME*/ break;
+        case 6: err('Internal error');
+        }
+    }
+    err('Reached end of file without ENDATA');
+}
+// seedrandom.js version 2.0.
+// Author: David Bau 4/2/2011
+//
+// Defines a method Math.seedrandom() that, when called, substitutes
+// an explicitly seeded RC4-based algorithm for Math.random().  Also
+// supports automatic seeding from local or network sources of entropy.
+//
+// Usage:
+//
+//   <script src=http://davidbau.com/encode/seedrandom-min.js></script>
+//
+//   Math.seedrandom('yipee'); Sets Math.random to a function that is
+//                             initialized using the given explicit seed.
+//
+//   Math.seedrandom();        Sets Math.random to a function that is
+//                             seeded using the current time, dom state,
+//                             and other accumulated local entropy.
+//                             The generated seed string is returned.
+//
+//   Math.seedrandom('yowza', true);
+//                             Seeds using the given explicit seed mixed
+//                             together with accumulated entropy.
+//
+//   <script src="http://bit.ly/srandom-512"></script>
+//                             Seeds using physical random bits downloaded
+//                             from random.org.
+//
+//   <script src="https://jsonlib.appspot.com/urandom?callback=Math.seedrandom">
+//   </script>                 Seeds using urandom bits from call.jsonlib.com,
+//                             which is faster than random.org.
+//
+// Examples:
+//
+//   Math.seedrandom("hello");            // Use "hello" as the seed.
+//   document.write(Math.random());       // Always 0.5463663768140734
+//   document.write(Math.random());       // Always 0.43973793770592234
+//   var rng1 = Math.random;              // Remember the current prng.
+//
+//   var autoseed = Math.seedrandom();    // New prng with an automatic seed.
+//   document.write(Math.random());       // Pretty much unpredictable.
+//
+//   Math.random = rng1;                  // Continue "hello" prng sequence.
+//   document.write(Math.random());       // Always 0.554769432473455
+//
+//   Math.seedrandom(autoseed);           // Restart at the previous seed.
+//   document.write(Math.random());       // Repeat the 'unpredictable' value.
+//
+// Notes:
+//
+// Each time seedrandom('arg') is called, entropy from the passed seed
+// is accumulated in a pool to help generate future seeds for the
+// zero-argument form of Math.seedrandom, so entropy can be injected over
+// time by calling seedrandom with explicit data repeatedly.
+//
+// On speed - This javascript implementation of Math.random() is about
+// 3-10x slower than the built-in Math.random() because it is not native
+// code, but this is typically fast enough anyway.  Seeding is more expensive,
+// especially if you use auto-seeding.  Some details (timings on Chrome 4):
+//
+// Our Math.random()            - avg less than 0.002 milliseconds per call
+// seedrandom('explicit')       - avg less than 0.5 milliseconds per call
+// seedrandom('explicit', true) - avg less than 2 milliseconds per call
+// seedrandom()                 - avg about 38 milliseconds per call
+//
+// LICENSE (BSD):
+//
+// Copyright 2010 David Bau, 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 this module 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
+// OWNER 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.
+//
+/**
+ * All code is in an anonymous closure to keep the global namespace clean.
+ *
+ * @param {number=} overflow 
+ * @param {number=} startdenom
+ */
+
+// Patched by Seb so that seedrandom.js does not pollute the Math object.
+// My tests suggest that doing Math.trouble = 1 makes Math lookups about 5%
+// slower.
+numeric.seedrandom = { pow:Math.pow, random:Math.random };
+
+(function (pool, math, width, chunks, significance, overflow, startdenom) {
+
+
+//
+// seedrandom()
+// This is the seedrandom function described above.
+//
+math['seedrandom'] = function seedrandom(seed, use_entropy) {
+  var key = [];
+  var arc4;
+
+  // Flatten the seed string or build one from local entropy if needed.
+  seed = mixkey(flatten(
+    use_entropy ? [seed, pool] :
+    arguments.length ? seed :
+    [new Date().getTime(), pool, window], 3), key);
+
+  // Use the seed to initialize an ARC4 generator.
+  arc4 = new ARC4(key);
+
+  // Mix the randomness into accumulated entropy.
+  mixkey(arc4.S, pool);
+
+  // Override Math.random
+
+  // This function returns a random double in [0, 1) that contains
+  // randomness in every bit of the mantissa of the IEEE 754 value.
+
+  math['random'] = function random() {  // Closure to return a random double:
+    var n = arc4.g(chunks);             // Start with a numerator n < 2 ^ 48
+    var d = startdenom;                 //   and denominator d = 2 ^ 48.
+    var x = 0;                          //   and no 'extra last byte'.
+    while (n < significance) {          // Fill up all significant digits by
+      n = (n + x) * width;              //   shifting numerator and
+      d *= width;                       //   denominator and generating a
+      x = arc4.g(1);                    //   new least-significant-byte.
+    }
+    while (n >= overflow) {             // To avoid rounding up, before adding
+      n /= 2;                           //   last byte, shift everything
+      d /= 2;                           //   right using integer math until
+      x >>>= 1;                         //   we have exactly the desired bits.
+    }
+    return (n + x) / d;                 // Form the number within [0, 1).
+  };
+
+  // Return the seed that was used
+  return seed;
+};
+
+//
+// ARC4
+//
+// An ARC4 implementation.  The constructor takes a key in the form of
+// an array of at most (width) integers that should be 0 <= x < (width).
+//
+// The g(count) method returns a pseudorandom integer that concatenates
+// the next (count) outputs from ARC4.  Its return value is a number x
+// that is in the range 0 <= x < (width ^ count).
+//
+/** @constructor */
+function ARC4(key) {
+  var t, u, me = this, keylen = key.length;
+  var i = 0, j = me.i = me.j = me.m = 0;
+  me.S = [];
+  me.c = [];
+
+  // The empty key [] is treated as [0].
+  if (!keylen) { key = [keylen++]; }
+
+  // Set up S using the standard key scheduling algorithm.
+  while (i < width) { me.S[i] = i++; }
+  for (i = 0; i < width; i++) {
+    t = me.S[i];
+    j = lowbits(j + t + key[i % keylen]);
+    u = me.S[j];
+    me.S[i] = u;
+    me.S[j] = t;
+  }
+
+  // The "g" method returns the next (count) outputs as one number.
+  me.g = function getnext(count) {
+    var s = me.S;
+    var i = lowbits(me.i + 1); var t = s[i];
+    var j = lowbits(me.j + t); var u = s[j];
+    s[i] = u;
+    s[j] = t;
+    var r = s[lowbits(t + u)];
+    while (--count) {
+      i = lowbits(i + 1); t = s[i];
+      j = lowbits(j + t); u = s[j];
+      s[i] = u;
+      s[j] = t;
+      r = r * width + s[lowbits(t + u)];
+    }
+    me.i = i;
+    me.j = j;
+    return r;
+  };
+  // For robust unpredictability discard an initial batch of values.
+  // See http://www.rsa.com/rsalabs/node.asp?id=2009
+  me.g(width);
+}
+
+//
+// flatten()
+// Converts an object tree to nested arrays of strings.
+//
+/** @param {Object=} result 
+  * @param {string=} prop
+  * @param {string=} typ */
+function flatten(obj, depth, result, prop, typ) {
+  result = [];
+  typ = typeof(obj);
+  if (depth && typ == 'object') {
+    for (prop in obj) {
+      if (prop.indexOf('S') < 5) {    // Avoid FF3 bug (local/sessionStorage)
+        try { result.push(flatten(obj[prop], depth - 1)); } catch (e) {}
+      }
+    }
+  }
+  return (result.length ? result : obj + (typ != 'string' ? '\0' : ''));
+}
+
+//
+// mixkey()
+// Mixes a string seed into a key that is an array of integers, and
+// returns a shortened string seed that is equivalent to the result key.
+//
+/** @param {number=} smear 
+  * @param {number=} j */
+function mixkey(seed, key, smear, j) {
+  seed += '';                         // Ensure the seed is a string
+  smear = 0;
+  for (j = 0; j < seed.length; j++) {
+    key[lowbits(j)] =
+      lowbits((smear ^= key[lowbits(j)] * 19) + seed.charCodeAt(j));
+  }
+  seed = '';
+  for (j in key) { seed += String.fromCharCode(key[j]); }
+  return seed;
+}
+
+//
+// lowbits()
+// A quick "n mod width" for width a power of 2.
+//
+function lowbits(n) { return n & (width - 1); }
+
+//
+// The following constants are related to IEEE 754 limits.
+//
+startdenom = math.pow(width, chunks);
+significance = math.pow(2, significance);
+overflow = significance * 2;
+
+//
+// When seedrandom.js is loaded, we immediately mix a few bits
+// from the built-in RNG into the entropy pool.  Because we do
+// not want to intefere with determinstic PRNG state later,
+// seedrandom will not call math.random on its own again after
+// initialization.
+//
+mixkey(math.random(), pool);
+
+// End anonymous scope, and pass initial values.
+}(
+  [],   // pool: entropy pool starts empty
+  numeric.seedrandom, // math: package containing random, pow, and seedrandom
+  256,  // width: each RC4 output is 0 <= x < 256
+  6,    // chunks: at least six RC4 outputs for each double
+  52    // significance: there are 52 significant digits in a double
+  ));
+/* This file is a slightly modified version of quadprog.js from Alberto Santini.
+ * It has been slightly modified by Sébastien Loisel to make sure that it handles
+ * 0-based Arrays instead of 1-based Arrays.
+ * License is in resources/LICENSE.quadprog */
+(function(exports) {
+
+function base0to1(A) {
+    if(typeof A !== "object") { return A; }
+    var ret = [], i,n=A.length;
+    for(i=0;i<n;i++) ret[i+1] = base0to1(A[i]);
+    return ret;
+}
+function base1to0(A) {
+    if(typeof A !== "object") { return A; }
+    var ret = [], i,n=A.length;
+    for(i=1;i<n;i++) ret[i-1] = base1to0(A[i]);
+    return ret;
+}
+
+function dpori(a, lda, n) {
+    var i, j, k, kp1, t;
+
+    for (k = 1; k <= n; k = k + 1) {
+        a[k][k] = 1 / a[k][k];
+        t = -a[k][k];
+        //~ dscal(k - 1, t, a[1][k], 1);
+        for (i = 1; i < k; i = i + 1) {
+            a[i][k] = t * a[i][k];
+        }
+
+        kp1 = k + 1;
+        if (n < kp1) {
+            break;
+        }
+        for (j = kp1; j <= n; j = j + 1) {
+            t = a[k][j];
+            a[k][j] = 0;
+            //~ daxpy(k, t, a[1][k], 1, a[1][j], 1);
+            for (i = 1; i <= k; i = i + 1) {
+                a[i][j] = a[i][j] + (t * a[i][k]);
+            }
+        }
+    }
+
+}
+
+function dposl(a, lda, n, b) {
+    var i, k, kb, t;
+
+    for (k = 1; k <= n; k = k + 1) {
+        //~ t = ddot(k - 1, a[1][k], 1, b[1], 1);
+        t = 0;
+        for (i = 1; i < k; i = i + 1) {
+            t = t + (a[i][k] * b[i]);
+        }
+
+        b[k] = (b[k] - t) / a[k][k];
+    }
+
+    for (kb = 1; kb <= n; kb = kb + 1) {
+        k = n + 1 - kb;
+        b[k] = b[k] / a[k][k];
+        t = -b[k];
+        //~ daxpy(k - 1, t, a[1][k], 1, b[1], 1);
+        for (i = 1; i < k; i = i + 1) {
+            b[i] = b[i] + (t * a[i][k]);
+        }
+    }
+}
+
+function dpofa(a, lda, n, info) {
+    var i, j, jm1, k, t, s;
+
+    for (j = 1; j <= n; j = j + 1) {
+        info[1] = j;
+        s = 0;
+        jm1 = j - 1;
+        if (jm1 < 1) {
+            s = a[j][j] - s;
+            if (s <= 0) {
+                break;
+            }
+            a[j][j] = Math.sqrt(s);
+        } else {
+            for (k = 1; k <= jm1; k = k + 1) {
+                //~ t = a[k][j] - ddot(k - 1, a[1][k], 1, a[1][j], 1);
+                t = a[k][j];
+                for (i = 1; i < k; i = i + 1) {
+                    t = t - (a[i][j] * a[i][k]);
+                }
+                t = t / a[k][k];
+                a[k][j] = t;
+                s = s + t * t;
+            }
+            s = a[j][j] - s;
+            if (s <= 0) {
+                break;
+            }
+            a[j][j] = Math.sqrt(s);
+        }
+        info[1] = 0;
+    }
+}
+
+function qpgen2(dmat, dvec, fddmat, n, sol, crval, amat,
+    bvec, fdamat, q, meq, iact, nact, iter, work, ierr) {
+
+    var i, j, l, l1, info, it1, iwzv, iwrv, iwrm, iwsv, iwuv, nvl, r, iwnbv,
+        temp, sum, t1, tt, gc, gs, nu,
+        t1inf, t2min,
+        vsmall, tmpa, tmpb,
+        go;
+
+    r = Math.min(n, q);
+    l = 2 * n + (r * (r + 5)) / 2 + 2 * q + 1;
+
+    vsmall = 1.0e-60;
+    do {
+        vsmall = vsmall + vsmall;
+        tmpa = 1 + 0.1 * vsmall;
+        tmpb = 1 + 0.2 * vsmall;
+    } while (tmpa <= 1 || tmpb <= 1);
+
+    for (i = 1; i <= n; i = i + 1) {
+        work[i] = dvec[i];
+    }
+    for (i = n + 1; i <= l; i = i + 1) {
+        work[i] = 0;
+    }
+    for (i = 1; i <= q; i = i + 1) {
+        iact[i] = 0;
+    }
+
+    info = [];
+
+    if (ierr[1] === 0) {
+        dpofa(dmat, fddmat, n, info);
+        if (info[1] !== 0) {
+            ierr[1] = 2;
+            return;
+        }
+        dposl(dmat, fddmat, n, dvec);
+        dpori(dmat, fddmat, n);
+    } else {
+        for (j = 1; j <= n; j = j + 1) {
+            sol[j] = 0;
+            for (i = 1; i <= j; i = i + 1) {
+                sol[j] = sol[j] + dmat[i][j] * dvec[i];
+            }
+        }
+        for (j = 1; j <= n; j = j + 1) {
+            dvec[j] = 0;
+            for (i = j; i <= n; i = i + 1) {
+                dvec[j] = dvec[j] + dmat[j][i] * sol[i];
+            }
+        }
+    }
+
+    crval[1] = 0;
+    for (j = 1; j <= n; j = j + 1) {
+        sol[j] = dvec[j];
+        crval[1] = crval[1] + work[j] * sol[j];
+        work[j] = 0;
+        for (i = j + 1; i <= n; i = i + 1) {
+            dmat[i][j] = 0;
+        }
+    }
+    crval[1] = -crval[1] / 2;
+    ierr[1] = 0;
+
+    iwzv = n;
+    iwrv = iwzv + n;
+    iwuv = iwrv + r;
+    iwrm = iwuv + r + 1;
+    iwsv = iwrm + (r * (r + 1)) / 2;
+    iwnbv = iwsv + q;
+
+    for (i = 1; i <= q; i = i + 1) {
+        sum = 0;
+        for (j = 1; j <= n; j = j + 1) {
+            sum = sum + amat[j][i] * amat[j][i];
+        }
+        work[iwnbv + i] = Math.sqrt(sum);
+    }
+    nact = 0;
+    iter[1] = 0;
+    iter[2] = 0;
+
+    function fn_goto_50() {
+        iter[1] = iter[1] + 1;
+
+        l = iwsv;
+        for (i = 1; i <= q; i = i + 1) {
+            l = l + 1;
+            sum = -bvec[i];
+            for (j = 1; j <= n; j = j + 1) {
+                sum = sum + amat[j][i] * sol[j];
+            }
+            if (Math.abs(sum) < vsmall) {
+                sum = 0;
+            }
+            if (i > meq) {
+                work[l] = sum;
+            } else {
+                work[l] = -Math.abs(sum);
+                if (sum > 0) {
+                    for (j = 1; j <= n; j = j + 1) {
+                        amat[j][i] = -amat[j][i];
+                    }
+                    bvec[i] = -bvec[i];
+                }
+            }
+        }
+
+        for (i = 1; i <= nact; i = i + 1) {
+            work[iwsv + iact[i]] = 0;
+        }
+
+        nvl = 0;
+        temp = 0;
+        for (i = 1; i <= q; i = i + 1) {
+            if (work[iwsv + i] < temp * work[iwnbv + i]) {
+                nvl = i;
+                temp = work[iwsv + i] / work[iwnbv + i];
+            }
+        }
+        if (nvl === 0) {
+            return 999;
+        }
+
+        return 0;
+    }
+
+    function fn_goto_55() {
+        for (i = 1; i <= n; i = i + 1) {
+            sum = 0;
+            for (j = 1; j <= n; j = j + 1) {
+                sum = sum + dmat[j][i] * amat[j][nvl];
+            }
+            work[i] = sum;
+        }
+
+        l1 = iwzv;
+        for (i = 1; i <= n; i = i + 1) {
+            work[l1 + i] = 0;
+        }
+        for (j = nact + 1; j <= n; j = j + 1) {
+            for (i = 1; i <= n; i = i + 1) {
+                work[l1 + i] = work[l1 + i] + dmat[i][j] * work[j];
+            }
+        }
+
+        t1inf = true;
+        for (i = nact; i >= 1; i = i - 1) {
+            sum = work[i];
+            l = iwrm + (i * (i + 3)) / 2;
+            l1 = l - i;
+            for (j = i + 1; j <= nact; j = j + 1) {
+                sum = sum - work[l] * work[iwrv + j];
+                l = l + j;
+            }
+            sum = sum / work[l1];
+            work[iwrv + i] = sum;
+            if (iact[i] < meq) {
+                // continue;
+                break;
+            }
+            if (sum < 0) {
+                // continue;
+                break;
+            }
+            t1inf = false;
+            it1 = i;
+        }
+
+        if (!t1inf) {
+            t1 = work[iwuv + it1] / work[iwrv + it1];
+            for (i = 1; i <= nact; i = i + 1) {
+                if (iact[i] < meq) {
+                    // continue;
+                    break;
+                }
+                if (work[iwrv + i] < 0) {
+                    // continue;
+                    break;
+                }
+                temp = work[iwuv + i] / work[iwrv + i];
+                if (temp < t1) {
+                    t1 = temp;
+                    it1 = i;
+                }
+            }
+        }
+
+        sum = 0;
+        for (i = iwzv + 1; i <= iwzv + n; i = i + 1) {
+            sum = sum + work[i] * work[i];
+        }
+        if (Math.abs(sum) <= vsmall) {
+            if (t1inf) {
+                ierr[1] = 1;
+                // GOTO 999
+                return 999;
+            } else {
+                for (i = 1; i <= nact; i = i + 1) {
+                    work[iwuv + i] = work[iwuv + i] - t1 * work[iwrv + i];
+                }
+                work[iwuv + nact + 1] = work[iwuv + nact + 1] + t1;
+                // GOTO 700
+                return 700;
+            }
+        } else {
+            sum = 0;
+            for (i = 1; i <= n; i = i + 1) {
+                sum = sum + work[iwzv + i] * amat[i][nvl];
+            }
+            tt = -work[iwsv + nvl] / sum;
+            t2min = true;
+            if (!t1inf) {
+                if (t1 < tt) {
+                    tt = t1;
+                    t2min = false;
+                }
+            }
+
+            for (i = 1; i <= n; i = i + 1) {
+                sol[i] = sol[i] + tt * work[iwzv + i];
+                if (Math.abs(sol[i]) < vsmall) {
+                    sol[i] = 0;
+                }
+            }
+
+            crval[1] = crval[1] + tt * sum * (tt / 2 + work[iwuv + nact + 1]);
+            for (i = 1; i <= nact; i = i + 1) {
+                work[iwuv + i] = work[iwuv + i] - tt * work[iwrv + i];
+            }
+            work[iwuv + nact + 1] = work[iwuv + nact + 1] + tt;
+
+            if (t2min) {
+                nact = nact + 1;
+                iact[nact] = nvl;
+
+                l = iwrm + ((nact - 1) * nact) / 2 + 1;
+                for (i = 1; i <= nact - 1; i = i + 1) {
+                    work[l] = work[i];
+                    l = l + 1;
+                }
+
+                if (nact === n) {
+                    work[l] = work[n];
+                } else {
+                    for (i = n; i >= nact + 1; i = i - 1) {
+                        if (work[i] === 0) {
+                            // continue;
+                            break;
+                        }
+                        gc = Math.max(Math.abs(work[i - 1]), Math.abs(work[i]));
+                        gs = Math.min(Math.abs(work[i - 1]), Math.abs(work[i]));
+                        if (work[i - 1] >= 0) {
+                            temp = Math.abs(gc * Math.sqrt(1 + gs * gs / (gc * gc)));
+                        } else {
+                            temp = -Math.abs(gc * Math.sqrt(1 + gs * gs / (gc * gc)));
+                        }
+                        gc = work[i - 1] / temp;
+                        gs = work[i] / temp;
+
+                        if (gc === 1) {
+                            // continue;
+                            break;
+                        }
+                        if (gc === 0) {
+                            work[i - 1] = gs * temp;
+                            for (j = 1; j <= n; j = j + 1) {
+                                temp = dmat[j][i - 1];
+                                dmat[j][i - 1] = dmat[j][i];
+                                dmat[j][i] = temp;
+                            }
+                        } else {
+                            work[i - 1] = temp;
+                            nu = gs / (1 + gc);
+                            for (j = 1; j <= n; j = j + 1) {
+                                temp = gc * dmat[j][i - 1] + gs * dmat[j][i];
+                                dmat[j][i] = nu * (dmat[j][i - 1] + temp) - dmat[j][i];
+                                dmat[j][i - 1] = temp;
+
+                            }
+                        }
+                    }
+                    work[l] = work[nact];
+                }
+            } else {
+                sum = -bvec[nvl];
+                for (j = 1; j <= n; j = j + 1) {
+                    sum = sum + sol[j] * amat[j][nvl];
+                }
+                if (nvl > meq) {
+                    work[iwsv + nvl] = sum;
+                } else {
+                    work[iwsv + nvl] = -Math.abs(sum);
+                    if (sum > 0) {
+                        for (j = 1; j <= n; j = j + 1) {
+                            amat[j][nvl] = -amat[j][nvl];
+                        }
+                        bvec[nvl] = -bvec[nvl];
+                    }
+                }
+                // GOTO 700
+                return 700;
+            }
+        }
+
+        return 0;
+    }
+
+    function fn_goto_797() {
+        l = iwrm + (it1 * (it1 + 1)) / 2 + 1;
+        l1 = l + it1;
+        if (work[l1] === 0) {
+            // GOTO 798
+            return 798;
+        }
+        gc = Math.max(Math.abs(work[l1 - 1]), Math.abs(work[l1]));
+        gs = Math.min(Math.abs(work[l1 - 1]), Math.abs(work[l1]));
+        if (work[l1 - 1] >= 0) {
+            temp = Math.abs(gc * Math.sqrt(1 + gs * gs / (gc * gc)));
+        } else {
+            temp = -Math.abs(gc * Math.sqrt(1 + gs * gs / (gc * gc)));
+        }
+        gc = work[l1 - 1] / temp;
+        gs = work[l1] / temp;
+
+        if (gc === 1) {
+            // GOTO 798
+            return 798;
+        }
+        if (gc === 0) {
+            for (i = it1 + 1; i <= nact; i = i + 1) {
+                temp = work[l1 - 1];
+                work[l1 - 1] = work[l1];
+                work[l1] = temp;
+                l1 = l1 + i;
+            }
+            for (i = 1; i <= n; i = i + 1) {
+                temp = dmat[i][it1];
+                dmat[i][it1] = dmat[i][it1 + 1];
+                dmat[i][it1 + 1] = temp;
+            }
+        } else {
+            nu = gs / (1 + gc);
+            for (i = it1 + 1; i <= nact; i = i + 1) {
+                temp = gc * work[l1 - 1] + gs * work[l1];
+                work[l1] = nu * (work[l1 - 1] + temp) - work[l1];
+                work[l1 - 1] = temp;
+                l1 = l1 + i;
+            }
+            for (i = 1; i <= n; i = i + 1) {
+                temp = gc * dmat[i][it1] + gs * dmat[i][it1 + 1];
+                dmat[i][it1 + 1] = nu * (dmat[i][it1] + temp) - dmat[i][it1 + 1];
+                dmat[i][it1] = temp;
+            }
+        }
+
+        return 0;
+    }
+
+    function fn_goto_798() {
+        l1 = l - it1;
+        for (i = 1; i <= it1; i = i + 1) {
+            work[l1] = work[l];
+            l = l + 1;
+            l1 = l1 + 1;
+        }
+
+        work[iwuv + it1] = work[iwuv + it1 + 1];
+        iact[it1] = iact[it1 + 1];
+        it1 = it1 + 1;
+        if (it1 < nact) {
+            // GOTO 797
+            return 797;
+        }
+
+        return 0;
+    }
+
+    function fn_goto_799() {
+        work[iwuv + nact] = work[iwuv + nact + 1];
+        work[iwuv + nact + 1] = 0;
+        iact[nact] = 0;
+        nact = nact - 1;
+        iter[2] = iter[2] + 1;
+
+        return 0;
+    }
+
+    go = 0;
+    while (true) {
+        go = fn_goto_50();
+        if (go === 999) {
+            return;
+        }
+        while (true) {
+            go = fn_goto_55();
+            if (go === 0) {
+                break;
+            }
+            if (go === 999) {
+                return;
+            }
+            if (go === 700) {
+                if (it1 === nact) {
+                    fn_goto_799();
+                } else {
+                    while (true) {
+                        fn_goto_797();
+                        go = fn_goto_798();
+                        if (go !== 797) {
+                            break;
+                        }
+                    }
+                    fn_goto_799();
+                }
+            }
+        }
+    }
+
+}
+
+function solveQP(Dmat, dvec, Amat, bvec, meq, factorized) {
+    Dmat = base0to1(Dmat);
+    dvec = base0to1(dvec);
+    Amat = base0to1(Amat);
+    var i, n, q,
+        nact, r,
+        crval = [], iact = [], sol = [], work = [], iter = [],
+        message;
+
+    meq = meq || 0;
+    factorized = factorized ? base0to1(factorized) : [undefined, 0];
+    bvec = bvec ? base0to1(bvec) : [];
+
+    // In Fortran the array index starts from 1
+    n = Dmat.length - 1;
+    q = Amat[1].length - 1;
+
+    if (!bvec) {
+        for (i = 1; i <= q; i = i + 1) {
+            bvec[i] = 0;
+        }
+    }
+    for (i = 1; i <= q; i = i + 1) {
+        iact[i] = 0;
+    }
+    nact = 0;
+    r = Math.min(n, q);
+    for (i = 1; i <= n; i = i + 1) {
+        sol[i] = 0;
+    }
+    crval[1] = 0;
+    for (i = 1; i <= (2 * n + (r * (r + 5)) / 2 + 2 * q + 1); i = i + 1) {
+        work[i] = 0;
+    }
+    for (i = 1; i <= 2; i = i + 1) {
+        iter[i] = 0;
+    }
+
+    qpgen2(Dmat, dvec, n, n, sol, crval, Amat,
+        bvec, n, q, meq, iact, nact, iter, work, factorized);
+
+    message = "";
+    if (factorized[1] === 1) {
+        message = "constraints are inconsistent, no solution!";
+    }
+    if (factorized[1] === 2) {
+        message = "matrix D in quadratic function is not positive definite!";
+    }
+
+    return {
+        solution: base1to0(sol),
+        value: base1to0(crval),
+        unconstrained_solution: base1to0(dvec),
+        iterations: base1to0(iter),
+        iact: base1to0(iact),
+        message: message
+    };
+}
+exports.solveQP = solveQP;
+}(numeric));
+/*

+Shanti Rao sent me this routine by private email. I had to modify it

+slightly to work on Arrays instead of using a Matrix object.

+It is apparently translated from http://stitchpanorama.sourceforge.net/Python/svd.py

+*/

+

+numeric.svd= function svd(A) {

+    var temp;

+//Compute the thin SVD from G. H. Golub and C. Reinsch, Numer. Math. 14, 403-420 (1970)

+	var prec= numeric.epsilon; //Math.pow(2,-52) // assumes double prec

+	var tolerance= 1.e-64/prec;

+	var itmax= 50;

+	var c=0;

+	var i=0;

+	var j=0;

+	var k=0;

+	var l=0;

+	

+	var u= numeric.clone(A);

+	var m= u.length;

+	

+	var n= u[0].length;

+	

+	if (m < n) throw "Need more rows than columns"

+	

+	var e = new Array(n);

+	var q = new Array(n);

+	for (i=0; i<n; i++) e[i] = q[i] = 0.0;

+	var v = numeric.rep([n,n],0);

+//	v.zero();

+	

+ 	function pythag(a,b)

+ 	{

+		a = Math.abs(a)

+		b = Math.abs(b)

+		if (a > b)

+			return a*Math.sqrt(1.0+(b*b/a/a))

+		else if (b == 0.0) 

+			return a

+		return b*Math.sqrt(1.0+(a*a/b/b))

+	}

+

+	//Householder's reduction to bidiagonal form

+

+	var f= 0.0;

+	var g= 0.0;

+	var h= 0.0;

+	var x= 0.0;

+	var y= 0.0;

+	var z= 0.0;

+	var s= 0.0;

+	

+	for (i=0; i < n; i++)

+	{	

+		e[i]= g;

+		s= 0.0;

+		l= i+1;

+		for (j=i; j < m; j++) 

+			s += (u[j][i]*u[j][i]);

+		if (s <= tolerance)

+			g= 0.0;

+		else

+		{	

+			f= u[i][i];

+			g= Math.sqrt(s);

+			if (f >= 0.0) g= -g;

+			h= f*g-s

+			u[i][i]=f-g;

+			for (j=l; j < n; j++)

+			{

+				s= 0.0

+				for (k=i; k < m; k++) 

+					s += u[k][i]*u[k][j]

+				f= s/h

+				for (k=i; k < m; k++) 

+					u[k][j]+=f*u[k][i]

+			}

+		}

+		q[i]= g

+		s= 0.0

+		for (j=l; j < n; j++) 

+			s= s + u[i][j]*u[i][j]

+		if (s <= tolerance)

+			g= 0.0

+		else

+		{	

+			f= u[i][i+1]

+			g= Math.sqrt(s)

+			if (f >= 0.0) g= -g

+			h= f*g - s

+			u[i][i+1] = f-g;

+			for (j=l; j < n; j++) e[j]= u[i][j]/h

+			for (j=l; j < m; j++)

+			{	

+				s=0.0

+				for (k=l; k < n; k++) 

+					s += (u[j][k]*u[i][k])

+				for (k=l; k < n; k++) 

+					u[j][k]+=s*e[k]

+			}	

+		}

+		y= Math.abs(q[i])+Math.abs(e[i])

+		if (y>x) 

+			x=y

+	}

+	

+	// accumulation of right hand gtransformations

+	for (i=n-1; i != -1; i+= -1)

+	{	

+		if (g != 0.0)

+		{

+		 	h= g*u[i][i+1]

+			for (j=l; j < n; j++) 

+				v[j][i]=u[i][j]/h

+			for (j=l; j < n; j++)

+			{	

+				s=0.0

+				for (k=l; k < n; k++) 

+					s += u[i][k]*v[k][j]

+				for (k=l; k < n; k++) 

+					v[k][j]+=(s*v[k][i])

+			}	

+		}

+		for (j=l; j < n; j++)

+		{

+			v[i][j] = 0;

+			v[j][i] = 0;

+		}

+		v[i][i] = 1;

+		g= e[i]

+		l= i

+	}

+	

+	// accumulation of left hand transformations

+	for (i=n-1; i != -1; i+= -1)

+	{	

+		l= i+1

+		g= q[i]

+		for (j=l; j < n; j++) 

+			u[i][j] = 0;

+		if (g != 0.0)

+		{

+			h= u[i][i]*g

+			for (j=l; j < n; j++)

+			{

+				s=0.0

+				for (k=l; k < m; k++) s += u[k][i]*u[k][j];

+				f= s/h

+				for (k=i; k < m; k++) u[k][j]+=f*u[k][i];

+			}

+			for (j=i; j < m; j++) u[j][i] = u[j][i]/g;

+		}

+		else

+			for (j=i; j < m; j++) u[j][i] = 0;

+		u[i][i] += 1;

+	}

+	

+	// diagonalization of the bidiagonal form

+	prec= prec*x

+	for (k=n-1; k != -1; k+= -1)

+	{

+		for (var iteration=0; iteration < itmax; iteration++)

+		{	// test f splitting

+			var test_convergence = false

+			for (l=k; l != -1; l+= -1)

+			{	

+				if (Math.abs(e[l]) <= prec)

+				{	test_convergence= true

+					break 

+				}

+				if (Math.abs(q[l-1]) <= prec)

+					break 

+			}

+			if (!test_convergence)

+			{	// cancellation of e[l] if l>0

+				c= 0.0

+				s= 1.0

+				var l1= l-1

+				for (i =l; i<k+1; i++)

+				{	

+					f= s*e[i]

+					e[i]= c*e[i]

+					if (Math.abs(f) <= prec)

+						break

+					g= q[i]

+					h= pythag(f,g)

+					q[i]= h

+					c= g/h

+					s= -f/h

+					for (j=0; j < m; j++)

+					{	

+						y= u[j][l1]

+						z= u[j][i]

+						u[j][l1] =  y*c+(z*s)

+						u[j][i] = -y*s+(z*c)

+					} 

+				}	

+			}

+			// test f convergence

+			z= q[k]

+			if (l== k)

+			{	//convergence

+				if (z<0.0)

+				{	//q[k] is made non-negative

+					q[k]= -z

+					for (j=0; j < n; j++)

+						v[j][k] = -v[j][k]

+				}

+				break  //break out of iteration loop and move on to next k value

+			}

+			if (iteration >= itmax-1)

+				throw 'Error: no convergence.'

+			// shift from bottom 2x2 minor

+			x= q[l]

+			y= q[k-1]

+			g= e[k-1]

+			h= e[k]

+			f= ((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y)

+			g= pythag(f,1.0)

+			if (f < 0.0)

+				f= ((x-z)*(x+z)+h*(y/(f-g)-h))/x

+			else

+				f= ((x-z)*(x+z)+h*(y/(f+g)-h))/x

+			// next QR transformation

+			c= 1.0

+			s= 1.0

+			for (i=l+1; i< k+1; i++)

+			{	

+				g= e[i]

+				y= q[i]

+				h= s*g

+				g= c*g

+				z= pythag(f,h)

+				e[i-1]= z

+				c= f/z

+				s= h/z

+				f= x*c+g*s

+				g= -x*s+g*c

+				h= y*s

+				y= y*c

+				for (j=0; j < n; j++)

+				{	

+					x= v[j][i-1]

+					z= v[j][i]

+					v[j][i-1] = x*c+z*s

+					v[j][i] = -x*s+z*c

+				}

+				z= pythag(f,h)

+				q[i-1]= z

+				c= f/z

+				s= h/z

+				f= c*g+s*y

+				x= -s*g+c*y

+				for (j=0; j < m; j++)

+				{

+					y= u[j][i-1]

+					z= u[j][i]

+					u[j][i-1] = y*c+z*s

+					u[j][i] = -y*s+z*c

+				}

+			}

+			e[l]= 0.0

+			e[k]= f

+			q[k]= x

+		} 

+	}

+		

+	//vt= transpose(v)

+	//return (u,q,vt)

+	for (i=0;i<q.length; i++) 

+	  if (q[i] < prec) q[i] = 0

+	  

+	//sort eigenvalues	

+	for (i=0; i< n; i++)

+	{	 

+	//writeln(q)

+	 for (j=i-1; j >= 0; j--)

+	 {

+	  if (q[j] < q[i])

+	  {

+	//  writeln(i,'-',j)

+	   c = q[j]

+	   q[j] = q[i]

+	   q[i] = c

+	   for(k=0;k<u.length;k++) { temp = u[k][i]; u[k][i] = u[k][j]; u[k][j] = temp; }

+	   for(k=0;k<v.length;k++) { temp = v[k][i]; v[k][i] = v[k][j]; v[k][j] = temp; }

+//	   u.swapCols(i,j)

+//	   v.swapCols(i,j)

+	   i = j	   

+	  }

+	 }	

+	}

+	

+	return {U:u,S:q,V:v}

+};

+

+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{}],8:[function(require,module,exports){
+/*
+ (c) 2013, Vladimir Agafonkin
+ Simplify.js, a high-performance JS polyline simplification library
+ mourner.github.io/simplify-js
+*/
+
+(function () { 'use strict';
+
+// to suit your point format, run search/replace for '.x' and '.y';
+// for 3D version, see 3d branch (configurability would draw significant performance overhead)
+
+// square distance between 2 points
+function getSqDist(p1, p2) {
+
+    var dx = p1.x - p2.x,
+        dy = p1.y - p2.y;
+
+    return dx * dx + dy * dy;
+}
+
+// square distance from a point to a segment
+function getSqSegDist(p, p1, p2) {
+
+    var x = p1.x,
+        y = p1.y,
+        dx = p2.x - x,
+        dy = p2.y - y;
+
+    if (dx !== 0 || dy !== 0) {
+
+        var t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);
+
+        if (t > 1) {
+            x = p2.x;
+            y = p2.y;
+
+        } else if (t > 0) {
+            x += dx * t;
+            y += dy * t;
+        }
+    }
+
+    dx = p.x - x;
+    dy = p.y - y;
+
+    return dx * dx + dy * dy;
+}
+// rest of the code doesn't care about point format
+
+// basic distance-based simplification
+function simplifyRadialDist(points, sqTolerance) {
+
+    var prevPoint = points[0],
+        newPoints = [prevPoint],
+        point;
+
+    for (var i = 1, len = points.length; i < len; i++) {
+        point = points[i];
+
+        if (getSqDist(point, prevPoint) > sqTolerance) {
+            newPoints.push(point);
+            prevPoint = point;
+        }
+    }
+
+    if (prevPoint !== point) newPoints.push(point);
+
+    return newPoints;
+}
+
+// simplification using optimized Douglas-Peucker algorithm with recursion elimination
+function simplifyDouglasPeucker(points, sqTolerance) {
+
+    var len = points.length,
+        MarkerArray = typeof Uint8Array !== 'undefined' ? Uint8Array : Array,
+        markers = new MarkerArray(len),
+        first = 0,
+        last = len - 1,
+        stack = [],
+        newPoints = [],
+        i, maxSqDist, sqDist, index;
+
+    markers[first] = markers[last] = 1;
+
+    while (last) {
+
+        maxSqDist = 0;
+
+        for (i = first + 1; i < last; i++) {
+            sqDist = getSqSegDist(points[i], points[first], points[last]);
+
+            if (sqDist > maxSqDist) {
+                index = i;
+                maxSqDist = sqDist;
+            }
+        }
+
+        if (maxSqDist > sqTolerance) {
+            markers[index] = 1;
+            stack.push(first, index, index, last);
+        }
+
+        last = stack.pop();
+        first = stack.pop();
+    }
+
+    for (i = 0; i < len; i++) {
+        if (markers[i]) newPoints.push(points[i]);
+    }
+
+    return newPoints;
+}
+
+// both algorithms combined for awesome performance
+function simplify(points, tolerance, highestQuality) {
+
+    var sqTolerance = tolerance !== undefined ? tolerance * tolerance : 1;
+
+    points = highestQuality ? points : simplifyRadialDist(points, sqTolerance);
+    points = simplifyDouglasPeucker(points, sqTolerance);
+
+    return points;
+}
+
+// export as AMD module / Node module / browser or worker variable
+if (typeof define === 'function' && define.amd) define(function() { return simplify; });
+else if (typeof module !== 'undefined') module.exports = simplify;
+else if (typeof self !== 'undefined') self.simplify = simplify;
+else window.simplify = simplify;
+
+})();
+
+},{}],9:[function(require,module,exports){
+"use strict"
+
+module.exports = createKDTree
+module.exports.deserialize = deserializeKDTree
+
+var ndarray = require("ndarray")
+var ndselect = require("ndarray-select")
+var pack = require("ndarray-pack")
+var ops = require("ndarray-ops")
+var ndscratch = require("ndarray-scratch")
+var pool = require("typedarray-pool")
+var inorderTree = require("inorder-tree-layout")
+var bits = require("bit-twiddle")
+var KDTHeap = require("./lib/heap.js")
+
+function KDTree(points, ids, n, d) {
+  this.points = points
+  this.ids = ids
+  this.dimension = d
+  this.length = n
+}
+
+var proto = KDTree.prototype
+
+proto.serialize = function() {
+  if(this.length > 0) {
+    return {
+      p: Array.prototype.slice.call(this.points.data, 0, this.length*this.dimension),
+      i: Array.prototype.slice.call(this.ids, 0, this.length)
+    }
+  } else {
+    return { d: this.dimension }
+  }
+}
+
+//Range query
+proto.range = function kdtRangeQuery(lo, hi, visit) {
+  var n = this.length
+  if(n < 1) {
+    return
+  }
+
+  //Check degenerate case
+  var d = this.dimension
+  for(var i=0; i<d; ++i) {
+    if(hi[i] < lo[i]) {
+      return
+    }
+  }
+
+  var points = this.points
+  var ids = this.ids
+
+  //Walk tree in level order, skipping subtrees which do not intersect range
+  var visitRange = ndscratch.malloc([n, 2, d])
+  var visitIndex = pool.mallocInt32(n)
+  var rangeData = visitRange.data
+  var pointData = points.data
+  var visitCount = 1
+  var visitTop = 0
+  var retval
+
+  visitIndex[0] = 0
+  pack(lo, visitRange.pick(0,0))
+  pack(hi, visitRange.pick(0,1))
+  
+  while(visitTop < visitCount) {
+    var idx = visitIndex[visitTop]
+    var k = bits.log2(idx+1)%d
+    var loidx = visitRange.index(visitTop, 0, 0)
+    var hiidx = visitRange.index(visitTop, 1, 0)
+    var pidx = points.index(idx, 0)
+
+    var visitPoint = true
+    for(var i=0; i<d; ++i) {
+      var pc = pointData[pidx+i]
+      if((pc < rangeData[loidx + i]) || 
+         (rangeData[hiidx + i] < pc)) {
+        visitPoint = false
+        break
+      }
+    }
+    if(visitPoint) {
+      retval = visit(ids[idx])
+      if(retval !== undefined) {
+        break
+      }
+    }
+
+    //Visit children
+    var pk = pointData[pidx+k]
+    var hk = rangeData[hiidx+k]
+    var lk = rangeData[loidx+k]
+    if(lk <= pk) {
+      var left = 2 * idx + 1
+      if(left < n) {
+        visitIndex[visitCount] = left
+        var y = visitRange.index(visitCount, 0, 0)
+        for(var i=0; i<d; ++i) {
+          rangeData[y+i] = rangeData[loidx+i]
+        }
+        var z = visitRange.index(visitCount, 1, 0)
+        for(var i=0; i<d; ++i) {
+          rangeData[z+i] = rangeData[hiidx+i]
+        }
+        rangeData[z+k] = Math.min(hk, pk)
+        visitCount += 1
+      }
+    }
+    if(pk <= hk) {
+      var right = 2 * (idx + 1)
+      if(right < n) {
+        visitIndex[visitCount] = right
+        var y = visitRange.index(visitCount, 0, 0)
+        for(var i=0; i<d; ++i) {
+          rangeData[y+i] = rangeData[loidx+i]
+        }
+        var z = visitRange.index(visitCount, 1, 0)
+        for(var i=0; i<d; ++i) {
+          rangeData[z+i] = rangeData[hiidx+i]
+        }
+        rangeData[y+k] = Math.max(lk, pk)
+        visitCount += 1
+      }
+    }
+
+    //Increment pointer
+    visitTop += 1
+  }
+  ndscratch.free(visitRange)
+  pool.free(visitIndex)
+  return retval
+}
+
+proto.rnn = function(point, radius, visit) {
+  if(radius < 0) {
+    return
+  }
+  var n = this.length
+  if(n < 1) {
+    return
+  }
+  var d = this.dimension
+  var points = this.points
+  var ids = this.ids
+
+  //Walk tree in level order, skipping subtrees which do not intersect sphere
+  var visitDistance = ndscratch.malloc([n, d])
+  var visitIndex = pool.mallocInt32(n)
+  var distanceData = visitDistance.data
+  var pointData = points.data
+  var visitCount = 1
+  var visitTop = 0
+  var r2 = radius*radius
+  var retval
+
+  //Initialize top of queue
+  visitIndex[0] = 0
+  for(var i=0; i<d; ++i) {
+    visitDistance.set(0, i, 0)
+  }
+
+  //Walk over queue
+  while(visitTop < visitCount) {
+    var idx = visitIndex[visitTop]
+    var pidx = points.index(idx, 0)
+
+    //Check if point in sphere
+    var d2 = 0.0
+    for(var i=0; i<d; ++i) {
+      d2 += Math.pow(point[i] - pointData[pidx+i], 2)
+    }
+    if(d2 <= r2) {
+      retval = visit(ids[idx])
+      if(retval !== undefined) {
+        break
+      }
+    }
+
+    //Visit children
+    var k = bits.log2(idx+1)%d
+    var ds = 0.0
+    var didx = visitDistance.index(visitTop, 0)
+    for(var i=0; i<d; ++i) {
+      if(i !== k) {
+        ds += distanceData[didx + i]
+      }
+    }
+
+    //Handle split axis
+    var qk = point[k]
+    var pk = pointData[pidx+k]
+    var dk = distanceData[didx+k]
+    var lk = dk
+    var hk = dk
+    if(qk < pk) {
+      hk = Math.max(dk, Math.pow(pk - qk, 2))
+    } else {
+      lk = Math.max(dk, Math.pow(pk - qk, 2))
+    }
+
+    var d2l = lk + ds
+    var d2h = hk + ds
+
+    if(d2l <= r2) {
+      var left = 2 * idx + 1
+      if(left < n) {
+        visitIndex[visitCount] = left
+        var y = visitDistance.index(visitCount, 0)
+        for(var i=0; i<d; ++i) {
+          distanceData[y+i] = distanceData[didx+i]
+        }
+        distanceData[y+k] = lk
+        visitCount += 1
+      }
+    }
+    if(d2h <= r2) {
+      var right = 2 * (idx + 1)
+      if(right < n) {
+        visitIndex[visitCount] = right
+        var y = visitDistance.index(visitCount, 0)
+        for(var i=0; i<d; ++i) {
+          distanceData[y+i] = distanceData[didx+i]
+        }
+        distanceData[y+k] = hk
+        visitCount += 1
+      }
+    }
+
+    //Increment pointer
+    visitTop += 1
+  }
+
+  ndscratch.free(visitDistance)
+  pool.free(visitIndex)
+  return retval
+}
+
+proto.nn = function(point, maxDistance) {
+  var n = this.length
+  if(n < 1) {
+    return -1
+  }
+  if(typeof maxDistance === "number") {
+    if(maxDistance < 0) {
+      return -1
+    } 
+  } else {
+    maxDistance = Infinity
+  }
+  var d = this.dimension
+  var points = this.points
+  var pointData = points.data
+  var dataVector = pool.mallocFloat64(d)
+
+  var toVisit = new KDTHeap(n, d+1)
+  var index = toVisit.index
+  var data = toVisit.data
+  index[0] = 0
+  for(var i=0; i<=d; ++i) {
+    data[i] = 0
+  }
+  toVisit.count += 1
+
+  var nearest = -1
+  var nearestD = maxDistance
+
+  while(toVisit.count > 0) {
+    if(data[0] >= nearestD) {
+      break
+    }
+
+    var idx = index[0]
+    var pidx = points.index(idx, 0)
+    var d2 = 0.0
+    for(var i=0; i<d; ++i) {
+      d2 += Math.pow(point[i]-pointData[pidx+i], 2)
+    }
+    if(d2 < nearestD) {
+      nearestD = d2
+      nearest = idx
+    }
+
+    //Compute distance bounds for children
+    var k = bits.log2(idx+1)%d
+    var ds = 0
+    for(var i=0; i<d; ++i) {
+      var dd = data[i+1]
+      if(i !== k) {
+        ds += dd
+      }
+      dataVector[i] = dd
+    }
+    var qk = point[k]
+    var pk = pointData[pidx+k]
+    var dk = dataVector[k]
+    var lk = dk
+    var hk = dk
+    if(qk < pk) {
+      hk = Math.max(dk, Math.pow(pk - qk, 2))
+    } else {
+      lk = Math.max(dk, Math.pow(pk - qk, 2))
+    }
+    var d2l = lk + ds
+    var d2h = hk + ds
+
+    toVisit.pop()
+    
+    if(d2l < nearestD) {
+      var left = 2 * idx + 1
+      if(left < n) {
+        var vcount = toVisit.count
+        index[vcount] = left
+        var vptr = vcount * (d+1)
+        data[vptr] = d2l
+        for(var i=1; i<=d; ++i) {
+          data[vptr+i] = dataVector[i-1]
+        }
+        data[vptr+k+1] = lk
+        toVisit.push()
+      }
+    }
+    if(d2h < nearestD) {
+      var right = 2 * (idx + 1)
+      if(right < n) {
+        var vcount = toVisit.count
+        index[vcount] = right
+        var vptr = vcount * (d+1)
+        data[vptr] = d2h
+        for(var i=1; i<=d; ++i) {
+          data[vptr+i] = dataVector[i-1]
+        }
+        data[vptr+k+1] = hk
+        toVisit.push()
+      }
+    }
+  }
+
+  pool.freeFloat64(dataVector)
+  toVisit.dispose()
+  
+  if(nearest < 0) {
+    return -1
+  }
+  return this.ids[nearest]
+}
+
+proto.knn = function(point, maxPoints, maxDistance) {
+  //Check degenerate cases
+  if(typeof maxDistance === "number") {
+    if(maxDistance < 0) {
+      return []
+    }
+  } else {
+    maxDistance = Infinity
+  }
+  var n = this.length
+  if(n < 1) {
+    return []
+  }
+  if(typeof maxPoints === "number") {
+    if(maxPoints <= 0) {
+      return []
+    }
+    maxPoints = Math.min(maxPoints, n)|0
+  } else {
+    maxPoints = n
+  }
+  var ids = this.ids
+
+  var d = this.dimension
+  var points = this.points
+  var pointData = points.data
+  var dataVector = pool.mallocFloat64(d)
+  
+  //List of closest points
+  var closestPoints = new KDTHeap(maxPoints, 1)
+  var cl_index = closestPoints.index
+  var cl_data = closestPoints.data
+
+  var toVisit = new KDTHeap(n, d+1)
+  var index = toVisit.index
+  var data = toVisit.data
+  index[0] = 0
+  for(var i=0; i<=d; ++i) {
+    data[i] = 0
+  }
+  toVisit.count += 1
+
+  var nearest = -1
+  var nearestD = maxDistance
+
+  while(toVisit.count > 0) {
+    if(data[0] >= nearestD) {
+      break
+    }
+
+    var idx = index[0]
+    var pidx = points.index(idx, 0)
+    var d2 = 0.0
+    for(var i=0; i<d; ++i) {
+      d2 += Math.pow(point[i]-pointData[pidx+i], 2)
+    }
+    if(d2 < nearestD) {
+      if(closestPoints.count >= maxPoints) {
+        closestPoints.pop()
+      }
+      var pcount = closestPoints.count
+      cl_index[pcount] = idx
+      cl_data[pcount] = -d2
+      closestPoints.push()
+      if(closestPoints.count >= maxPoints) {
+        nearestD = -cl_data[0]
+      }
+    }
+
+    //Compute distance bounds for children
+    var k = bits.log2(idx+1)%d
+    var ds = 0
+    for(var i=0; i<d; ++i) {
+      var dd = data[i+1]
+      if(i !== k) {
+        ds += dd
+      }
+      dataVector[i] = dd
+    }
+    var qk = point[k]
+    var pk = pointData[pidx+k]
+    var dk = dataVector[k]
+    var lk = dk
+    var hk = dk
+    if(qk < pk) {
+      hk = Math.max(dk, Math.pow(pk - qk, 2))
+    } else {
+      lk = Math.max(dk, Math.pow(pk - qk, 2))
+    }
+    var d2l = lk + ds
+    var d2h = hk + ds
+
+    toVisit.pop()
+    if(d2l < nearestD) {
+      var left = 2 * idx + 1
+      if(left < n) {
+        var vcount = toVisit.count
+        index[vcount] = left
+        var vptr = vcount * (d+1)
+        data[vptr] = d2l
+        for(var i=1; i<=d; ++i) {
+          data[vptr+i] = dataVector[i-1]
+        }
+        data[vptr+k+1] = lk
+        toVisit.push()
+      }
+    }
+    if(d2h < nearestD) {
+      var right = 2 * (idx + 1)
+      if(right < n) {
+        var vcount = toVisit.count
+        index[vcount] = right
+        var vptr = vcount * (d+1)
+        data[vptr] = d2h
+        for(var i=1; i<=d; ++i) {
+          data[vptr+i] = dataVector[i-1]
+        }
+        data[vptr+k+1] = hk
+        toVisit.push()
+      }
+    }
+  }
+
+  pool.freeFloat64(dataVector)
+  toVisit.dispose()
+
+  //Sort result
+  var result = new Array(closestPoints.count)
+  var ids = this.ids
+  for(var i=closestPoints.count-1; i>=0; --i) {
+    result[i] = ids[cl_index[0]]
+    closestPoints.pop()
+  }
+  closestPoints.dispose()
+
+  return result
+}
+
+proto.dispose = function kdtDispose() {
+  pool.free(this.points.data)
+  pool.freeInt32(this.ids)
+  this.points = null
+  this.ids = null
+  this.length = 0
+}
+
+function createKDTree(points) {
+  var n, d, indexed
+  if(Array.isArray(points)) {
+    n = points.length
+    if(n === 0) {
+      return new KDTree(null, null, 0, 0)
+    }
+    d = points[0].length
+    indexed = ndarray(pool.mallocDouble(n*(d+1)), [n, d+1])
+    pack(points, indexed.hi(n, d))
+  } else {
+    n = points.shape[0]
+    d = points.shape[1]
+
+    //Round up data type size
+    var type = points.dtype
+    if(type === "int8" ||
+       type === "int16" ||
+       type === "int32" ) {
+      type = "int32"
+    } else if(type === "uint8" ||
+      type === "uint8_clamped" ||
+      type === "buffer" ||
+      type === "uint16" ||
+      type === "uint32") {
+      type = "uint32"
+    } else if(type === "float32") {
+      type = "float32"
+    } else {
+      type = "float64"
+    }
+    indexed = ndarray(pool.malloc(n*(d+1)), [n, d+1])
+    ops.assign(indexed.hi(n,d), points)
+  }
+  for(var i=0; i<n; ++i) {
+    indexed.set(i, d, i)
+  }
+
+  var pointArray = ndscratch.malloc([n, d], points.dtype)
+  var indexArray = pool.mallocInt32(n)
+  var pointer = 0
+  var pointData = pointArray.data
+  var arrayData = indexed.data
+  var l2_n = bits.log2(bits.nextPow2(n))
+
+  var sel_cmp = ndselect.compile(indexed.order, true, indexed.dtype)
+
+  //Walk tree in level order
+  var toVisit = [indexed]
+  while(pointer < n) {
+    var head = toVisit.shift()
+    var array = head
+    var nn = array.shape[0]|0
+    
+    //Find median
+    if(nn > 1) {
+      var k = bits.log2(pointer+1)%d
+      var median
+      var n_2 = inorderTree.root(nn)
+      median = sel_cmp(array, n_2, function(a,b) {
+        return a.get(k) - b.get(k)
+      })
+
+      //Copy into new array
+      var pptr = pointArray.index(pointer, 0)
+      var mptr = median.offset
+      for(var i=0; i<d; ++i) {
+        pointData[pptr++] = arrayData[mptr++]
+      }
+      indexArray[pointer] = arrayData[mptr]
+      pointer += 1
+
+      //Queue new items
+      toVisit.push(array.hi(n_2))
+      if(nn > 2) {
+        toVisit.push(array.lo(n_2+1))
+      }
+    } else {
+      //Copy into new array
+      var mptr = array.offset
+      var pptr = pointArray.index(pointer, 0)
+      for(var i=0; i<d; ++i) {
+        pointData[pptr+i] = arrayData[mptr++]
+      }
+      indexArray[pointer] = arrayData[mptr]
+      pointer += 1
+    }
+  }
+
+  //Release indexed
+  pool.free(indexed.data)
+
+  return new KDTree(pointArray, indexArray, n, d)
+}
+
+function deserializeKDTree(data) {
+  var points = data.p
+  var ids = data.i
+  if(points) {
+    var nd = points.length
+    var pointArray = pool.mallocFloat64(nd)
+    for(var i=0; i<nd; ++i) {
+      pointArray[i] = points[i]
+    }
+    var n = ids.length
+    var idArray = pool.mallocInt32(n)
+    for(var i=0; i<n; ++i) {
+      idArray[i] = ids[i]
+    }
+    var d = (nd/n)|0
+    return new KDTree(
+      ndarray(pointArray, [n,d]),
+      idArray,
+      n,
+      d)
+  } else {
+    return new KDTree(null, null, 0, data.d)
+  }
+}
+},{"./lib/heap.js":10,"bit-twiddle":11,"inorder-tree-layout":12,"ndarray":30,"ndarray-ops":14,"ndarray-pack":19,"ndarray-scratch":28,"ndarray-select":29,"typedarray-pool":33}],10:[function(require,module,exports){
+"use strict"
+
+module.exports = KDTHeap
+
+var pool = require("typedarray-pool")
+
+function heapParent(i) {
+  if(i & 1) {
+    return (i - 1) >> 1
+  }
+  return (i >> 1) - 1
+}
+
+function KDTHeap(n, d) {
+  this.count = 0
+  this.dataSize = d
+  this.index = pool.mallocInt32(n)
+  this.data = pool.mallocFloat64(n*d)
+}
+
+var proto = KDTHeap.prototype
+
+proto.heapSwap = function(_i,_j) {
+  var data = this.data
+  var index = this.index
+  var d = this.dataSize
+  var tmp = index[_i]
+  index[_i] = index[_j]
+  index[_j] = tmp
+  var aptr = d*_i
+  var bptr = d*_j
+  for(var _k=0; _k<d; ++_k) {
+    var t2 = data[aptr]
+    data[aptr] = data[bptr]
+    data[bptr] = t2
+    aptr += 1
+    bptr += 1
+  }
+}
+
+proto.heapUp = function(i) {
+  var d = this.dataSize
+  var index = this.index
+  var data = this.data
+  var w = data[d*i]
+  while(i>0) {
+    var parent = heapParent(i)
+    if(parent >= 0) {
+      var pw = data[d*parent]
+      if(w < pw) {
+        this.heapSwap(i, parent)
+        i = parent
+        continue
+      }
+    }
+    break
+  }
+}
+
+proto.heapDown = function(i) {
+  var d = this.dataSize
+  var index = this.index
+  var data = this.data
+  var count = this.count
+  var w = data[d*i]
+  while(true) {
+    var tw = w
+    var left  = 2*i + 1
+    var right = 2*(i + 1)
+    var next = i
+    if(left < count) {
+      var lw = data[d*left]
+      if(lw < tw) {
+        next = left
+        tw = lw
+      }
+    }
+    if(right < count) {
+      var rw = data[d*right]
+      if(rw < tw) {
+        next = right
+      }
+    }
+    if(next === i) {
+      break
+    }
+    this.heapSwap(i, next)
+    i = next      
+  }
+}
+
+//Clear item from top of heap
+proto.pop = function() {
+  this.count -= 1
+  this.heapSwap(0, this.count)
+  this.heapDown(0)
+}
+
+//Assume object already written to data
+proto.push = function() {
+  this.heapUp(this.count)
+  this.count += 1
+}
+
+proto.dispose = function() {
+  pool.freeInt32(this.index)
+  pool.freeFloat64(this.data)
+}
+},{"typedarray-pool":33}],11:[function(require,module,exports){
+/**
+ * Bit twiddling hacks for JavaScript.
+ *
+ * Author: Mikola Lysenko
+ *
+ * Ported from Stanford bit twiddling hack library:
+ *    http://graphics.stanford.edu/~seander/bithacks.html
+ */
+
+"use strict"; "use restrict";
+
+//Number of bits in an integer
+var INT_BITS = 32;
+
+//Constants
+exports.INT_BITS  = INT_BITS;
+exports.INT_MAX   =  0x7fffffff;
+exports.INT_MIN   = -1<<(INT_BITS-1);
+
+//Returns -1, 0, +1 depending on sign of x
+exports.sign = function(v) {
+  return (v > 0) - (v < 0);
+}
+
+//Computes absolute value of integer
+exports.abs = function(v) {
+  var mask = v >> (INT_BITS-1);
+  return (v ^ mask) - mask;
+}
+
+//Computes minimum of integers x and y
+exports.min = function(x, y) {
+  return y ^ ((x ^ y) & -(x < y));
+}
+
+//Computes maximum of integers x and y
+exports.max = function(x, y) {
+  return x ^ ((x ^ y) & -(x < y));
+}
+
+//Checks if a number is a power of two
+exports.isPow2 = function(v) {
+  return !(v & (v-1)) && (!!v);
+}
+
+//Computes log base 2 of v
+exports.log2 = function(v) {
+  var r, shift;
+  r =     (v > 0xFFFF) << 4; v >>>= r;
+  shift = (v > 0xFF  ) << 3; v >>>= shift; r |= shift;
+  shift = (v > 0xF   ) << 2; v >>>= shift; r |= shift;
+  shift = (v > 0x3   ) << 1; v >>>= shift; r |= shift;
+  return r | (v >> 1);
+}
+
+//Computes log base 10 of v
+exports.log10 = function(v) {
+  return  (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 :
+          (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 :
+          (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0;
+}
+
+//Counts number of bits
+exports.popCount = function(v) {
+  v = v - ((v >>> 1) & 0x55555555);
+  v = (v & 0x33333333) + ((v >>> 2) & 0x33333333);
+  return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24;
+}
+
+//Counts number of trailing zeros
+function countTrailingZeros(v) {
+  var c = 32;
+  v &= -v;
+  if (v) c--;
+  if (v & 0x0000FFFF) c -= 16;
+  if (v & 0x00FF00FF) c -= 8;
+  if (v & 0x0F0F0F0F) c -= 4;
+  if (v & 0x33333333) c -= 2;
+  if (v & 0x55555555) c -= 1;
+  return c;
+}
+exports.countTrailingZeros = countTrailingZeros;
+
+//Rounds to next power of 2
+exports.nextPow2 = function(v) {
+  v += v === 0;
+  --v;
+  v |= v >>> 1;
+  v |= v >>> 2;
+  v |= v >>> 4;
+  v |= v >>> 8;
+  v |= v >>> 16;
+  return v + 1;
+}
+
+//Rounds down to previous power of 2
+exports.prevPow2 = function(v) {
+  v |= v >>> 1;
+  v |= v >>> 2;
+  v |= v >>> 4;
+  v |= v >>> 8;
+  v |= v >>> 16;
+  return v - (v>>>1);
+}
+
+//Computes parity of word
+exports.parity = function(v) {
+  v ^= v >>> 16;
+  v ^= v >>> 8;
+  v ^= v >>> 4;
+  v &= 0xf;
+  return (0x6996 >>> v) & 1;
+}
+
+var REVERSE_TABLE = new Array(256);
+
+(function(tab) {
+  for(var i=0; i<256; ++i) {
+    var v = i, r = i, s = 7;
+    for (v >>>= 1; v; v >>>= 1) {
+      r <<= 1;
+      r |= v & 1;
+      --s;
+    }
+    tab[i] = (r << s) & 0xff;
+  }
+})(REVERSE_TABLE);
+
+//Reverse bits in a 32 bit word
+exports.reverse = function(v) {
+  return  (REVERSE_TABLE[ v         & 0xff] << 24) |
+          (REVERSE_TABLE[(v >>> 8)  & 0xff] << 16) |
+          (REVERSE_TABLE[(v >>> 16) & 0xff] << 8)  |
+           REVERSE_TABLE[(v >>> 24) & 0xff];
+}
+
+//Interleave bits of 2 coordinates with 16 bits.  Useful for fast quadtree codes
+exports.interleave2 = function(x, y) {
+  x &= 0xFFFF;
+  x = (x | (x << 8)) & 0x00FF00FF;
+  x = (x | (x << 4)) & 0x0F0F0F0F;
+  x = (x | (x << 2)) & 0x33333333;
+  x = (x | (x << 1)) & 0x55555555;
+
+  y &= 0xFFFF;
+  y = (y | (y << 8)) & 0x00FF00FF;
+  y = (y | (y << 4)) & 0x0F0F0F0F;
+  y = (y | (y << 2)) & 0x33333333;
+  y = (y | (y << 1)) & 0x55555555;
+
+  return x | (y << 1);
+}
+
+//Extracts the nth interleaved component
+exports.deinterleave2 = function(v, n) {
+  v = (v >>> n) & 0x55555555;
+  v = (v | (v >>> 1))  & 0x33333333;
+  v = (v | (v >>> 2))  & 0x0F0F0F0F;
+  v = (v | (v >>> 4))  & 0x00FF00FF;
+  v = (v | (v >>> 16)) & 0x000FFFF;
+  return (v << 16) >> 16;
+}
+
+
+//Interleave bits of 3 coordinates, each with 10 bits.  Useful for fast octree codes
+exports.interleave3 = function(x, y, z) {
+  x &= 0x3FF;
+  x  = (x | (x<<16)) & 4278190335;
+  x  = (x | (x<<8))  & 251719695;
+  x  = (x | (x<<4))  & 3272356035;
+  x  = (x | (x<<2))  & 1227133513;
+
+  y &= 0x3FF;
+  y  = (y | (y<<16)) & 4278190335;
+  y  = (y | (y<<8))  & 251719695;
+  y  = (y | (y<<4))  & 3272356035;
+  y  = (y | (y<<2))  & 1227133513;
+  x |= (y << 1);
+  
+  z &= 0x3FF;
+  z  = (z | (z<<16)) & 4278190335;
+  z  = (z | (z<<8))  & 251719695;
+  z  = (z | (z<<4))  & 3272356035;
+  z  = (z | (z<<2))  & 1227133513;
+  
+  return x | (z << 2);
+}
+
+//Extracts nth interleaved component of a 3-tuple
+exports.deinterleave3 = function(v, n) {
+  v = (v >>> n)       & 1227133513;
+  v = (v | (v>>>2))   & 3272356035;
+  v = (v | (v>>>4))   & 251719695;
+  v = (v | (v>>>8))   & 4278190335;
+  v = (v | (v>>>16))  & 0x3FF;
+  return (v<<22)>>22;
+}
+
+//Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page)
+exports.nextCombination = function(v) {
+  var t = v | (v - 1);
+  return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1));
+}
+
+
+},{}],12:[function(require,module,exports){
+"use strict"
+
+var bits = require("bit-twiddle")
+
+function rootInorder(n) {
+  var ptree = (bits.nextPow2(n+1)>>>1) - 1
+  var f     = n - ptree
+  if(bits.nextPow2(f)-1 >= ptree) {
+    return ptree
+  }
+  return (ptree>>>1)+f
+}
+exports.root = rootInorder
+
+function beginInorder(n) {
+  return 0
+}
+exports.begin = beginInorder
+
+function endInorder(n) {
+  return n-1
+}
+exports.end = endInorder
+
+
+//This is really horrible because n is not necessarily a power of 2
+// If it was, we could just do:
+//
+//    height = bits.countTrailingZeros(~x)
+//
+// Instead, we just binary search because doing the right thing here is way too complicated.
+function heightInorder(n, x) {
+  if(n <= 0) {
+    return 0
+  }
+  var r = rootInorder(n)
+  if(x > r) {
+    return heightInorder(n-r-1, x-r-1)
+  } else if(x === r) {
+    return bits.log2(n)
+  }
+  return heightInorder(r, x)
+}
+exports.height = heightInorder
+
+function prevInorder(n, x) {
+  return Math.max(x-1,0)
+}
+exports.prev = prevInorder
+
+function nextInorder(n, x) {
+  return Math.min(x+1,n-1)
+}
+exports.next = nextInorder
+
+
+//The version for n = (1<<k)-1:
+//
+//  parent = (x & ~(1<<(h+1))) + (1<<h)
+//
+function parentInorder(n, x) {
+  if(n <= 0) {
+    return -1
+  }
+  var r = rootInorder(n)
+  if(x > r) {
+    var q = parentInorder(n-r-1, x-r-1)
+    if(q < 0) {
+      return r
+    } else {
+      return q + r + 1
+    }
+  } else if(x === r) {
+    return -1
+  }
+  var q =  parentInorder(r, x)
+  if(q < 0) {
+    return r
+  }
+  return q
+}
+exports.parent = parentInorder
+
+
+//Again, we get screwed because n is not a power of two -1.  If it was, we could do:
+//
+//    left = x - (1 << (h-1) )
+//
+// Where h is the height of the node
+//
+function leftInorder(n, x) {
+  if(n <= 0) {
+    return 0
+  }
+  var r = rootInorder(n)
+  if(x > r) {
+    return leftInorder(n-r-1, x-r-1) + r + 1
+  } else if(x === r) {
+    return rootInorder(x)
+  }
+  return leftInorder(r, x)
+
+}
+exports.left = leftInorder
+
+//for power of two minus one:
+//
+//    right = x + (1<<(h-1))
+//
+function rightInorder(n, x) {
+  if(n <= 0) {
+    return 0
+  }
+  var r = rootInorder(n)
+  if(x > r) {
+    return rightInorder(n-r-1, x-r-1) + r + 1
+  } else if(x === r) {
+    return rootInorder(n-r-1) + r + 1
+  }
+  return rightInorder(r, x)
+}
+exports.right = rightInorder
+
+
+function leafInorder(n, x) {
+  return heightInorder(n, x) === 0
+}
+exports.leaf = leafInorder
+
+
+function loInorder(n, x) {
+  n |= 0
+  x |= 0
+  var l = 0
+  while(n > 1) {
+    var r = rootInorder(n)
+    if(x > r) {
+      l += r + 1
+      n -= r + 1
+      x -= r + 1
+    } else if(x === r) {
+      break
+    } else {
+      n = r
+    }
+  }
+  return l
+}
+exports.lo = loInorder
+
+function hiInorder(n, x) {
+  n |= 0
+  x |= 0
+  var l = 0
+  while(n > 1) {
+    var r = rootInorder(n)
+    if(x > r) {
+      l += r + 1
+      n -= r + 1
+      x -= r + 1
+    } else if(x === r) {
+      l += n-1
+      break
+    } else {
+      n = r
+    }
+  }
+  return l
+}
+exports.hi = hiInorder
+
+},{"bit-twiddle":13}],13:[function(require,module,exports){
+arguments[4][11][0].apply(exports,arguments)
+},{"dup":11}],14:[function(require,module,exports){
+"use strict"
+
+var compile = require("cwise-compiler")
+
+var EmptyProc = {
+  body: "",
+  args: [],
+  thisVars: [],
+  localVars: []
+}
+
+function fixup(x) {
+  if(!x) {
+    return EmptyProc
+  }
+  for(var i=0; i<x.args.length; ++i) {
+    var a = x.args[i]
+    if(i === 0) {
+      x.args[i] = {name: a, lvalue:true, rvalue: !!x.rvalue, count:x.count||1 }
+    } else {
+      x.args[i] = {name: a, lvalue:false, rvalue:true, count: 1}
+    }
+  }
+  if(!x.thisVars) {
+    x.thisVars = []
+  }
+  if(!x.localVars) {
+    x.localVars = []
+  }
+  return x
+}
+
+function pcompile(user_args) {
+  return compile({
+    args:     user_args.args,
+    pre:      fixup(user_args.pre),
+    body:     fixup(user_args.body),
+    post:     fixup(user_args.proc),
+    funcName: user_args.funcName
+  })
+}
+
+function makeOp(user_args) {
+  var args = []
+  for(var i=0; i<user_args.args.length; ++i) {
+    args.push("a"+i)
+  }
+  var wrapper = new Function("P", [
+    "return function ", user_args.funcName, "_ndarrayops(", args.join(","), ") {P(", args.join(","), ");return a0}"
+  ].join(""))
+  return wrapper(pcompile(user_args))
+}
+
+var assign_ops = {
+  add:  "+",
+  sub:  "-",
+  mul:  "*",
+  div:  "/",
+  mod:  "%",
+  band: "&",
+  bor:  "|",
+  bxor: "^",
+  lshift: "<<",
+  rshift: ">>",
+  rrshift: ">>>"
+}
+;(function(){
+  for(var id in assign_ops) {
+    var op = assign_ops[id]
+    exports[id] = makeOp({
+      args: ["array","array","array"],
+      body: {args:["a","b","c"],
+             body: "a=b"+op+"c"},
+      funcName: id
+    })
+    exports[id+"eq"] = makeOp({
+      args: ["array","array"],
+      body: {args:["a","b"],
+             body:"a"+op+"=b"},
+      rvalue: true,
+      funcName: id+"eq"
+    })
+    exports[id+"s"] = makeOp({
+      args: ["array", "array", "scalar"],
+      body: {args:["a","b","s"],
+             body:"a=b"+op+"s"},
+      funcName: id+"s"
+    })
+    exports[id+"seq"] = makeOp({
+      args: ["array","scalar"],
+      body: {args:["a","s"],
+             body:"a"+op+"=s"},
+      rvalue: true,
+      funcName: id+"seq"
+    })
+  }
+})();
+
+var unary_ops = {
+  not: "!",
+  bnot: "~",
+  neg: "-",
+  recip: "1.0/"
+}
+;(function(){
+  for(var id in unary_ops) {
+    var op = unary_ops[id]
+    exports[id] = makeOp({
+      args: ["array", "array"],
+      body: {args:["a","b"],
+             body:"a="+op+"b"},
+      funcName: id
+    })
+    exports[id+"eq"] = makeOp({
+      args: ["array"],
+      body: {args:["a"],
+             body:"a="+op+"a"},
+      rvalue: true,
+      count: 2,
+      funcName: id+"eq"
+    })
+  }
+})();
+
+var binary_ops = {
+  and: "&&",
+  or: "||",
+  eq: "===",
+  neq: "!==",
+  lt: "<",
+  gt: ">",
+  leq: "<=",
+  geq: ">="
+}
+;(function() {
+  for(var id in binary_ops) {
+    var op = binary_ops[id]
+    exports[id] = makeOp({
+      args: ["array","array","array"],
+      body: {args:["a", "b", "c"],
+             body:"a=b"+op+"c"},
+      funcName: id
+    })
+    exports[id+"s"] = makeOp({
+      args: ["array","array","scalar"],
+      body: {args:["a", "b", "s"],
+             body:"a=b"+op+"s"},
+      funcName: id+"s"
+    })
+    exports[id+"eq"] = makeOp({
+      args: ["array", "array"],
+      body: {args:["a", "b"],
+             body:"a=a"+op+"b"},
+      rvalue:true,
+      count:2,
+      funcName: id+"eq"
+    })
+    exports[id+"seq"] = makeOp({
+      args: ["array", "scalar"],
+      body: {args:["a","s"],
+             body:"a=a"+op+"s"},
+      rvalue:true,
+      count:2,
+      funcName: id+"seq"
+    })
+  }
+})();
+
+var math_unary = [
+  "abs",
+  "acos",
+  "asin",
+  "atan",
+  "ceil",
+  "cos",
+  "exp",
+  "floor",
+  "log",
+  "round",
+  "sin",
+  "sqrt",
+  "tan"
+]
+;(function() {
+  for(var i=0; i<math_unary.length; ++i) {
+    var f = math_unary[i]
+    exports[f] = makeOp({
+                    args: ["array", "array"],
+                    pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
+                    body: {args:["a","b"], body:"a=this_f(b)", thisVars:["this_f"]},
+                    funcName: f
+                  })
+    exports[f+"eq"] = makeOp({
+                      args: ["array"],
+                      pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
+                      body: {args: ["a"], body:"a=this_f(a)", thisVars:["this_f"]},
+                      rvalue: true,
+                      count: 2,
+                      funcName: f+"eq"
+                    })
+  }
+})();
+
+var math_comm = [
+  "max",
+  "min",
+  "atan2",
+  "pow"
+]
+;(function(){
+  for(var i=0; i<math_comm.length; ++i) {
+    var f= math_comm[i]
+    exports[f] = makeOp({
+                  args:["array", "array", "array"],
+                  pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
+                  body: {args:["a","b","c"], body:"a=this_f(b,c)", thisVars:["this_f"]},
+                  funcName: f
+                })
+    exports[f+"s"] = makeOp({
+                  args:["array", "array", "scalar"],
+                  pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
+                  body: {args:["a","b","c"], body:"a=this_f(b,c)", thisVars:["this_f"]},
+                  funcName: f+"s"
+                  })
+    exports[f+"eq"] = makeOp({ args:["array", "array"],
+                  pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
+                  body: {args:["a","b"], body:"a=this_f(a,b)", thisVars:["this_f"]},
+                  rvalue: true,
+                  count: 2,
+                  funcName: f+"eq"
+                  })
+    exports[f+"seq"] = makeOp({ args:["array", "scalar"],
+                  pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
+                  body: {args:["a","b"], body:"a=this_f(a,b)", thisVars:["this_f"]},
+                  rvalue:true,
+                  count:2,
+                  funcName: f+"seq"
+                  })
+  }
+})();
+
+var math_noncomm = [
+  "atan2",
+  "pow"
+]
+;(function(){
+  for(var i=0; i<math_noncomm.length; ++i) {
+    var f= math_noncomm[i]
+    exports[f+"op"] = makeOp({
+                  args:["array", "array", "array"],
+                  pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
+                  body: {args:["a","b","c"], body:"a=this_f(c,b)", thisVars:["this_f"]},
+                  funcName: f+"op"
+                })
+    exports[f+"ops"] = makeOp({
+                  args:["array", "array", "scalar"],
+                  pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
+                  body: {args:["a","b","c"], body:"a=this_f(c,b)", thisVars:["this_f"]},
+                  funcName: f+"ops"
+                  })
+    exports[f+"opeq"] = makeOp({ args:["array", "array"],
+                  pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
+                  body: {args:["a","b"], body:"a=this_f(b,a)", thisVars:["this_f"]},
+                  rvalue: true,
+                  count: 2,
+                  funcName: f+"opeq"
+                  })
+    exports[f+"opseq"] = makeOp({ args:["array", "scalar"],
+                  pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
+                  body: {args:["a","b"], body:"a=this_f(b,a)", thisVars:["this_f"]},
+                  rvalue:true,
+                  count:2,
+                  funcName: f+"opseq"
+                  })
+  }
+})();
+
+exports.any = compile({
+  args:["array"],
+  pre: EmptyProc,
+  body: {args:[{name:"a", lvalue:false, rvalue:true, count:1}], body: "if(a){return true}", localVars: [], thisVars: []},
+  post: {args:[], localVars:[], thisVars:[], body:"return false"},
+  funcName: "any"
+})
+
+exports.all = compile({
+  args:["array"],
+  pre: EmptyProc,
+  body: {args:[{name:"x", lvalue:false, rvalue:true, count:1}], body: "if(!x){return false}", localVars: [], thisVars: []},
+  post: {args:[], localVars:[], thisVars:[], body:"return true"},
+  funcName: "all"
+})
+
+exports.sum = compile({
+  args:["array"],
+  pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
+  body: {args:[{name:"a", lvalue:false, rvalue:true, count:1}], body: "this_s+=a", localVars: [], thisVars: ["this_s"]},
+  post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
+  funcName: "sum"
+})
+
+exports.prod = compile({
+  args:["array"],
+  pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=1"},
+  body: {args:[{name:"a", lvalue:false, rvalue:true, count:1}], body: "this_s*=a", localVars: [], thisVars: ["this_s"]},
+  post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
+  funcName: "prod"
+})
+
+exports.norm2squared = compile({
+  args:["array"],
+  pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
+  body: {args:[{name:"a", lvalue:false, rvalue:true, count:2}], body: "this_s+=a*a", localVars: [], thisVars: ["this_s"]},
+  post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
+  funcName: "norm2squared"
+})
+  
+exports.norm2 = compile({
+  args:["array"],
+  pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
+  body: {args:[{name:"a", lvalue:false, rvalue:true, count:2}], body: "this_s+=a*a", localVars: [], thisVars: ["this_s"]},
+  post: {args:[], localVars:[], thisVars:["this_s"], body:"return Math.sqrt(this_s)"},
+  funcName: "norm2"
+})
+  
+
+exports.norminf = compile({
+  args:["array"],
+  pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
+  body: {args:[{name:"a", lvalue:false, rvalue:true, count:4}], body:"if(-a>this_s){this_s=-a}else if(a>this_s){this_s=a}", localVars: [], thisVars: ["this_s"]},
+  post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
+  funcName: "norminf"
+})
+
+exports.norm1 = compile({
+  args:["array"],
+  pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
+  body: {args:[{name:"a", lvalue:false, rvalue:true, count:3}], body: "this_s+=a<0?-a:a", localVars: [], thisVars: ["this_s"]},
+  post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
+  funcName: "norm1"
+})
+
+exports.sup = compile({
+  args: [ "array" ],
+  pre:
+   { body: "this_h=-Infinity",
+     args: [],
+     thisVars: [ "this_h" ],
+     localVars: [] },
+  body:
+   { body: "if(_inline_1_arg0_>this_h)this_h=_inline_1_arg0_",
+     args: [{"name":"_inline_1_arg0_","lvalue":false,"rvalue":true,"count":2} ],
+     thisVars: [ "this_h" ],
+     localVars: [] },
+  post:
+   { body: "return this_h",
+     args: [],
+     thisVars: [ "this_h" ],
+     localVars: [] }
+ })
+
+exports.inf = compile({
+  args: [ "array" ],
+  pre:
+   { body: "this_h=Infinity",
+     args: [],
+     thisVars: [ "this_h" ],
+     localVars: [] },
+  body:
+   { body: "if(_inline_1_arg0_<this_h)this_h=_inline_1_arg0_",
+     args: [{"name":"_inline_1_arg0_","lvalue":false,"rvalue":true,"count":2} ],
+     thisVars: [ "this_h" ],
+     localVars: [] },
+  post:
+   { body: "return this_h",
+     args: [],
+     thisVars: [ "this_h" ],
+     localVars: [] }
+ })
+
+exports.argmin = compile({
+  args:["index","array","shape"],
+  pre:{
+    body:"{this_v=Infinity;this_i=_inline_0_arg2_.slice(0)}",
+    args:[
+      {name:"_inline_0_arg0_",lvalue:false,rvalue:false,count:0},
+      {name:"_inline_0_arg1_",lvalue:false,rvalue:false,count:0},
+      {name:"_inline_0_arg2_",lvalue:false,rvalue:true,count:1}
+      ],
+    thisVars:["this_i","this_v"],
+    localVars:[]},
+  body:{
+    body:"{if(_inline_1_arg1_<this_v){this_v=_inline_1_arg1_;for(var _inline_1_k=0;_inline_1_k<_inline_1_arg0_.length;++_inline_1_k){this_i[_inline_1_k]=_inline_1_arg0_[_inline_1_k]}}}",
+    args:[
+      {name:"_inline_1_arg0_",lvalue:false,rvalue:true,count:2},
+      {name:"_inline_1_arg1_",lvalue:false,rvalue:true,count:2}],
+    thisVars:["this_i","this_v"],
+    localVars:["_inline_1_k"]},
+  post:{
+    body:"{return this_i}",
+    args:[],
+    thisVars:["this_i"],
+    localVars:[]}
+})
+
+exports.argmax = compile({
+  args:["index","array","shape"],
+  pre:{
+    body:"{this_v=-Infinity;this_i=_inline_0_arg2_.slice(0)}",
+    args:[
+      {name:"_inline_0_arg0_",lvalue:false,rvalue:false,count:0},
+      {name:"_inline_0_arg1_",lvalue:false,rvalue:false,count:0},
+      {name:"_inline_0_arg2_",lvalue:false,rvalue:true,count:1}
+      ],
+    thisVars:["this_i","this_v"],
+    localVars:[]},
+  body:{
+    body:"{if(_inline_1_arg1_>this_v){this_v=_inline_1_arg1_;for(var _inline_1_k=0;_inline_1_k<_inline_1_arg0_.length;++_inline_1_k){this_i[_inline_1_k]=_inline_1_arg0_[_inline_1_k]}}}",
+    args:[
+      {name:"_inline_1_arg0_",lvalue:false,rvalue:true,count:2},
+      {name:"_inline_1_arg1_",lvalue:false,rvalue:true,count:2}],
+    thisVars:["this_i","this_v"],
+    localVars:["_inline_1_k"]},
+  post:{
+    body:"{return this_i}",
+    args:[],
+    thisVars:["this_i"],
+    localVars:[]}
+})  
+
+exports.random = makeOp({
+  args: ["array"],
+  pre: {args:[], body:"this_f=Math.random", thisVars:["this_f"]},
+  body: {args: ["a"], body:"a=this_f()", thisVars:["this_f"]},
+  funcName: "random"
+})
+
+exports.assign = makeOp({
+  args:["array", "array"],
+  body: {args:["a", "b"], body:"a=b"},
+  funcName: "assign" })
+
+exports.assigns = makeOp({
+  args:["array", "scalar"],
+  body: {args:["a", "b"], body:"a=b"},
+  funcName: "assigns" })
+
+
+exports.equals = compile({
+  args:["array", "array"],
+  pre: EmptyProc,
+  body: {args:[{name:"x", lvalue:false, rvalue:true, count:1},
+               {name:"y", lvalue:false, rvalue:true, count:1}], 
+        body: "if(x!==y){return false}", 
+        localVars: [], 
+        thisVars: []},
+  post: {args:[], localVars:[], thisVars:[], body:"return true"},
+  funcName: "equals"
+})
+
+
+
+},{"cwise-compiler":15}],15:[function(require,module,exports){
+"use strict"
+
+var createThunk = require("./lib/thunk.js")
+
+function Procedure() {
+  this.argTypes = []
+  this.shimArgs = []
+  this.arrayArgs = []
+  this.scalarArgs = []
+  this.offsetArgs = []
+  this.offsetArgIndex = []
+  this.indexArgs = []
+  this.shapeArgs = []
+  this.funcName = ""
+  this.pre = null
+  this.body = null
+  this.post = null
+  this.debug = false
+}
+
+function compileCwise(user_args) {
+  //Create procedure
+  var proc = new Procedure()
+  
+  //Parse blocks
+  proc.pre    = user_args.pre
+  proc.body   = user_args.body
+  proc.post   = user_args.post
+
+  //Parse arguments
+  var proc_args = user_args.args.slice(0)
+  proc.argTypes = proc_args
+  for(var i=0; i<proc_args.length; ++i) {
+    var arg_type = proc_args[i]
+    if(arg_type === "array") {
+      proc.arrayArgs.push(i)
+      proc.shimArgs.push("array" + i)
+      if(i < proc.pre.args.length && proc.pre.args[i].count>0) {
+        throw new Error("cwise: pre() block may not reference array args")
+      }
+      if(i < proc.post.args.length && proc.post.args[i].count>0) {
+        throw new Error("cwise: post() block may not reference array args")
+      }
+    } else if(arg_type === "scalar") {
+      proc.scalarArgs.push(i)
+      proc.shimArgs.push("scalar" + i)
+    } else if(arg_type === "index") {
+      proc.indexArgs.push(i)
+      if(i < proc.pre.args.length && proc.pre.args[i].count > 0) {
+        throw new Error("cwise: pre() block may not reference array index")
+      }
+      if(i < proc.body.args.length && proc.body.args[i].lvalue) {
+        throw new Error("cwise: body() block may not write to array index")
+      }
+      if(i < proc.post.args.length && proc.post.args[i].count > 0) {
+        throw new Error("cwise: post() block may not reference array index")
+      }
+    } else if(arg_type === "shape") {
+      proc.shapeArgs.push(i)
+      if(i < proc.pre.args.length && proc.pre.args[i].lvalue) {
+        throw new Error("cwise: pre() block may not write to array shape")
+      }
+      if(i < proc.body.args.length && proc.body.args[i].lvalue) {
+        throw new Error("cwise: body() block may not write to array shape")
+      }
+      if(i < proc.post.args.length && proc.post.args[i].lvalue) {
+        throw new Error("cwise: post() block may not write to array shape")
+      }
+    } else if(typeof arg_type === "object" && arg_type.offset) {
+      proc.argTypes[i] = "offset"
+      proc.offsetArgs.push({ array: arg_type.array, offset:arg_type.offset })
+      proc.offsetArgIndex.push(i)
+    } else {
+      throw new Error("cwise: Unknown argument type " + proc_args[i])
+    }
+  }
+  
+  //Make sure at least one array argument was specified
+  if(proc.arrayArgs.length <= 0) {
+    throw new Error("cwise: No array arguments specified")
+  }
+  
+  //Make sure arguments are correct
+  if(proc.pre.args.length > proc_args.length) {
+    throw new Error("cwise: Too many arguments in pre() block")
+  }
+  if(proc.body.args.length > proc_args.length) {
+    throw new Error("cwise: Too many arguments in body() block")
+  }
+  if(proc.post.args.length > proc_args.length) {
+    throw new Error("cwise: Too many arguments in post() block")
+  }
+
+  //Check debug flag
+  proc.debug = !!user_args.printCode || !!user_args.debug
+  
+  //Retrieve name
+  proc.funcName = user_args.funcName || "cwise"
+  
+  //Read in block size
+  proc.blockSize = user_args.blockSize || 64
+
+  return createThunk(proc)
+}
+
+module.exports = compileCwise
+
+},{"./lib/thunk.js":17}],16:[function(require,module,exports){
+"use strict"
+
+var uniq = require("uniq")
+
+function innerFill(order, proc, body) {
+  var dimension = order.length
+    , nargs = proc.arrayArgs.length
+    , has_index = proc.indexArgs.length>0
+    , code = []
+    , vars = []
+    , idx=0, pidx=0, i, j
+  for(i=0; i<dimension; ++i) {
+    vars.push(["i",i,"=0"].join(""))
+  }
+  //Compute scan deltas
+  for(j=0; j<nargs; ++j) {
+    for(i=0; i<dimension; ++i) {
+      pidx = idx
+      idx = order[i]
+      if(i === 0) {
+        vars.push(["d",j,"s",i,"=t",j,"p",idx].join(""))
+      } else {
+        vars.push(["d",j,"s",i,"=(t",j,"p",idx,"-s",pidx,"*t",j,"p",pidx,")"].join(""))
+      }
+    }
+  }
+  code.push("var " + vars.join(","))
+  //Scan loop
+  for(i=dimension-1; i>=0; --i) {
+    idx = order[i]
+    code.push(["for(i",i,"=0;i",i,"<s",idx,";++i",i,"){"].join(""))
+  }
+  //Push body of inner loop
+  code.push(body)
+  //Advance scan pointers
+  for(i=0; i<dimension; ++i) {
+    pidx = idx
+    idx = order[i]
+    for(j=0; j<nargs; ++j) {
+      code.push(["p",j,"+=d",j,"s",i].join(""))
+    }
+    if(has_index) {
+      if(i > 0) {
+        code.push(["index[",pidx,"]-=s",pidx].join(""))
+      }
+      code.push(["++index[",idx,"]"].join(""))
+    }
+    code.push("}")
+  }
+  return code.join("\n")
+}
+
+function outerFill(matched, order, proc, body) {
+  var dimension = order.length
+    , nargs = proc.arrayArgs.length
+    , blockSize = proc.blockSize
+    , has_index = proc.indexArgs.length > 0
+    , code = []
+  for(var i=0; i<nargs; ++i) {
+    code.push(["var offset",i,"=p",i].join(""))
+  }
+  //Generate matched loops
+  for(var i=matched; i<dimension; ++i) {
+    code.push(["for(var j"+i+"=SS[", order[i], "]|0;j", i, ">0;){"].join(""))
+    code.push(["if(j",i,"<",blockSize,"){"].join(""))
+    code.push(["s",order[i],"=j",i].join(""))
+    code.push(["j",i,"=0"].join(""))
+    code.push(["}else{s",order[i],"=",blockSize].join(""))
+    code.push(["j",i,"-=",blockSize,"}"].join(""))
+    if(has_index) {
+      code.push(["index[",order[i],"]=j",i].join(""))
+    }
+  }
+  for(var i=0; i<nargs; ++i) {
+    var indexStr = ["offset"+i]
+    for(var j=matched; j<dimension; ++j) {
+      indexStr.push(["j",j,"*t",i,"p",order[j]].join(""))
+    }
+    code.push(["p",i,"=(",indexStr.join("+"),")"].join(""))
+  }
+  code.push(innerFill(order, proc, body))
+  for(var i=matched; i<dimension; ++i) {
+    code.push("}")
+  }
+  return code.join("\n")
+}
+
+//Count the number of compatible inner orders
+function countMatches(orders) {
+  var matched = 0, dimension = orders[0].length
+  while(matched < dimension) {
+    for(var j=1; j<orders.length; ++j) {
+      if(orders[j][matched] !== orders[0][matched]) {
+        return matched
+      }
+    }
+    ++matched
+  }
+  return matched
+}
+
+//Processes a block according to the given data types
+function processBlock(block, proc, dtypes) {
+  var code = block.body
+  var pre = []
+  var post = []
+  for(var i=0; i<block.args.length; ++i) {
+    var carg = block.args[i]
+    if(carg.count <= 0) {
+      continue
+    }
+    var re = new RegExp(carg.name, "g")
+    var ptrStr = ""
+    var arrNum = proc.arrayArgs.indexOf(i)
+    switch(proc.argTypes[i]) {
+      case "offset":
+        var offArgIndex = proc.offsetArgIndex.indexOf(i)
+        var offArg = proc.offsetArgs[offArgIndex]
+        arrNum = offArg.array
+        ptrStr = "+q" + offArgIndex
+      case "array":
+        ptrStr = "p" + arrNum + ptrStr
+        var localStr = "l" + i
+        var arrStr = "a" + arrNum
+        if(carg.count === 1) {
+          if(dtypes[arrNum] === "generic") {
+            if(carg.lvalue) {
+              pre.push(["var ", localStr, "=", arrStr, ".get(", ptrStr, ")"].join(""))
+              code = code.replace(re, localStr)
+              post.push([arrStr, ".set(", ptrStr, ",", localStr,")"].join(""))
+            } else {
+              code = code.replace(re, [arrStr, ".get(", ptrStr, ")"].join(""))
+            }
+          } else {
+            code = code.replace(re, [arrStr, "[", ptrStr, "]"].join(""))
+          }
+        } else if(dtypes[arrNum] === "generic") {
+          pre.push(["var ", localStr, "=", arrStr, ".get(", ptrStr, ")"].join(""))
+          code = code.replace(re, localStr)
+          if(carg.lvalue) {
+            post.push([arrStr, ".set(", ptrStr, ",", localStr,")"].join(""))
+          }
+        } else {
+          pre.push(["var ", localStr, "=", arrStr, "[", ptrStr, "]"].join(""))
+          code = code.replace(re, localStr)
+          if(carg.lvalue) {
+            post.push([arrStr, "[", ptrStr, "]=", localStr].join(""))
+          }
+        }
+      break
+      case "scalar":
+        code = code.replace(re, "Y" + proc.scalarArgs.indexOf(i))
+      break
+      case "index":
+        code = code.replace(re, "index")
+      break
+      case "shape":
+        code = code.replace(re, "shape")
+      break
+    }
+  }
+  return [pre.join("\n"), code, post.join("\n")].join("\n").trim()
+}
+
+function typeSummary(dtypes) {
+  var summary = new Array(dtypes.length)
+  var allEqual = true
+  for(var i=0; i<dtypes.length; ++i) {
+    var t = dtypes[i]
+    var digits = t.match(/\d+/)
+    if(!digits) {
+      digits = ""
+    } else {
+      digits = digits[0]
+    }
+    if(t.charAt(0) === 0) {
+      summary[i] = "u" + t.charAt(1) + digits
+    } else {
+      summary[i] = t.charAt(0) + digits
+    }
+    if(i > 0) {
+      allEqual = allEqual && summary[i] === summary[i-1]
+    }
+  }
+  if(allEqual) {
+    return summary[0]
+  }
+  return summary.join("")
+}
+
+//Generates a cwise operator
+function generateCWiseOp(proc, typesig) {
+
+  //Compute dimension
+  var dimension = typesig[1].length|0
+  var orders = new Array(proc.arrayArgs.length)
+  var dtypes = new Array(proc.arrayArgs.length)
+
+  //First create arguments for procedure
+  var arglist = ["SS"]
+  var code = ["'use strict'"]
+  var vars = []
+  
+  for(var j=0; j<dimension; ++j) {
+    vars.push(["s", j, "=SS[", j, "]"].join(""))
+  }
+  for(var i=0; i<proc.arrayArgs.length; ++i) {
+    arglist.push("a"+i)
+    arglist.push("t"+i)
+    arglist.push("p"+i)
+    dtypes[i] = typesig[2*i]
+    orders[i] = typesig[2*i+1]
+    
+    for(var j=0; j<dimension; ++j) {
+      vars.push(["t",i,"p",j,"=t",i,"[",j,"]"].join(""))
+    }
+  }
+  for(var i=0; i<proc.scalarArgs.length; ++i) {
+    arglist.push("Y" + i)
+  }
+  if(proc.shapeArgs.length > 0) {
+    vars.push("shape=SS.slice(0)")
+  }
+  if(proc.indexArgs.length > 0) {
+    var zeros = new Array(dimension)
+    for(var i=0; i<dimension; ++i) {
+      zeros[i] = "0"
+    }
+    vars.push(["index=[", zeros.join(","), "]"].join(""))
+  }
+  for(var i=0; i<proc.offsetArgs.length; ++i) {
+    var off_arg = proc.offsetArgs[i]
+    var init_string = []
+    for(var j=0; j<off_arg.offset.length; ++j) {
+      if(off_arg.offset[j] === 0) {
+        continue
+      } else if(off_arg.offset[j] === 1) {
+        init_string.push(["t", off_arg.array, "p", j].join(""))      
+      } else {
+        init_string.push([off_arg.offset[j], "*t", off_arg.array, "p", j].join(""))
+      }
+    }
+    if(init_string.length === 0) {
+      vars.push("q" + i + "=0")
+    } else {
+      vars.push(["q", i, "=", init_string.join("+")].join(""))
+    }
+  }
+
+  //Prepare this variables
+  var thisVars = uniq([].concat(proc.pre.thisVars)
+                      .concat(proc.body.thisVars)
+                      .concat(proc.post.thisVars))
+  vars = vars.concat(thisVars)
+  code.push("var " + vars.join(","))
+  for(var i=0; i<proc.arrayArgs.length; ++i) {
+    code.push("p"+i+"|=0")
+  }
+  
+  //Inline prelude
+  if(proc.pre.body.length > 3) {
+    code.push(processBlock(proc.pre, proc, dtypes))
+  }
+
+  //Process body
+  var body = processBlock(proc.body, proc, dtypes)
+  var matched = countMatches(orders)
+  if(matched < dimension) {
+    code.push(outerFill(matched, orders[0], proc, body))
+  } else {
+    code.push(innerFill(orders[0], proc, body))
+  }
+
+  //Inline epilog
+  if(proc.post.body.length > 3) {
+    code.push(processBlock(proc.post, proc, dtypes))
+  }
+  
+  if(proc.debug) {
+    console.log("Generated cwise routine for ", typesig, ":\n\n", code.join("\n"))
+  }
+  
+  var loopName = [(proc.funcName||"unnamed"), "_cwise_loop_", orders[0].join("s"),"m",matched,typeSummary(dtypes)].join("")
+  var f = new Function(["function ",loopName,"(", arglist.join(","),"){", code.join("\n"),"} return ", loopName].join(""))
+  return f()
+}
+module.exports = generateCWiseOp
+},{"uniq":18}],17:[function(require,module,exports){
+"use strict"
+
+var compile = require("./compile.js")
+
+function createThunk(proc) {
+  var code = ["'use strict'", "var CACHED={}"]
+  var vars = []
+  var thunkName = proc.funcName + "_cwise_thunk"
+  
+  //Build thunk
+  code.push(["return function ", thunkName, "(", proc.shimArgs.join(","), "){"].join(""))
+  var typesig = []
+  var string_typesig = []
+  var proc_args = [["array",proc.arrayArgs[0],".shape"].join("")]
+  for(var i=0; i<proc.arrayArgs.length; ++i) {
+    var j = proc.arrayArgs[i]
+    vars.push(["t", j, "=array", j, ".dtype,",
+               "r", j, "=array", j, ".order"].join(""))
+    typesig.push("t" + j)
+    typesig.push("r" + j)
+    string_typesig.push("t"+j)
+    string_typesig.push("r"+j+".join()")
+    proc_args.push("array" + j + ".data")
+    proc_args.push("array" + j + ".stride")
+    proc_args.push("array" + j + ".offset|0")
+  }
+  for(var i=0; i<proc.scalarArgs.length; ++i) {
+    proc_args.push("scalar" + proc.scalarArgs[i])
+  }
+  vars.push(["type=[", string_typesig.join(","), "].join()"].join(""))
+  vars.push("proc=CACHED[type]")
+  code.push("var " + vars.join(","))
+  
+  code.push(["if(!proc){",
+             "CACHED[type]=proc=compile([", typesig.join(","), "])}",
+             "return proc(", proc_args.join(","), ")}"].join(""))
+
+  if(proc.debug) {
+    console.log("Generated thunk:", code.join("\n"))
+  }
+  
+  //Compile thunk
+  var thunk = new Function("compile", code.join("\n"))
+  return thunk(compile.bind(undefined, proc))
+}
+
+module.exports = createThunk
+
+},{"./compile.js":16}],18:[function(require,module,exports){
+"use strict"
+
+function unique_pred(list, compare) {
+  var ptr = 1
+    , len = list.length
+    , a=list[0], b=list[0]
+  for(var i=1; i<len; ++i) {
+    b = a
+    a = list[i]
+    if(compare(a, b)) {
+      if(i === ptr) {
+        ptr++
+        continue
+      }
+      list[ptr++] = a
+    }
+  }
+  list.length = ptr
+  return list
+}
+
+function unique_eq(list) {
+  var ptr = 1
+    , len = list.length
+    , a=list[0], b = list[0]
+  for(var i=1; i<len; ++i, b=a) {
+    b = a
+    a = list[i]
+    if(a !== b) {
+      if(i === ptr) {
+        ptr++
+        continue
+      }
+      list[ptr++] = a
+    }
+  }
+  list.length = ptr
+  return list
+}
+
+function unique(list, compare, sorted) {
+  if(list.length === 0) {
+    return list
+  }
+  if(compare) {
+    if(!sorted) {
+      list.sort(compare)
+    }
+    return unique_pred(list, compare)
+  }
+  if(!sorted) {
+    list.sort()
+  }
+  return unique_eq(list)
+}
+
+module.exports = unique
+
+},{}],19:[function(require,module,exports){
+"use strict"
+
+var ndarray = require("ndarray")
+var do_convert = require("./doConvert.js")
+
+module.exports = function convert(arr, result) {
+  var shape = [], c = arr, sz = 1
+  while(c instanceof Array) {
+    shape.push(c.length)
+    sz *= c.length
+    c = c[0]
+  }
+  if(shape.length === 0) {
+    return ndarray()
+  }
+  if(!result) {
+    result = ndarray(new Float64Array(sz), shape)
+  }
+  do_convert(result, arr)
+  return result
+}
+
+},{"./doConvert.js":20,"ndarray":30}],20:[function(require,module,exports){
+module.exports=require('cwise-compiler')({"args":["array","scalar","index"],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{\nvar _inline_1_v=_inline_1_arg1_,_inline_1_i\nfor(_inline_1_i=0;_inline_1_i<_inline_1_arg2_.length-1;++_inline_1_i) {\n_inline_1_v=_inline_1_v[_inline_1_arg2_[_inline_1_i]]\n}\n_inline_1_arg0_=_inline_1_v[_inline_1_arg2_[_inline_1_arg2_.length-1]]\n}","args":[{"name":"_inline_1_arg0_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_1_arg1_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_1_arg2_","lvalue":false,"rvalue":true,"count":4}],"thisVars":[],"localVars":["_inline_1_i","_inline_1_v"]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"funcName":"convert","blockSize":64})
+
+},{"cwise-compiler":21}],21:[function(require,module,exports){
+"use strict"
+
+var createThunk = require("./lib/thunk.js")
+
+function Procedure() {
+  this.argTypes = []
+  this.shimArgs = []
+  this.arrayArgs = []
+  this.scalarArgs = []
+  this.offsetArgs = []
+  this.offsetArgIndex = []
+  this.indexArgs = []
+  this.shapeArgs = []
+  this.funcName = ""
+  this.pre = null
+  this.body = null
+  this.post = null
+  this.debug = false
+}
+
+function compileCwise(user_args) {
+  //Create procedure
+  var proc = new Procedure()
+  
+  //Parse blocks
+  proc.pre    = user_args.pre
+  proc.body   = user_args.body
+  proc.post   = user_args.post
+
+  //Parse arguments
+  var proc_args = user_args.args.slice(0)
+  proc.argTypes = proc_args.slice(0)
+  for(var i=0; i<proc_args.length; ++i) {
+    var arg_type = proc_args[i]
+    if(arg_type === "array") {
+      proc.arrayArgs.push(i)
+      proc.shimArgs.push("array" + i)
+      if(i < proc.pre.args.length && proc.pre.args[i].count>0) {
+        throw new Error("cwise: pre() block may not reference array args")
+      }
+      if(i < proc.post.args.length && proc.post.args[i].count>0) {
+        throw new Error("cwise: post() block may not reference array args")
+      }
+    } else if(arg_type === "scalar") {
+      proc.scalarArgs.push(i)
+      proc.shimArgs.push("scalar" + i)
+    } else if(arg_type === "index") {
+      proc.indexArgs.push(i)
+      if(i < proc.pre.args.length && proc.pre.args[i].count > 0) {
+        throw new Error("cwise: pre() block may not reference array index")
+      }
+      if(i < proc.body.args.length && proc.body.args[i].lvalue) {
+        throw new Error("cwise: body() block may not write to array index")
+      }
+      if(i < proc.post.args.length && proc.post.args[i].count > 0) {
+        throw new Error("cwise: post() block may not reference array index")
+      }
+    } else if(arg_type === "shape") {
+      proc.shapeArgs.push(i)
+      if(i < proc.pre.args.length && proc.pre.args[i].lvalue) {
+        throw new Error("cwise: pre() block may not write to array shape")
+      }
+      if(i < proc.body.args.length && proc.body.args[i].lvalue) {
+        throw new Error("cwise: body() block may not write to array shape")
+      }
+      if(i < proc.post.args.length && proc.post.args[i].lvalue) {
+        throw new Error("cwise: post() block may not write to array shape")
+      }
+    } else if(typeof arg_type === "object" && arg_type.offset) {
+      proc.argTypes[i] = "offset"
+      proc.offsetArgs.push({ array: arg_type.array, offset:arg_type.offset })
+      proc.offsetArgIndex.push(i)
+    } else {
+      throw new Error("cwise: Unknown argument type " + proc_args[i])
+    }
+  }
+  
+  //Make sure at least one array argument was specified
+  if(proc.arrayArgs.length <= 0) {
+    throw new Error("cwise: No array arguments specified")
+  }
+  
+  //Make sure arguments are correct
+  if(proc.pre.args.length > proc_args.length) {
+    throw new Error("cwise: Too many arguments in pre() block")
+  }
+  if(proc.body.args.length > proc_args.length) {
+    throw new Error("cwise: Too many arguments in body() block")
+  }
+  if(proc.post.args.length > proc_args.length) {
+    throw new Error("cwise: Too many arguments in post() block")
+  }
+
+  //Check debug flag
+  proc.debug = !!user_args.printCode || !!user_args.debug
+  
+  //Retrieve name
+  proc.funcName = user_args.funcName || "cwise"
+  
+  //Read in block size
+  proc.blockSize = user_args.blockSize || 64
+
+  return createThunk(proc)
+}
+
+module.exports = compileCwise
+
+},{"./lib/thunk.js":23}],22:[function(require,module,exports){
+"use strict"
+
+var uniq = require("uniq")
+
+function innerFill(order, proc, body) {
+  var dimension = order.length
+    , nargs = proc.arrayArgs.length
+    , has_index = proc.indexArgs.length>0
+    , code = []
+    , vars = []
+    , idx=0, pidx=0, i, j
+  for(i=0; i<dimension; ++i) {
+    vars.push(["i",i,"=0"].join(""))
+  }
+  //Compute scan deltas
+  for(j=0; j<nargs; ++j) {
+    for(i=0; i<dimension; ++i) {
+      pidx = idx
+      idx = order[i]
+      if(i === 0) {
+        vars.push(["d",j,"s",i,"=t",j,"[",idx,"]"].join(""))
+      } else {
+        vars.push(["d",j,"s",i,"=(t",j,"[",idx,"]-s",pidx,"*t",j,"[",pidx,"])"].join(""))
+      }
+    }
+  }
+  code.push("var " + vars.join(","))
+  //Scan loop
+  for(i=dimension-1; i>=0; --i) {
+    idx = order[i]
+    code.push(["for(i",i,"=0;i",i,"<s",idx,";++i",i,"){"].join(""))
+  }
+  //Push body of inner loop
+  code.push(body)
+  //Advance scan pointers
+  for(i=0; i<dimension; ++i) {
+    pidx = idx
+    idx = order[i]
+    for(j=0; j<nargs; ++j) {
+      code.push(["p",j,"+=d",j,"s",i].join(""))
+    }
+    if(has_index) {
+      if(i > 0) {
+        code.push(["index[",pidx,"]-=s",pidx].join(""))
+      }
+      code.push(["++index[",idx,"]"].join(""))
+    }
+    code.push("}")
+  }
+  return code.join("\n")
+}
+
+function outerFill(matched, order, proc, body) {
+  var dimension = order.length
+    , nargs = proc.arrayArgs.length
+    , blockSize = proc.blockSize
+    , has_index = proc.indexArgs.length > 0
+    , code = []
+  for(var i=0; i<nargs; ++i) {
+    code.push(["var offset",i,"=p",i].join(""))
+  }
+  //Generate matched loops
+  for(var i=matched; i<dimension; ++i) {
+    code.push(["for(var j"+i+"=SS[", order[i], "]|0;j", i, ">0;){"].join(""))
+    code.push(["if(j",i,"<",blockSize,"){"].join(""))
+    code.push(["s",order[i],"=j",i].join(""))
+    code.push(["j",i,"=0"].join(""))
+    code.push(["}else{s",order[i],"=",blockSize].join(""))
+    code.push(["j",i,"-=",blockSize,"}"].join(""))
+    if(has_index) {
+      code.push(["index[",order[i],"]=j",i].join(""))
+    }
+  }
+  for(var i=0; i<nargs; ++i) {
+    var indexStr = ["offset"+i]
+    for(var j=matched; j<dimension; ++j) {
+      indexStr.push(["j",j,"*t",i,"[",order[j],"]"].join(""))
+    }
+    code.push(["p",i,"=(",indexStr.join("+"),")"].join(""))
+  }
+  code.push(innerFill(order, proc, body))
+  for(var i=matched; i<dimension; ++i) {
+    code.push("}")
+  }
+  return code.join("\n")
+}
+
+//Count the number of compatible inner orders
+function countMatches(orders) {
+  var matched = 0, dimension = orders[0].length
+  while(matched < dimension) {
+    for(var j=1; j<orders.length; ++j) {
+      if(orders[j][matched] !== orders[0][matched]) {
+        return matched
+      }
+    }
+    ++matched
+  }
+  return matched
+}
+
+//Processes a block according to the given data types
+function processBlock(block, proc, dtypes) {
+  var code = block.body
+  var pre = []
+  var post = []
+  for(var i=0; i<block.args.length; ++i) {
+    var carg = block.args[i]
+    if(carg.count <= 0) {
+      continue
+    }
+    var re = new RegExp(carg.name, "g")
+    var ptrStr = ""
+    var arrNum = proc.arrayArgs.indexOf(i)
+    switch(proc.argTypes[i]) {
+      case "offset":
+        var offArgIndex = proc.offsetArgIndex.indexOf(i)
+        var offArg = proc.offsetArgs[offArgIndex]
+        arrNum = offArg.array
+        ptrStr = "+q" + offArgIndex
+      case "array":
+        ptrStr = "p" + arrNum + ptrStr
+        var localStr = "l" + i
+        var arrStr = "a" + arrNum
+        if(carg.count === 1) {
+          if(dtypes[arrNum] === "generic") {
+            if(carg.lvalue) {
+              pre.push(["var ", localStr, "=", arrStr, ".get(", ptrStr, ")"].join(""))
+              code = code.replace(re, localStr)
+              post.push([arrStr, ".set(", ptrStr, ",", localStr,")"].join(""))
+            } else {
+              code = code.replace(re, [arrStr, ".get(", ptrStr, ")"].join(""))
+            }
+          } else {
+            code = code.replace(re, [arrStr, "[", ptrStr, "]"].join(""))
+          }
+        } else if(dtypes[arrNum] === "generic") {
+          pre.push(["var ", localStr, "=", arrStr, ".get(", ptrStr, ")"].join(""))
+          code = code.replace(re, localStr)
+          if(carg.lvalue) {
+            post.push([arrStr, ".set(", ptrStr, ",", localStr,")"].join(""))
+          }
+        } else {
+          pre.push(["var ", localStr, "=", arrStr, "[", ptrStr, "]"].join(""))
+          code = code.replace(re, localStr)
+          if(carg.lvalue) {
+            post.push([arrStr, "[", ptrStr, "]=", localStr].join(""))
+          }
+        }
+      break
+      case "scalar":
+        code = code.replace(re, "Y" + proc.scalarArgs.indexOf(i))
+      break
+      case "index":
+        code = code.replace(re, "index")
+      break
+      case "shape":
+        code = code.replace(re, "shape")
+      break
+    }
+  }
+  return [pre.join("\n"), code, post.join("\n")].join("\n").trim()
+}
+
+function typeSummary(dtypes) {
+  var summary = new Array(dtypes.length)
+  var allEqual = true
+  for(var i=0; i<dtypes.length; ++i) {
+    var t = dtypes[i]
+    var digits = t.match(/\d+/)
+    if(!digits) {
+      digits = ""
+    } else {
+      digits = digits[0]
+    }
+    if(t.charAt(0) === 0) {
+      summary[i] = "u" + t.charAt(1) + digits
+    } else {
+      summary[i] = t.charAt(0) + digits
+    }
+    if(i > 0) {
+      allEqual = allEqual && summary[i] === summary[i-1]
+    }
+  }
+  if(allEqual) {
+    return summary[0]
+  }
+  return summary.join("")
+}
+
+//Generates a cwise operator
+function generateCWiseOp(proc, typesig) {
+
+  //Compute dimension
+  var dimension = typesig[1].length|0
+  var orders = new Array(proc.arrayArgs.length)
+  var dtypes = new Array(proc.arrayArgs.length)
+
+  //First create arguments for procedure
+  var arglist = ["SS"]
+  var code = ["'use strict'"]
+  var vars = []
+  
+  for(var j=0; j<dimension; ++j) {
+    vars.push(["s", j, "=SS[", j, "]"].join(""))
+  }
+  for(var i=0; i<proc.arrayArgs.length; ++i) {
+    arglist.push("a"+i)
+    arglist.push("t"+i)
+    arglist.push("p"+i)
+    dtypes[i] = typesig[2*i]
+    orders[i] = typesig[2*i+1]
+  }
+  for(var i=0; i<proc.scalarArgs.length; ++i) {
+    arglist.push("Y" + i)
+  }
+  if(proc.shapeArgs.length > 0) {
+    vars.push("shape=SS.slice(0)")
+  }
+  if(proc.indexArgs.length > 0) {
+    var zeros = new Array(dimension)
+    for(var i=0; i<dimension; ++i) {
+      zeros[i] = "0"
+    }
+    vars.push(["index=[", zeros.join(","), "]"].join(""))
+  }
+  for(var i=0; i<proc.offsetArgs.length; ++i) {
+    var off_arg = proc.offsetArgs[i]
+    var init_string = []
+    for(var j=0; j<off_arg.offset.length; ++j) {
+      if(off_arg.offset[j] === 0) {
+        continue
+      } else if(off_arg.offset[j] === 1) {
+        init_string.push(["t", off_arg.array, "[", j, "]"].join(""))      
+      } else {
+        init_string.push([off_arg.offset[j], "*t", off_arg.array, "[", j, "]"].join(""))
+      }
+    }
+    if(init_string.length === 0) {
+      vars.push("q" + i + "=0")
+    } else {
+      vars.push(["q", i, "=(", init_string.join("+"),")|0"].join(""))
+    }
+  }
+
+  //Prepare this variables
+  var thisVars = uniq([].concat(proc.pre.thisVars)
+                      .concat(proc.body.thisVars)
+                      .concat(proc.post.thisVars))
+  vars = vars.concat(thisVars)
+  code.push("var " + vars.join(","))
+  for(var i=0; i<proc.arrayArgs.length; ++i) {
+    code.push("p"+i+"|=0")
+  }
+  
+  //Inline prelude
+  if(proc.pre.body.length > 3) {
+    code.push(processBlock(proc.pre, proc, dtypes))
+  }
+
+  //Process body
+  var body = processBlock(proc.body, proc, dtypes)
+  var matched = countMatches(orders)
+  if(matched < dimension) {
+    code.push(outerFill(matched, orders[0], proc, body))
+  } else {
+    code.push(innerFill(orders[0], proc, body))
+  }
+
+  //Inline epilog
+  if(proc.post.body.length > 3) {
+    code.push(processBlock(proc.post, proc, dtypes))
+  }
+  
+  if(proc.debug) {
+    console.log("Generated cwise routine for ", typesig, ":\n\n", code.join("\n"))
+  }
+  
+  var loopName = [(proc.funcName||"unnamed"), "_cwise_loop_", orders[0].join("s"),"m",matched,typeSummary(dtypes)].join("")
+  var f = new Function(["function ",loopName,"(", arglist.join(","),"){", code.join("\n"),"} return ", loopName].join(""))
+  return f()
+}
+module.exports = generateCWiseOp
+},{"uniq":24}],23:[function(require,module,exports){
+arguments[4][17][0].apply(exports,arguments)
+},{"./compile.js":22,"dup":17}],24:[function(require,module,exports){
+"use strict"
+
+function unique_pred(list, compare) {
+  var ptr = 1
+    , len = list.length
+    , a=list[0], b=list[0]
+  for(var i=1; i<len; ++i) {
+    b = a
+    a = list[i]
+    if(compare(a, b)) {
+      if(i === ptr) {
+        ptr++
+        continue
+      }
+      list[ptr++] = a
+    }
+  }
+  list.length = ptr
+  return list
+}
+
+function unique_eq(list) {
+  var ptr = 1
+    , len = list.length
+    , a=list[0], b = list[0]
+  for(var i=1; i<len; ++i, b=a) {
+    b = a
+    a = list[i]
+    if(a !== b) {
+      if(i === ptr) {
+        ptr++
+        continue
+      }
+      list[ptr++] = a
+    }
+  }
+  list.length = ptr
+  return list
+}
+
+function unique(list, compare, sorted) {
+  if(list.length === 0) {
+    return []
+  }
+  if(compare) {
+    if(!sorted) {
+      list.sort(compare)
+    }
+    return unique_pred(list, compare)
+  }
+  if(!sorted) {
+    list.sort()
+  }
+  return unique_eq(list)
+}
+
+module.exports = unique
+},{}],25:[function(require,module,exports){
+arguments[4][11][0].apply(exports,arguments)
+},{"dup":11}],26:[function(require,module,exports){
+"use strict"
+
+function dupe_array(count, value, i) {
+  var c = count[i]|0
+  if(c <= 0) {
+    return []
+  }
+  var result = new Array(c), j
+  if(i === count.length-1) {
+    for(j=0; j<c; ++j) {
+      result[j] = value
+    }
+  } else {
+    for(j=0; j<c; ++j) {
+      result[j] = dupe_array(count, value, i+1)
+    }
+  }
+  return result
+}
+
+function dupe_number(count, value) {
+  var result, i
+  result = new Array(count)
+  for(i=0; i<count; ++i) {
+    result[i] = value
+  }
+  return result
+}
+
+function dupe(count, value) {
+  if(typeof value === "undefined") {
+    value = 0
+  }
+  switch(typeof count) {
+    case "number":
+      if(count > 0) {
+        return dupe_number(count|0, value)
+      }
+    break
+    case "object":
+      if(typeof (count.length) === "number") {
+        return dupe_array(count, value, 0)
+      }
+    break
+  }
+  return []
+}
+
+module.exports = dupe
+},{}],27:[function(require,module,exports){
+(function (global,Buffer){
+'use strict'
+
+var bits = require('bit-twiddle')
+var dup = require('dup')
+
+//Legacy pool support
+if(!global.__TYPEDARRAY_POOL) {
+  global.__TYPEDARRAY_POOL = {
+      UINT8   : dup([32, 0])
+    , UINT16  : dup([32, 0])
+    , UINT32  : dup([32, 0])
+    , INT8    : dup([32, 0])
+    , INT16   : dup([32, 0])
+    , INT32   : dup([32, 0])
+    , FLOAT   : dup([32, 0])
+    , DOUBLE  : dup([32, 0])
+    , DATA    : dup([32, 0])
+    , UINT8C  : dup([32, 0])
+    , BUFFER  : dup([32, 0])
+  }
+}
+
+var hasUint8C = (typeof Uint8ClampedArray) !== 'undefined'
+var POOL = global.__TYPEDARRAY_POOL
+
+//Upgrade pool
+if(!POOL.UINT8C) {
+  POOL.UINT8C = dup([32, 0])
+}
+if(!POOL.BUFFER) {
+  POOL.BUFFER = dup([32, 0])
+}
+
+//New technique: Only allocate from ArrayBufferView and Buffer
+var DATA    = POOL.DATA
+  , BUFFER  = POOL.BUFFER
+
+exports.free = function free(array) {
+  if(Buffer.isBuffer(array)) {
+    BUFFER[bits.log2(array.length)].push(array)
+  } else {
+    if(Object.prototype.toString.call(array) !== '[object ArrayBuffer]') {
+      array = array.buffer
+    }
+    if(!array) {
+      return
+    }
+    var n = array.length || array.byteLength
+    var log_n = bits.log2(n)|0
+    DATA[log_n].push(array)
+  }
+}
+
+function freeArrayBuffer(buffer) {
+  if(!buffer) {
+    return
+  }
+  var n = buffer.length || buffer.byteLength
+  var log_n = bits.log2(n)
+  DATA[log_n].push(buffer)
+}
+
+function freeTypedArray(array) {
+  freeArrayBuffer(array.buffer)
+}
+
+exports.freeUint8 =
+exports.freeUint16 =
+exports.freeUint32 =
+exports.freeInt8 =
+exports.freeInt16 =
+exports.freeInt32 =
+exports.freeFloat32 = 
+exports.freeFloat =
+exports.freeFloat64 = 
+exports.freeDouble = 
+exports.freeUint8Clamped = 
+exports.freeDataView = freeTypedArray
+
+exports.freeArrayBuffer = freeArrayBuffer
+
+exports.freeBuffer = function freeBuffer(array) {
+  BUFFER[bits.log2(array.length)].push(array)
+}
+
+exports.malloc = function malloc(n, dtype) {
+  if(dtype === undefined || dtype === 'arraybuffer') {
+    return mallocArrayBuffer(n)
+  } else {
+    switch(dtype) {
+      case 'uint8':
+        return mallocUint8(n)
+      case 'uint16':
+        return mallocUint16(n)
+      case 'uint32':
+        return mallocUint32(n)
+      case 'int8':
+        return mallocInt8(n)
+      case 'int16':
+        return mallocInt16(n)
+      case 'int32':
+        return mallocInt32(n)
+      case 'float':
+      case 'float32':
+        return mallocFloat(n)
+      case 'double':
+      case 'float64':
+        return mallocDouble(n)
+      case 'uint8_clamped':
+        return mallocUint8Clamped(n)
+      case 'buffer':
+        return mallocBuffer(n)
+      case 'data':
+      case 'dataview':
+        return mallocDataView(n)
+
+      default:
+        return null
+    }
+  }
+  return null
+}
+
+function mallocArrayBuffer(n) {
+  var n = bits.nextPow2(n)
+  var log_n = bits.log2(n)
+  var d = DATA[log_n]
+  if(d.length > 0) {
+    return d.pop()
+  }
+  return new ArrayBuffer(n)
+}
+exports.mallocArrayBuffer = mallocArrayBuffer
+
+function mallocUint8(n) {
+  return new Uint8Array(mallocArrayBuffer(n), 0, n)
+}
+exports.mallocUint8 = mallocUint8
+
+function mallocUint16(n) {
+  return new Uint16Array(mallocArrayBuffer(2*n), 0, n)
+}
+exports.mallocUint16 = mallocUint16
+
+function mallocUint32(n) {
+  return new Uint32Array(mallocArrayBuffer(4*n), 0, n)
+}
+exports.mallocUint32 = mallocUint32
+
+function mallocInt8(n) {
+  return new Int8Array(mallocArrayBuffer(n), 0, n)
+}
+exports.mallocInt8 = mallocInt8
+
+function mallocInt16(n) {
+  return new Int16Array(mallocArrayBuffer(2*n), 0, n)
+}
+exports.mallocInt16 = mallocInt16
+
+function mallocInt32(n) {
+  return new Int32Array(mallocArrayBuffer(4*n), 0, n)
+}
+exports.mallocInt32 = mallocInt32
+
+function mallocFloat(n) {
+  return new Float32Array(mallocArrayBuffer(4*n), 0, n)
+}
+exports.mallocFloat32 = exports.mallocFloat = mallocFloat
+
+function mallocDouble(n) {
+  return new Float64Array(mallocArrayBuffer(8*n), 0, n)
+}
+exports.mallocFloat64 = exports.mallocDouble = mallocDouble
+
+function mallocUint8Clamped(n) {
+  if(hasUint8C) {
+    return new Uint8ClampedArray(mallocArrayBuffer(n), 0, n)
+  } else {
+    return mallocUint8(n)
+  }
+}
+exports.mallocUint8Clamped = mallocUint8Clamped
+
+function mallocDataView(n) {
+  return new DataView(mallocArrayBuffer(n), 0, n)
+}
+exports.mallocDataView = mallocDataView
+
+function mallocBuffer(n) {
+  n = bits.nextPow2(n)
+  var log_n = bits.log2(n)
+  var cache = BUFFER[log_n]
+  if(cache.length > 0) {
+    return cache.pop()
+  }
+  return new Buffer(n)
+}
+exports.mallocBuffer = mallocBuffer
+
+exports.clearCache = function clearCache() {
+  for(var i=0; i<32; ++i) {
+    POOL.UINT8[i].length = 0
+    POOL.UINT16[i].length = 0
+    POOL.UINT32[i].length = 0
+    POOL.INT8[i].length = 0
+    POOL.INT16[i].length = 0
+    POOL.INT32[i].length = 0
+    POOL.FLOAT[i].length = 0
+    POOL.DOUBLE[i].length = 0
+    POOL.UINT8C[i].length = 0
+    DATA[i].length = 0
+    BUFFER[i].length = 0
+  }
+}
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
+},{"bit-twiddle":25,"buffer":1,"dup":26}],28:[function(require,module,exports){
+"use strict"
+
+var ndarray = require("ndarray")
+var ops = require("ndarray-ops")
+var pool = require("typedarray-pool")
+
+function clone(array) {
+  var dtype = array.dtype
+  if(dtype === "generic" || dtype === "array") {
+    dtype = "double"
+  }
+  var data = pool.malloc(array.size, dtype)
+  var result = ndarray(data, array.shape)
+  ops.assign(result, array)
+  return result
+}
+exports.clone = clone
+
+function malloc(shape, dtype) {
+  if(!dtype) {
+    dtype = "double"
+  }
+  var sz = 1
+  var stride = new Array(shape.length)
+  for(var i=shape.length-1; i>=0; --i) {
+    stride[i] = sz
+    sz *= shape[i]
+  }
+  return ndarray(pool.malloc(sz, dtype), shape, stride, 0)
+}
+exports.malloc = malloc
+
+function free(array) {
+  if(array.dtype === "generic" || array.dtype === "array") {
+    return
+  }
+  pool.free(array.data)
+}
+exports.free = free
+
+function zeros(shape, dtype) {
+  if(!dtype) {
+    dtype = "double"
+  }
+
+  var sz = 1
+  var stride = new Array(shape.length)
+  for(var i=shape.length-1; i>=0; --i) {
+    stride[i] = sz
+    sz *= shape[i]
+  }
+  var buf = pool.malloc(sz, dtype)
+  for(var i=0; i<sz; ++i) {
+    buf[i] = 0
+  }
+  return ndarray(buf, shape, stride, 0)
+}
+exports.zeros = zeros
+},{"ndarray":30,"ndarray-ops":14,"typedarray-pool":27}],29:[function(require,module,exports){
+"use strict"
+
+module.exports = ndSelect
+module.exports.compile = lookupCache
+
+//Macros
+var ARRAY = "a"
+var RANK = "K"
+var CMP = "C"
+var DATA = "d"
+var OFFSET = "o"
+var RND = "R"
+var TMP = "T"
+var LO = "L"
+var HI = "H"
+var PIVOT = "X"
+function SHAPE(i) {
+  return "s" + i
+}
+function STRIDE(i) {
+  return "t" + i
+}
+function STEP(i) {
+  return "u" + i
+}
+function STEP_CMP(i) {
+  return "v" + i
+}
+function INDEX(i) {
+  return "i" + i
+}
+function PICK(i) {
+  return "p" + i
+}
+function PTR(i) {
+  return "x" + i
+}
+
+//Create new order where index 0 is slowest index
+function permuteOrder(order) {
+  var norder = order.slice()
+  norder.splice(order.indexOf(0), 1)
+  norder.unshift(0)
+  return norder
+}
+
+//Generate quick select procedure
+function compileQuickSelect(order, useCompare, dtype) {
+  order = permuteOrder(order)
+
+  var dimension = order.length
+  var useGetter = (dtype === "generic")
+  var funcName = "ndSelect" + dtype + order.join("_") + "_" + (useCompare ? "cmp" : "lex")
+
+  var code = []
+
+  //Get arguments for code
+  var args = [ARRAY, RANK]
+  if(useCompare) {
+    args.push(CMP)
+  }
+
+  //Unpack ndarray variables
+  var vars = [
+    DATA + "=" + ARRAY + ".data",
+    OFFSET + "=" + ARRAY + ".offset|0",
+    RND + "=Math.random",
+    TMP]
+  for(var i=0; i<2; ++i) {
+    vars.push(PTR(i) + "=0")
+  }
+  for(var i=0; i<dimension; ++i) {
+    vars.push(
+      SHAPE(i) + "=" + ARRAY + ".shape[" + i + "]|0",
+      STRIDE(i) + "=" + ARRAY + ".stride[" + i + "]|0",
+      INDEX(i) + "=0")
+  }
+  for(var i=1; i<dimension; ++i) {
+    if(i < dimension-1) {
+      vars.push(STEP_CMP(i) + "=(" + STRIDE(i) + "-" + SHAPE(i+1) + "*" + STRIDE(i+1) + ")|0",
+                STEP(order[i]) + "=(" + STRIDE(order[i]) + "-" + SHAPE(order[i+1]) + "*" + STRIDE(order[i+1]) + ")|0")
+    } else {
+      vars.push(STEP_CMP(i) + "=" + STRIDE(i),
+                STEP(order[i]) + "=" + STRIDE(order[i]))
+    }
+  }
+  if(useCompare) {
+    for(var i=0; i<2; ++i) {
+      vars.push(PICK(i) + "=" + ARRAY + ".pick(0)")
+    }
+  }
+  vars.push(
+    PIVOT + "=0",
+    LO + "=0",
+    HI + "=" + SHAPE(order[0]) + "-1")
+
+  function compare(out, i0, i1) {
+    if(useCompare) {
+      code.push(
+        PICK(0), ".offset=", OFFSET, "+", STRIDE(order[0]), "*(", i0, ");",
+        PICK(1), ".offset=", OFFSET, "+", STRIDE(order[0]), "*(", i1, ");",
+        out, "=", CMP, "(", PICK(0), ",", PICK(1), ");")
+    } else {
+      code.push(
+        PTR(0), "=", OFFSET, "+", STRIDE(0), "*(", i0, ");",
+        PTR(1), "=", OFFSET, "+", STRIDE(0), "*(", i1, ");")
+      if(dimension > 1) {
+        code.push("_cmp:")
+      }
+      for(var i=dimension-1; i>0; --i) {
+        code.push("for(", INDEX(i), "=0;", 
+          INDEX(i), "<", SHAPE(i), ";",
+          INDEX(i), "++){")
+      }
+      if(useGetter) {
+        code.push(out, "=", DATA, ".get(", PTR(0), ")-", 
+                            DATA, ".get(", PTR(1), ");")
+      } else {
+        code.push(out, "=", DATA, "[", PTR(0), "]-", 
+                            DATA, "[", PTR(1), "];")
+      }
+      if(dimension > 1) {
+        code.push("if(", out, ")break _cmp;")
+      }
+      for(var i=1; i<dimension; ++i) {
+        code.push(
+          PTR(0), "+=", STEP_CMP(i), ";",
+          PTR(1), "+=", STEP_CMP(i),
+          "}")
+      }
+    }
+  }
+
+  function swap(i0, i1) {
+    code.push(
+      PTR(0), "=", OFFSET, "+", STRIDE(order[0]), "*(", i0, ");",
+      PTR(1), "=", OFFSET, "+", STRIDE(order[0]), "*(", i1, ");")
+    for(var i=dimension-1; i>0; --i) {
+      code.push("for(", INDEX(order[i]), "=0;", 
+        INDEX(order[i]), "<", SHAPE(order[i]), ";",
+        INDEX(order[i]), "++){")
+    }
+    if(useGetter) {
+      code.push(TMP, "=", DATA, ".get(", PTR(0), ");", 
+                DATA, ".set(", PTR(0), ",", DATA, ".get(", PTR(1), "));",
+                DATA, ".set(", PTR(1), ",", TMP, ");")
+    } else {
+      code.push(TMP, "=", DATA, "[", PTR(0), "];", 
+                DATA, "[", PTR(0), "]=", DATA, "[", PTR(1), "];",
+                DATA, "[", PTR(1), "]=", TMP, ";")
+    }
+    for(var i=1; i<dimension; ++i) {
+      code.push(
+        PTR(0), "+=", STEP(order[i]), ";",
+        PTR(1), "+=", STEP(order[i]),
+        "}")
+    }
+  }
+
+  code.push(
+    "while(", LO, "<", HI, "){",
+      PIVOT, "=(", RND, "()*(", HI, "-", LO, "+1)+", LO, ")|0;")
+
+  //Partition array by pivot
+  swap(PIVOT, HI)
+
+  code.push(
+    PIVOT, "=", LO, ";",
+    "for(", INDEX(0), "=", LO, ";",
+      INDEX(0), "<", HI, ";",
+      INDEX(0), "++){")
+  compare(TMP, INDEX(0), HI)
+  code.push("if(", TMP, "<0){")
+    swap(PIVOT, INDEX(0))
+    code.push(PIVOT, "++;")
+  code.push("}}")
+  swap(PIVOT, HI)
+
+  //Check pivot bounds
+  code.push(
+    "if(", PIVOT, "===", RANK, "){",
+      LO, "=", PIVOT, ";",
+      "break;",
+    "}else if(", RANK, "<", PIVOT, "){",
+      HI, "=", PIVOT, "-1;",
+    "}else{",
+      LO, "=", PIVOT, "+1;",
+    "}",
+  "}")
+
+  if(useCompare) {
+    code.push(PICK(0), ".offset=", OFFSET, "+", LO, "*", STRIDE(0), ";",
+      "return ", PICK(0), ";")
+  } else {
+    code.push("return ", ARRAY, ".pick(", LO, ");")
+  }
+
+  //Compile and link js together
+  var procCode = [
+    "'use strict';function ", funcName, "(", args, "){",
+      "var ", vars.join(), ";",
+      code.join(""),
+    "};return ", funcName
+  ].join("")
+
+  var proc = new Function(procCode)
+  return proc()
+}
+
+var CACHE = {}
+
+function lookupCache(order, useCompare, dtype) {
+  var typesig = order.join() + useCompare + dtype
+  var proc = CACHE[typesig]
+  if(proc) {
+    return proc
+  }
+  return CACHE[typesig] = compileQuickSelect(order, useCompare, dtype)
+}
+
+function ndSelect(array, k, compare) {
+  k |= 0
+  if((array.dimension === 0) || 
+    (array.shape[0] <= k) ||
+    (k < 0)) {
+    return null
+  }
+  var useCompare = !!compare
+  var proc = lookupCache(array.order, useCompare, array.dtype)
+  if(useCompare) {
+    return proc(array, k, compare)
+  } else {
+    return proc(array, k)
+  }
+}
+},{}],30:[function(require,module,exports){
+(function (Buffer){
+var iota = require("iota-array")
+
+var arrayMethods = [
+  "concat",
+  "join",
+  "slice",
+  "toString",
+  "indexOf",
+  "lastIndexOf",
+  "forEach",
+  "every",
+  "some",
+  "filter",
+  "map",
+  "reduce",
+  "reduceRight"
+]
+
+var hasTypedArrays  = ((typeof Float64Array) !== "undefined")
+var hasBuffer       = ((typeof Buffer) !== "undefined")
+
+function compare1st(a, b) {
+  return a[0] - b[0]
+}
+
+function order() {
+  var stride = this.stride
+  var terms = new Array(stride.length)
+  var i
+  for(i=0; i<terms.length; ++i) {
+    terms[i] = [Math.abs(stride[i]), i]
+  }
+  terms.sort(compare1st)
+  var result = new Array(terms.length)
+  for(i=0; i<result.length; ++i) {
+    result[i] = terms[i][1]
+  }
+  return result
+}
+
+function compileConstructor(dtype, dimension) {
+  var className = ["View", dimension, "d", dtype].join("")
+  if(dimension < 0) {
+    className = "View_Nil" + dtype
+  }
+  var useGetters = (dtype === "generic")
+  
+  if(dimension === -1) {
+    //Special case for trivial arrays
+    var code = 
+      "function "+className+"(a){this.data=a;};\
+var proto="+className+".prototype;\
+proto.dtype='"+dtype+"';\
+proto.index=function(){return -1};\
+proto.size=0;\
+proto.dimension=-1;\
+proto.shape=proto.stride=proto.order=[];\
+proto.lo=proto.hi=proto.transpose=proto.step=\
+function(){return new "+className+"(this.data);};\
+proto.get=proto.set=function(){};\
+proto.pick=function(){return null};\
+return function construct_"+className+"(a){return new "+className+"(a);}"
+    var procedure = new Function(code)
+    return procedure()
+  } else if(dimension === 0) {
+    //Special case for 0d arrays
+    var code =
+      "function "+className+"(a,d) {\
+this.data = a;\
+this.offset = d\
+};\
+var proto="+className+".prototype;\
+proto.dtype='"+dtype+"';\
+proto.index=function(){return this.offset};\
+proto.dimension=0;\
+proto.size=1;\
+proto.shape=\
+proto.stride=\
+proto.order=[];\
+proto.lo=\
+proto.hi=\
+proto.transpose=\
+proto.step=function "+className+"_copy() {\
+return new "+className+"(this.data,this.offset)\
+};\
+proto.pick=function "+className+"_pick(){\
+return TrivialArray(this.data);\
+};\
+proto.valueOf=proto.get=function "+className+"_get(){\
+return "+(useGetters ? "this.data.get(this.offset)" : "this.data[this.offset]")+
+"};\
+proto.set=function "+className+"_set(v){\
+return "+(useGetters ? "this.data.set(this.offset,v)" : "this.data[this.offset]=v")+"\
+};\
+return function construct_"+className+"(a,b,c,d){return new "+className+"(a,d)}"
+    var procedure = new Function("TrivialArray", code)
+    return procedure(CACHED_CONSTRUCTORS[dtype][0])
+  }
+
+  var code = ["'use strict'"]
+    
+  //Create constructor for view
+  var indices = iota(dimension)
+  var args = indices.map(function(i) { return "i"+i })
+  var index_str = "this.offset+" + indices.map(function(i) {
+        return "this._stride" + i + "*i" + i
+      }).join("+")
+  code.push("function "+className+"(a,"+
+    indices.map(function(i) {
+      return "b"+i
+    }).join(",") + "," +
+    indices.map(function(i) {
+      return "c"+i
+    }).join(",") + ",d){this.data=a")
+  for(var i=0; i<dimension; ++i) {
+    code.push("this._shape"+i+"=b"+i+"|0")
+  }
+  for(var i=0; i<dimension; ++i) {
+    code.push("this._stride"+i+"=c"+i+"|0")
+  }
+  code.push("this.offset=d|0}",
+    "var proto="+className+".prototype",
+    "proto.dtype='"+dtype+"'",
+    "proto.dimension="+dimension)
+  
+  //view.stride and view.shape
+  var strideClassName = "VStride" + dimension + "d" + dtype
+  var shapeClassName = "VShape" + dimension + "d" + dtype
+  var props = {"stride":strideClassName, "shape":shapeClassName}
+  for(var prop in props) {
+    var arrayName = props[prop]
+    code.push(
+      "function " + arrayName + "(v) {this._v=v} var aproto=" + arrayName + ".prototype",
+      "aproto.length="+dimension)
+    
+    var array_elements = []
+    for(var i=0; i<dimension; ++i) {
+      array_elements.push(["this._v._", prop, i].join(""))
+    }
+    code.push(
+      "aproto.toJSON=function " + arrayName + "_toJSON(){return [" + array_elements.join(",") + "]}",
+      "aproto.valueOf=aproto.toString=function " + arrayName + "_toString(){return [" + array_elements.join(",") + "].join()}")
+    
+    for(var i=0; i<dimension; ++i) {
+      code.push("Object.defineProperty(aproto,"+i+",{get:function(){return this._v._"+prop+i+"},set:function(v){return this._v._"+prop+i+"=v|0},enumerable:true})")
+    }
+    for(var i=0; i<arrayMethods.length; ++i) {
+      if(arrayMethods[i] in Array.prototype) {
+        code.push("aproto."+arrayMethods[i]+"=Array.prototype."+arrayMethods[i])
+      }
+    }
+    code.push(["Object.defineProperty(proto,'",prop,"',{get:function ", arrayName, "_get(){return new ", arrayName, "(this)},set: function ", arrayName, "_set(v){"].join(""))
+    for(var i=0; i<dimension; ++i) {
+      code.push("this._"+prop+i+"=v["+i+"]|0")
+    }
+    code.push("return v}})")
+  }
+  
+  //view.size:
+  code.push("Object.defineProperty(proto,'size',{get:function "+className+"_size(){\
+return "+indices.map(function(i) { return "this._shape"+i }).join("*"),
+"}})")
+
+  //view.order:
+  if(dimension === 1) {
+    code.push("proto.order=[0]")
+  } else {
+    code.push("Object.defineProperty(proto,'order',{get:")
+    if(dimension < 4) {
+      code.push("function "+className+"_order(){")
+      if(dimension === 2) {
+        code.push("return (Math.abs(this._stride0)>Math.abs(this._stride1))?[1,0]:[0,1]}})")
+      } else if(dimension === 3) {
+        code.push(
+"var s0=Math.abs(this._stride0),s1=Math.abs(this._stride1),s2=Math.abs(this._stride2);\
+if(s0>s1){\
+if(s1>s2){\
+return [2,1,0];\
+}else if(s0>s2){\
+return [1,2,0];\
+}else{\
+return [1,0,2];\
+}\
+}else if(s0>s2){\
+return [2,0,1];\
+}else if(s2>s1){\
+return [0,1,2];\
+}else{\
+return [0,2,1];\
+}}})")
+      }
+    } else {
+      code.push("ORDER})")
+    }
+  }
+  
+  //view.set(i0, ..., v):
+  code.push(
+"proto.set=function "+className+"_set("+args.join(",")+",v){")
+  if(useGetters) {
+    code.push("return this.data.set("+index_str+",v)}")
+  } else {
+    code.push("return this.data["+index_str+"]=v}")
+  }
+  
+  //view.get(i0, ...):
+  code.push("proto.get=function "+className+"_get("+args.join(",")+"){")
+  if(useGetters) {
+    code.push("return this.data.get("+index_str+")}")
+  } else {
+    code.push("return this.data["+index_str+"]}")
+  }
+  
+  //view.index:
+  code.push(
+    "proto.index=function "+className+"_index(", args.join(), "){return "+index_str+"}")
+
+  //view.hi():
+  code.push("proto.hi=function "+className+"_hi("+args.join(",")+"){return new "+className+"(this.data,"+
+    indices.map(function(i) {
+      return ["(typeof i",i,"!=='number'||i",i,"<0)?this._shape", i, ":i", i,"|0"].join("")
+    }).join(",")+","+
+    indices.map(function(i) {
+      return "this._stride"+i
+    }).join(",")+",this.offset)}")
+  
+  //view.lo():
+  var a_vars = indices.map(function(i) { return "a"+i+"=this._shape"+i })
+  var c_vars = indices.map(function(i) { return "c"+i+"=this._stride"+i })
+  code.push("proto.lo=function "+className+"_lo("+args.join(",")+"){var b=this.offset,d=0,"+a_vars.join(",")+","+c_vars.join(","))
+  for(var i=0; i<dimension; ++i) {
+    code.push(
+"if(typeof i"+i+"==='number'&&i"+i+">=0){\
+d=i"+i+"|0;\
+b+=c"+i+"*d;\
+a"+i+"-=d}")
+  }
+  code.push("return new "+className+"(this.data,"+
+    indices.map(function(i) {
+      return "a"+i
+    }).join(",")+","+
+    indices.map(function(i) {
+      return "c"+i
+    }).join(",")+",b)}")
+  
+  //view.step():
+  code.push("proto.step=function "+className+"_step("+args.join(",")+"){var "+
+    indices.map(function(i) {
+      return "a"+i+"=this._shape"+i
+    }).join(",")+","+
+    indices.map(function(i) {
+      return "b"+i+"=this._stride"+i
+    }).join(",")+",c=this.offset,d=0,ceil=Math.ceil")
+  for(var i=0; i<dimension; ++i) {
+    code.push(
+"if(typeof i"+i+"==='number'){\
+d=i"+i+"|0;\
+if(d<0){\
+c+=b"+i+"*(a"+i+"-1);\
+a"+i+"=ceil(-a"+i+"/d)\
+}else{\
+a"+i+"=ceil(a"+i+"/d)\
+}\
+b"+i+"*=d\
+}")
+  }
+  code.push("return new "+className+"(this.data,"+
+    indices.map(function(i) {
+      return "a" + i
+    }).join(",")+","+
+    indices.map(function(i) {
+      return "b" + i
+    }).join(",")+",c)}")
+  
+  //view.transpose():
+  var tShape = new Array(dimension)
+  var tStride = new Array(dimension)
+  for(var i=0; i<dimension; ++i) {
+    tShape[i] = "a[i"+i+"]"
+    tStride[i] = "b[i"+i+"]"
+  }
+  code.push("proto.transpose=function "+className+"_transpose("+args+"){"+
+    args.map(function(n,idx) { return n + "=(" + n + "===undefined?" + idx + ":" + n + "|0)"}).join(";"),
+    "var a=this.shape,b=this.stride;return new "+className+"(this.data,"+tShape.join(",")+","+tStride.join(",")+",this.offset)}")
+  
+  //view.pick():
+  code.push("proto.pick=function "+className+"_pick("+args+"){var a=[],b=[],c=this.offset")
+  for(var i=0; i<dimension; ++i) {
+    code.push("if(typeof i"+i+"==='number'&&i"+i+">=0){c=(c+this._stride"+i+"*i"+i+")|0}else{a.push(this._shape"+i+");b.push(this._stride"+i+")}")
+  }
+  code.push("var ctor=CTOR_LIST[a.length+1];return ctor(this.data,a,b,c)}")
+    
+  //Add return statement
+  code.push("return function construct_"+className+"(data,shape,stride,offset){return new "+className+"(data,"+
+    indices.map(function(i) {
+      return "shape["+i+"]"
+    }).join(",")+","+
+    indices.map(function(i) {
+      return "stride["+i+"]"
+    }).join(",")+",offset)}")
+
+  //Compile procedure
+  var procedure = new Function("CTOR_LIST", "ORDER", code.join("\n"))
+  return procedure(CACHED_CONSTRUCTORS[dtype], order)
+}
+
+function arrayDType(data) {
+  if(hasBuffer) {
+    if(Buffer.isBuffer(data)) {
+      return "buffer"
+    }
+  }
+  if(hasTypedArrays) {
+    switch(Object.prototype.toString.call(data)) {
+      case "[object Float64Array]":
+        return "float64"
+      case "[object Float32Array]":
+        return "float32"
+      case "[object Int8Array]":
+        return "int8"
+      case "[object Int16Array]":
+        return "int16"
+      case "[object Int32Array]":
+        return "int32"
+      case "[object Uint8Array]":
+        return "uint8"
+      case "[object Uint16Array]":
+        return "uint16"
+      case "[object Uint32Array]":
+        return "uint32"
+      case "[object Uint8ClampedArray]":
+        return "uint8_clamped"
+    }
+  }
+  if(Array.isArray(data)) {
+    return "array"
+  }
+  return "generic"
+}
+
+var CACHED_CONSTRUCTORS = {
+  "float32":[],
+  "float64":[],
+  "int8":[],
+  "int16":[],
+  "int32":[],
+  "uint8":[],
+  "uint16":[],
+  "uint32":[],
+  "array":[],
+  "uint8_clamped":[],
+  "buffer":[],
+  "generic":[]
+}
+
+;(function() {
+  for(var id in CACHED_CONSTRUCTORS) {
+    CACHED_CONSTRUCTORS[id].push(compileConstructor(id, -1))
+  }
+});
+
+function wrappedNDArrayCtor(data, shape, stride, offset) {
+  if(data === undefined) {
+    var ctor = CACHED_CONSTRUCTORS.array[0]
+    return ctor([])
+  } else if(typeof data === "number") {
+    data = [data]
+  }
+  if(shape === undefined) {
+    shape = [ data.length ]
+  }
+  var d = shape.length
+  if(stride === undefined) {
+    stride = new Array(d)
+    for(var i=d-1, sz=1; i>=0; --i) {
+      stride[i] = sz
+      sz *= shape[i]
+    }
+  }
+  if(offset === undefined) {
+    offset = 0
+    for(var i=0; i<d; ++i) {
+      if(stride[i] < 0) {
+        offset -= (shape[i]-1)*stride[i]
+      }
+    }
+  }
+  var dtype = arrayDType(data)
+  var ctor_list = CACHED_CONSTRUCTORS[dtype]
+  while(ctor_list.length <= d+1) {
+    ctor_list.push(compileConstructor(dtype, ctor_list.length-1))
+  }
+  var ctor = ctor_list[d+1]
+  return ctor(data, shape, stride, offset)
+}
+
+module.exports = wrappedNDArrayCtor
+}).call(this,require("buffer").Buffer)
+},{"buffer":1,"iota-array":31}],31:[function(require,module,exports){
+"use strict"
+
+function iota(n) {
+  var result = new Array(n)
+  for(var i=0; i<n; ++i) {
+    result[i] = i
+  }
+  return result
+}
+
+module.exports = iota
+},{}],32:[function(require,module,exports){
+arguments[4][26][0].apply(exports,arguments)
+},{"dup":26}],33:[function(require,module,exports){
+arguments[4][27][0].apply(exports,arguments)
+},{"bit-twiddle":11,"buffer":1,"dup":27}],34:[function(require,module,exports){
+var colorSort;
+
+colorSort = require("../color/sort.coffee");
+
+module.exports = function(a, b, keys, sort, colors, vars, depth) {
+  var i, k, retVal;
+  if (!sort) {
+    sort = "asc";
+  }
+  if (!(colors instanceof Array)) {
+    colors = [colors];
+  }
+  if (!(keys instanceof Array)) {
+    keys = [keys];
+  }
+  if (vars && depth !== void 0 && typeof depth !== "number") {
+    depth = vars.id.nesting.indexOf(depth);
+  }
+  retVal = 0;
+  i = 0;
+  while (i < keys.length) {
+    k = keys[i];
+    a = vars && a.d3plus && a.d3plus.sortKeys ? a.d3plus.sortKeys[k] : a[k];
+    b = vars && b.d3plus && b.d3plus.sortKeys ? b.d3plus.sortKeys[k] : b[k];
+    if (vars && colors.indexOf(k) >= 0) {
+      retVal = colorSort(a, b);
+    } else {
+      retVal = a < b ? -1 : 1;
+    }
+    if (retVal !== 0 || i === keys.length - 1) {
+      break;
+    }
+    i++;
+  }
+  if (sort === "asc") {
+    return retVal;
+  } else {
+    return -retVal;
+  }
+};
+
+
+},{"../color/sort.coffee":50}],35:[function(require,module,exports){
+module.exports = function(arr, value) {
+  var constructor;
+  if (arr instanceof Array) {
+    constructor = value === void 0 || value === null ? value : value.constructor;
+    return arr.indexOf(value) >= 0 || arr.indexOf(constructor) >= 0;
+  } else {
+    return false;
+  }
+};
+
+
+},{}],36:[function(require,module,exports){
+var comparator, fetchSort;
+
+comparator = require("./comparator.coffee");
+
+fetchSort = require("../core/fetch/sort.coffee");
+
+module.exports = function(arr, keys, sort, colors, vars, depth) {
+  var d, data, i, len;
+  if (!arr || arr.length <= 1) {
+    return arr || [];
+  } else {
+    if (vars) {
+      if (!keys) {
+        keys = vars.order.value || vars.size.value || vars.id.value;
+      }
+      if (!sort) {
+        sort = vars.order.sort.value;
+      }
+      if (!colors) {
+        colors = vars.color.value || [];
+      }
+      for (i = 0, len = arr.length; i < len; i++) {
+        d = arr[i];
+        if (!d.d3plus) {
+          d.d3plus = {};
+        }
+        data = "d3plus" in d && "d3plus" in d.d3plus ? d.d3plus : d;
+        d.d3plus.sortKeys = fetchSort(vars, data, keys, colors, depth);
+      }
+    }
+    return arr.sort(function(a, b) {
+      return comparator(a, b, keys, sort, colors, vars, depth);
+    });
+  }
+};
+
+
+},{"../core/fetch/sort.coffee":66,"./comparator.coffee":34}],37:[function(require,module,exports){
+module.exports = function(arr, x) {
+  if (x === void 0) {
+    return arr;
+  }
+  if (x === false) {
+    return [];
+  }
+  if (x instanceof Array) {
+    return x;
+  }
+  if (!(arr instanceof Array)) {
+    arr = [];
+  }
+  if (arr.indexOf(x) >= 0) {
+    arr.splice(arr.indexOf(x), 1);
+  } else {
+    arr.push(x);
+  }
+  return arr;
+};
+
+
+},{}],38:[function(require,module,exports){
+var sheet;
+
+sheet = function(name) {
+  var css, i, returnBoolean, tested;
+  tested = sheet.tested;
+  if (name in tested) {
+    return tested[name];
+  }
+  i = 0;
+  returnBoolean = false;
+  while (i < document.styleSheets.length) {
+    css = document.styleSheets[i];
+    if (css.href && css.href.indexOf(name) >= 0) {
+      returnBoolean = true;
+      break;
+    }
+    i++;
+  }
+  return returnBoolean;
+};
+
+sheet.tested = {};
+
+module.exports = sheet;
+
+
+},{}],39:[function(require,module,exports){
+// Determines if the current browser is Internet Explorer.
+module.exports = /*@cc_on!@*/false
+
+},{}],40:[function(require,module,exports){
+var ie, touch;
+
+ie = require("./ie.js");
+
+touch = require("./touch.coffee");
+
+if (touch) {
+  module.exports = {
+    click: "click",
+    down: "touchstart",
+    up: "touchend",
+    over: "touchstart",
+    out: "touchend",
+    move: "touchmove"
+  };
+} else {
+  module.exports = {
+    click: "click",
+    down: "mousedown",
+    up: "mouseup",
+    over: ie ? "mouseenter" : "mouseover",
+    out: ie ? "mouseleave" : "mouseout",
+    move: "mousemove"
+  };
+}
+
+
+},{"./ie.js":39,"./touch.coffee":44}],41:[function(require,module,exports){
+var prefix;
+
+prefix = function() {
+  var val;
+  if ("-webkit-transform" in document.body.style) {
+    val = "-webkit-";
+  } else if ("-moz-transform" in document.body.style) {
+    val = "-moz-";
+  } else if ("-ms-transform" in document.body.style) {
+    val = "-ms-";
+  } else if ("-o-transform" in document.body.style) {
+    val = "-o-";
+  } else {
+    val = "";
+  }
+  prefix = function() {
+    return val;
+  };
+  return val;
+};
+
+module.exports = prefix;
+
+
+},{}],42:[function(require,module,exports){
+module.exports = d3.select("html").attr("dir") === "rtl";
+
+
+},{}],43:[function(require,module,exports){
+var scrollbar;
+
+scrollbar = function() {
+  var inner, outer, val, w1, w2;
+  inner = document.createElement("p");
+  inner.style.width = "100%";
+  inner.style.height = "200px";
+  outer = document.createElement("div");
+  outer.style.position = "absolute";
+  outer.style.top = "0px";
+  outer.style.left = "0px";
+  outer.style.visibility = "hidden";
+  outer.style.width = "200px";
+  outer.style.height = "150px";
+  outer.style.overflow = "hidden";
+  outer.appendChild(inner);
+  document.body.appendChild(outer);
+  w1 = inner.offsetWidth;
+  outer.style.overflow = "scroll";
+  w2 = inner.offsetWidth;
+  if (w1 === w2) {
+    w2 = outer.clientWidth;
+  }
+  document.body.removeChild(outer);
+  val = w1 - w2;
+  scrollbar = function() {
+    return val;
+  };
+  return val;
+};
+
+module.exports = scrollbar;
+
+
+},{}],44:[function(require,module,exports){
+module.exports = ("ontouchstart" in window) || window.DocumentTouch && document instanceof DocumentTouch ? true : false;
+
+
+},{}],45:[function(require,module,exports){
+module.exports = function(color) {
+  var hsl;
+  hsl = d3.hsl(color);
+  if (hsl.l > .45) {
+    if (hsl.s > .8) {
+      hsl.s = 0.8;
+    }
+    hsl.l = 0.45;
+  }
+  return hsl.toString();
+};
+
+
+},{}],46:[function(require,module,exports){
+module.exports = function(color, increment) {
+  var c;
+  if (increment === void 0) {
+    increment = 0.5;
+  }
+  c = d3.hsl(color);
+  increment = (1 - c.l) * increment;
+  c.l += increment;
+  c.s -= increment;
+  return c.toString();
+};
+
+
+},{}],47:[function(require,module,exports){
+module.exports = function(c1, c2, o1, o2) {
+  var b, g, r;
+  if (!o1) {
+    o1 = 1;
+  }
+  if (!o2) {
+    o2 = 1;
+  }
+  c1 = d3.rgb(c1);
+  c2 = d3.rgb(c2);
+  r = (o1 * c1.r + o2 * c2.r - o1 * o2 * c2.r) / (o1 + o2 - o1 * o2);
+  g = (o1 * c1.g + o2 * c2.g - o1 * o2 * c2.g) / (o1 + o2 - o1 * o2);
+  b = (o1 * c1.b + o2 * c2.b - o1 * o2 * c2.b) / (o1 + o2 - o1 * o2);
+  return d3.rgb(r, g, b).toString();
+};
+
+
+},{}],48:[function(require,module,exports){
+var defaultScale;
+
+defaultScale = require("./scale.coffee");
+
+module.exports = function(x, scale) {
+  var rand_int;
+  rand_int = x || Math.floor(Math.random() * 20);
+  scale = scale || defaultScale;
+  return scale(rand_int);
+};
+
+
+},{"./scale.coffee":49}],49:[function(require,module,exports){
+module.exports = d3.scale.ordinal().range(["#b22200", "#EACE3F", "#282F6B", "#B35C1E", "#224F20", "#5F487C", "#759143", "#419391", "#993F88", "#e89c89", "#ffee8d", "#afd5e8", "#f7ba77", "#a5c697", "#c5b5e5", "#d1d392", "#bbefd0", "#e099cf"]);
+
+
+},{}],50:[function(require,module,exports){
+module.exports = function(a, b) {
+  var aHSL, bHSL;
+  aHSL = d3.hsl(a);
+  bHSL = d3.hsl(b);
+  a = aHSL.s === 0 ? 361 : aHSL.h;
+  b = bHSL.s === 0 ? 361 : bHSL.h;
+  if (a === b) {
+    return aHSL.l - bHSL.l;
+  } else {
+    return a - b;
+  }
+};
+
+
+},{}],51:[function(require,module,exports){
+module.exports = function(color) {
+  var b, g, r, rgbColor, yiq;
+  rgbColor = d3.rgb(color);
+  r = rgbColor.r;
+  g = rgbColor.g;
+  b = rgbColor.b;
+  yiq = (r * 299 + g * 587 + b * 114) / 1000;
+  if (yiq >= 128) {
+    return "#444444";
+  } else {
+    return "#f7f7f7";
+  }
+};
+
+
+},{}],52:[function(require,module,exports){
+module.exports = function(color) {
+  var blackColors, testColor, userBlack;
+  color = color + "";
+  color = color.replace(RegExp(" ", "g"), "");
+  if (color.indexOf("rgb") === 0) {
+    color = color.split("(")[1].split(")")[0].split(",").slice(0, 3).join(",");
+  }
+  if (color.indexOf("hsl") === 0) {
+    color = color.split(",")[2].split(")")[0];
+  }
+  testColor = d3.rgb(color).toString();
+  blackColors = ["black", "#000", "#000000", "0%", "0,0,0"];
+  userBlack = blackColors.indexOf(color) >= 0;
+  return testColor !== "#000000" || userBlack;
+};
+
+
+},{}],53:[function(require,module,exports){
+var icon, ie, print, wiki;
+
+ie = require("../../client/ie.js");
+
+wiki = require("./wiki.coffee");
+
+icon = "http://d3plus.org/assets/img/favicon.ico";
+
+print = function(type, message, style) {
+  style = style || "";
+  if (ie || typeof InstallTrigger !== 'undefined') {
+    console.log("[ D3plus ] " + message);
+  } else if (type.indexOf("group") === 0) {
+    if (window.chrome && navigator.onLine) {
+      console[type]("%c%c " + message, "padding: 3px 10px;" + "line-height: 25px;" + "background-size: 20px;" + "background-position: top left;" + "background-image: url('" + icon + "');", "font-weight:200;" + style);
+    } else {
+      console[type]("%cD3plus%c " + message, "line-height: 25px;" + "font-weight: 800;" + "color: #b35c1e;" + "margin-left: 0px;", "font-weight:200;" + style);
+    }
+  } else {
+    console[type]("%c" + message, style + "font-weight:200;");
+  }
+};
+
+print.comment = function(message) {
+  this("log", message, "color:#aaa;");
+};
+
+print.error = function(message, url) {
+  this("groupCollapsed", "ERROR: " + message, "font-weight:800;color:#D74B03;");
+  this.stack();
+  this.wiki(url);
+  this.groupEnd();
+};
+
+print.group = function(message) {
+  this("group", message, "color:#888;");
+};
+
+print.groupCollapsed = function(message) {
+  this("groupCollapsed", message, "color:#888;");
+};
+
+print.groupEnd = function() {
+  if (!ie) {
+    console.groupEnd();
+  }
+};
+
+print.log = function(message) {
+  this("log", message, "color:#444444;");
+};
+
+print.stack = function() {
+  var err, line, message, page, splitter, stack, url;
+  if (!ie) {
+    err = new Error();
+    if (err.stack) {
+      stack = err.stack.split("\n");
+      stack = stack.filter(function(e) {
+        return e.indexOf("Error") !== 0 && e.indexOf("d3plus.js:") < 0 && e.indexOf("d3plus.min.js:") < 0;
+      });
+      if (stack.length && stack[0].length) {
+        splitter = (window.chrome ? "at " : "@");
+        url = stack[0].split(splitter)[1];
+        stack = url.split(":");
+        if (stack.length === 3) {
+          stack.pop();
+        }
+        line = stack.pop();
+        page = stack.join(":").split("/");
+        page = page[page.length - 1];
+        message = "line " + line + " of " + page + ": " + url;
+        this("log", message, "color:#D74B03;");
+      }
+    }
+  }
+};
+
+print.time = function(message) {
+  if (!ie) {
+    console.time(message);
+  }
+};
+
+print.timeEnd = function(message) {
+  if (!ie) {
+    console.timeEnd(message);
+  }
+};
+
+print.warning = function(message, url) {
+  this("groupCollapsed", message, "color:#888;");
+  this.stack();
+  this.wiki(url);
+  this.groupEnd();
+};
+
+print.wiki = function(url) {
+  if (url) {
+    if (url in wiki) {
+      url = d3plus.repo + "wiki/" + wiki[url];
+    }
+    this("log", "documentation: " + url, "color:#aaa;");
+  }
+};
+
+module.exports = print;
+
+
+},{"../../client/ie.js":39,"./wiki.coffee":54}],54:[function(require,module,exports){
+module.exports = {
+  active: "Segmenting-Data#active",
+  aggs: "Custom-Aggregations",
+  alt: "Alt-Text-Parameters",
+  attrs: "Attribute-Data#axes",
+  axes: "Axis-Parameters",
+  background: "Background",
+  color: "Color-Parameters",
+  container: "Container-Element",
+  coords: "Geography-Data",
+  csv: "CSV-Export",
+  data: "Data-Points",
+  depth: "Visible-Depth",
+  descs: "Value-Definitions",
+  dev: "Verbose-Mode",
+  draw: "Draw",
+  edges: "Edges-List",
+  error: "Custom-Error-Message",
+  focus: "Focus-Element",
+  font: "Font-Styles",
+  footer: "Custom-Footer",
+  format: "Value-Formatting",
+  height: "Height",
+  history: "User-History",
+  hover: "Hover-Element",
+  icon: "Icon-Parameters",
+  id: "Unique-ID",
+  keywords: "Keyword-Parameters",
+  labels: "Data-Labels",
+  legend: "Legend",
+  links: "Link-Styles",
+  margin: "Outer-Margins",
+  messages: "Status-Messages",
+  method: "Methods",
+  nodes: "Node-Positions",
+  open: "Open",
+  order: "Data-Ordering",
+  remove: "Remove",
+  search: "Search-Box",
+  select: "Selecting-Elements#select",
+  selectAll: "Selecting-Elements#selectall",
+  shape: "Data-Shapes",
+  size: "Size-Parameters",
+  temp: "Segmenting-Data#temp",
+  text: "Text-Parameters",
+  time: "Time-Parameters",
+  timeline: "Timeline",
+  timing: "Animation-Timing",
+  title: "Custom-Titles",
+  tooltip: "Tooltip-Parameters",
+  total: "Segmenting-Data#total",
+  type: "Output-Type",
+  ui: "Custom-Interface",
+  width: "Width",
+  x: "Axis-Parameters",
+  y: "Axis-Parameters",
+  zoom: "Zooming"
+};
+
+
+},{}],55:[function(require,module,exports){
+var buckets = require("../../util/buckets.coffee"),
+    fetchValue = require("../fetch/value.coffee"),
+    print      = require("../console/print.coffee")
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Sets color range of data, if applicable
+//-------------------------------------------------------------------
+module.exports = function(vars) {
+
+  if ( vars.dev.value ) print.time("getting color data range")
+
+  var data_range = []
+  vars.data.pool.forEach(function(d){
+    var val = parseFloat(fetchValue(vars,d,vars.color.value))
+    if (typeof val == "number" && !isNaN(val) && data_range.indexOf(val) < 0) data_range.push(val)
+  })
+
+  if ( vars.dev.value ) print.timeEnd("getting color data range")
+
+  if (data_range.length > 1) {
+
+    var data_domain = null
+
+    if ( vars.dev.value ) print.time("calculating color scale")
+
+    data_range = d3.extent(data_range)
+
+    if (data_range[0] < 0 && data_range[1] > 0) {
+      var color_range = vars.color.range
+      if (color_range.length == 3) {
+        data_range.push(data_range[1])
+        data_range[1] = 0
+      }
+    }
+    else if (data_range[1] > 0 && data_range[0] >= 0) {
+      var color_range = vars.color.heatmap
+      data_range = buckets(data_range,color_range.length)
+    }
+    else {
+      var color_range = vars.color.range.slice(0)
+      if (data_range[0] < 0) {
+        color_range.pop()
+      }
+      else {
+        color_range.shift()
+      }
+    }
+
+    vars.color.valueScale = d3.scale.sqrt()
+      .domain(data_range)
+      .range(color_range)
+      .interpolate(d3.interpolateRgb)
+
+    if ( vars.dev.value ) print.timeEnd("calculating color scale")
+
+  }
+  else {
+    vars.color.valueScale = null
+  }
+
+}
+
+},{"../../util/buckets.coffee":203,"../console/print.coffee":53,"../fetch/value.coffee":68}],56:[function(require,module,exports){
+var fetchValue = require("../fetch/value.coffee"),
+    print       = require("../console/print.coffee"),
+    validObject = require("../../object/validate.coffee")
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Restricts data based on Solo/Mute filters
+//------------------------------------------------------------------------------
+module.exports = function( vars , data ) {
+
+  if ( vars.dev.value ) print.time("filtering data")
+
+  var availableKeys = d3.keys(vars.data.keys || {})
+
+  if ( "attrs" in vars ) {
+    availableKeys = availableKeys.concat(d3.keys(vars.attrs.keys || {}))
+  }
+
+  data = data.filter(function(d){
+    var val = fetchValue(vars, d, vars.id.value);
+    return val !== null;
+  });
+
+  var typeReqs = vars.types[vars.type.value].requirements || [];
+
+  vars.data.filters.forEach( function( key ) {
+
+    if (availableKeys.indexOf(vars[key].value) >= 0 &&
+        typeReqs.indexOf(key) >= 0) {
+
+      data = data.filter( function( d ) {
+
+        var val = fetchValue(vars,d,vars[key].value)
+        if ( key === "size" ) {
+          return typeof val === "number"
+        }
+        else {
+          return val !== null
+        }
+
+      })
+
+    }
+
+  });
+
+  // if "solo", only check against "solo" (disregard "mute")
+  var key = vars.data.solo.length ? "solo" : "mute";
+
+  vars.data[key].forEach(function(v) {
+
+    function test_value(val) {
+
+      var arr = vars[v][key].value;
+
+      var match = false;
+      arr.forEach(function(f){
+        if (typeof f === "function") {
+          match = f(val);
+        }
+        else if (f === val) {
+          match = true;
+        }
+
+      })
+
+      return key === "solo" ? match : !match;
+
+    }
+
+    function filter_data(d, flat) {
+      if (!flat && vars[v].nesting) {
+        var nesting = vars[v].nesting;
+        if (validObject(nesting)) {
+          nesting = d3.values(nesting);
+        }
+        for (var n = 0; n < nesting.length; n++) {
+          var new_data = d.filter(function(dd){
+            return test_value(fetchValue(vars, dd, nesting[n]));
+          });
+          if (new_data.length) d = new_data;
+        }
+      }
+      else {
+        d = d.filter(function(dd){
+          return test_value(fetchValue(vars, dd, vars[v].value));
+        });
+      }
+      return d;
+    }
+
+    data = filter_data(data);
+
+    if ( v === "id" ) {
+
+      if ("nodes" in vars && vars.nodes.value) {
+        if ( vars.dev.value ) print.time("filtering nodes")
+        vars.nodes.restricted = filter_data(vars.nodes.value)
+        if ( vars.dev.value ) print.timeEnd("filtering nodes")
+      }
+
+      if ("edges" in vars && vars.edges.value) {
+        if ( vars.dev.value ) print.time("filtering edges")
+        vars.edges.restricted = vars.edges.value.filter(function(d){
+          var points = filter_data([d[vars.edges.source], d[vars.edges.target]], true);
+          return points.length === 2;
+        })
+        if ( vars.dev.value ) print.timeEnd("filtering edges")
+      }
+
+    }
+
+  })
+
+  if ( vars.dev.value ) print.timeEnd("filtering data")
+
+  return data
+
+}
+
+},{"../../object/validate.coffee":171,"../console/print.coffee":53,"../fetch/value.coffee":68}],57:[function(require,module,exports){
+var dataNest   = require("./nest.js"),
+    fetchValue = require("../fetch/value.coffee"),
+    print      = require("../console/print.coffee"),
+    uniques    = require("../../util/uniques.coffee");
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Formats raw data by time and nesting
+//------------------------------------------------------------------------------
+module.exports = function( vars ) {
+
+  var timerString;
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Gets all unique time values
+  //----------------------------------------------------------------------------
+  vars.data.time = {"values": []};
+  if (vars.time && vars.time.value) {
+
+    if ( vars.dev.value ) {
+      timerString = "analyzing time periods";
+      print.time( timerString );
+    }
+
+    vars.data.time.values = uniques(vars.data.value, vars.time.value, fetchValue, vars);
+
+    vars.data.time.values.sort(function(a,b){ return a-b; });
+
+    var step = [];
+    vars.data.time.values.forEach(function(y,i){
+      if (i !== 0) {
+        var prev = vars.data.time.values[i-1];
+        step.push(y-prev);
+        if (i === vars.data.time.values.length - 1) {
+          vars.data.time.total = y - vars.data.time.values[0];
+        }
+      }
+    });
+
+    step = d3.min(step);
+    vars.data.time.step = step;
+
+    var periods = ["Milliseconds","Seconds","Minutes","Hours","Date","Month","FullYear"],
+        conversions = [1000,60,60,24,30,12,1];
+
+    vars.data.time.periods = periods;
+
+    var getDiff = function(start,end,i) {
+
+      if (!vars.data.time.stepDivider) {
+        arr = conversions.slice(0,i);
+        if (arr.length) {
+          vars.data.time.stepDivider = arr.reduce(function(a,b){ return a*b; });
+        }
+        else {
+          vars.data.time.stepDivider = 1;
+        }
+      }
+
+      return Math.round(Math.floor(end-start)/vars.data.time.stepDivider);
+
+    };
+
+    var total = vars.data.time.total;
+    periods.forEach(function(p,i){
+      var c = p === "Date" ? 28 : conversions[i];
+      if (!vars.data.time.stepType && (i === periods.length-1 || Math.round(step) < c)) {
+        vars.data.time.stepType = p;
+        var start = vars.data.time.values[0],
+            end = vars.data.time.values[vars.data.time.values.length-1];
+        vars.data.time.stepIntervals = getDiff(start,end,i);
+      }
+
+      if (!vars.data.time.totalType && (i === periods.length-1 || Math.round(total) < c)) {
+        vars.data.time.totalType = p;
+      }
+
+      step = step/c;
+      total = total/c;
+    });
+
+    vars.data.time.values.forEach(function(y,i){
+      if (i !== 0) {
+        var prev = vars.data.time.values[0];
+        vars.data.time.dataSteps.push(getDiff(prev,y,periods.indexOf(vars.data.time.stepType)));
+      }
+      else {
+        vars.data.time.dataSteps = [0];
+      }
+    });
+
+    var userFormat = vars.time.format.value,
+        locale = vars.format.locale.value,
+        functions = [
+          function(d) { return d.getMilliseconds(); },
+          function(d) { return d.getSeconds(); },
+          function(d) { return d.getMinutes(); },
+          function(d) { return d.getHours(); },
+          function(d) { return d.getDate() != 1; },
+          function(d) { return d.getMonth(); },
+          function(d) { return true; }
+        ];
+
+    vars.data.time.functions = functions;
+
+    var getFormat = function(s,t,small) {
+
+      if (s === t) {
+        return small && locale.timeFormat[s+"Small"] ? locale.timeFormat[s+"Small"] : locale.timeFormat[s];
+      }
+      else {
+        if (periods.indexOf(s) >= 4 || periods.indexOf(t) <= 3) {
+          return locale.timeFormat[t+"-"+s];
+        }
+        else {
+
+          var format;
+
+          if (t === "Date") {
+            format = locale.timeFormat[t];
+          }
+          else {
+            format = locale.timeFormat[t+"-Date"];
+          }
+
+          if (s === "Hours") {
+            return format +" "+ locale.timeFormat[s];
+          }
+          else {
+            return format +" "+ locale.timeFormat["Hours-"+s];
+          }
+
+        }
+      }
+
+    };
+
+    vars.data.time.getFormat = getFormat;
+
+    if (userFormat) {
+
+      if (typeof userFormat === "string") {
+        vars.data.time.format = d3.locale(locale.format).timeFormat(userFormat);
+      }
+      else if (typeof userFormat === "function") {
+        vars.data.time.format = userFormat;
+      }
+      else if (userFormat instanceof Array) {
+        vars.data.time.format = d3.locale(locale.format).timeFormat.multi(userFormat);
+      }
+      vars.data.time.multiFormat = vars.data.time.format;
+
+    }
+    else {
+
+      var stepType = vars.data.time.stepType,
+          totalType = vars.data.time.totalType;
+
+      var multi = [];
+
+      for (var p = periods.indexOf(stepType); p <= periods.indexOf(totalType); p++) {
+        var prev = p-1 < periods.indexOf(stepType) ? periods[p] : periods[p-1];
+        var small = periods[p] === prev && stepType !== totalType;
+        var format = getFormat(prev,periods[p],small);
+        multi.push([format,functions[p]]);
+      }
+
+      vars.data.time.format = d3.locale(locale.format).timeFormat(getFormat(stepType,totalType));
+      if (multi.length > 1) {
+        multi[multi.length-1][1] = function (d) { return true; }
+        vars.data.time.multiFormat = d3.locale(locale.format).timeFormat.multi(multi);
+      }
+      else {
+        vars.data.time.multiFormat = vars.data.time.format;
+      }
+
+    }
+
+    vars.data.time.ticks = [];
+    var min = d3.min(vars.data.time.values);
+    var max = d3.max(vars.data.time.values);
+    for (var s = 0; s <= vars.data.time.stepIntervals; s++) {
+      var m = new Date(min);
+      m["set"+vars.data.time.stepType](m["get"+vars.data.time.stepType]() + s);
+      if (m <= max) vars.data.time.ticks.push(m);
+    }
+
+    if ( vars.dev.value ) print.timeEnd( timerString );
+
+  }
+
+  if ( vars.dev.value ) {
+    timerString = "nesting data by time and depths";
+    print.time( timerString );
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Gets all unique time values
+  //----------------------------------------------------------------------------
+  vars.data.nested = {};
+  if (vars.data.time.values.length === 0) {
+
+    vars.data.nested.all = {};
+    vars.id.nesting.forEach( function( depth , i ) {
+
+      var nestingDepth = vars.id.nesting.slice( 0 , i + 1 );
+      vars.data.nested.all[ depth ] = dataNest(vars, vars.data.value, nestingDepth);
+
+    });
+
+  }
+  else {
+
+    var timeData = vars.data.value.reduce(function(o, d){
+      var ms = fetchValue(vars, d, vars.time.value).getTime();
+      if (!(ms in o)) o[ms] = [];
+      o[ms].push(d);
+      return o;
+    }, {});
+
+    vars.data.time.values.forEach( function( t ) {
+
+      var ms = t.getTime();
+
+      vars.data.nested[ms] = {};
+
+      vars.id.nesting.forEach( function( depth , i ) {
+        var nestingDepth = vars.id.nesting.slice(0, i + 1);
+        vars.data.nested[ ms ][ depth ] = dataNest(vars, timeData[ms], nestingDepth);
+      });
+
+    });
+
+  }
+
+  if ( vars.dev.value ) print.timeEnd( timerString );
+
+};
+
+},{"../../util/uniques.coffee":209,"../console/print.coffee":53,"../fetch/value.coffee":68,"./nest.js":61}],58:[function(require,module,exports){
+var fetchValue;
+
+fetchValue = require("../fetch/value.coffee");
+
+module.exports = function(vars, data, nesting) {
+  var d, groupedData, i, j, k, len, len1, n, strippedData, val;
+  groupedData = d3.nest();
+  if (vars.id.grouping.value) {
+    if (nesting === void 0) {
+      nesting = vars.id.nesting;
+    }
+    for (i = j = 0, len = nesting.length; j < len; i = ++j) {
+      n = nesting[i];
+      if (i < vars.depth.value) {
+        (function(n) {
+          return groupedData.key(function(d) {
+            return fetchValue(vars, d.d3plus, n);
+          });
+        })(n);
+      }
+    }
+  }
+  strippedData = [];
+  for (k = 0, len1 = data.length; k < len1; k++) {
+    d = data[k];
+    val = vars.size.value ? fetchValue(vars, d, vars.size.value) : 1;
+    if (val && typeof val === "number" && val > 0) {
+      delete d.d3plus.r;
+      delete d.d3plus.x;
+      delete d.d3plus.y;
+      strippedData.push({
+        d3plus: d,
+        id: d[vars.id.value],
+        value: val
+      });
+    }
+  }
+  return groupedData.entries(strippedData);
+};
+
+
+},{"../fetch/value.coffee":68}],59:[function(require,module,exports){
+var print, validObject,
+  indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+print = require("../console/print.coffee");
+
+validObject = require("../../object/validate.coffee");
+
+module.exports = function(vars, type) {
+  var get_keys, k, kk, lengthMatch, ref, ref1, timerString, v, vv;
+  timerString = type + " key analysis";
+  if (vars.dev.value) {
+    print.time(timerString);
+  }
+  vars[type].keys = {};
+  get_keys = function(arr) {
+    var a, i, k, len, results, results1, v;
+    if (arr instanceof Array) {
+      results = [];
+      for (i = 0, len = arr.length; i < len; i++) {
+        a = arr[i];
+        results.push(get_keys(a));
+      }
+      return results;
+    } else if (validObject(arr)) {
+      results1 = [];
+      for (k in arr) {
+        v = arr[k];
+        if (k.indexOf("d3plus") !== 0 && !(indexOf.call(vars[type].keys, k) >= 0) && v !== null) {
+          results1.push(vars[type].keys[k] = typeof v);
+        } else {
+          results1.push(void 0);
+        }
+      }
+      return results1;
+    }
+  };
+  if (validObject(vars[type].value)) {
+    lengthMatch = d3.keys(vars[type].value).length === vars.id.nesting.length;
+    ref = vars[type].value;
+    for (k in ref) {
+      v = ref[k];
+      if (lengthMatch && vars.id.nesting.indexOf(k) >= 0 && validObject(v)) {
+        for (kk in v) {
+          vv = v[kk];
+          get_keys(vv);
+        }
+      } else {
+        get_keys(v);
+      }
+    }
+  } else {
+    ref1 = vars[type].value;
+    for (k in ref1) {
+      v = ref1[k];
+      get_keys(v);
+    }
+  }
+  if (vars.dev.value) {
+    return print.time(timerString);
+  }
+};
+
+
+},{"../../object/validate.coffee":171,"../console/print.coffee":53}],60:[function(require,module,exports){
+var print, validObject;
+
+print = require("../console/print.coffee");
+
+validObject = require("../../object/validate.coffee");
+
+module.exports = function(vars, key, next) {
+  var consoleMessage, fileType, parser, url;
+  consoleMessage = vars.dev.value;
+  if (consoleMessage) {
+    print.time("loading " + key);
+  }
+  url = vars[key].url;
+  if (!vars[key].filetype.value) {
+    fileType = url.slice(url.length - 5).split(".");
+    if (fileType.length > 1) {
+      fileType = fileType[1];
+    } else {
+      fileType = false;
+    }
+    if (fileType) {
+      if (fileType === "txt") {
+        fileType = "text";
+      }
+      if (vars[key].filetype.accepted.indexOf(fileType) < 0) {
+        fileType = "json";
+      }
+    } else {
+      fileType = "json";
+    }
+  } else {
+    fileType = vars[key].filetype.value;
+  }
+  if (fileType === "dsv") {
+    parser = d3.dsv(vars[key].delimiter.value, "text/plain");
+  } else {
+    parser = d3[fileType];
+  }
+  return parser(url, function(error, data) {
+    var k, ret;
+    if (!error && data) {
+      if (typeof vars[key].callback === "function") {
+        ret = vars[key].callback(data);
+        if (ret) {
+          if (validObject(ret) && key in ret) {
+            for (k in ret) {
+              if (k in vars) {
+                vars[k].value = ret[k];
+              }
+            }
+          } else {
+            vars[key].value = ret;
+          }
+        }
+      } else {
+        vars[key].value = data;
+      }
+      if (["json"].indexOf(fileType) < 0) {
+        vars[key].value.forEach(function(d) {
+          var results;
+          results = [];
+          for (k in d) {
+            if (!isNaN(d[k])) {
+              results.push(d[k] = parseFloat(d[k]));
+            } else if (d[k].toLowerCase() === "false") {
+              results.push(d[k] = false);
+            } else if (d[k].toLowerCase() === "true") {
+              results.push(d[k] = true);
+            } else if (d[k].toLowerCase() === "null") {
+              results.push(d[k] = null);
+            } else {
+              if (d[k].toLowerCase() === "undefined") {
+                results.push(d[k] = void 0);
+              } else {
+                results.push(void 0);
+              }
+            }
+          }
+          return results;
+        });
+      }
+      vars[key].changed = true;
+      vars[key].loaded = true;
+    } else {
+      vars.error.internal = "Could not load data from: \"" + url + "\"";
+    }
+    if (consoleMessage) {
+      print.timeEnd("loading " + key);
+    }
+    return next();
+  });
+};
+
+
+},{"../../object/validate.coffee":171,"../console/print.coffee":53}],61:[function(require,module,exports){
+var fetchValue = require("../fetch/value.coffee"),
+    validObject  = require("../../object/validate.coffee"),
+    uniqueValues = require("../../util/uniques.coffee");
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Nests and groups the data.
+//------------------------------------------------------------------------------
+var dataNest = function(vars, flatData, nestingLevels) {
+
+  var nestedData   = d3.nest(),
+      groupedData  = [],
+      segments     = "temp" in vars ? [ "active" , "temp" , "total" ] : [];
+
+  if (!nestingLevels.length) {
+    nestedData.key(function(d){ return true; });
+  }
+  else {
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Loop through each nesting level.
+    //----------------------------------------------------------------------------
+    nestingLevels.forEach(function(level, i){
+
+      //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+      // Create a nest key for the current level.
+      //--------------------------------------------------------------------------
+      nestedData.key(function(d){ return fetchValue(vars, d, level); });
+
+    });
+
+  }
+
+  if (vars.axes && vars.axes.discrete && (!vars.time || vars[vars.axes.discrete].value !== vars.time.value)) {
+    nestedData.key(function(d){
+      return fetchValue(vars, d, vars[vars.axes.discrete].value);
+    });
+  }
+
+  var deepest_is_id = nestingLevels.length && vars.id.nesting.indexOf(nestingLevels[nestingLevels.length - 1]) >= 0;
+  var i = nestingLevels.length && deepest_is_id ? nestingLevels.length - 1 : 0;
+  var depthKey = deepest_is_id ? vars.id.nesting[i] : vars.depth.value;
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // If we're at the deepest level, create the rollup function.
+  //----------------------------------------------------------------------------
+  nestedData.rollup(function(leaves) {
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // If there's only 1 leaf, and it's been processed, return it as-is.
+    //--------------------------------------------------------------------------
+    if (leaves.length === 1 && ("d3plus" in leaves[0])) {
+      groupedData.push(leaves[0]);
+      return leaves[0];
+    }
+
+    leaves = leaves.reduce(function(arr, ll){
+      if (ll.values instanceof Array) {
+        return arr.concat(ll.values);
+      }
+      arr.push(ll);
+      return arr;
+    }, []);
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Create the "d3plus" object for the return variable, starting with
+    // just the current depth.
+    //--------------------------------------------------------------------------
+    var returnObj = {
+      "d3plus": {
+        "data": {},
+        "depth": i
+      }
+    };
+
+    var merged = d3.sum(leaves, function(ll){ return "d3plus" in ll && ll.d3plus.merged ? 1 : 0; });
+
+    if (merged === leaves.length) {
+      for (var ll = 0; ll < leaves.length; ll++) {
+        var l = leaves[ll];
+        if (!returnObj.d3plus.merged) returnObj.d3plus.merged = [];
+        returnObj.d3plus.merged = returnObj.d3plus.merged.concat(l.d3plus.merged);
+        if (l.d3plus.text) returnObj.d3plus.text = l.d3plus.text;
+      }
+    }
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Create a reference sum for the 3 different "segment" variables.
+    //--------------------------------------------------------------------------
+    for (var s = 0; s < segments.length; s++) {
+
+      var c = segments[s];
+      var segmentAgg = vars.aggs && vars.aggs.value[key] ? vars.aggs.value[key] : "sum";
+
+      if ("d3plus" in leaves[0] && c in leaves[0].d3plus) {
+        returnObj.d3plus[c] = d3.sum(leaves, function(d){
+          return d.d3plus[c];
+        });
+      }
+      else if (typeof segmentAgg === "function") {
+        returnObj.d3plus[c] = segmentAgg(leaves);
+      }
+      else {
+
+        returnObj.d3plus[c] = d3[segmentAgg](leaves, function(d) {
+
+          var a = c === "total" ? 1 : 0;
+          if (vars[c].value) {
+            a = fetchValue(vars, d, vars[c].value);
+            if (typeof a !== "number") a = a ? 1 : 0;
+          }
+          return a;
+
+        });
+
+      }
+    }
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Aggregate all values detected in the data.
+    //--------------------------------------------------------------------------
+    for (var key in vars.data.keys) {
+
+      if (key in returnObj.d3plus.data) {
+        returnObj[key] = returnObj.d3plus[key];
+      }
+      else {
+
+        var agg     = vars.aggs && vars.aggs.value[key] ? vars.aggs.value[key] : "sum",
+            aggType = typeof agg,
+            keyType = vars.data.keys[key],
+            idKey   = vars.id.nesting.indexOf(key) >= 0,
+            timeKey = "time" in vars && key === vars.time.value;
+
+        if (key in returnObj.d3plus.data) {
+          returnObj[key] = returnObj.d3plus[key];
+        }
+        if (aggType === "function") {
+          returnObj[key] = vars.aggs.value[key](leaves);
+        }
+        else if (timeKey) {
+          returnObj[key] = parseDates(uniqueValues(leaves, key));
+        }
+        else if (keyType === "number" && aggType === "string" && !idKey) {
+          var vals = leaves.map(function(d){ return d[key]; });
+          vals = vals.filter(function(d){ return typeof d === keyType; });
+          if (vals.length) returnObj[key] = d3[agg](vals);
+        }
+        else {
+
+          var testVals = checkVal(leaves, key);
+          var keyValues = testVals.length === 1 ? testVals[0][key]
+                        : uniqueValues(testVals, key);
+
+          if (testVals.length === 1) {
+            returnObj[key] = keyValues;
+          }
+          else if (keyValues && keyValues.length) {
+
+            if (!(keyValues instanceof Array)) {
+              keyValues = [keyValues];
+            }
+
+            if (idKey && vars.id.nesting.indexOf(key) > i) {
+            // if (idKey && vars.id.nesting.indexOf(key) > i && keyValues.length > 1) {
+              // if (nestingLevels.length == 1 && testVals.length > leaves.length) {
+              //   var newNesting = nestingLevels.concat(key);
+              //   testVals = dataNest(vars,testVals,newNesting);
+              // }
+              returnObj[key] = testVals;
+            }
+            else {
+
+              returnObj[key] = keyValues;
+
+            }
+
+          }
+          else if (idKey) {
+            var endPoint = vars.id.nesting.indexOf(key) - 1;
+            if (endPoint >= i && (!("endPoint" in returnObj.d3plus) || returnObj.d3plus.endPoint > i)) {
+              returnObj.d3plus.endPoint = i;
+            }
+          }
+
+        }
+
+      }
+
+      if (key in returnObj && returnObj[key] instanceof Array && returnObj[key].length === 1) {
+        returnObj[key] = returnObj[key][0];
+      }
+
+    }
+
+    for (var lll = 0; lll < nestingLevels.length; lll++) {
+      var level = nestingLevels[lll];
+      if (!(level in returnObj)) {
+        returnObj[level] = fetchValue(vars, leaves[0], level);
+      }
+    }
+
+    groupedData.push(returnObj);
+
+    return returnObj;
+
+  });
+
+  var find_keys = function(obj,depth,keys) {
+    if (obj.children) {
+      if (vars.data.keys[nestingLevels[depth]] == "number") {
+        obj.key = parseFloat(obj.key);
+      }
+      keys[nestingLevels[depth]] = obj.key;
+      delete obj.key;
+      for ( var k in keys ) {
+        obj[k] = keys[k];
+      }
+      depth++;
+      obj.children.forEach(function(c){
+        find_keys(c,depth,keys);
+      });
+    }
+  };
+
+  nestedData = nestedData
+    .entries(flatData)
+    .map(rename_key_value)
+    .map(function(obj){
+      find_keys(obj,0,{});
+      return obj;
+    });
+
+  return groupedData;
+
+};
+
+var checkVal = function(leaves, key) {
+
+  var returnVals = [];
+
+  function run(obj) {
+    if (obj instanceof Array) {
+      obj.forEach(run);
+    }
+    else if (validObject(obj) && key in obj) {
+      if (obj[key] instanceof Array) {
+        obj[key].forEach(run);
+      }
+      else {
+        returnVals.push(obj);
+      }
+    }
+  }
+
+  run(leaves);
+
+  return returnVals;
+
+};
+
+var parseDates = function(dateArray) {
+
+  var dates = [];
+
+  function checkDate(arr) {
+
+    for (var i = 0; i < arr.length; i++) {
+      var d = arr[i];
+      if (d) {
+        if (d.constructor === Array) {
+          checkDate(d);
+        }
+        else {
+          dates.push(d);
+        }
+        // if (d.constructor === Date) dates.push(d);
+        // else if (d.constructor === Array) {
+        //   checkDate(d);
+        // }
+        // else {
+        //   d = new Date(d.toString());
+        //   if (d !== "Invalid Date") {
+        //     d.setTime( d.getTime() + d.getTimezoneOffset() * 60 * 1000 );
+        //     dates.push(d);
+        //   }
+        // }
+      }
+    }
+
+  }
+
+  checkDate(dateArray);
+
+  return uniqueValues(dates);
+
+};
+
+var rename_key_value = function(obj) {
+  if (obj.values && obj.values.length) {
+    obj.children = obj.values.map(function(obj) {
+      return rename_key_value(obj);
+    });
+    delete obj.values;
+    return obj;
+  }
+  else if(obj.values) {
+    return obj.values;
+  }
+  else {
+    return obj;
+  }
+};
+
+module.exports = dataNest;
+
+},{"../../object/validate.coffee":171,"../../util/uniques.coffee":209,"../fetch/value.coffee":68}],62:[function(require,module,exports){
+var arraySort = require("../../array/sort.coffee"),
+    dataNest   = require("./nest.js"),
+    fetchValue = require("../fetch/value.coffee"),
+    fetchColor = require("../fetch/color.coffee"),
+    fetchText  = require("../fetch/text.js");
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Merges data underneath the size threshold
+//-------------------------------------------------------------------
+module.exports = function( vars , rawData , split ) {
+
+  var threshold;
+  if ( vars.size.threshold.value === false ) {
+    threshold = 0;
+  }
+  else if (typeof vars.size.threshold.value === "number") {
+    threshold = vars.size.threshold.value;
+  }
+  else if (typeof vars.size.threshold.value === "function") {
+    threshold = vars.size.threshold.value(vars);
+  }
+  else if (typeof vars.types[vars.type.value].threshold === "number") {
+    threshold = vars.types[vars.type.value].threshold;
+  }
+  else if (typeof vars.types[vars.type.value].threshold === "function") {
+    threshold = vars.types[vars.type.value].threshold(vars);
+  }
+  else {
+    threshold = 0.02;
+  }
+
+  if (typeof threshold == "number" && threshold > 0) {
+
+    var largeEnough = [],
+        cutoff = vars.depth.value === 0 ? 0 : {},
+        removed = [],
+        parents = [],
+        labelException = [],
+        largest = {};
+
+    var nest = d3.nest();
+
+    if (split) {
+      nest
+        .key(function(d){
+          return fetchValue(vars, d, split);
+        });
+    }
+
+    nest
+      .rollup(function(leaves){
+        var total = leaves.length;
+        if (vars.aggs.value[vars.size.value]) {
+          if (typeof vars.aggs.value[vars.size.value] == "function") {
+            total = vars.aggs.value[vars.size.value](leaves);
+          }
+          else if (typeof vars.aggs.value[vars.size.value] == "string") {
+            total = d3[vars.aggs.value[vars.size.value]](leaves,function(l){
+              return fetchValue(vars,l,vars.size.value);
+            });
+          }
+        }
+        else {
+          total = d3.sum(leaves,function(l){
+            return fetchValue(vars,l,vars.size.value);
+          });
+        }
+        var x = split ? fetchValue(vars,leaves[0],split) : "all";
+        largest[x] = total;
+        return total;
+      })
+      .entries(rawData);
+
+    rawData.forEach(function(d){
+      var id = fetchValue(vars, d, vars.id.value),
+          val = fetchValue(vars, d, vars.size.value),
+          x = split ? fetchValue(vars, d, split) : "all",
+          allowed = val/largest[x] >= threshold;
+
+      if (allowed && largeEnough.indexOf(id) < 0) {
+        largeEnough.push(id);
+        if (vars.depth.value) {
+          var p = fetchValue(vars, d, vars.id.nesting[vars.depth.value-1]);
+          if (parents.indexOf(p) < 0) {
+            parents.push(p);
+          }
+        }
+      }
+
+    });
+
+    var filteredData = rawData.filter(function(d){
+
+      var id = fetchValue(vars, d, vars.id.value),
+          allowed = largeEnough.indexOf(id) >= 0;
+
+      var p = vars.depth.value ?
+              fetchValue(vars, d, vars.id.nesting[vars.depth.value-1]) :
+              null;
+
+      if (p !== null && parents.indexOf(p) < 0 && labelException.indexOf(p) < 0) {
+        labelException.push(p);
+      }
+
+      if (!allowed) {
+        var val = fetchValue(vars, d, vars.size.value);
+        if (val > 0) {
+          if (vars.depth.value === 0) {
+            if (val > cutoff) cutoff = val;
+          }
+          else {
+            if (!(p in cutoff)) cutoff[p] = 0;
+            if (val > cutoff[p]) cutoff[p] = val;
+          }
+          removed.push(d);
+        }
+      }
+      return allowed;
+
+    });
+
+    if ( removed.length > 1 ) {
+
+      removed = arraySort( removed , vars.size.value , "desc" , [] , vars );
+
+      var levels = vars.id.nesting.slice(0,vars.depth.value);
+      if (vars.types[vars.type.value].requirements.indexOf(vars.axes.discrete) >= 0) {
+        levels.push(vars[vars.axes.discrete].value);
+      }
+      var merged = dataNest(vars, removed, levels);
+
+      merged.forEach(function(m){
+
+        var parent = vars.id.nesting[vars.depth.value-1];
+        var p_id = fetchValue(vars, m, parent);
+        children = parent ? removed.filter(function(r){
+          return fetchValue(vars, r, parent) === p_id;
+        }) : removed;
+
+        if (children.length > 1) {
+
+          vars.id.nesting.forEach(function(d,i){
+
+            if (vars.depth.value == i) {
+              var prev = m[d];
+              if ( typeof prev === "string" ) {
+                m[d] = "d3plus_other_"+prev;
+              }
+              else {
+                m[d] = "d3plus_other";
+              }
+            }
+            else if (i > vars.depth.value) {
+              delete m[d];
+            }
+          });
+
+          if (vars.color.value && vars.color.type === "string") {
+            if (vars.depth.value === 0) {
+              m[vars.color.value] = vars.color.missing;
+            }
+            else {
+              m[vars.color.value] = fetchValue(vars,p_id,vars.color.value,parent);
+            }
+          }
+
+          if (vars.icon.value) {
+            m[vars.icon.value] = fetchValue(vars,p_id,vars.icon.value,parent);
+          }
+
+          if (p_id) {
+            m.d3plus.depth = vars.depth.value;
+          }
+
+          var textLabel;
+          if (vars.depth.value === 0) {
+            textLabel = vars.format.value(vars.format.locale.value.ui.values, {"key": "threshold", "vars": vars});
+            textLabel += " < "+vars.format.value(cutoff, {"key": vars.size.value, "vars": vars});
+          }
+          else {
+            textLabel = fetchText(vars,m,vars.depth.value-1);
+            textLabel = textLabel.length ? textLabel[0].split(" < ")[0] : vars.format.value(vars.format.locale.value.ui.values, {"key": "threshold", "vars": vars});
+            if (p_id, labelException.indexOf(p_id) < 0) {
+              textLabel += " < "+vars.format.value(cutoff[p_id], {"key": vars.size.value, "vars": vars});
+            }
+          }
+          if (p_id, labelException.indexOf(p_id) < 0) {
+            textLabel += " ("+vars.format.value(threshold*100, {"key": "share", "vars": vars})+")";
+          }
+
+          m.d3plus.threshold = cutoff;
+          m.d3plus.merged = children;
+
+          if (vars.text.value) {
+            m[vars.text.value] = textLabel;
+          }
+          m.d3plus.text = textLabel;
+
+        }
+
+      });
+
+    }
+    else {
+      merged = removed;
+    }
+
+    return filteredData.concat(merged);
+
+  }
+
+  return rawData;
+
+};
+
+},{"../../array/sort.coffee":36,"../fetch/color.coffee":64,"../fetch/text.js":67,"../fetch/value.coffee":68,"./nest.js":61}],63:[function(require,module,exports){
+var sizes;
+
+sizes = require("../../font/sizes.coffee");
+
+module.exports = function(vars, opts) {
+  var f, format, func, getFormat, limit, locale, p, periods, pp, prev, render, small, step, style, time, total, vals, values;
+  values = opts.values || vars.data.time.ticks;
+  style = opts.style || {};
+  limit = opts.limit || vars.width.value;
+  time = {};
+  periods = vars.data.time.periods;
+  step = vars.data.time.stepType;
+  total = vars.data.time.totalType;
+  func = vars.data.time.functions;
+  getFormat = vars.data.time.getFormat;
+  locale = vars.format.locale.value.format;
+  if (vars.time.format.value) {
+    time.format = vars.data.time.format;
+    time.values = values;
+    time.sizes = sizes(values.map(function(v) {
+      return time.format(v);
+    }), style);
+  } else {
+    p = periods.indexOf(step);
+    while (p <= periods.indexOf(total)) {
+      vals = values.filter(function(t) {
+        var match, pp;
+        if (p === periods.indexOf(step)) {
+          return true;
+        }
+        match = true;
+        pp = p - 1;
+        if (p < 0) {
+          return true;
+        }
+        while (pp >= periods.indexOf(step)) {
+          if (!match) {
+            break;
+          }
+          match = !func[pp](t);
+          pp--;
+        }
+        return match;
+      });
+      if (periods[p] === total) {
+        format = d3.locale(locale).timeFormat(getFormat(periods[p], total));
+      } else {
+        pp = p;
+        format = [];
+        while (pp <= periods.indexOf(total)) {
+          prev = pp - 1 < periods.indexOf(step) ? pp : pp - 1;
+          prev = periods[prev];
+          small = periods[pp] === prev && step !== total;
+          f = getFormat(prev, periods[pp], small);
+          format.push([f, func[pp]]);
+          pp++;
+        }
+        format[format.length - 1][1] = function() {
+          return true;
+        };
+        format = d3.locale(locale).timeFormat.multi(format);
+      }
+      render = sizes(vals.map(function(v) {
+        return format(v);
+      }), style);
+      if (d3.sum(render, function(r) {
+        return r.width;
+      }) < limit || p === periods.indexOf(total)) {
+        time.format = format;
+        time.values = vals;
+        time.sizes = render;
+        break;
+      }
+      p++;
+    }
+  }
+  return time;
+};
+
+
+},{"../../font/sizes.coffee":101}],64:[function(require,module,exports){
+var fetchValue, getColor, getRandom, randomColor, uniques, validColor, validObject;
+
+fetchValue = require("./value.coffee");
+
+randomColor = require("../../color/random.coffee");
+
+validColor = require("../../color/validate.coffee");
+
+validObject = require("../../object/validate.coffee");
+
+uniques = require("../../util/uniques.coffee");
+
+module.exports = function(vars, id, level) {
+  var color, colorLevel, colors, i, obj, value;
+  obj = validObject(id);
+  if (obj && "d3plus" in id && "color" in id.d3plus) {
+    return id.d3plus.color;
+  }
+  if (level === void 0) {
+    level = vars.id.value;
+  }
+  if (typeof level === "number") {
+    level = vars.id.nesting[level];
+  }
+  if (!vars.color.value) {
+    return getRandom(vars, id, level);
+  } else {
+    colors = [];
+    i = vars.id.nesting.indexOf(level);
+    while (i >= 0) {
+      colorLevel = vars.id.nesting[i];
+      value = uniques(id, vars.color.value, fetchValue, vars, colorLevel);
+      if (value.length === 1) {
+        value = value[0];
+      }
+      if (!(value instanceof Array) && value !== void 0 && value !== null) {
+        color = getColor(vars, id, value, level);
+        if (colors.indexOf(color) < 0) {
+          colors.push(color);
+        }
+        break;
+      }
+      i--;
+    }
+    if (colors.length === 1) {
+      return colors[0];
+    } else {
+      return vars.color.missing;
+    }
+  }
+};
+
+getColor = function(vars, id, color, level) {
+  if (!color) {
+    if (vars.color.value && typeof vars.color.valueScale === "function") {
+      return vars.color.valueScale(0);
+    }
+    return getRandom(vars, id, level);
+  } else if (!vars.color.valueScale) {
+    if (validColor(color)) {
+      return color;
+    } else {
+      return getRandom(vars, color, level);
+    }
+  } else {
+    return vars.color.valueScale(color);
+  }
+};
+
+getRandom = function(vars, c, level) {
+  if (validObject(c)) {
+    c = fetchValue(vars, c, level);
+  }
+  if (c instanceof Array) {
+    c = c[0];
+  }
+  return randomColor(c, vars.color.scale.value);
+};
+
+
+},{"../../color/random.coffee":48,"../../color/validate.coffee":52,"../../object/validate.coffee":171,"../../util/uniques.coffee":209,"./value.coffee":68}],65:[function(require,module,exports){
+var dataFilter = require("../data/filter.js"),
+    dataNest     = require("../data/nest.js"),
+    print        = require("../console/print.coffee"),
+    stringFormat = require("../../string/format.js"),
+    stringList   = require("../../string/list.coffee");
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Fetches specific years of data
+//-------------------------------------------------------------------
+module.exports = function(vars, years, depth) {
+
+  if (!vars.data.value) return [];
+
+  if (depth === undefined) depth = vars.depth.value;
+  var nestLevel = vars.id.nesting[depth];
+
+  if (years && !(years instanceof Array)) years = [years];
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // If "years" have not been requested, determine the years using .time()
+  // solo and mute
+  //----------------------------------------------------------------------------
+  if (!years && "time" in vars) {
+
+    years = [];
+
+    var key = vars.time.solo.value.length ? "solo" : "mute",
+        filterList = vars.time[key].value;
+
+    if (filterList.length) {
+
+      years = [];
+      for (var yi = 0; yi < filterList.length; yi++) {
+        var y = filterList[yi];
+
+        if (typeof y === "function") {
+          for (var ti = 0; ti < vars.data.time.values.length; ti++) {
+            var ms = vars.data.time.values[ti].getTime();
+            if (y(ms)) years.push(ms);
+          }
+        }
+        else if (y.constructor === Date) {
+          years.push(new Date(y).getTime());
+        }
+        else {
+          y += "";
+          if (y.length === 4 && parseInt(y)+"" === y) y = y + "/01/01";
+          var d = new Date(y);
+          if (d !== "Invalid Date") {
+            // d.setTime(d.getTime() + d.getTimezoneOffset() * 60 * 1000);
+            years.push(d.getTime());
+          }
+        }
+
+      }
+
+      if ( key === "mute" ) {
+        years = vars.data.time.values.filter(function( t ){
+          return years.indexOf(t.getTime()) < 0;
+        });
+      }
+
+    }
+    else years.push("all");
+
+  }
+  else {
+    years = ["all"];
+  }
+
+  if (years.indexOf("all") >= 0 && vars.data.time.values.length) {
+    years = vars.data.time.values.slice(0);
+    for (var i = 0; i < years.length; i++) {
+      years[i] = years[i].getTime();
+    }
+  }
+
+  var cacheID = [ vars.type.value , nestLevel , depth ]
+                  .concat( vars.data.filters )
+                  .concat( years ),
+      filter  = vars.data.solo.length ? "solo" : "mute",
+      cacheKeys = d3.keys(vars.data.cache),
+      vizFilter = vars.types[vars.type.value].filter || undefined;
+
+  if ( vars.data[filter].length ) {
+    for (var di = 0; di < vars.data[filter].length; di++) {
+      var f = vars.data[filter][di];
+      var vals = vars[f][filter].value.slice(0);
+      vals.unshift(f);
+      cacheID = cacheID.concat(vals);
+    }
+  }
+
+  if (vars.axes && vars.axes.discrete) cacheID.push(vars.axes.discrete);
+
+  cacheID = cacheID.join("_");
+  vars.data.cacheID = cacheID;
+
+  var match = false;
+
+  for (var c = 0 ; c < cacheKeys.length ; c++) {
+
+    var matchKey = cacheKeys[c].split("_").slice(1).join("_");
+
+    if ( matchKey === cacheID ) {
+      cacheID = new Date().getTime() + "_" + cacheID;
+      vars.data.cache[cacheID] = vars.data.cache[cacheKeys[c]];
+      delete vars.data.cache[cacheKeys[c]];
+      break;
+    }
+
+  }
+
+  var returnData;
+
+  if ( vars.data.cache[cacheID] ) {
+
+    if ( vars.dev.value ) print.comment("data already cached");
+
+    returnData = vars.data.cache[cacheID];
+
+    if ( typeof vizFilter === "function" ) {
+      returnData = vizFilter( vars ,  returnData );
+    }
+
+    return returnData;
+
+  }
+  else {
+
+    var missing = [];
+    returnData = [];
+
+    if (vars.data.value && vars.data.value.length) {
+
+      for (var yz = 0; yz < years.length; yz++) {
+        var year = years[yz];
+        if (vars.data.nested[year]) {
+          returnData = returnData.concat(vars.data.nested[year][nestLevel]);
+        }
+        else {
+          missing.push(year);
+        }
+      }
+
+    }
+
+    if (returnData.length === 0 && missing.length && !vars.error.internal) {
+
+      if (missing.length > 1) {
+        missing = d3.extent(missing);
+      }
+
+      missing = missing.map(function(m){
+        return vars.data.time.format(new Date(m));
+      });
+      missing = missing.join(" - ");
+
+      var str = vars.format.locale.value.error.dataYear,
+          and = vars.format.locale.value.ui.and;
+      missing = stringList(missing,and);
+      vars.error.internal = stringFormat(str,missing);
+      vars.time.missing = true;
+
+    }
+    else {
+
+      if (vars.time) vars.time.missing = false;
+
+      if ( years.length > 1 ) {
+
+        var separated = false;
+        ["x","y"].forEach(function(a){
+          if (vars[a].value === vars.time.value &&
+              vars[a].scale.value === "discrete" ) {
+            separated = true;
+          }
+        });
+
+        if (!separated) {
+          var nested = vars.id.nesting.slice(0,depth+1);
+          returnData = dataNest(vars, returnData, nested);
+        }
+
+      }
+
+      if (!returnData) {
+        returnData = [];
+      }
+      else {
+        returnData = dataFilter(vars, returnData);
+      }
+
+      if ( cacheKeys.length === 20 ) {
+        cacheKeys.sort();
+        delete vars.data.cache[cacheKeys[0]];
+      }
+
+      cacheID = new Date().getTime() + "_" + cacheID;
+      vars.data.cache[cacheID] = returnData;
+
+      if ( typeof vizFilter === "function" ) {
+        returnData = vizFilter( vars , returnData );
+      }
+
+      if ( vars.dev.value ) print.comment("storing data in cache");
+
+    }
+
+    return returnData;
+
+  }
+
+};
+
+},{"../../string/format.js":172,"../../string/list.coffee":173,"../console/print.coffee":53,"../data/filter.js":56,"../data/nest.js":61}],66:[function(require,module,exports){
+var fetchColor, fetchText, fetchValue;
+
+fetchValue = require("./value.coffee");
+
+fetchColor = require("./color.coffee");
+
+fetchText = require("./text.js");
+
+module.exports = function(vars, d, keys, colors, depth) {
+  var i, key, len, obj, value;
+  if (!(keys instanceof Array)) {
+    keys = [keys];
+  }
+  if (!(colors instanceof Array)) {
+    colors = [colors];
+  }
+  if (vars && depth !== void 0 && typeof depth !== "number") {
+    depth = vars.id.nesting.indexOf(depth);
+  }
+  obj = {};
+  for (i = 0, len = keys.length; i < len; i++) {
+    key = keys[i];
+    if (vars) {
+      if (colors.indexOf(key) >= 0) {
+        value = fetchColor(vars, d, depth);
+      } else if (key === vars.text.value) {
+        value = fetchText(vars, d, depth);
+      } else {
+        value = fetchValue(vars, d, key, depth);
+      }
+    } else {
+      value = d[key];
+    }
+    if (value instanceof Array) {
+      value = value[0];
+    }
+    value = typeof value === "string" ? value.toLowerCase() : value;
+    obj[key] = value;
+  }
+  return obj;
+};
+
+
+},{"./color.coffee":64,"./text.js":67,"./value.coffee":68}],67:[function(require,module,exports){
+var fetchValue = require("./value.coffee"),
+    validObject = require("../../object/validate.coffee"),
+    uniques     = require("../../util/uniques.coffee");
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Get array of available text values
+//------------------------------------------------------------------------------
+module.exports = function(vars, obj, depth) {
+
+  if (typeof depth !== "number") depth = vars.depth.value;
+
+  var key = vars.id.nesting[depth], textKeys;
+
+  if ( vars.text.nesting && validObject(vars.text.nesting) ) {
+    if ( vars.text.nesting[key] ) {
+      textKeys = vars.text.nesting[key];
+    }
+    else {
+      textKeys = vars.text.value;
+    }
+  }
+  else {
+    textKeys = [];
+    if (vars.text.value && depth === vars.depth.value) textKeys.push(vars.text.value);
+    textKeys.push(key);
+  }
+
+  if ( !(textKeys instanceof Array) ) {
+    textKeys = [ textKeys ];
+  }
+
+  var names = [];
+
+  if (validObject(obj) && "d3plus" in obj && obj.d3plus.text) {
+    names.push(obj.d3plus.text.toString());
+    names.push(vars.format.value(obj.d3plus.text.toString(), {"vars": vars, "data": obj}));
+  }
+  else {
+
+    var formatObj = validObject(obj) ? obj : undefined;
+
+    if (formatObj && obj[vars.id.value] instanceof Array) {
+      obj = obj[vars.id.value];
+    }
+    else if (!(obj instanceof Array)) {
+      obj = [obj];
+    }
+
+    textKeys.forEach(function( t ){
+
+      var name = uniques(obj, t, fetchValue, vars, key);
+
+      if ( name.length ) {
+        if (name.length > 1) {
+          name = name.filter(function(n){
+            return (n instanceof Array) || (typeof n === "string" && n.indexOf(" < ") < 0);
+          });
+        }
+        name = name.map(function(n){
+          if (n instanceof Array) {
+            n = n.filter(function(nn){ return nn; });
+            return n.map(function(nn){
+              return vars.format.value(nn.toString(), {"vars": vars, "data": formatObj, "key": t});
+            });
+          }
+          else if (n) {
+            return vars.format.value(n.toString(), {"vars": vars, "data": formatObj, "key": t});
+          }
+        });
+        if (name.length === 1) name = name[0];
+        names.push(name);
+      }
+
+    });
+
+  }
+
+  return names;
+
+};
+
+},{"../../object/validate.coffee":171,"../../util/uniques.coffee":209,"./value.coffee":68}],68:[function(require,module,exports){
+var cacheInit, checkAttrs, checkData, fetch, fetchArray, filterArray, find, uniqueValues, validObject, valueParse;
+
+validObject = require("../../object/validate.coffee");
+
+uniqueValues = require("../../util/uniques.coffee");
+
+find = function(vars, node, variable, depth) {
+  var cache, nodeObject, returned, val;
+  nodeObject = validObject(node);
+  if (typeof variable === "function" && nodeObject) {
+    return variable(node, vars);
+  }
+  if (nodeObject) {
+    if (variable in node) {
+      return node[variable];
+    }
+    cache = vars.data.cacheID + "_" + depth;
+    cacheInit(node, cache, vars);
+    if (variable in node.d3plus.data[cache]) {
+      return node.d3plus.data[cache][variable];
+    }
+    if (depth in node) {
+      node = node[depth];
+    } else if (vars.id.value in node) {
+      node = node[vars.id.value];
+      if (depth !== variable) {
+        returned = checkData(vars, node, depth, vars.id.value);
+      }
+      if (returned === null) {
+        returned = checkAttrs(vars, node, depth, vars.id.value);
+      }
+      if (returned === null) {
+        return null;
+      }
+      node = returned;
+    } else {
+      return null;
+    }
+  }
+  if (node instanceof Array && !validObject(node[0])) {
+    node = uniqueValues(node);
+  }
+  if (node instanceof Array && validObject(node[0])) {
+    val = uniqueValues(node, variable);
+    if (val.length) {
+      return val;
+    }
+  }
+  val = checkData(vars, node, variable, depth);
+  if (val) {
+    return val;
+  }
+  val = checkAttrs(vars, node, variable, depth);
+  return val;
+};
+
+checkData = function(vars, node, variable, depth) {
+  var val;
+  if (vars.data.viz instanceof Array && variable in vars.data.keys) {
+    val = uniqueValues(filterArray(vars.data.viz, node, depth), variable);
+  }
+  if (val && val.length) {
+    return val;
+  } else {
+    return null;
+  }
+};
+
+checkAttrs = function(vars, node, variable, depth) {
+  var attrList, n, val, vals;
+  if ("attrs" in vars && vars.attrs.value && variable in vars.attrs.keys) {
+    if (validObject(vars.attrs.value) && depth in vars.attrs.value) {
+      attrList = vars.attrs.value[depth];
+    } else {
+      attrList = vars.attrs.value;
+    }
+    if (attrList instanceof Array) {
+      val = uniqueValues(filterArray(attrList, node, depth), variable);
+      if (val.length) {
+        return val;
+      }
+    } else if (node instanceof Array) {
+      attrList = [
+        (function() {
+          var j, len, results;
+          if (n in attrList) {
+            results = [];
+            for (j = 0, len = node.length; j < len; j++) {
+              n = node[j];
+              results.push(attrList[n]);
+            }
+            return results;
+          }
+        })()
+      ];
+      if (attrList.length) {
+        vals = uniqueValues(attrList, variable);
+        if (vals.length) {
+          return vals;
+        }
+      }
+    } else if (node in attrList) {
+      return attrList[node][variable];
+    }
+  }
+  return null;
+};
+
+filterArray = function(arr, node, depth) {
+  if (node instanceof Array) {
+    return arr.filter(function(d) {
+      return node.indexOf(d[depth]) >= 0;
+    });
+  } else {
+    return arr.filter(function(d) {
+      return d[depth] === node;
+    });
+  }
+};
+
+cacheInit = function(node, cache, vars) {
+  if (!("d3plus" in node)) {
+    node.d3plus = {};
+  }
+  if (!("data" in node.d3plus)) {
+    node.d3plus.data = {};
+  }
+  if (vars.data.changed || (vars.attrs && vars.attrs.changed) || !(cache in node.d3plus.data)) {
+    node.d3plus.data[cache] = {};
+  }
+  return node;
+};
+
+valueParse = function(vars, node, depth, variable, val) {
+  var cache, d, i, j, len, timeVar, v;
+  if (val === null) {
+    return val;
+  }
+  timeVar = "time" in vars && vars.time.value === variable;
+  if (!(val instanceof Array)) {
+    val = [val];
+  }
+  for (i = j = 0, len = val.length; j < len; i = ++j) {
+    v = val[i];
+    if (timeVar && v !== null && v.constructor !== Date) {
+      v = v + "";
+      if (v.length === 4 && parseInt(v) + "" === v) {
+        v += "/01/01";
+      }
+      d = new Date(v);
+      if (d !== "Invalid Date") {
+        val[i] = d;
+      }
+    }
+  }
+  if (val.length === 1) {
+    val = val[0];
+  }
+  if (val !== null && validObject(node) && typeof variable === "string" && !(variable in node)) {
+    cache = vars.data.cacheID + "_" + depth;
+    node.d3plus.data[cache][variable] = val;
+  }
+  return val;
+};
+
+fetchArray = function(vars, arr, variable, depth) {
+  var item, j, len, v, val;
+  val = [];
+  for (j = 0, len = arr.length; j < len; j++) {
+    item = arr[j];
+    if (validObject(item)) {
+      v = find(vars, item, variable, depth);
+      val.push(valueParse(vars, item, depth, variable, v));
+    } else {
+      val.push(item);
+    }
+  }
+  if (typeof val[0] !== "number") {
+    val = uniqueValues(val);
+  }
+  if (val.length === 1) {
+    return val[0];
+  } else {
+    return val;
+  }
+};
+
+fetch = function(vars, node, variable, depth) {
+  var nodeObject, val;
+  if (!variable) {
+    return null;
+  }
+  if (typeof variable === "number") {
+    return variable;
+  }
+  nodeObject = validObject(node);
+  if (!depth) {
+    depth = vars.id.value;
+  }
+  if (nodeObject && node.values instanceof Array) {
+    val = fetchArray(vars, node.values, variable, depth);
+  } else if (nodeObject && node[variable] instanceof Array) {
+    val = fetchArray(vars, node[variable], variable, depth);
+  } else if (node instanceof Array) {
+    val = fetchArray(vars, node, variable, depth);
+  } else {
+    val = find(vars, node, variable, depth);
+    val = valueParse(vars, node, depth, variable, val);
+  }
+  return val;
+};
+
+module.exports = fetch;
+
+
+},{"../../object/validate.coffee":171,"../../util/uniques.coffee":209}],69:[function(require,module,exports){
+module.exports = function(type) {
+  var attrs, styles, tester;
+  if (["div", "svg"].indexOf(type) < 0) {
+    type = "div";
+  }
+  styles = {
+    position: "absolute",
+    left: "-9999px",
+    top: "-9999px",
+    visibility: "hidden",
+    display: "block"
+  };
+  attrs = type === "div" ? {} : {
+    position: "absolute"
+  };
+  tester = d3.select("body").selectAll(type + ".d3plus_tester").data([0]);
+  tester.enter().append(type).attr("class", "d3plus_tester").style(styles).attr(attrs);
+  return tester;
+};
+
+
+},{}],70:[function(require,module,exports){
+module.exports = {
+  dev: {
+    accepted: "{0} is not an accepted value for {1}, please use one of the following: {2}.",
+    deprecated: "the {0} method has been removed, please update your code to use {1}.",
+    noChange: "{0} was not updated because it did not change.",
+    noContainer: "cannot find a container on the page matching {0}.",
+    of: "of",
+    oldStyle: "style properties for {0} have now been embedded directly into .{1}().",
+    sameEdge: "edges cannot link to themselves. automatically removing self-referencing edge {0}.",
+    set: "{0} has been set.",
+    setLong: "{0} has been set to {1}.",
+    setContainer: "please define a container div using .container()"
+  },
+  error: {
+    accepted: "{0} is not an accepted {1} for {2} visualizations, please use one of the following: {3}.",
+    connections: "no connections available for {0}.",
+    data: "no data available",
+    dataYear: "no data available for {0}.",
+    lib: "{0} visualizations require loading the {1} library.",
+    libs: "{0} visualizations require loading the following libraries: {1}.",
+    method: "{0} visualizations require setting the {1} method.",
+    methods: "{0} visualizations require setting the following methods: {1}."
+  },
+  format: {
+    decimal: ".",
+    thousands: ",",
+    grouping: [3],
+    currency: ["$", ""],
+    dateTime: "%A, %B %-d, %Y %X",
+    date: "%-m/%-d/%Y",
+    time: "%I:%M:%S %p",
+    periods: ["AM", "PM"],
+    days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+    shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+    months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+    shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
+  },
+  lowercase: ["a", "an", "and", "as", "at", "but", "by", "for", "from", "if", "in", "into", "near", "nor", "of", "on", "onto", "or", "per", "that", "the", "to", "with", "via", "vs", "vs."],
+  message: {
+    data: "analyzing data",
+    draw: "drawing visualization",
+    initializing: "initializing {0}",
+    loading: "loading data",
+    tooltipReset: "resetting tooltips",
+    ui: "updating ui"
+  },
+  method: {
+    active: "active segments",
+    color: "color",
+    depth: "depth",
+    dev: "verbose",
+    focus: "focus",
+    icon: "icon",
+    id: "id",
+    height: "height",
+    labels: "labels",
+    legend: "legend",
+    margin: "margin",
+    messages: "status messages",
+    mode: "mode",
+    mute: "hide",
+    order: "order",
+    search: "search",
+    shape: "shape",
+    size: "size",
+    solo: "isolate",
+    style: "style",
+    temp: "temporary segments",
+    text: "text",
+    time: "time",
+    timeline: "timeline",
+    total: "total segments",
+    type: "type",
+    width: "width",
+    x: "x axis",
+    y: "y axis",
+    zoom: "zoom"
+  },
+  time: ["date", "day", "month", "time", "year"],
+  timeFormat: {
+    FullYear: "%Y",
+    Month: "%B",
+    MonthSmall: "%b",
+    Date: "%A %-d",
+    DateSmall: "%-d",
+    Hours: "%I %p",
+    Minutes: "%I:%M",
+    Seconds: "%Ss",
+    Milliseconds: "%Lms",
+    "FullYear-Month": "%b %Y",
+    "FullYear-Date": "%-m/%-d/%Y",
+    "Month-Date": "%b %-d",
+    "Hours-Minutes": "%I:%M %p",
+    "Hours-Seconds": "%I:%M:%S %p",
+    "Hours-Milliseconds": "%H:%M:%S.%L",
+    "Minutes-Seconds": "%I:%M:%S %p",
+    "Minutes-Milliseconds": "%H:%M:%S.%L",
+    "Seconds-Milliseconds": "%H:%M:%S.%L"
+  },
+  ui: {
+    and: "and",
+    back: "back",
+    collapse: "click to collapse",
+    error: "error",
+    expand: "click to expand",
+    including: "including",
+    loading: "loading...",
+    more: "{0} more",
+    moreInfo: "click for more info",
+    or: "or",
+    noResults: "no results matching {0}.",
+    primary: "primary connections",
+    share: "share",
+    total: "total",
+    values: "values"
+  },
+  uppercase: ["CEO", "CEOs", "CFO", "CFOs", "CNC", "COO", "COOs", "CPU", "CPUs", "GDP", "HVAC", "ID", "IT", "R&D", "TV", "UI"],
+  visualization: {
+    bar: "Bar Chart",
+    box: "Box Plot",
+    bubbles: "Bubbles",
+    chart: "Chart",
+    geo_map: "Geo Map",
+    line: "Line Plot",
+    network: "Network",
+    paths: "Paths",
+    pie: "Pie Chart",
+    rings: "Rings",
+    scatter: "Scatter Plot",
+    stacked: "Stacked Area",
+    table: "Table",
+    tree_map: "Tree Map"
+  }
+};
+
+
+},{}],71:[function(require,module,exports){
+module.exports = {
+    "format": {
+        "decimal": ",",
+        "thousands": ".",
+        "grouping": [3],
+        "currency": ["", " €"],
+        "dateTime": "%A, %e de %B de %Y, %X",
+        "date": "%d/%m/%Y",
+        "time": "%H:%M:%S",
+        "periods": ["AM", "PM"],
+        "days": ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"],
+        "shortDays": ["dom", "lun", "mar", "mié", "jue", "vie", "sáb"],
+        "months": ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"],
+        "shortMonths": ["ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic"]
+    },
+    "dev": {
+        "accepted": "{0} no es un valor aceptado para {1}, por favor utilice uno de los siguientes: {2}.",
+        "deprecated": "el método {0} ha sido eliminado, por favor, actualiza tu código para utilizar {1}.",
+        "noChange": "{0} no se actualiza porque no cambió.",
+        "noContainer": "no se puede encontrar un contenedor en la página correspondiente a {0}.",
+        "of": "de",
+        "oldStyle": "propiedades de estilo para {0} ahora se han incorporado directamente en. {1} ().",
+        "sameEdge": "los vínculos no se pueden enlazar con si mismos. eliminando automáticamente el vínculo {0} que se autorreferencia.",
+        "set": "{0} se ha establecido.",
+        "setLong": "{0} ha sido establecido a {1}.",
+        "setContainer": "defina un div contenedor utilizando .container ()"
+    },
+    "error": {
+        "accepted": "{0} no es un {1} aceptado para visualizaciones de {2}, por favor utilice uno de los siguientes: {3}.",
+        "connections": "no hay conexiones disponibles para {0}.",
+        "data": "No hay datos disponibles",
+        "dataYear": "no hay datos disponibles para {0}.",
+        "lib": "{0} visualizaciones requieren cargar las siguientes librerías: {1}.",
+        "libs": "{0} visualizaciones requieren cargar las siguientes librerías: {1}.",
+        "method": "{0} visualizaciones requieren establecer el ​​método {1}.",
+        "methods": "{0} visualizaciones requieren establecer los siguientes métodos: {1}."
+    },
+    "lowercase": [
+        "una",
+        "y",
+        "en",
+        "pero",
+        "en",
+        "de",
+        "o",
+        "el",
+        "la",
+        "los",
+        "las",
+        "para",
+        "a",
+        "con"
+    ],
+    "method": {
+        "active": "segmentos activos",
+        "color": "color",
+        "depth": "profundidad",
+        "dev": "detallado",
+        "focus": "foco",
+        "icon": "ícono",
+        "id": "id",
+        "height": "alto",
+        "labels": "rótulo",
+        "legend": "leyenda",
+        "margin": "margen",
+        "messages": "mensajes de estado",
+        "mute": "ocultar",
+        "order": "orden",
+        "search": "búsqueda",
+        "shape": "forma",
+        "size": "tamaño",
+        "solo": "aislar",
+        "style": "estilo",
+        "temp": "segmentos temporales",
+        "text": "texto",
+        "time": "tiempo",
+        "timeline": "línea de tiempo",
+        "total": "segmentos totales",
+        "type": "tipo",
+        "width": "anchura",
+        "x": "eje x",
+        "y": "eje Y",
+        "zoom": "#ERROR!",
+        "mode": "modo"
+    },
+    "time": [
+        "fecha",
+        "día",
+        "mes",
+        "hora",
+        "año"
+    ],
+    "visualization": {
+        "bubbles": "Burbujas",
+        "chart": "Tabla",
+        "geo_map": "Mapa Geo",
+        "line": "Línea Solar",
+        "network": "Red",
+        "rings": "Anillos",
+        "scatter": "Gráfico De Dispersión",
+        "stacked": "Área Apilada",
+        "tree_map": "Mapa de Árbol",
+        "bar": "Gráfico De Barras",
+        "box": "Diagrama de Cajas",
+        "paths": "Caminos",
+        "pie": "Gráfico de Pastel",
+        "table": "Tabla"
+    },
+    "ui": {
+        "and": "y",
+        "back": "atrás",
+        "collapse": "click para cerrar",
+        "error": "error",
+        "expand": "haga clic para ampliar",
+        "loading": "Cargando ...",
+        "more": "{0} más",
+        "moreInfo": "clic para más información",
+        "noResults": "no se encontraron resultados para {0}.",
+        "primary": "relaciones principales",
+        "share": "porcentaje",
+        "total": "total",
+        "values": "valores",
+        "including": "Incluyendo",
+        "or": "o"
+    },
+    "message": {
+        "data": "analizando los datos",
+        "draw": "visualizando",
+        "initializing": "inicializando {0}",
+        "loading": "cargando datos",
+        "tooltipReset": "restableciendo las descripciones emergentes",
+        "ui": "actualizando la interfaz de usuario"
+    },
+    "uppercase": [
+        "CEO",
+        "CEOs",
+        "CFO",
+        "CFOs",
+        "CNC",
+        "COO",
+        "COOs",
+        "CPU",
+        "CPUs",
+        "PIB",
+        "HVAC",
+        "ID",
+        "TI",
+        "I&D",
+        "TV",
+        "UI"
+    ]
+}
+
+},{}],72:[function(require,module,exports){
+module.exports = {
+    "format": {
+        "decimal": ",",
+        "thousands": ".",
+        "grouping": [3],
+        "currency": ["", " €"],
+        "dateTime": "%A, le %e %B %Y, %X",
+        "date": "%d/%m/%Y",
+        "time": "%H:%M:%S",
+        "periods": ["AM", "PM"], // unused
+        "days": ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"],
+        "shortDays": ["dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam."],
+        "months": ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"],
+        "shortMonths": ["janv.", "févr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc."]
+    },
+    "dev": {
+        "accepted": "{0} n'est pas une option valide pour {1}, les valeurs possibles sont: {2}.",
+        "deprecated": "{0} a été éliminé de la version courante, mettez à jour votre code source avec {1}.",
+        "noChange": "{0} n'a pas été mis à jour car inchangé.",
+        "noContainer": "impossible de trouver un contenant correspondant à {0}.",
+        "of": "de",
+        "oldStyle": "les propriétés de {0} ont été imbriquées dans .{1}().",
+        "sameEdge": "un arc ne peut pas boucler sur lui même. L'auto-référence est automatiquement éliminée {0}.",
+        "set": "{0} a été mis à jour.",
+        "setLong": "{0} a été mis à jour à {1}.",
+        "setContainer": "merci de choisir un div qui utilise .container()"
+    },
+    "error": {
+        "accepted": "{0} n'est pas correct {1} pour {2} visualisations, merci d'utilisez une des options suivantes: {3}.",
+        "connections": "Pas de connections disponibles pour {0}.",
+        "data": "Pas de données disponibles",
+        "dataYear": "Pas de données disponibles pour {0}.",
+        "lib": "La visualisation de {0} nécessite le chargement de la librairie {1}.",
+        "libs": "La visualisation de {0} nécessite le chargement des librairies {1}.",
+        "method": "La visualisation du {0} exige la définition de {1}.",
+        "methods": "La visualisation du {0} exige les définitions de {1}."
+    },
+    "lowercase": [
+        "un",
+        "une",
+        "de",
+        "des",
+        "et",
+        "mais",
+        "les",
+        "ou",
+        "pour",
+        "avec",
+        "comme",
+        "par",
+        "vers",
+        "si",
+        "dans",
+        "près",
+        "ni",
+        "dessus",
+        "que",
+        "le",
+        "la",
+        "via",
+        "sinon",
+        "alors"
+    ],
+    "method": {
+        "active": "segments actifs",
+        "color": "couleur",
+        "depth": "profondeur",
+        "dev": "verbeux",
+        "focus": "focus",
+        "icon": "ícone",
+        "id": "id",
+        "height": "hauteur",
+        "labels": "labels",
+        "legend": "légende",
+        "margin": "marge",
+        "messages": "messages",
+        "mute": "cacher",
+        "order": "ordre",
+        "search": "recherche",
+        "shape": "format",
+        "size": "taille",
+        "solo": "isoler",
+        "style": "style",
+        "temp": "segments temporaires",
+        "text": "texte",
+        "time": "temps",
+        "timeline": "ligne temporelle",
+        "total": "segments totaux",
+        "type": "type",
+        "width": "largeur",
+        "x": "axe x",
+        "y": "axe y",
+        "zoom": "zoom",
+        "mode": "mode"
+    },
+    "time": [
+        "année",
+        "date",
+        "jour",
+        "heure",
+        "mois"
+    ],
+    "visualization": {
+        "bubbles": "Bulles",
+        "chart": "Graphique",
+        "geo_map": "Carte",
+        "line": "Courbes",
+        "network": "Réseau",
+        "rings": "Anneaux",
+        "scatter": "Nuage de points",
+        "stacked": "Aires empilées",
+        "tree_map": "Arbre",
+        "bar": "Diagramme en barres",
+        "box": "Boîtes à Moustaches",
+        "paths": "Chemins",
+        "pie": "Camembert",
+        "table": "Table"
+    },
+    "ui": {
+        "and": "et",
+        "back": "retour",
+        "collapse": "clic pour réduire",
+        "error": "erreur",
+        "expand": "clic pour agrandir",
+        "loading": "chargement ...",
+        "more": "plus {0}",
+        "moreInfo": "clic pour plus d'information",
+        "noResults": "pas de résultat correspondant à {0}.",
+        "primary": "connections primaires",
+        "share": "part",
+        "total": "total",
+        "values": "valeurs",
+        "including": "incluant",
+        "or": "ou"
+    },
+    "message": {
+        "data": "analyse des données",
+        "draw": "tracé en cours",
+        "initializing": "Initialisation {0}",
+        "loading": "chargement",
+        "tooltipReset": "réinitialisation des bulles",
+        "ui": "rafraichissement de l'interface"
+    },
+    "uppercase": [
+        "CEO",
+        "CEOs",
+        "CFO",
+        "CFOs",
+        "CNC",
+        "COO",
+        "COOs",
+        "CPU",
+        "CPUs",
+        "PIB",
+        "HVAC",
+        "ID",
+        "IT",
+        "TV",
+        "UI"
+    ]
+}
+
+},{}],73:[function(require,module,exports){
+module.exports = {
+    "format": {
+        "decimal": ",",
+        "thousands": ".",
+        "grouping": [3],
+        "currency": ["", " ден."],
+        "dateTime": "%A, %e %B %Y г. %X",
+        "date": "%d.%m.%Y",
+        "time": "%H:%M:%S",
+        "periods": ["AM", "PM"],
+        "days": ["недела", "понеделник", "вторник", "среда", "четврток", "петок", "сабота"],
+        "shortDays": ["нед", "пон", "вто", "сре", "чет", "пет", "саб"],
+        "months": ["јануари", "февруари", "март", "април", "мај", "јуни", "јули", "август", "септември", "октомври", "ноември", "декември"],
+        "shortMonths": ["јан", "фев", "мар", "апр", "мај", "јун", "јул", "авг", "сеп", "окт", "ное", "дек"]
+    },
+    "dev": {
+        "accepted": "{0} не е прифатенa вредноста за {1}, ве молиме користете еднa од следниве вредности: {2}.",
+        "deprecated": "{0} метод е отстранета, ве молиме обновете го вашиот код за да се користи {1}.",
+        "noChange": "{0} не е ажурирана, бидејќи немаше промени.",
+        "noContainer": "не можe да се најде контејнер на страницата кој се совпаѓа со {0}.",
+        "of": "на",
+        "oldStyle": "својствата за стилот за {0} сега се вградени директно во. {1} ().",
+        "sameEdge": "рабовите не може да имаат алка самите кон себе. автоматски ги отстранувам рабовите кои се само-референцираат {0}.",
+        "set": "{0} е наместен.",
+        "setLong": "{0} е поставен на {1}.",
+        "setContainer": "Ве молиме дефинирајте контејнер div користејќи .container()"
+    },
+    "error": {
+        "accepted": "{0} не е прифатлива за {1} {2} визуелизација, ве молиме користете една од следниве: {3}.",
+        "connections": "не е достапна за врски {0}.",
+        "data": "нема податоци",
+        "dataYear": "Нема достапни податоци за {0}.",
+        "lib": "{0} визуализации бараат вчитување на библиотеката {1} .",
+        "libs": "{0} визуализации бараат вчитување следниве библиотеки: {1}.",
+        "method": "{0} визуализации бара поставување на {1} методот.",
+        "methods": "{0} визуализации бараат поставување на следниве методи: {1}."
+    },
+    "lowercase": [
+        "a",
+        "и",
+        "во",
+        "но",
+        "на",
+        "или",
+        "да",
+        "се",
+        "со"
+    ],
+    "method": {
+        "active": "активни сегменти",
+        "color": "боја",
+        "depth": "длабочина",
+        "dev": "опширно",
+        "focus": "фокус",
+        "icon": "икона",
+        "id": "id",
+        "height": "висина",
+        "labels": "етикети",
+        "legend": "легенда",
+        "margin": "маргина",
+        "messages": "пораки за статусот",
+        "mute": "скрие",
+        "order": "цел",
+        "search": "барај",
+        "shape": "форма",
+        "size": "големина",
+        "solo": "изолирање",
+        "style": "стил",
+        "temp": "привремени сегменти",
+        "text": "текст",
+        "time": "време",
+        "timeline": "времеплов",
+        "total": "Вкупно сегменти",
+        "type": "тип",
+        "width": "ширина",
+        "x": "x оската",
+        "y": "оската y",
+        "zoom": "зум",
+        "mode": "режим"
+    },
+    "time": [
+        "датум",
+        "ден",
+        "месец",
+        "време",
+        "година"
+    ],
+    "visualization": {
+        "bubbles": "Меурчиња",
+        "chart": "Шема",
+        "geo_map": "Гео мапа",
+        "line": "Линиски график",
+        "network": "Мрежа",
+        "rings": "Прстени",
+        "scatter": "Распрскан график",
+        "stacked": "Наредена површина",
+        "tree_map": "Мапа во вид на дрво",
+        "bar": "Бар табела",
+        "box": "Кутија Парцел",
+        "paths": "Патеки",
+        "pie": "Пита графикон",
+        "table": "Табела"
+    },
+    "ui": {
+        "and": "и",
+        "back": "назад",
+        "collapse": "кликни за да се собере",
+        "error": "грешка",
+        "expand": "кликни за да се прошири",
+        "loading": "Се вчитува ...",
+        "more": "{0} повеќе",
+        "moreInfo": "кликнете за повеќе информации",
+        "noResults": "Не се пронајдени појавување на {0}.",
+        "primary": "основно врски",
+        "share": "удел",
+        "total": "Вкупниот",
+        "values": "вредности",
+        "including": "Вклучувајќи",
+        "or": "или"
+    },
+    "message": {
+        "data": "анализа на податоци",
+        "draw": "цртање на визуелизација",
+        "initializing": "иницијализација {0}",
+        "loading": "податоци за вчитување",
+        "tooltipReset": "ресетирање на објаснувањата",
+        "ui": "ажурирање на кориничкиот интерфејс"
+    },
+    "uppercase": [
+        "CEO",
+        "CEOs",
+        "CFO",
+        "CFOs",
+        "CNC",
+        "COO",
+        "COOs",
+        "CPU",
+        "CPUs",
+        "GDP",
+        "HVAC",
+        "ID",
+        "IT",
+        "R&D",
+        "TV",
+        "UI"
+    ]
+}
+
+},{}],74:[function(require,module,exports){
+module.exports = {
+    "format": {
+        "decimal": ",",
+        "thousands": ".",
+        "grouping": [3],
+        "currency": ["R$", ""],
+        "dateTime": "%A, %e de %B de %Y. %X",
+        "date": "%d/%m/%Y",
+        "time": "%H:%M:%S",
+        "periods": ["AM", "PM"],
+        "days": ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"],
+        "shortDays": ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"],
+        "months": ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
+        "shortMonths": ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"]
+    },
+    "dev": {
+        "accepted": "{0} não é um valor válido para {1}, por favor use um dos seguintes procedimentos: {2}.",
+        "deprecated": "{0} método foi removido, por favor atualize seu código para utilizar {1}.",
+        "noChange": "{0} não foi atualizado porque ele não mudou.",
+        "noContainer": "Não foi possível encontrar um local na página correspondente a {0}.",
+        "of": "de",
+        "oldStyle": "propriedades de estilo para {0} já foi incorporado diretamente no. {1} ().",
+        "sameEdge": "bordas não podem vincular a si mesmos. removendo automaticamente borda de auto-referência {0}.",
+        "set": "{0} foi definido.",
+        "setLong": "{0} foi definida para {1}.",
+        "setContainer": "por favor, defina um div utilizando .container()"
+    },
+    "error": {
+        "accepted": "{0} não é um {1} reconhecido para visualizações {2}, favor usar um dos seguintes procedimentos: {3}.",
+        "connections": "Não há conexões disponíveis para {0}.",
+        "data": "Não há dados disponíveis",
+        "dataYear": "Não há dados disponíveis para {0}.",
+        "lib": "A visualização {0} necessita que seja carregado a biblioteca {1}.",
+        "libs": "A visualização {0} necessita que seja carregado as bibliotecas {1}.",
+        "method": "A visualização {0} exige a definição do método {1}.",
+        "methods": "A visualização {0} exige a definição dos métodos {1}."
+    },
+    "lowercase": [
+        "um",
+        "uma",
+        "e",
+        "como",
+        "em",
+        "no",
+        "na",
+        "mas",
+        "por",
+        "para",
+        "pelo",
+        "pela",
+        "de",
+        "do",
+        "da",
+        "se",
+        "perto",
+        "nem",
+        "ou",
+        "que",
+        "o",
+        "a",
+        "com",
+        "v"
+    ],
+    "method": {
+        "active": "segmentos activos",
+        "color": "cor",
+        "depth": "profundidade",
+        "dev": "verboso",
+        "focus": "foco",
+        "icon": "ícone",
+        "id": "identificador",
+        "height": "altura",
+        "labels": "etiquetas",
+        "legend": "legenda",
+        "margin": "margem",
+        "messages": "mensagens de status",
+        "mute": "ocultar",
+        "order": "ordenar",
+        "search": "pesquisar",
+        "shape": "forma",
+        "size": "tamanho",
+        "solo": "isolar",
+        "style": "estilo",
+        "temp": "segmentos temporários",
+        "text": "texto",
+        "time": "tempo",
+        "timeline": "linha do tempo",
+        "total": "segmentos no total",
+        "type": "tipo",
+        "width": "largura",
+        "x": "eixo x",
+        "y": "eixo y",
+        "zoom": "zoom",
+        "mode": "modo"
+    },
+    "time": [
+        "data",
+        "dia",
+        "mês",
+        "hora",
+        "ano"
+    ],
+    "visualization": {
+        "bubbles": "Bolhas",
+        "chart": "Gráfico",
+        "geo_map": "Mapa",
+        "line": "Gráfico de Linha",
+        "network": "Rede",
+        "rings": "Anéis",
+        "scatter": "Dispersão",
+        "stacked": "Evolução",
+        "tree_map": "Tree Map",
+        "bar": "Gráfico de Barras",
+        "box": "Box Plot",
+        "paths": "Caminhos",
+        "pie": "Pie Chart",
+        "table": "Tabela"
+    },
+    "ui": {
+        "and": "e",
+        "back": "voltar",
+        "collapse": "Clique para fechar",
+        "error": "erro",
+        "expand": "clique para expandir",
+        "loading": "carregando ...",
+        "more": "mais {0}",
+        "moreInfo": "Clique para mais informações",
+        "noResults": "nenhum resultado para {0}.",
+        "primary": "conexões primárias",
+        "share": "participação",
+        "total": "total",
+        "values": "valores",
+        "including": "Incluindo",
+        "or": "ou"
+    },
+    "message": {
+        "data": "analisando dados",
+        "draw": "desenhando visualização",
+        "initializing": "inicializando {0}",
+        "loading": "carregando dados",
+        "tooltipReset": "redefinindo as dicas",
+        "ui": "atualizando interface"
+    },
+    "uppercase": [
+        "CEO",
+        "CEOs",
+        "CFO",
+        "CFOs",
+        "CNC",
+        "COO",
+        "COOs",
+        "CPU",
+        "CPUs",
+        "PIB",
+        "HVAC",
+        "ID",
+        "TI",
+        "P&D",
+        "TV",
+        "IU"
+    ]
+}
+
+},{}],75:[function(require,module,exports){
+module.exports = {
+    "format": {
+        "decimal": ",",
+        "thousands": ".",
+        "grouping": [3],
+        "currency": ["€", ""],
+        "dateTime": "%A, %e de %B de %Y. %X",
+        "date": "%d/%m/%Y",
+        "time": "%H:%M:%S",
+        "periods": ["AM", "PM"],
+        "days": ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"],
+        "shortDays": ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"],
+        "months": ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
+        "shortMonths": ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"]
+    },
+    "dev": {
+        "accepted": "{0} não é um valor válido para {1}, por favor escolha uma das seguintes opções: {2}.",
+        "deprecated": "o método {0} foi removido, por favor atualize o seu código para usar {1}.",
+        "noChange": "{0} não foi atualizado porque não houve modificações.",
+        "noContainer": "Não foi possível encontrar um elemento na página correspondente a {0}.",
+        "of": "de",
+        "oldStyle": "as propriedades de {0} já foram incluídas em .{1}().",
+        "sameEdge": "bordas não podem vincular a si mesmos. removendo automaticamente borda de auto-referência {0}.",
+        "set": "{0} foi definido.",
+        "setLong": "{0} foi alterado para {1}.",
+        "setContainer": "por favor indique um elemento div através do método .container()"
+    },
+    "error": {
+        "accepted": "{0} não é uma {1} válida para a visualização {2}, por favor escolha uma das seguintes: {3}.",
+        "connections": "não existem ligações disponíveis para {0}.",
+        "data": "não existem dados disponíveis",
+        "dataYear": "não existem dados disponíveis para {0}.",
+        "lib": "a visualização {0} necessita que a biblioteca {1} seja carregada.",
+        "libs": "a visualização {0} necessita que as seguintes bibliotecas sejam carregadas: {1}.",
+        "method": "A visualização {0} exige a definição do método {1}.",
+        "methods": "A visualização {0} exige a definição dos seguintes métodos {1}."
+    },
+    "lowercase": [
+        "um",
+        "uma",
+        "e",
+        "como",
+        "em",
+        "no",
+        "na",
+        "mas",
+        "por",
+        "para",
+        "pelo",
+        "pela",
+        "de",
+        "do",
+        "da",
+        "se",
+        "perto",
+        "nem",
+        "ou",
+        "que",
+        "o",
+        "a",
+        "com",
+        "v"
+    ],
+    "method": {
+        "active": "segmentos activos",
+        "color": "cor",
+        "depth": "profundidade",
+        "dev": "verboso",
+        "focus": "foco",
+        "icon": "ícone",
+        "id": "identificador",
+        "height": "altura",
+        "labels": "etiquetas",
+        "legend": "legenda",
+        "margin": "margem",
+        "messages": "estado",
+        "order": "ordenar",
+        "search": "pesquisar",
+        "shape": "forma",
+        "size": "tamanho",
+        "style": "estilo",
+        "temp": "segmentos temporários",
+        "text": "texto",
+        "time": "tempo",
+        "timeline": "linha temporal",
+        "total": "segmentos no total",
+        "type": "tipo",
+        "width": "largura",
+        "x": "eixo dos xx",
+        "y": "eixo dos yy",
+        "zoom": "zoom",
+        "mode": "#ERROR!",
+        "mute": "ocultar",
+        "solo": "isolar"
+    },
+    "time": [
+        "data",
+        "dia",
+        "mês",
+        "hora",
+        "ano"
+    ],
+    "visualization": {
+        "bubbles": "Bolhas",
+        "chart": "Diagrama",
+        "geo_map": "Mapa",
+        "line": "Gráfico de Linha",
+        "network": "Grafo",
+        "rings": "Anéis",
+        "scatter": "Gráfico de Dispersão",
+        "stacked": "Gráfico de Área",
+        "tree_map": "Tree Map",
+        "bar": "Gráfico de Barras",
+        "box": "Diagrama de Caixa e Bigodes",
+        "paths": "Caminhos",
+        "pie": "Gráfico de Setores",
+        "table": "Tabela"
+    },
+    "ui": {
+        "and": "e",
+        "back": "voltar",
+        "collapse": "Clique para colapsar",
+        "error": "erro",
+        "expand": "clique para expandir",
+        "loading": "a carregar ...",
+        "more": "mais {0}",
+        "moreInfo": "Clique para mais informações",
+        "noResults": "nenhum resultado para {0}.",
+        "primary": "ligações principais",
+        "share": "proporção",
+        "total": "total",
+        "values": "valores",
+        "including": "Incluindo",
+        "or": "ou"
+    },
+    "message": {
+        "data": "a analisar os dados",
+        "draw": "a desenhar a visualização",
+        "initializing": "a inicializar {0}",
+        "loading": "a carregar os dados",
+        "tooltipReset": "a actualizar as caixas de informação",
+        "ui": "a actualizar o interface"
+    },
+    "uppercase": [
+        "CEO",
+        "CEOs",
+        "CFO",
+        "CFOs",
+        "CNC",
+        "COO",
+        "COOs",
+        "CPU",
+        "CPUs",
+        "PIB",
+        "HVAC",
+        "ID",
+        "TI",
+        "I&D",
+        "TV",
+        "IU"
+    ]
+}
+
+},{}],76:[function(require,module,exports){
+module.exports = {
+    "format": {
+        "decimal": ",",
+        "thousands": "\xa0",
+        "grouping": [3],
+        "currency": ["", " руб."],
+        "dateTime": "%A, %e %B %Y г. %X",
+        "date": "%d.%m.%Y",
+        "time": "%H:%M:%S",
+        "periods": ["AM", "PM"],
+        "days": ["воскресенье", "понедельник", "вторник", "среда", "четверг", "пятница", "суббота"],
+        "shortDays": ["вс", "пн", "вт", "ср", "чт", "пт", "сб"],
+        "months": ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"],
+        "shortMonths": ["янв", "фев", "мар", "апр", "май", "июн", "июл", "авг", "сен", "окт", "ноя", "дек"]
+    },
+    "dev": {
+        "accepted": "{0} не принимаются значение {1}, пожалуйста, используйте один из следующих: {2}.",
+        "deprecated": "Метод {0} был удален, пожалуйста, обновите ваш код, чтобы использовать {1}.",
+        "noChange": "{0} не обновлен, поскольку он не изменится.",
+        "noContainer": "не могу найти контейнер на странице соответствия {0}.",
+        "of": "из",
+        "oldStyle": "свойства стиля для {0} уже в настоящее время были встроен непосредственно в. {1} ().",
+        "sameEdge": "Края не может связать себя. автоматически удаляя автореферентных ребро {0}.",
+        "set": "{0} был установлен.",
+        "setLong": "{0} установлено значение {1}.",
+        "setContainer": "пожалуйста, определить контейнер DIV с помощью .container ()"
+    },
+    "error": {
+        "accepted": "{0} не принимаются {1} для {2} визуализации, пожалуйста, используйте один из следующих: {3}.",
+        "connections": "нет соединения, доступные для {0}.",
+        "data": "данные недоступны",
+        "dataYear": "нет данных {0}.",
+        "lib": "{0} визуализации требуют загрузки {1} библиотеку.",
+        "libs": "{0} визуализации требуют загрузки следующих библиотек: {1}.",
+        "method": "{0} визуализации требуют установки {1} метода.",
+        "methods": "{0} визуализации требуют установки следующих методов: {1}."
+    },
+    "lowercase": [
+        "и",
+        "как",
+        "в",
+        "но",
+        "для",
+        "из",
+        "если в",
+        "в",
+        "недалеко",
+        "ни",
+        "на",
+        "на",
+        "или",
+        "в",
+        "что",
+        "к",
+        "с",
+        "с помощью",
+        "против",
+        "против"
+    ],
+    "method": {
+        "active": "активные сегменты",
+        "color": "цвет",
+        "depth": "глубина",
+        "dev": "многословный",
+        "focus": "фокус",
+        "icon": "значок",
+        "id": "ID",
+        "height": "высота",
+        "labels": "надписи",
+        "legend": "легенда",
+        "margin": "поле",
+        "messages": "Сообщения о состоянии",
+        "mute": "скрывать",
+        "order": "порядок",
+        "search": "поиск",
+        "shape": "форма",
+        "size": "размер",
+        "solo": "изолировать",
+        "style": "стиль",
+        "temp": "временные сегменты",
+        "text": "текст",
+        "time": "время",
+        "timeline": "график",
+        "total": "всего сегментов",
+        "type": "тип",
+        "width": "ширина",
+        "x": "ось х",
+        "y": "Ось Y",
+        "zoom": "масштаб",
+        "mode": "режим"
+    },
+    "time": [
+        "дата",
+        "день",
+        "месяц",
+        "время",
+        "год"
+    ],
+    "visualization": {
+        "bubbles": "Пузыри",
+        "chart": "График",
+        "geo_map": "Гео Карта",
+        "line": "Линия земля",
+        "network": "Сеть",
+        "rings": "Кольца",
+        "scatter": "Разброс земля",
+        "stacked": "С накоплением Площадь",
+        "tree_map": "Дерево Карта",
+        "bar": "Гистограмма",
+        "box": "Коробка земля",
+        "paths": "Пути",
+        "pie": "Круговая диаграмма",
+        "table": "Стол"
+    },
+    "ui": {
+        "and": "и",
+        "back": "назад",
+        "collapse": "Щелкните, чтобы свернуть",
+        "error": "ошибка",
+        "expand": "щелкните, чтобы развернуть",
+        "loading": "загрузка ...",
+        "more": "{0} более",
+        "moreInfo": "нажмите для получения более подробной информации",
+        "noResults": "нет результатов, соответствующих {0}.",
+        "primary": "первичные соединения",
+        "share": "доля",
+        "total": "общее",
+        "values": "значения",
+        "including": "включая",
+        "or": "или"
+    },
+    "message": {
+        "data": "Анализируя данные",
+        "draw": "рисунок визуализация",
+        "initializing": "инициализации {0}",
+        "loading": "загрузка данных",
+        "tooltipReset": "сброс подсказки",
+        "ui": "обновление пользовательского интерфейса"
+    },
+    "uppercase": [
+        "ID"
+    ]
+}
+
+},{}],77:[function(require,module,exports){
+module.exports = {
+    "format": {
+        "decimal": ".",
+        "thousands": ",",
+        "grouping": [3],
+        "currency": ["¥", ""],
+        "dateTime": "%A %B %e %Y %X",
+        "date": "%Y/%-m/%-d",
+        "time": "%H:%M:%S",
+        "periods": ["上午", "下午"],
+        "days": ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
+        "shortDays": ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
+        "months": ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
+        "shortMonths": ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]
+    },
+    "dev": {
+        "accepted": "{0}不是{1}的可接受值, 请用下列之一的值:{2}",
+        "deprecated": "{0}的方法已被移除, 请更新您的代码去使用{1}",
+        "noChange": "{0}没有更新, 因为它并没有改变。",
+        "noContainer": "无法在该页找到容器去匹配{0}",
+        "of": "的",
+        "oldStyle": "样式属性{0}现在已经直接嵌入到。{1}()。",
+        "sameEdge": "边缘不能链接到自己。自动去除自我参照边缘{0}。",
+        "set": "{0}已经被设置。",
+        "setLong": "{0}被设置为{1}。",
+        "setContainer": "请使用()容器来定义div容器"
+    },
+    "error": {
+        "accepted": "{0}对于{2}的可视化效果并不是一个可接受的{1}, 请使用如下的一个:{3}.",
+        "connections": "没有对{0}可用的连接。",
+        "data": "无可用数据",
+        "dataYear": "没有数据对{0}可用。",
+        "lib": "{0}的可视化要求装载{1}库。",
+        "libs": "{0}的可视化需要加载以下库:{1}。",
+        "method": "{0}的可视化要求设置{1}方法。",
+        "methods": "{0}的可视化要求设置以下方法:{1}。"
+    },
+    "lowercase": [
+        "一个",
+        "和",
+        "在",
+        "但是",
+        "在...里",
+        "的",
+        "或者",
+        "这",
+        "向",
+        "与...一起"
+    ],
+    "method": {
+        "active": "活跃段",
+        "color": "颜色",
+        "depth": "深度",
+        "dev": "详细",
+        "focus": "焦点",
+        "icon": "图标",
+        "id": "身份认证",
+        "height": "高度",
+        "labels": "标签",
+        "legend": "图例注释",
+        "margin": "外边距",
+        "messages": "状态消息",
+        "mute": "隐藏",
+        "order": "规则",
+        "search": "搜索",
+        "shape": "形状",
+        "size": "大小",
+        "solo": "隔离",
+        "style": "样式",
+        "temp": "暂时性区段",
+        "text": "文本",
+        "time": "时间",
+        "timeline": "时间轴",
+        "total": "总段",
+        "type": "类型",
+        "width": "宽度",
+        "x": "X轴",
+        "y": "Y轴",
+        "zoom": "缩放",
+        "mode": "模式"
+    },
+    "time": [
+        "日",
+        "星期",
+        "月",
+        "时间",
+        "年"
+    ],
+    "visualization": {
+        "bubbles": "气泡",
+        "chart": "图表",
+        "geo_map": "地理地图",
+        "line": "线图",
+        "network": "网络",
+        "rings": "特性",
+        "scatter": "散点图",
+        "stacked": "堆积面积图",
+        "tree_map": "树图",
+        "bar": "条图",
+        "box": "箱线图",
+        "paths": "路径",
+        "pie": "饼图",
+        "table": "表"
+    },
+    "ui": {
+        "and": "和",
+        "back": "后面",
+        "collapse": "点击合并",
+        "error": "错误",
+        "expand": "单击以展开",
+        "loading": "载入中...",
+        "more": "{0}更多",
+        "moreInfo": "点击了解更多信息",
+        "noResults": "没有结果匹配{0}。",
+        "primary": "主要连接",
+        "share": "共享",
+        "total": "总",
+        "values": "值",
+        "including": "包括",
+        "or": "或"
+    },
+    "message": {
+        "data": "分析数据",
+        "draw": "绘制可视化",
+        "initializing": "初始化{0}",
+        "loading": "加载数据",
+        "tooltipReset": "重置工具提示",
+        "ui": "更新UI"
+    },
+    "uppercase": [
+        "CEO",
+        "CEOs",
+        "CFO",
+        "CFOs",
+        "CNC",
+        "COO",
+        "COOs",
+        "CPU",
+        "CPUs",
+        "GDP",
+        "HVAC",
+        "ID",
+        "电视",
+        "用户界面",
+        "研发"
+    ]
+}
+
+},{}],78:[function(require,module,exports){
+module.exports = {
+  en_US: require("./languages/en_US.coffee"),
+  es_ES: require("./languages/es_ES.js"),
+  fr_FR: require("./languages/fr_FR.js"),
+  mk_MK: require("./languages/mk_MK.js"),
+  pt_BR: require("./languages/pt_BR.js"),
+  pt_PT: require("./languages/pt_PT.js"),
+  ru_RU: require("./languages/ru_RU.js"),
+  zh_CN: require("./languages/zh_CN.js")
+};
+
+
+},{"./languages/en_US.coffee":70,"./languages/es_ES.js":71,"./languages/fr_FR.js":72,"./languages/mk_MK.js":73,"./languages/pt_BR.js":74,"./languages/pt_PT.js":75,"./languages/ru_RU.js":76,"./languages/zh_CN.js":77}],79:[function(require,module,exports){
+var checkObject, copy, createFunction, initialize, print, process, setMethod, stringFormat, validObject;
+
+copy = require("../../util/copy.coffee");
+
+print = require("../console/print.coffee");
+
+process = require("./process/detect.coffee");
+
+setMethod = require("./set.coffee");
+
+stringFormat = require("../../string/format.js");
+
+validObject = require("../../object/validate.coffee");
+
+module.exports = function(vars, methods) {
+  var method, obj, results;
+  results = [];
+  for (method in methods) {
+    obj = methods[method];
+    vars[method] = copy(obj);
+    vars[method].initialized = initialize(vars, vars[method], method);
+    results.push(vars.self[method] = createFunction(vars, method));
+  }
+  return results;
+};
+
+initialize = function(vars, obj, method) {
+  var d, deps, i, len, o;
+  obj.previous = false;
+  obj.changed = false;
+  obj.initialized = false;
+  obj.callback = false;
+  if ("init" in obj && (!("value" in obj))) {
+    obj.value = obj.init(vars);
+    delete obj.init;
+  }
+  if ("process" in obj) {
+    obj.value = process(vars, obj, obj.value);
+  }
+  for (o in obj) {
+    if (o === "deprecates") {
+      deps = obj[o] instanceof Array ? obj[o] : [obj[o]];
+      for (i = 0, len = deps.length; i < len; i++) {
+        d = deps[i];
+        vars.self[d] = (function(dep, n) {
+          return function(x) {
+            var str;
+            str = vars.format.locale.value.dev.deprecated;
+            dep = "." + dep + "()";
+            print.error(stringFormat(str, dep, "." + n + "()"), n);
+            return vars.self;
+          };
+        })(d, method);
+      }
+    } else if (o === "global") {
+      if (!(method in vars)) {
+        vars[method] = [];
+      }
+    } else if (o !== "value") {
+      if (validObject(obj[o])) {
+        initialize(vars, obj[o], o);
+      }
+    }
+  }
+  return true;
+};
+
+createFunction = function(vars, key) {
+  return function(user, callback) {
+    var accepted, checkFont, checkValue, fontAttr, fontAttrValue, s, starting, str;
+    accepted = "accepted" in vars[key] ? vars[key].accepted : null;
+    if (typeof accepted === "function") {
+      accepted = accepted(vars);
+    }
+    if (!(accepted instanceof Array)) {
+      accepted = [accepted];
+    }
+    if (user === Object) {
+      return vars[key];
+    } else if (!arguments.length && accepted.indexOf(void 0) < 0) {
+      if ("value" in vars[key]) {
+        return vars[key].value;
+      } else {
+        return vars[key];
+      }
+    }
+    if (key === "style" && typeof user === "object") {
+      str = vars.format.locale.value.dev.oldStyle;
+      for (s in user) {
+        print.warning(stringFormat(str, "\"" + s + "\"", s), s);
+        vars.self[s](user[s]);
+      }
+    }
+    if (key === "font") {
+      if (typeof user === "string") {
+        user = {
+          family: user
+        };
+      }
+      starting = true;
+      checkValue = function(o, a, m, v) {
+        if (validObject(o[m]) && a in o[m]) {
+          if (validObject(o[m][a])) {
+            if (o[m][a].process) {
+              o[m][a].value = o[m][a].process(v);
+            } else {
+              o[m][a].value = v;
+            }
+          } else {
+            o[m][a] = v;
+          }
+        }
+      };
+      checkFont = function(o, a, v) {
+        var m;
+        if (validObject(o)) {
+          if (starting) {
+            for (m in o) {
+              checkValue(o, a, m, v);
+            }
+          } else if ("font" in o) {
+            checkValue(o, a, "font", v);
+          }
+          starting = false;
+          for (m in o) {
+            checkFont(o[m], a, v);
+          }
+        }
+      };
+      for (fontAttr in user) {
+        fontAttrValue = user[fontAttr];
+        if (fontAttr !== "secondary") {
+          if (validObject(fontAttrValue)) {
+            fontAttrValue = fontAttrValue.value;
+          }
+          if (fontAttrValue) {
+            checkFont(vars, fontAttr, fontAttrValue);
+          }
+        }
+      }
+    }
+    checkObject(vars, key, vars, key, user);
+    if (typeof callback === "function") {
+      vars[key].callback = callback;
+    }
+    if (vars[key].chainable === false) {
+      return vars[key].value;
+    } else {
+      return vars.self;
+    }
+  };
+};
+
+checkObject = function(vars, method, object, key, value) {
+  var approvedObject, d, objectOnly, passingObject;
+  if (["accepted", "changed", "initialized", "previous", "process"].indexOf(key) < 0) {
+    passingObject = validObject(value);
+    objectOnly = validObject(object[key]) && "objectAccess" in object[key] && object[key]["objectAccess"] === false;
+    approvedObject = passingObject && (objectOnly || ((!("value" in value)) && (!(d3.keys(value)[0] in object[key]))));
+    if (value === null || !passingObject || approvedObject) {
+      setMethod(vars, method, object, key, value);
+    } else if (passingObject) {
+      for (d in value) {
+        checkObject(vars, method, object[key], d, value[d]);
+      }
+    }
+  }
+};
+
+
+},{"../../object/validate.coffee":171,"../../string/format.js":172,"../../util/copy.coffee":206,"../console/print.coffee":53,"./process/detect.coffee":87,"./set.coffee":93}],80:[function(require,module,exports){
+module.exports = function(g) {
+  if (!g) {
+    g = false;
+  }
+  return {
+    accepted: [false, Array, Function, Number, Object, String],
+    callback: {
+      accepted: [false, Function],
+      value: false
+    },
+    global: g,
+    process: Array,
+    value: []
+  };
+};
+
+
+},{}],81:[function(require,module,exports){
+var rtl;
+
+rtl = require("../../../client/rtl.coffee");
+
+module.exports = function(align) {
+  var accepted;
+  accepted = ["left", "center", "right"];
+  if (align === false) {
+    accepted.unshift(false);
+  }
+  if (accepted.indexOf(align) < 0) {
+    align = "left";
+  }
+  return {
+    accepted: accepted,
+    process: function(value) {
+      if (rtl) {
+        if (value === "left") {
+          return "right";
+        } else {
+          if (value === "right") {
+            return "left";
+          } else {
+            return value;
+          }
+        }
+      } else {
+        return value;
+      }
+    },
+    value: align
+  };
+};
+
+
+},{"../../../client/rtl.coffee":42}],82:[function(require,module,exports){
+module.exports = function(decoration) {
+  var accepted;
+  accepted = ["line-through", "none", "overline", "underline"];
+  if (decoration === false) {
+    accepted.unshift(false);
+  }
+  if (accepted.indexOf(decoration) < 0) {
+    decoration = "none";
+  }
+  return {
+    accepted: accepted,
+    value: decoration
+  };
+};
+
+
+},{}],83:[function(require,module,exports){
+var helvetica, validate;
+
+validate = require("../../../font/validate.coffee");
+
+helvetica = ["Helvetica Neue", "HelveticaNeue", "Helvetica", "Arial", "sans-serif"];
+
+module.exports = function(family) {
+  if (family === void 0) {
+    family = helvetica;
+  }
+  return {
+    process: validate,
+    value: family
+  };
+};
+
+
+},{"../../../font/validate.coffee":102}],84:[function(require,module,exports){
+module.exports = function(position) {
+  var accepted;
+  accepted = ["top", "middle", "bottom"];
+  if (position === false) {
+    accepted.unshift(false);
+  }
+  if (accepted.indexOf(position) < 0) {
+    position = "bottom";
+  }
+  return {
+    accepted: accepted,
+    mapping: {
+      top: "0ex",
+      middle: "0.5ex",
+      bottom: "1ex"
+    },
+    process: function(value) {
+      this.text = value;
+      return this.mapping[value];
+    },
+    value: position
+  };
+};
+
+
+},{}],85:[function(require,module,exports){
+module.exports = function(transform) {
+  var accepted;
+  accepted = ["capitalize", "lowercase", "none", "uppercase"];
+  if (transform === false) {
+    accepted.unshift(false);
+  }
+  if (accepted.indexOf(transform) < 0) {
+    transform = "none";
+  }
+  return {
+    accepted: accepted,
+    value: transform
+  };
+};
+
+
+},{}],86:[function(require,module,exports){
+module.exports = function(value, vars, method) {
+  var elem;
+  if (vars.history) {
+    vars.history.reset();
+  }
+  if (value.constructor === String) {
+    if (value.indexOf("/") >= 0) {
+      method.url = value;
+      return [];
+    }
+    elem = d3.selectAll(value);
+    if (elem.size()) {
+      return elem;
+    }
+    if (value.indexOf(".") >= 0) {
+      method.url = value;
+    }
+    return [];
+  } else {
+    return value;
+  }
+};
+
+
+},{}],87:[function(require,module,exports){
+var copy, update;
+
+copy = require("../../../util/copy.coffee");
+
+update = require("../../../array/update.coffee");
+
+module.exports = function(vars, object, value) {
+  if (object.process === Array) {
+    return update(copy(object.value), value);
+  } else if (typeof object.process === "object" && typeof value === "string") {
+    return object.process[value];
+  } else if (typeof object.process === "function") {
+    return object.process(value, vars, object);
+  } else {
+    return value;
+  }
+};
+
+
+},{"../../../array/update.coffee":37,"../../../util/copy.coffee":206}],88:[function(require,module,exports){
+var stylesheet;
+
+stylesheet = require("../../../client/css.coffee");
+
+module.exports = function(value, vars, method) {
+  if (value === false || value.indexOf("fa-") < 0 || (value.indexOf("fa-") === 0 && stylesheet("font-awesome"))) {
+    return value;
+  } else {
+    return method.fallback;
+  }
+};
+
+
+},{"../../../client/css.coffee":38}],89:[function(require,module,exports){
+module.exports = function(value, self) {
+  var i, j, k, l, len, len1, len2, len3, m, results, side, sides, v;
+  if (typeof value === "string") {
+    value = value.split(" ");
+    for (i = j = 0, len = value.length; j < len; i = ++j) {
+      v = value[i];
+      value[i] = parseFloat(v, 10);
+    }
+    if (value.length === 1) {
+      value = value[0];
+    } else if (value.length === 2) {
+      value = {
+        top: value[0],
+        right: value[1],
+        bottom: value[0],
+        left: value[1]
+      };
+    } else if (value.length === 3) {
+      value = {
+        top: value[0],
+        right: value[1],
+        bottom: value[2],
+        left: value[1]
+      };
+    } else if (value.length === 4) {
+      value = {
+        top: value[0],
+        right: value[1],
+        bottom: value[2],
+        left: value[3]
+      };
+    } else {
+      value = 0;
+    }
+  }
+  sides = ["top", "right", "bottom", "left"];
+  if (typeof value === "number") {
+    for (k = 0, len1 = sides.length; k < len1; k++) {
+      side = sides[k];
+      self[side] = value;
+    }
+  } else {
+    for (l = 0, len2 = sides.length; l < len2; l++) {
+      side = sides[l];
+      self[side] = value[side];
+    }
+  }
+  self.css = "";
+  results = [];
+  for (i = m = 0, len3 = sides.length; m < len3; i = ++m) {
+    side = sides[i];
+    if (i) {
+      self.css += " ";
+    }
+    results.push(self.css += self[side] + "px");
+  }
+  return results;
+};
+
+
+},{}],90:[function(require,module,exports){
+var contains, format, list, print;
+
+contains = require("../../array/contains.coffee");
+
+format = require("../../string/format.js");
+
+list = require("../../string/list.coffee");
+
+print = require("../console/print.coffee");
+
+module.exports = function(vars, accepted, value, method, text) {
+  var a, allowed, app, i, len, recs, str, val;
+  if (typeof accepted === "function") {
+    accepted = accepted(vars);
+  }
+  if (!(accepted instanceof Array)) {
+    accepted = [accepted];
+  }
+  allowed = contains(accepted, value);
+  if (allowed === false && value !== void 0) {
+    recs = [];
+    val = JSON.stringify(value);
+    if (typeof value !== "string") {
+      val = "\"" + val + "\"";
+    }
+    for (i = 0, len = accepted.length; i < len; i++) {
+      a = accepted[i];
+      if (typeof a === "string") {
+        recs.push("\"" + a + "\"");
+      } else if (typeof a === "function") {
+        recs.push(a.toString().split("()")[0].substring(9));
+      } else if (a === void 0) {
+        recs.push("undefined");
+      } else {
+        recs.push(JSON.stringify(a));
+      }
+    }
+    recs = list(recs, vars.format.locale.value.ui.or);
+    if (vars.type && ["mode", "shape"].indexOf(method) >= 0) {
+      str = vars.format.locale.value.error.accepted;
+      app = vars.format.locale.value.visualization[vars.type.value] || vars.type.value;
+      print.warning(format(str, val, method, app, recs), method);
+    } else {
+      str = vars.format.locale.value.dev.accepted;
+      print.warning(format(str, val, text, recs), method);
+    }
+  }
+  return !allowed;
+};
+
+
+},{"../../array/contains.coffee":35,"../../string/format.js":172,"../../string/list.coffee":173,"../console/print.coffee":53}],91:[function(require,module,exports){
+module.exports = function(rendering) {
+  var accepted;
+  accepted = ["auto", "optimizeSpeed", "crispEdges", "geometricPrecision"];
+  if (!(accepted.indexOf(rendering) >= 0)) {
+    rendering = "crispEdges";
+  }
+  return {
+    accepted: accepted,
+    value: rendering
+  };
+};
+
+
+},{}],92:[function(require,module,exports){
+var reset, validObject;
+
+validObject = require("../../object/validate.coffee");
+
+reset = function(obj, method) {
+  var o;
+  if (obj.changed) {
+    obj.changed = false;
+  }
+  if (method === "draw") {
+    obj.frozen = false;
+    obj.update = true;
+    obj.first = false;
+  }
+  for (o in obj) {
+    if (o.indexOf("d3plus") < 0 && validObject(obj[o])) {
+      reset(obj[o], o);
+    }
+  }
+};
+
+module.exports = reset;
+
+
+},{"../../object/validate.coffee":171}],93:[function(require,module,exports){
+var copy, d3selection, mergeObject, print, process, rejected, stringFormat, updateArray, validObject;
+
+copy = require("../../util/copy.coffee");
+
+d3selection = require("../../util/d3selection.coffee");
+
+validObject = require("../../object/validate.coffee");
+
+mergeObject = require("../../object/merge.coffee");
+
+print = require("../console/print.coffee");
+
+process = require("./process/detect.coffee");
+
+rejected = require("./rejected.coffee");
+
+stringFormat = require("../../string/format.js");
+
+updateArray = require("../../array/update.coffee");
+
+module.exports = function(vars, method, object, key, value) {
+  var accepted, c, callback, d3object, hasValue, id, k, longArray, n, parentKey, str, text, typeFunction, valString;
+  if (key === "value" || !key || key === method) {
+    text = "." + method + "()";
+  } else {
+    text = "\"" + key + "\" " + vars.format.locale.value.dev.of + " ." + method + "()";
+  }
+  if (key === "value" && "accepted" in object) {
+    accepted = object.accepted;
+  } else if (validObject(object[key]) && "accepted" in object[key]) {
+    accepted = object[key].accepted;
+  } else {
+    accepted = [value];
+  }
+  if (!rejected(vars, accepted, value, method, text)) {
+    if (validObject(object[key]) && "value" in object[key]) {
+      parentKey = key;
+      object = object[key];
+      key = "value";
+    }
+    if (key === "value" && "process" in object) {
+      value = process(vars, object, value);
+    }
+    if ((!(object[key] instanceof Array)) && object[key] === value && value !== void 0) {
+      str = vars.format.locale.value.dev.noChange;
+      if (vars.dev.value) {
+        print.comment(stringFormat(str, text));
+      }
+    } else {
+      object.changed = true;
+      if (object.loaded) {
+        object.loaded = false;
+      }
+      if ("history" in vars && method !== "draw") {
+        c = copy(object);
+        c.method = method;
+        vars.history.chain.push(c);
+      }
+      object.previous = object[key];
+      if ("id" in vars && key === "value" && "nesting" in object) {
+        if (method !== "id") {
+          if (typeof object.nesting !== "object") {
+            object.nesting = {};
+          }
+          if (validObject(value)) {
+            for (id in value) {
+              if (typeof value[id] === "string") {
+                value[id] = [value[id]];
+              }
+            }
+            object.nesting = mergeObject(object.nesting, value);
+            if (!(vars.id.value in object.nesting)) {
+              object.nesting[vars.id.value] = value[d3.keys(value)[0]];
+            }
+          } else if (value instanceof Array) {
+            object.nesting[vars.id.value] = value;
+          } else {
+            object.nesting[vars.id.value] = [value];
+          }
+          object[key] = object.nesting[vars.id.value][0];
+        } else {
+          if (value instanceof Array) {
+            object.nesting = value;
+            if ("depth" in vars && vars.depth.value < value.length) {
+              object[key] = value[vars.depth.value];
+            } else {
+              object[key] = value[0];
+              if ("depth" in vars) {
+                vars.depth.value = 0;
+              }
+            }
+          } else {
+            object[key] = value;
+            object.nesting = [value];
+            if ("depth" in vars) {
+              vars.depth.value = 0;
+            }
+          }
+        }
+      } else if (method === "depth") {
+        if (value >= vars.id.nesting.length) {
+          vars.depth.value = vars.id.nesting.length - 1;
+        } else if (value < 0) {
+          vars.depth.value = 0;
+        } else {
+          vars.depth.value = value;
+        }
+        vars.id.value = vars.id.nesting[vars.depth.value];
+        if (typeof vars.text.nesting === "object") {
+          n = vars.text.nesting[vars.id.value];
+          if (n) {
+            vars.text.nesting[vars.id.value] = typeof n === "string" ? [n] : n;
+            vars.text.value = (n instanceof Array ? n[0] : n);
+          }
+        }
+      } else if (validObject(object[key]) && validObject(value)) {
+        object[key] = mergeObject(object[key], value);
+      } else {
+        object[key] = value;
+      }
+      if (key === "value" && object.global) {
+        hasValue = object[key].length > 0;
+        k = parentKey || key;
+        if (k in vars && ((hasValue && vars.data[k].indexOf(method) < 0) || (!hasValue && vars.data[k].indexOf(method) >= 0))) {
+          vars.data[k] = updateArray(vars.data[k], method);
+        }
+      }
+      if (key === "value" && object.dataFilter && vars.data && vars.data.filters.indexOf(method) < 0) {
+        vars.data.filters.push(method);
+      }
+      if (vars.dev.value && object.changed && object[key] !== void 0) {
+        longArray = object[key] instanceof Array && object[key].length > 10;
+        d3object = d3selection(object[key]);
+        typeFunction = typeof object[key] === "function";
+        valString = (!longArray && !d3object && !typeFunction ? (typeof object[key] === "string" ? object[key] : JSON.stringify(object[key])) : null);
+        if (valString !== null && valString.length < 260) {
+          str = vars.format.locale.value.dev.setLong;
+          print.log(stringFormat(str, text, "\"" + valString + "\""));
+        } else {
+          str = vars.format.locale.value.dev.set;
+          print.log(stringFormat(str, text));
+        }
+      }
+    }
+    if (key === "value" && object.callback && !object.url) {
+      callback = typeof object.callback === "function" ? object.callback : object.callback.value;
+      if (callback) {
+        callback(value, vars.self);
+      }
+    }
+  }
+};
+
+
+},{"../../array/update.coffee":37,"../../object/merge.coffee":170,"../../object/validate.coffee":171,"../../string/format.js":172,"../../util/copy.coffee":206,"../../util/d3selection.coffee":207,"../console/print.coffee":53,"./process/detect.coffee":87,"./rejected.coffee":90}],94:[function(require,module,exports){
+var print = require("../console/print.coffee"),
+    stringFormat = require("../../string/format.js")
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Cleans edges list and populates nodes list if needed
+//-------------------------------------------------------------------
+module.exports = function( vars ) {
+
+  if ( vars.dev.value ) {
+    var timerString = "analyzing edges list"
+    print.time( timerString )
+  }
+
+  var appReqs     = vars.types[vars.type.value].requirements
+  if (!(appReqs instanceof Array)) appReqs = [appReqs]
+  var createNodes = appReqs.indexOf("nodes") >= 0 && !vars.nodes.value
+
+  if ( createNodes ) {
+    vars.nodes.value = []
+    var placed = []
+    vars.nodes.changed = true
+  }
+
+  vars.edges.value.forEach(function(e){
+
+    ["source", "target"].forEach(function(dir){
+
+      var dirType = typeof e[vars.edges[dir]];
+
+      if (dirType !== "object") {
+        if (dirType === "number" && !createNodes && vars.data.keys[vars.id.value] !== "number") {
+          e[vars.edges[dir]] = vars.nodes.value[e[vars.edges[dir]]];
+        }
+        else {
+          if (createNodes && placed.indexOf(e[vars.edges[dir]]) >= 0) {
+            e[vars.edges[dir]] = vars.nodes.value.filter(function(n){
+              return n[vars.id.value] === e[vars.edges[dir]];
+            })[0];
+          }
+          else {
+            var obj = {};
+            obj[vars.id.value] = e[vars.edges[dir]];
+            e[vars.edges[dir]] = obj;
+          }
+        }
+      }
+
+      var newNode = e[vars.edges[dir]];
+      if (createNodes) {
+        if (placed.indexOf(newNode[vars.id.value]) < 0) {
+          placed.push(newNode[vars.id.value]);
+          vars.nodes.value.push(newNode);
+        }
+      }
+    });
+
+    if (!("keys" in vars.data)) {
+      vars.data.keys = {};
+    }
+
+    if (!(vars.id.value in vars.data.keys)) {
+      vars.data.keys[vars.id.value] = typeof e[vars.edges.source][vars.id.value];
+    }
+
+  });
+
+  vars.edges.value = vars.edges.value.filter(function(e){
+
+    var source = e[vars.edges.source][vars.id.value]
+      , target = e[vars.edges.target][vars.id.value]
+
+    if ( source === target ) {
+      var str = vars.format.locale.value.dev.sameEdge
+      print.warning(stringFormat(str,"\""+source+"\"") , "edges" )
+      return false
+    }
+    else {
+      return true
+    }
+
+  })
+
+  vars.edges.linked = true
+
+  if ( vars.dev.value ) print.timeEnd( timerString )
+
+}
+
+},{"../../string/format.js":172,"../console/print.coffee":53}],95:[function(require,module,exports){
+var hideElement = require("./hideElement.js");
+
+// Parses an HTML element for data
+module.exports = function( vars ) {
+
+  var attributes = [ vars.color.value
+                   , vars.icon.value
+                   , vars.keywords.value
+                   , vars.alt.value
+                   , "style" ]
+
+  if (!vars.text.value) {
+    vars.self.text("text")
+  }
+
+  attributes = attributes.concat(vars.id.nesting)
+
+  function get_attributes( obj , elem ) {
+    [].forEach.call(elem.attributes, function(attr) {
+        if (/^data-/.test(attr.name)) {
+            var camelCaseName = attr.name.substr(5).replace(/-(.)/g, function ($0, $1) {
+                return $1.toUpperCase();
+            });
+            obj[camelCaseName] = attr.value;
+        }
+    })
+
+    attributes.forEach(function(a){
+
+      if ( elem.getAttribute(a) !== null ) {
+        obj[a] = elem.getAttribute(a)
+      }
+
+    })
+
+  }
+
+  vars.self.data({"element": vars.data.value})
+
+  var elementTag  = vars.data.element.value.node().tagName.toLowerCase()
+    , elementType = vars.data.element.value.attr("type")
+    , elementData = []
+
+  if ( elementTag === "select" ) {
+
+    var elementID = vars.data.element.value.node().id
+    if ( elementID ) {
+      vars.self.container({"id": elementID})
+    }
+
+    vars.data.element.value.selectAll("option")
+      .each(function( o , i ){
+
+        var data_obj = {}
+
+        data_obj.text = this.innerHTML
+
+        get_attributes(data_obj,this)
+
+        elementData.push(data_obj)
+
+        if (this.selected) {
+          for (var i = vars.id.nesting.length-1; i >= 0; i--) {
+            var level = vars.id.nesting[i]
+            if (level in data_obj) {
+              vars.self.focus(data_obj[level])
+              break
+            }
+          }
+        }
+
+      })
+
+  }
+  else if ( elementTag === "input" && elementType === "radio" ) {
+
+    var elementName = vars.data.element.value.node().getAttribute("name")
+    if ( elementName ) {
+      vars.self.container({"id": elementName})
+    }
+
+    vars.data.element.value
+      .each(function( o , i ){
+
+        var data_obj = {}
+
+        get_attributes(data_obj,this)
+
+        var id = data_obj[vars.id.value] || this.id || false
+
+        if ( id && isNaN(parseFloat(id)) ) {
+
+          var label = d3.select("label[for="+id+"]")
+
+          if ( !label.empty() ) {
+            data_obj.text = label.html()
+            label.call(hideElement)
+          }
+
+        }
+
+        elementData.push(data_obj)
+
+        if (this.checked) {
+          vars.self.focus(data_obj[vars.id.value])
+        }
+
+      })
+
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Get focus from data, if it hasn't been found or set.
+  //----------------------------------------------------------------------------
+  if ( !vars.focus.value.length && elementData.length ) {
+
+    vars.data.element.value.node().selectedIndex = 0
+    vars.self.focus(elementData[0][vars.id.value])
+
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // If a <legend> element exists, use it as the title.
+  //----------------------------------------------------------------------------
+  var elementLegend = d3.select("legend[for="+vars.container.id+"]")
+  if ( !elementLegend.empty() ) {
+
+    vars.self.title(elementLegend.html())
+    elementLegend.call(hideElement)
+
+  }
+
+  var containerTag = vars.container.value
+                   ? vars.container.value.node().tagName.toLowerCase() : false
+
+  if ( vars.container.value === false || containerTag === "body" ) {
+    vars.container.value = d3.select(vars.data.element.value.node().parentNode)
+  }
+
+  vars.data.element.value.call(hideElement)
+
+  return elementData
+
+};
+
+},{"./hideElement.js":96}],96:[function(require,module,exports){
+module.exports = function(elem) {
+
+  elem
+    .style("position","absolute","important")
+    .style("clip","rect(1px 1px 1px 1px)","important")
+    .style("clip","rect(1px, 1px, 1px, 1px)","important")
+    .style("width","1px","important")
+    .style("height","1px","important")
+    .style("margin","-1px","important")
+    .style("padding","0","important")
+    .style("border","0","important")
+    .style("overflow","hidden","important");
+
+}
+
+},{}],97:[function(require,module,exports){
+var print = require("../console/print.coffee");
+
+// Calculates node positions, if needed for network.
+module.exports = function(vars) {
+
+  if (vars.dev.value) {
+    var timerString = "analyzing node positions";
+    print.time(timerString);
+  }
+
+  var set = vars.nodes.value.filter(function(n){
+    return typeof n.x === "number" && typeof n.y === "number";
+  }).length;
+
+  if (set === vars.nodes.value.length) {
+    vars.nodes.positions = true;
+  }
+  else {
+
+    var force = d3.layout.force()
+      .size([vars.width.viz, vars.height.viz])
+      .nodes(vars.nodes.value)
+      .links(vars.edges.value);
+
+    var strength = vars.edges.strength.value;
+    if (strength) {
+      if (typeof strength === "string") {
+        force.linkStrength(function(e){
+          return e[strength];
+        });
+      }
+      else {
+        force.linkStrength(strength);
+      }
+    }
+
+    var iterations = 50,
+        threshold = 0.01;
+
+    force.start(); // Defaults to alpha = 0.1
+    for (var i = iterations; i > 0; --i) {
+      force.tick();
+      if(force.alpha() < threshold) {
+        break;
+      }
+    }
+    force.stop();
+
+    vars.nodes.positions = true;
+
+  }
+
+  if (vars.dev.value) print.timeEnd(timerString);
+
+}
+
+},{"../console/print.coffee":53}],98:[function(require,module,exports){
+var numeric;
+
+numeric = require('numeric');
+
+module.exports = function(data, options) {
+  var N, X, Xfulltr, Xtr, bestResult, beta_hat, bic, degree, degrees, i, j, k, l, loglike, m, point, prevBIC, q, ref, ref1, residual, sigma2, sse, y, y_hat;
+  if (options == null) {
+    options = {};
+  }
+  if (options.maxDegree == null) {
+    options.maxDegree = 5;
+  }
+  N = data.length;
+  prevBIC = Number.MAX_VALUE;
+  bestResult = null;
+  Xfulltr = (function() {
+    var l, ref, results;
+    results = [];
+    for (degree = l = 1, ref = options.maxDegree + 1; 1 <= ref ? l < ref : l > ref; degree = 1 <= ref ? ++l : --l) {
+      results.push((function() {
+        var len, m, results1;
+        results1 = [];
+        for (m = 0, len = data.length; m < len; m++) {
+          point = data[m];
+          results1.push(Math.pow(point[0], degree));
+        }
+        return results1;
+      })());
+    }
+    return results;
+  })();
+  y = (function() {
+    var l, len, results;
+    results = [];
+    for (l = 0, len = data.length; l < len; l++) {
+      point = data[l];
+      results.push(point[1]);
+    }
+    return results;
+  })();
+  for (i = l = 0, ref = 1 << options.maxDegree; 0 <= ref ? l < ref : l > ref; i = 0 <= ref ? ++l : --l) {
+    Xtr = [
+      (function() {
+        var m, ref1, results;
+        results = [];
+        for (q = m = 0, ref1 = N; 0 <= ref1 ? m < ref1 : m > ref1; q = 0 <= ref1 ? ++m : --m) {
+          results.push(1);
+        }
+        return results;
+      })()
+    ];
+    degrees = [0];
+    for (j = m = 0, ref1 = options.maxDegree; 0 <= ref1 ? m < ref1 : m > ref1; j = 0 <= ref1 ? ++m : --m) {
+      if ((i & 1 << j) > 0) {
+        Xtr.push(Xfulltr[j]);
+        degrees.push(j + 1);
+      }
+    }
+    X = numeric.transpose(Xtr);
+    k = degrees.length;
+    beta_hat = numeric.dot(numeric.dot(numeric.inv(numeric.dot(Xtr, X)), Xtr), y);
+    y_hat = numeric.dot(X, beta_hat);
+    residual = numeric.sub(y, y_hat);
+    sse = numeric.dot(residual, residual);
+    sigma2 = sse / (N - k);
+    loglike = -0.5 * N * Math.log(2 * Math.PI) - 0.5 * N * Math.log(sigma2) - sse / (2 * sigma2);
+    bic = -2 * loglike + k * (Math.log(N) - Math.log(2 * Math.PI));
+    if (bic < prevBIC) {
+      prevBIC = bic;
+      bestResult = [degrees, beta_hat, y_hat];
+    }
+  }
+  return bestResult;
+};
+
+
+},{"numeric":7}],99:[function(require,module,exports){
+var kdtree;
+
+kdtree = require('static-kdtree');
+
+module.exports = function(points, K) {
+  var avg_lrd, i, j, kdists, ldr, ldrs, neighbors, p, reachDist, result, sqDist, tree;
+  if (K == null) {
+    K = 10;
+  }
+  tree = kdtree(points);
+  neighbors = (function() {
+    var k, len, results;
+    results = [];
+    for (k = 0, len = points.length; k < len; k++) {
+      p = points[k];
+      results.push(tree.knn(p, K + 1).slice(1));
+    }
+    return results;
+  })();
+  sqDist = function(i, j) {
+    var A, B, delta, dist, k, ref;
+    A = points[i];
+    B = points[j];
+    dist = 0;
+    for (i = k = 0, ref = A.length; 0 <= ref ? k < ref : k > ref; i = 0 <= ref ? ++k : --k) {
+      delta = A[i] - B[i];
+      dist += delta * delta;
+    }
+    return dist;
+  };
+  kdists = (function() {
+    var k, ref, results;
+    results = [];
+    for (i = k = 0, ref = points.length; 0 <= ref ? k < ref : k > ref; i = 0 <= ref ? ++k : --k) {
+      results.push(sqDist(i, neighbors[i][K - 1]));
+    }
+    return results;
+  })();
+  reachDist = function(i, j) {
+    return Math.max(sqDist(i, j), kdists[j]);
+  };
+  ldr = function(i) {
+    var j, k, len, rDist, ref;
+    rDist = 0;
+    ref = neighbors[i];
+    for (k = 0, len = ref.length; k < len; k++) {
+      j = ref[k];
+      rDist += reachDist(i, j);
+    }
+    return K / rDist;
+  };
+  ldrs = (function() {
+    var k, ref, results;
+    results = [];
+    for (i = k = 0, ref = points.length; 0 <= ref ? k < ref : k > ref; i = 0 <= ref ? ++k : --k) {
+      results.push(ldr(i));
+    }
+    return results;
+  })();
+  result = (function() {
+    var k, l, len, ref, ref1, results;
+    results = [];
+    for (i = k = 0, ref = points.length; 0 <= ref ? k < ref : k > ref; i = 0 <= ref ? ++k : --k) {
+      avg_lrd = 0;
+      ref1 = neighbors[i];
+      for (l = 0, len = ref1.length; l < len; l++) {
+        j = ref1[l];
+        avg_lrd += ldrs[j];
+      }
+      avg_lrd /= K;
+      results.push([i, avg_lrd / ldrs[i]]);
+    }
+    return results;
+  })();
+  return result.sort(function(a, b) {
+    return b[1] - a[1];
+  });
+};
+
+
+},{"static-kdtree":9}],100:[function(require,module,exports){
+module.exports = function(points) {
+  var mad, median, result;
+  median = d3.median(points);
+  mad = d3.median(points.map(function(p) {
+    return Math.abs(p - median);
+  }));
+  result = points.map(function(p, i) {
+    return [i, Math.abs(p - median) / mad];
+  });
+  return result.sort(function(a, b) {
+    return b[1] - a[1];
+  });
+};
+
+
+},{}],101:[function(require,module,exports){
+var fontTester, getHeight, getWidth;
+
+fontTester = require("../core/font/tester.coffee");
+
+module.exports = function(words, style, opts) {
+  var attr, sizes, tester, tspans;
+  if (!opts) {
+    opts = {};
+  }
+  tester = opts.parent || fontTester("svg").append("text");
+  style = style || {};
+  sizes = [];
+  if (!(words instanceof Array)) {
+    words = [words];
+  }
+  tspans = tester.selectAll("tspan").data(words);
+  attr = {
+    left: "0px",
+    position: "absolute",
+    top: "0px",
+    x: 0,
+    y: 0
+  };
+  tspans.enter().append("tspan").text(String).style(style).attr(attr).each(function(d) {
+    if (typeof opts.mod === "function") {
+      return opts.mod(this);
+    }
+  }).each(function(d) {
+    var children, height, width;
+    children = d3.select(this).selectAll("tspan");
+    if (children.size()) {
+      width = [];
+      children.each(function() {
+        return width.push(getWidth(this));
+      });
+      width = d3.max(width);
+    } else {
+      width = getWidth(this);
+    }
+    height = getHeight(this);
+    return sizes.push({
+      height: height,
+      text: d,
+      width: width
+    });
+  });
+  tspans.remove();
+  if (!opts.parent) {
+    tester.remove();
+  }
+  return sizes;
+};
+
+getWidth = function(elem) {
+  return elem.getComputedTextLength();
+};
+
+getHeight = function(elem) {
+  return elem.offsetHeight || elem.getBoundingClientRect().height || elem.parentNode.getBBox().height;
+};
+
+
+},{"../core/font/tester.coffee":69}],102:[function(require,module,exports){
+var fontTester, validate;
+
+fontTester = require("../core/font/tester.coffee");
+
+validate = function(fontList) {
+  var completed, family, font, fontString, i, j, len, len1, monospace, proportional, testElement, testWidth, tester, valid;
+  if (!(fontList instanceof Array)) {
+    fontList = fontList.split(",");
+  }
+  for (i = 0, len = fontList.length; i < len; i++) {
+    font = fontList[i];
+    font.trim();
+  }
+  fontString = fontList.join(", ");
+  completed = validate.complete;
+  if (fontString in completed) {
+    return completed[fontString];
+  }
+  testElement = function(font) {
+    return tester.append("span").style("font-family", font).style("font-size", "32px").style("padding", "0px").style("margin", "0px").text("abcdefghiABCDEFGHI_!@#$%^&*()_+1234567890");
+  };
+  testWidth = function(font, control) {
+    var elem, width1, width2;
+    elem = testElement(font);
+    width1 = elem.node().offsetWidth;
+    width2 = control.node().offsetWidth;
+    elem.remove();
+    return width1 !== width2;
+  };
+  tester = fontTester("div");
+  monospace = testElement("monospace");
+  proportional = testElement("sans-serif");
+  for (j = 0, len1 = fontList.length; j < len1; j++) {
+    family = fontList[j];
+    valid = testWidth(family + ",monospace", monospace);
+    if (!valid) {
+      valid = testWidth(family + ",sans-serif", proportional);
+    }
+    if (valid) {
+      valid = family;
+      break;
+    }
+  }
+  if (!valid) {
+    valid = "sans-serif";
+  }
+  monospace.remove();
+  proportional.remove();
+  completed[fontString] = valid;
+  return valid;
+};
+
+validate.complete = {};
+
+module.exports = validate;
+
+
+},{"../core/font/tester.coffee":69}],103:[function(require,module,exports){
+var arraySort = require("../array/sort.coffee"),
+    attach      = require("../core/methods/attach.coffee"),
+    dataFormat  = require("../core/data/format.js"),
+    dataKeys    = require("../core/data/keys.coffee"),
+    dataLoad    = require("../core/data/load.coffee"),
+    fetchData   = require("../core/fetch/data.js"),
+    ie          = require("../client/ie.js"),
+    methodReset = require("../core/methods/reset.coffee"),
+    print       = require("../core/console/print.coffee");
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Form Element shell
+//------------------------------------------------------------------------------
+module.exports = function() {
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Initialize the global variable object.
+  //----------------------------------------------------------------------------
+  var vars = {
+    "types": {
+      "auto": require("./types/auto.js"),
+      "button": require("./types/button/button.coffee"),
+      "drop": require("./types/drop/drop.coffee"),
+      "toggle": require("./types/toggle.js")
+    }
+  };
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Create the main drawing function.
+  //----------------------------------------------------------------------------
+  vars.self = function( selection ) {
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Set timing to 0 if it's the first time running this function or if the
+    // data length is longer than the "large" limit
+    //--------------------------------------------------------------------------
+    var large = vars.data.value instanceof Array && vars.data.value.length > vars.data.large;
+
+    vars.draw.timing = vars.draw.first || large || ie ? 0 : vars.timing.ui;
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Create/update the UI element
+    //--------------------------------------------------------------------------
+    if ( vars.data.value instanceof Array ) {
+
+      if ( vars.dev.value ) print.group("drawing \""+vars.type.value+"\"");
+
+      //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+      // Analyze new data, if changed.
+      //------------------------------------------------------------------------
+      if ( vars.data.changed ) {
+        vars.data.cache = {};
+        dataKeys( vars , "data" );
+        dataFormat( vars );
+      }
+
+      vars.data.viz = fetchData( vars );
+
+      //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+      // Sort the data, if needed.
+      //------------------------------------------------------------------------
+      if (vars.data.sort.value && (vars.data.changed || vars.order.changed || vars.order.sort.changed) ) {
+        arraySort( vars.data.viz , vars.order.value || vars.text.value,
+                   vars.order.sort.value , vars.color.value , vars );
+      }
+
+      //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+      // Set first element in data as focus if there is no focus set.
+      //------------------------------------------------------------------------
+      if (vars.focus.value === false && ["auto", "button"].indexOf(vars.type.value) < 0) {
+
+        var element = vars.data.element.value;
+
+        if ( element && element.node().tagName.toLowerCase() === "select" ) {
+          var i = element.property("selectedIndex");
+          i = i < 0 ? 0 : i;
+          var option = element.selectAll("option")[0][i],
+              val = option.getAttribute("data-"+vars.id.value) || option.getAttribute(vars.id.value);
+          if (val) vars.focus.value = val;
+        }
+
+        if ( vars.focus.value === false && vars.data.viz.length ) {
+          vars.focus.value = vars.data.viz[0][vars.id.value];
+        }
+
+        if ( vars.dev.value && vars.focus.value ) print.log("\"value\" set to \""+vars.focus.value+"\"");
+
+      }
+
+      var getLevel = function(d,depth) {
+
+        depth = typeof depth !== "number" ? vars.id.nesting.length === 1 ? 0 : vars.id.nesting.length-1 : depth;
+        var level = vars.id.nesting[depth];
+
+        if ( depth > 0 && (!(level in d) || d[level] instanceof Array) ) {
+          return getLevel(d,depth-1);
+        }
+        else {
+          return level;
+        }
+
+      };
+
+      //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+      // Run these things if the data has changed.
+      //------------------------------------------------------------------------
+      if ( vars.data.changed ) {
+
+        //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        // Determine if search box is needed.
+        //----------------------------------------------------------------------
+        if ( vars.search.value === "auto" ) {
+
+          if (vars.data.viz.length > 10) {
+            vars.search.enabled = true;
+            if ( vars.dev.value ) print.log("Search enabled.");
+          }
+          else {
+            vars.search.enabled = false;
+            if ( vars.dev.value ) print.log("Search disabled.");
+          }
+
+        }
+        else {
+
+          vars.search.enabled = vars.search.value;
+
+        }
+
+        //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        // Update OPTION elements with the new data.
+        //----------------------------------------------------------------------
+        var elementTag = vars.data.element.value ? vars.data.element.value.node().tagName.toLowerCase() : "";
+        if ( vars.data.element.value && elementTag === "select" ) {
+
+          var optionData = [];
+          for (var level in vars.data.nested.all) {
+            optionData = optionData.concat(vars.data.nested.all[level]);
+          }
+
+          options = vars.data.element.value.selectAll("option")
+            .data(optionData,function(d){
+              var level = d ? getLevel(d) : false;
+              return d && level in d ? d[level] : false;
+            });
+
+          options.exit().remove();
+
+          options.enter().append("option");
+
+          options
+            .each(function(d){
+
+              var level   = getLevel(d),
+                  textKey = level === vars.id.value ? vars.text.value || vars.id.value
+                          : vars.text.nesting !== true && level in vars.text.nesting ? vars.text.nesting[level] : level;
+
+              for ( var k in d ) {
+
+                if ( typeof d[k] !== "object" ) {
+
+                  if ( k === textKey ) {
+                    d3.select(this).html(d[k]);
+                  }
+
+                  if ( ["alt","value"].indexOf(k) >= 0 ) {
+                    d3.select(this).attr(k,d[k]);
+                  }
+                  else {
+                    d3.select(this).attr("data-"+k,d[k]);
+                  }
+
+                }
+
+              }
+
+              if (d[level] === vars.focus.value) {
+                this.selected = true;
+              }
+              else {
+                this.selected = false;
+              }
+
+            });
+
+        }
+
+      }
+      else if (vars.focus.changed && vars.data.element.value) {
+        var tag = vars.data.element.value.node().tagName.toLowerCase();
+        if (tag === "select") {
+          vars.data.element.value.selectAll("option")
+            .each(function(d){
+              if (d[getLevel(d)] === vars.focus.value) {
+                this.selected = true;
+              }
+              else {
+                this.selected = false;
+              }
+            });
+        }
+        else {
+          var tag = vars.data.element.value.attr("type").toLowerCase();
+          if (tag === "radio") {
+            vars.data.element.value
+              .each(function(d){
+                if (this.value === vars.focus.value) {
+                  this.checked = true;
+                }
+                else {
+                  this.checked = false;
+                }
+              })
+          }
+        }
+      }
+
+      if ( vars.type.value !== "auto" ) {
+
+        if ( !vars.container.ui ) {
+
+          //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+          // Select container DIV for UI element
+          //----------------------------------------------------------------------
+          vars.container.ui = vars.container.value
+            .selectAll("div#d3plus_"+vars.type.value+"_"+vars.container.id)
+            .data(["container"]);
+
+          //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+          // Create container DIV for UI element
+          //----------------------------------------------------------------------
+          var before = vars.data.element.value ? vars.data.element.value[0][0] : null;
+
+          if ( before ) {
+
+            if ( before.id ) {
+              before = "#"+before.id;
+            }
+            else {
+
+              var id = before.getAttribute(vars.id.value) ? vars.id.value : "data-"+vars.id.value;
+
+              if ( before.getAttribute(id) ) {
+                before = "["+id+"="+before.getAttribute(id)+"]";
+              }
+              else {
+                before = null;
+              }
+
+            }
+
+          }
+
+          vars.container.ui.enter()
+            .insert("div",before)
+            .attr("id","d3plus_"+vars.type.value+"_"+vars.container.id)
+            .style("position","relative")
+            .style("overflow","visible")
+            .style("vertical-align","top");
+
+        }
+
+        //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        // Update Container
+        //------------------------------------------------------------------------
+        vars.container.ui
+          .style("display", vars.ui.display.value);
+
+        vars.container.ui.transition().duration(vars.draw.timing)
+          .style("margin", vars.ui.margin.css);
+
+        //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        // Create title, if available.
+        //------------------------------------------------------------------------
+        var title = vars.container.ui.selectAll("div.d3plus_title")
+          .data(vars.title.value ? [vars.title.value] : []);
+
+        title.enter().insert("div","#d3plus_"+vars.type.value+"_"+vars.container.id)
+          .attr("class","d3plus_title")
+          .style("display","inline-block");
+
+        title
+          .style("color",vars.font.color)
+          .style("font-family",vars.font.family.value)
+          .style("font-size",vars.font.size+"px")
+          .style("font-weight",vars.font.weight)
+          .style("padding",vars.ui.padding.css)
+          .style("border-color","transparent")
+          .style("border-style","solid")
+          .style("border-width",vars.ui.border+"px")
+          .text(String)
+          .each(function(d){
+            vars.margin.left = this.offsetWidth;
+          });
+
+      }
+
+      //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+      // Call specific UI element type, if there is data.
+      //------------------------------------------------------------------------
+      if ( vars.data.value.length ) {
+
+        var app = vars.format.locale.value.visualization[vars.type.value];
+        if ( vars.dev.value ) print.time("drawing "+ app);
+        vars.types[vars.type.value]( vars );
+        if ( vars.dev.value ) print.timeEnd("drawing "+ app);
+
+      }
+      else if ( vars.data.url && (!vars.data.loaded || vars.data.stream) ) {
+
+        dataLoad( vars , "data" , vars.self.draw );
+
+      }
+
+      //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+      // Initialization complete
+      //------------------------------------------------------------------------
+      if (vars.dev.value) print.timeEnd("total draw time");
+      methodReset( vars );
+
+    }
+
+  };
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Define methods and expose public variables.
+  //----------------------------------------------------------------------------
+  attach(vars, {
+    "active":    require("./methods/active.coffee"),
+    "alt":       require("./methods/alt.coffee"),
+    "color":     require("./methods/color.coffee"),
+    "config":    require("./methods/config.coffee"),
+    "container": require("./methods/container.coffee"),
+    "data":      require("./methods/data.js"),
+    "depth":     require("./methods/depth.coffee"),
+    "dev":       require("./methods/dev.coffee"),
+    "draw":      require("./methods/draw.js"),
+    "focus":     require("./methods/focus.coffee"),
+    "font":      require("./methods/font.coffee"),
+    "format":    require("./methods/format.coffee"),
+    "height":    require("./methods/height.coffee"),
+    "history":   require("./methods/history.coffee"),
+    "hover":     require("./methods/hover.coffee"),
+    "icon":      require("./methods/icon.coffee"),
+    "id":        require("./methods/id.coffee"),
+    "keywords":  require("./methods/keywords.coffee"),
+    "margin":    require("./methods/margin.coffee"),
+    "open":      require("./methods/open.coffee"),
+    "order":     require("./methods/order.coffee"),
+    "remove":    require("./methods/remove.coffee"),
+    "search":    require("./methods/search.coffee"),
+    "select":    require("./methods/select.coffee"),
+    "selectAll": require("./methods/selectAll.coffee"),
+    "text":      require("./methods/text.coffee"),
+    "timing":    require("./methods/timing.coffee"),
+    "title":     require("./methods/title.coffee"),
+    "type":      require("./methods/type.coffee"),
+    "ui":        require("./methods/ui.coffee"),
+    "width":     require("./methods/width.coffee")
+  });
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Finally, return the main UI function to the user
+  //----------------------------------------------------------------------------
+  return vars.self;
+
+};
+
+},{"../array/sort.coffee":36,"../client/ie.js":39,"../core/console/print.coffee":53,"../core/data/format.js":57,"../core/data/keys.coffee":59,"../core/data/load.coffee":60,"../core/fetch/data.js":65,"../core/methods/attach.coffee":79,"../core/methods/reset.coffee":92,"./methods/active.coffee":104,"./methods/alt.coffee":105,"./methods/color.coffee":106,"./methods/config.coffee":107,"./methods/container.coffee":108,"./methods/data.js":109,"./methods/depth.coffee":110,"./methods/dev.coffee":111,"./methods/draw.js":112,"./methods/focus.coffee":113,"./methods/font.coffee":114,"./methods/format.coffee":115,"./methods/height.coffee":116,"./methods/history.coffee":117,"./methods/hover.coffee":118,"./methods/icon.coffee":119,"./methods/id.coffee":120,"./methods/keywords.coffee":121,"./methods/margin.coffee":122,"./methods/open.coffee":123,"./methods/order.coffee":124,"./methods/remove.coffee":125,"./methods/search.coffee":126,"./methods/select.coffee":127,"./methods/selectAll.coffee":128,"./methods/text.coffee":129,"./methods/timing.coffee":130,"./methods/title.coffee":131,"./methods/type.coffee":132,"./methods/ui.coffee":133,"./methods/width.coffee":134,"./types/auto.js":135,"./types/button/button.coffee":136,"./types/drop/drop.coffee":141,"./types/toggle.js":158}],104:[function(require,module,exports){
+var filter;
+
+filter = require("../../core/methods/filter.coffee");
+
+module.exports = {
+  accepted: [false, Array, Function, Number, String],
+  value: false
+};
+
+
+},{"../../core/methods/filter.coffee":80}],105:[function(require,module,exports){
+var filter;
+
+filter = require("../../core/methods/filter.coffee");
+
+module.exports = {
+  accepted: [false, Array, Function, Object, String],
+  mute: filter(true),
+  solo: filter(true),
+  value: "alt"
+};
+
+
+},{"../../core/methods/filter.coffee":80}],106:[function(require,module,exports){
+module.exports = {
+  accepted: [String],
+  value: "color"
+};
+
+
+},{}],107:[function(require,module,exports){
+module.exports = {
+  accepted: [Object],
+  objectAccess: false,
+  process: function(value, vars) {
+    var method, setting;
+    for (method in value) {
+      setting = value[method];
+      if (method in vars.self) {
+        vars.self[method](setting);
+      }
+    }
+    return value;
+  },
+  value: {}
+};
+
+
+},{}],108:[function(require,module,exports){
+var d3selection;
+
+d3selection = require("../../util/d3selection.coffee");
+
+module.exports = {
+  accepted: [false, Array, Object, String],
+  element: false,
+  id: "default",
+  process: function(value) {
+    if (value === false) {
+      return d3.select("body");
+    } else if (d3selection(value)) {
+      return value;
+    } else if (value instanceof Array) {
+      return d3.select(value[0][0]);
+    } else {
+      return d3.select(value);
+    }
+  },
+  value: d3.select("body")
+};
+
+
+},{"../../util/d3selection.coffee":207}],109:[function(require,module,exports){
+var d3selection = require("../../util/d3selection.coffee"),
+    process = require("../../core/methods/process/data.coffee");
+
+module.exports = {
+  "accepted" : [ false , Array , Function , String ],
+  "delimiter" : {
+    "accepted" : [ String ],
+    "value"    : "|"
+  },
+  "element": {
+    "process": function(value, vars) {
+
+      var element = false;
+
+      if ( d3selection(value) ) {
+        element = value;
+      }
+      else if (typeof value === "string" && !d3.select(value).empty()) {
+        element = d3.select(value);
+      }
+
+      if (element) {
+        vars.self.container(d3.select(element.node().parentNode));
+      }
+
+      return element;
+
+    },
+    "value": false
+  },
+  "filetype" : {
+    "accepted" : [false, "json", "xml", "html", "csv", "dsv", "tsv", "txt"],
+    "value"    : false
+  },
+  "filters"  : [],
+  "large": 400,
+  "mute"     : [],
+  "process"  : function(value, vars) {
+
+    if ( vars.container.id === "default" && value.length ) {
+      vars.self.container({"id": "default"+value.length});
+    }
+
+    return process(value, vars, this);
+  },
+  "solo"     : [],
+  "sort": {
+    "accepted": [Boolean],
+    "value":    false
+  },
+  "value"    : false
+};
+
+},{"../../core/methods/process/data.coffee":86,"../../util/d3selection.coffee":207}],110:[function(require,module,exports){
+module.exports = {
+  accepted: [Number],
+  value: 0
+};
+
+
+},{}],111:[function(require,module,exports){
+module.exports = {
+  accepted: [Boolean],
+  value: false
+};
+
+
+},{}],112:[function(require,module,exports){
+var d3selection  = require("../../util/d3selection.coffee"),
+    hideElement  = require("../../core/parse/hideElement.js"),
+    parseElement = require("../../core/parse/element.js"),
+    print        = require("../../core/console/print.coffee"),
+    stringFormat = require("../../string/format.js")
+
+module.exports = {
+  "accepted" : [ undefined , Function ],
+  "first"    : true,
+  "frozen"   : false,
+  "process"  : function (value, vars) {
+
+    if ( this.initialized === false ) {
+      this.initialized = true
+      return value
+    }
+
+    if (vars.data.value && (!(vars.data.value instanceof Array) || d3selection(vars.data.value))) {
+      vars.data.value = parseElement( vars )
+    }
+    else if (vars.data.element.value) {
+      vars.data.element.value.call(hideElement);
+    }
+
+    if ( value === undefined && typeof this.value === "function" ) {
+      value = this.value
+    }
+
+    if ( vars.container.value === false ) {
+
+      var str = vars.format.locale.value.dev.setContainer
+      print.warning( str , "container" )
+
+    }
+    else if ( vars.container.value.empty() ) {
+
+      var str = vars.format.locale.value.dev.noContainer
+      print.warning( stringFormat(str,"\""+vars.container.value+"\"") , "container" )
+
+    }
+    else {
+
+      if (vars.dev.value) print.time("total draw time");
+
+      vars.container.value.call(vars.self);
+
+    }
+
+    if ( typeof value === "function" && vars.history.chain.length ) {
+
+      var changesObject = {}
+      changes.forEach(function(c){
+        var method = c.method
+        delete c.method
+        changesObject[method] = c
+      })
+
+      value(changesObject)
+
+      vars.history.chain = []
+
+    }
+
+    return value
+
+  },
+  "update"   : true,
+  "value"    : undefined
+}
+
+},{"../../core/console/print.coffee":53,"../../core/parse/element.js":95,"../../core/parse/hideElement.js":96,"../../string/format.js":172,"../../util/d3selection.coffee":207}],113:[function(require,module,exports){
+module.exports = {
+  accepted: [false, Number, String],
+  deprecates: "highlight",
+  process: function(value, vars) {
+    var d, element, elementTag, elementType, i, j, k, len, len1, ref;
+    element = vars.data.element.value;
+    if (element && ["string", "number"].indexOf(typeof value) >= 0) {
+      elementTag = element.node().tagName.toLowerCase();
+      elementType = element.attr("type");
+      if (elementTag === "select") {
+        ref = element.selectAll("option");
+        for (i = j = 0, len = ref.length; j < len; i = ++j) {
+          d = ref[i];
+          if (d && d[vars.id.value] === value) {
+            element.node().selectedIndex = i;
+          }
+        }
+      } else if (elementTag === "input" && elementType === "radio") {
+        for (k = 0, len1 = element.length; k < len1; k++) {
+          d = element[k];
+          this.checked = d && d[vars.id.value] === value;
+        }
+      }
+    }
+    return value;
+  },
+  value: false
+};
+
+
+},{}],114:[function(require,module,exports){
+var align, decoration, family, transform;
+
+family = require("../../core/methods/font/family.coffee");
+
+align = require("../../core/methods/font/align.coffee");
+
+decoration = require("../../core/methods/font/decoration.coffee");
+
+transform = require("../../core/methods/font/transform.coffee");
+
+module.exports = {
+  align: align(),
+  color: "#444444",
+  decoration: decoration(),
+  family: family(),
+  secondary: {
+    align: align(),
+    color: "#444444",
+    decoration: decoration(),
+    family: family(),
+    size: 12,
+    spacing: 0,
+    transform: transform(),
+    weight: 200
+  },
+  size: 12,
+  spacing: 0,
+  transform: transform(),
+  weight: 200
+};
+
+
+},{"../../core/methods/font/align.coffee":81,"../../core/methods/font/decoration.coffee":82,"../../core/methods/font/family.coffee":83,"../../core/methods/font/transform.coffee":85}],115:[function(require,module,exports){
+var formatNumber, locale, mergeObject, titleCase;
+
+formatNumber = require("../../number/format.coffee");
+
+locale = require("../../core/locale/locale.coffee");
+
+mergeObject = require("../../object/merge.coffee");
+
+titleCase = require("../../string/title.coffee");
+
+module.exports = {
+  accepted: [Function, String],
+  affixes: {
+    accepted: [Object],
+    objectAccess: false,
+    value: {}
+  },
+  deprecates: ["number_format", "text_format"],
+  locale: {
+    accepted: function() {
+      return d3.keys(locale);
+    },
+    process: function(value) {
+      var defaultLocale, returnObject;
+      defaultLocale = "en_US";
+      returnObject = locale[defaultLocale];
+      if (value !== defaultLocale) {
+        returnObject = mergeObject(returnObject, locale[value]);
+      }
+      this.language = value;
+      return returnObject;
+    },
+    value: "en_US"
+  },
+  number: {
+    accepted: [false, Function],
+    value: false
+  },
+  process: function(value, vars) {
+    if (typeof value === "string") {
+      vars.self.format({
+        locale: value
+      });
+    } else {
+      if (typeof value === "function") {
+        return value;
+      }
+    }
+    return this.value;
+  },
+  text: {
+    accepted: [false, Function],
+    value: false
+  },
+  value: function(value, opts) {
+    var f, v, vars;
+    if (!opts) {
+      opts = {};
+    }
+    vars = opts.vars || {};
+    if (vars.time && vars.time.value && opts.key === vars.time.value) {
+      v = value.constructor === Date ? value : new Date(value);
+      return vars.data.time.format(v);
+    } else if (typeof value === "number") {
+      f = this.number.value || formatNumber;
+      return f(value, opts);
+    } else if (typeof value === "string") {
+      f = this.text.value || titleCase;
+      return f(value, opts);
+    } else {
+      return JSON.stringify(value);
+    }
+  }
+};
+
+
+},{"../../core/locale/locale.coffee":78,"../../number/format.coffee":169,"../../object/merge.coffee":170,"../../string/title.coffee":175}],116:[function(require,module,exports){
+module.exports = {
+  accepted: [false, Number],
+  max: 600,
+  secondary: false,
+  value: false
+};
+
+
+},{}],117:[function(require,module,exports){
+module.exports = {
+  back: function() {
+    if (this.states.length) {
+      return this.states.pop()();
+    }
+  },
+  chain: [],
+  reset: function() {
+    var results;
+    results = [];
+    while (this.states.length) {
+      results.push(this.states.pop()());
+    }
+    return results;
+  },
+  states: []
+};
+
+
+},{}],118:[function(require,module,exports){
+module.exports = {
+  accepted: [Boolean, Number, String],
+  value: false
+};
+
+
+},{}],119:[function(require,module,exports){
+var process;
+
+process = require("../../core/methods/process/icon.coffee");
+
+module.exports = {
+  accepted: [false, Array, Function, Object, String],
+  back: {
+    accepted: [false, String],
+    fallback: "&#x276e;",
+    opacity: 1,
+    process: process,
+    rotate: 0,
+    value: "fa-angle-left"
+  },
+  button: {
+    accepted: [false, String],
+    fallback: false,
+    opacity: 1,
+    process: process,
+    rotate: 0,
+    value: false
+  },
+  drop: {
+    accepted: [false, String],
+    fallback: "&#x276f;",
+    opacity: 1,
+    process: process,
+    rotate: 0,
+    value: "fa-angle-down"
+  },
+  next: {
+    accepted: [false, String],
+    fallback: "&#x276f;",
+    opacity: 1,
+    process: process,
+    rotate: 0,
+    value: "fa-angle-right"
+  },
+  select: {
+    accepted: [false, String],
+    fallback: "&#x2713;",
+    opacity: 1,
+    process: process,
+    rotate: 0,
+    value: "fa-check"
+  },
+  style: {
+    accepted: [Object, String],
+    value: "default"
+  },
+  value: "icon"
+};
+
+
+},{"../../core/methods/process/icon.coffee":88}],120:[function(require,module,exports){
+var filter;
+
+filter = require("../../core/methods/filter.coffee");
+
+module.exports = {
+  accepted: [Array, String],
+  dataFilter: true,
+  mute: filter(true),
+  nesting: ["value"],
+  solo: filter(true),
+  value: "value"
+};
+
+
+},{"../../core/methods/filter.coffee":80}],121:[function(require,module,exports){
+var filter;
+
+filter = require("../../core/methods/filter.coffee");
+
+module.exports = {
+  accepted: [false, Array, Function, Object, String],
+  mute: filter(true),
+  solo: filter(true),
+  value: "keywords"
+};
+
+
+},{"../../core/methods/filter.coffee":80}],122:[function(require,module,exports){
+var process;
+
+process = require("../../core/methods/process/margin.coffee");
+
+module.exports = {
+  accepted: [Number, Object, String],
+  process: function(value) {
+    var userValue;
+    if (value === void 0) {
+      value = this.value;
+    }
+    userValue = value;
+    process(value, this);
+    return userValue;
+  },
+  value: 0
+};
+
+
+},{"../../core/methods/process/margin.coffee":89}],123:[function(require,module,exports){
+module.exports = {
+  accepted: [Boolean],
+  flipped: {
+    accepted: [Boolean],
+    value: false
+  },
+  value: false
+};
+
+
+},{}],124:[function(require,module,exports){
+module.exports = {
+  accepted: [false, Function, String],
+  sort: {
+    accepted: ["asc", "desc"],
+    deprecates: ["sort"],
+    value: "asc"
+  },
+  value: false
+};
+
+
+},{}],125:[function(require,module,exports){
+module.exports = {
+  accepted: void 0,
+  process: function(value, vars) {
+    if (this.initialized) {
+      vars.container.value.remove();
+    }
+  },
+  value: void 0
+};
+
+
+},{}],126:[function(require,module,exports){
+module.exports = {
+  accepted: ["auto", Boolean],
+  process: function(value) {
+    if (typeof value === "Boolean") {
+      this.enabled = value;
+    }
+    return value;
+  },
+  term: "",
+  value: "auto"
+};
+
+
+},{}],127:[function(require,module,exports){
+module.exports = {
+  accepted: [String],
+  chainable: false,
+  process: function(value, vars) {
+    var container;
+    container = vars.container.value;
+    if (container && value) {
+      return container.select(value);
+    } else {
+      return value;
+    }
+  },
+  value: void 0
+};
+
+
+},{}],128:[function(require,module,exports){
+module.exports = {
+  accepted: [String],
+  chainable: false,
+  process: function(value, vars) {
+    var container;
+    container = vars.container.value;
+    if (container && value) {
+      return container.selectAll(value);
+    } else {
+      return value;
+    }
+  },
+  value: void 0
+};
+
+
+},{}],129:[function(require,module,exports){
+var filter;
+
+filter = require("../../core/methods/filter.coffee");
+
+module.exports = {
+  accepted: [false, String],
+  nesting: true,
+  mute: filter(true),
+  solo: filter(true),
+  secondary: {
+    accepted: [false, String],
+    nesting: true,
+    value: false
+  },
+  value: false
+};
+
+
+},{"../../core/methods/filter.coffee":80}],130:[function(require,module,exports){
+module.exports = {
+  mouseevents: 60,
+  ui: 200
+};
+
+
+},{}],131:[function(require,module,exports){
+var decoration, family, stringStrip, transform;
+
+decoration = require("../../core/methods/font/decoration.coffee");
+
+family = require("../../core/methods/font/family.coffee");
+
+transform = require("../../core/methods/font/transform.coffee");
+
+stringStrip = require("../../string/strip.js");
+
+module.exports = {
+  accepted: [false, Function, String],
+  font: {
+    align: "center",
+    color: "#444444",
+    decoration: decoration(),
+    family: family(),
+    size: 16,
+    transform: transform(),
+    weight: 400
+  },
+  link: false,
+  process: function(value, vars) {
+    var id;
+    if (vars.container.id.indexOf("default") === 0 && value) {
+      id = stringStrip(value).toLowerCase();
+      vars.self.container({
+        id: id
+      });
+    }
+    return value;
+  },
+  value: false
+};
+
+
+},{"../../core/methods/font/decoration.coffee":82,"../../core/methods/font/family.coffee":83,"../../core/methods/font/transform.coffee":85,"../../string/strip.js":174}],132:[function(require,module,exports){
+module.exports = {
+  accepted: function(vars) {
+    return d3.keys(vars.types);
+  },
+  value: "auto"
+};
+
+
+},{}],133:[function(require,module,exports){
+var align, decoration, family, margin, transform;
+
+family = require("../../core/methods/font/family.coffee");
+
+align = require("../../core/methods/font/align.coffee");
+
+decoration = require("../../core/methods/font/decoration.coffee");
+
+margin = require("../../core/methods/process/margin.coffee");
+
+transform = require("../../core/methods/font/transform.coffee");
+
+module.exports = {
+  align: align("center"),
+  border: 1,
+  color: {
+    primary: {
+      process: function(value, vars) {
+        var primary;
+        primary = this.value;
+        if (!vars.ui.color.secondary.value) {
+          vars.ui.color.secondary.value = d3.rgb(primary).darker(0.75).toString();
+        }
+        return value;
+      },
+      value: "#ffffff"
+    },
+    secondary: {
+      value: false
+    }
+  },
+  display: {
+    acceped: ["block", "inline-block"],
+    value: "inline-block"
+  },
+  font: {
+    align: align("center"),
+    color: "#444",
+    decoration: decoration(),
+    family: family(),
+    size: 11,
+    transform: transform(),
+    weight: 200
+  },
+  margin: {
+    process: function(value) {
+      var userValue;
+      if (value === void 0) {
+        value = this.value;
+      }
+      userValue = value;
+      margin(value, this);
+      return userValue;
+    },
+    value: 5
+  },
+  padding: {
+    process: function(value) {
+      var userValue;
+      if (value === void 0) {
+        value = this.value;
+      }
+      userValue = value;
+      margin(value, this);
+      return userValue;
+    },
+    value: 5
+  }
+};
+
+
+},{"../../core/methods/font/align.coffee":81,"../../core/methods/font/decoration.coffee":82,"../../core/methods/font/family.coffee":83,"../../core/methods/font/transform.coffee":85,"../../core/methods/process/margin.coffee":89}],134:[function(require,module,exports){
+module.exports = {
+  accepted: [false, Number],
+  secondary: false,
+  value: false
+};
+
+
+},{}],135:[function(require,module,exports){
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Determines form type based on data length.
+//------------------------------------------------------------------------------
+module.exports = function( vars ) {
+
+  var dataLength = vars.data.value.length
+
+  if ( dataLength === 1 ) {
+    vars.self.type("button").draw()
+  }
+  else if ( dataLength < 5 ) {
+    vars.self.type("toggle").draw()
+  }
+  else {
+    vars.self.type("drop").draw()
+  }
+
+}
+
+},{}],136:[function(require,module,exports){
+module.exports = function(vars) {
+  var button, checks, color, icons, mouseevents, print, style, updatedButtons;
+  print = require("../../../core/console/print.coffee");
+  color = require("./functions/color.coffee");
+  icons = require("./functions/icons.js");
+  mouseevents = require("./functions/mouseevents.coffee");
+  style = require("./functions/style.js");
+  button = vars.container.ui.selectAll('div.d3plus_node').data(vars.data.viz, function(d) {
+    return d[vars.id.value];
+  });
+  if (vars.dev.value) {
+    print.time("enter");
+  }
+  button.enter().append("div").attr("class", "d3plus_node").call(color, vars).call(style, vars).call(icons, vars).call(mouseevents, vars);
+  if (vars.dev.value) {
+    print.timeEnd("enter");
+  }
+  if (vars.draw.update || vars.draw.timing) {
+    if (vars.dev.value) {
+      print.time("ordering");
+    }
+    button.order();
+    if (vars.dev.value) {
+      print.timeEnd("ordering");
+    }
+    updatedButtons = button;
+  } else {
+    checks = [vars.focus.previous, vars.focus.value, vars.hover.previous, vars.hover.value].filter(function(c) {
+      return c;
+    });
+    updatedButtons = button.filter(function(b) {
+      return checks.indexOf(b[vars.id.value]) >= 0;
+    });
+  }
+  if (vars.dev.value) {
+    print.time("update");
+  }
+  if (vars.draw.timing) {
+    updatedButtons.transition().duration(vars.draw.timing).call(color, vars).call(style, vars);
+  } else {
+    updatedButtons.call(color, vars).call(style, vars);
+  }
+  updatedButtons.call(icons, vars).call(mouseevents, vars);
+  if (vars.dev.value) {
+    print.timeEnd("update");
+  }
+  return button.exit().remove();
+};
+
+
+},{"../../../core/console/print.coffee":53,"./functions/color.coffee":137,"./functions/icons.js":138,"./functions/mouseevents.coffee":139,"./functions/style.js":140}],137:[function(require,module,exports){
+module.exports = function(elem, vars) {
+  var legible, lighter, textColor;
+  legible = require("../../../../color/legible.coffee");
+  lighter = require("../../../../color/lighter.coffee");
+  textColor = require("../../../../color/text.coffee");
+  return elem.style("background-color", function(d) {
+    var color;
+    if (vars.focus.value === d[vars.id.value]) {
+      color = vars.ui.color.secondary.value;
+    } else {
+      color = vars.ui.color.primary.value;
+    }
+    if (vars.hover.value === d[vars.id.value]) {
+      color = d3.rgb(color).darker(0.15).toString();
+    }
+    return color;
+  }).style("color", function(d) {
+    var color, image, opacity;
+    if (vars.focus.value === d[vars.id.value]) {
+      opacity = 0.75;
+    } else {
+      opacity = 1;
+    }
+    image = d[vars.icon.value] && vars.data.viz.length < vars.data.large;
+    if (!image && d[vars.color.value]) {
+      color = legible(d[vars.color.value]);
+    } else {
+      color = textColor(d3.select(this).style("background-color"));
+    }
+    color = d3.rgb(color);
+    return "rgba(" + color.r + "," + color.g + "," + color.b + "," + opacity + ")";
+  }).style('border-color', vars.ui.color.secondary.value);
+};
+
+
+},{"../../../../color/legible.coffee":45,"../../../../color/lighter.coffee":46,"../../../../color/text.coffee":51}],138:[function(require,module,exports){
+var prefix = require("../../../../client/prefix.coffee"),
+    rtl = require("../../../../client/rtl.coffee")
+
+module.exports = function ( elem , vars ) {
+
+  var reversed = (vars.font.align.value === "right" && !rtl)
+                 || (rtl && vars.font.align.value === "right")
+
+  elem
+    .each(function(d,i){
+
+      var children = ["label"]
+
+      if ( d[vars.icon.value] && vars.data.viz.length <= vars.data.large ) {
+        children.push("icon")
+      }
+
+      var iconGraphic = vars.icon.button.value
+      if ( d[vars.id.value] === vars.focus.value && vars.icon.select.value ) {
+        iconGraphic = vars.icon.select.value
+        children.push("selected")
+      }
+      else if ( iconGraphic && d.d3plus.icon !== false ) {
+        children.push("selected")
+      }
+
+      var buffer = 0
+
+      var items = d3.select(this).selectAll("div.d3plus_button_element")
+        .data(children,function(c){
+          return c
+        })
+
+      items.enter().append("div")
+        .style("display",function(c){
+          return c === "label" ? "block" : "absolute"
+        })
+
+      items.order()
+        .attr("class",function(c){
+          var extra = ""
+          if ( c === "selected" && iconGraphic.indexOf("fa-") === 0 ) {
+            extra = " fa "+iconGraphic
+          }
+          return "d3plus_button_element d3plus_button_" + c + extra
+        })
+        .html(function(c){
+          if ( c === "label" ) {
+            var k = vars.text.value && vars.text.value in d && !(d[vars.text.value] instanceof Array)
+                  ? vars.text.value : vars.id.value
+            return vars.format.value(d[k])
+          }
+          return c === "selected" && iconGraphic.indexOf("fa-") < 0
+                 ? iconGraphic : ""
+        })
+        .style("background-image",function(c){
+          if (c === "icon") {
+            return "url('"+d[vars.icon.value]+"')"
+          }
+          return "none"
+        })
+        .style("background-color",function(c){
+          if (c === "icon" && d.style === "knockout") {
+            return d[vars.color.value] || vars.ui.color.primary.value
+          }
+          return "transparent"
+        })
+        .style("background-size","100%")
+        .style("text-align",function(c){
+          return c === "label" ? vars.font.align.value : "center"
+        })
+        .style("position",function(c){
+          return c == "label" ? "static" : "absolute"
+        })
+        .style("width",function(c){
+
+          if ( c === "label" ) {
+            return "auto"
+          }
+
+          if (vars.height.value) {
+            buffer = (vars.height.value-(vars.ui.padding.top + vars.ui.padding.bottom)-(vars.ui.border*2));
+          }
+          else {
+            buffer = vars.font.size+vars.ui.border;
+          }
+          return buffer+"px"
+        })
+        .style("height",function(c){
+          if ( c === "icon" ) {
+            return buffer+"px"
+          }
+          return "auto"
+        })
+        .style("margin-top",function(c){
+          if ( c === "label" ) {
+            return "0px"
+          }
+          if (this.offsetHeight || this.getBoundingClientRect().height) {
+            var h = this.offsetHeight || this.getBoundingClientRect().height
+          }
+          else if ( c === "selected" ) {
+            var h = vars.font.size
+          }
+          else {
+            var h = buffer
+          }
+          return -h/2+"px"
+        })
+        .style("top",function(c){
+          return c === "label" ? "auto" : "50%"
+        })
+        .style("left",function(c){
+          if ((c === "icon" && !reversed) || (c === "selected" && reversed)) {
+            return vars.ui.padding.left+"px"
+          }
+          return "auto"
+        })
+        .style("right",function(c){
+          if ((c === "icon" && reversed) || (c === "selected" && !reversed)) {
+            return vars.ui.padding.right+"px"
+          }
+          return "auto"
+        })
+        .style(prefix()+"transition",function(c){
+          return c === "selected" ? (vars.draw.timing/1000)+"s" : "none"
+        })
+        .style(prefix()+"transform",function(c){
+          var degree = c === "selected" ? vars.icon.select.rotate : "none"
+          return typeof degree === "string" ? degree : "rotate("+degree+"deg)"
+        })
+        .style("opacity",function(c){
+          return c === "selected" ? vars.icon.select.opacity : 1
+        })
+
+      items.exit().remove()
+
+      var text = d3.select(this).selectAll(".d3plus_button_label")
+
+      if (buffer > 0) {
+
+        var p = vars.ui.padding;
+
+        if (children.length === 3) {
+          p = p.top+"px "+(p.right*2+buffer)+"px "+p.bottom+"px "+(p.left*2+buffer)+"px";
+        }
+        else if ((children.indexOf("icon") >= 0 && !rtl) || (children.indexOf("selected") >= 0 && rtl)) {
+          p = p.top+"px "+p.right+"px "+p.bottom+"px "+(p.left*2+buffer)+"px";
+        }
+        else {
+          p = p.top+"px "+(p.right*2+buffer)+"px "+p.bottom+"px "+p.left+"px";
+        }
+
+        text.style("padding", p)
+
+      }
+      else {
+        text.style("padding",vars.ui.padding.css)
+      }
+
+      if (typeof vars.width.value === "number") {
+        var width = vars.width.value
+        width -= parseFloat(text.style("padding-left"),10)
+        width -= parseFloat(text.style("padding-right"),10)
+        width -= vars.ui.border*2
+        width += "px"
+      }
+      else {
+        var width = "auto"
+      }
+
+      text.style("width",width)
+
+    })
+
+}
+
+},{"../../../../client/prefix.coffee":41,"../../../../client/rtl.coffee":42}],139:[function(require,module,exports){
+module.exports = function(elem, vars, color) {
+  var events, ie;
+  color = require("./color.coffee");
+  events = require("../../../../client/pointer.coffee");
+  ie = require("../../../../client/ie.js");
+  return elem.on(events.over, function(d, i) {
+    vars.self.hover(d[vars.id.value]);
+    if (ie || !vars.draw.timing) {
+      return d3.select(this).style("cursor", "pointer").call(color, vars);
+    } else {
+      return d3.select(this).style("cursor", "pointer").transition().duration(vars.timing.mouseevents).call(color, vars);
+    }
+  }).on(events.out, function(d) {
+    vars.self.hover(false);
+    if (ie || !vars.draw.timing) {
+      return d3.select(this).style("cursor", "auto").call(color, vars);
+    } else {
+      return d3.select(this).style("cursor", "auto").transition().duration(vars.timing.mouseevents).call(color, vars);
+    }
+  }).on(events.click, function(d) {
+    if (vars.focus.value) {
+      return vars.self.focus(d[vars.id.value]).draw();
+    } else if (vars.focus.callback) {
+      return vars.focus.callback(d, vars.self);
+    }
+  });
+};
+
+
+},{"../../../../client/ie.js":39,"../../../../client/pointer.coffee":40,"./color.coffee":137}],140:[function(require,module,exports){
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+//------------------------------------------------------------------------------
+module.exports = function ( elem , vars ) {
+
+  elem
+    .style("position","relative")
+    .style("margin",vars.ui.margin.css)
+    .style("display",vars.ui.display.value)
+    .style("border-style","solid")
+    .style("border-width",vars.ui.border+"px")
+    .style("font-family",vars.font.family.value)
+    .style("font-size",vars.font.size+"px")
+    .style("font-weight",vars.font.weight)
+    .style("letter-spacing",vars.font.spacing+"px")
+
+}
+
+},{}],141:[function(require,module,exports){
+module.exports = function(vars) {
+  var button, data, element, keyboard, list, search, selector, title, update, width, windowevent;
+  element = require("./functions/element.coffee");
+  keyboard = require("./functions/keyboard.coffee");
+  windowevent = require("./functions/window.js");
+  width = require("./functions/width.js");
+  button = require("./functions/button.js");
+  selector = require("./functions/selector.js");
+  title = require("./functions/title.js");
+  search = require("./functions/search.js");
+  list = require("./functions/list.js");
+  data = require("./functions/data.js");
+  update = require("./functions/update.js");
+  vars.margin.top = 0;
+  vars.margin.title = 0;
+  element(vars);
+  keyboard(vars);
+  windowevent(vars);
+  width(vars);
+  button(vars);
+  selector(vars);
+  title(vars);
+  search(vars);
+  list(vars);
+  data(vars);
+  return update(vars);
+};
+
+
+},{"./functions/button.js":144,"./functions/data.js":145,"./functions/element.coffee":146,"./functions/keyboard.coffee":149,"./functions/list.js":150,"./functions/search.js":152,"./functions/selector.js":153,"./functions/title.js":154,"./functions/update.js":155,"./functions/width.js":156,"./functions/window.js":157}],142:[function(require,module,exports){
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Checks to see if a given variable is allowed to be selected.
+//------------------------------------------------------------------------------
+module.exports = function ( vars , value , active ) {
+
+  var ret = []
+    , active = active || vars.active.value
+
+  if ( active instanceof Array ) {
+
+    for (var i = 0; i < active.length; i++) {
+      ret.push(this(vars,value,active[i]))
+    }
+
+  }
+  else {
+
+    var t = typeof active
+
+    if (t === "number") {
+      ret.push(vars.depth.value === active)
+    }
+    else if (t === "function") {
+      ret.push(active(value))
+    }
+    else {
+      ret.push(value === active)
+    }
+
+  }
+
+  return ret.indexOf(true) >= 0
+
+}
+
+},{}],143:[function(require,module,exports){
+var print = require("../../../../core/console/print.coffee")
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Toggles the state of the dropdown menu.
+//------------------------------------------------------------------------------
+module.exports = function ( vars ) {
+
+  if ( vars.dev.value ) print.time("rotating arrow")
+
+  var offset = vars.icon.drop.value === "&#x276f;" ? 90 : 0
+
+  if (vars.open.value != vars.open.flipped.value) {
+    var rotate = 180 + offset
+  }
+  else {
+    var rotate = offset
+  }
+
+  vars.container.button
+    .icon({
+      "select": {
+        "opacity": vars.open.value ? 0.5 : 1,
+        "rotate": rotate
+      }
+    })
+    .draw()
+
+  if ( vars.dev.value ) print.timeEnd("rotating arrow")
+
+}
+
+},{"../../../../core/console/print.coffee":53}],144:[function(require,module,exports){
+var copy = require("../../../../util/copy.coffee"),
+    events = require("../../../../client/pointer.coffee"),
+    form   = require("../../../form.js"),
+    print  = require("../../../../core/console/print.coffee")
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Creates and styles the main drop button.
+//------------------------------------------------------------------------------
+module.exports = function ( vars ) {
+
+  if ( !("button" in vars.container) ) {
+
+    if ( vars.dev.value ) print.time("creating main button")
+
+    vars.container.button = form()
+      .container(vars.container.ui)
+      .type("button")
+      .ui({
+        "margin": 0
+      })
+
+    if ( vars.dev.value ) print.timeEnd("creating main button")
+
+  }
+
+  if ( vars.focus.changed || vars.data.changed || vars.depth.changed ) {
+
+    var depth = vars.depth.value
+
+    var buttonData = copy(vars.data.value.filter(function(d){
+      var match = false
+      for ( var i = 0 ; i < vars.id.nesting.length ; i++ ) {
+        var level = vars.id.nesting[i]
+        match = level in d && d[level] === vars.focus.value
+        if (match) {
+          depth = i
+          break
+        }
+      }
+      return match
+    })[0])
+
+    if ( !buttonData ) {
+      buttonData = vars.container.button.data()[0] || vars.data.viz[0]
+    }
+
+    vars.container.button
+      .data([buttonData])
+      .id( vars.id.nesting )
+      .depth(depth)
+
+  }
+
+  var hover = vars.hover.value === true ? vars.focus.value : false;
+
+  vars.container.button
+    .draw({
+      "update": vars.draw.update
+    })
+    .focus("")
+    .font( vars.font )
+    .format(vars.format)
+    .hover(hover)
+    .icon({
+      "button": vars.icon.drop.value,
+      "select": vars.icon.drop.value,
+      "value": vars.icon.value
+    })
+    .text( vars.text.value )
+    .timing({
+      "ui": vars.draw.timing
+    })
+    .ui({
+      "color": vars.ui.color,
+      "padding": vars.ui.padding.css
+    })
+    .width(vars.width.value)
+    .draw()
+
+  var button = vars.container.button.container(Object).ui
+
+  vars.margin.top += button.node().offsetHeight || button.node().getBoundingClientRect().height
+
+  button.on(events.click,function(){
+    vars.self.open(!vars.open.value).draw()
+  })
+
+}
+
+},{"../../../../client/pointer.coffee":40,"../../../../core/console/print.coffee":53,"../../../../util/copy.coffee":206,"../../../form.js":103}],145:[function(require,module,exports){
+var stringFormat = require("../../../../string/format.js"),
+    stringStrip = require("../../../../string/strip.js");
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Creates and populates the dropdown list of items.
+//------------------------------------------------------------------------------
+module.exports = function ( vars ) {
+
+  if ( vars.data.url && !vars.data.loaded ) {
+    var loadingObject = {};
+    loadingObject[vars.text.value || vars.id.value] = vars.format.value(vars.format.locale.value.ui.loading);
+    vars.data.filtered = [loadingObject];
+    vars.data.changed = vars.data.lastFilter !== "loading";
+    vars.data.lastFilter = "loading";
+  }
+  else if (vars.open.value) {
+
+    if (!vars.search.term) {
+      vars.data.filtered = vars.data.viz;
+      vars.data.changed = vars.data.lastFilter !== "viz";
+      vars.data.lastFilter = "viz";
+      if (vars.id.nesting.length > 1 && vars.depth.value < vars.id.nesting.length-1) {
+        vars.data.filtered = vars.data.filtered.filter(function(d){
+          if ("endPoint" in d.d3plus && d.d3plus.endPoint === vars.depth.value) {
+            d.d3plus.icon = false;
+          }
+          return true;
+        });
+        vars.data.changed = vars.data.lastFilter !== "depth";
+        vars.data.lastFilter = "depth";
+      }
+    }
+    else {
+
+      var searchWords = stringStrip(vars.search.term).split("_"),
+          searchKeys  = [vars.id.value, vars.text.value, vars.alt.value, vars.keywords.value ];
+
+      searchKeys = searchKeys.filter(function(t){ return t; });
+      searchWords = searchWords.filter(function(t){ return t !== ""; });
+
+      var startMatches = [],
+          exactMatches = [],
+          softMatches  = [],
+          searchData   = [];
+
+      vars.id.nesting.forEach(function(n){
+        searchData = searchData.concat(vars.data.nested.all[n]);
+      });
+
+      searchData.forEach(function(d){
+
+        var match = false;
+
+        searchKeys.forEach(function(key){
+
+          if ( !match && key in d && typeof d[key] === "string" ) {
+
+            var text = d[key].toLowerCase();
+
+            if ( [vars.text.value,vars.id.value].indexOf(key) >= 0 && text.indexOf(vars.search.term) === 0 ) {
+              startMatches.push(d);
+              match = true;
+            }
+            else if ( text.indexOf(vars.search.term) >= 0 ) {
+              exactMatches.push(d);
+              match = true;
+            }
+            else {
+
+              var texts = stringStrip(text).split("_");
+
+              for (var t in texts) {
+
+                if ( !match ) {
+
+                  for (var s in searchWords) {
+                    if (texts[t].indexOf(searchWords[s]) === 0) {
+                      softMatches.push(d);
+                      match = true;
+                      break;
+                    }
+                  }
+
+                }
+                else {
+                  break;
+                }
+
+              }
+
+            }
+          }
+
+        });
+
+      });
+
+      vars.data.filtered = d3.merge([ startMatches , exactMatches , softMatches ]);
+
+      vars.data.filtered.forEach(function(d,i){
+        d.d3plus_order = i;
+      });
+
+      vars.data.changed = true;
+      vars.data.lastFilter = "search";
+
+      if ( vars.data.filtered.length === 0 ) {
+
+        var noData = {}, str = vars.format.value(vars.format.locale.value.ui.noResults);
+        noData[vars.text.value || vars.id.value] = stringFormat(str,"\""+vars.search.term+"\"");
+        vars.data.filtered = [ noData ];
+
+      }
+
+    }
+
+  }
+  else {
+    vars.data.filtered = [];
+  }
+
+};
+
+},{"../../../../string/format.js":172,"../../../../string/strip.js":174}],146:[function(require,module,exports){
+module.exports = function(vars) {
+  if (vars.data.element.value) {
+    vars.data.element.value.on("focus." + vars.container.id, function() {
+      return vars.self.hover(true).draw();
+    });
+    vars.data.element.value.on("blur." + vars.container.id, function() {
+      var search;
+      if (vars.search.enabled) {
+        search = d3.event.relatedTarget !== vars.container.value.select('input').node();
+      } else {
+        search = true;
+      }
+      if (search) {
+        return vars.self.open(false).hover(false).draw();
+      }
+    });
+    vars.data.element.value.on("change." + vars.container.id, function() {
+      return vars.self.focus(this.value).draw();
+    });
+    return vars.data.element.value.on("keydown.cancel_" + vars.container.id, function() {
+      if (d3.event.keyCode !== 9) {
+        return d3.event.preventDefault();
+      }
+    });
+  }
+};
+
+
+},{}],147:[function(require,module,exports){
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Calculates the height and orientation of the dropdown list, based on
+// available screen space.
+//------------------------------------------------------------------------------
+module.exports = function ( vars ) {
+
+  var height = vars.height.secondary,
+      button = vars.container.button.container().node().getBoundingClientRect(),
+      available = window.innerHeight - button.bottom - vars.ui.border * 2 -
+                  vars.ui.margin.top - vars.ui.margin.bottom -
+                  vars.ui.padding.top - vars.ui.padding.bottom;
+
+  if (available < button.height * 3) {
+    available = button.top-10;
+    vars.self.open({"flipped": true});
+  }
+  // else {
+  //   vars.self.open({"flipped": false});
+  // }
+
+  if (typeof height !== "number") {
+    height = available;
+  }
+
+  if (height > vars.height.max) {
+    height = vars.height.max;
+  }
+
+  vars.self.height({"secondary": height});
+
+};
+
+},{}],148:[function(require,module,exports){
+var active, copy, form, print;
+
+active = require("./active.js");
+
+copy = require("../../../../util/copy.coffee");
+
+form = require("../../../form.js");
+
+print = require("../../../../core/console/print.coffee");
+
+module.exports = function(vars) {
+  var deepest, large, order;
+  if (vars.open.value) {
+    if (vars.dev.value) {
+      print.time("updating list items");
+    }
+    if (!("items" in vars.container)) {
+      vars.container.items = form().container(vars.container.list).type("button").ui({
+        border: 0,
+        display: "block",
+        margin: 0
+      }).width(false);
+    }
+    large = vars.draw.timing ? vars.data.large : 1;
+    order = copy(vars.order);
+    order.value = vars.search.term.length ? "d3plus_order" : vars.order.value;
+    deepest = vars.depth.value === vars.id.nesting.length - 1;
+    if (vars.focus.changed || vars.container.items.focus() === false) {
+      vars.container.items.focus(vars.focus.value, function(value) {
+        var change, data, depth, solo;
+        data = vars.data.filtered.filter(function(f) {
+          return f[vars.id.value] === value;
+        })[0];
+        if (vars.depth.value < vars.id.nesting.length - 1 && vars.id.nesting[vars.depth.value + 1] in data) {
+          depth = vars.depth.value;
+          solo = vars.id.solo.value;
+          vars.history.states.push(function() {
+            return vars.self.depth(depth).id({
+              solo: solo
+            }).draw();
+          });
+          vars.self.depth(vars.depth.value + 1).id({
+            solo: [value]
+          }).draw();
+        } else {
+          if (!vars.depth.changed) {
+            vars.self.open(false);
+          }
+          change = value !== vars.focus.value;
+          if (change && vars.active.value) {
+            change = active(vars, value);
+          }
+          if (change) {
+            vars.self.focus(value).draw();
+          }
+        }
+      });
+    }
+    if (vars.data.changed) {
+      vars.container.items.data({
+        large: large,
+        value: vars.data.filtered
+      });
+    }
+    vars.container.items.active(vars.active.value).data({
+      "sort": vars.data.sort.value
+    }).draw({
+      update: vars.draw.update
+    }).font(vars.font.secondary).format(vars.format).hover(vars.hover.value).id(vars.id.value).icon({
+      button: (deepest ? false : vars.icon.next),
+      select: (deepest ? vars.icon.select : false),
+      value: vars.icon.value
+    }).order(order).text(vars.text.secondary.value || vars.text.value).timing({
+      ui: vars.draw.timing
+    }).ui({
+      color: {
+        primary: (vars.id.nesting.length === 1 ? vars.ui.color.primary.value : vars.ui.color.secondary.value),
+        secondary: vars.ui.color.secondary.value
+      },
+      padding: vars.ui.padding.css
+    }).draw();
+    if (vars.dev.value) {
+      print.timeEnd("updating list items");
+    }
+  }
+};
+
+
+},{"../../../../core/console/print.coffee":53,"../../../../util/copy.coffee":206,"../../../form.js":103,"./active.js":142}],149:[function(require,module,exports){
+module.exports = function(vars) {
+  return d3.select(window).on("keydown." + vars.container.id, function() {
+    var d, data, depth, hist, hover, i, index, j, key, len, matchKey, ref, solo;
+    key = d3.event.keyCode;
+    if (vars.open.value || vars.hover.value === true) {
+      matchKey = vars.hover.value === true ? "focus" : "hover";
+      index = false;
+      ref = vars.data.filtered;
+      for (i = j = 0, len = ref.length; j < len; i = ++j) {
+        d = ref[i];
+        if (d[vars.id.value] === vars[matchKey].value) {
+          index = i;
+          break;
+        }
+      }
+      if (key === 9 && vars.open.value && (!vars.search.enabled || (vars.search.enabled && !d3.event.shiftKey))) {
+        return vars.self.open(false).hover(false).draw();
+      } else if ([38, 40].indexOf(key) >= 0) {
+        if (index === false) {
+          index = 0;
+        } else if (key === 38) {
+          if (vars.open.value) {
+            if (index <= 0) {
+              index = vars.data.filtered.length - 1;
+            } else {
+              index -= 1;
+            }
+          }
+        } else if (key === 40) {
+          if (vars.open.value) {
+            if (index >= vars.data.filtered.length - 1) {
+              index = 0;
+            } else {
+              index += 1;
+            }
+          }
+        }
+        if (typeof vars.hover.value !== "boolean") {
+          hover = vars.data.filtered[index][vars.id.value];
+        } else {
+          hover = vars.focus.value;
+        }
+        return vars.self.hover(hover).open(true).draw();
+      } else if (key === 13) {
+        if (typeof vars.hover.value !== "boolean") {
+          data = vars.data.filtered.filter(function(f) {
+            return f[vars.id.value] === vars.hover.value;
+          })[0];
+          depth = vars.depth.value;
+          if (depth < vars.id.nesting.length - 1 && vars.id.nesting[depth + 1] in data) {
+            solo = vars.id.solo.value;
+            hist = function() {
+              return vars.self.depth(depth).id({
+                solo: solo
+              }).draw();
+            };
+            vars.history.states.push(hist);
+            return vars.self.depth(vars.depth.value + 1).id({
+              solo: [vars.hover.value]
+            }).draw();
+          } else {
+            return vars.self.focus(vars.hover.value).hover(true).draw();
+          }
+        } else {
+          return vars.self.hover(vars.focus.value).open(true).draw();
+        }
+      } else if (key === 27) {
+        if (vars.open.value) {
+          return vars.self.open(false).hover(true).draw();
+        } else if (vars.hover.value === true) {
+          return vars.self.hover(false).draw();
+        }
+      }
+    }
+  });
+};
+
+
+},{}],150:[function(require,module,exports){
+var print = require("../../../../core/console/print.coffee")
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Creates and populates the dropdown list of items.
+//------------------------------------------------------------------------------
+module.exports = function ( vars ) {
+
+  if ( vars.dev.value ) print.time("populating list")
+
+  vars.container.list = vars.container.selector.selectAll("div.d3plus_drop_list")
+    .data(["list"])
+
+  vars.container.list.enter().append("div")
+    .attr("class","d3plus_drop_list")
+    .attr("id","d3plus_drop_list_"+vars.container.id)
+    .style("overflow-y","auto")
+    .style("overflow-x","hidden")
+
+  if ( vars.dev.value ) print.timeEnd("populating list")
+
+}
+
+},{"../../../../core/console/print.coffee":53}],151:[function(require,module,exports){
+var print = require("../../../../core/console/print.coffee")
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Calculates scroll position of list.
+//------------------------------------------------------------------------------
+module.exports = function ( vars ) {
+
+  if (vars.open.value) {
+
+    if ( vars.dev.value ) print.time("calculating height")
+
+    var hidden = false
+    if (vars.container.selector.style("display") == "none") {
+      var hidden = true
+    }
+
+    if (hidden) vars.container.selector.style("display","block")
+
+    var old_height = vars.container.selector.style("height"),
+        old_scroll = vars.container.selector.property("scrollTop"),
+        list_height = vars.container.list.style("max-height"),
+        list_scroll = vars.container.list.property("scrollTop")
+
+    vars.container.selector.style("height","auto")
+    vars.container.list.style("max-height","200000px")
+
+    vars.container.listHeight = parseFloat(vars.container.selector.style("height"),10)
+
+    vars.container.list
+      .style("max-height",list_height)
+      .property("scrollTop",list_scroll)
+
+    vars.container.selector
+      .style("height",old_height)
+      .property("scrollTop",old_scroll)
+
+    var scrolling = false
+    if (vars.container.listHeight > vars.height.secondary) {
+      vars.container.listHeight = vars.height.secondary
+      scrolling = true
+    }
+
+    if (hidden) vars.container.selector.style("display","none")
+
+    if ( vars.dev.value ) print.timeEnd("calculating height")
+
+    if (scrolling) {
+
+      if ( vars.dev.value ) print.time("calculating scroll position")
+
+      var options = vars.container.list.select("div").selectAll("div.d3plus_node")
+      var option = options[0][0]
+      var matchID = typeof vars.hover.value !== "boolean" ? vars.hover.value : vars.focus.value;
+      options.each(function(d,i){
+        if (d[vars.id.value] === matchID) {
+          option = this
+        }
+      })
+
+      var hidden = false
+      if (vars.container.selector.style("display") === "none") {
+        hidden = true
+        vars.container.selector.style("display","block")
+      }
+
+      var button_top = option.offsetTop,
+          button_height = option.offsetHeight || option.getBoundingClientRect().height,
+          list_top = vars.container.list.property("scrollTop")
+
+      if (hidden) vars.container.selector.style("display","none")
+
+      if ( hidden || vars.data.changed || vars.depth.changed ) {
+
+        vars.container.listScroll = button_top
+
+      }
+      else {
+
+        vars.container.listScroll = list_top;
+
+        if (button_top < list_top) {
+          vars.container.listScroll = button_top
+        }
+        else if (button_top+button_height > list_top+vars.height.secondary-vars.search.height) {
+          vars.container.listScroll = button_top - (vars.height.secondary-button_height-vars.search.height)
+        }
+
+      }
+
+      if ( vars.dev.value ) print.timeEnd("calculating scroll position")
+
+    }
+    else {
+      vars.container.listScroll = 0
+    }
+
+  }
+  else {
+    vars.container.listScroll = vars.container.list.property("scrollTop")
+    vars.container.listHeight = 0
+  }
+
+}
+
+},{"../../../../core/console/print.coffee":53}],152:[function(require,module,exports){
+var prefix = require("../../../../client/prefix.coffee"),
+    print = require("../../../../core/console/print.coffee")
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Creates and styles the search box, if enabled.
+//------------------------------------------------------------------------------
+module.exports = function ( vars ) {
+
+  if ( vars.dev.value ) print.time("creating search")
+
+  var data = require("./data.js")
+    , items = require("./items.coffee")
+    , update = require("./update.js")
+
+  vars.container.search = vars.container.selector.selectAll("div.d3plus_drop_search")
+    .data(vars.search.enabled ? ["search"] : [])
+
+  function searchStyle(elem) {
+
+    elem
+      .style("padding",vars.ui.padding.css)
+      .style("display","block")
+      .style("background-color",d3.rgb(vars.ui.color.primary.value).darker(0.15).toString())
+
+  }
+
+  function inputStyle(elem) {
+
+    var width = vars.width.secondary - vars.ui.padding.left*2 - vars.ui.padding.right*2 + vars.ui.border*2
+
+    elem
+      .style("padding",vars.ui.padding.left/2+vars.ui.padding.right/2+"px")
+      .style("width",width+"px")
+      .style("border-width","0px")
+      .style("font-family",vars.font.secondary.family.value)
+      .style("font-size",vars.font.secondary.size+"px")
+      .style("font-weight",vars.font.secondary.weight)
+      .style("text-align",vars.font.secondary.align)
+      .style("outline","none")
+      .style(prefix()+"border-radius","0")
+      .attr("placeholder",vars.format.value(vars.format.locale.value.method.search))
+
+  }
+
+  if (vars.draw.timing) {
+
+    vars.container.search.transition().duration(vars.draw.timing)
+      .call(searchStyle)
+
+    vars.container.search.select("input").transition().duration(vars.draw.timing)
+      .call(inputStyle)
+
+  }
+  else {
+
+    vars.container.search
+      .call(searchStyle)
+
+    vars.container.search.select("input")
+      .call(inputStyle)
+
+  }
+
+  vars.container.search.enter()
+    .insert("div","#d3plus_drop_list_"+vars.container.id)
+      .attr("class","d3plus_drop_search")
+      .attr("id","d3plus_drop_search_"+vars.container.id)
+      .call(searchStyle)
+      .append("input")
+        .attr("id","d3plus_drop_input_"+vars.container.id)
+        .style("-webkit-appearance","none")
+        .call(inputStyle)
+
+  vars.container.search.select("input").on("keyup."+vars.container.id,function(d){
+    var term = this.value;
+    if (vars.search.term !== term) {
+      vars.search.term = term;
+      data(vars);
+      items(vars);
+      update(vars);
+    }
+  });
+
+  vars.container.search.exit().remove()
+
+  var oldDisplay = vars.container.selector.style("display")
+  vars.container.selector.style("display", "block")
+  vars.search.height = vars.search.enabled ? vars.container.search.node().offsetHeight ||
+                       vars.container.search.node().getBoundingClientRect().height : 0;
+  vars.container.selector.style("display", oldDisplay)
+
+  if ( vars.search.enabled ) {
+    vars.margin.title += vars.search.height
+  }
+
+  if ( vars.dev.value ) print.timeEnd("creating search")
+
+}
+
+},{"../../../../client/prefix.coffee":41,"../../../../core/console/print.coffee":53,"./data.js":145,"./items.coffee":148,"./update.js":155}],153:[function(require,module,exports){
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Creates and styles the div that holds the search box and item list.
+//------------------------------------------------------------------------------
+module.exports = function ( vars ) {
+
+  vars.container.selector = vars.container.ui
+    .selectAll("div.d3plus_drop_selector")
+    .data(["selector"])
+
+  vars.container.selector.enter().append("div")
+    .attr("class","d3plus_drop_selector")
+    .style("position","absolute")
+    .style("top","0px")
+    .style("z-index","-1")
+    .style("overflow","hidden")
+
+    vars.container.selector
+      .style("padding",vars.ui.border+"px")
+
+}
+
+},{}],154:[function(require,module,exports){
+var events = require("../../../../client/pointer.coffee"),
+    lighter   = require("../../../../color/lighter.coffee"),
+    print     = require("../../../../core/console/print.coffee"),
+    textColor = require("../../../../color/text.coffee")
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Creates and styles the title and back button.
+//------------------------------------------------------------------------------
+module.exports = function ( vars ) {
+
+  if ( vars.open.value ) {
+
+    if ( vars.dev.value ) print.time("creating title and back button")
+
+    var self    = this
+      , enabled = vars.id.solo.value.length === 1 && vars.depth.value > 0
+      , title   = enabled
+      , focus   = vars.container.button.data(Object).viz[0]
+
+    title = true
+    for (var i = 0; i < vars.id.nesting.length; i++) {
+      var level = vars.id.nesting[i]
+      if ( level in focus && focus[level] === vars.focus.value ) {
+        title = false
+        break;
+      }
+    }
+
+    vars.container.title = vars.container.selector.selectAll("div.d3plus_drop_title")
+      .data(enabled ? ["title"] : [])
+
+    function boxStyle(elem) {
+
+      elem
+        .style("padding",vars.ui.padding.css)
+        .style("display","block")
+        .style("background-color",vars.ui.color.secondary.value)
+        .style("font-family",vars.font.secondary.family.value)
+        .style("font-size",vars.font.secondary.size+"px")
+        .style("font-weight",vars.font.secondary.weight)
+        .style("text-align",vars.font.secondary.align)
+        .style("color",textColor(vars.ui.color.secondary.value))
+
+    }
+
+    function backStyle(elem) {
+
+      if ( !elem.empty() ) {
+
+        var className = vars.icon.back.value.indexOf("fa-") === 0 ? " fa "+vars.icon.back.value : ""
+        className = "d3plus_drop_back" + className
+
+        var text = vars.icon.back.value.indexOf("fa-") === 0 ? "" : vars.icon.back.value
+
+        elem
+          .style("position","absolute")
+          .attr("class",className)
+          .style("top",vars.ui.padding.top+(vars.font.secondary.size/2)/2.5+"px")
+          .html(text)
+
+      }
+
+    }
+
+    function titleStyle(elem) {
+
+      var text = title ? vars.focus.value : vars.format.locale.value.ui.back
+
+      elem
+        .text(vars.format.value(text))
+        .style("padding","0px "+(vars.ui.padding.left+vars.ui.padding.right)+"px")
+
+    }
+
+    if (vars.draw.timing) {
+
+      vars.container.title.transition().duration(vars.draw.timing)
+        .call(boxStyle)
+
+      vars.container.title.select("div.d3plus_drop_title_text")
+        .transition().duration(vars.draw.timing)
+        .call(titleStyle)
+
+    }
+    else {
+
+      vars.container.title
+        .call(boxStyle)
+
+      vars.container.title.select("div.d3plus_drop_title_text")
+        .call(titleStyle)
+
+    }
+
+    vars.container.title.select("span.d3plus_drop_back")
+      .call(backStyle)
+
+    var enter = vars.container.title.enter()
+      .insert("div","#d3plus_drop_list_"+vars.container.id)
+        .attr("class","d3plus_drop_title")
+        .attr("id","d3plus_drop_title_"+vars.container.id)
+        .call(boxStyle)
+
+    enter.append("span")
+      .attr("id","d3plus_drop_back_"+vars.container.id)
+      .attr("class","d3plus_drop_back")
+      .call(backStyle)
+
+    enter.append("div")
+      .attr("id","d3plus_drop_title_text_"+vars.container.id)
+      .attr("class","d3plus_drop_title_text")
+      .call(titleStyle)
+
+    vars.container.title
+      .on(events.over,function(d,i){
+
+        var color = lighter(vars.ui.color.secondary.value)
+
+        d3.select(this).style("cursor","pointer")
+          .transition().duration(vars.timing.mouseevents)
+          .style("background-color",color)
+          .style("color",textColor(color))
+
+      })
+      .on(events.out,function(d){
+
+        var color = vars.ui.color.secondary.value
+
+        d3.select(this).style("cursor","auto")
+          .transition().duration(vars.timing.mouseevents)
+          .style("background-color",color)
+          .style("color",textColor(color))
+
+      })
+      .on(events.click,function(d){
+        vars.history.back()
+      })
+
+    vars.container.title.exit().remove()
+
+    if ( enabled ) {
+      vars.margin.title += vars.container.title.node().offsetHeight || vars.container.title.node().getBoundingClientRect().height
+    }
+
+    if ( vars.dev.value ) print.timeEnd("creating title and back button")
+
+  }
+
+}
+
+},{"../../../../client/pointer.coffee":40,"../../../../color/lighter.coffee":46,"../../../../color/text.coffee":51,"../../../../core/console/print.coffee":53}],155:[function(require,module,exports){
+var items = require("./items.coffee"),
+    height     = require("./height.js"),
+    print      = require("../../../../core/console/print.coffee"),
+    scrolllist = require("./scroll.js"),
+    arrow      = require("./arrow.js")
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Redraws only the drop down list.
+//------------------------------------------------------------------------------
+module.exports = function ( vars ) {
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // If the menu is open, set the container element's z-index to '9999'.
+  //----------------------------------------------------------------------------
+  if ( vars.draw.timing ) {
+
+    vars.container.ui.transition().duration(vars.draw.timing)
+      .each("start",function(){
+        if (vars.open.value) {
+          d3.select(this).style("z-index",9999)
+        }
+      })
+      .style("margin",vars.ui.margin.css)
+      .each("end",function(){
+        if (!vars.open.value) {
+          d3.select(this).style("z-index","auto")
+        }
+      })
+
+  }
+  else {
+
+    vars.container.ui
+      .style("margin",vars.ui.margin.css)
+      .style("z-index",function(){
+        if (vars.open.value) {
+          return 9999
+        }
+        else {
+          return "auto"
+        }
+      })
+
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Update list items based on filtered data.
+  //----------------------------------------------------------------------------
+  items( vars )
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Calculate the height and orientation of the dropdown list.
+  //----------------------------------------------------------------------------
+  height( vars )
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Calculate scroll position of dropdown menu.
+  //----------------------------------------------------------------------------
+  scrolllist( vars )
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Rotate the dropdown button arrow appropriately.
+  //----------------------------------------------------------------------------
+  arrow( vars )
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Update List
+  //----------------------------------------------------------------------------
+  if ( vars.dev.value ) print.time("drawing list")
+
+  function position(elem) {
+    var flipped = vars.open.flipped.value
+    elem
+      .style("top",function(){
+        return flipped ? "auto" : vars.margin.top-vars.ui.border+"px";
+      })
+      .style("bottom",function(){
+        return flipped ? vars.margin.top+vars.ui.border+"px" : "auto";
+      });
+  }
+
+  function update(elem) {
+
+    elem
+      .style("left",function(){
+        if (vars.font.align.value === "left") {
+          return vars.margin.left+"px";
+        }
+        else if (vars.font.align.value === "center") {
+          return vars.margin.left-((vars.width.secondary-vars.width.value)/2)+"px";
+        }
+        else {
+          return "auto";
+        }
+      })
+      .style("right",function(){
+        return vars.font.align.value === "right" ? "0px" : "auto";
+      })
+      .style("height",vars.container.listHeight+"px")
+      .style("padding",vars.ui.border+"px")
+      .style("background-color",vars.ui.color.secondary.value)
+      .style("z-index",function(){
+        return vars.open.value ? "9999" : "-1";
+      })
+      .style("width",(vars.width.secondary-(vars.ui.border*2))+"px")
+      .style("opacity",vars.open.value ? 1 : 0)
+      .call(position);
+
+  }
+
+  function finish(elem) {
+
+    elem.style("display", vars.open.value ? null : "none")
+      .call(position);
+
+
+    if (vars.search.enabled && vars.open.value) {
+      vars.container.selector.select("div.d3plus_drop_search input").node().focus()
+    }
+
+  }
+
+  var max_height = vars.open.value ? vars.height.secondary - vars.margin.title: 0;
+
+  if (!vars.draw.timing) {
+
+    vars.container.selector.call(update).call(finish)
+
+    vars.container.list
+      .style("width",vars.width.secondary-vars.ui.border*2+"px")
+      .style("max-height", max_height + "px")
+      .property("scrollTop",vars.container.listScroll);
+
+  }
+  else {
+    vars.container.selector.transition().duration(vars.draw.timing)
+      .each("start",function(){
+        d3.select(this)
+          .style("display",vars.open.value ? "block" : null)
+      })
+      .call(update)
+      .each("end",function(){
+
+        d3.select(this).transition().duration(vars.draw.timing)
+          .call(finish)
+
+      })
+
+    function scrollTopTween(scrollTop) {
+        return function() {
+            var i = d3.interpolateNumber(this.scrollTop, scrollTop);
+            return function(t) { this.scrollTop = i(t); };
+        };
+    }
+
+    vars.container.list.transition().duration(vars.draw.timing)
+      .style("width",vars.width.secondary-vars.ui.border*2+"px")
+      .style("max-height",max_height+"px")
+      .tween("scroll",scrollTopTween(vars.container.listScroll))
+  }
+
+  if ( vars.dev.value ) print.timeEnd("drawing list")
+
+}
+
+},{"../../../../core/console/print.coffee":53,"./arrow.js":143,"./height.js":147,"./items.coffee":148,"./scroll.js":151}],156:[function(require,module,exports){
+var copy = require("../../../../util/copy.coffee"),
+    fontTester  = require("../../../../core/font/tester.coffee"),
+    form        = require("../../../form.js"),
+    print       = require("../../../../core/console/print.coffee"),
+    validObject = require("../../../../object/validate.coffee")
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// If no widths are defined, then this calculates the width needed to fit the
+// longest entry in the list.
+//------------------------------------------------------------------------------
+module.exports = function ( vars ) {
+
+  var data = [], buffer = 0
+  for ( var level in vars.data.nested.all ) {
+    var newData = vars.data.nested.all[level]
+      , key     = validObject(vars.text.nesting) && level in vars.text.nesting
+                ? vars.text.nesting[level][0] : level
+
+    if ( [vars.id.value,vars.text.value].indexOf(key) < 0 ) {
+      newData = copy(newData)
+      newData.forEach(function(d){
+        d[vars.text.value || vars.id.value] = d[key]
+      })
+    }
+    data = data.concat( newData )
+  }
+
+  function getWidth( type ) {
+
+    var key  = type === "primary" ? "value" : type
+      , icon = key === "value" ? vars.icon.drop.value
+             : vars.icon.select.value || vars.icon.drop.value
+      , text = key === "value" ? vars.text.value
+             : vars.text.secondary.value || vars.text.value
+      , font = key === "value" ? vars.font : vars.font.secondary
+
+    if ( vars.dev.value ) print.time("calculating "+type+" width")
+
+    var button = form()
+      .container( fontTester() )
+      .data({
+        "large": 9999,
+        "value": data
+      })
+      .draw({ "update": false })
+      .font( font )
+      .format(vars.format)
+      .icon({ "button": icon, "value": vars.icon.value })
+      .id(vars.id.value)
+      .timing({
+        "ui": 0
+      })
+      .text( text || vars.id.value )
+      .type( "button" )
+      .ui({
+        "border": type === "primary" ? vars.ui.border : 0,
+        "display": "inline-block",
+        "margin": 0,
+        "padding": vars.ui.padding.css
+      })
+      .width(false)
+      .draw()
+
+    var w = []
+    button.selectAll("div.d3plus_node").each(function(o){
+      w.push(this.offsetWidth + 1)
+    }).remove()
+
+    var dropWidth = {}
+    dropWidth[key] = d3.max(w)
+
+    vars.self.width( dropWidth )
+
+    if ( vars.dev.value ) print.timeEnd("calculating "+type+" width")
+
+  }
+
+  if ( typeof vars.width.value !== "number" ) {
+
+    getWidth( "primary" )
+
+  }
+
+  if ( typeof vars.width.secondary !== "number" ) {
+
+    if ( !vars.text.secondary.value || vars.text.value === vars.text.secondary.value ) {
+      vars.self.width({"secondary": vars.width.value})
+    }
+    else {
+      getWidth( "secondary" )
+    }
+
+  }
+
+}
+
+},{"../../../../core/console/print.coffee":53,"../../../../core/font/tester.coffee":69,"../../../../object/validate.coffee":171,"../../../../util/copy.coffee":206,"../../../form.js":103}],157:[function(require,module,exports){
+var child = require("../../../../util/child.coffee")
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Recursive function that applies a click event to all parent windows that
+// will close the dropdown if it is open.
+//------------------------------------------------------------------------------
+var windowEvents = function ( vars , elem ) {
+
+  if ( elem === undefined ) {
+    var elem = window
+  }
+
+  d3.select(elem).on("click."+vars.container.id,function(){
+
+    var element = d3.event.target || d3.event.toElement
+      , parent  = element.parentNode
+
+    if ( parent && ["d3plus_node","d3plus_drop_title"].indexOf(parent.className) >= 0 ) {
+      element = parent.parentNode
+    }
+
+    if (element && parent && !child(vars.container.ui, element) && (vars.open.value || vars.hover.value)) {
+      vars.self.open(false).hover(false).draw()
+    }
+
+  })
+
+  try {
+    var same_origin = window.parent.location.host === window.location.host;
+  }
+  catch (e) {
+    var same_origin = false
+  }
+
+  if (same_origin) {
+    if (elem.self !== window.top) {
+      windowEvents( vars , elem.parent )
+    }
+  }
+
+}
+
+module.exports = windowEvents
+
+},{"../../../../util/child.coffee":204}],158:[function(require,module,exports){
+var form = require("../form.js")
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Creates a set of Toggle Buttons
+//------------------------------------------------------------------------------
+module.exports = function( vars ) {
+
+  if ( !("buttons" in vars.container) ) {
+
+    vars.container.buttons = form()
+      .container(vars.container.ui)
+      .type("button")
+
+  }
+
+  var dataLength  = vars.data.viz.length
+    , buttonWidth = vars.width.value
+                  ? vars.width.value/dataLength
+                  : false
+
+  var toggles = vars.container.ui.selectAll("div.d3plus_toggle")
+    .data(vars.data.viz,function(d){
+      return d[vars.id.value]
+    })
+
+  toggles.enter().append("div")
+    .attr("class","d3plus_toggle")
+    .style("display","inline-block")
+    .style("vertical-align","top")
+
+  toggles.order()
+    .each(function(d){
+
+      if (!("form" in d.d3plus)) {
+        d.d3plus.form = form().container(d3.select(this))
+      }
+
+      var id = vars.id.nesting.length > vars.depth.value ? vars.id.nesting[vars.depth.value+1] : vars.id.value
+
+      if (d[id] instanceof Array) {
+        d.d3plus.form
+          .container({"id": vars.container.id+"_"+d[vars.id.value]})
+          .data(d[id])
+          .id(vars.id.nesting.slice(1))
+          .type("drop")
+      }
+      else {
+        d.d3plus.form
+          .data([d])
+          .id(vars.id.value)
+          .type("button")
+      }
+
+      d.d3plus.form
+        .color(vars.color)
+        .focus(vars.focus.value,function(value){
+
+          if (value !== vars.focus.value) {
+            vars.self.focus(value).draw()
+          }
+
+        })
+        .hover(vars.hover.value)
+        .icon({
+          "select": false,
+          "value": vars.icon.value
+        })
+        .font(vars.font)
+        .format(vars.format)
+        .order(vars.order)
+        .text(vars.text.value)
+        .ui({
+          "border": vars.ui.border,
+          "color": vars.ui.color,
+          "display": "inline-block",
+          "margin": 0,
+          "padding": vars.ui.padding.css
+        })
+        .width(buttonWidth)
+        .draw()
+
+    })
+
+  if (vars.data.element.value) {
+    vars.data.element.value
+      .on("focus."+vars.container.id, function(){
+        vars.self.focus(this.value).hover(this.value).draw();
+      })
+      .on("blur."+vars.container.id, function(){
+        vars.self.hover(false).draw();
+      })
+  }
+
+}
+
+},{"../form.js":103}],159:[function(require,module,exports){
+var intersectPoints, lineIntersection, pointInPoly, pointInSegmentBox, polyInsidePoly, print, rayIntersectsSegment, rotatePoint, rotatePoly, segmentsIntersect, simplify, squaredDist;
+
+print = require("../core/console/print.coffee");
+
+simplify = require("simplify-js");
+
+module.exports = function(poly, options) {
+  var aRatio, aRatios, angle, angleRad, angleStep, angles, area, aspectRatioStep, aspectRatios, bBox, boxHeight, boxWidth, centroid, events, height, i, insidePoly, j, k, l, left, len, len1, len2, len3, m, maxArea, maxAspectRatio, maxHeight, maxRect, maxWidth, maxx, maxy, minAspectRatio, minSqDistH, minSqDistW, minx, miny, modifOrigins, origOrigin, origin, origins, p, p1H, p1W, p2H, p2W, rectPoly, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, right, rndPoint, rndX, rndY, tempPoly, tolerance, width, widthStep, x0, y0;
+  if (poly.length < 3) {
+    print.error('polygon has to have at least 3 points');
+    return null;
+  }
+  events = [];
+  aspectRatioStep = 0.5;
+  angleStep = 5;
+  if (options == null) {
+    options = {};
+  }
+  if (options.maxAspectRatio == null) {
+    options.maxAspectRatio = 15;
+  }
+  if (options.minWidth == null) {
+    options.minWidth = 0;
+  }
+  if (options.minHeight == null) {
+    options.minHeight = 0;
+  }
+  if (options.tolerance == null) {
+    options.tolerance = 0.02;
+  }
+  if (options.nTries == null) {
+    options.nTries = 20;
+  }
+  if (options.angle != null) {
+    if (options.angle instanceof Array) {
+      angles = options.angle;
+    } else if (typeof options.angle === 'number') {
+      angles = [options.angle];
+    } else if (typeof options.angle === 'string' && !isNaN(options.angle)) {
+      angles = [Number(options.angle)];
+    }
+  }
+  if (angles == null) {
+    angles = d3.range(-90, 90 + angleStep, angleStep);
+  }
+  if (options.aspectRatio != null) {
+    if (options.aspectRatio instanceof Array) {
+      aspectRatios = options.aspectRatio;
+    } else if (typeof options.aspectRatio === 'number') {
+      aspectRatios = [options.aspectRatio];
+    } else if (typeof options.aspectRatio === 'string' && !isNaN(options.aspectRatio)) {
+      aspectRatios = [Number(options.aspectRatio)];
+    }
+  }
+  if (options.origin != null) {
+    if (options.origin instanceof Array) {
+      if (options.origin[0] instanceof Array) {
+        origins = options.origin;
+      } else {
+        origins = [options.origin];
+      }
+    }
+  }
+  area = Math.abs(d3.geom.polygon(poly).area());
+  if (area === 0) {
+    print.error('polygon has 0 area');
+    return null;
+  }
+  ref = d3.extent(poly, function(d) {
+    return d[0];
+  }), minx = ref[0], maxx = ref[1];
+  ref1 = d3.extent(poly, function(d) {
+    return d[1];
+  }), miny = ref1[0], maxy = ref1[1];
+  tolerance = Math.min(maxx - minx, maxy - miny) * options.tolerance;
+  tempPoly = (function() {
+    var j, len, results;
+    results = [];
+    for (j = 0, len = poly.length; j < len; j++) {
+      p = poly[j];
+      results.push({
+        x: p[0],
+        y: p[1]
+      });
+    }
+    return results;
+  })();
+  if (tolerance > 0) {
+    tempPoly = simplify(tempPoly, tolerance);
+    poly = (function() {
+      var j, len, results;
+      results = [];
+      for (j = 0, len = tempPoly.length; j < len; j++) {
+        p = tempPoly[j];
+        results.push([p.x, p.y]);
+      }
+      return results;
+    })();
+  }
+  if (options.vdebug) {
+    events.push({
+      type: 'simplify',
+      poly: poly
+    });
+  }
+  ref2 = d3.extent(poly, function(d) {
+    return d[0];
+  }), minx = ref2[0], maxx = ref2[1];
+  ref3 = d3.extent(poly, function(d) {
+    return d[1];
+  }), miny = ref3[0], maxy = ref3[1];
+  bBox = [[minx, miny], [maxx, miny], [maxx, maxy], [minx, maxy]];
+  ref4 = [maxx - minx, maxy - miny], boxWidth = ref4[0], boxHeight = ref4[1];
+  widthStep = Math.min(boxWidth, boxHeight) / 50;
+  if (origins == null) {
+    origins = [];
+    centroid = d3.geom.polygon(poly).centroid();
+    if (pointInPoly(centroid, poly)) {
+      origins.push(centroid);
+    }
+    while (origins.length < options.nTries) {
+      rndX = Math.random() * boxWidth + minx;
+      rndY = Math.random() * boxHeight + miny;
+      rndPoint = [rndX, rndY];
+      if (pointInPoly(rndPoint, poly)) {
+        origins.push(rndPoint);
+      }
+    }
+  }
+  if (options.vdebug) {
+    events.push({
+      type: 'origins',
+      points: origins
+    });
+  }
+  maxArea = 0;
+  maxRect = null;
+  for (j = 0, len = angles.length; j < len; j++) {
+    angle = angles[j];
+    angleRad = -angle * Math.PI / 180;
+    if (options.vdebug) {
+      events.push({
+        type: 'angle',
+        angle: angle
+      });
+    }
+    for (i = k = 0, len1 = origins.length; k < len1; i = ++k) {
+      origOrigin = origins[i];
+      ref5 = intersectPoints(poly, origOrigin, angleRad), p1W = ref5[0], p2W = ref5[1];
+      ref6 = intersectPoints(poly, origOrigin, angleRad + Math.PI / 2), p1H = ref6[0], p2H = ref6[1];
+      modifOrigins = [];
+      if ((p1W != null) && (p2W != null)) {
+        modifOrigins.push([(p1W[0] + p2W[0]) / 2, (p1W[1] + p2W[1]) / 2]);
+      }
+      if ((p1H != null) && (p2H != null)) {
+        modifOrigins.push([(p1H[0] + p2H[0]) / 2, (p1H[1] + p2H[1]) / 2]);
+      }
+      if (options.vdebug) {
+        events.push({
+          type: 'modifOrigin',
+          idx: i,
+          p1W: p1W,
+          p2W: p2W,
+          p1H: p1H,
+          p2H: p2H,
+          modifOrigins: modifOrigins
+        });
+      }
+      for (l = 0, len2 = modifOrigins.length; l < len2; l++) {
+        origin = modifOrigins[l];
+        if (options.vdebug) {
+          events.push({
+            type: 'origin',
+            cx: origin[0],
+            cy: origin[1]
+          });
+        }
+        ref7 = intersectPoints(poly, origin, angleRad), p1W = ref7[0], p2W = ref7[1];
+        if (p1W === null || p2W === null) {
+          continue;
+        }
+        minSqDistW = Math.min(squaredDist(origin, p1W), squaredDist(origin, p2W));
+        maxWidth = 2 * Math.sqrt(minSqDistW);
+        ref8 = intersectPoints(poly, origin, angleRad + Math.PI / 2), p1H = ref8[0], p2H = ref8[1];
+        if (p1H === null || p2H === null) {
+          continue;
+        }
+        minSqDistH = Math.min(squaredDist(origin, p1H), squaredDist(origin, p2H));
+        maxHeight = 2 * Math.sqrt(minSqDistH);
+        if (maxWidth * maxHeight < maxArea) {
+          continue;
+        }
+        if (aspectRatios != null) {
+          aRatios = aspectRatios;
+        } else {
+          minAspectRatio = Math.max(1, options.minWidth / maxHeight, maxArea / (maxHeight * maxHeight));
+          maxAspectRatio = Math.min(options.maxAspectRatio, maxWidth / options.minHeight, (maxWidth * maxWidth) / maxArea);
+          aRatios = d3.range(minAspectRatio, maxAspectRatio + aspectRatioStep, aspectRatioStep);
+        }
+        for (m = 0, len3 = aRatios.length; m < len3; m++) {
+          aRatio = aRatios[m];
+          left = Math.max(options.minWidth, Math.sqrt(maxArea * aRatio));
+          right = Math.min(maxWidth, maxHeight * aRatio);
+          if (right * maxHeight < maxArea) {
+            continue;
+          }
+          if ((right - left) >= widthStep) {
+            if (options.vdebug) {
+              events.push({
+                type: 'aRatio',
+                aRatio: aRatio
+              });
+            }
+          }
+          while ((right - left) >= widthStep) {
+            width = (left + right) / 2;
+            height = width / aRatio;
+            x0 = origin[0], y0 = origin[1];
+            rectPoly = [[x0 - width / 2, y0 - height / 2], [x0 + width / 2, y0 - height / 2], [x0 + width / 2, y0 + height / 2], [x0 - width / 2, y0 + height / 2]];
+            rectPoly = rotatePoly(rectPoly, angleRad, origin);
+            if (polyInsidePoly(rectPoly, poly)) {
+              insidePoly = true;
+              maxArea = width * height;
+              maxRect = {
+                cx: x0,
+                cy: y0,
+                width: width,
+                height: height,
+                angle: angle
+              };
+              left = width;
+            } else {
+              insidePoly = false;
+              right = width;
+            }
+            if (options.vdebug) {
+              events.push({
+                type: 'rectangle',
+                cx: x0,
+                cy: y0,
+                width: width,
+                height: height,
+                areaFraction: (width * height) / area,
+                angle: angle,
+                insidePoly: insidePoly
+              });
+            }
+          }
+        }
+      }
+    }
+  }
+  return [maxRect, maxArea, events];
+};
+
+squaredDist = function(a, b) {
+  var deltax, deltay;
+  deltax = b[0] - a[0];
+  deltay = b[1] - a[1];
+  return deltax * deltax + deltay * deltay;
+};
+
+rayIntersectsSegment = function(p, p1, p2) {
+  var a, b, mAB, mAP, ref;
+  ref = p1[1] < p2[1] ? [p1, p2] : [p2, p1], a = ref[0], b = ref[1];
+  if (p[1] === b[1] || p[1] === a[1]) {
+    p[1] += Number.MIN_VALUE;
+  }
+  if (p[1] > b[1] || p[1] < a[1]) {
+    return false;
+  } else if (p[0] > a[0] && p[0] > b[0]) {
+    return false;
+  } else if (p[0] < a[0] && p[0] < b[0]) {
+    return true;
+  } else {
+    mAB = (b[1] - a[1]) / (b[0] - a[0]);
+    mAP = (p[1] - a[1]) / (p[0] - a[0]);
+    return mAP > mAB;
+  }
+};
+
+pointInPoly = function(p, poly) {
+  var a, b, c, i, n;
+  i = -1;
+  n = poly.length;
+  b = poly[n - 1];
+  c = 0;
+  while (++i < n) {
+    a = b;
+    b = poly[i];
+    if (rayIntersectsSegment(p, a, b)) {
+      c++;
+    }
+  }
+  return c % 2 !== 0;
+};
+
+pointInSegmentBox = function(p, p1, q1) {
+  var eps, px, py;
+  eps = 1e-9;
+  px = p[0], py = p[1];
+  if (px < Math.min(p1[0], q1[0]) - eps || px > Math.max(p1[0], q1[0]) + eps || py < Math.min(p1[1], q1[1]) - eps || py > Math.max(p1[1], q1[1]) + eps) {
+    return false;
+  }
+  return true;
+};
+
+lineIntersection = function(p1, q1, p2, q2) {
+  var cross1, cross2, denom, dx1, dx2, dy1, dy2, eps, px, py;
+  eps = 1e-9;
+  dx1 = p1[0] - q1[0];
+  dy1 = p1[1] - q1[1];
+  dx2 = p2[0] - q2[0];
+  dy2 = p2[1] - q2[1];
+  denom = dx1 * dy2 - dy1 * dx2;
+  if (Math.abs(denom) < eps) {
+    return null;
+  }
+  cross1 = p1[0] * q1[1] - p1[1] * q1[0];
+  cross2 = p2[0] * q2[1] - p2[1] * q2[0];
+  px = (cross1 * dx2 - cross2 * dx1) / denom;
+  py = (cross1 * dy2 - cross2 * dy1) / denom;
+  return [px, py];
+};
+
+segmentsIntersect = function(p1, q1, p2, q2) {
+  var p;
+  p = lineIntersection(p1, q1, p2, q2);
+  if (p == null) {
+    return false;
+  }
+  return pointInSegmentBox(p, p1, q1) && pointInSegmentBox(p, p2, q2);
+};
+
+polyInsidePoly = function(polyA, polyB) {
+  var aA, aB, bA, bB, iA, iB, nA, nB;
+  iA = -1;
+  nA = polyA.length;
+  nB = polyB.length;
+  bA = polyA[nA - 1];
+  while (++iA < nA) {
+    aA = bA;
+    bA = polyA[iA];
+    iB = -1;
+    bB = polyB[nB - 1];
+    while (++iB < nB) {
+      aB = bB;
+      bB = polyB[iB];
+      if (segmentsIntersect(aA, bA, aB, bB)) {
+        return false;
+      }
+    }
+  }
+  return pointInPoly(polyA[0], polyB);
+};
+
+rotatePoint = function(p, alpha, origin) {
+  var cosAlpha, sinAlpha, xshifted, yshifted;
+  if (origin == null) {
+    origin = [0, 0];
+  }
+  xshifted = p[0] - origin[0];
+  yshifted = p[1] - origin[1];
+  cosAlpha = Math.cos(alpha);
+  sinAlpha = Math.sin(alpha);
+  return [cosAlpha * xshifted - sinAlpha * yshifted + origin[0], sinAlpha * xshifted + cosAlpha * yshifted + origin[1]];
+};
+
+rotatePoly = function(poly, alpha, origin) {
+  var j, len, point, results;
+  results = [];
+  for (j = 0, len = poly.length; j < len; j++) {
+    point = poly[j];
+    results.push(rotatePoint(point, alpha, origin));
+  }
+  return results;
+};
+
+intersectPoints = function(poly, origin, alpha) {
+  var a, b, closestPointLeft, closestPointRight, eps, i, idx, minSqDistLeft, minSqDistRight, n, p, shiftedOrigin, sqDist, x0, y0;
+  eps = 1e-9;
+  origin = [origin[0] + eps * Math.cos(alpha), origin[1] + eps * Math.sin(alpha)];
+  x0 = origin[0], y0 = origin[1];
+  shiftedOrigin = [x0 + Math.cos(alpha), y0 + Math.sin(alpha)];
+  idx = 0;
+  if (Math.abs(shiftedOrigin[0] - x0) < eps) {
+    idx = 1;
+  }
+  i = -1;
+  n = poly.length;
+  b = poly[n - 1];
+  minSqDistLeft = Number.MAX_VALUE;
+  minSqDistRight = Number.MAX_VALUE;
+  closestPointLeft = null;
+  closestPointRight = null;
+  while (++i < n) {
+    a = b;
+    b = poly[i];
+    p = lineIntersection(origin, shiftedOrigin, a, b);
+    if ((p != null) && pointInSegmentBox(p, a, b)) {
+      sqDist = squaredDist(origin, p);
+      if (p[idx] < origin[idx]) {
+        if (sqDist < minSqDistLeft) {
+          minSqDistLeft = sqDist;
+          closestPointLeft = p;
+        }
+      } else if (p[idx] > origin[idx]) {
+        if (sqDist < minSqDistRight) {
+          minSqDistRight = sqDist;
+          closestPointRight = p;
+        }
+      }
+    }
+  }
+  return [closestPointLeft, closestPointRight];
+};
+
+
+},{"../core/console/print.coffee":53,"simplify-js":8}],160:[function(require,module,exports){
+module.exports = function(radians, distance, shape) {
+  var adjacentLegLength, coords, diagonal, oppositeLegLength;
+  coords = {
+    x: 0,
+    y: 0
+  };
+  if (radians < 0) {
+    radians = Math.PI * 2 + radians;
+  }
+  if (shape === "square") {
+    diagonal = 45 * (Math.PI / 180);
+    if (radians <= Math.PI) {
+      if (radians < (Math.PI / 2)) {
+        if (radians < diagonal) {
+          coords.x += distance;
+          oppositeLegLength = Math.tan(radians) * distance;
+          coords.y += oppositeLegLength;
+        } else {
+          coords.y += distance;
+          adjacentLegLength = distance / Math.tan(radians);
+          coords.x += adjacentLegLength;
+        }
+      } else {
+        if (radians < (Math.PI - diagonal)) {
+          coords.y += distance;
+          adjacentLegLength = distance / Math.tan(Math.PI - radians);
+          coords.x -= adjacentLegLength;
+        } else {
+          coords.x -= distance;
+          oppositeLegLength = Math.tan(Math.PI - radians) * distance;
+          coords.y += oppositeLegLength;
+        }
+      }
+    } else {
+      if (radians < (3 * Math.PI / 2)) {
+        if (radians < (diagonal + Math.PI)) {
+          coords.x -= distance;
+          oppositeLegLength = Math.tan(radians - Math.PI) * distance;
+          coords.y -= oppositeLegLength;
+        } else {
+          coords.y -= distance;
+          adjacentLegLength = distance / Math.tan(radians - Math.PI);
+          coords.x -= adjacentLegLength;
+        }
+      } else {
+        if (radians < (2 * Math.PI - diagonal)) {
+          coords.y -= distance;
+          adjacentLegLength = distance / Math.tan(2 * Math.PI - radians);
+          coords.x += adjacentLegLength;
+        } else {
+          coords.x += distance;
+          oppositeLegLength = Math.tan(2 * Math.PI - radians) * distance;
+          coords.y -= oppositeLegLength;
+        }
+      }
+    }
+  } else {
+    coords.x += distance * Math.cos(radians);
+    coords.y += distance * Math.sin(radians);
+  }
+  return coords;
+};
+
+
+},{}],161:[function(require,module,exports){
+var offset;
+
+offset = require("../geom/offset.coffee");
+
+module.exports = function(path) {
+  var angle, i, j, last, len, length, o, obtuse, p, poly, prev, radius, segments, start, step, width;
+  path = path.slice(1).slice(0, -1).split(/L|A/);
+  poly = [];
+  for (j = 0, len = path.length; j < len; j++) {
+    p = path[j];
+    p = p.split(" ");
+    if (p.length === 1) {
+      poly.push(p[0].split(",").map(function(d) {
+        return parseFloat(d);
+      }));
+    } else {
+      prev = poly[poly.length - 1];
+      last = p.pop().split(",").map(function(d) {
+        return parseFloat(d);
+      });
+      radius = parseFloat(p.shift().split(",")[0]);
+      width = Math.sqrt(Math.pow(last[0] - prev[0], 2) + Math.pow(last[1] - prev[1], 2));
+      angle = Math.acos((radius * radius + radius * radius - width * width) / (2 * radius * radius));
+      obtuse = p[1].split(",")[0] === "1";
+      if (obtuse) {
+        angle = Math.PI * 2 - angle;
+      }
+      length = angle / (Math.PI * 2) * (radius * Math.PI * 2);
+      segments = length / 5;
+      start = Math.atan2(-prev[1], -prev[0]) - Math.PI;
+      step = angle / segments;
+      i = step;
+      while (i < angle) {
+        o = offset(start + i, radius);
+        poly.push([o.x, o.y]);
+        i += step;
+      }
+      poly.push(last);
+    }
+  }
+  return poly;
+};
+
+
+},{"../geom/offset.coffee":160}],162:[function(require,module,exports){
+
+/**
+ * @class d3plus
+ */
+var d3plus, message, stylesheet;
+
+d3plus = {};
+
+if (typeof window !== "undefined") {
+  window.d3plus = d3plus;
+}
+
+module.exports = d3plus;
+
+
+/**
+ * The current version of **D3plus** you are using. Returns a string in
+ * [semantic versioning](http://semver.org/) format.
+ * @property d3plus.version
+ * @for d3plus
+ * @type String
+ * @static
+ */
+
+d3plus.version = "1.8.0 - Cerulean";
+
+
+/**
+ * The URL for the repo, used internally for certain error messages.
+ * @property d3plus.repo
+ * @for d3plus
+ * @type String
+ * @static
+ */
+
+d3plus.repo = "https://github.com/alexandersimoes/d3plus/";
+
+
+/**
+ * Utilities related to modifying arrays.
+ * @class d3plus.array
+ * @for d3plus
+ * @static
+ */
+
+d3plus.array = {
+  comparator: require("./array/comparator.coffee"),
+  contains: require("./array/contains.coffee"),
+  sort: require("./array/sort.coffee"),
+  update: require("./array/update.coffee")
+};
+
+
+/**
+ * Utilities related to the client's browser.
+ * @class d3plus.client
+ * @for d3plus
+ * @static
+ */
+
+d3plus.client = {
+  css: require("./client/css.coffee"),
+  ie: require("./client/ie.js"),
+  pointer: require("./client/pointer.coffee"),
+  prefix: require("./client/prefix.coffee"),
+  rtl: require("./client/rtl.coffee"),
+  scrollbar: require("./client/scrollbar.coffee"),
+  touch: require("./client/touch.coffee")
+};
+
+
+/**
+ * Utilities related to color manipulation.
+ * @class d3plus.color
+ * @for d3plus
+ * @static
+ */
+
+d3plus.color = {
+  legible: require("./color/legible.coffee"),
+  lighter: require("./color/lighter.coffee"),
+  mix: require("./color/mix.coffee"),
+  random: require("./color/random.coffee"),
+  scale: require("./color/scale.coffee"),
+  sort: require("./color/sort.coffee"),
+  text: require("./color/text.coffee"),
+  validate: require("./color/validate.coffee")
+};
+
+
+/**
+ * Utilities related to manipulating data.
+ * @class d3plus.data
+ * @for d3plus
+ * @static
+ */
+
+d3plus.data = {
+  bestRegress: require("./data/bestRegress.coffee"),
+  lof: require("./data/lof.coffee"),
+  mad: require("./data/mad.coffee")
+};
+
+
+/**
+ * Utilities related to fonts.
+ * @class d3plus.font
+ * @for d3plus
+ * @static
+ */
+
+d3plus.font = {
+  sizes: require("./font/sizes.coffee"),
+  validate: require("./font/validate.coffee")
+};
+
+
+/**
+ * D3plus Forms
+ * @class d3plus.form
+ * @for d3plus
+ */
+
+d3plus.form = require("./form/form.js");
+
+
+/**
+ * Utilities related to geometric algorithms.
+ * @class d3plus.geom
+ * @for d3plus
+ * @static
+ */
+
+d3plus.geom = {
+  largestRect: require("./geom/largestRect.coffee"),
+  offset: require("./geom/offset.coffee"),
+  path2poly: require("./geom/path2poly.coffee")
+};
+
+
+/**
+ * Utilities related to network graphs.
+ * @class d3plus.network
+ * @for d3plus
+ * @static
+ */
+
+d3plus.network = {
+  cluster: require("./network/cluster.coffee"),
+  distance: require("./network/distance.coffee"),
+  normalize: require("./network/normalize.coffee"),
+  shortestPath: require("./network/shortestPath.coffee"),
+  smallestGap: require("./network/smallestGap.coffee"),
+  subgraph: require("./network/subgraph.coffee")
+};
+
+
+/**
+ * Utilities that process numbers.
+ * @class d3plus.number
+ * @for d3plus
+ * @static
+ */
+
+d3plus.number = {
+  format: require("./number/format.coffee")
+};
+
+
+/**
+ * D3plus features a set of methods that relate to various object properties. These methods may be used outside of the normal constraints of the visualizations.
+ * @class d3plus.object
+ * @for d3plus
+ * @static
+ */
+
+d3plus.object = {
+  merge: require("./object/merge.coffee"),
+  validate: require("./object/validate.coffee")
+};
+
+
+/**
+ * Utilities that process strings.
+ * @class d3plus.string
+ * @for d3plus
+ * @static
+ */
+
+d3plus.string = {
+  format: require("./string/format.js"),
+  list: require("./string/list.coffee"),
+  strip: require("./string/strip.js"),
+  title: require("./string/title.coffee")
+};
+
+
+/**
+ * D3plus SVG Textwrapping
+ * @class d3plus.textwrap
+ * @for d3plus
+ */
+
+d3plus.textwrap = require("./textwrap/textwrap.coffee");
+
+
+/**
+ * D3plus Tooltips
+ * @class d3plus.tooltip
+ * @for d3plus
+ */
+
+d3plus.tooltip = {
+  create: require("./tooltip/create.js"),
+  move: require("./tooltip/move.coffee"),
+  remove: require("./tooltip/remove.coffee")
+};
+
+
+/**
+ * D3plus features Utilities that can be used to help with some common javascript processes.
+ * @class d3plus.util
+ * @for d3plus
+ * @static
+ */
+
+d3plus.util = {
+  buckets: require("./util/buckets.coffee"),
+  child: require("./util/child.coffee"),
+  closest: require("./util/closest.coffee"),
+  copy: require("./util/copy.coffee"),
+  d3selection: require("./util/d3selection.coffee"),
+  dataurl: require("./util/dataURL.coffee"),
+  uniques: require("./util/uniques.coffee")
+};
+
+
+/**
+ * D3plus Visualizations
+ * @class d3plus.viz
+ * @for d3plus
+ */
+
+d3plus.viz = require("./viz/viz.coffee");
+
+stylesheet = require("./client/css.coffee");
+
+message = require("./core/console/print.coffee");
+
+if (stylesheet("d3plus.css")) {
+  message.warning("d3plus.css has been deprecated, you do not need to load this file.", d3plus.repo + "releases/tag/v1.4.0");
+}
+
+
+},{"./array/comparator.coffee":34,"./array/contains.coffee":35,"./array/sort.coffee":36,"./array/update.coffee":37,"./client/css.coffee":38,"./client/ie.js":39,"./client/pointer.coffee":40,"./client/prefix.coffee":41,"./client/rtl.coffee":42,"./client/scrollbar.coffee":43,"./client/touch.coffee":44,"./color/legible.coffee":45,"./color/lighter.coffee":46,"./color/mix.coffee":47,"./color/random.coffee":48,"./color/scale.coffee":49,"./color/sort.coffee":50,"./color/text.coffee":51,"./color/validate.coffee":52,"./core/console/print.coffee":53,"./data/bestRegress.coffee":98,"./data/lof.coffee":99,"./data/mad.coffee":100,"./font/sizes.coffee":101,"./font/validate.coffee":102,"./form/form.js":103,"./geom/largestRect.coffee":159,"./geom/offset.coffee":160,"./geom/path2poly.coffee":161,"./network/cluster.coffee":163,"./network/distance.coffee":164,"./network/normalize.coffee":165,"./network/shortestPath.coffee":166,"./network/smallestGap.coffee":167,"./network/subgraph.coffee":168,"./number/format.coffee":169,"./object/merge.coffee":170,"./object/validate.coffee":171,"./string/format.js":172,"./string/list.coffee":173,"./string/strip.js":174,"./string/title.coffee":175,"./textwrap/textwrap.coffee":199,"./tooltip/create.js":200,"./tooltip/move.coffee":201,"./tooltip/remove.coffee":202,"./util/buckets.coffee":203,"./util/child.coffee":204,"./util/closest.coffee":205,"./util/copy.coffee":206,"./util/d3selection.coffee":207,"./util/dataURL.coffee":208,"./util/uniques.coffee":209,"./viz/viz.coffee":325}],163:[function(require,module,exports){
+var normalize;
+
+normalize = require("./normalize.coffee");
+
+module.exports = function(edges, options) {
+  var Q, a, b, cid, commSize, commSizes, communities, community, deltaQ, distance, edge, endpoint, events, i, id, iter, j, k, len, len1, linksMap, m, maxa, maxb, node, nodeid, nodes, nodesMap, ref, ref1, result, startpoint;
+  events = [];
+  if (options == null) {
+    options = {};
+  }
+  if ((options.nodes == null) || typeof options.nodes !== 'object') {
+    ref = normalize(edges, options), edges = ref[0], options = ref[1];
+    if (options === null) {
+      return null;
+    }
+  }
+  distance = options.distance, nodeid = options.nodeid, startpoint = options.startpoint, endpoint = options.endpoint, nodes = options.nodes;
+  nodesMap = {};
+  for (id in nodes) {
+    nodesMap[id] = {
+      node: nodes[id].node,
+      degree: 0
+    };
+  }
+  m = 0;
+  linksMap = {};
+  for (i = 0, len = edges.length; i < len; i++) {
+    edge = edges[i];
+    a = nodeid(startpoint(edge));
+    b = nodeid(endpoint(edge));
+    if (!(a in linksMap)) {
+      linksMap[a] = {};
+    }
+    if (!(b in linksMap)) {
+      linksMap[b] = {};
+    }
+    if (!(b in linksMap[a])) {
+      linksMap[a][b] = 0;
+      linksMap[b][a] = 0;
+      m++;
+      nodesMap[a].degree += 1;
+      nodesMap[b].degree += 1;
+    }
+  }
+  communities = {};
+  Q = 0;
+  for (id in nodesMap) {
+    node = nodesMap[id];
+    communities[id] = {
+      score: node.degree / (2.0 * m),
+      nodes: [id]
+    };
+  }
+  for (a in linksMap) {
+    for (b in linksMap[a]) {
+      linksMap[a][b] = 1.0 / (2 * m) - (nodesMap[a].degree * nodesMap[b].degree) / (4.0 * m * m);
+    }
+  }
+  iter = 0;
+  while (iter < 1000) {
+    deltaQ = -1;
+    maxa = void 0;
+    maxb = void 0;
+    for (a in linksMap) {
+      for (b in linksMap[a]) {
+        if (linksMap[a][b] > deltaQ) {
+          deltaQ = linksMap[a][b];
+          maxa = a;
+          maxb = b;
+        }
+      }
+    }
+    if (deltaQ < 0) {
+      break;
+    }
+    for (k in linksMap[maxa]) {
+      if (k !== maxb) {
+        if (k in linksMap[maxb]) {
+          linksMap[maxb][k] += linksMap[maxa][k];
+        } else {
+          linksMap[maxb][k] = linksMap[maxa][k] - 2 * communities[maxb].score * communities[k].score;
+        }
+        linksMap[k][maxb] = linksMap[maxb][k];
+      }
+      delete linksMap[k][maxa];
+    }
+    for (k in linksMap[maxb]) {
+      if (!(k in linksMap[maxa]) && k !== maxb) {
+        linksMap[maxb][k] -= 2 * communities[maxa].score * communities[k].score;
+        linksMap[k][maxb] = linksMap[maxb][k];
+      }
+    }
+    ref1 = communities[maxa].nodes;
+    for (j = 0, len1 = ref1.length; j < len1; j++) {
+      node = ref1[j];
+      communities[maxb].nodes.push(node);
+    }
+    communities[maxb].score += communities[maxa].score;
+    if (options.vdebug) {
+      events.push({
+        type: 'merge',
+        father: maxb,
+        child: maxa,
+        nodes: communities[maxb].nodes
+      });
+    }
+    delete communities[maxa];
+    delete linksMap[maxa];
+    Q += deltaQ;
+    iter++;
+  }
+  commSizes = (function() {
+    var results;
+    results = [];
+    for (cid in communities) {
+      community = communities[cid];
+      results.push([cid, community.nodes.length]);
+    }
+    return results;
+  })();
+  commSizes.sort(function(a, b) {
+    return b[1] - a[1];
+  });
+  result = (function() {
+    var l, len2, results;
+    results = [];
+    for (l = 0, len2 = commSizes.length; l < len2; l++) {
+      commSize = commSizes[l];
+      results.push(communities[commSize[0]].nodes);
+    }
+    return results;
+  })();
+  return [result, events];
+};
+
+
+},{"./normalize.coffee":165}],164:[function(require,module,exports){
+module.exports = function(n1, n2) {
+  var xx, yy;
+  if (!(n1 instanceof Array)) {
+    n1 = [n1.x, n1.y];
+  }
+  if (!(n2 instanceof Array)) {
+    n2 = [n2.x, n2.y];
+  }
+  xx = Math.abs(n1[0] - n2[0]);
+  yy = Math.abs(n1[1] - n2[1]);
+  return Math.sqrt((xx * xx) + (yy * yy));
+};
+
+
+},{}],165:[function(require,module,exports){
+var print;
+
+print = require("../core/console/print.coffee");
+
+module.exports = function(edges, options) {
+  var K, a, b, directed, distance, edge, edge2distance, endpoint, errormsg, i, id, id1, idA, idB, j, k, l, len, len1, len2, node, nodeA, nodeB, nodeid, nodes, ref, ref1, source, startpoint, target, vdebug;
+  source = options.source, target = options.target, directed = options.directed, distance = options.distance, nodeid = options.nodeid, startpoint = options.startpoint, endpoint = options.endpoint, K = options.K, vdebug = options.vdebug;
+  if (!directed) {
+    directed = false;
+  }
+  if (K == null) {
+    K = 1;
+  }
+  if (nodeid == null) {
+    nodeid = function(node) {
+      return node;
+    };
+  } else if (typeof nodeid === 'string') {
+    nodeid = (function(nodeid) {
+      return function(node) {
+        return node[nodeid];
+      };
+    })(nodeid);
+  }
+  if ((source != null) && typeof source === 'object') {
+    source = nodeid(source);
+  }
+  if ((target != null) && typeof target === 'object') {
+    target = nodeid(target);
+  }
+  if (startpoint == null) {
+    startpoint = function(edge) {
+      return edge.source;
+    };
+  } else if (typeof startpoint === 'string') {
+    startpoint = (function(startpoint) {
+      return function(edge) {
+        return edge[startpoint];
+      };
+    })(startpoint);
+  }
+  if (endpoint == null) {
+    endpoint = function(edge) {
+      return edge.target;
+    };
+  } else if (typeof endpoint === 'string') {
+    endpoint = (function(endpoint) {
+      return function(edge) {
+        return edge[endpoint];
+      };
+    })(endpoint);
+  }
+  if (distance == null) {
+    distance = function(edge) {
+      return 1;
+    };
+  } else if (typeof distance === 'number') {
+    distance = (function(distance) {
+      return function(edge) {
+        return distance;
+      };
+    })(distance);
+  } else if (typeof distance === 'string') {
+    distance = (function(distance) {
+      return function(edge) {
+        return edge[distance];
+      };
+    })(distance);
+  } else if (distance instanceof Array) {
+    edge2distance = {};
+    for (i = j = 0, len = edges.length; j < len; i = ++j) {
+      edge = edges[i];
+      a = nodeid(startpoint(edge));
+      b = nodeid(endpoint(edge));
+      edge2distance[a + '_' + b] = distance[i];
+    }
+    distance = function(edge) {
+      a = nodeid(startpoint(edge));
+      b = nodeid(endpoint(edge));
+      return edge2distance[a + '_' + b];
+    };
+  }
+  nodes = {};
+  for (k = 0, len1 = edges.length; k < len1; k++) {
+    edge = edges[k];
+    nodeA = startpoint(edge);
+    nodeB = endpoint(edge);
+    idA = nodeid(nodeA);
+    idB = nodeid(nodeB);
+    ref = [nodeA, nodeB];
+    for (l = 0, len2 = ref.length; l < len2; l++) {
+      node = ref[l];
+      id = nodeid(node);
+      if (!(id in nodes)) {
+        nodes[id] = {
+          node: node,
+          outedges: []
+        };
+      }
+    }
+    nodes[idA].outedges.push(edge);
+    if (!directed) {
+      nodes[idB].outedges.push(edge);
+    }
+  }
+  errormsg = null;
+  if (edges.length === 0) {
+    errormsg = 'The length of edges is 0';
+  } else if (K < 0) {
+    errormsg = 'K can not have negative value';
+  } else if (distance(edges[0]) == null) {
+    errormsg = 'Check the distance function/attribute';
+  } else if (startpoint(edges[0]) == null) {
+    errormsg = 'Check the startpoint function/attribute';
+  } else if (endpoint(edges[0]) == null) {
+    errormsg = 'Check the endpoint function/attribute';
+  } else {
+    id1 = nodeid(startpoint(edges[0]));
+    if ((id1 == null) || ((ref1 = typeof id1) !== 'string' && ref1 !== 'number')) {
+      errormsg = 'Check the nodeid function/attribute';
+    } else if ((source != null) && !(source in nodes)) {
+      errormsg = 'The source is not in the graph';
+    } else if ((target != null) && !(target in nodes)) {
+      errormsg = 'The target is not in the graph';
+    }
+  }
+  if (errormsg != null) {
+    print.error(errormsg);
+    return null;
+  }
+  return [
+    edges, {
+      source: source,
+      target: target,
+      directed: directed,
+      distance: distance,
+      nodeid: nodeid,
+      startpoint: startpoint,
+      endpoint: endpoint,
+      K: K,
+      nodes: nodes,
+      vdebug: vdebug
+    }
+  ];
+};
+
+
+},{"../core/console/print.coffee":53}],166:[function(require,module,exports){
+var Heap, normalize;
+
+Heap = require('heap');
+
+normalize = require("./normalize.coffee");
+
+module.exports = function(edges, source, options) {
+  var K, a, alt, b, directed, distance, edge, endpoint, getPath, heap, i, id, j, len, len1, maxsize, node, nodeid, nodes, path, ref, ref1, ref2, res, result, startpoint, target, u, visited;
+  if (options == null) {
+    options = {};
+  }
+  options.source = source;
+  if ((options.nodes == null) || typeof options.nodes !== 'object') {
+    ref = normalize(edges, options), edges = ref[0], options = ref[1];
+    if (options === null) {
+      return null;
+    }
+  }
+  source = options.source, target = options.target, directed = options.directed, distance = options.distance, nodeid = options.nodeid, startpoint = options.startpoint, endpoint = options.endpoint, K = options.K, nodes = options.nodes;
+  for (id in nodes) {
+    node = nodes[id];
+    node.count = 0;
+  }
+  heap = new Heap(function(a, b) {
+    return a.distance - b.distance;
+  });
+  visited = {};
+  if (target == null) {
+    visited[source] = true;
+  }
+  heap.push({
+    edge: null,
+    target: source,
+    distance: 0
+  });
+  maxsize = 0;
+  result = [];
+  while (!heap.empty()) {
+    maxsize = Math.max(maxsize, heap.size());
+    path = heap.pop();
+    u = path.target;
+    nodes[u].count++;
+    if (target == null) {
+      result.push(path);
+    } else if (u === target) {
+      result.push(path);
+    }
+    if (result.length === K) {
+      break;
+    }
+    if (nodes[u].count <= K) {
+      ref1 = nodes[u].outedges;
+      for (i = 0, len = ref1.length; i < len; i++) {
+        edge = ref1[i];
+        a = nodeid(startpoint(edge));
+        b = nodeid(endpoint(edge));
+        if (!directed && b === u) {
+          ref2 = [b, a], a = ref2[0], b = ref2[1];
+        }
+        if (target == null) {
+          if (visited[b]) {
+            continue;
+          }
+          visited[b] = true;
+        }
+        alt = path.distance + distance(edge);
+        heap.push({
+          edge: edge,
+          previous: path,
+          target: b,
+          distance: alt
+        });
+      }
+    }
+  }
+  getPath = function(path) {
+    edges = [];
+    while (path.edge != null) {
+      edges.push(path.edge);
+      path = path.previous;
+    }
+    return edges.reverse();
+  };
+  for (j = 0, len1 = result.length; j < len1; j++) {
+    res = result[j];
+    if (target != null) {
+      delete res.target;
+      res.edges = getPath(res);
+    }
+    delete res.edge;
+    delete res.previous;
+  }
+  return result;
+};
+
+
+},{"./normalize.coffee":165,"heap":5}],167:[function(require,module,exports){
+var distance;
+
+distance = require("./distance.coffee");
+
+module.exports = function(arr, opts) {
+  var distances, quad;
+  if (!opts) {
+    opts = {};
+  }
+  distances = [];
+  quad = d3.geom.quadtree().x(function(d) {
+    if (opts.accessor) {
+      return opts.accessor(d)[0];
+    } else {
+      return d[0];
+    }
+  }).y(function(d) {
+    if (opts.accessor) {
+      return opts.accessor(d)[1];
+    } else {
+      return d[1];
+    }
+  });
+  quad(arr).visit(function(node) {
+    var i, j, len, len1, n1, n2, ref, ref1;
+    if (!node.leaf) {
+      ref = node.nodes;
+      for (i = 0, len = ref.length; i < len; i++) {
+        n1 = ref[i];
+        if (n1 && n1.point) {
+          if (opts.origin) {
+            distances.push(distance(n1, opts));
+          } else {
+            ref1 = node.nodes;
+            for (j = 0, len1 = ref1.length; j < len1; j++) {
+              n2 = ref1[j];
+              if (n2 && n2.point && n2.point !== n1.point) {
+                distances.push(distance(n1, n2));
+              }
+            }
+          }
+        }
+      }
+    }
+    return false;
+  });
+  if (opts.all) {
+    return distances.sort(function(aa, bb) {
+      return aa - bb;
+    });
+  } else {
+    return d3.min(distances);
+  }
+};
+
+
+},{"./distance.coffee":164}],168:[function(require,module,exports){
+var normalize;
+
+normalize = require("./normalize.coffee");
+
+module.exports = function(edges, source, options) {
+  var K, dfs, directed, distance, edge, endpoint, id, nodeid, nodes, ref, startpoint, visited;
+  if (options == null) {
+    options = {};
+  }
+  options.source = source;
+  if ((options.nodes == null) || typeof options.nodes !== 'object') {
+    ref = normalize(edges, options), edges = ref[0], options = ref[1];
+    if (options === null) {
+      return null;
+    }
+  }
+  source = options.source, directed = options.directed, distance = options.distance, nodeid = options.nodeid, startpoint = options.startpoint, endpoint = options.endpoint, K = options.K, nodes = options.nodes;
+  visited = {};
+  visited[source] = true;
+  dfs = function(origin, curr_distance) {
+    var a, b, edge, i, len, new_distance, ref1, ref2, results;
+    ref1 = nodes[origin].outedges;
+    results = [];
+    for (i = 0, len = ref1.length; i < len; i++) {
+      edge = ref1[i];
+      a = nodeid(startpoint(edge));
+      b = nodeid(endpoint(edge));
+      if (!directed && b === origin) {
+        ref2 = [b, a], a = ref2[0], b = ref2[1];
+      }
+      if (!(b in visited)) {
+        new_distance = curr_distance + distance(edge);
+        if (new_distance <= K) {
+          visited[b] = true;
+          results.push(dfs(b, new_distance));
+        } else {
+          results.push(void 0);
+        }
+      } else {
+        results.push(void 0);
+      }
+    }
+    return results;
+  };
+  dfs(source, 0);
+  return {
+    nodes: (function() {
+      var results;
+      results = [];
+      for (id in visited) {
+        results.push(nodes[id].node);
+      }
+      return results;
+    })(),
+    edges: (function() {
+      var i, len, results;
+      results = [];
+      for (i = 0, len = edges.length; i < len; i++) {
+        edge = edges[i];
+        if (nodeid(startpoint(edge)) in visited && nodeid(endpoint(edge)) in visited) {
+          results.push(edge);
+        }
+      }
+      return results;
+    })()
+  };
+};
+
+
+},{"./normalize.coffee":165}],169:[function(require,module,exports){
+var defaultLocale;
+
+defaultLocale = require("../core/locale/languages/en_US.coffee");
+
+module.exports = function(number, opts) {
+  var affixes, format, key, labels, length, locale, ret, sigs, symbol, time, vars, zeros;
+  if (!opts) {
+    opts = {};
+  }
+  if ("locale" in opts) {
+    locale = opts.locale;
+  } else {
+    locale = defaultLocale;
+  }
+  time = locale.time.slice();
+  format = d3.locale(locale.format);
+  if (!opts) {
+    opts = {};
+  }
+  vars = opts.vars || {};
+  key = opts.key;
+  labels = "labels" in opts ? opts.labels : true;
+  length = number.toString().split(".")[0].length;
+  if (vars.time && vars.time.value) {
+    time.push(vars.time.value);
+  }
+  if (typeof key === "string" && time.indexOf(key.toLowerCase()) >= 0) {
+    ret = number;
+  } else if (key === "share") {
+    if (number === 0) {
+      ret = 0;
+    } else if (number >= 100) {
+      ret = format.numberFormat(",f")(number);
+    } else if (number > 99) {
+      ret = format.numberFormat(".3g")(number);
+    } else {
+      ret = format.numberFormat(".2g")(number);
+    }
+    ret += "%";
+  } else if (number < 10 && number > -10) {
+    length = number.toString().split(".");
+    sigs = 1;
+    if (length.length > 1) {
+      sigs = d3.min([parseFloat(length[1]).toString().length, 2]);
+      if (!((-1 < number && number < 1))) {
+        zeros = length[1].length - parseFloat(length[1]).toString().length;
+        sigs += 1 + zeros;
+      }
+    }
+    ret = format.numberFormat("." + sigs + "g")(number);
+  } else if (length > 3) {
+    symbol = d3.formatPrefix(number).symbol;
+    symbol = symbol.replace("G", "B");
+    number = d3.formatPrefix(number).scale(number);
+    number = format.numberFormat(".3g")(number);
+    number = number.replace(locale.format.decimal, ".");
+    number = parseFloat(number) + "";
+    number = number.replace(".", locale.format.decimal);
+    ret = number + symbol;
+  } else if (length === 3) {
+    ret = format.numberFormat(",f")(number);
+  } else if (number === 0) {
+    ret = 0;
+  } else {
+    if (number === parseInt(number, 10)) {
+      ret = format.numberFormat(".2")(number);
+    } else {
+      ret = format.numberFormat(".3g")(number);
+    }
+  }
+  if (labels && key && "format" in vars && key in vars.format.affixes.value) {
+    affixes = vars.format.affixes.value[key];
+    return affixes[0] + ret + affixes[1];
+  } else {
+    return ret;
+  }
+};
+
+
+},{"../core/locale/languages/en_US.coffee":70}],170:[function(require,module,exports){
+var d3selection, validate;
+
+d3selection = require("../util/d3selection.coffee");
+
+validate = require("./validate.coffee");
+
+
+/**
+ * Given any two objects, this method will merge the two objects together, returning a new third object. The values of the second object always overwrite the first.
+ * @method d3plus.object.merge
+ * @for d3plus.object
+ * @param obj1 {Object} The primary object.
+ * @param obj2 {Object} The secondary object to merge into the first.
+ * @return {Object}
+ */
+
+module.exports = function(obj1, obj2) {
+  var copyObject, obj3;
+  copyObject = function(obj, ret, shallow) {
+    var k, results, v;
+    results = [];
+    for (k in obj) {
+      v = obj[k];
+      if (typeof v !== "undefined") {
+        if (!shallow && validate(v)) {
+          if (typeof ret[k] !== "object") {
+            ret[k] = {};
+          }
+          results.push(copyObject(v, ret[k], k.indexOf("d3plus") === 0));
+        } else if (!d3selection(v) && v instanceof Array) {
+          results.push(ret[k] = v.slice(0));
+        } else {
+          results.push(ret[k] = v);
+        }
+      } else {
+        results.push(void 0);
+      }
+    }
+    return results;
+  };
+  obj3 = {};
+  if (obj1) {
+    copyObject(obj1, obj3);
+  }
+  if (obj2) {
+    copyObject(obj2, obj3);
+  }
+  return obj3;
+};
+
+
+},{"../util/d3selection.coffee":207,"./validate.coffee":171}],171:[function(require,module,exports){
+
+/**
+ * This function returns true if the variable passed is a literal javascript keyed Object. It's a small, simple function, but it catches some edge-cases that can throw off your code (such as Arrays and `null`).
+ * @method d3plus.object.validate
+ * @for d3plus.object
+ * @param obj {Object} The object to validate.
+ * @return {Boolean}
+ */
+module.exports = function(obj) {
+  return obj && obj.constructor === Object;
+};
+
+
+},{}],172:[function(require,module,exports){
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Formats a string similar to Python's "format"
+//------------------------------------------------------------------------------
+module.exports = function() {
+
+  var args = Array.prototype.slice.call(arguments)
+    , str = args.shift()
+
+  str.unkeyed_index = 0;
+  return str.replace(/\{(\w*)\}/g, function(match, key) {
+      if (key === '') {
+          key = str.unkeyed_index;
+          str.unkeyed_index++
+      }
+      if (key == +key) {
+          return args[key] !== 'undefined'
+              ? args[key]
+              : match;
+      } else {
+          for (var i = 0; i < args.length; i++) {
+              if (typeof args[i] === 'object' && typeof args[i][key] !== 'undefined') {
+                  return args[i][key];
+              }
+          }
+          return match;
+      }
+  }.bind(str));
+
+}
+
+},{}],173:[function(require,module,exports){
+var format, locale;
+
+format = require("./format.js");
+
+locale = require("../core/locale/languages/en_US.coffee").ui;
+
+module.exports = function(list, andText, max, moreText) {
+  var amount;
+  if (!(list instanceof Array)) {
+    return list;
+  } else {
+    list = list.slice(0);
+  }
+  if (!andText) {
+    andText = locale.and;
+  }
+  if (!moreText) {
+    moreText = locale.moreText;
+  }
+  if (list.length === 2) {
+    return list.join(" " + andText + " ");
+  } else {
+    if (max && list.length > max) {
+      amount = list.length - max + 1;
+      list = list.slice(0, max - 1);
+      list[max - 1] = format(moreText, amount);
+    }
+    if (list.length > 1) {
+      list[list.length - 1] = andText + " " + list[list.length - 1];
+    }
+    return list.join(", ");
+  }
+};
+
+
+},{"../core/locale/languages/en_US.coffee":70,"./format.js":172}],174:[function(require,module,exports){
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Removes all non ASCII characters
+//------------------------------------------------------------------------------
+module.exports = function(str) {
+
+  var removed = [ "!","@","#","$","%","^","&","*","(",")",
+                  "[","]","{","}",".",",","/","\\","|",
+                  "'","\"",";",":","<",">","?","=","+"];
+
+  var diacritics = [
+      [/[\300-\306]/g, "A"],
+      [/[\340-\346]/g, "a"],
+      [/[\310-\313]/g, "E"],
+      [/[\350-\353]/g, "e"],
+      [/[\314-\317]/g, "I"],
+      [/[\354-\357]/g, "i"],
+      [/[\322-\330]/g, "O"],
+      [/[\362-\370]/g, "o"],
+      [/[\331-\334]/g, "U"],
+      [/[\371-\374]/g, "u"],
+      [/[\321]/g, "N"],
+      [/[\361]/g, "n"],
+      [/[\307]/g, "C"],
+      [/[\347]/g, "c"]
+  ];
+
+  str += "";
+
+  return ""+str.replace(/[^A-Za-z0-9\-_]/g, function(chr) {
+
+    if (" " === chr) {
+      return "_";
+    }
+    else if (removed.indexOf(chr) >= 0) {
+      return "";
+    }
+
+    var ret = chr;
+    for (var d = 0; d < diacritics.length; d++) {
+      if (new RegExp(diacritics[d][0]).test(chr)) {
+        ret = diacritics[d][1];
+        break;
+      }
+    }
+
+    return ret;
+
+  });
+
+};
+
+},{}],175:[function(require,module,exports){
+var defaultLocale;
+
+defaultLocale = require("../core/locale/languages/en_US.coffee");
+
+module.exports = function(text, opts) {
+  var biglow, bigs, key, locale, smalls;
+  if (!text) {
+    return "";
+  }
+  if (!opts) {
+    opts = {};
+  }
+  key = opts.key;
+  if (text.charAt(text.length - 1) === ".") {
+    return text.charAt(0).toUpperCase() + text.substr(1);
+  }
+  locale = "locale" in this ? this.locale.value : defaultLocale;
+  smalls = locale.lowercase.map(function(b) {
+    return b.toLowerCase();
+  });
+  bigs = locale.uppercase;
+  bigs = bigs.concat(bigs.map(function(b) {
+    return b + "s";
+  }));
+  biglow = bigs.map(function(b) {
+    return b.toLowerCase();
+  });
+  return text.replace(/[^\s!-#%-\x2A,-\/:;\x3F@\x5B-\x5D_\x7B}\u00A1\u00A7\u00AB\u00B6\u00B7\u00BB\u00BF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E3B\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]*/g, function(txt, i) {
+    var bigindex, new_txt;
+    if (txt) {
+      bigindex = biglow.indexOf(txt.toLowerCase());
+      if (bigindex >= 0) {
+        return new_txt = bigs[bigindex];
+      } else if (smalls.indexOf(txt.toLowerCase()) >= 0 && i !== 0 && i !== text.length - 1) {
+        return new_txt = txt.toLowerCase();
+      } else {
+        return new_txt = txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
+      }
+    } else {
+      return "";
+    }
+  });
+};
+
+
+},{"../core/locale/languages/en_US.coffee":70}],176:[function(require,module,exports){
+var foreign, tspan;
+
+foreign = require("./foreign.coffee");
+
+tspan = require("./tspan.coffee");
+
+module.exports = function(vars) {
+  if (vars.text.html.value) {
+    foreign(vars);
+  } else {
+    tspan(vars);
+  }
+};
+
+
+},{"./foreign.coffee":177,"./tspan.coffee":180}],177:[function(require,module,exports){
+module.exports = function(vars) {
+  var anchor, color, family, opacity, text;
+  text = vars.container.value;
+  family = text.attr("font-family") || text.style("font-family");
+  anchor = vars.align.value || text.attr("text-anchor") || text.style("text-anchor");
+  color = text.attr("fill") || text.style("fill");
+  opacity = text.attr("opacity") || text.style("opacity");
+  anchor = anchor === "end" ? "right" : (anchor === "middle" ? "center" : "left");
+  d3.select(text.node().parentNode).append("foreignObject").attr("width", vars.width.value + "px").attr("height", vars.height.value + "px").attr("x", "0px").attr("y", "0px").append("xhtml:div").style("font-family", family).style("font-size", vars.size.value[1] + "px").style("color", color).style("text-align", anchor).style("opacity", opacity).text(vars.text.current);
+};
+
+
+},{}],178:[function(require,module,exports){
+module.exports = function(vars) {
+  var diff, elem, height, prev, radius, shape, size, width, x, y;
+  elem = vars.container.value;
+  prev = elem.node().previousElementSibling;
+  shape = prev ? prev.tagName.toLowerCase() : "";
+  if (prev) {
+    prev = d3.select(prev);
+  }
+  vars.container.x = vars.x.value || parseFloat(elem.attr("x"), 10);
+  vars.container.y = vars.y.value || parseFloat(elem.attr("y"), 10);
+  if (prev) {
+    if (vars.shape.accepted.indexOf(shape) >= 0) {
+      vars.self.shape(shape);
+    }
+    if (shape === "rect") {
+      x = parseFloat(prev.attr("x"), 10) || 0;
+      y = parseFloat(prev.attr("y"), 10) || 0;
+      if (vars.padding.value === false) {
+        diff = Math.abs(x - vars.container.x);
+        if (diff) {
+          vars.self.padding(diff);
+        }
+      }
+      if (!vars.container.x) {
+        vars.container.x = x + vars.padding.value;
+      }
+      if (!vars.container.y) {
+        vars.container.y = y + vars.padding.value;
+      }
+      if (!vars.width.value) {
+        width = parseFloat(prev.attr("width" || prev.style("width", 10)));
+        vars.self.width(width);
+      }
+      if (!vars.height.value) {
+        height = parseFloat(prev.attr("height" || prev.style("height", 10)));
+        vars.self.height(height);
+      }
+    } else if (shape === "circle") {
+      radius = parseFloat(prev.attr("r"), 10);
+      x = parseFloat(prev.attr("cx"), 10) || 0;
+      x -= radius;
+      y = parseFloat(prev.attr("cy"), 10) || 0;
+      y -= radius;
+      if (vars.padding.value === false) {
+        diff = Math.abs(x - vars.container.x);
+        if (diff) {
+          vars.self.padding(diff);
+        }
+      }
+      if (!vars.container.x) {
+        vars.container.x = x + vars.padding.value;
+      }
+      if (!vars.container.y) {
+        vars.container.y = y + vars.padding.value;
+      }
+      if (!vars.width.value) {
+        vars.self.width(radius * 2, 10);
+      }
+      if (!vars.height.value) {
+        vars.self.height(radius * 2, 10);
+      }
+    } else {
+      if (!vars.width.value) {
+        vars.self.width(500);
+      }
+      if (!vars.height.value) {
+        vars.self.height(500);
+      }
+    }
+  }
+  if (!vars.container.x) {
+    vars.container.x = 0;
+  }
+  if (!vars.container.y) {
+    vars.container.y = 0;
+  }
+  vars.width.inner = vars.width.value - vars.padding.value * 2;
+  vars.height.inner = vars.height.value - vars.padding.value * 2;
+  size = elem.attr("font-size") || elem.style("font-size");
+  size = parseFloat(size, 10);
+  vars.container.fontSize = size;
+  vars.container.dy = parseFloat(elem.attr("dy"), 10);
+  if (!vars.size.value) {
+    if (vars.resize.value) {
+      return vars.self.size([4, 80]);
+    } else {
+      return vars.self.size([size / 2, size]);
+    }
+  }
+};
+
+
+},{}],179:[function(require,module,exports){
+module.exports = function(vars) {
+  var text;
+  if (!vars.text.value) {
+    text = vars.container.value.text();
+    if (text) {
+      if (text.indexOf("tspan") >= 0) {
+        text.replace(/\<\/tspan\>\<tspan\>/g, " ");
+        text.replace(/\<\/tspan\>/g, "");
+        text.replace(/\<tspan\>/g, "");
+      }
+      text = text.replace(/(\r\n|\n|\r)/gm, "");
+      text = text.replace(/^\s+|\s+$/g, "");
+      vars.self.text(text);
+    }
+  }
+  if (vars.text.value instanceof Array) {
+    vars.text.phrases = vars.text.value.filter(function(t) {
+      return ["string", "number"].indexOf(typeof t) >= 0;
+    });
+  } else {
+    vars.text.phrases = [vars.text.value + ""];
+  }
+  if (!vars.align.value) {
+    return vars.container.align = vars.container.value.style("text-anchor") || vars.container.value.attr("text-anchor");
+  }
+};
+
+
+},{}],180:[function(require,module,exports){
+module.exports = function(vars) {
+  var anchor, dx, dy, ellipsis, fontSize, h, height, line, lineWidth, lines, mirror, newLine, placeWord, progress, reverse, rmod, rotate, rx, ry, space, start, textBox, translate, truncate, valign, width, words, wrap, x, y, yOffset;
+  newLine = function(w, first) {
+    var tspan;
+    if (!w) {
+      w = "";
+    }
+    if (!reverse || first) {
+      tspan = vars.container.value.append("tspan");
+    } else {
+      tspan = vars.container.value.insert("tspan", "tspan");
+    }
+    return tspan.attr("x", x + "px").attr("dx", dx + "px").attr("dy", dy + "px").style("baseline-shift", "0%").attr("dominant-baseline", "alphabetic").text(w);
+  };
+  mirror = vars.rotate.value === -90 || vars.rotate.value === 90;
+  width = mirror ? vars.height.inner : vars.width.inner;
+  height = mirror ? vars.width.inner : vars.height.inner;
+  if (vars.shape.value === "circle") {
+    anchor = "middle";
+  } else {
+    anchor = vars.align.value || vars.container.align || "start";
+  }
+  if (anchor === "end") {
+    dx = width;
+  } else if (anchor === "middle") {
+    dx = width / 2;
+  } else {
+    dx = 0;
+  }
+  valign = vars.valign.value || "top";
+  x = vars.container.x;
+  fontSize = vars.resize.value ? vars.size.value[1] : vars.container.fontSize || vars.size.value[0];
+  dy = vars.container.dy || fontSize * 1.1;
+  textBox = null;
+  progress = null;
+  words = null;
+  reverse = false;
+  yOffset = 0;
+  if (vars.shape.value === "circle") {
+    if (valign === "middle") {
+      yOffset = ((height / dy % 1) * dy) / 2;
+    } else if (valign === "end") {
+      yOffset = (height / dy % 1) * dy;
+    }
+  }
+  vars.container.value.attr("text-anchor", anchor).attr("font-size", fontSize + "px").style("font-size", fontSize + "px").attr("x", vars.container.x).attr("y", vars.container.y);
+  truncate = function() {
+    textBox.remove();
+    if (reverse) {
+      line++;
+      textBox = vars.container.value.select("tspan");
+    } else {
+      line--;
+      textBox = d3.select(vars.container.value.node().lastChild);
+    }
+    if (!textBox.empty()) {
+      words = textBox.text().match(/[^\s-]+-?/g);
+      return ellipsis();
+    }
+  };
+  lineWidth = function() {
+    var b;
+    if (vars.shape.value === "circle") {
+      b = ((line - 1) * dy) + yOffset;
+      if (b > height / 2) {
+        b += dy;
+      }
+      return 2 * Math.sqrt(b * ((2 * (width / 2)) - b));
+    } else {
+      return width;
+    }
+  };
+  ellipsis = function() {
+    var lastChar, lastWord;
+    if (words && words.length) {
+      lastWord = words.pop();
+      lastChar = lastWord.charAt(lastWord.length - 1);
+      if (lastWord.length === 1 && vars.text.split.value.indexOf(lastWord) >= 0) {
+        return ellipsis();
+      } else {
+        if (vars.text.split.value.indexOf(lastChar) >= 0) {
+          lastWord = lastWord.substr(0, lastWord.length - 1);
+        }
+        textBox.text(words.join(" ") + " " + lastWord + "...");
+        if (textBox.node().getComputedTextLength() > lineWidth()) {
+          return ellipsis();
+        }
+      }
+    } else {
+      return truncate();
+    }
+  };
+  placeWord = function(word) {
+    var current, joiner, next_char;
+    current = textBox.text();
+    if (reverse) {
+      next_char = vars.text.current.charAt(vars.text.current.length - progress.length - 1);
+      joiner = next_char === " " ? " " : "";
+      progress = word + joiner + progress;
+      textBox.text(word + joiner + current);
+    } else {
+      next_char = vars.text.current.charAt(progress.length);
+      joiner = next_char === " " ? " " : "";
+      progress += joiner + word;
+      textBox.text(current + joiner + word);
+    }
+    if (textBox.node().getComputedTextLength() > lineWidth()) {
+      textBox.text(current);
+      textBox = newLine(word);
+      if (reverse) {
+        return line--;
+      } else {
+        return line++;
+      }
+    }
+  };
+  start = 1;
+  line = null;
+  lines = null;
+  wrap = function() {
+    var i, len, next_char, unsafe, word;
+    vars.container.value.selectAll("tspan").remove();
+    vars.container.value.html("");
+    words = vars.text.words.slice(0);
+    if (reverse) {
+      words.reverse();
+    }
+    progress = words[0];
+    textBox = newLine(words.shift(), true);
+    line = start;
+    for (i = 0, len = words.length; i < len; i++) {
+      word = words[i];
+      if (line * dy > height) {
+        truncate();
+        break;
+      }
+      placeWord(word);
+      unsafe = true;
+      while (unsafe) {
+        next_char = vars.text.current.charAt(progress.length + 1);
+        unsafe = vars.text.split.value.indexOf(next_char) >= 0;
+        if (unsafe) {
+          placeWord(next_char);
+        }
+      }
+    }
+    if (line * dy > height) {
+      truncate();
+    }
+    return lines = Math.abs(line - start) + 1;
+  };
+  wrap();
+  lines = line;
+  if (vars.shape.value === "circle") {
+    space = height - lines * dy;
+    if (space > dy) {
+      if (valign === "middle") {
+        start = (space / dy / 2 >> 0) + 1;
+        wrap();
+      } else if (valign === "bottom") {
+        reverse = true;
+        start = height / dy >> 0;
+        wrap();
+      }
+    }
+  }
+  if (valign === "top") {
+    y = 0;
+  } else {
+    h = lines * dy;
+    y = valign === "middle" ? height / 2 - h / 2 : height - h;
+  }
+  y -= dy * 0.2;
+  translate = "translate(0," + y + ")";
+  if (vars.rotate.value === 180 || vars.rotate.value === -180) {
+    rx = vars.container.x + width / 2;
+    ry = vars.container.y + height / 2;
+  } else {
+    rmod = vars.rotate.value < 0 ? width : height;
+    rx = vars.container.x + rmod / 2;
+    ry = vars.container.y + rmod / 2;
+  }
+  rotate = "rotate(" + vars.rotate.value + ", " + rx + ", " + ry + ")";
+  return vars.container.value.attr("transform", rotate + translate);
+};
+
+
+},{}],181:[function(require,module,exports){
+var flow, fontSizes, resize, wrap;
+
+flow = require("./flow.coffee");
+
+fontSizes = require("../../font/sizes.coffee");
+
+wrap = function(vars) {
+  var firstChar;
+  if (vars.text.phrases.length) {
+    vars.text.current = vars.text.phrases.shift() + "";
+    vars.text.words = vars.text.current.match(vars.text["break"]);
+    firstChar = vars.text.current.charAt(0);
+    if (firstChar !== vars.text.words[0].charAt(0)) {
+      vars.text.words[0] = firstChar + vars.text.words[0];
+    }
+    vars.container.value.text("");
+    if (vars.resize.value) {
+      resize(vars);
+    } else {
+      flow(vars);
+    }
+  }
+};
+
+module.exports = wrap;
+
+resize = function(vars) {
+  var addon, areaMod, areaRatio, boxArea, height, heightMax, i, lineWidth, maxWidth, mirror, sizeMax, sizeRatio, sizes, textArea, width, widthRatio, words;
+  words = [];
+  i = 0;
+  while (i < vars.text.words.length) {
+    addon = (i === vars.text.words.length - 1 ? "" : " ");
+    words.push(vars.text.words[i] + addon);
+    i++;
+  }
+  mirror = vars.rotate.value === -90 || vars.rotate.value === 90;
+  width = mirror ? vars.height.inner : vars.width.inner;
+  height = mirror ? vars.width.inner : vars.height.inner;
+  sizeMax = Math.floor(vars.size.value[1]);
+  lineWidth = vars.shape.value === "circle" ? width * 0.75 : width;
+  sizes = fontSizes(words, {
+    "font-size": sizeMax + "px",
+    parent: vars.container.value
+  });
+  maxWidth = d3.max(sizes, function(d) {
+    return d.width;
+  });
+  areaMod = 1.165 + (width / height * 0.11);
+  textArea = d3.sum(sizes, function(d) {
+    var h;
+    h = vars.container.dy || sizeMax * 1.2;
+    return d.width * h;
+  }) * areaMod;
+  if (vars.shape.value === "circle") {
+    boxArea = Math.PI * Math.pow(width / 2, 2);
+  } else {
+    boxArea = lineWidth * height;
+  }
+  if (maxWidth > lineWidth || textArea > boxArea) {
+    areaRatio = Math.sqrt(boxArea / textArea);
+    widthRatio = lineWidth / maxWidth;
+    sizeRatio = d3.min([areaRatio, widthRatio]);
+    sizeMax = d3.max([vars.size.value[0], Math.floor(sizeMax * sizeRatio)]);
+  }
+  heightMax = Math.floor(height * 0.8);
+  if (sizeMax > heightMax) {
+    sizeMax = heightMax;
+  }
+  if (maxWidth * (sizeMax / vars.size.value[1]) <= lineWidth) {
+    if (sizeMax !== vars.size.value[1]) {
+      vars.self.size([vars.size.value[0], sizeMax]);
+    }
+    flow(vars);
+  } else {
+    wrap(vars);
+  }
+};
+
+
+},{"../../font/sizes.coffee":101,"./flow.coffee":176}],182:[function(require,module,exports){
+module.exports = {
+  accepted: [false, "start", "middle", "end", "left", "center", "right"],
+  process: function(value) {
+    var css;
+    css = ["left", "center", "right"].indexOf(value);
+    if (css >= 0) {
+      value = this.accepted[css + 1];
+    }
+    return value;
+  },
+  value: false
+};
+
+
+},{}],183:[function(require,module,exports){
+module.exports = {
+  accepted: [Object],
+  objectAccess: false,
+  process: function(value, vars) {
+    var method, setting;
+    for (method in value) {
+      setting = value[method];
+      if (method in vars.self) {
+        vars.self[method](setting);
+      }
+    }
+    return value;
+  },
+  value: {}
+};
+
+
+},{}],184:[function(require,module,exports){
+var d3selection;
+
+d3selection = require("../../util/d3selection.coffee");
+
+module.exports = {
+  accepted: [false, Array, Object, String],
+  element: false,
+  id: "default",
+  process: function(value) {
+    if (value === false) {
+      return false;
+    } else if (d3selection(value)) {
+      return value;
+    } else if (value instanceof Array) {
+      return d3.select(value[0][0]);
+    } else {
+      return d3.select(value);
+    }
+  },
+  value: false
+};
+
+
+},{"../../util/d3selection.coffee":207}],185:[function(require,module,exports){
+module.exports = {
+  accepted: [Boolean],
+  value: false
+};
+
+
+},{}],186:[function(require,module,exports){
+var print, stringFormat;
+
+print = require("../../core/console/print.coffee");
+
+stringFormat = require("../../string/format.js");
+
+module.exports = {
+  accepted: [void 0],
+  process: function(value, vars) {
+    var str;
+    if (this.initialized === false) {
+      return value;
+    }
+    if (vars.container.value === false) {
+      str = vars.format.locale.value.dev.setContainer;
+      print.warning(str, "container");
+    } else if (vars.container.value.empty()) {
+      str = vars.format.locale.value.dev.noContainer;
+      print.warning(stringFormat(str, "\"" + vars.container.value + "\""), "container");
+    } else {
+      if (vars.dev.value) {
+        print.time("total draw time");
+      }
+      vars.container.value.call(vars.self);
+    }
+    return value;
+  },
+  value: void 0
+};
+
+
+},{"../../core/console/print.coffee":53,"../../string/format.js":172}],187:[function(require,module,exports){
+var locale, mergeObject;
+
+locale = require("../../core/locale/locale.coffee");
+
+mergeObject = require("../../object/merge.coffee");
+
+module.exports = {
+  accepted: [Function, String],
+  locale: {
+    accepted: function() {
+      return d3.keys(locale);
+    },
+    process: function(value) {
+      var defaultLocale, returnObject;
+      defaultLocale = "en_US";
+      returnObject = locale[defaultLocale];
+      if (value !== defaultLocale) {
+        returnObject = mergeObject(returnObject, locale[value]);
+      }
+      this.language = value;
+      return returnObject;
+    },
+    value: "en_US"
+  },
+  process: function(value, vars) {
+    if (this.initialized && typeof value === "string") {
+      vars.self.format({
+        locale: value
+      });
+    } else {
+      if (typeof value === "function") {
+        return value;
+      }
+    }
+    return this.value;
+  },
+  value: "en_US"
+};
+
+
+},{"../../core/locale/locale.coffee":78,"../../object/merge.coffee":170}],188:[function(require,module,exports){
+module.exports = {
+  accepted: [false, Number],
+  value: false
+};
+
+
+},{}],189:[function(require,module,exports){
+module.exports = {
+  accepted: [false, Number],
+  value: false
+};
+
+
+},{}],190:[function(require,module,exports){
+module.exports = {
+  accepted: [Boolean],
+  value: false
+};
+
+
+},{}],191:[function(require,module,exports){
+module.exports = {
+  accepted: [-180, -90, 0, 90, 180],
+  value: 0
+};
+
+
+},{}],192:[function(require,module,exports){
+module.exports = {
+  accepted: ["circle", "square"],
+  value: false
+};
+
+
+},{}],193:[function(require,module,exports){
+module.exports = {
+  accepted: [Array, false],
+  value: false
+};
+
+
+},{}],194:[function(require,module,exports){
+module.exports = {
+  accepted: [false, Array, Number, String],
+  html: {
+    accepted: [Boolean],
+    value: false
+  },
+  init: function(vars) {
+    var s;
+    s = this.split.value;
+    this["break"] = new RegExp("[^\\s\\" + s.join("\\") + "]+\\" + s.join("?\\") + "?", "g");
+    return false;
+  },
+  split: {
+    accepted: [Array],
+    value: ["-", "/", ";", ":", "&"]
+  }
+};
+
+
+},{}],195:[function(require,module,exports){
+module.exports = {
+  accepted: [false, "top", "middle", "bottom"],
+  value: false
+};
+
+
+},{}],196:[function(require,module,exports){
+module.exports = {
+  accepted: [false, Number],
+  value: false
+};
+
+
+},{}],197:[function(require,module,exports){
+module.exports = {
+  accepted: [false, Number],
+  value: false
+};
+
+
+},{}],198:[function(require,module,exports){
+module.exports = {
+  accepted: [false, Number],
+  value: false
+};
+
+
+},{}],199:[function(require,module,exports){
+var attach, print, sizes, text, wrap;
+
+attach = require("../core/methods/attach.coffee");
+
+sizes = require("./helpers/parseSize.coffee");
+
+print = require("../core/console/print.coffee");
+
+text = require("./helpers/parseText.coffee");
+
+wrap = require("./helpers/wrap.coffee");
+
+module.exports = function() {
+  var vars;
+  vars = {
+    self: function(selection) {
+      selection.each(function() {
+        sizes(vars);
+        if (vars.size.value[0] <= vars.height.inner) {
+          text(vars);
+          wrap(vars);
+        } else {
+          vars.container.value.html("");
+        }
+        if (vars.dev.value) {
+          print.timeEnd("total draw time");
+        }
+      });
+      return vars.self;
+    }
+  };
+  attach(vars, {
+    align: require("./methods/align.coffee"),
+    config: require("./methods/config.coffee"),
+    container: require("./methods/container.coffee"),
+    dev: require("./methods/dev.coffee"),
+    draw: require("./methods/draw.coffee"),
+    format: require("./methods/format.coffee"),
+    height: require("./methods/height.coffee"),
+    padding: require("./methods/padding.coffee"),
+    resize: require("./methods/resize.coffee"),
+    rotate: require("./methods/rotate.coffee"),
+    text: require("./methods/text.coffee"),
+    shape: require("./methods/shape.coffee"),
+    size: require("./methods/size.coffee"),
+    valign: require("./methods/valign.coffee"),
+    width: require("./methods/width.coffee"),
+    x: require("./methods/x.coffee"),
+    y: require("./methods/y.coffee")
+  });
+  return vars.self;
+};
+
+
+},{"../core/console/print.coffee":53,"../core/methods/attach.coffee":79,"./helpers/parseSize.coffee":178,"./helpers/parseText.coffee":179,"./helpers/wrap.coffee":181,"./methods/align.coffee":182,"./methods/config.coffee":183,"./methods/container.coffee":184,"./methods/dev.coffee":185,"./methods/draw.coffee":186,"./methods/format.coffee":187,"./methods/height.coffee":188,"./methods/padding.coffee":189,"./methods/resize.coffee":190,"./methods/rotate.coffee":191,"./methods/shape.coffee":192,"./methods/size.coffee":193,"./methods/text.coffee":194,"./methods/valign.coffee":195,"./methods/width.coffee":196,"./methods/x.coffee":197,"./methods/y.coffee":198}],200:[function(require,module,exports){
+var defaultLocale = require("../core/locale/languages/en_US.coffee"),
+    events        = require("../client/pointer.coffee"),
+    legible       = require("../color/legible.coffee"),
+    move          = require("./move.coffee"),
+    prefix        = require("../client/prefix.coffee"),
+    rtl           = require("../client/rtl.coffee"),
+    removeTooltip = require("./remove.coffee"),
+    stringList    = require("../string/list.coffee"),
+    textColor     = require("../color/text.coffee")
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Create a Tooltip
+//-------------------------------------------------------------------
+module.exports = function(params) {
+
+  var default_width = params.fullscreen ? 250 : 200
+    , vendor = prefix()
+  params.width = params.width || default_width
+  params.max_width = params.max_width || 386
+  params.id = params.id || "default"
+  params.size = params.fullscreen || params.html ? "large" : "small"
+  params.offset = params.offset || 0
+  params.arrow_offset = params.arrow ? 8 : 0
+  params.x = params.x || 0
+  params.y = params.y || 0
+  params.parent = params.parent || d3.select("body")
+  params.curtain = params.curtain || "#fff"
+  params.curtainopacity = params.curtainopacity || 0.8
+  params.background = params.background || "#fff"
+  params.fontcolor = params.fontcolor || "#444"
+  params.fontfamily = params.fontfamily || "sans-serif"
+  params.fontweight = params.fontweight || "normal"
+  params.fontsize = params.fontsize || "12px"
+  params.style = params.style || "default"
+  params.zindex = params.size == "small" ? 2000 : 500
+  params.locale = params.locale || defaultLocale
+
+
+  var parentHeight = params.parent ? params.parent.node().offsetHeight
+                  || params.parent.node().getBoundingClientRect().height : 0
+
+  if (!params.iconsize) {
+    params.iconsize = params.size == "small" ? 22 : 50
+  }
+
+  if (params.parent.node() === document.body) {
+    params.limit = [window.innerWidth + window.scrollX, window.innerHeight + window.scrollY];
+  }
+  else {
+    params.limit = [
+      parseFloat(params.parent.style("width"),10),
+      parseFloat(params.parent.style("height"),10)
+    ];
+  }
+
+  if ( params.title instanceof Array ) {
+
+    var and = params.locale.ui.and
+      , more = params.locale.ui.more
+
+    params.title = stringList( params.title , and , 3 , more )
+
+  }
+
+  removeTooltip(params.id)
+
+  params.anchor = {}
+  if (params.fullscreen) {
+    params.anchor.x = "center"
+    params.anchor.y = "center"
+    params.x = params.parent ? params.parent.node().offsetWidth/2 : window.innerWidth/2
+    params.y = params.parent ? parentHeight/2 : window.innerHeight/2
+  }
+  else if (params.align) {
+    var a = params.align.split(" ")
+    params.anchor.y = a[0]
+    if (a[1]) params.anchor.x = a[1]
+    else params.anchor.x = "center"
+  }
+  else {
+    params.anchor.x = "center"
+    params.anchor.y = "top"
+  }
+
+  var title_width = params.width - 30
+
+  if (params.fullscreen) {
+    var curtain = params.parent.append("div")
+      .attr("id","d3plus_tooltip_curtain_"+params.id)
+      .attr("class","d3plus_tooltip_curtain")
+      .style("background-color",params.curtain)
+      .style("opacity",params.curtainopacity)
+      .style("position","absolute")
+      .style("z-index",499)
+      .style("top","0px")
+      .style("right","0px")
+      .style("bottom","0px")
+      .style("left","0px")
+      .on(events.click,function(){
+        removeTooltip(params.id)
+      })
+  }
+
+  var tooltip = params.parent.append("div")
+    .datum(params)
+    .attr("id","d3plus_tooltip_id_"+params.id)
+    .attr("class","d3plus_tooltip d3plus_tooltip_"+params.size)
+    .style("color",params.fontcolor)
+    .style("font-family",params.fontfamily)
+    .style("font-weight",params.fontweight)
+    .style("font-size",params.fontsize+"px")
+    .style(vendor+"box-shadow","0px 1px 3px rgba(0, 0, 0, 0.25)")
+    .style("position","absolute")
+    // .style("z-index",params.zindex)
+    .on(events.out, close_descriptions)
+
+  if (params.max_height) {
+    tooltip.style("max-height",params.max_height+"px")
+  }
+
+  if (params.fixed) {
+    tooltip.style("z-index",500)
+    params.mouseevents = true
+  }
+  else {
+    tooltip.style("z-index",2000)
+  }
+
+  var container = tooltip.append("div")
+    .datum(params)
+    .attr("class","d3plus_tooltip_container")
+    .style("background-color",params.background)
+    .style("padding","6px")
+
+  if (params.fullscreen && params.html) {
+
+    w = params.parent ? params.parent.node().offsetWidth*0.75 : window.innerWidth*0.75
+    h = params.parent ? parentHeight*0.75 : window.innerHeight*0.75
+
+    container
+      .style("width",w+"px")
+      .style("height",h+"px")
+
+    var body = container.append("div")
+      .attr("class","d3plus_tooltip_body")
+      .style("padding-right","6px")
+      .style("display","inline-block")
+      .style("z-index",1)
+      .style("width",params.width+"px")
+
+  }
+  else {
+
+    if (params.width == "auto") {
+      var w = "auto"
+      container.style("max-width",params.max_width+"px")
+    }
+    else var w = params.width-14+"px"
+
+    var body = container
+      .style("width",w)
+
+  }
+
+  if (params.title || params.icon) {
+    var header = body.append("div")
+      .attr("class","d3plus_tooltip_header")
+      .style("position","relative")
+      .style("z-index",1)
+  }
+
+  if (params.fullscreen) {
+    var close = tooltip.append("div")
+      .attr("class","d3plus_tooltip_close")
+      .style("background-color",params.color)
+      .style("color",textColor(params.color))
+      .style("position","absolute")
+      .style(vendor+"box-shadow","0 1px 3px rgba(0, 0, 0, 0.25)")
+      .style("font-size","20px")
+      .style("height","18px")
+      .style("line-height","14px")
+      .style("text-align","center")
+      .style("right","16px")
+      .style("top","-10px")
+      .style("width","18px")
+      .style("z-index",10)
+      .html("\&times;")
+      .on(events.over,function(){
+        d3.select(this)
+          .style("cursor","pointer")
+          .style(vendor+"box-shadow","0 1px 3px rgba(0, 0, 0, 0.5)")
+      })
+      .on(events.out,function(){
+        d3.select(this)
+          .style("cursor","auto")
+          .style(vendor+"box-shadow","0 1px 3px rgba(0, 0, 0, 0.25)")
+      })
+      .on(events.click,function(){
+        removeTooltip(params.id)
+      })
+  }
+
+  if (!params.mouseevents) {
+    tooltip.style("pointer-events","none")
+  }
+  else if (params.mouseevents !== true) {
+
+    var oldout = d3.select(params.mouseevents).on(events.out)
+
+    var newout = function() {
+
+      var target = d3.event.toElement || d3.event.relatedTarget
+      if (target) {
+        var c = typeof target.className == "string" ? target.className : target.className.baseVal
+        var istooltip = c.indexOf("d3plus_tooltip") == 0
+      }
+      else {
+        var istooltip = false
+      }
+      if (!target || (!ischild(tooltip.node(),target) && !ischild(params.mouseevents,target) && !istooltip)) {
+        oldout(d3.select(params.mouseevents).datum())
+        close_descriptions()
+        d3.select(params.mouseevents).on(events.out,oldout)
+      }
+    }
+
+    var ischild = function(parent, child) {
+       var node = child.parentNode;
+       while (node !== null) {
+         if (node == parent) {
+           return true;
+         }
+         node = node.parentNode;
+       }
+       return false;
+    }
+
+    d3.select(params.mouseevents).on(events.out,newout)
+    tooltip.on(events.out,newout)
+
+    var move_event = d3.select(params.mouseevents).on(events.move)
+    if (move_event) {
+      tooltip.on(events.move,move_event)
+    }
+
+  }
+
+  if (params.arrow) {
+    var arrow = tooltip.append("div")
+      .attr("class","d3plus_tooltip_arrow")
+      .style("background-color",params.background)
+      .style(vendor+"box-shadow","0px 1px 3px rgba(0, 0, 0, 0.25)")
+      .style("position","absolute")
+      .style("bottom","-5px")
+      .style("height","10px")
+      .style("left","50%")
+      .style("margin-left","-5px")
+      .style("width","10px")
+      .style(vendor+"transform","rotate(45deg)")
+      .style("z-index",-1)
+  }
+
+  if (params.icon) {
+
+    var title_icon = header.append("div")
+      .attr("class","d3plus_tooltip_icon")
+      .style("width",params.iconsize+"px")
+      .style("height",params.iconsize+"px")
+      .style("z-index",1)
+      .style("background-position","50%")
+      .style("background-size","100%")
+      .style("background-image","url("+params.icon+")")
+      .style("display","inline-block")
+      .style("margin","0px 3px 3px 0px")
+
+    if (params.style == "knockout") {
+      title_icon.style("background-color",params.color)
+    }
+
+    title_width -= title_icon.node().offsetWidth
+  }
+
+  if (params.title) {
+    var mw = params.max_width-6
+    if ( params.icon ) mw -= (params.iconsize+6)
+    mw += "px"
+
+    var title = header.append("div")
+      .attr("class","d3plus_tooltip_title")
+      .style("max-width",mw)
+      .style("color",!params.icon ? legible(params.color) : params.fontcolor)
+      .style("vertical-align","top")
+      .style("width",title_width+"px")
+      .style("display","inline-block")
+      .style("overflow","hidden")
+      .style("text-overflow","ellipsis")
+      .style("word-wrap","break-word")
+      .style("z-index",1)
+      .style("font-size",params.size === "large" ? "18px" : "16px")
+      .style("line-height",params.size === "large" ? "20px" : "17px")
+      .style("padding",params.size === "large" ? "3px 6px" : "3px")
+      .text(params.title)
+  }
+
+  if (params.description) {
+    var description = body.append("div")
+      .attr("class","d3plus_tooltip_description")
+      .style("font-size","12px")
+      .style("padding","6px")
+      .text(params.description)
+  }
+
+  if (params.data || params.html && !params.fullscreen) {
+
+    var data_container = body.append("div")
+      .attr("class","d3plus_tooltip_data_container")
+      .style("overflow-y","auto")
+      .style("z-index",-1)
+  }
+
+  if (params.data) {
+
+    var val_width = 0, val_heights = {}
+
+    var last_group = null
+    params.data.forEach(function(d,i){
+
+      if (d.group) {
+        if (last_group != d.group) {
+          last_group = d.group
+          data_container.append("div")
+            .attr("class","d3plus_tooltip_data_title")
+            .style("font-size","12px")
+            .style("font-weight","bold")
+            .style("padding","6px 3px 0px 3px")
+            .text(d.group)
+        }
+      }
+
+      var block = data_container.append("div")
+        .attr("class","d3plus_tooltip_data_block")
+        .style("font-size","12px")
+        .style("padding","3px 6px")
+        .style("position","relative")
+        .datum(d)
+
+      if ( d.highlight === true ) {
+        block.style("color",legible(params.color))
+      }
+      else if ( d.allColors || d.highlight !== params.color ) {
+        block.style("color",legible(d.highlight))
+      }
+
+      var name = block.append("div")
+          .attr("class","d3plus_tooltip_data_name")
+          .style("display","inline-block")
+          .html(d.name)
+          .on(events.out,function(){
+            d3.event.stopPropagation()
+          })
+
+      if (d.link) {
+        name
+          .style("cursor","pointer")
+          .on(events.click,d.link)
+      }
+
+      if ( d.value instanceof Array ) {
+
+        var and = params.locale.ui.and
+          , more = params.locale.ui.more
+
+        d.value = list( d.value , and , 3 , more )
+
+      }
+
+      var val = block.append("div")
+          .attr("class","d3plus_tooltip_data_value")
+          .style("display","block")
+          .style("position","absolute")
+          .style("text-align","right")
+          .style("top","3px")
+          .html(d.value)
+          .on(events.out,function(){
+            d3.event.stopPropagation()
+          })
+
+      if (rtl) {
+        val.style("left","6px")
+      }
+      else {
+        val.style("right","6px")
+      }
+
+      if (params.mouseevents && d.desc) {
+        var desc = block.append("div")
+          .attr("class","d3plus_tooltip_data_desc")
+          .style("color","#888")
+          .style("overflow","hidden")
+          .style(vendor+"transition","height 0.5s")
+          .style("width","85%")
+          .text(d.desc)
+          .on(events.out,function(){
+            d3.event.stopPropagation()
+          })
+
+        var dh = desc.node().offsetHeight || desc.node().getBoundingClientRect().height
+
+        desc.style("height","0px")
+
+        var help = name.append("div")
+          .attr("class","d3plus_tooltip_data_help")
+          .style("background-color","#ccc")
+          .style(vendor+"border-radius","5px")
+          .style("color","#fff")
+          .style("cursor","pointer")
+          .style("display","inline-block")
+          .style("font-size","8px")
+          .style("font-weight","bold")
+          .style("height","10px")
+          .style("margin","3px 0px 0px 3px")
+          .style("padding-right","1px")
+          .style("text-align","center")
+          .style("width","10px")
+          .style("vertical-align","top")
+          .style(prefix+"transition","background-color 0.5s")
+          .text("?")
+          .on(events.over,function(){
+            var c = d3.select(this.parentNode.parentNode).style("color")
+            d3.select(this).style("background-color",c)
+            desc.style("height",dh+"px")
+          })
+          .on(events.out,function(){
+            d3.event.stopPropagation()
+          })
+
+        name
+          .style("cursor","pointer")
+          .on(events.over,function(){
+            close_descriptions()
+            var c = d3.select(this.parentNode).style("color")
+            help.style("background-color",c)
+            desc.style("height",dh+"px")
+          })
+
+        block.on(events.out,function(){
+          d3.event.stopPropagation()
+          close_descriptions()
+        })
+      }
+
+      var w = parseFloat(val.style("width"),10)
+      if (w > params.width/2) w = params.width/2
+      if (w > val_width) val_width = w
+
+      if (i != params.data.length-1) {
+        if ((d.group && d.group == params.data[i+1].group) || !d.group && !params.data[i+1].group)
+        data_container.append("div")
+          .attr("class","d3plus_tooltip_data_seperator")
+          .style("background-color","#ddd")
+          .style("display","block")
+          .style("height","1px")
+          .style("margin","0px 3px")
+      }
+
+    })
+
+    data_container.selectAll(".d3plus_tooltip_data_name")
+      .style("width",function(){
+        var w = parseFloat(d3.select(this.parentNode).style("width"),10)
+        return (w-val_width-30)+"px"
+      })
+
+    data_container.selectAll(".d3plus_tooltip_data_value")
+      .style("width",val_width+"px")
+      .each(function(d){
+        var h = parseFloat(d3.select(this).style("height"),10)
+        val_heights[d.name] = h
+      })
+
+    data_container.selectAll(".d3plus_tooltip_data_name")
+      .style("min-height",function(d){
+        return val_heights[d.name]+"px"
+      })
+
+  }
+
+  if (params.html && !params.fullscreen) {
+    data_container.append("div")
+      .html(params.html)
+    if (params.js) {
+      params.js(container)
+    }
+  }
+
+  var footer = body.append("div")
+    .attr("class","d3plus_tooltip_footer")
+    .style("font-size","10px")
+    .style("position","relative")
+    .style("text-align","center")
+
+  if (params.footer) {
+    footer.html(params.footer)
+  }
+
+  params.height = tooltip.node().offsetHeight || tooltip.node().getBoundingClientRect().height
+
+  if (params.html && params.fullscreen) {
+    var h = params.height-12
+    var w = tooltip.node().offsetWidth-params.width-44
+    container.append("div")
+      .attr("class","d3plus_tooltip_html")
+      .style("width",w+"px")
+      .style("height",h+"px")
+      .style("display","inline-block")
+      .style("vertical-align","top")
+      .style("overflow-y","auto")
+      .style("padding","0px 12px")
+      .style("position","absolute")
+      .html(params.html)
+    if (params.js) {
+      params.js(container)
+    }
+  }
+
+  params.width = tooltip.node().offsetWidth
+
+  if (params.anchor.y != "center") params.height += params.arrow_offset
+  else params.width += params.arrow_offset
+
+  if (params.data || (!params.fullscreen && params.html)) {
+
+    if (!params.fullscreen) {
+      var limit = params.fixed ? parentHeight-params.y-10 : parentHeight-10
+      var h = params.height < limit ? params.height : limit
+    }
+    else {
+      var h = params.height
+    }
+    h -= parseFloat(container.style("padding-top"),10)
+    h -= parseFloat(container.style("padding-bottom"),10)
+    if (header) {
+      h -= header.node().offsetHeight || header.node().getBoundingClientRect().height
+      h -= parseFloat(header.style("padding-top"),10)
+      h -= parseFloat(header.style("padding-bottom"),10)
+    }
+    if (footer) {
+      h -= footer.node().offsetHeight || footer.node().getBoundingClientRect().height
+      h -= parseFloat(footer.style("padding-top"),10)
+      h -= parseFloat(footer.style("padding-bottom"),10)
+    }
+
+    data_container
+      .style("max-height",h+"px")
+  }
+
+  params.height = tooltip.node().offsetHeight || tooltip.node().getBoundingClientRect().height
+
+  move(params.x, params.y, params.id);
+
+}
+
+
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Function that closes ALL Descriptions
+//-------------------------------------------------------------------
+function close_descriptions() {
+  d3.selectAll("div.d3plus_tooltip_data_desc").style("height","0px");
+  d3.selectAll("div.d3plus_tooltip_data_help").style("background-color","#ccc");
+}
+
+},{"../client/pointer.coffee":40,"../client/prefix.coffee":41,"../client/rtl.coffee":42,"../color/legible.coffee":45,"../color/text.coffee":51,"../core/locale/languages/en_US.coffee":70,"../string/list.coffee":173,"./move.coffee":201,"./remove.coffee":202}],201:[function(require,module,exports){
+var arrowStyle;
+
+module.exports = function(x, y, id) {
+  var d, mins, tooltip;
+  if (!id) {
+    id = "default";
+  }
+  tooltip = d3.select("div#d3plus_tooltip_id_" + id);
+  if (tooltip.node()) {
+    d = tooltip.datum();
+    d.cx = x;
+    d.cy = y;
+    if (!d.fixed) {
+      if (d.parent.node().tagName.toLowerCase() === "body") {
+        mins = [window.scrollX, window.scrollY];
+      } else {
+        mins = [0, 0];
+      }
+      if (d.anchor.y !== "center") {
+        if (d.anchor.x === "right") {
+          d.x = d.cx - d.arrow_offset - 4;
+        } else if (d.anchor.x === "center") {
+          d.x = d.cx - d.width / 2;
+        } else {
+          if (d.anchor.x === "left") {
+            d.x = d.cx - d.width + d.arrow_offset + 2;
+          }
+        }
+        if (d.anchor.y === "bottom") {
+          d.flip = d.cy + d.height + d.offset <= d.limit[1];
+        } else {
+          if (d.anchor.y === "top") {
+            d.flip = d.cy - d.height - d.offset < mins[1];
+          }
+        }
+        if (d.flip) {
+          d.y = d.cy + d.offset + d.arrow_offset;
+        } else {
+          d.y = d.cy - d.height - d.offset - d.arrow_offset;
+        }
+      } else {
+        d.y = d.cy - d.height / 2;
+        if (d.anchor.x === "right") {
+          d.flip = d.cx + d.width + d.offset <= d.limit[0];
+        } else {
+          if (d.anchor.x === "left") {
+            d.flip = d.cx - d.width - d.offset < mins[0];
+          }
+        }
+        if (d.anchor.x === "center") {
+          d.flip = false;
+          d.x = d.cx - d.width / 2;
+        } else if (d.flip) {
+          d.x = d.cx + d.offset + d.arrow_offset;
+        } else {
+          d.x = d.cx - d.width - d.offset;
+        }
+      }
+      if (d.x < mins[0]) {
+        d.x = mins[0];
+      } else {
+        if (d.x + d.width > d.limit[0]) {
+          d.x = d.limit[0] - d.width;
+        }
+      }
+      if (d.y < mins[1]) {
+        d.y = mins[1];
+      } else {
+        if (d.y + d.height > d.limit[1]) {
+          d.y = d.limit[1] - d.height;
+        }
+      }
+    }
+    tooltip.style("top", d.y + "px").style("left", d.x + "px");
+    if (d.arrow) {
+      tooltip.selectAll(".d3plus_tooltip_arrow").call(arrowStyle);
+    }
+  }
+  return tooltip;
+};
+
+arrowStyle = function(arrow) {
+  return arrow.style("bottom", function(d) {
+    if (d.anchor.y !== "center" && !d.flip) {
+      return "-5px";
+    } else {
+      return "auto";
+    }
+  }).style("right", function(d) {
+    if (d.anchor.y === "center" && !d.flip) {
+      return "-5px";
+    } else {
+      return "auto";
+    }
+  }).style("top", function(d) {
+    if (d.anchor.y !== "center" && d.flip) {
+      return "-5px";
+    } else if (d.anchor.y === "center") {
+      return "50%";
+    } else {
+      return "auto";
+    }
+  }).style("left", function(d) {
+    if (d.anchor.y === "center" && d.flip) {
+      return "-5px";
+    } else if (d.anchor.y !== "center") {
+      return "50%";
+    } else {
+      return "auto";
+    }
+  }).style("margin-left", function(d) {
+    var arrow_x;
+    if (d.anchor.y === "center") {
+      return "auto";
+    } else {
+      if (d.anchor.x === "right") {
+        arrow_x = -d.width / 2 + d.arrow_offset / 2;
+      } else if (d.anchor.x === "left") {
+        arrow_x = d.width / 2 - d.arrow_offset * 2 - 5;
+      } else {
+        arrow_x = -5;
+      }
+      if (d.cx - d.width / 2 - 5 < arrow_x) {
+        arrow_x = d.cx - d.width / 2 - 5;
+        if (arrow_x < 2 - d.width / 2) {
+          arrow_x = 2 - d.width / 2;
+        }
+      } else if (-(d.limit[0] - d.cx - d.width / 2 + 5) > arrow_x) {
+        arrow_x = -(d.limit[0] - d.cx - d.width / 2 + 5);
+        if (arrow_x > d.width / 2 - 11) {
+          arrow_x = d.width / 2 - 11;
+        }
+      }
+      return arrow_x + "px";
+    }
+  }).style("margin-top", function(d) {
+    var arrow_y;
+    if (d.anchor.y !== "center") {
+      return "auto";
+    } else {
+      if (d.anchor.y === "bottom") {
+        arrow_y = -d.height / 2 + d.arrow_offset / 2 - 1;
+      } else if (d.anchor.y === "top") {
+        arrow_y = d.height / 2 - d.arrow_offset * 2 - 2;
+      } else {
+        arrow_y = -9;
+      }
+      if (d.cy - d.height / 2 - d.arrow_offset < arrow_y) {
+        arrow_y = d.cy - d.height / 2 - d.arrow_offset;
+        if (arrow_y < 4 - d.height / 2) {
+          arrow_y = 4 - d.height / 2;
+        }
+      } else if (-(d.limit[1] - d.cy - d.height / 2 + d.arrow_offset) > arrow_y) {
+        arrow_y = -(d.limit[1] - d.cy - d.height / 2 + d.arrow_offset);
+        if (arrow_y > d.height / 2 - 22) {
+          arrow_y = d.height / 2 - 22;
+        }
+      }
+      return arrow_y + "px";
+    }
+  });
+};
+
+
+},{}],202:[function(require,module,exports){
+module.exports = function(id) {
+  if (id) {
+    d3.selectAll("div#d3plus_tooltip_curtain_" + id).remove();
+    return d3.selectAll("div#d3plus_tooltip_id_" + id).remove();
+  } else {
+    d3.selectAll("div.d3plus_tooltip_curtain").remove();
+    return d3.selectAll("div.d3plus_tooltip").remove();
+  }
+};
+
+
+},{}],203:[function(require,module,exports){
+module.exports = function(arr, n) {
+  var buckets, step;
+  buckets = [];
+  step = 1 / (n - 1) * (arr[1] - arr[0]);
+  return d3.range(arr[0], arr[1] + step, step);
+};
+
+
+},{}],204:[function(require,module,exports){
+var d3selection;
+
+d3selection = require("./d3selection.coffee");
+
+module.exports = function(parent, child) {
+  var node;
+  if (!parent || !child) {
+    return false;
+  }
+  if (d3selection(parent)) {
+    parent = parent.node();
+  }
+  if (d3selection(parent)) {
+    child = child.node();
+  }
+  node = child.parentNode;
+  while (node !== null) {
+    if (node === parent) {
+      return true;
+    }
+    node = node.parentNode;
+  }
+  return false;
+};
+
+
+},{"./d3selection.coffee":207}],205:[function(require,module,exports){
+module.exports = function(arr, value) {
+  var closest;
+  closest = arr[0];
+  arr.forEach(function(p) {
+    if (Math.abs(value - p) < Math.abs(value - closest)) {
+      return closest = p;
+    }
+  });
+  return closest;
+};
+
+
+},{}],206:[function(require,module,exports){
+var copy, objectMerge, objectValidate;
+
+objectMerge = require("../object/merge.coffee");
+
+objectValidate = require("../object/validate.coffee");
+
+copy = function(variable) {
+  var ret;
+  if (objectValidate(variable)) {
+    return objectMerge(variable);
+  } else if (variable instanceof Array) {
+    ret = [];
+    variable.forEach(function(o) {
+      return ret.push(copy(o));
+    });
+    return ret;
+  } else {
+    return variable;
+  }
+};
+
+module.exports = copy;
+
+
+},{"../object/merge.coffee":170,"../object/validate.coffee":171}],207:[function(require,module,exports){
+var ie;
+
+ie = require("../client/ie.js");
+
+module.exports = function(elem) {
+  if (ie) {
+    return typeof elem === "object" && elem instanceof Array && "size" in elem && "select" in elem;
+  } else {
+    return elem instanceof d3.selection;
+  }
+};
+
+
+},{"../client/ie.js":39}],208:[function(require,module,exports){
+module.exports = function(url, callback) {
+  var img;
+  img = new Image();
+  img.src = url;
+  img.crossOrigin = "Anonymous";
+  img.onload = function() {
+    var canvas, context;
+    canvas = document.createElement("canvas");
+    canvas.width = this.width;
+    canvas.height = this.height;
+    context = canvas.getContext("2d");
+    context.drawImage(this, 0, 0);
+    callback.call(this, canvas.toDataURL("image/png"));
+    canvas = null;
+  };
+};
+
+
+},{}],209:[function(require,module,exports){
+var objectValidate, uniques;
+
+objectValidate = require("../object/validate.coffee");
+
+uniques = function(data, value, fetch, vars, depth) {
+  var check, d, i, j, k, len, len1, len2, len3, lookups, m, v, val, vals;
+  if (data === void 0) {
+    return [];
+  }
+  if (vars && depth === void 0) {
+    depth = vars.id.value;
+  }
+  if (!(data instanceof Array)) {
+    data = [data];
+  }
+  lookups = [];
+  if (value === void 0) {
+    return data.reduce(function(p, c) {
+      var lookup;
+      lookup = JSON.stringify(c);
+      if (lookups.indexOf(lookup) < 0) {
+        if (p.indexOf(c) < 0) {
+          p.push(c);
+        }
+        lookups.push(lookup);
+      }
+      return p;
+    }, []);
+  }
+  vals = [];
+  check = function(v) {
+    var l;
+    if (v !== void 0 && v !== null) {
+      l = JSON.stringify(v);
+      if (lookups.indexOf(l) < 0) {
+        vals.push(v);
+        return lookups.push(l);
+      }
+    }
+  };
+  if (typeof fetch === "function" && vars) {
+    for (i = 0, len = data.length; i < len; i++) {
+      d = data[i];
+      val = uniques(fetch(vars, d, value, depth));
+      for (j = 0, len1 = val.length; j < len1; j++) {
+        v = val[j];
+        check(v);
+      }
+    }
+  } else if (typeof value === "function") {
+    for (k = 0, len2 = data.length; k < len2; k++) {
+      d = data[k];
+      val = value(d);
+      check(val);
+    }
+  } else {
+    for (m = 0, len3 = data.length; m < len3; m++) {
+      d = data[m];
+      if (objectValidate(d)) {
+        val = d[value];
+        check(val);
+      }
+    }
+  }
+  return vals.sort(function(a, b) {
+    return a - b;
+  });
+};
+
+module.exports = uniques;
+
+
+},{"../object/validate.coffee":171}],210:[function(require,module,exports){
+module.exports = function(vars) {
+  var checkParent, i, len, ref, s;
+  vars.container.value.style("position", function() {
+    var current, remain;
+    current = d3.select(this).style("position");
+    remain = ["absolute", "fixed"].indexOf(current) >= 0;
+    if (remain) {
+      return current;
+    } else {
+      return "relative";
+    }
+  }).html("");
+  ref = ["width", "height"];
+  for (i = 0, len = ref.length; i < len; i++) {
+    s = ref[i];
+    if (!vars[s].value) {
+      checkParent = function(element) {
+        var elem, val;
+        if (element.tagName === void 0 || ["BODY", "HTML"].indexOf(element.tagName) >= 0) {
+          val = window["inner" + s.charAt(0).toUpperCase() + s.slice(1)];
+          elem = document !== element ? d3.select(element) : false;
+          if (elem) {
+            if (s === "width") {
+              val -= parseFloat(elem.style("margin-left"), 10);
+              val -= parseFloat(elem.style("margin-right"), 10);
+              val -= parseFloat(elem.style("padding-left"), 10);
+              val -= parseFloat(elem.style("padding-right"), 10);
+            } else {
+              val -= parseFloat(elem.style("margin-top"), 10);
+              val -= parseFloat(elem.style("margin-bottom"), 10);
+              val -= parseFloat(elem.style("padding-top"), 10);
+              val -= parseFloat(elem.style("padding-bottom"), 10);
+            }
+          }
+          return vars[s].value = val <= 20 ? vars[s].small : val;
+        } else {
+          val = parseFloat(d3.select(element).style(s), 10);
+          if (typeof val === "number" && val > 0) {
+            return vars[s].value = val;
+          } else if (element.tagName !== "BODY") {
+            return checkParent(element.parentNode);
+          }
+        }
+      };
+      checkParent(vars.container.value.node());
+      if (d3.selectAll("body > *:not(script)").size() === 1) {
+        d3.select("body").style("overflow", "hidden");
+      }
+    }
+  }
+  vars.container.value.style("width", vars.width.value + "px").style("height", vars.height.value + "px");
+};
+
+
+},{}],211:[function(require,module,exports){
+var dataFormat    = require("../../core/data/format.js"),
+    dataColor     = require("../../core/data/color.js"),
+    dataKeys      = require("../../core/data/keys.coffee"),
+    dataLoad      = require("../../core/data/load.coffee"),
+    drawDrawer    = require("./ui/drawer.js"),
+    drawLegend    = require("./ui/legend.js"),
+    drawTimeline  = require("./ui/timeline.coffee"),
+    errorCheck    = require("./errorCheck.js"),
+    fetchData     = require("../../core/fetch/data.js"),
+    finish        = require("./finish.js"),
+    focusTooltip  = require("./focus/tooltip.coffee"),
+    focusViz      = require("./focus/viz.js"),
+    history       = require("./ui/history.coffee"),
+    parseEdges    = require("../../core/parse/edges.js"),
+    parseNodes    = require("../../core/parse/nodes.js"),
+    print         = require("../../core/console/print.coffee"),
+    removeTooltip = require("../../tooltip/remove.coffee"),
+    runType       = require("./types/run.coffee"),
+    shapes        = require("./shapes/draw.js"),
+    stringFormat  = require("../../string/format.js"),
+    svgSetup      = require("./svg/enter.js"),
+    svgUpdate     = require("./svg/update.js"),
+    titles        = require("./ui/titles.js"),
+    validObject   = require("../../object/validate.coffee")
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Calculate steps needed to redraw the visualization
+//------------------------------------------------------------------------------
+module.exports = function(vars) {
+
+  var steps       = []
+    , appType     = vars.type.value
+    , locale      = vars.format.locale.value
+    , uiMessage   = locale.message.ui
+    , drawMessage = locale.message.draw
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Check to see if any data needs to be loaded with JSON
+  //----------------------------------------------------------------------------
+  var urlLoads = [ "data" , "attrs" , "coords" , "nodes" , "edges" ]
+  urlLoads.forEach(function(u){
+
+    if (!vars.error.value && !vars[u].loaded && vars[u].url) {
+
+      steps.push({
+        "function": function( vars , next ){
+          dataLoad( vars , u , next )
+        },
+        "message": locale.message.loading,
+        "wait": true
+      })
+
+    }
+
+  })
+
+  if (vars.draw.update) {
+
+    var appName     = locale.visualization[appType] || appType
+      , appSetup    = vars.types[appType].setup || false
+      , appReqs     = vars.types[appType].requirements || []
+      , appMessage  = stringFormat(locale.message.initializing,appName)
+      , dataMessage = locale.message.data
+
+    if (!(appReqs instanceof Array)) appReqs = [appReqs]
+    appName = appName.toLowerCase()
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // If it has one, run the current app's setup function.
+    //--------------------------------------------------------------------------
+    if (!vars.error.value && typeof appSetup === "function") {
+
+      steps.push({
+        "function": function( vars ) {
+
+          if ( vars.dev.value ) {
+            var timerString = "running " + appName + " setup"
+            print.time( timerString )
+          }
+
+          appSetup( vars )
+
+          if ( vars.dev.value ) print.timeEnd( timerString )
+
+        },
+        "message": appMessage
+      })
+
+    }
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Create SVG group elements if the container is new or has changed
+    //--------------------------------------------------------------------------
+    if (vars.container.changed) {
+
+      steps.push({ "function" : svgSetup , "message" : appMessage })
+
+    }
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Create group for current app, if it doesn't exist.
+    //--------------------------------------------------------------------------
+    if (!(appType in vars.g.apps)) {
+
+      steps.push({
+        "function": function( vars ) {
+
+          if ( vars.dev.value ) {
+            var timerString = "creating " + appName + " group"
+            print.time( timerString )
+          }
+
+          vars.g.apps[appType] = vars.g.app.append("g")
+            .attr("id", appType)
+            .attr("opacity", 0);
+
+          if ( vars.dev.value ) print.timeEnd( timerString )
+
+        },
+        "message": appMessage
+      })
+
+    }
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // If new data is detected, analyze and reset it.
+    //--------------------------------------------------------------------------
+    if (vars.data.changed) {
+
+      steps.push({
+        "function": function(vars) {
+          vars.data.cache = {}
+          delete vars.nodes.restricted
+          delete vars.edges.restricted
+          dataKeys(vars, "data")
+        },
+        "message": dataMessage
+      })
+
+    }
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // If new attributes are detected, analyze them.
+    //--------------------------------------------------------------------------
+    if (vars.attrs.changed) {
+
+      steps.push({
+        "function": function( vars ) {
+          dataKeys(vars, "attrs")
+        },
+        "message": dataMessage
+      })
+
+    }
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Determine color type
+    //--------------------------------------------------------------------------
+    steps.push({
+      "function": function(vars) {
+
+          if (!vars.color.type || vars.color.changed || vars.data.changed ||
+              vars.attrs.changed || vars.id.changed || vars.depth.changed ||
+              (vars.time.fixed.value &&
+                (vars.time.solo.changed || vars.time.mute.changed))) {
+
+            vars.color.valueScale = false;
+
+            if ( vars.dev.value ) {
+              var timerString = "checking color type";
+              print.time(timerString);
+            }
+
+            vars.color.type = false;
+
+            if (vars.color.value) {
+
+              var colorKey = vars.color.value;
+
+              if ( validObject(colorKey) ) {
+                if (colorKey[vars.id.value]) {
+                  colorKey = colorKey[vars.id.value];
+                }
+                else {
+                  colorKey = colorKey[d3.keys(colorKey)[0]];
+                }
+              }
+
+              if (vars.data.keys && colorKey in vars.data.keys) {
+                vars.color.type = vars.data.keys[colorKey];
+              }
+              else if (vars.attrs.keys && colorKey in vars.attrs.keys) {
+                vars.color.type = vars.attrs.keys[colorKey];
+              }
+
+            }
+            else if (vars.data.keys) {
+              vars.color.type = vars.data.keys[vars.id.value];
+            }
+
+            if (vars.dev.value) print.timeEnd(timerString);
+
+          }
+
+      },
+      "message": dataMessage
+    })
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Format nodes/edges if needed
+    //--------------------------------------------------------------------------
+    if ( appReqs.indexOf("edges") >= 0 && vars.edges.value
+    && ( !vars.edges.linked || vars.edges.changed ) ) {
+      steps.push({ "function" : parseEdges, "message" : dataMessage })
+    }
+
+    if ( appReqs.indexOf("nodes") >= 0 && vars.edges.value
+    && ( !vars.nodes.positions || vars.nodes.changed ) ) {
+      steps.push({ "function" : parseNodes , "message" : dataMessage })
+    }
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Groups data by time and nesting.
+    //--------------------------------------------------------------------------
+    if (vars.data.changed || vars.time.changed || vars.time.format.changed || vars.id.changed || (vars.x.scale.changed && [vars.x.scale.value, vars.x.scale.previous].indexOf("discrete") >= 0) || (vars.y.scale.changed && [vars.y.scale.value, vars.y.scale.previous].indexOf("discrete") >= 0)) {
+      steps.push({ "function" : dataFormat , "message" : dataMessage })
+    }
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Fetches data for app and "pool"
+    //--------------------------------------------------------------------------
+    if (!vars.error.value) {
+      steps.push({
+        "function": function(vars) {
+
+          var year = !vars.time.fixed.value ? ["all"] : null
+          if (vars.dev.value) {
+            var timerString = year ? "fetching pool data" : "fetching data"
+            print.time( timerString )
+          }
+          vars.data.pool = fetchData( vars , year )
+          if (vars.dev.value) print.timeEnd( timerString )
+          if ( !year ) {
+            vars.data.viz = vars.data.pool
+          }
+          else {
+            if ( vars.dev.value ) print.time("fetching data for current year")
+            vars.data.viz = fetchData( vars )
+            if ( vars.dev.value ) print.timeEnd("fetching data for current year")
+          }
+
+          vars.draw.timing = vars.data.viz.length < vars.data.large ?
+                             vars.timing.transitions : 0;
+
+        },
+        "message": dataMessage
+      })
+    }
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Calculate color scale if type is number
+    //--------------------------------------------------------------------------
+    if (!vars.error.value) {
+      steps.push({
+        "check": function(vars) {
+
+          return vars.color.value && vars.color.type === "number" &&
+                 vars.color.valueScale === false
+
+        },
+        "function": dataColor,
+        "message": dataMessage
+      })
+
+    }
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Remove any lingering tooltips.
+  //----------------------------------------------------------------------------
+  steps.push({
+    "function": function(vars) {
+      if ( vars.dev.value ) {
+        var str = vars.format.locale.value.message.tooltipReset
+        print.time(str)
+      }
+      if ( vars.type.previous && appType !== vars.type.previous ) {
+        removeTooltip(vars.type.previous)
+      }
+      removeTooltip(appType)
+      if ( vars.dev.value ) print.timeEnd(str)
+    },
+    "message": uiMessage
+  })
+
+  if (!vars.error.value) {
+    steps.push({"function": errorCheck, "message": uiMessage})
+  }
+
+  steps.push({
+    "function": function(vars) {
+
+      vars.margin.process()
+      titles(vars)
+
+      if (!vars.error.value) {
+        if (vars.draw.update) {
+
+          drawDrawer(vars)
+          drawTimeline(vars)
+          drawLegend(vars)
+
+        }
+        else {
+
+          if ( vars.dev.value ) print.time("calculating margins")
+
+          var drawer = vars.container.value.select("div#d3plus_drawer").node().offsetHeight
+                    || vars.container.value.select("div#d3plus_drawer").node().getBoundingClientRect().height
+
+          var timeline = vars.g.timeline.node().getBBox()
+          timeline = vars.timeline.value ? timeline.height+vars.ui.padding : 0
+
+          var legend = vars.g.legend.node().getBBox()
+          legend = vars.legend.value ? legend.height+vars.ui.padding : 0
+
+          vars.margin.bottom += drawer+timeline+legend
+
+          if ( vars.dev.value ) print.timeEnd("calculating margins")
+
+        }
+      }
+
+      history(vars)
+      vars.height.viz -= (vars.margin.top+vars.margin.bottom)
+      vars.width.viz -= (vars.margin.left+vars.margin.right)
+
+    },
+    "message": uiMessage
+  })
+
+  if (!vars.error.value) {
+    steps.push({
+      "function": focusTooltip,
+      "message": uiMessage
+    })
+  }
+
+  steps.push({
+    "function": svgUpdate,
+    "message": drawMessage
+  })
+
+  if (!vars.error.value && vars.draw.update) {
+    steps.push({
+      "function" : [ runType, shapes ],
+      "message"  : drawMessage
+    })
+  }
+
+  steps.push({
+    "function" : [ focusViz , finish ],
+    "message" : drawMessage
+  })
+
+  return steps
+
+}
+
+},{"../../core/console/print.coffee":53,"../../core/data/color.js":55,"../../core/data/format.js":57,"../../core/data/keys.coffee":59,"../../core/data/load.coffee":60,"../../core/fetch/data.js":65,"../../core/parse/edges.js":94,"../../core/parse/nodes.js":97,"../../object/validate.coffee":171,"../../string/format.js":172,"../../tooltip/remove.coffee":202,"./errorCheck.js":212,"./finish.js":213,"./focus/tooltip.coffee":214,"./focus/viz.js":215,"./shapes/draw.js":224,"./svg/enter.js":235,"./svg/update.js":236,"./types/run.coffee":239,"./ui/drawer.js":240,"./ui/history.coffee":241,"./ui/legend.js":242,"./ui/timeline.coffee":244,"./ui/titles.js":245}],212:[function(require,module,exports){
+var fetchText    = require("../../core/fetch/text.js"),
+    print        = require("../../core/console/print.coffee"),
+    rejected     = require("../../core/methods/rejected.coffee"),
+    stringFormat = require("../../string/format.js"),
+    stringList   = require("../../string/list.coffee")
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Miscellaneous Error Checks
+//------------------------------------------------------------------------------
+module.exports = function(vars) {
+
+  if ( vars.dev.value ) print.time("checking for errors")
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Check to see if we have all required variables set
+  //----------------------------------------------------------------------------
+  var reqs = ["id"]
+    , app_reqs = vars.types[vars.type.value].requirements
+  if (app_reqs) {
+    if (!(app_reqs instanceof Array)) reqs.push(app_reqs)
+    else reqs = reqs.concat(vars.types[vars.type.value].requirements)
+  }
+
+  var missing = []
+  reqs.forEach(function(r){
+    if (typeof r === "string") {
+      if (!vars[r].value) missing.push("\""+r+"\"")
+    }
+    else if (typeof r === "function") {
+      var reqReturn = r(vars)
+      if (!reqReturn.status && reqReturn.text) {
+        missing.push("\""+reqReturn.text+"\"")
+      }
+    }
+  })
+
+  if ( missing.length > 1 ) {
+    var str = vars.format.locale.value.error.methods
+      , app = vars.format.locale.value.visualization[vars.type.value] || vars.type.value
+      , and = vars.format.locale.value.ui.and
+    missing = stringList(missing,and)
+    vars.error.internal = stringFormat(str,app,missing)
+  }
+  else if ( missing.length === 1 ) {
+    var str = vars.format.locale.value.error.method
+      , app = vars.format.locale.value.visualization[vars.type.value] || vars.type.value
+    vars.error.internal = stringFormat(str,app,missing[0])
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Check to see if we have focus connections, if needed
+  //----------------------------------------------------------------------------
+  if (!vars.error.internal && reqs.indexOf("edges") >= 0 && reqs.indexOf("focus") >= 0) {
+    var connections = vars.edges.connections(vars.focus.value[0],vars.id.value)
+    if (connections.length == 0) {
+      var name = fetchText(vars,vars.focus.value[0],vars.depth.value)
+        , str = vars.format.locale.value.error.connections
+      vars.error.internal = stringFormat(str,"\""+name+"\"")
+    }
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Check to see if we have all required libraries
+  //----------------------------------------------------------------------------
+  var reqs = ["d3"]
+  if (vars.types[vars.type.value].libs) {
+    reqs = reqs.concat(vars.types[vars.type.value].libs)
+  }
+  var missing = []
+  reqs.forEach(function(r){
+    if (!window[r]) missing.push("\""+r+"\"")
+  })
+
+  if ( missing.length > 1 ) {
+    var str = vars.format.locale.value.error.libs
+      , app = vars.format.locale.value.visualization[vars.type.value]
+      , and = vars.format.locale.value.ui.and
+    missing = stringList(missing,and)
+    vars.error.internal = stringFormat(str,app,missing)
+  }
+  else if ( missing.length === 1 ) {
+    var str = vars.format.locale.value.error.lib
+      , app = vars.format.locale.value.visualization[vars.type.value]
+    vars.error.internal = stringFormat(str,app,missing[0])
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Check to see if the requested app supports the set shape
+  //----------------------------------------------------------------------------
+  var shapes = vars.shape.accepted(vars);
+  if (!(shapes instanceof Array)) shapes = [shapes]
+  var shape = vars.shape.value;
+
+  if (!shape || rejected(vars, shapes, shape, "shape")) {
+    vars.self.shape(shapes[0]);
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Check to see if the requested app supports the set "mode"
+  //----------------------------------------------------------------------------
+  if ("modes" in vars.types[vars.type.value]) {
+
+    var modes = vars.types[vars.type.value].modes
+    if (!(modes instanceof Array)) modes = [modes]
+    var mode = vars.type.mode.value
+
+    if (!mode || rejected(vars, modes, mode, "mode")) {
+      vars.self.type({"mode": modes[0]})
+    }
+
+  }
+
+  if ( vars.dev.value ) print.timeEnd("checking for errors")
+
+}
+
+},{"../../core/console/print.coffee":53,"../../core/fetch/text.js":67,"../../core/methods/rejected.coffee":90,"../../string/format.js":172,"../../string/list.coffee":173}],213:[function(require,module,exports){
+var edges = require("./shapes/edges.js"),
+    flash       = require("./ui/message.js"),
+    methodReset = require("../../core/methods/reset.coffee"),
+    print       = require("../../core/console/print.coffee"),
+    shapeLabels = require("./shapes/labels.js"),
+    titleCase   = require("../../string/title.coffee")
+
+var bounds = require("./zoom/bounds.coffee")
+var labels = require("./zoom/labels.coffee")
+var mouse  = require("./zoom/mouse.coffee")
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Finalize Visualization
+//------------------------------------------------------------------------------
+module.exports = function(vars) {
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Zoom to fit bounds, if applicable
+  //----------------------------------------------------------------------------
+  if (!vars.error.value) {
+
+    var zoom = vars.zoom.viewport || vars.zoom.bounds
+    if (vars.types[vars.type.value].zoom && vars.zoom.value && zoom) {
+
+      if ( vars.dev.value ) print.time("calculating zoom")
+
+      if (vars.draw.first || vars.zoom.reset) {
+        bounds(vars, zoom, 0);
+      }
+      else if (vars.type.changed || vars.focus.changed || vars.height.changed || vars.width.changed || vars.nodes.changed || vars.legend.changed || vars.timeline.changed || vars.ui.changed) {
+        bounds(vars, zoom);
+      }
+
+      if ( vars.dev.value ) print.timeEnd("calculating zoom")
+
+    }
+    else {
+      vars.zoom.bounds = [[0,0],[vars.width.viz,vars.height.viz]]
+      vars.zoom.scale = 1
+      bounds(vars)
+    }
+
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Resize/Reposition Overlay Rect for Mouse events
+  //----------------------------------------------------------------------------
+  var w = vars.zoom.size ? vars.zoom.size.width : vars.width.viz,
+      h = vars.zoom.size ? vars.zoom.size.height : vars.height.viz,
+      x = vars.zoom.bounds ? vars.zoom.bounds[0][0] : 0,
+      y = vars.zoom.bounds ? vars.zoom.bounds[0][1] : 0
+
+  vars.g.overlay
+    .attr("width",w)
+    .attr("height",h)
+    .attr("x",x)
+    .attr("y",y)
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Create labels
+  //----------------------------------------------------------------------------
+  if (!vars.error.value) {
+    if (vars.draw.update) {
+      edges(vars)
+      // if (vars.draw.timing || (!vars.types[vars.type.value].zoom && !vars.draw.timing)) {
+      shapeLabels( vars , "data" )
+      if (vars.edges.label) {
+        setTimeout(function(){
+          shapeLabels( vars , "edges" )
+        }, vars.draw.timing+200)
+      }
+      // }
+    }
+    else if (vars.types[vars.type.value].zoom && vars.zoom.value && vars.draw.timing) {
+      setTimeout(function(){
+        labels(vars)
+      },vars.draw.timing)
+    }
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Check for Errors
+  //----------------------------------------------------------------------------
+  if (!vars.error.value) {
+    var reqs = vars.types[vars.type.value].requirements || []
+    if (!(reqs instanceof Array)) reqs = [reqs]
+    var data_req = reqs.indexOf("data") >= 0
+    if (!vars.error.internal) {
+      if ((!vars.data.viz || !vars.returned.nodes.length) && data_req) {
+        vars.error.internal = vars.format.locale.value.error.data
+      }
+    }
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Hide the previous app, if applicable
+  //----------------------------------------------------------------------------
+  var prev = vars.type.previous
+  if (prev && vars.type.value != prev && vars.g.apps[prev]) {
+    if ( vars.dev.value ) print.time("hiding \"" + prev + "\"")
+    if (vars.draw.timing) {
+      vars.g.apps[prev].transition().duration(vars.draw.timing)
+        .attr("opacity",0)
+    }
+    else {
+      vars.g.apps[prev].attr("opacity",0)
+    }
+    if ( vars.dev.value ) print.timeEnd()
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Show the current app, data, and edges groups
+  //----------------------------------------------------------------------------
+  if (!vars.error.value) {
+    var new_opacity = (data_req && vars.data.viz.length === 0) ||
+                       vars.error.internal || vars.error.value ? 0 : vars.focus.value.length &&
+                       vars.types[vars.type.value].zoom && vars.zoom.value ?
+                       1 - vars.tooltip.curtain.opacity : 1;
+
+    var timing = vars.draw.timing;
+
+    vars.group.transition().duration(timing)
+      .attr("opacity",new_opacity);
+
+    vars.g.data.transition().duration(timing)
+      .attr("opacity",new_opacity);
+
+    vars.g.edges.transition().duration(timing)
+      .attr("opacity",new_opacity);
+
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Display and reset internal_error, if applicable
+  //----------------------------------------------------------------------------
+  if (vars.error.value) {
+    flash(vars, vars.error.value);
+  }
+  else if (vars.error.internal) {
+    vars.error.internal = titleCase(vars.error.internal);
+    print.warning(vars.error.internal);
+    flash(vars, vars.error.internal);
+    vars.error.internal = null;
+  }
+  else {
+    flash(vars);
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Unfreeze controls and apply zoom behavior, if applicable
+  //----------------------------------------------------------------------------
+  setTimeout(function(){
+
+    methodReset( vars )
+
+    if (vars.types[vars.type.value].zoom && vars.zoom.value) {
+      vars.g.zoom
+        .datum(vars)
+        .call(vars.zoom.behavior.on("zoom",mouse))
+      if (!vars.zoom.scroll.value) {
+        vars.g.zoom
+          .on("mousewheel.zoom",null)
+          .on("MozMousePixelScroll.zoom",null)
+          .on("wheel.zoom",null)
+      }
+      if (!vars.zoom.click.value) {
+        vars.g.zoom.on("dblclick.zoom",null)
+      }
+      if (!vars.zoom.pan.value) {
+        vars.g.zoom
+          .on("mousedown.zoom",null)
+          .on("mousemove.zoom",null)
+      }
+    }
+    else {
+      vars.g.zoom
+        .call(vars.zoom.behavior.on("zoom",null))
+        .on("dblclick.zoom",null)
+        .on("mousedown.zoom",null)
+        .on("mousemove.zoom",null)
+        .on("mousewheel.zoom",null)
+        .on("MozMousePixelScroll.zoom",null)
+        .on("touchstart.zoom",null)
+        .on("wheel.zoom",null)
+    }
+
+  },vars.draw.timing)
+
+}
+
+},{"../../core/console/print.coffee":53,"../../core/methods/reset.coffee":92,"../../string/title.coffee":175,"./shapes/edges.js":225,"./shapes/labels.js":227,"./ui/message.js":243,"./zoom/bounds.coffee":246,"./zoom/labels.coffee":248,"./zoom/mouse.coffee":249}],214:[function(require,module,exports){
+var createTooltip, fetchValue, print, removeTooltip;
+
+createTooltip = require("../tooltip/create.js");
+
+fetchValue = require("../../../core/fetch/value.coffee");
+
+print = require("../../../core/console/print.coffee");
+
+removeTooltip = require("../../../tooltip/remove.coffee");
+
+module.exports = function(vars) {
+  var data, focus, offset;
+  focus = vars.focus;
+  if (!vars.error.internal && focus.value.length === 1 && focus.value.length && !vars.small && focus.tooltip.value) {
+    if (vars.dev.value) {
+      print.time("drawing focus tooltip");
+    }
+    data = vars.data.pool.filter(function(d) {
+      return fetchValue(vars, d, vars.id.value) === focus.value[0];
+    });
+    if (data.length >= 1) {
+      data = data[0];
+    } else {
+      data = {};
+      data[vars.id.value] = focus.value[0];
+    }
+    offset = vars.labels.padding;
+    createTooltip({
+      anchor: "top left",
+      arrow: false,
+      data: data,
+      fullscreen: false,
+      id: "visualization_focus",
+      length: "long",
+      maxheight: vars.height.viz - offset * 2,
+      mouseevents: true,
+      offset: 0,
+      vars: vars,
+      width: vars.tooltip.large,
+      x: vars.width.value - vars.margin.right - offset,
+      y: vars.margin.top + offset
+    });
+    vars.width.viz -= vars.tooltip.large + offset * 2;
+    if (vars.dev.value) {
+      print.timeEnd("drawing focus tooltip");
+    }
+  } else {
+    removeTooltip("visualization_focus");
+  }
+};
+
+
+},{"../../../core/console/print.coffee":53,"../../../core/fetch/value.coffee":68,"../../../tooltip/remove.coffee":202,"../tooltip/create.js":237}],215:[function(require,module,exports){
+var events = require("../../../client/pointer.coffee"),
+    ie           = require("../../../client/ie.js"),
+    fetchValue   = require("../../../core/fetch/value.coffee"),
+    print        = require("../../../core/console/print.coffee"),
+    uniqueValues = require("../../../util/uniques.coffee")
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Creates focus elements, if available
+//------------------------------------------------------------------------------
+module.exports = function(vars) {
+
+  vars.g.edge_focus
+    .selectAll("g")
+    .remove()
+
+  vars.g.data_focus
+    .selectAll("g")
+    .remove()
+
+  if (vars.focus.value.length && vars.types[vars.type.value].zoom && vars.zoom.value) {
+
+    if ( vars.dev.value ) print.time("drawing focus elements")
+
+    var edges = vars.g.edges.selectAll("g")
+
+    if (edges.size() > 0) {
+
+      edges.each(function(l){
+
+          var source = l[vars.edges.source][vars.id.value],
+              target = l[vars.edges.target][vars.id.value]
+
+          if (source == vars.focus.value[0] || target == vars.focus.value[0]) {
+            var elem = vars.g.edge_focus.node().appendChild(this.cloneNode(true))
+            d3.select(elem).datum(l).attr("opacity",1)
+              .selectAll("line, path").datum(l)
+          }
+
+        })
+
+
+      var marker = vars.edges.arrows.value
+
+      vars.g.edge_focus.selectAll("line, path")
+        .attr("vector-effect","non-scaling-stroke")
+        .style("stroke",vars.color.focus)
+        .style("stroke-width",function(){
+          if (ie && vars.types[vars.type.value].zoom) return 0;
+          return vars.edges.size.value ? d3.select(this).style("stroke-width")
+               : vars.data.stroke.width*2
+        })
+        .attr("marker-start",function(e){
+
+          var direction = vars.edges.arrows.direction.value
+
+          if ("bucket" in e.d3plus) {
+            var d = "_"+e.d3plus.bucket
+          }
+          else {
+            var d = ""
+          }
+
+          return direction == "source" && marker
+               ? "url(#d3plus_edge_marker_focus"+d+")" : "none"
+
+        })
+        .attr("marker-end",function(e){
+
+          var direction = vars.edges.arrows.direction.value
+
+          if ("bucket" in e.d3plus) {
+            var d = "_"+e.d3plus.bucket
+          }
+          else {
+            var d = ""
+          }
+
+          return direction == "target" && marker
+               ? "url(#d3plus_edge_marker_focus"+d+")" : "none"
+
+        })
+
+      vars.g.edge_focus.selectAll("text")
+        .style("fill",vars.color.focus)
+
+    }
+
+    var focii = uniqueValues(vars.edges.connections(vars.focus.value[0],vars.id.value,true),vars.id.value, fetchValue, vars)
+    focii.push(vars.focus.value[0])
+
+    var x_bounds = [], y_bounds = [], x_buffer = [0], y_buffer = [0]
+
+    var groups = vars.g.data.selectAll("g")
+      .each(function(d){
+        if (focii.indexOf(d[vars.id.value]) >= 0) {
+          var elem = vars.g.data_focus.node().appendChild(this.cloneNode(true))
+          var elem = d3.select(elem).datum(d).attr("opacity",1)
+
+          if (vars.shape.value == "coordinates") {
+
+            vars.zoom.viewport = vars.path.bounds(vars.zoom.coords[d.d3plus.id])
+
+          }
+          else if ("d3plus" in d) {
+            if ("x" in d.d3plus) {
+              x_bounds.push(d.d3plus.x)
+            }
+            if ("y" in d.d3plus) {
+              y_bounds.push(d.d3plus.y)
+            }
+            if ("r" in d.d3plus) {
+              x_buffer.push(d.d3plus.r)
+              y_buffer.push(d.d3plus.r)
+            }
+            else {
+              if ("width" in d.d3plus) {
+                x_buffer.push(d.d3plus.width/2)
+              }
+              if ("height" in d.d3plus) {
+                y_buffer.push(d.d3plus.height/2)
+              }
+            }
+          }
+
+          for (e in events) {
+            var evt = d3.select(this).on(events[e])
+            if (evt) {
+              elem.on(events[e],evt)
+            }
+          }
+
+        }
+      })
+
+    if (x_bounds.length && y_bounds.length) {
+
+      var xcoords = d3.extent(x_bounds),
+          ycoords = d3.extent(y_bounds),
+          xmax = d3.max(x_buffer),
+          ymax = d3.max(y_buffer)
+
+      vars.zoom.viewport = [
+        [xcoords[0]-xmax,ycoords[0]-ymax],
+        [xcoords[1]+xmax,ycoords[1]+ymax]
+      ]
+
+    }
+
+    vars.g.data_focus.selectAll("path")
+      .style("stroke-width", ie && vars.types[vars.type.value].zoom ?
+                             0 : vars.data.stroke.width * 2);
+
+    if ( vars.dev.value ) print.timeEnd("drawing focus elements")
+
+  }
+  else {
+    vars.zoom.viewport = false
+  }
+
+}
+
+},{"../../../client/ie.js":39,"../../../client/pointer.coffee":40,"../../../core/console/print.coffee":53,"../../../core/fetch/value.coffee":68,"../../../util/uniques.coffee":209}],216:[function(require,module,exports){
+var angles, largestRect, path2poly, shapeStyle;
+
+shapeStyle = require("./style.coffee");
+
+largestRect = require("../../../geom/largestRect.coffee");
+
+path2poly = require("../../../geom/path2poly.coffee");
+
+angles = {
+  start: {},
+  end: {}
+};
+
+module.exports = function(vars, selection, enter, exit) {
+  var arc, arcTween, data, newarc;
+  arc = d3.svg.arc().innerRadius(0).outerRadius(function(d) {
+    return d.d3plus.r;
+  }).startAngle(function(d) {
+    return d.d3plus.startAngle;
+  }).endAngle(function(d) {
+    return d.d3plus.endAngle;
+  });
+  data = function(d) {
+    var poly, rect;
+    if (vars.labels.value) {
+      if (d.d3plus.label) {
+        d.d3plus_label = d.d3plus.label;
+      } else {
+        poly = path2poly(arc(d));
+        rect = largestRect(poly, {
+          angle: 0
+        });
+        if (rect[0]) {
+          d.d3plus_label = {
+            w: rect[0].width,
+            h: rect[0].height,
+            x: rect[0].cx,
+            y: rect[0].cy
+          };
+        } else {
+          delete d.d3plus_label;
+        }
+      }
+    }
+    return [d];
+  };
+  if (vars.draw.timing) {
+    newarc = d3.svg.arc().innerRadius(0).outerRadius(function(d) {
+      return d.d3plus.r;
+    }).startAngle(function(d) {
+      if (angles.start[d.d3plus.id] === void 0) {
+        angles.start[d.d3plus.id] = 0;
+      }
+      if (isNaN(angles.start[d.d3plus.id])) {
+        angles.start[d.d3plus.id] = d.d3plus.startAngle;
+      }
+      return angles.start[d.d3plus.id];
+    }).endAngle(function(d) {
+      if (angles.end[d.d3plus.id] === void 0) {
+        angles.end[d.d3plus.id] = 0;
+      }
+      if (isNaN(angles.end[d.d3plus.id])) {
+        angles.end[d.d3plus.id] = d.d3plus.endAngle;
+      }
+      return angles.end[d.d3plus.id];
+    });
+    arcTween = function(arcs, newAngle) {
+      return arcs.attrTween("d", function(d) {
+        var e, interpolateE, interpolateS, s;
+        if (newAngle === void 0) {
+          s = d.d3plus.startAngle;
+          e = d.d3plus.endAngle;
+        } else if (newAngle === 0) {
+          s = 0;
+          e = 0;
+        }
+        interpolateS = d3.interpolate(angles.start[d.d3plus.id], s);
+        interpolateE = d3.interpolate(angles.end[d.d3plus.id], e);
+        return function(t) {
+          angles.start[d.d3plus.id] = interpolateS(t);
+          angles.end[d.d3plus.id] = interpolateE(t);
+          return newarc(d);
+        };
+      });
+    };
+    enter.append("path").attr("class", "d3plus_data").call(shapeStyle, vars).attr("d", newarc);
+    selection.selectAll("path.d3plus_data").data(data).transition().duration(vars.draw.timing).call(shapeStyle, vars).call(arcTween);
+    exit.selectAll("path.d3plus_data").transition().duration(vars.draw.timing).call(arcTween, 0);
+  } else {
+    enter.append("path").attr("class", "d3plus_data");
+    selection.selectAll("path.d3plus_data").data(data).call(shapeStyle, vars).attr("d", arc);
+  }
+};
+
+
+},{"../../../geom/largestRect.coffee":159,"../../../geom/path2poly.coffee":161,"./style.coffee":231}],217:[function(require,module,exports){
+var fetchText = require("../../../core/fetch/text.js"),
+    fontSizes   = require("../../../font/sizes.coffee"),
+    largestRect = require("../../../geom/largestRect.coffee"),
+    shapeStyle  = require("./style.coffee");
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Draws "square" and "circle" shapes using svg:rect
+//------------------------------------------------------------------------------
+module.exports = function(vars, selection, enter, exit) {
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // D3 area definition
+  //----------------------------------------------------------------------------
+  var area = d3.svg.area()
+    .x(function(d) { return d.d3plus.x; })
+    .y0(function(d) { return d.d3plus.y0; })
+    .y1(function(d) { return d.d3plus.y; })
+    .interpolate(vars.shape.interpolate.value);
+
+  var startArea = d3.svg.area()
+    .x(function(d) { return d.d3plus.x; })
+    .y0(function(d) { return d.d3plus.y0; })
+    .y1(function(d) { return d.d3plus.y0; })
+    .interpolate(vars.shape.interpolate.value);
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // "paths" Enter
+  //----------------------------------------------------------------------------
+  enter.append("path").attr("class","d3plus_data")
+    .attr("d",function(d){ return startArea(d.values); })
+    .call(shapeStyle,vars);
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // "paths" Update
+  //----------------------------------------------------------------------------
+
+  var style = {
+    "font-weight": vars.labels.font.weight,
+    "font-family": vars.labels.font.family.value
+  };
+
+  selection.selectAll("path.d3plus_data")
+    .data(function(d) {
+
+      if (vars.labels.value && d.values.length > 1) {
+
+        var max = d3.max(d.values, function(v){
+          return v.d3plus.y0 - v.d3plus.y;
+        }), lr = false;
+
+        if (max > vars.labels.font.size) {
+
+          var tops = [], bottoms = [], names = fetchText(vars, d);
+
+          d.values.forEach(function(v){
+            tops.push([v.d3plus.x,v.d3plus.y]);
+            bottoms.push([v.d3plus.x,v.d3plus.y0]);
+          });
+          tops = tops.concat(bottoms.reverse());
+
+          var ratio = null;
+          if (names.length) {
+            var size = fontSizes(names[0],style);
+            ratio = size[0].width/size[0].height;
+          }
+
+          lr = largestRect(tops,{
+            "angle": d3.range(-70, 71, 1),
+            "aspectRatio": ratio,
+            "tolerance": 0
+          });
+
+        }
+
+        if (lr && lr[0]) {
+
+          var label = {
+            "w": ~~(lr[0].width),
+            "h": ~~(lr[0].height),
+            "x": ~~(lr[0].cx),
+            "y": ~~(lr[0].cy),
+            "angle": lr[0].angle*-1,
+            "padding": 2,
+            "names": names
+          }
+
+          if (lr[0].angle !== 0) {
+            label.translate = {
+              "x":label.x,
+              "y":label.y
+            }
+          }
+          else {
+            label.translate = false
+          }
+
+          if (label.w >= 10 && label.h >= 10) {
+            d.d3plus_label = label
+          }
+
+        }
+
+      }
+
+      return [d];
+    })
+
+  if (vars.draw.timing) {
+    selection.selectAll("path.d3plus_data")
+      .transition().duration(vars.draw.timing)
+        .attr("d",function(d){ return area(d.values) })
+        .call(shapeStyle,vars)
+  }
+  else {
+    selection.selectAll("path.d3plus_data")
+      .attr("d",function(d){ return area(d.values) })
+      .call(shapeStyle,vars)
+  }
+
+}
+
+},{"../../../core/fetch/text.js":67,"../../../font/sizes.coffee":101,"../../../geom/largestRect.coffee":159,"./style.coffee":231}],218:[function(require,module,exports){
+var fetchText = require("../../../core/fetch/text.js"),
+    largestRect = require("../../../geom/largestRect.coffee"),
+    shapeStyle  = require("./style.coffee")
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Draws "square" and "circle" shapes using svg:rect
+//------------------------------------------------------------------------------
+module.exports = function(vars,selection,enter,exit) {
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Initialize check scale on enter and exit.
+  //----------------------------------------------------------------------------
+  function init(paths){
+    paths.attr("transform", "scale(1)")
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Change scale of check on update.
+  //---------------------------------------------------------------------------
+  function update(paths){
+    paths.attr("transform", function(d){
+      var smaller_dim = Math.min(d.d3plus.width, d.d3plus.height);
+      var scale = Math.floor(smaller_dim / 16);
+      return "scale("+scale+")";
+    })
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // "paths" Enter
+  //----------------------------------------------------------------------------
+  enter.append("path").attr("class","d3plus_data")
+    .attr("d", "M5-6.844L3.594-5.407L-2,0.188l-1.594-1.594L-5-2.844L-7.844,0l1.438,1.406l3,3L-2,5.843l1.406-1.438l7-7L7.844-4L5-6.844z")
+    .call(init)
+    .call(shapeStyle,vars)
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // "paths" Update
+  //----------------------------------------------------------------------------
+  selection.selectAll("path.d3plus_data")
+    .data(function(d) {
+      return [d];
+    })
+
+  if (vars.draw.timing) {
+    selection.selectAll("path.d3plus_data")
+      .transition().duration(vars.draw.timing)
+        .call(update)
+        .call(shapeStyle,vars)
+  }
+  else {
+    selection.selectAll("path.d3plus_data")
+      .call(update)
+      .call(shapeStyle,vars)
+  }
+
+}
+
+},{"../../../core/fetch/text.js":67,"../../../geom/largestRect.coffee":159,"./style.coffee":231}],219:[function(require,module,exports){
+var fetchColor, fetchValue, lighter, segments;
+
+fetchValue = require("../../../core/fetch/value.coffee");
+
+fetchColor = require("../../../core/fetch/color.coffee");
+
+lighter = require("../../../color/lighter.coffee");
+
+segments = require("./segments.coffee");
+
+module.exports = function(d, vars, stroke) {
+  var active, shape, temp, total;
+  shape = d.d3plus.shape || vars.shape.value;
+  if (vars.shape.value === "line" && shape !== "circle") {
+    return "none";
+  } else if (vars.shape.value === "area" || shape === "active" || vars.shape.value === "line") {
+    return fetchColor(vars, d);
+  } else if (shape === "temp") {
+    if (stroke) {
+      return fetchColor(vars, d);
+    } else {
+      return "url(#d3plus_hatch_" + d.d3plus.id + ")";
+    }
+  } else if (d.d3plus["static"]) {
+    return lighter(fetchColor(vars, d), .75);
+  }
+  active = segments(vars, d, "active");
+  temp = segments(vars, d, "temp");
+  total = segments(vars, d, "total");
+  if ((!vars.active.value && !vars.temp.value) || active === true || (active && total && active >= total && !temp) || (active && !total)) {
+    return fetchColor(vars, d);
+  } else if (vars.active.spotlight.value) {
+    return "#eee";
+  } else {
+    return lighter(fetchColor(vars, d), .75);
+  }
+};
+
+
+},{"../../../color/lighter.coffee":46,"../../../core/fetch/color.coffee":64,"../../../core/fetch/value.coffee":68,"./segments.coffee":230}],220:[function(require,module,exports){
+var copy, distance, fetchText, fontSizes, labels, largestRect, path2poly, shapeStyle;
+
+copy = require("../../../util/copy.coffee");
+
+distance = require("../../../network/distance.coffee");
+
+fetchText = require("../../../core/fetch/text.js");
+
+fontSizes = require("../../../font/sizes.coffee");
+
+largestRect = require("../../../geom/largestRect.coffee");
+
+path2poly = require("../../../geom/path2poly.coffee");
+
+shapeStyle = require("./style.coffee");
+
+labels = {};
+
+module.exports = function(vars, selection, enter, exit) {
+  var projection, size_change;
+  projection = d3.geo[vars.coords.projection.value]().center(vars.coords.center);
+  if (!vars.zoom.scale) {
+    vars.zoom.scale = 1;
+  }
+  vars.zoom.area = 1 / vars.zoom.scale / vars.zoom.scale;
+  vars.path = d3.geo.path().projection(projection);
+  enter.append("path").attr("id", function(d) {
+    return d.id;
+  }).attr("class", "d3plus_data").attr("d", vars.path).call(shapeStyle, vars);
+  if (vars.draw.timing) {
+    selection.selectAll("path.d3plus_data").transition().duration(vars.draw.timing).call(shapeStyle, vars);
+  } else {
+    selection.selectAll("path.d3plus_data").call(shapeStyle, vars);
+  }
+  size_change = vars.old_height !== vars.height.viz || vars.height.changed || vars.old_width !== vars.width.viz || vars.width.changed;
+  vars.old_height = vars.height.viz;
+  vars.old_width = vars.width.viz;
+  if (vars.coords.changed || size_change || vars.coords.mute.changed || vars.coords.solo.changed || vars.type.changed) {
+    vars.zoom.bounds = null;
+    vars.zoom.reset = true;
+    vars.zoom.coords = {};
+    return selection.each(function(d) {
+      var areaM, areas, b, c, center, coords, dist_cutoff, dist_values, distances, i, j, largest, len, names, path, ratio, rect, reduced, ref, size, style, test;
+      if (d.geometry.coordinates.length > 1) {
+        distances = [];
+        areas = [];
+        areaM = 0;
+        test = copy(d);
+        largest = copy(d);
+        d.geometry.coordinates = d.geometry.coordinates.filter(function(c, i) {
+          var a;
+          test.geometry.coordinates = [c];
+          a = vars.path.area(test);
+          if (a > 0) {
+            areas.push(a);
+            if (a > areaM) {
+              largest.geometry.coordinates = [c];
+              areaM = a;
+            }
+            return true;
+          } else {
+            return false;
+          }
+        });
+        center = vars.path.centroid(largest);
+        reduced = copy(d);
+        ref = d.geometry.coordinates;
+        for (i = j = 0, len = ref.length; j < len; i = ++j) {
+          c = ref[i];
+          test.geometry.coordinates = [c];
+          distances.push(distance(vars.path.centroid(test), center));
+        }
+        dist_values = distances.reduce(function(arr, dist, i) {
+          if (dist) {
+            arr.push(areas[i] / dist);
+          }
+          return arr;
+        }, []);
+        dist_cutoff = d3.quantile(dist_values, vars.coords.threshold.value);
+        reduced.geometry.coordinates = reduced.geometry.coordinates.filter(function(c, i) {
+          var a, dist;
+          dist = distances[i];
+          a = areas[i];
+          return dist === 0 || a / dist >= dist_cutoff;
+        });
+        coords = largest.geometry.coordinates[0];
+        if (coords && largest.geometry.type === "MultiPolygon") {
+          coords = coords[0];
+          largest.geometry.coordinates[0] = coords;
+          largest.geometry.type = "Polygon";
+        }
+      } else {
+        reduced = d;
+        largest = d;
+        coords = d.geometry.coordinates[0];
+      }
+      vars.zoom.coords[d.d3plus.id] = reduced;
+      b = vars.path.bounds(reduced);
+      names = fetchText(vars, d);
+      delete d.d3plus_label;
+      if (coords && names.length) {
+        path = path2poly(vars.path(largest));
+        style = {
+          "font-weight": vars.labels.font.weight,
+          "font-family": vars.labels.font.family.value
+        };
+        ratio = null;
+        if (names[0].split(" ").length === 1) {
+          size = fontSizes(names[0], style)[0];
+          ratio = size.width / size.height;
+        }
+        rect = largestRect(path, {
+          angle: 0,
+          aspectRatio: ratio
+        });
+        if (rect) {
+          rect = rect[0];
+          d.d3plus_label = {
+            anchor: "middle",
+            valign: "center",
+            h: rect.height,
+            w: rect.width,
+            x: rect.cx,
+            y: rect.cy,
+            names: names
+          };
+        }
+      }
+      labels[d.id] = d.d3plus_label;
+      if (!vars.zoom.bounds) {
+        return vars.zoom.bounds = b;
+      } else {
+        if (vars.zoom.bounds[0][0] > b[0][0]) {
+          vars.zoom.bounds[0][0] = b[0][0];
+        }
+        if (vars.zoom.bounds[0][1] > b[0][1]) {
+          vars.zoom.bounds[0][1] = b[0][1];
+        }
+        if (vars.zoom.bounds[1][0] < b[1][0]) {
+          vars.zoom.bounds[1][0] = b[1][0];
+        }
+        if (vars.zoom.bounds[1][1] < b[1][1]) {
+          return vars.zoom.bounds[1][1] = b[1][1];
+        }
+      }
+    });
+  } else if (!vars.focus.value.length) {
+    vars.zoom.viewport = false;
+    return selection.each(function(d) {
+      return d.d3plus_label = labels[d.id];
+    });
+  }
+};
+
+
+},{"../../../core/fetch/text.js":67,"../../../font/sizes.coffee":101,"../../../geom/largestRect.coffee":159,"../../../geom/path2poly.coffee":161,"../../../network/distance.coffee":164,"../../../util/copy.coffee":206,"./style.coffee":231}],221:[function(require,module,exports){
+var shapeStyle  = require("./style.coffee")
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Draws "square" and "circle" shapes using svg:rect
+//------------------------------------------------------------------------------
+module.exports = function(vars,selection,enter,exit) {
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Initialize check scale on enter and exit.
+  //----------------------------------------------------------------------------
+  function init(paths){
+    paths.attr("d", d3.svg.symbol().type("cross").size(10))
+  }
+  
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Change scale of check on update.
+  //---------------------------------------------------------------------------
+  function update(paths){
+    paths.attr("d", d3.svg.symbol().type("cross").size(function(d){
+      var smaller_dim = Math.min(d.d3plus.width, d.d3plus.height);
+      return d3.scale.pow().exponent(2)(smaller_dim/2);
+    }))
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // "paths" Enter
+  //----------------------------------------------------------------------------
+  enter.append("path").attr("class","d3plus_data")
+    .call(init)
+    .call(shapeStyle,vars)
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // "paths" Update
+  //----------------------------------------------------------------------------
+  selection.selectAll("path.d3plus_data")
+    .data(function(d) {
+      return [d];
+    })
+
+  if (vars.draw.timing) {
+    selection.selectAll("path.d3plus_data")
+      .transition().duration(vars.draw.timing)
+        .call(update)
+        .call(shapeStyle,vars)
+  }
+  else {
+    selection.selectAll("path.d3plus_data")
+      .call(update)
+      .call(shapeStyle,vars)
+  }
+
+}
+
+},{"./style.coffee":231}],222:[function(require,module,exports){
+var shapeStyle  = require("./style.coffee")
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Draws "square" and "circle" shapes using svg:rect
+//------------------------------------------------------------------------------
+module.exports = function(vars,selection,enter,exit) {
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Initialize check scale on enter and exit.
+  //----------------------------------------------------------------------------
+  function init(paths){
+    paths.attr("d", d3.svg.symbol().type("diamond").size(10))
+  }
+  
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Change scale of check on update.
+  //---------------------------------------------------------------------------
+  function update(paths){
+    paths.attr("d", d3.svg.symbol().type("diamond").size(function(d){
+      var smaller_dim = Math.min(d.d3plus.width, d.d3plus.height);
+      return d3.scale.pow().exponent(2)(smaller_dim/2);
+    }))
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // "paths" Enter
+  //----------------------------------------------------------------------------
+  enter.append("path").attr("class","d3plus_data")
+    .call(init)
+    .call(shapeStyle,vars)
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // "paths" Update
+  //----------------------------------------------------------------------------
+  selection.selectAll("path.d3plus_data")
+    .data(function(d) {
+      return [d];
+    })
+
+  if (vars.draw.timing) {
+    selection.selectAll("path.d3plus_data")
+      .transition().duration(vars.draw.timing)
+        .call(update)
+        .call(shapeStyle,vars)
+  }
+  else {
+    selection.selectAll("path.d3plus_data")
+      .call(update)
+      .call(shapeStyle,vars)
+  }
+
+}
+
+},{"./style.coffee":231}],223:[function(require,module,exports){
+var shapeStyle = require("./style.coffee")
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Draws "donut" shapes using svg:path with arcs
+//------------------------------------------------------------------------------
+module.exports = function(vars,selection,enter,exit) {
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // In order to correctly animate each donut's size and arcs, we need to store
+  // it's previous values in a lookup object that does not get destroyed when
+  // redrawing the visualization.
+  //----------------------------------------------------------------------------
+  if (!vars.arcs) {
+    vars.arcs = {
+      "donut": {},
+      "active": {},
+      "temp": {}
+    }
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // This is the main arc function that determines what values to use for each
+  // arc angle and radius.
+  //----------------------------------------------------------------------------
+  var arc = d3.svg.arc()
+    .startAngle(0)
+    .endAngle(function(d){
+      var a = vars.arcs[d.d3plus.shape][d.d3plus.id].a;
+      return a > Math.PI*2 ? Math.PI*2 : a;
+    })
+    .innerRadius(function(d){
+      if (d.d3plus.static) return 0;
+      var r = vars.arcs[d.d3plus.shape][d.d3plus.id].r;
+      return r * vars.data.donut.size;
+    })
+    .outerRadius(function(d){
+      return vars.arcs[d.d3plus.shape][d.d3plus.id].r;
+    })
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // This is the main "arcTween" function where all of the animation happens
+  // for each arc.
+  //----------------------------------------------------------------------------
+  function size(path,mod,rad,ang) {
+    if (!mod) var mod = 0
+    if (typeof rad != "number") var rad = undefined
+    if (typeof ang != "number") var ang = undefined
+    path.attrTween("d", function(d){
+      if (rad == undefined) var r = d.d3plus.r ? d.d3plus.r : d3.max([d.d3plus.width,d.d3plus.height])
+      else var r = rad
+      if (ang == undefined) var a = d.d3plus.segments[d.d3plus.shape]
+      else var a = ang
+      if (!vars.arcs[d.d3plus.shape][d.d3plus.id]) {
+        vars.arcs[d.d3plus.shape][d.d3plus.id] = {"r": 0}
+        vars.arcs[d.d3plus.shape][d.d3plus.id].a = Math.PI * 2
+      }
+      var radius = d3.interpolate(vars.arcs[d.d3plus.shape][d.d3plus.id].r,r+mod),
+          angle = d3.interpolate(vars.arcs[d.d3plus.shape][d.d3plus.id].a,a)
+      return function(t) {
+        vars.arcs[d.d3plus.shape][d.d3plus.id].r = radius(t)
+        vars.arcs[d.d3plus.shape][d.d3plus.id].a = angle(t)
+        return arc(d)
+      }
+    })
+  }
+
+  function data(d) {
+
+    if (d.d3plus.label) {
+      d.d3plus_label = d.d3plus.label;
+    }
+    else {
+      delete d.d3plus_label;
+    }
+
+    return [d];
+  }
+
+  if (vars.draw.timing) {
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // "paths" Exit
+    //----------------------------------------------------------------------------
+    exit.selectAll("path.d3plus_data").transition().duration(vars.draw.timing)
+      .call(size,0,0)
+      .each("end",function(d){
+        delete vars.arcs[d.d3plus.shape][d.d3plus.id];
+      });
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // "paths" Update
+    //----------------------------------------------------------------------------
+    selection.selectAll("path.d3plus_data")
+      .data(data)
+      .transition().duration(vars.draw.timing)
+        .call(size)
+        .call(shapeStyle,vars);
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // "paths" Enter
+    //----------------------------------------------------------------------------
+    enter.append("path")
+      .attr("class","d3plus_data")
+      .transition().duration(0)
+        .call(size,0,0)
+        .call(shapeStyle,vars)
+        .transition().duration(vars.draw.timing)
+          .call(size)
+          .call(shapeStyle,vars);
+
+  }
+  else {
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // "paths" Exit
+    //----------------------------------------------------------------------------
+    exit.selectAll("path.d3plus_data")
+      .each(function(d){
+        delete vars.arcs[d.d3plus.shape][d.d3plus.id];
+      });
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // "paths" Enter
+    //----------------------------------------------------------------------------
+    enter.append("path")
+      .attr("class","d3plus_data");
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // "paths" Update
+    //----------------------------------------------------------------------------
+    selection.selectAll("path.d3plus_data")
+      .data(data)
+      .call(size)
+      .call(shapeStyle,vars);
+  }
+
+};
+
+},{"./style.coffee":231}],224:[function(require,module,exports){
+var child         = require("../../../util/child.coffee"),
+    closest       = require("../../../util/closest.coffee"),
+    createTooltip = require("../tooltip/create.js"),
+    events        = require("../../../client/pointer.coffee"),
+    fetchValue    = require("../../../core/fetch/value.coffee"),
+    fetchColor    = require("../../../core/fetch/color.coffee"),
+    fetchText     = require("../../../core/fetch/text.js"),
+    legible       = require("../../../color/legible.coffee"),
+    print         = require("../../../core/console/print.coffee"),
+    removeTooltip = require("../../../tooltip/remove.coffee"),
+    segments      = require("./segments.coffee"),
+    shapeFill     = require("./fill.js"),
+    stringStrip   = require("../../../string/strip.js"),
+    touch         = require("../../../client/touch.coffee"),
+    touchEvent    = require("../zoom/propagation.coffee"),
+    uniqueValues  = require("../../../util/uniques.coffee"),
+    validObject   = require("../../../object/validate.coffee"),
+    zoomDirection = require("../zoom/direction.coffee");
+
+var drawShape = {
+  "arc":           require("./arc.coffee"),
+  "area":          require("./area.js"),
+  "check":         require("./check.js"),
+  "coordinates":   require("./coordinates.coffee"),
+  "cross":         require("./cross.js"),
+  "diamond":       require("./diamond.js"),
+  "donut":         require("./donut.js"),
+  "line":          require("./line.js"),
+  "rect":          require("./rect.coffee"),
+  "triangle_down": require("./triangle_down.js"),
+  "triangle_up":   require("./triangle_up.js"),
+  "whisker":       require("./whisker.coffee")
+};
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Draws the appropriate shape based on the data
+//------------------------------------------------------------------------------
+module.exports = function(vars) {
+
+  var data = vars.returned.nodes || [],
+      edges = vars.returned.edges || [];
+
+  vars.draw.timing = data.length < vars.data.large &&
+                     edges.length < vars.edges.large ?
+                     vars.timing.transitions : 0;
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Match vars.shape types to their respective d3plus.shape functions. For
+  // example, both "square", and "circle" shapes use "rect" as their drawing
+  // class.
+  //----------------------------------------------------------------------------
+  var shapeLookup = {
+    "arc":             "arc",
+    "area":            "area",
+    "check":           "check",
+    "circle":          "rect",
+    "coordinates":     "coordinates",
+    "cross":           "cross",
+    "donut":           "donut",
+    "diamond":         "diamond",
+    "line":            "line",
+    "plus":            "cross",
+    "rect":            "rect",
+    "square":          "rect",
+    "triangle_down":   "triangle_down",
+    "triangle":        "triangle_up",
+    "triangle_up":     "triangle_up",
+    "whisker":         "whisker"
+  };
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Split the data by each shape type in the data.
+  //----------------------------------------------------------------------------
+  var shapes = {};
+  data.forEach(function(d){
+    var s = d.d3plus && d.d3plus.shape ? d.d3plus.shape : vars.shape.value;
+    if (s in shapeLookup) {
+      if (d.d3plus) d.d3plus.shape = s
+      s = shapeLookup[s]
+      if (!shapes[s]) shapes[s] = []
+      shapes[s].push(d)
+    }
+  })
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Resets the "id" of each data point to use with matching.
+  //----------------------------------------------------------------------------
+  function id(d) {
+
+    if (!d.d3plus.id) {
+      d.d3plus.id = ""
+      for (var i = 0; i <= vars.depth.value; i++) {
+        d.d3plus.id += fetchValue(vars,d,vars.id.nesting[i])+"_"
+      }
+
+      d.d3plus.id += shape;
+
+      ["x","y"].forEach(function(axis){
+        if (vars[axis].scale.value == "discrete") {
+          var val = fetchValue(vars, d, vars[axis].value)
+          if (val.constructor === Date) val = val.getTime()
+          d.d3plus.id += "_"+val
+        }
+      })
+
+      d.d3plus.id = stringStrip(d.d3plus.id)
+    }
+
+    return d
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Transforms the positions and scale of each group.
+  //----------------------------------------------------------------------------
+  function transform(g,grow) {
+
+    var scales = vars.types[vars.type.value].scale,
+        scale = 1;
+    if (scales) {
+      if (validObject[scales] && vars.shape.value in scales) {
+        scale = scales[vars.shape.value];
+      }
+      else if (typeof scales == "function") {
+        scale = scales(vars, vars.shape.value);
+      }
+      else if (typeof scales == "number") {
+        scale = scales;
+      }
+    }
+
+    scale = grow ? scale : 1;
+    g.attr("transform", function(d){
+
+      if (["line","area","coordinates"].indexOf(shape) < 0) {
+          var x = d.d3plus.x || 0, y = d.d3plus.y || 0;
+          return "translate("+x+","+y+")scale("+scale+")";
+      }
+      else {
+        return "scale("+scale+")";
+      }
+
+    });
+
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Remove old groups
+  //----------------------------------------------------------------------------
+  for (var s in shapeLookup) {
+    if (!(shapeLookup[s] in shapes) || d3.keys(shapes).length === 0) {
+      var oldShapes = vars.g.data.selectAll("g.d3plus_"+shapeLookup[s]);
+      if (vars.draw.timing) {
+        oldShapes
+          .transition().duration(vars.draw.timing)
+          .attr("opacity",0)
+          .remove();
+      }
+      else {
+        oldShapes
+          .remove();
+      }
+    }
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Initialize arrays for labels and sizes
+  //----------------------------------------------------------------------------
+  var labels = [], shares = [];
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Create groups by shape, apply data, and call specific shape drawing class.
+  //----------------------------------------------------------------------------
+  for (var shape in shapes) {
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Bind Data to Groups
+    //--------------------------------------------------------------------------
+    var selection = vars.g.data.selectAll("g.d3plus_"+shape)
+      .data(shapes[shape],function(d){
+
+        if (!d.d3plus) d.d3plus = {}
+
+        if ( shape === "coordinates" ) {
+          d.d3plus.id = d.id
+          return d.id
+        }
+
+        if ( !d.d3plus.id ) {
+
+          if (d.values) {
+
+            d.values.forEach(function(v){
+              v = id(v)
+              v.d3plus.shape = "circle"
+            })
+            d.d3plus.id = d.key
+
+          }
+          else {
+
+            d = id(d)
+
+            if (!d.d3plus.segments) {
+
+              d.d3plus.segments = {"donut": Math.PI*2}
+              var active = segments(vars, d, "active"),
+                  temp   = segments(vars, d, "temp"),
+                  total  = segments(vars, d, "total");
+
+              if (total) {
+                if (active) {
+                  d.d3plus.segments.active = (active/total) * (Math.PI * 2)
+                }
+                else {
+                  d.d3plus.segments.active = 0
+                }
+                if (temp) {
+                  d.d3plus.segments.temp = ((temp/total) * (Math.PI * 2)) + d.d3plus.segments.active
+                }
+                else {
+                  d.d3plus.segments.temp = 0
+                }
+              }
+
+            }
+
+          }
+
+        }
+
+        return d.d3plus ? d.d3plus.id : false;
+
+      })
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Groups Exit
+    //--------------------------------------------------------------------------
+    if (vars.draw.timing) {
+      var exit = selection.exit()
+        .transition().duration(vars.draw.timing)
+        .attr("opacity",0)
+        .remove()
+    }
+    else {
+      var exit = selection.exit()
+        .remove()
+    }
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Existing Groups Update
+    //--------------------------------------------------------------------------
+    if (vars.draw.timing) {
+      selection
+        .transition().duration(vars.draw.timing)
+        .call(transform)
+    }
+    else {
+      selection.call(transform)
+    }
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Groups Enter
+    //--------------------------------------------------------------------------
+    var opacity = vars.draw.timing ? 0 : 1
+    var enter = selection.enter().append("g")
+      .attr("class","d3plus_"+shape)
+      .attr("opacity",opacity)
+      .call(transform)
+
+    if (vars.draw.timing) {
+      enter.transition().duration(vars.draw.timing)
+        .attr("opacity",1)
+    }
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // All Groups Sort Order
+    //--------------------------------------------------------------------------
+    selection.order()
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Draw appropriate graphics inside of each group
+    //--------------------------------------------------------------------------
+    if ( vars.dev.value ) print.time("drawing \"" + shape + "\" shapes")
+    drawShape[shape]( vars , selection , enter , exit , transform )
+    if ( vars.dev.value ) print.timeEnd("drawing \"" + shape + "\" shapes")
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Check for active and temp fills for rects and donuts
+    //--------------------------------------------------------------------------
+    if (["rect","donut"].indexOf(shape) >= 0 && vars.types[vars.type.value].fill) {
+      if ( vars.dev.value ) print.time("filling \"" + shape + "\" shapes")
+      shapeFill( vars , selection , enter , exit , transform )
+      if ( vars.dev.value ) print.timeEnd("filling \"" + shape + "\" shapes")
+    }
+
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Function to Update Edges
+  //----------------------------------------------------------------------------
+  function edge_update(d) {
+
+    if (d && vars.g.edges.selectAll("g").size() > 0) {
+
+      vars.g.edge_hover
+        .selectAll("*")
+        .remove()
+
+      vars.g.edges.selectAll("g")
+        .each(function(l){
+
+          var id = d[vars.id.value],
+              source = l[vars.edges.source][vars.id.value],
+              target = l[vars.edges.target][vars.id.value]
+
+          if (source == id || target == id) {
+            var elem = vars.g.edge_hover.node().appendChild(this.cloneNode(true))
+            d3.select(elem).datum(l).attr("opacity",1)
+              .selectAll("line, path").datum(l)
+          }
+
+        })
+
+
+      var marker = vars.edges.arrows.value
+
+      vars.g.edge_hover
+        .attr("opacity",0)
+        .selectAll("line, path")
+          .style("stroke",vars.color.primary)
+          .style("stroke-width",function(){
+            return vars.edges.size.value ? d3.select(this).style("stroke-width")
+                 : vars.data.stroke.width*2
+          })
+          .attr("marker-start",function(e){
+
+            var direction = vars.edges.arrows.direction.value
+
+            if ("bucket" in e.d3plus) {
+              var d = "_"+e.d3plus.bucket
+            }
+            else {
+              var d = ""
+            }
+
+            return direction == "source" && marker
+                 ? "url(#d3plus_edge_marker_highlight"+d+")" : "none"
+
+          })
+          .attr("marker-end",function(e){
+
+            var direction = vars.edges.arrows.direction.value
+
+            if ("bucket" in e.d3plus) {
+              var d = "_"+e.d3plus.bucket
+            }
+            else {
+              var d = ""
+            }
+
+            return direction == "target" && marker
+                 ? "url(#d3plus_edge_marker_highlight"+d+")" : "none"
+
+          })
+
+
+      vars.g.edge_hover.selectAll("text")
+        .style("fill",vars.color.primary)
+
+      if (vars.draw.timing) {
+
+        vars.g.edge_hover
+          .transition().duration(vars.timing.mouseevents)
+          .attr("opacity",1)
+
+        vars.g.edges
+          .transition().duration(vars.timing.mouseevents)
+          .attr("opacity",0.5)
+
+      }
+      else {
+
+        vars.g.edge_hover
+          .attr("opacity",1)
+
+      }
+
+    }
+    else {
+
+      if (vars.draw.timing) {
+
+        vars.g.edge_hover
+          .transition().duration(vars.timing.mouseevents)
+          .attr("opacity",0)
+          .transition()
+          .selectAll("*")
+          .remove()
+
+        vars.g.edges
+          .transition().duration(vars.timing.mouseevents)
+          .attr("opacity",1)
+
+      }
+      else {
+
+        vars.g.edge_hover
+          .selectAll("*")
+          .remove()
+
+      }
+
+    }
+
+  }
+
+  edge_update()
+
+  if (!touch && vars.tooltip.value) {
+
+    vars.g.data.selectAll("g")
+      .on(events.over,function(d){
+
+        if (vars.mouse.value && vars.mouse.over.value && !vars.draw.frozen && (!d.d3plus || !d.d3plus.static)) {
+
+          if (typeof vars.mouse.over.value === "function") {
+            vars.mouse.over.value(d, vars.self);
+          }
+          else {
+
+            d3.select(this).style("cursor","pointer")
+              .transition().duration(vars.timing.mouseevents)
+              .call(transform,true)
+
+            d3.select(this).selectAll(".d3plus_data")
+              .transition().duration(vars.timing.mouseevents)
+              .attr("opacity",1)
+
+            vars.covered = false
+
+            if (d.values && vars.axes.discrete) {
+
+              var index = vars.axes.discrete === "x" ? 0 : 1
+                , mouse = d3.mouse(vars.container.value.node())[index]
+                , positions = uniqueValues(d.values,function(x){return x.d3plus[vars.axes.discrete]})
+                , match = closest(positions,mouse)
+
+              d.d3plus_data = d.values[positions.indexOf(match)]
+              d.d3plus = d.values[positions.indexOf(match)].d3plus
+
+            }
+
+            var tooltip_data = d.d3plus_data ? d.d3plus_data : d
+
+            createTooltip({
+              "vars": vars,
+              "data": tooltip_data
+            })
+
+            if (typeof vars.mouse.viz == "function") {
+              vars.mouse.viz(d.d3plus_data || d, vars)
+            }
+            else if (vars.mouse.viz[events.over]) {
+              vars.mouse.viz[events.over](d.d3plus_data || d, vars)
+            }
+
+            edge_update(d)
+
+          }
+
+        }
+
+      })
+      .on(events.move,function(d){
+
+        if (vars.mouse.value && vars.mouse.move.value && !vars.draw.frozen && (!d.d3plus || !d.d3plus.static)) {
+
+          if (typeof vars.mouse.move.value === "function") {
+            vars.mouse.move.value(d, vars.self);
+          }
+          else {
+
+            // vars.covered = false
+            var tooltipType = vars.types[vars.type.value].tooltip || "follow"
+
+            if (d.values && vars.axes.discrete) {
+
+              var index = vars.axes.discrete === "x" ? 0 : 1
+                , mouse = d3.mouse(vars.container.value.node())[index]
+                , positions = uniqueValues(d.values,function(x){return x.d3plus[vars.axes.discrete]})
+                , match = closest(positions,mouse)
+
+              d.d3plus_data = d.values[positions.indexOf(match)]
+              d.d3plus = d.values[positions.indexOf(match)].d3plus
+
+            }
+
+            var tooltip_data = d.d3plus_data ? d.d3plus_data : d
+            createTooltip({
+              "vars": vars,
+              "data": tooltip_data
+            })
+
+            if (typeof vars.mouse.viz == "function") {
+              vars.mouse.viz(d.d3plus_data || d, vars)
+            }
+            else if (vars.mouse.viz[events.move]) {
+              vars.mouse.viz[events.move](d.d3plus_data || d, vars)
+            }
+
+          }
+
+        }
+
+      })
+      .on(events.out,function(d){
+
+        if (vars.mouse.value && vars.mouse.out.value) {
+
+          if (typeof vars.mouse.out.value === "function") {
+            vars.mouse.out.value(d, vars.self);
+          }
+          else {
+
+            var childElement = child(this,d3.event.toElement)
+
+            if (!childElement && !vars.draw.frozen && (!d.d3plus || !d.d3plus.static)) {
+
+              d3.select(this)
+                .transition().duration(vars.timing.mouseevents)
+                .call(transform)
+
+              d3.select(this).selectAll(".d3plus_data")
+                .transition().duration(vars.timing.mouseevents)
+                .attr("opacity",vars.data.opacity)
+
+              if (!vars.covered) {
+                removeTooltip(vars.type.value)
+              }
+
+              if (typeof vars.mouse.viz == "function") {
+                vars.mouse.viz(d.d3plus_data || d, vars)
+              }
+              else if (vars.mouse.viz[events.out]) {
+                vars.mouse.viz[events.out](d.d3plus_data || d, vars)
+              }
+
+              edge_update()
+
+            }
+
+          }
+
+        }
+
+      })
+
+  }
+  else {
+
+    var mouseEvent = function() {
+      touchEvent(vars, d3.event)
+    }
+
+    vars.g.data.selectAll("g")
+      .on(events.over, mouseEvent)
+      .on(events.move, mouseEvent)
+      .on(events.out , mouseEvent)
+
+  }
+
+  vars.g.data.selectAll("g")
+    .on(events.click,function(d){
+
+      if (vars.mouse.value && vars.mouse.click.value && !d3.event.defaultPrevented && !vars.draw.frozen && (!d.d3plus || !d.d3plus.static)) {
+
+        if (typeof vars.mouse.click.value === "function") {
+          vars.mouse.click.value(d, vars.self);
+        }
+        else {
+
+          if (typeof vars.mouse.viz == "function") {
+            vars.mouse.viz(d.d3plus_data || d, vars)
+          }
+          else if (vars.mouse.viz[events.out]) {
+            vars.mouse.viz[events.out](d.d3plus_data || d, vars)
+          }
+          else if (vars.mouse.viz[events.click]) {
+            vars.mouse.viz[events.click](d.d3plus_data || d, vars)
+          }
+
+          var depth_delta = zoomDirection(d.d3plus_data || d, vars)
+            , previous = vars.id.solo.value
+            , title = fetchText(vars,d)[0]
+            , color = legible(fetchColor(vars,d))
+            , prev_sub = vars.title.sub.value || false
+            , prev_color = vars.title.sub.font.color
+            , prev_total = vars.title.total.font.color
+
+          if (d.d3plus.threshold && d.d3plus.merged && vars.zoom.value) {
+
+            vars.history.states.push(function(){
+
+              vars.self
+                .id({"solo": previous})
+                .title({
+                  "sub": {
+                    "font": {
+                      "color": prev_color
+                    },
+                    "value": prev_sub
+                  },
+                  "total": {
+                    "font": {
+                      "color": prev_total
+                    }
+                  }
+                })
+                .draw()
+
+            })
+
+            vars.self
+              .id({"solo": previous.concat(uniqueValues(d.d3plus.merged, vars.id.value, fetchValue, vars))})
+              .title({
+                "sub": {
+                  "font": {
+                    "color": color
+                  },
+                  "value": title
+                },
+                "total": {
+                  "font": {
+                    "color": color
+                  }
+                }
+              })
+              .draw()
+
+          }
+          else if (depth_delta === 1 && vars.zoom.value) {
+
+            var id = fetchValue(vars, d.d3plus_data || d, vars.id.value)
+
+            vars.history.states.push(function(){
+
+              vars.self
+                .depth(vars.depth.value-1)
+                .id({"solo": previous})
+                .title({
+                  "sub": {
+                    "font": {
+                      "color": prev_color
+                    },
+                    "value": prev_sub
+                  },
+                  "total": {
+                    "font": {
+                      "color": prev_total
+                    }
+                  }
+                })
+                .draw()
+
+            })
+
+            vars.self
+              .depth(vars.depth.value+1)
+              .id({"solo": previous.concat(id)})
+              .title({
+                "sub": {
+                  "font": {
+                    "color": color
+                  },
+                  "value": title
+                },
+                "total": {
+                  "font": {
+                    "color": color
+                  }
+                }
+              })
+              .draw()
+
+          }
+          else if (depth_delta === -1 && vars.zoom.value &&
+                   vars.history.states.length && !vars.tooltip.value.long) {
+
+            vars.history.back()
+
+          }
+          else if (vars.types[vars.type.value].zoom && vars.zoom.value) {
+
+            edge_update()
+
+            d3.select(this)
+              .transition().duration(vars.timing.mouseevents)
+              .call(transform)
+
+            d3.select(this).selectAll(".d3plus_data")
+              .transition().duration(vars.timing.mouseevents)
+              .attr("opacity",vars.data.opacity)
+
+            removeTooltip(vars.type.value)
+            vars.draw.update = false
+
+            if (!d || d[vars.id.value] == vars.focus.value[0]) {
+              vars.self.focus(false).draw()
+            }
+            else {
+              vars.self.focus(d[vars.id.value]).draw()
+            }
+
+          }
+          else if (vars.types[vars.type.value].requirements.indexOf("focus") < 0) {
+
+            edge_update()
+
+            var tooltip_data = d.d3plus_data ? d.d3plus_data : d
+
+            createTooltip({
+              "vars": vars,
+              "data": tooltip_data
+            })
+
+          }
+
+        }
+
+      }
+
+    })
+
+}
+
+},{"../../../client/pointer.coffee":40,"../../../client/touch.coffee":44,"../../../color/legible.coffee":45,"../../../core/console/print.coffee":53,"../../../core/fetch/color.coffee":64,"../../../core/fetch/text.js":67,"../../../core/fetch/value.coffee":68,"../../../object/validate.coffee":171,"../../../string/strip.js":174,"../../../tooltip/remove.coffee":202,"../../../util/child.coffee":204,"../../../util/closest.coffee":205,"../../../util/uniques.coffee":209,"../tooltip/create.js":237,"../zoom/direction.coffee":247,"../zoom/propagation.coffee":250,"./arc.coffee":216,"./area.js":217,"./check.js":218,"./coordinates.coffee":220,"./cross.js":221,"./diamond.js":222,"./donut.js":223,"./fill.js":226,"./line.js":228,"./rect.coffee":229,"./segments.coffee":230,"./triangle_down.js":232,"./triangle_up.js":233,"./whisker.coffee":234}],225:[function(require,module,exports){
+var buckets = require("../../../util/buckets.coffee"),
+    offset  = require("../../../geom/offset.coffee");
+
+module.exports = function(vars) {
+
+  var edges = vars.returned.edges || [],
+      scale = vars.zoom.behavior.scaleExtent()[0];
+
+  if (typeof vars.edges.size.value === "string") {
+
+    var strokeDomain = d3.extent(edges, function(e){
+                         return e[vars.edges.size.value];
+                       }),
+        maxSize = d3.min(vars.returned.nodes || [], function(n){
+                        return n.d3plus.r;
+                      }) * (vars.edges.size.scale * 2);
+
+    vars.edges.scale = d3.scale.sqrt()
+      .domain(strokeDomain)
+      .range([vars.edges.size.min,maxSize*scale]);
+
+  }
+  else {
+
+    var defaultWidth = typeof vars.edges.size.value == "number" ?
+                       vars.edges.size.value : vars.edges.size.min;
+
+    vars.edges.scale = function(){
+      return defaultWidth;
+    };
+
+  }
+
+  var o = vars.edges.opacity.value;
+  var o_type = typeof o;
+
+  if (vars.edges.opacity.changed && o_type === "string") {
+    vars.edges.opacity.scale.value
+      .domain(d3.extent(edges, function(d){
+        return d[o];
+      }))
+      .range([vars.edges.opacity.min.value,1]);
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Initialization of Lines
+  //----------------------------------------------------------------------------
+  function init(l) {
+
+    l
+      .attr("opacity", 0)
+      .style("stroke-width",0)
+      .style("stroke",vars.background.value)
+      .style("fill","none");
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Styling of Lines
+  //----------------------------------------------------------------------------
+  function style(edges) {
+
+    var marker = vars.edges.arrows.value;
+
+    edges
+      .attr("opacity", function(d){
+        return o_type === "number" ? o :
+               o_type === "function" ? o(d, vars) :
+               vars.edges.opacity.scale.value(d[o]);
+      })
+      .style("stroke-width",function(e){
+        return vars.edges.scale(e[vars.edges.size.value]);
+      })
+      .style("stroke",vars.edges.color)
+      .attr("marker-start",function(e){
+
+        var direction = vars.edges.arrows.direction.value;
+
+        if ("bucket" in e.d3plus) {
+          var d = "_"+e.d3plus.bucket;
+        }
+        else {
+          var d = "";
+        }
+
+        return direction == "source" && marker
+             ? "url(#d3plus_edge_marker_default"+d+")" : "none"
+
+      })
+      .attr("marker-end",function(e){
+
+        var direction = vars.edges.arrows.direction.value
+
+        if ("bucket" in e.d3plus) {
+          var d = "_"+e.d3plus.bucket
+        }
+        else {
+          var d = ""
+        }
+
+        return direction == "target" && marker
+             ? "url(#d3plus_edge_marker_default"+d+")" : "none"
+
+      })
+      .attr("vector-effect","non-scaling-stroke")
+      .attr("pointer-events","none")
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Positioning of Lines
+  //----------------------------------------------------------------------------
+  function line(l) {
+    l
+      .attr("x1",function(d){
+        return d[vars.edges.source].d3plus.edges[d[vars.edges.target][vars.id.value]].x;
+      })
+      .attr("y1",function(d){
+        return d[vars.edges.source].d3plus.edges[d[vars.edges.target][vars.id.value]].y;
+      })
+      .attr("x2",function(d){
+        return d[vars.edges.target].d3plus.edges[d[vars.edges.source][vars.id.value]].x;
+      })
+      .attr("y2",function(d){
+        return d[vars.edges.target].d3plus.edges[d[vars.edges.source][vars.id.value]].y;
+      });
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Positioning of Splines
+  //----------------------------------------------------------------------------
+  var curve = d3.svg.line().interpolate(vars.edges.interpolate.value);
+
+  function spline(l) {
+    l
+      .attr("d", function(d) {
+
+        return curve(d.d3plus.spline);
+
+      });
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Calculates and Draws Label for edge
+  //----------------------------------------------------------------------------
+  function label(d) {
+
+    delete d.d3plus_label
+
+    if (vars.g.edges.selectAll("line, path").size() < vars.edges.large && vars.edges.label && d[vars.edges.label]) {
+
+      if ("spline" in d.d3plus) {
+
+        var length = this.getTotalLength(),
+            center = this.getPointAtLength(length/2),
+            prev = this.getPointAtLength((length/2)-(length*.1)),
+            next = this.getPointAtLength((length/2)+(length*.1)),
+            radians = Math.atan2(next.y-prev.y,next.x-prev.x),
+            angle = radians*(180/Math.PI),
+            bounding = this.parentNode.getBBox(),
+            width = length*.8,
+            x = center.x,
+            y = center.y
+
+      }
+      else {
+
+        var bounds = this.getBBox(),
+            source = d[vars.edges.source],
+            target = d[vars.edges.target],
+            start = {"x": source.d3plus.edges[target[vars.id.value]].x, "y": source.d3plus.edges[target[vars.id.value]].y},
+            end = {"x": target.d3plus.edges[source[vars.id.value]].x, "y": target.d3plus.edges[source[vars.id.value]].y},
+            xdiff = end.x-start.x,
+            ydiff = end.y-start.y,
+            center = {"x": end.x-(xdiff)/2, "y": end.y-(ydiff)/2},
+            radians = Math.atan2(ydiff,xdiff),
+            angle = radians*(180/Math.PI),
+            length = Math.sqrt((xdiff*xdiff)+(ydiff*ydiff)),
+            width = length,
+            x = center.x,
+            y = center.y
+
+      }
+
+      width += vars.labels.padding*2
+
+      var m = 0
+      if (vars.edges.arrows.value) {
+        m = typeof vars.edges.arrows.value === "number"
+          ? vars.edges.arrows.value : 8
+        m = m/vars.zoom.behavior.scaleExtent()[1]
+        width -= m*2
+      }
+
+      if (angle < -90 || angle > 90) {
+        angle -= 180
+      }
+
+      if (width*vars.zoom.behavior.scaleExtent()[0] > 20) {
+
+        d.d3plus_label = {
+          "x": x,
+          "y": y,
+          "translate": {"x": x, "y": y},
+          "w": width,
+          "h": 15+vars.labels.padding*2,
+          "angle": angle,
+          "anchor": "middle",
+          "valign": "center",
+          "color": vars.edges.color,
+          "resize": false,
+          "names": [vars.format.value(d[vars.edges.label])],
+          "background": 1
+        }
+
+      }
+
+    }
+
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Enter/update/exit the Arrow Marker
+  //----------------------------------------------------------------------------
+  var markerData = vars.edges.arrows.value ? typeof vars.edges.size.value == "string"
+                  ? [ "default_0", "default_1", "default_2",
+                      "highlight_0", "highlight_1", "highlight_2",
+                      "focus_0", "focus_1", "focus_2" ]
+                  : [ "default", "highlight", "focus" ] : []
+
+  if (typeof vars.edges.size.value == "string") {
+    var b = buckets(vars.edges.scale.range(),4)
+      , markerSize = []
+    for (var i = 0; i < 3; i++) {
+      markerSize.push(b[i+1]+(b[1]-b[0])*(i+2)*2)
+    }
+  }
+  else {
+    var m = typeof vars.edges.arrows.value === "number"
+          ? vars.edges.arrows.value : 8
+
+    var markerSize = typeof vars.edges.size.value === "number"
+                    ? vars.edges.size.value/m : m
+  }
+
+  var marker = vars.defs.selectAll(".d3plus_edge_marker")
+    .data(markerData, String)
+
+  var marker_style = function(path) {
+    path
+      .attr("d",function(id){
+
+        var depth = id.split("_")
+
+        if (depth.length == 2 && vars.edges.scale) {
+          depth = parseInt(depth[1])
+          var m = markerSize[depth]
+        }
+        else {
+          var m = markerSize
+        }
+
+        if (vars.edges.arrows.direction.value == "target") {
+          return "M 0,-"+m/2+" L "+m*.85+",0 L 0,"+m/2+" L 0,-"+m/2
+        }
+        else {
+          return "M 0,-"+m/2+" L -"+m*.85+",0 L 0,"+m/2+" L 0,-"+m/2
+        }
+      })
+      .attr("fill",function(d){
+
+        var type = d.split("_")[0]
+
+        if (type == "default") {
+          return vars.edges.color
+        }
+        else if (type == "focus") {
+          return vars.color.focus
+        }
+        else {
+          return vars.color.primary
+        }
+      })
+      .attr("transform","scale("+1/scale+")")
+  }
+
+  if (vars.draw.timing) {
+    marker.exit().transition().duration(vars.draw.timing)
+      .attr("opacity",0)
+      .remove()
+
+    marker.select("path").transition().duration(vars.draw.timing)
+      .attr("opacity",1)
+      .call(marker_style)
+  }
+  else {
+    marker.exit().remove()
+
+    marker.select("path")
+      .attr("opacity",1)
+      .call(marker_style)
+  }
+
+  var opacity = vars.draw.timing ? 0 : 1
+  var enter = marker.enter().append("marker")
+    .attr("id",function(d){
+      return "d3plus_edge_marker_"+d
+    })
+    .attr("class","d3plus_edge_marker")
+    .attr("orient","auto")
+    .attr("markerUnits","userSpaceOnUse")
+    .style("overflow","visible")
+    .append("path")
+    .attr("opacity",opacity)
+    .attr("vector-effect","non-scaling-stroke")
+    .call(marker_style)
+
+  if (vars.draw.timing) {
+    enter.transition().duration(vars.draw.timing)
+      .attr("opacity",1)
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Bind "edges" data to lines in the "edges" group
+  //----------------------------------------------------------------------------
+  var strokeBuckets = typeof vars.edges.size.value == "string"
+                    ? buckets(vars.edges.scale.domain(),4)
+                    : null
+    , direction = vars.edges.arrows.direction.value
+
+  var line_data = edges.filter(function(l){
+
+    if (!l.d3plus) l.d3plus = {}
+
+    l.d3plus.id = "edge_"+l[vars.edges.source][vars.id.value]+"_"+l[vars.edges.target][vars.id.value]
+
+    if ( l.d3plus.spline !== true ) {
+
+      if (strokeBuckets) {
+        var size = l[vars.edges.size.value]
+        l.d3plus.bucket = size < strokeBuckets[1] ? 0
+                        : size < strokeBuckets[2] ? 1 : 2
+        var marker = markerSize[l.d3plus.bucket]*.85/scale
+      }
+      else {
+        delete l.d3plus.bucket
+        var marker = markerSize*.85/scale
+      }
+
+      var source = l[vars.edges.source]
+        , target = l[vars.edges.target]
+
+      if (!source.d3plus || !target.d3plus) return false
+
+      var sourceAngle = Math.atan2( source.d3plus.y - target.d3plus.y
+                                  , source.d3plus.x - target.d3plus.x )
+        , targetAngle = Math.atan2( target.d3plus.y - source.d3plus.y
+                                  , target.d3plus.x - source.d3plus.x )
+        , sourceRadius = direction == "source" && vars.edges.arrows.value
+                       ? source.d3plus.r + marker
+                       : source.d3plus.r
+        , targetRadius = direction == "target" && vars.edges.arrows.value
+                       ? target.d3plus.r + marker
+                       : target.d3plus.r
+        , sourceOffset = offset( sourceAngle
+                                           , sourceRadius
+                                           , vars.shape.value )
+        , targetOffset = offset( targetAngle
+                                           , targetRadius
+                                           , vars.shape.value )
+
+      if (!("edges" in source.d3plus)) source.d3plus.edges = {}
+      source.d3plus.edges[target[vars.id.value]] = {
+          "x": source.d3plus.x - sourceOffset.x,
+          "y": source.d3plus.y - sourceOffset.y
+      }
+
+      if (!("edges" in target.d3plus)) target.d3plus.edges = {}
+      target.d3plus.edges[source[vars.id.value]] = {
+          "x": target.d3plus.x - targetOffset.x,
+          "y": target.d3plus.y - targetOffset.y
+      }
+
+      return true
+    }
+
+    return false
+
+  })
+
+  var lines = vars.g.edges.selectAll("g.d3plus_edge_line")
+    .data(line_data,function(d){
+
+      return d.d3plus.id
+
+    })
+
+  var spline_data = edges.filter(function(l){
+
+    if (l.d3plus.spline) {
+
+      if (strokeBuckets) {
+        var size = l[vars.edges.size.value]
+        l.d3plus.bucket = size < strokeBuckets[1] ? 0
+                        : size < strokeBuckets[2] ? 1 : 2
+        var marker = markerSize[l.d3plus.bucket]*.85/scale
+      }
+      else {
+        delete l.d3plus.bucket
+        var marker = markerSize*.85/scale
+      }
+
+      var source = l[vars.edges.source]
+        , target = l[vars.edges.target]
+        , sourceEdge = source.d3plus.edges ? source.d3plus.edges[target[vars.id.value]] || {} : {}
+        , targetEdge = target.d3plus.edges ? target.d3plus.edges[source[vars.id.value]] || {} : {}
+        , sourceMod = vars.edges.arrows.value && direction == "source" ? marker : 0
+        , targetMod = vars.edges.arrows.value && direction == "target" ? marker : 0
+        , angleTweak = 0.1
+        , sourceTweak = source.d3plus.x > target.d3plus.x ? 1-angleTweak : 1+angleTweak
+        , targetTweak = source.d3plus.x > target.d3plus.x ? 1+angleTweak : 1-angleTweak
+        , sourceAngle = typeof sourceEdge.angle === "number" ? sourceEdge.angle
+                      : Math.atan2( source.d3plus.y - target.d3plus.y
+                                  , source.d3plus.x - target.d3plus.x ) * sourceTweak
+        , sourceOffset = offset(sourceAngle, source.d3plus.r + sourceMod, vars.shape.value )
+        , targetAngle = typeof targetEdge.angle === "number" ? targetEdge.angle
+                      : Math.atan2( target.d3plus.y - source.d3plus.y
+                                  , target.d3plus.x - source.d3plus.x ) * targetTweak
+        , targetOffset = offset(targetAngle, target.d3plus.r + targetMod, vars.shape.value )
+        , start = [source.d3plus.x-sourceOffset.x, source.d3plus.y-sourceOffset.y]
+        , startOffset = sourceEdge.offset ? offset(sourceAngle,sourceEdge.offset) : false
+        , startPoint = startOffset ? [start[0]-startOffset.x,start[1]-startOffset.y] : start
+        , end = [target.d3plus.x-targetOffset.x, target.d3plus.y-targetOffset.y]
+        , endOffset = targetEdge.offset ? offset(targetAngle,targetEdge.offset) : false
+        , endPoint = endOffset ? [end[0]-endOffset.x,end[1]-endOffset.y] : end
+        , xd = endPoint[0] - startPoint[0]
+        , yd = endPoint[1] - startPoint[1]
+        , sourceDistance = typeof sourceEdge.radius === "number" ? sourceEdge.radius : Math.sqrt(xd*xd+yd*yd)/4
+        , targetDistance = typeof targetEdge.radius === "number" ? targetEdge.radius : Math.sqrt(xd*xd+yd*yd)/4
+        , startAnchor = offset(sourceAngle,sourceDistance-source.d3plus.r-sourceMod*2)
+        , endAnchor = offset(targetAngle,targetDistance-target.d3plus.r-targetMod*2)
+
+      l.d3plus.spline = [ start, end ]
+      var testAngle = Math.abs(Math.atan2( source.d3plus.y - target.d3plus.y
+                                         , source.d3plus.x - target.d3plus.x )).toFixed(5)
+        , testStart = Math.abs(sourceAngle).toFixed(5)
+        , testEnd   = Math.abs(targetAngle - Math.PI).toFixed(5)
+
+      if (testStart !== testEnd || [testStart,testEnd].indexOf(testAngle) < 0) {
+
+        l.d3plus.spline.splice(1,0,[startPoint[0]-startAnchor.x,startPoint[1]-startAnchor.y],
+                                   [endPoint[0]-endAnchor.x,endPoint[1]-endAnchor.y])
+
+        if (startOffset) l.d3plus.spline.splice(1,0,startPoint)
+        if (endOffset) l.d3plus.spline.splice(l.d3plus.spline.length-1,0,endPoint)
+
+      }
+
+      return true
+
+    }
+
+    return false
+
+  })
+
+  var splines = vars.g.edges.selectAll("g.d3plus_edge_path")
+    .data(spline_data,function(d){
+
+      return d.d3plus.id
+
+    })
+
+  if (vars.draw.timing) {
+
+    lines.exit().transition().duration(vars.draw.timing)
+      .attr("opacity",0)
+      .remove()
+
+    splines.exit().transition().duration(vars.draw.timing)
+      .attr("opacity",0)
+      .remove()
+
+    lines.selectAll("text.d3plus_label, rect.d3plus_label_bg")
+      .transition().duration(vars.draw.timing/2)
+      .attr("opacity",0)
+      .remove()
+
+    splines.selectAll("text.d3plus_label, rect.d3plus_label_bg")
+      .transition().duration(vars.draw.timing/2)
+      .attr("opacity",0)
+      .remove()
+
+    lines.selectAll("line")
+      .data(function(d){ return [d] })
+      .transition().duration(vars.draw.timing)
+        .call(line)
+        .call(style)
+        .each("end",label)
+
+    splines.selectAll("path")
+      .data(function(d){ return [d] })
+      .transition().duration(vars.draw.timing)
+        .call(spline)
+        .call(style)
+        .each("end",label)
+
+    lines.enter().append("g")
+      .attr("class","d3plus_edge_line")
+      .append("line")
+      .call(line)
+      .call(init)
+      .transition().duration(vars.draw.timing)
+        .call(style)
+        .each("end",label)
+
+    splines.enter().append("g")
+      .attr("class","d3plus_edge_path")
+      .append("path")
+      .call(spline)
+      .call(init)
+      .transition().duration(vars.draw.timing)
+        .call(style)
+        .each("end",label)
+
+  }
+  else {
+
+    lines.exit().remove()
+
+    splines.exit().remove()
+
+    lines.selectAll("text.d3plus_label, rect.d3plus_label_bg")
+      .remove()
+
+    splines.selectAll("text.d3plus_label, rect.d3plus_label_bg")
+      .remove()
+
+    lines.selectAll("line")
+      .data(function(d){ return [d] })
+      .call(line)
+      .call(style)
+      .call(label)
+
+    splines.selectAll("path")
+      .data(function(d){ return [d] })
+      .call(spline)
+      .call(style)
+      .call(label)
+
+    lines.enter().append("g")
+      .attr("class","d3plus_edge_line")
+      .append("line")
+      .call(line)
+      .call(init)
+      .call(style)
+      .call(label)
+
+    splines.enter().append("g")
+      .attr("class","d3plus_edge_path")
+      .append("path")
+      .call(spline)
+      .call(init)
+      .call(style)
+      .call(label)
+
+  }
+
+}
+
+},{"../../../geom/offset.coffee":160,"../../../util/buckets.coffee":203}],226:[function(require,module,exports){
+var copy       = require("../../../util/copy.coffee"),
+    fetchColor = require("../../../core/fetch/color.coffee"),
+    fetchValue = require("../../../core/fetch/value.coffee"),
+    segments   = require("./segments.coffee"),
+    shapeStyle = require("./style.coffee");
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Draws "square" and "circle" shapes using svg:rect
+//------------------------------------------------------------------------------
+module.exports = function(vars,selection,enter,exit) {
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // The position and size of each rectangle on enter and exit.
+  //----------------------------------------------------------------------------
+  function init(nodes) {
+
+    nodes
+      .attr("x",0)
+      .attr("y",0)
+      .attr("width",0)
+      .attr("height",0);
+
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // The position and size of each rectangle on update.
+  //----------------------------------------------------------------------------
+  function update(nodes,mod) {
+    if (!mod) mod = 0;
+    nodes
+      .attr("x",function(d){
+        var w = d.d3plus.r ? d.d3plus.r*2 : d.d3plus.width;
+        return (-w/2)-(mod/2);
+      })
+      .attr("y",function(d){
+        var h = d.d3plus.r ? d.d3plus.r*2 : d.d3plus.height;
+        return (-h/2)-(mod/2);
+      })
+      .attr("width",function(d){
+        var w = d.d3plus.r ? d.d3plus.r*2 : d.d3plus.width;
+        return w+mod;
+      })
+      .attr("height",function(d){
+        var h = d.d3plus.r ? d.d3plus.r*2 : d.d3plus.height;
+        return h+mod;
+      })
+      .attr("rx",function(d){
+        var w = d.d3plus.r ? d.d3plus.r*2 : d.d3plus.width;
+        var rounded = ["circle","donut"].indexOf(vars.shape.value) >= 0;
+        return rounded ? (w+mod)/2 : 0;
+      })
+      .attr("ry",function(d){
+        var h = d.d3plus.r ? d.d3plus.r*2 : d.d3plus.height;
+        var rounded = ["circle","donut"].indexOf(vars.shape.value) >= 0;
+        return rounded ? (h+mod)/2 : 0;
+      })
+      .attr("shape-rendering",function(d){
+        if (["square"].indexOf(vars.shape.value) >= 0) {
+          return vars.shape.rendering.value;
+        }
+        else {
+          return "auto";
+        }
+      });
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // In order to correctly animate each donut's size and arcs, we need to store
+  // it's previous values in a lookup object that does not get destroyed when
+  // redrawing the visualization.
+  //----------------------------------------------------------------------------
+  if (!vars.arcs) {
+    vars.arcs = {
+      "donut": {},
+      "active": {},
+      "temp": {}
+    };
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // This is the main arc function that determines what values to use for each
+  // arc angle and radius.
+  //----------------------------------------------------------------------------
+  var arc = d3.svg.arc()
+    .startAngle(0)
+    .endAngle(function(d){
+      var a = vars.arcs[d.d3plus.shape][d.d3plus.id].a;
+      return a > Math.PI*2 ? Math.PI*2 : a;
+    })
+    .innerRadius(function(d){
+      if (!d.d3plus.static && vars.shape.value === "donut") {
+        var r = vars.arcs[d.d3plus.shape][d.d3plus.id].r;
+        return r * vars.data.donut.size;
+      }
+      else {
+        return 0;
+      }
+    })
+    .outerRadius(function(d){
+      var r = vars.arcs[d.d3plus.shape][d.d3plus.id].r;
+      return vars.shape.value === "donut" ? r : r*2;
+    });
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // This is the main "arcTween" function where all of the animation happens
+  // for each arc.
+  //----------------------------------------------------------------------------
+  function size(path,mod,rad,ang) {
+    if (!mod) mod = 0;
+    if (typeof rad != "number") rad = undefined;
+    if (typeof ang != "number") ang = undefined;
+    path.attrTween("d", function(d){
+      if (rad === undefined) var r = d.d3plus.r ? d.d3plus.r : d3.max([d.d3plus.width,d.d3plus.height]);
+      else var r = rad;
+      if (ang === undefined) var a = d.d3plus.segments[d.d3plus.shape];
+      else var a = ang;
+      if (!vars.arcs[d.d3plus.shape][d.d3plus.id]) {
+        vars.arcs[d.d3plus.shape][d.d3plus.id] = {"r": 0};
+        vars.arcs[d.d3plus.shape][d.d3plus.id].a = d.d3plus.shape === "donut" ? Math.PI * 2 : 0;
+      }
+      var radius = d3.interpolate(vars.arcs[d.d3plus.shape][d.d3plus.id].r,r+mod),
+          angle = d3.interpolate(vars.arcs[d.d3plus.shape][d.d3plus.id].a,a);
+
+      return function(t) {
+        vars.arcs[d.d3plus.shape][d.d3plus.id].r = radius(t);
+        vars.arcs[d.d3plus.shape][d.d3plus.id].a = angle(t);
+        return arc(d);
+      };
+    });
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Check each data point for active and temp data
+  //----------------------------------------------------------------------------
+  selection.each(function(d){
+
+    var active = segments(vars, d, "active"),
+        temp  = segments(vars, d, "temp"),
+        total = segments(vars, d, "total"),
+        group = d3.select(this),
+        color = fetchColor(vars,d);
+
+    var fill_data = [], hatch_data = [];
+
+    if (total && vars.types[vars.type.value].fill) {
+
+      if (temp) {
+        var c = copy(d);
+        c.d3plus.shape = "temp";
+        fill_data.push(c);
+        hatch_data = ["temp"];
+      }
+
+      if (active && (active < total || temp)) {
+        var c = copy(d);
+        c.d3plus.shape = "active";
+        fill_data.push(c);
+      }
+
+    }
+
+    function hatch_lines(l) {
+      l
+        .attr("stroke",color)
+        .attr("stroke-width",1)
+        .attr("shape-rendering",vars.shape.rendering.value);
+    }
+
+    var pattern = vars.defs.selectAll("pattern#d3plus_hatch_"+d.d3plus.id)
+      .data(hatch_data);
+
+    if (vars.draw.timing) {
+
+      pattern.selectAll("rect")
+        .transition().duration(vars.draw.timing)
+        .style("fill",color);
+
+      pattern.selectAll("line")
+        .transition().duration(vars.draw.timing)
+        .style("stroke",color);
+
+    }
+    else {
+
+      pattern.selectAll("rect").style("fill",color);
+
+      pattern.selectAll("line").style("stroke",color);
+
+    }
+
+    var pattern_enter = pattern.enter().append("pattern")
+      .attr("id","d3plus_hatch_"+d.d3plus.id)
+      .attr("patternUnits","userSpaceOnUse")
+      .attr("x","0")
+      .attr("y","0")
+      .attr("width","10")
+      .attr("height","10")
+      .append("g");
+
+    pattern_enter.append("rect")
+      .attr("x","0")
+      .attr("y","0")
+      .attr("width","10")
+      .attr("height","10")
+      .attr("fill",color)
+      .attr("fill-opacity",0.25);
+
+    pattern_enter.append("line")
+      .attr("x1","0")
+      .attr("x2","10")
+      .attr("y1","0")
+      .attr("y2","10")
+      .call(hatch_lines);
+
+    pattern_enter.append("line")
+      .attr("x1","-1")
+      .attr("x2","1")
+      .attr("y1","9")
+      .attr("y2","11")
+      .call(hatch_lines);
+
+    pattern_enter.append("line")
+      .attr("x1","9")
+      .attr("x2","11")
+      .attr("y1","-1")
+      .attr("y2","1")
+      .call(hatch_lines);
+
+    var clip_data = fill_data.length ? [d] : [];
+
+    var clip = group.selectAll("#d3plus_clip_"+d.d3plus.id)
+      .data(clip_data);
+
+    clip.enter().insert("clipPath",".d3plus_mouse")
+      .attr("id","d3plus_clip_"+d.d3plus.id)
+      .append("rect")
+      .attr("class","d3plus_clipping")
+      .call(init);
+
+    if (vars.draw.timing) {
+
+      clip.selectAll("rect").transition().duration(vars.draw.timing)
+        .call(update);
+
+      clip.exit().transition().delay(vars.draw.timing)
+        .remove();
+
+    }
+    else {
+
+      clip.selectAll("rect").call(update);
+
+      clip.exit().remove();
+
+    }
+
+    var fills = group.selectAll("path.d3plus_fill")
+      .data(fill_data);
+
+    fills.transition().duration(vars.draw.timing)
+      .call(shapeStyle,vars)
+      .call(size);
+
+    fills.enter().insert("path","rect.d3plus_mouse")
+      .attr("class","d3plus_fill")
+      .attr("clip-path","url(#d3plus_clip_"+d.d3plus.id+")")
+      .transition().duration(0)
+        .call(shapeStyle,vars)
+        .call(size,0,undefined,0)
+        .transition().duration(vars.draw.timing)
+          .call(size)
+          .call(shapeStyle,vars);
+
+    fills.exit().transition().duration(vars.draw.timing)
+      .call(size,0,undefined,0)
+      .remove();
+
+  });
+
+};
+
+},{"../../../core/fetch/color.coffee":64,"../../../core/fetch/value.coffee":68,"../../../util/copy.coffee":206,"./segments.coffee":230,"./style.coffee":231}],227:[function(require,module,exports){
+var copy       = require("../../../util/copy.coffee"),
+    fetchText  = require("../../../core/fetch/text.js"),
+    fetchValue = require("../../../core/fetch/value.coffee"),
+    mix        = require("../../../color/mix.coffee"),
+    print      = require("../../../core/console/print.coffee"),
+    rtl        = require("../../../client/rtl.coffee"),
+    segments   = require("./segments.coffee"),
+    shapeColor = require("./color.coffee"),
+    stringList = require("../../../string/list.coffee"),
+    textColor  = require("../../../color/text.coffee"),
+    textWrap   = require("../../../textwrap/textwrap.coffee");
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Draws "labels" using svg:text and d3plus.textwrap
+//------------------------------------------------------------------------------
+module.exports = function( vars , group ) {
+
+  var scale = vars.types[vars.type.value].zoom ? vars.zoom.behavior.scaleExtent() : [1,1],
+              selection = vars.g[ group ].selectAll("g");
+
+  var opacity = function(elem) {
+
+    elem
+      .attr("opacity",function(d){
+        // if (vars.draw.timing) return 1;
+        var size = parseFloat(d3.select(this).attr("font-size"),10);
+        d.visible = size * (vars.zoom.scale/scale[1]) >= 2;
+        return d.visible ? 1 : 0;
+      });
+
+  };
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Label Exiting
+  //----------------------------------------------------------------------------
+  remove = function(text) {
+
+    if (vars.draw.timing) {
+      text
+        .transition().duration(vars.draw.timing)
+        .attr("opacity",0)
+        .remove();
+    }
+    else {
+      text.remove();
+    }
+
+  };
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Label Styling
+  //----------------------------------------------------------------------------
+  style = function(text) {
+
+    var salign = vars.labels.valign.value === "bottom" ? "top" : "bottom";
+
+    text
+      .attr("font-weight",vars.labels.font.weight)
+      .attr("font-family",vars.labels.font.family.value)
+      .attr("pointer-events",function(t){
+        return t.mouse ? "auto": "none";
+      })
+      .attr("fill", function(t){
+
+        if ( t.color ) return t.color;
+
+        var color = shapeColor(t.parent,vars),
+            legible = textColor(color),
+            opacity = t.text ? 0.15 : 1;
+
+        return mix( color , legible , 0.2 , opacity );
+
+      })
+      .each(function(t){
+
+        if (t.resize instanceof Array) {
+          var min = t.resize[0], max = t.resize[1];
+        }
+
+        var size = t.resize, resize = true;
+
+        if (t.text) {
+
+          if ( !(size instanceof Array) ) {
+            size = [9, 50];
+            resize = t.resize;
+          }
+
+          var y = t.y - t.h*scale[1]/2 + t.padding/2;
+          if (salign === "bottom") y += (t.h * scale[1])/2;
+
+          textWrap()
+            .align("center")
+            .container(d3.select(this))
+            .height((t.h * scale[1])/2)
+            .padding(t.padding/2)
+            .resize(resize)
+            .size(size)
+            .text(vars.format.value(t.text*100,{"key": "share", "vars": vars}))
+            .width(t.w * scale[1])
+            .valign(salign)
+            .x(t.x - t.w*scale[1]/2 + t.padding/2)
+            .y(y)
+            .draw();
+
+        }
+        else {
+
+          if ( !(t.resize instanceof Array) ) {
+            size = [7, 40*(scale[1]/scale[0])];
+            resize = t.resize;
+          }
+
+          var yOffset = vars.labels.valign.value === "bottom" ? t.share : 0;
+
+          textWrap()
+            .align(t.anchor || vars.labels.align.value)
+            .container( d3.select(this) )
+            .height(t.h * scale[1] - t.share)
+            .padding(t.padding/2)
+            .resize( resize )
+            .size( size )
+            .shape(t.shape || "square")
+            .text( t.names )
+            .valign(vars.labels.valign.value)
+            .width(t.w * scale[1])
+            .x(t.x - t.w*scale[1]/2 + t.padding/2)
+            .y(t.y - t.h*scale[1]/2 + t.padding/2 + yOffset)
+            .draw();
+
+        }
+
+      })
+      .attr("transform",function(t){
+        var translate = d3.select(this).attr("transform") || "";
+        var a = t.angle || 0,
+            x = t.translate && t.translate.x ? t.translate.x : 0,
+            y = t.translate && t.translate.y ? t.translate.y : 0;
+
+        if (translate.length) {
+          translate = translate.split(")").slice(-3).join(")");
+        }
+        return "rotate("+a+","+x+","+y+")scale("+1/scale[1]+")translate("+(t.x*scale[1]-t.x)+","+(t.y*scale[1]-t.y)+")" + translate;
+
+      });
+
+  };
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Loop through each selection and analyze the labels
+  //----------------------------------------------------------------------------
+  if (group === "edges" || vars.labels.value) {
+
+    if ( vars.dev.value ) {
+      var timerString = "drawing " + group + " labels";
+      print.time( timerString );
+    }
+
+    selection.each(function(d){
+
+      var disabled = d.d3plus && "label" in d.d3plus && !d.d3plus.label,
+          label = d.d3plus_label || null,
+          share = d.d3plus_share,
+          names = d.d3plus.text ? d.d3plus.text :
+                  label && label.names ? label.names :
+                  vars.labels.text.value ?
+                  fetchValue(vars, d, vars.labels.text.value) :
+                  fetchText(vars,d),
+          group = label && "group" in label ? label.group : d3.select(this),
+          share_size = 0,
+          fill = vars.types[vars.type.value].fill;
+
+      if (!(names instanceof Array)) names = [names];
+
+      if (label) {
+
+        if (["line","area"].indexOf(vars.shape.value) >= 0) {
+          var background = true;
+        }
+        else if (d && "d3plus" in d) {
+          var active = segments(vars, d, "active"),
+              temp   = segments(vars, d, "temp"),
+              total  = segments(vars, d, "total"),
+              background = (!temp && !active) || (active >= total) || (!active && temp >= total);
+        }
+
+      }
+
+      if (!disabled && ((label && label.force) || background || !fill)) {
+
+        if (share && d.d3plus.share && share.w-vars.labels.padding*2 >= 10 && share.h-vars.labels.padding*2 >= 10 && vars.labels.valign.value != "middle") {
+
+          share.resize = vars.labels.resize.value === false ? false :
+            share && "resize" in share ? share.resize : true;
+
+          share.padding = vars.labels.padding;
+
+          share.text = d.d3plus.share;
+          share.parent = d;
+
+          var text = group.selectAll("text#d3plus_share_"+d.d3plus.id)
+            .data([share],function(t){
+              return t.w+""+t.h+""+t.text;
+            });
+
+          if (vars.draw.timing && vars.zoom.scale === 1) {
+
+            text
+              .transition().duration(vars.draw.timing/2)
+              .call(style);
+
+            text.enter().append("text")
+              .attr("id","d3plus_share_"+d.d3plus.id)
+              .attr("class","d3plus_share")
+              .attr("opacity",0)
+              .call(style)
+              .transition().duration(vars.draw.timing/2)
+              .delay(vars.draw.timing/2)
+              .attr("opacity",1);
+
+          }
+          else {
+
+            text
+              .attr("opacity",1)
+              .call(style);
+
+            text.enter().append("text")
+              .attr("id","d3plus_share_"+d.d3plus.id)
+              .attr("class","d3plus_share")
+              .attr("opacity",1)
+              .call(style);
+
+          }
+
+          share_size = text.node().getBBox().height + vars.labels.padding;
+
+          text.exit().call(remove);
+
+        }
+        else {
+          group.selectAll("text.d3plus_share")
+            .call(remove);
+        }
+
+        if (label) {
+
+          label.resize = vars.labels.resize.value === false ? false :
+            label && "resize" in label ? label.resize : true;
+
+          label.padding = typeof label.padding === "number" ? label.padding : vars.labels.padding;
+
+        }
+
+        if (label && label.w*scale[1]-label.padding >= 20 && label.h*scale[1]-label.padding >= 10 && names.length) {
+
+          var and = vars.format.locale.value.ui.and,
+              more = vars.format.locale.value.ui.more;
+
+          for (var i = 0; i < names.length; i++) {
+            if (names[i] instanceof Array) {
+              names[i] = stringList(names[i],and,3,more);
+            }
+          }
+
+          label.names = names;
+
+          label.share = share_size;
+          label.parent = d;
+
+          var text = group.selectAll("text#d3plus_label_"+d.d3plus.id)
+            .data([label],function(t){
+              if (!t) return false;
+              return t.w+"_"+t.h+"_"+t.x+"_"+t.y+"_"+t.names.join("_");
+            }), fontSize = label.resize ? undefined :
+                           (vars.labels.font.size * scale[0]) + "px";
+
+          if (vars.draw.timing && vars.zoom.scale === 1) {
+
+            text
+              .transition().duration(vars.draw.timing/2)
+              .call(style)
+              .call(opacity);
+
+            text.enter().append("text")
+              .attr("font-size",fontSize)
+              .attr("id","d3plus_label_"+d.d3plus.id)
+              .attr("class","d3plus_label")
+              .attr("opacity",0)
+              .call(style)
+              .transition().duration(vars.draw.timing/2)
+                .delay(vars.draw.timing/2)
+                .call(opacity);
+
+          }
+          else {
+
+            text
+              .attr("opacity",1)
+              .call(style)
+              .call(opacity);
+
+            text.enter().append("text")
+              .attr("font-size",fontSize)
+              .attr("id","d3plus_label_"+d.d3plus.id)
+              .attr("class","d3plus_label")
+              .call(style)
+              .call(opacity);
+
+          }
+
+          text.exit().call(remove);
+
+          if (text.size() === 0 || text.selectAll("tspan").size() === 0) {
+            delete d.d3plus_label;
+            d3.select(this).selectAll("text#d3plus_label_"+d.d3plus.id+", rect#d3plus_label_bg_"+d.d3plus.id)
+              .call(remove);
+            vars.g.labels.selectAll("text#d3plus_label_"+d.d3plus.id+", rect#d3plus_label_bg_"+d.d3plus.id)
+              .call(remove);
+          }
+          else {
+
+            if (label.background) {
+
+              var background_data = ["background"];
+
+              var bounds = copy(text.node().getBBox());
+              bounds.width += vars.labels.padding*scale[0];
+              bounds.height += vars.labels.padding*scale[0];
+              bounds.x -= (vars.labels.padding*scale[0])/2;
+              bounds.y -= (vars.labels.padding*scale[0])/2;
+              var t = text.attr("transform").split(")");
+              bounds.y += parseFloat(t[t.length-2].split(",")[1]);
+
+            }
+            else {
+              var background_data = [],
+                  bounds = {};
+            }
+
+            var bg = group.selectAll("rect#d3plus_label_bg_"+d.d3plus.id)
+                       .data(background_data),
+                bg_opacity = typeof label.background === "number" ?
+                             label.background :
+                             typeof label.background === "string" ? 1 : 0.6;
+
+            function bg_style(elem) {
+
+              var color = typeof label.background === "string" ? label.background : vars.background.value === "none"
+                        ? "#ffffff" : vars.background.value
+                , fill = typeof label.background === "string"
+                       ? label.background : color
+                , transform = text.attr("transform").split(")");
+              transform.pop();
+              transform.pop();
+              transform.push("");
+              transform = transform.join(")");
+
+              elem
+                .attr("fill",fill)
+                .attr(bounds)
+                .attr("transform",transform);
+
+            }
+
+            if (vars.draw.timing) {
+
+              bg.exit().transition().duration(vars.draw.timing)
+                .attr("opacity",0)
+                .remove();
+
+              bg.transition().duration(vars.draw.timing)
+                .attr("opacity",bg_opacity)
+                .call(bg_style);
+
+              bg.enter().insert("rect",".d3plus_label")
+                .attr("id","d3plus_label_bg_"+d.d3plus.id)
+                .attr("class","d3plus_label_bg")
+                .attr("opacity",0)
+                .call(bg_style)
+                .transition().duration(vars.draw.timing)
+                  .attr("opacity",bg_opacity);
+
+            }
+            else {
+
+              bg.exit().remove();
+
+              bg.enter().insert("rect",".d3plus_label")
+                .attr("id","d3plus_label_bg_"+d.d3plus.id)
+                .attr("class","d3plus_label_bg");
+
+              bg.attr("opacity",bg_opacity)
+                .call(bg_style);
+
+            }
+
+          }
+
+        }
+        else {
+          delete d.d3plus_label;
+          d3.select(this).selectAll("text#d3plus_label_"+d.d3plus.id+", rect#d3plus_label_bg_"+d.d3plus.id)
+            .call(remove);
+          vars.g.labels.selectAll("text#d3plus_label_"+d.d3plus.id+", rect#d3plus_label_bg_"+d.d3plus.id)
+            .call(remove);
+        }
+
+      }
+      else {
+        delete d.d3plus_label;
+        d3.select(this).selectAll("text#d3plus_label_"+d.d3plus.id+", rect#d3plus_label_bg_"+d.d3plus.id)
+          .call(remove);
+        vars.g.labels.selectAll("text#d3plus_label_"+d.d3plus.id+", rect#d3plus_label_bg_"+d.d3plus.id)
+          .call(remove);
+      }
+    });
+
+    if ( vars.dev.value ) print.timeEnd( timerString );
+
+  }
+  else {
+
+    if ( vars.dev.value ) {
+      var timerString = "removing " + group + " labels";
+      print.time( timerString );
+    }
+
+    selection.selectAll("text.d3plus_label, rect.d3plus_label_bg")
+      .call(remove);
+
+    vars.g.labels.selectAll("text.d3plus_label, rect.d3plus_label_bg")
+      .call(remove);
+
+    if ( vars.dev.value ) print.timeEnd( timerString );
+
+  }
+}
+
+},{"../../../client/rtl.coffee":42,"../../../color/mix.coffee":47,"../../../color/text.coffee":51,"../../../core/console/print.coffee":53,"../../../core/fetch/text.js":67,"../../../core/fetch/value.coffee":68,"../../../string/list.coffee":173,"../../../textwrap/textwrap.coffee":199,"../../../util/copy.coffee":206,"./color.coffee":219,"./segments.coffee":230}],228:[function(require,module,exports){
+var copy       = require("../../../util/copy.coffee"),
+    closest    = require("../../../util/closest.coffee"),
+    events     = require("../../../client/pointer.coffee"),
+    shapeStyle = require("./style.coffee"),
+    fetchValue = require("../../../core/fetch/value.coffee");
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Draws "line" shapes using svg:line
+//------------------------------------------------------------------------------
+module.exports = function(vars,selection,enter,exit) {
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // The D3 line function that determines what variables to use for x and y
+  // positioning, as well as line interpolation defined by the user.
+  //----------------------------------------------------------------------------
+  var line = d3.svg.line()
+    .x(function(d){ return d.d3plus.x; })
+    .y(function(d){ return d.d3plus.y; })
+    .interpolate(vars.shape.interpolate.value);
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Divide each line into it's segments. We do this so that there can be gaps
+  // in the line and mouseover.
+  //
+  // Then, create new data group from values to become small nodes at each
+  // point on the line.
+  //----------------------------------------------------------------------------
+
+  var stroke = vars.data.stroke.width * 2,
+      hitarea = stroke < 15 ? 15 : stroke,
+      discrete = vars[vars.axes.discrete];
+
+  var ticks = discrete.ticks.values.map(function(d){
+    if (d.constructor === Date) return d.getTime();
+    else return d;
+  });
+
+  selection.each(function(d){
+
+    var lastIndex = false,
+        segments = [],
+        nodes = [],
+        temp = copy(d),
+        group = d3.select(this);
+
+    temp.values = [];
+    temp.segment_key = temp.key;
+    d.values.forEach(function(v,i,arr){
+
+      var k = fetchValue(vars, v, discrete.value);
+
+      if (k.constructor === Date) k = k.getTime();
+
+      var index = ticks.indexOf(closest(ticks,k));
+
+      if (lastIndex === false || lastIndex === index - 1) {
+        temp.values.push(v);
+        temp.segment_key += "_" + index;
+      }
+      else {
+        if (temp.values.length > 1) {
+          segments.push(temp);
+        }
+        else {
+          nodes.push(temp.values[0]);
+        }
+        temp = copy(d);
+        temp.values = [v];
+      }
+
+      if ( i === arr.length - 1 ) {
+        if (temp.values.length > 1) {
+          segments.push(temp);
+        }
+        else {
+          nodes.push(temp.values[0]);
+        }
+      }
+
+      lastIndex = index;
+
+    });
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Bind segment data to "paths"
+    //--------------------------------------------------------------------------
+    var paths = group.selectAll("path.d3plus_line")
+      .data(segments, function(d){
+        if (!d.d3plus) d.d3plus = {};
+        d.d3plus.shape = "line";
+        return d.segment_key;
+      });
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Bind node data to "rects"
+    //--------------------------------------------------------------------------
+    var rects = group.selectAll("rect.d3plus_anchor")
+      .data(nodes, function(d){
+        if (!d.d3plus) d.d3plus = {};
+        d.d3plus.r = vars.data.stroke.width * 2;
+        return d.d3plus.id;
+      });
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // "paths" and "rects" Enter/Update
+    //--------------------------------------------------------------------------
+    if (vars.draw.timing) {
+
+      paths.exit().transition().duration(vars.draw.timing)
+        .attr("opacity", 0)
+        .remove();
+
+      paths.transition().duration(vars.draw.timing)
+        .attr("d",function(d){ return line(d.values); })
+        .call(shapeStyle,vars);
+
+      paths.enter().append("path")
+        .attr("class","d3plus_line")
+        .style("stroke-linecap","round")
+        .attr("d", function(d){ return line(d.values); })
+        .call(shapeStyle,vars)
+        .attr("opacity", 0)
+        .transition().duration(vars.draw.timing)
+          .attr("opacity", 1);
+
+      rects.enter().append("rect")
+        .attr("class","d3plus_anchor")
+        .attr("id",function(d){ return d.d3plus.id; })
+        .call(init)
+        .call(shapeStyle,vars);
+
+      rects.transition().duration(vars.draw.timing)
+        .call(update)
+        .call(shapeStyle,vars);
+
+      rects.exit().transition().duration(vars.draw.timing)
+        .call(init)
+        .remove();
+
+    }
+    else {
+
+      paths.exit().remove();
+
+      paths.enter().append("path")
+        .attr("class","d3plus_line")
+        .style("stroke-linecap","round");
+
+      paths
+        .attr("d",function(d){ return line(d.values); })
+        .call(shapeStyle,vars);
+
+      rects.enter().append("rect")
+        .attr("class","d3plus_anchor")
+        .attr("id",function(d){
+          return d.d3plus.id;
+        });
+
+      rects.exit().remove();
+
+      rects.call(update)
+        .call(shapeStyle,vars);
+
+    }
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Create mouse event lines
+    //--------------------------------------------------------------------------
+    var mouse = group.selectAll("path.d3plus_mouse")
+      .data(segments, function(d){
+        return d.segment_key;
+      });
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Mouse "paths" Enter
+    //--------------------------------------------------------------------------
+    mouse.enter().append("path")
+      .attr("class","d3plus_mouse")
+      .attr("d", function(l){ return line(l.values); })
+      .style("stroke","black")
+      .style("stroke-width",hitarea)
+      .style("fill","none")
+      .style("stroke-linecap","round")
+      .attr("opacity",0);
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Mouse "paths" Update
+    //--------------------------------------------------------------------------
+    mouse
+      .on(events.over,function(m){
+        if (!vars.draw.frozen) mouseStyle(vars, this, stroke, 2);
+      })
+      .on(events.out,function(d){
+        if (!vars.draw.frozen) mouseStyle(vars, this, stroke, 0);
+      });
+
+    if (vars.draw.timing) {
+
+      mouse.transition().duration(vars.draw.timing)
+        .attr("d",function(l){ return line(l.values); })
+        .style("stroke-width",hitarea);
+
+    }
+    else {
+
+      mouse.attr("d",function(l){ return line(l.values); })
+        .style("stroke-width",hitarea);
+
+    }
+
+    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    // Mouse "paths" Exit
+    //--------------------------------------------------------------------------
+    mouse.exit().remove();
+
+  });
+
+};
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// The position and size of each anchor point on enter and exit.
+//----------------------------------------------------------------------------
+function init(n) {
+
+  n
+    .attr("x",function(d){
+      return d.d3plus.x;
+    })
+    .attr("y",function(d){
+      return d.d3plus.y;
+    })
+    .attr("width",0)
+    .attr("height",0);
+
+}
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// The position and size of each anchor point on update.
+//----------------------------------------------------------------------------
+function update(n,mod) {
+
+  if (mod === undefined) mod = 0;
+
+  n
+    .attr("x",function(d){
+      var w = d.d3plus.r ? d.d3plus.r*2 : d.d3plus.width;
+      return d.d3plus.x - ((w/2)+(mod/2));
+    })
+    .attr("y",function(d){
+      var h = d.d3plus.r ? d.d3plus.r*2 : d.d3plus.height;
+      return d.d3plus.y - ((h/2)+(mod/2));
+    })
+    .attr("width",function(d){
+      var w = d.d3plus.r ? d.d3plus.r*2 : d.d3plus.width;
+      return w+mod;
+    })
+    .attr("height",function(d){
+      var h = d.d3plus.r ? d.d3plus.r*2 : d.d3plus.height;
+      return h+mod;
+    })
+    .attr("rx",function(d){
+      var w = d.d3plus.r ? d.d3plus.r*2 : d.d3plus.width;
+      return (w+mod)/2;
+    })
+    .attr("ry",function(d){
+      var h = d.d3plus.r ? d.d3plus.r*2 : d.d3plus.height;
+      return (h+mod)/2;
+    });
+
+}
+
+function mouseStyle(vars, elem, stroke, mod) {
+
+  var timing = vars.draw.timing ? vars.timing.mouseevents : 0;
+  var pathWidth = mod ? stroke * mod : stroke;
+
+  if (timing) {
+
+    d3.select(elem.parentNode).selectAll("path.d3plus_line")
+    .transition().duration(timing)
+    .style("stroke-width",pathWidth);
+
+    d3.select(elem.parentNode).selectAll("rect")
+    .transition().duration(timing)
+    .style("stroke-width",stroke)
+    .call(update, mod);
+
+  }
+  else {
+
+    d3.select(elem.parentNode).selectAll("path.d3plus_line")
+    .style("stroke-width",pathWidth);
+
+    d3.select(elem.parentNode).selectAll("rect")
+    .style("stroke-width",stroke)
+    .call(update, mod);
+  }
+
+}
+
+},{"../../../client/pointer.coffee":40,"../../../core/fetch/value.coffee":68,"../../../util/closest.coffee":205,"../../../util/copy.coffee":206,"./style.coffee":231}],229:[function(require,module,exports){
+var shapeStyle;
+
+shapeStyle = require("./style.coffee");
+
+module.exports = function(vars, selection, enter, exit) {
+  var data, init, update;
+  data = function(d) {
+    var h, w;
+    if (vars.labels.value && !d.d3plus.label) {
+      w = (d.d3plus.r ? d.d3plus.r * 2 : d.d3plus.width);
+      h = (d.d3plus.r ? d.d3plus.r * 2 : d.d3plus.height);
+      d.d3plus_label = {
+        w: w,
+        h: h,
+        x: 0,
+        y: 0
+      };
+      d.d3plus_share = {
+        w: w,
+        h: h,
+        x: 0,
+        y: 0
+      };
+      d.d3plus_label.shape = (d.d3plus.shape === "circle" ? "circle" : "square");
+    } else if (d.d3plus.label) {
+      d.d3plus_label = d.d3plus.label;
+    } else {
+      delete d.d3plus_label;
+    }
+    return [d];
+  };
+  init = function(nodes) {
+    return nodes.attr("x", function(d) {
+      if (d.d3plus.init && "x" in d.d3plus.init) {
+        return d.d3plus.init.x;
+      } else {
+        if (d.d3plus.init && "width" in d.d3plus.init) {
+          return -d.d3plus.width / 2;
+        } else {
+          return 0;
+        }
+      }
+    }).attr("y", function(d) {
+      if (d.d3plus.init && "y" in d.d3plus.init) {
+        return d.d3plus.init.y;
+      } else {
+        if (d.d3plus.init && "height" in d.d3plus.init) {
+          return -d.d3plus.height / 2;
+        } else {
+          return 0;
+        }
+      }
+    }).attr("width", function(d) {
+      if (d.d3plus.init && "width" in d.d3plus.init) {
+        return d.d3plus.init.width;
+      } else {
+        return 0;
+      }
+    }).attr("height", function(d) {
+      if (d.d3plus.init && "height" in d.d3plus.init) {
+        return d.d3plus.init.height;
+      } else {
+        return 0;
+      }
+    });
+  };
+  update = function(nodes) {
+    return nodes.attr("x", function(d) {
+      var w;
+      w = d.d3plus.r ? d.d3plus.r * 2 : d.d3plus.width;
+      return -w / 2;
+    }).attr("y", function(d) {
+      var h;
+      h = d.d3plus.r ? d.d3plus.r * 2 : d.d3plus.height;
+      return -h / 2;
+    }).attr("width", function(d) {
+      if (d.d3plus.r) {
+        return d.d3plus.r * 2;
+      } else {
+        return d.d3plus.width;
+      }
+    }).attr("height", function(d) {
+      if (d.d3plus.r) {
+        return d.d3plus.r * 2;
+      } else {
+        return d.d3plus.height;
+      }
+    }).attr("rx", function(d) {
+      var rounded, w;
+      rounded = d.d3plus.shape === "circle";
+      w = d.d3plus.r ? d.d3plus.r * 2 : d.d3plus.width;
+      if (rounded) {
+        return (w + 2) / 2;
+      } else {
+        return 0;
+      }
+    }).attr("ry", function(d) {
+      var h, rounded;
+      rounded = d.d3plus.shape === "circle";
+      h = d.d3plus.r ? d.d3plus.r * 2 : d.d3plus.height;
+      if (rounded) {
+        return (h + 2) / 2;
+      } else {
+        return 0;
+      }
+    }).attr("transform", function(d) {
+      if ("rotate" in d.d3plus) {
+        return "rotate(" + d.d3plus.rotate + ")";
+      } else {
+        return "";
+      }
+    }).attr("shape-rendering", function(d) {
+      if (d.d3plus.shape === "square" && (!("rotate" in d.d3plus))) {
+        return vars.shape.rendering.value;
+      } else {
+        return "auto";
+      }
+    });
+  };
+  if (vars.draw.timing) {
+    enter.append("rect").attr("class", "d3plus_data").call(init).call(shapeStyle, vars);
+    selection.selectAll("rect.d3plus_data").data(data).transition().duration(vars.draw.timing).call(update).call(shapeStyle, vars);
+    return exit.selectAll("rect.d3plus_data").transition().duration(vars.draw.timing).call(init);
+  } else {
+    enter.append("rect").attr("class", "d3plus_data");
+    return selection.selectAll("rect.d3plus_data").data(data).call(update).call(shapeStyle, vars);
+  }
+};
+
+
+},{"./style.coffee":231}],230:[function(require,module,exports){
+var fetchValue;
+
+fetchValue = require("../../../core/fetch/value.coffee");
+
+module.exports = function(vars, d, segment) {
+  var ret;
+  ret = vars[segment].value;
+  if (ret) {
+    if (segment in d.d3plus) {
+      return d.d3plus[segment];
+    } else {
+      return fetchValue(vars, d, ret);
+    }
+  } else {
+    return d.d3plus[segment];
+  }
+};
+
+
+},{"../../../core/fetch/value.coffee":68}],231:[function(require,module,exports){
+var color, ie;
+
+color = require("./color.coffee");
+
+ie = require("../../../client/ie.js");
+
+module.exports = function(nodes, vars) {
+  return nodes.attr("fill", function(d) {
+    if (d.d3plus && d.d3plus.spline) {
+      return "none";
+    } else {
+      return color(d, vars);
+    }
+  }).style("stroke", function(d) {
+    var c;
+    if (d.d3plus && d.d3plus.stroke) {
+      return d.d3plus.stroke;
+    } else {
+      c = d.values ? color(d.values[0], vars) : color(d, vars, true);
+      return d3.rgb(c).darker(0.6);
+    }
+  }).style("stroke-width", function(d) {
+    var mod;
+    if (ie && vars.types[vars.type.value].zoom) {
+      return 0;
+    }
+    mod = d.d3plus.shape === "line" ? 2 : 1;
+    return vars.data.stroke.width * mod;
+  }).attr("opacity", vars.data.opacity).attr("vector-effect", "non-scaling-stroke");
+};
+
+
+},{"../../../client/ie.js":39,"./color.coffee":219}],232:[function(require,module,exports){
+var shapeStyle  = require("./style.coffee")
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Draws "square" and "circle" shapes using svg:rect
+//------------------------------------------------------------------------------
+module.exports = function(vars,selection,enter,exit) {
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Initialize check scale on enter and exit.
+  //----------------------------------------------------------------------------
+  function init(paths){
+    paths.attr("d", d3.svg.symbol().type("triangle-down").size(10))
+  }
+  
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Change scale of check on update.
+  //---------------------------------------------------------------------------
+  function update(paths){
+    paths.attr("d", d3.svg.symbol().type("triangle-down").size(function(d){
+      var smaller_dim = Math.min(d.d3plus.width, d.d3plus.height);
+      return d3.scale.pow().exponent(2)(smaller_dim/2);
+    }))
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // "paths" Enter
+  //----------------------------------------------------------------------------
+  enter.append("path").attr("class","d3plus_data")
+    .call(init)
+    .call(shapeStyle,vars)
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // "paths" Update
+  //----------------------------------------------------------------------------
+  selection.selectAll("path.d3plus_data")
+    .data(function(d) {
+      return [d];
+    })
+
+  if (vars.draw.timing) {
+    selection.selectAll("path.d3plus_data")
+      .transition().duration(vars.draw.timing)
+        .call(update)
+        .call(shapeStyle,vars)
+  }
+  else {
+    selection.selectAll("path.d3plus_data")
+      .call(update)
+      .call(shapeStyle,vars)
+  }
+
+}
+
+},{"./style.coffee":231}],233:[function(require,module,exports){
+var shapeStyle  = require("./style.coffee")
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Draws "square" and "circle" shapes using svg:rect
+//------------------------------------------------------------------------------
+module.exports = function(vars,selection,enter,exit) {
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Initialize check scale on enter and exit.
+  //----------------------------------------------------------------------------
+  function init(paths){
+    paths.attr("d", d3.svg.symbol().type("triangle-up").size(10))
+  }
+  
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Change scale of check on update.
+  //---------------------------------------------------------------------------
+  function update(paths){
+    paths.attr("d", d3.svg.symbol().type("triangle-up").size(function(d){
+      var smaller_dim = Math.min(d.d3plus.width, d.d3plus.height);
+      return d3.scale.pow().exponent(2)(smaller_dim/2);
+    }))
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // "paths" Enter
+  //----------------------------------------------------------------------------
+  enter.append("path").attr("class","d3plus_data")
+    .call(init)
+    .call(shapeStyle,vars)
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // "paths" Update
+  //----------------------------------------------------------------------------
+  selection.selectAll("path.d3plus_data")
+    .data(function(d) {
+      return [d];
+    })
+
+  if (vars.draw.timing) {
+    selection.selectAll("path.d3plus_data")
+      .transition().duration(vars.draw.timing)
+        .call(update)
+        .call(shapeStyle,vars)
+  }
+  else {
+    selection.selectAll("path.d3plus_data")
+      .call(update)
+      .call(shapeStyle,vars)
+  }
+
+}
+
+},{"./style.coffee":231}],234:[function(require,module,exports){
+module.exports = function(vars, selection, enter, exit) {
+  var d, data, init, marker, orient, pos, position, size, style;
+  data = function(d) {
+    if (d.d3plus.text) {
+      d.d3plus_label = {
+        w: size,
+        h: size,
+        x: 0,
+        y: 0,
+        background: "#fff",
+        resize: false,
+        angle: ["left", "right"].indexOf(d.d3plus.position) >= 0 ? 90 : 0
+      };
+    } else if (d.d3plus.label) {
+      d.d3plus_label = d.d3plus.label;
+    } else {
+      delete d.d3plus_label;
+    }
+    return [d];
+  };
+  style = function(line) {
+    return line.style("stroke-width", vars.data.stroke.width).style("stroke", "#444").attr("fill", "none").attr("shape-rendering", vars.shape.rendering.value);
+  };
+  init = function(line) {
+    return line.attr("x1", 0).attr("x2", 0).attr("y1", 0).attr("y2", 0);
+  };
+  position = function(line) {
+    return line.attr("x1", function(d) {
+      var offset, w, x;
+      if (["top", "bottom"].indexOf(d.d3plus.position) >= 0) {
+        return 0;
+      } else {
+        offset = d.d3plus.offset || 0;
+        w = d.d3plus.width || 0;
+        x = offset < 0 ? -w : w;
+        return x + offset;
+      }
+    }).attr("x2", function(d) {
+      if (["top", "bottom"].indexOf(d.d3plus.position) >= 0) {
+        return 0;
+      } else {
+        return d.d3plus.offset || 0;
+      }
+    }).attr("y1", function(d) {
+      var h, offset, y;
+      if (["left", "right"].indexOf(d.d3plus.position) >= 0) {
+        return 0;
+      } else {
+        offset = d.d3plus.offset || 0;
+        h = d.d3plus.height || 0;
+        y = offset < 0 ? -h : h;
+        return y + offset;
+      }
+    }).attr("y2", function(d) {
+      if (["left", "right"].indexOf(d.d3plus.position) >= 0) {
+        return 0;
+      } else {
+        return d.d3plus.offset || 0;
+      }
+    }).attr("marker-start", "url(#d3plus_whisker_marker)");
+  };
+  marker = vars.defs.selectAll("#d3plus_whisker_marker").data([0]);
+  marker.enter().append("marker").attr("id", "d3plus_whisker_marker").attr("markerUnits", "userSpaceOnUse").style("overflow", "visible").append("line");
+  d = selection.datum();
+  if (d) {
+    pos = d.d3plus.position;
+    orient = ["top", "bottom"].indexOf(pos) >= 0 ? "horizontal" : "vertical";
+    size = orient === "horizontal" ? d.d3plus.width : d.d3plus.height;
+  } else {
+    orient = "horizontal";
+    size = 0;
+  }
+  marker.select("line").attr("x1", orient === "horizontal" ? -size / 2 : 0).attr("x2", orient === "horizontal" ? size / 2 : 0).attr("y1", orient === "vertical" ? -size / 2 : 0).attr("y2", orient === "vertical" ? size / 2 : 0).call(style).style("stroke-width", vars.data.stroke.width * 2);
+  if (vars.draw.timing) {
+    enter.append("line").attr("class", "d3plus_data").call(style).call(init);
+    selection.selectAll("line.d3plus_data").data(data).transition().duration(vars.draw.timing).call(style).call(position);
+    exit.selectAll("line.d3plus_data").transition().duration(vars.draw.timing).call(init);
+  } else {
+    enter.append("line").attr("class", "d3plus_data");
+    selection.selectAll("line.d3plus_data").data(data).call(style).call(position);
+  }
+};
+
+
+},{}],235:[function(require,module,exports){
+var events = require("../../../client/pointer.coffee"),
+    prefix     = require("../../../client/prefix.coffee"),
+    print      = require("../../../core/console/print.coffee"),
+    touch      = require("../../../client/touch.coffee"),
+    touchEvent = require("../zoom/propagation.coffee");
+
+// Enter SVG Elements
+module.exports = function(vars) {
+
+  if ( vars.dev.value ) print.time("creating SVG elements");
+
+  // Enter SVG
+  vars.svg = vars.container.value.selectAll("svg#d3plus").data([0]);
+  vars.svg.enter().insert("svg","#d3plus_message")
+    .attr("id","d3plus")
+    .attr("width",vars.width.value)
+    .attr("height",vars.height.value)
+    .attr("xmlns","http://www.w3.org/2000/svg")
+    .attr("xmlns:xmlns:xlink","http://www.w3.org/1999/xlink");
+
+  // Enter BG Rectangle
+  vars.g.bg = vars.svg.selectAll("rect#bg").data(["bg"]);
+  vars.g.bg.enter().append("rect")
+    .attr("id","bg")
+    .attr("fill",vars.background.value)
+    .attr("width",vars.width.value)
+    .attr("height",vars.height.value);
+
+  // Enter Timeline Group
+  vars.g.timeline = vars.svg.selectAll("g#timeline").data(["timeline"]);
+  vars.g.timeline.enter().append("g")
+    .attr("id","timeline")
+    .attr("transform","translate(0,"+vars.height.value+")");
+
+  // Enter Key Group
+  vars.g.legend = vars.svg.selectAll("g#key").data(["key"]);
+  vars.g.legend.enter().append("g")
+    .attr("id","key")
+    .attr("transform","translate(0,"+vars.height.value+")");
+
+  // Enter Footer Group
+  vars.g.footer = vars.svg.selectAll("g#footer").data(["footer"]);
+  vars.g.footer.enter().append("g")
+    .attr("id","footer")
+    .attr("transform","translate(0,"+vars.height.value+")");
+
+  // Enter App Clipping Mask
+  var clipID = "clipping_" + vars.container.id;
+  vars.g.clipping = vars.svg.selectAll("#clipping").data(["clipping"]);
+  vars.g.clipping.enter().append("clipPath")
+    .attr("id", clipID)
+    .append("rect")
+      .attr("width",vars.width.viz)
+      .attr("height",vars.height.viz);
+
+  // Enter Container Group
+  vars.g.container = vars.svg.selectAll("g#container").data(["container"]);
+  vars.g.container.enter().append("g")
+    .attr("id","container")
+    .attr("clip-path","url(#" + clipID + ")")
+    .attr("transform","translate("+vars.margin.left+","+vars.margin.top+")");
+
+  // Enter Zoom Group
+  vars.g.zoom = vars.g.container.selectAll("g#zoom").data(["zoom"]);
+  vars.g.zoom.enter().append("g")
+    .attr("id","zoom");
+
+  // Enter App Background Group
+  vars.g.viz = vars.g.zoom.selectAll("g#d3plus_viz").data(["d3plus_viz"]);
+  vars.g.viz.enter().append("g")
+    .attr("id","d3plus_viz");
+
+  // Enter App Overlay Rect
+  vars.g.overlay = vars.g.viz.selectAll("rect#d3plus_overlay").data([{"id":"d3plus_overlay"}]);
+  vars.g.overlay.enter().append("rect")
+    .attr("id","d3plus_overlay")
+    .attr("width",vars.width.value)
+    .attr("height",vars.height.value)
+    .attr("opacity",0);
+
+  if (!touch) {
+
+    vars.g.overlay
+      .on(events.move,function(d){
+
+        if (vars.types[vars.type.value].zoom && vars.zoom.pan.value &&
+          vars.zoom.behavior.scaleExtent()[0] < vars.zoom.scale) {
+          d3.select(this).style("cursor",prefix()+"grab");
+        }
+        else {
+          d3.select(this).style("cursor","auto");
+        }
+
+      })
+      .on(events.up,function(d){
+
+        if (vars.types[vars.type.value].zoom && vars.zoom.pan.value &&
+          vars.zoom.behavior.scaleExtent()[0] < vars.zoom.scale) {
+          d3.select(this).style("cursor",prefix()+"grab");
+        }
+        else {
+          d3.select(this).style("cursor","auto");
+        }
+
+      })
+      .on(events.down,function(d){
+
+        if (vars.types[vars.type.value].zoom && vars.zoom.pan.value &&
+          vars.zoom.behavior.scaleExtent()[0] < vars.zoom.scale) {
+          d3.select(this).style("cursor",prefix()+"grabbing");
+        }
+        else {
+          d3.select(this).style("cursor","auto");
+        }
+
+      });
+
+  }
+  else {
+
+    var mouseEvent = function() {
+      touchEvent(vars, d3.event);
+    };
+
+    vars.g.overlay
+      .on(events.over, mouseEvent)
+      .on(events.move, mouseEvent)
+      .on(events.out , mouseEvent);
+
+  }
+
+  // Enter App Background Group
+  vars.g.app = vars.g.viz.selectAll("g#app").data(["app"]);
+  vars.g.app.enter().append("g")
+    .attr("id","app");
+
+  // Enter Edges Group
+  vars.g.edges = vars.g.viz.selectAll("g#edges").data(["edges"]);
+  vars.g.edges.enter().append("g")
+    .attr("id","edges")
+    .attr("opacity",0);
+
+  // Enter Edge Focus Group
+  vars.g.edge_focus = vars.g.viz.selectAll("g#focus").data(["focus"]);
+  vars.g.edge_focus.enter().append("g")
+    .attr("id","focus");
+
+  // Enter Edge Hover Group
+  vars.g.edge_hover = vars.g.viz.selectAll("g#edge_hover").data(["edge_hover"]);
+  vars.g.edge_hover.enter().append("g")
+    .attr("id","edge_hover")
+    .attr("opacity",0);
+
+  // Enter App Data Group
+  vars.g.data = vars.g.viz.selectAll("g#data").data(["data"]);
+  vars.g.data.enter().append("g")
+    .attr("id","data")
+    .attr("opacity",0);
+
+  // Enter Data Focus Group
+  vars.g.data_focus = vars.g.viz.selectAll("g#data_focus").data(["data_focus"]);
+  vars.g.data_focus.enter().append("g")
+    .attr("id","data_focus");
+
+  // Enter Top Label Group
+  vars.g.labels = vars.g.viz.selectAll("g#d3plus_labels").data(["d3plus_labels"]);
+  vars.g.labels.enter().append("g")
+    .attr("id","d3plus_labels");
+
+  vars.defs = vars.svg.selectAll("defs").data(["defs"]);
+  vars.defs.enter().append("defs");
+
+  if ( vars.dev.value ) print.timeEnd("creating SVG elements");
+
+};
+
+},{"../../../client/pointer.coffee":40,"../../../client/prefix.coffee":41,"../../../client/touch.coffee":44,"../../../core/console/print.coffee":53,"../zoom/propagation.coffee":250}],236:[function(require,module,exports){
+var print = require("../../../core/console/print.coffee")
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Updating Elements
+//------------------------------------------------------------------------------
+module.exports = function(vars) {
+
+  if ( vars.dev.value ) print.time("updating SVG elements")
+
+  if ( vars.draw.timing ) {
+
+    // Update Parent Element
+    vars.container.value.transition().duration(vars.draw.timing)
+      .style("width",vars.width.value+"px")
+      .style("height",vars.height.value+"px")
+
+    // Update SVG
+    vars.svg.transition().duration(vars.draw.timing)
+        .attr("width",vars.width.value)
+        .attr("height",vars.height.value)
+
+    // Update Background Rectangle
+    vars.g.bg.transition().duration(vars.draw.timing)
+        .attr("width",vars.width.value)
+        .attr("height",vars.height.value)
+
+    // Update App Clipping Rectangle
+    vars.g.clipping.select("rect").transition().duration(vars.draw.timing)
+      .attr("width",vars.width.viz)
+      .attr("height",vars.height.viz)
+
+    // Update Container Groups
+    vars.g.container.transition().duration(vars.draw.timing)
+      .attr("transform","translate("+vars.margin.left+","+vars.margin.top+")")
+
+  }
+  else {
+
+    // Update Parent Element
+    vars.container.value
+      .style("width",vars.width.value+"px")
+      .style("height",vars.height.value+"px")
+
+    // Update SVG
+    vars.svg
+      .attr("width",vars.width.value)
+      .attr("height",vars.height.value)
+
+    // Update Background Rectangle
+    vars.g.bg
+      .attr("width",vars.width.value)
+      .attr("height",vars.height.value)
+
+    // Update App Clipping Rectangle
+    vars.g.clipping.select("rect")
+      .attr("width",vars.width.viz)
+      .attr("height",vars.height.viz)
+
+    // Update Container Groups
+    vars.g.container
+      .attr("transform","translate("+vars.margin.left+","+vars.margin.top+")")
+
+  }
+
+  if ( vars.dev.value ) print.timeEnd("updating SVG elements")
+
+}
+
+},{"../../../core/console/print.coffee":53}],237:[function(require,module,exports){
+var arraySort     = require("../../../array/sort.coffee"),
+    createTooltip = require("../../../tooltip/create.js"),
+    dataNest      = require("../../../core/data/nest.js"),
+    fetchData     = require("./data.js"),
+    fetchColor    = require("../../../core/fetch/color.coffee"),
+    fetchText     = require("../../../core/fetch/text.js"),
+    fetchValue    = require("../../../core/fetch/value.coffee"),
+    mergeObject   = require("../../../object/merge.coffee"),
+    removeTooltip = require("../../../tooltip/remove.coffee"),
+    segments      = require("../shapes/segments.coffee"),
+    uniques       = require("../../../util/uniques.coffee"),
+    validObject   = require("../../../object/validate.coffee"),
+    zoomDirection = require("../zoom/direction.coffee");
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Creates correctly formatted tooltip for Apps
+//-------------------------------------------------------------------
+module.exports = function(params) {
+
+  if ( !( "d3plus" in params.data ) ) {
+    params.data.d3plus = {}
+  }
+
+  var vars = params.vars,
+      d = params.data,
+      dataDepth = "d3plus" in d && "depth" in d.d3plus ? d.d3plus.depth : vars.depth.value,
+      ex = params.ex,
+      mouse = params.mouseevents ? params.mouseevents : false,
+      arrow = "arrow" in params ? params.arrow : true,
+      id = fetchValue(vars,d,vars.id.value),
+      tooltip_id = params.id || vars.type.value
+
+  if ((d3.event && d3.event.type == "click") && (vars.tooltip.html.value || vars.tooltip.value.long) && !("fullscreen" in params)) {
+    var fullscreen = true,
+        arrow = false,
+        mouse = true,
+        length = "long",
+        footer = vars.footer.value
+
+    vars.covered = true
+  }
+  else {
+    var fullscreen = false,
+        align = params.anchor || vars.tooltip.anchor,
+        length = params.length || "short",
+        zoom = zoomDirection(d, vars)
+
+    if (zoom === -1) {
+      var key = vars.id.nesting[dataDepth-1],
+          parent = fetchValue(vars,id,key)
+    }
+
+    if (zoom === 1 && vars.zoom.value) {
+      var text = vars.format.value(vars.format.locale.value.ui.expand)
+    }
+    else if (zoom === -1 && vars.zoom.value && vars.history.states.length && !vars.tooltip.value.long) {
+      var text = vars.format.value(vars.format.locale.value.ui.collapse)
+    }
+    else if (!vars.small && length == "short" && (vars.tooltip.html.value || vars.tooltip.value.long) && (vars.focus.value.length !== 1 || vars.focus.value[0] != id)) {
+      var text = vars.format.locale.value.ui.moreInfo
+    }
+    else if (length == "long") {
+      var text = vars.footer.value || ""
+    }
+    else {
+      var text = ""
+    }
+
+    var footer = text.length ? vars.format.value(text,{"key": "footer", "vars": vars}) : false
+
+  }
+
+  if ("x" in params) {
+    var x = params.x;
+  }
+  else if (vars.types[vars.type.value].tooltip === "static") {
+    var x = d.d3plus.x;
+    if (vars.zoom.translate && vars.zoom.scale) {
+      x = vars.zoom.translate[0]+x*vars.zoom.scale;
+    }
+    x += vars.margin.left;
+    if (params.length !== "long") {
+      y += window.scrollX;
+      x += vars.container.value.node().getBoundingClientRect().left;
+      x += parseFloat(vars.container.value.style("padding-left"), 10);
+    }
+  }
+  else {
+    var x = d3.mouse(d3.select("html").node())[0];
+  }
+
+  if ("y" in params) {
+    var y = params.y;
+  }
+  else if (vars.types[vars.type.value].tooltip == "static") {
+    var y = d.d3plus.y;
+    if (vars.zoom.translate && vars.zoom.scale) {
+      y = vars.zoom.translate[1]+y*vars.zoom.scale;
+    }
+    y += vars.margin.top;
+    if (params.length !== "long") {
+      y += window.scrollY;
+      y += vars.container.value.node().getBoundingClientRect().top;
+      y += parseFloat(vars.container.value.style("padding-top"), 10);
+    }
+  }
+  else {
+    var y = d3.mouse(d3.select("html").node())[1];
+  }
+
+  if ("offset" in params) {
+    var offset = params.offset;
+  }
+  else if (vars.types[vars.type.value].tooltip == "static") {
+    var offset = d.d3plus.r ? d.d3plus.r : d.d3plus.height/2;
+    if (vars.zoom.scale) {
+      offset = offset * vars.zoom.scale;
+    }
+  }
+  else {
+    var offset = 3;
+  }
+
+  function make_tooltip(html) {
+
+    var titleDepth = "depth" in params ? params.depth : dataDepth;
+
+    var ex = {},
+        children,
+        depth     = vars.id.nesting[titleDepth+1] in d ? titleDepth + 1 : titleDepth,
+        nestKey   = vars.id.nesting[depth],
+        nameList  = "merged" in d.d3plus ? d.d3plus.merged : d[nestKey];
+
+    if (!(nameList instanceof Array)) nameList = [nameList];
+
+    var dataValue = fetchValue( vars , d , vars.size.value );
+
+    if (vars.tooltip.children.value) {
+
+      nameList = nameList.slice(0);
+      if (nameList.length > 1 && validObject(nameList[0])) nameList = dataNest(vars, nameList, [nestKey]);
+
+      if (vars.size.value && validObject(nameList[0])) {
+
+        var namesNoValues = [];
+        var namesWithValues = nameList.filter(function(n){
+          var val = fetchValue(vars, n, vars.size.value);
+          if (val !== null && (!("d3plus" in n) || !n.d3plus.merged)) {
+            return true;
+          }
+          else {
+            namesNoValues.push(n);
+          }
+        });
+
+        arraySort(namesWithValues, vars.size.value, "desc", [], vars);
+
+        nameList = namesWithValues.concat(namesNoValues);
+
+      }
+
+      var limit = length === "short" ? 3 : vars.data.large,
+          listLength = nameList.length,
+          max   = d3.min([listLength , limit]),
+          objs  = [];
+
+      children = {"values": []};
+      for (var i = 0; i < max; i++) {
+
+        if (!nameList.length) break;
+
+        var obj  = nameList.shift(),
+            name = fetchText(vars, obj, depth)[0],
+            id   = validObject(obj) ? fetchValue(vars, obj, nestKey, depth) : obj;
+
+        if (id !== d[vars.id.nesting[titleDepth]] && name && !children[name]) {
+
+          var value = validObject(obj) ? fetchValue(vars, obj, vars.size.value, nestKey) : null,
+              color = fetchColor(vars, obj, nestKey);
+
+          children[name] = value && !(value instanceof Array) ? vars.format.value(value, {"key": vars.size.value, "vars": vars, "data": obj}) : "";
+          var child = {};
+          child[name] = children[name];
+          children.values.push(child);
+
+          if (color) {
+            if ( !children.d3plus_colors ) children.d3plus_colors = {};
+            children.d3plus_colors[name] = color;
+          }
+
+        }
+        else {
+          i--;
+        }
+
+      }
+
+      if ( listLength > max ) {
+        children.d3plusMore = listLength - max;
+      }
+
+    }
+
+    if (d.d3plus.tooltip) {
+      ex = mergeObject(ex, d.d3plus.tooltip);
+    }
+
+    function getLabel(method) {
+      return typeof vars[method].value === "string" ? vars[method].value :
+             vars.format.locale.value.method[method];
+    }
+
+    if ( vars.tooltip.size.value ) {
+      if (dataValue && typeof vars.size.value !== "number") {
+        ex[getLabel("size")] = dataValue;
+      }
+      if (vars.axes.opposite && vars[vars.axes.opposite].value !== vars.size.value) {
+        ex[getLabel(vars.axes.opposite)] = fetchValue(vars, d, vars[vars.axes.opposite].value);
+      }
+      if (vars.color.valueScale) {
+        ex[getLabel("color")] = fetchValue(vars, d, vars.color.value);
+      }
+    }
+
+    var active = segments(vars, d, "active"),
+        temp   = segments(vars, d, "temp"),
+        total  = segments(vars, d, "total");
+
+    if (typeof active == "number" && active > 0 && total) {
+      ex[getLabel("active")] = active+"/"+total+" ("+vars.format.value((active/total)*100, {"key": "share", "vars": vars, "data": d})+")";
+    }
+
+    if (typeof temp == "number" && temp > 0 && total) {
+      ex[getLabel("temp")] = temp+"/"+total+" ("+vars.format.value((temp/total)*100, {"key": "share", "vars": vars, "data": d})+")";
+    }
+
+    if ( vars.tooltip.share.value && d.d3plus.share ) {
+      ex.share = vars.format.value(d.d3plus.share*100, {"key": "share", "vars": vars, "data": d});
+    }
+
+    var depth = "depth" in params ? params.depth : dataDepth,
+        title = params.title || fetchText(vars,d,depth)[0],
+        icon = uniques(d, vars.icon.value, fetchValue, vars, vars.id.nesting[depth]),
+        tooltip_data = fetchData(vars,d,length,ex,children,depth)
+
+    if (icon.length === 1 && typeof icon[0] === "string") {
+      icon = icon[0];
+    }
+    else {
+      icon = false;
+    }
+
+    if ((tooltip_data.length > 0 || footer) || ((!d.d3plus_label && length == "short" && title) || (d.d3plus_label && (!("visible" in d.d3plus_label) || ("visible" in d.d3plus_label && d.d3plus_label.visible === false))))) {
+
+      if (!title) {
+        title = id;
+      }
+
+      var depth = "d3plus" in d && "merged" in d.d3plus ? dataDepth - 1 : "depth" in params ? params.depth : dataDepth;
+
+      if (depth < 0) depth = 0
+
+      depth = vars.id.nesting[depth]
+
+      if (typeof vars.icon.style.value == "string") {
+        var icon_style = vars.icon.style.value
+      }
+      else if (typeof vars.icon.style.value == "object" && vars.icon.style.value[depth]) {
+        var icon_style = vars.icon.style.value[depth]
+      }
+      else {
+        var icon_style = "default"
+      }
+
+      if (params.width) {
+        var width = params.width
+      }
+      else if (!fullscreen && tooltip_data.length == 0) {
+        var width = "auto"
+      }
+      else {
+        var width = vars.tooltip.small
+      }
+
+      var parent = params.length !== "long" ? d3.select("body") : vars.container.value;
+
+      if (!params.description && d && vars.tooltip.sub.value) {
+        params.description = fetchValue(vars, d, vars.tooltip.sub.value);
+      }
+
+      createTooltip({
+        "align": align,
+        "arrow": arrow,
+        "locale": vars.format.locale.value,
+        "background": vars.tooltip.background,
+        "curtain": vars.tooltip.curtain.color,
+        "curtainopacity": vars.tooltip.curtain.opacity,
+        "fontcolor": vars.tooltip.font.color,
+        "fontfamily": vars.tooltip.font.family.value,
+        "fontsize": vars.tooltip.font.size,
+        "fontweight": vars.tooltip.font.weight,
+        "data": tooltip_data,
+        "color": fetchColor(vars, d),
+        "allColors": true,
+        "footer": params.footer === false ? params.footer : footer,
+        "fullscreen": fullscreen,
+        "html": html,
+        "js": params.js,
+        "icon": icon,
+        "id": tooltip_id,
+        "max_height": params.maxheight,
+        "max_width": vars.tooltip.small,
+        "mouseevents": mouse,
+        "offset": offset,
+        "parent": parent,
+        "style": icon_style,
+        "title": title,
+        "description": params.description,
+        "width": width,
+        "x": x,
+        "y": y
+      })
+
+    }
+    else {
+      removeTooltip(tooltip_id)
+    }
+
+  }
+
+  if (fullscreen || params.length === "long") {
+
+    if (typeof vars.tooltip.html.value == "string") {
+      make_tooltip(vars.tooltip.html.value)
+    }
+    else if (typeof vars.tooltip.html.value == "function") {
+      make_tooltip(vars.tooltip.html.value(id))
+    }
+    else if (vars.tooltip.html.value && typeof vars.tooltip.html.value == "object" && vars.tooltip.html.value.url) {
+      var tooltip_url = vars.tooltip.html.value.url;
+      if (typeof tooltip_url === "function") tooltip_url = tooltip_url(id);
+      d3.json(tooltip_url,function(data){
+        var html = vars.tooltip.html.value.callback ? vars.tooltip.html.value.callback(data) : data
+        make_tooltip(html)
+      })
+    }
+    else {
+      make_tooltip(params.html)
+    }
+
+  }
+  else {
+    make_tooltip(params.html)
+  }
+
+}
+
+},{"../../../array/sort.coffee":36,"../../../core/data/nest.js":61,"../../../core/fetch/color.coffee":64,"../../../core/fetch/text.js":67,"../../../core/fetch/value.coffee":68,"../../../object/merge.coffee":170,"../../../object/validate.coffee":171,"../../../tooltip/create.js":200,"../../../tooltip/remove.coffee":202,"../../../util/uniques.coffee":209,"../shapes/segments.coffee":230,"../zoom/direction.coffee":247,"./data.js":238}],238:[function(require,module,exports){
+var copy = require("../../../util/copy.coffee"),
+    fetchValue   = require("../../../core/fetch/value.coffee"),
+    fetchColor   = require("../../../core/fetch/color.coffee"),
+    fetchText    = require("../../../core/fetch/text.js"),
+    legible      = require("../../../color/legible.coffee"),
+    mergeObject  = require("../../../object/merge.coffee"),
+    prefix       = require("../../../client/prefix.coffee"),
+    stringFormat = require("../../../string/format.js"),
+    validObject  = require("../../../object/validate.coffee");
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Creates a data object for the Tooltip
+//------------------------------------------------------------------------------
+module.exports = function(vars, id, length, extras, children, depth) {
+
+  if (vars.small) {
+    return []
+  }
+
+  if (!length) var length = "long"
+  if (length == "long") {
+    var other_length = "short"
+  }
+  else {
+    var other_length = "long"
+  }
+
+  var extra_data = {}
+  if (extras && typeof extras == "string") extras = [extras]
+  else if (extras && typeof extras == "object") {
+    extra_data = mergeObject(extra_data,extras)
+    var extras = []
+    for ( var k in extra_data ) {
+      extras.push(k)
+    }
+  }
+  else if (!extras) var extras = []
+
+  var tooltip_highlights = []
+
+  if (vars.tooltip.value instanceof Array) {
+    var a = vars.tooltip.value
+  }
+  else if (typeof vars.tooltip.value == "string") {
+    var a = [vars.tooltip.value]
+  }
+  else {
+
+    if (vars.tooltip.value[vars.id.nesting[depth]]) {
+      var a = vars.tooltip.value[vars.id.nesting[depth]]
+    }
+    else {
+      var a = vars.tooltip.value
+    }
+
+    if (!(a instanceof Array)) {
+
+      if (a[length]) {
+        a = a[length]
+      }
+      else if (a[other_length]) {
+        a = []
+      }
+      else {
+        a = mergeObject({"":[]},a)
+      }
+
+    }
+
+    if (typeof a == "string") {
+      a = [a]
+    }
+    else if (!(a instanceof Array)) {
+      a = mergeObject({"":[]},a)
+    }
+
+  }
+
+  function format_key(key,group) {
+
+    if (vars.attrs.value[group]) var id_var = group
+    else var id_var = null
+
+    if (group) group = vars.format.value(group)
+
+    var value = extra_data[key] || fetchValue(vars,id,key,id_var)
+
+    if (validObject(value)) {
+      tooltip_data.push({
+        "name": vars.format.value(key),
+        "value": vars.format.value(value.value, {"key": value.key, "vars": vars}),
+        "group": group
+      })
+    }
+    else if (value != null && value != "undefined" && !(value instanceof Array) && ((typeof value === "string" && value.indexOf("d3plus_other") < 0) || !(typeof value === "string"))) {
+      var name = vars.format.locale.value.ui[key]
+               ? vars.format.value(vars.format.locale.value.ui[key])
+               : vars.format.value(key),
+          h = tooltip_highlights.indexOf(key) >= 0
+
+      if ( value instanceof Array ) {
+        value.forEach(function(v){
+          v = vars.format.value(v, {"key": key, "vars": vars, "data": id})
+        })
+      }
+      else {
+        value = vars.format.value(value, {"key": key, "vars": vars, "data": id})
+      }
+
+      var obj = {"name": name, "value": value, "highlight": h, "group": group}
+
+      if ( vars.descs.value ) {
+
+        if ( typeof vars.descs.value === "function" ) {
+          var descReturn = vars.descs.value( key )
+          if ( typeof descReturn === "string" ) {
+            obj.desc = descReturn
+          }
+        }
+        else if ( key in vars.descs.value ) {
+          obj.desc = vars.descs.value[key]
+        }
+
+      }
+
+      tooltip_data.push(obj)
+
+    }
+
+  }
+
+  var tooltip_data = []
+  if (a.constructor === Array) a = {"": a};
+
+  if (vars.id.nesting.length && depth < vars.id.nesting.length-1) {
+    var a = copy(a)
+    vars.id.nesting.forEach(function(n,i){
+      if (i > depth && a[n]) delete a[n]
+    })
+  }
+
+  for (var group in a) {
+    if (a[group].constructor !== Array) a[group] = [a[group]]
+    for (var i = extras.length; i > 0; i--) {
+      if (a[group].indexOf(extras[i-1]) >= 0) {
+        extras.splice(i-1, 1);
+      }
+    }
+  }
+
+  if (vars.tooltip.value.long && typeof vars.tooltip.value.long == "object") {
+    var placed = []
+
+    for (var group in vars.tooltip.value.long) {
+
+      for (var i = extras.length; i > 0; i--) {
+        var e = extras[i-1];
+        if (vars.tooltip.value.long[group].indexOf(e) >= 0) {
+          if (!a[group]) a[group] = [];
+          a[group].push(e);
+          extras.splice(i-1, 1);
+        }
+      }
+
+    }
+
+  }
+
+  if (extras.length) {
+    if (!a[""]) a[""] = []
+    a[""] = a[""].concat(extras);
+  }
+
+  for (var group in a) {
+    a[group].forEach(function(t){
+      format_key(t, group);
+    });
+  }
+
+  if ( children ) {
+
+    var title  = vars.format.locale.value.ui.including
+      , colors = children.d3plus_colors
+
+    children.values.forEach(function(child) {
+      var name = d3.keys(child)[0];
+      tooltip_data.push({
+        "group": vars.format.value(title),
+        "highlight": colors && colors[name] ? colors[name] : false,
+        "name": name,
+        "value": child[name]
+      })
+    });
+
+    if (children.d3plusMore) {
+
+      tooltip_data.push({
+        "group": vars.format.value(title),
+        "highlight": true,
+        "name": stringFormat(vars.format.locale.value.ui.more, children.d3plusMore),
+        "value": ""
+      })
+
+    }
+
+  }
+
+  if ( vars.tooltip.connections.value && length === "long" ) {
+
+    var connections = vars.edges.connections( id[vars.id.value] , vars.id.value , true )
+
+    if ( connections.length ) {
+      connections.forEach(function(conn){
+
+        var c = vars.data.viz.filter(function(d){
+          return d[vars.id.value] === conn[vars.id.value]
+        })
+
+        var c = c.length ? c[0] : conn
+
+        var name = fetchText(vars,c)[0],
+            color = fetchColor(vars,c),
+            size = vars.tooltip.font.size,
+            radius = vars.shape.value == "square" ? 0 : size
+            styles = [
+              "background-color: "+color,
+              "border-color: "+legible(color),
+              "border-style: solid",
+              "border-width: "+vars.data.stroke.width+"px",
+              "display: inline-block",
+              "height: "+size+"px",
+              "left: 0px",
+              "position: absolute",
+              "width: "+size+"px",
+              "top: 0px",
+              prefix()+"border-radius: "+radius+"px",
+            ]
+            node = "<div style='"+styles.join("; ")+";'></div>"
+
+        var nodeClick = function() {
+          vars.self.focus([c[vars.id.value]]).draw()
+        }
+
+        tooltip_data.push({
+          "group": vars.format.value(vars.format.locale.value.ui.primary),
+          "highlight": false,
+          "link": nodeClick,
+          "name": "<div id='d3plustooltipfocuslink_"+c[vars.id.value]+"' class='d3plus_tooltip_focus_link' style='position:relative;padding-left:"+size*1.5+"px;'>"+node+name+"</div>"
+        })
+
+      })
+    }
+
+  }
+
+  return tooltip_data
+
+}
+
+},{"../../../client/prefix.coffee":41,"../../../color/legible.coffee":45,"../../../core/fetch/color.coffee":64,"../../../core/fetch/text.js":67,"../../../core/fetch/value.coffee":68,"../../../object/merge.coffee":170,"../../../object/validate.coffee":171,"../../../string/format.js":172,"../../../util/copy.coffee":206}],239:[function(require,module,exports){
+var print;
+
+print = require("../../../core/console/print.coffee");
+
+module.exports = function(vars) {
+  var app, d, dataRequired, drawable, i, len, ref, requirements, returned, visualization;
+  vars.group = vars.g.apps[vars.type.value];
+  vars.mouse.viz = false;
+  visualization = vars.types[vars.type.value];
+  requirements = visualization.requirements || [];
+  dataRequired = requirements.indexOf("data") >= 0;
+  drawable = !dataRequired || (dataRequired && vars.data.viz.length);
+  if (!vars.error.internal && drawable) {
+    app = vars.format.locale.value.visualization[vars.type.value];
+    if (vars.dev.value) {
+      print.time("running " + app);
+    }
+    ref = vars.data.viz;
+    for (i = 0, len = ref.length; i < len; i++) {
+      d = ref[i];
+      if (d.d3plus) {
+        delete d.d3plus.shape;
+        delete d.d3plus.label;
+        delete d.d3plus.rotate;
+        delete d.d3plus.share;
+      }
+    }
+    returned = visualization(vars);
+    if (vars.dev.value) {
+      print.timeEnd("running " + app);
+    }
+  } else {
+    returned = null;
+  }
+  vars.returned = {
+    nodes: [],
+    edges: null
+  };
+  if (returned instanceof Array) {
+    vars.returned.nodes = returned;
+  } else if (returned) {
+    if (returned.nodes) {
+      vars.returned.nodes = returned.nodes;
+    }
+    if (returned.edges) {
+      vars.returned.edges = returned.edges;
+    }
+  }
+};
+
+
+},{"../../../core/console/print.coffee":53}],240:[function(require,module,exports){
+var copy        = require("../../../util/copy.coffee"),
+    form        = require("../../../form/form.js"),
+    print       = require("../../../core/console/print.coffee"),
+    validObject = require("../../../object/validate.coffee");
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Draws a UI drawer, if defined.
+//------------------------------------------------------------------------------
+module.exports = function( vars ) {
+
+  var enabled = vars.ui.value && vars.ui.value.length,
+      position = vars.ui.position.value;
+
+  if ( vars.dev.value && enabled ) print.time("drawing custom UI elements");
+
+  var drawer = vars.container.value.selectAll("div#d3plus_drawer")
+    .data(["d3plus_drawer"]);
+
+  drawer.enter().append("div")
+    .attr("id","d3plus_drawer");
+
+  var positionStyles = {};
+  vars.ui.position.accepted.forEach(function(p){
+    positionStyles[p] = p == position ? vars.margin.bottom+"px" : "auto";
+  });
+
+  drawer
+    .style("text-align",vars.ui.align.value)
+    .style("position","absolute")
+    .style("width",vars.width.value-(vars.ui.padding*2)+"px")
+    .style("height","auto")
+    .style(positionStyles);
+
+  var ui = drawer.selectAll("div.d3plus_drawer_ui")
+    .data(enabled ? vars.ui.value : [], function(d){
+      return d.method || false;
+    });
+
+  function create(d) {
+
+    var data = [], title;
+
+    if (d.label) {
+      title = d.label;
+    }
+    else if (typeof d.method === "string" && d.method in vars) {
+      title = vars.format.locale.value.method[d.method] || d.method;
+    }
+
+    d.value.forEach(function(o){
+
+      var obj = {};
+
+      if (validObject(o)) {
+        obj.id   = o[d3.keys(o)[0]];
+        obj.text = vars.format.value(d3.keys(o)[0]);
+      }
+      else {
+        obj.id   = o;
+        obj.text = vars.format.value(o);
+      }
+
+      data.push(obj);
+
+    });
+
+    var font = copy(vars.ui.font);
+    font.align = copy(vars.font.align);
+    font.secondary = copy(font);
+
+    d.form
+      .data(data)
+      .font(font)
+      .format(vars.format.locale.language)
+      .title(vars.format.value(title))
+      .type(d.type || "auto")
+      .ui({
+        "align": vars.ui.align.value,
+        "padding": vars.ui.padding,
+        "margin": 0
+      })
+      .width(d.width || false)
+      .draw();
+
+  }
+
+  ui.exit().remove();
+
+  ui.each(create);
+
+  ui.enter().append("div")
+    .attr("class","d3plus_drawer_ui")
+    .style("padding",vars.ui.padding+"px")
+    .style("display","inline-block")
+    .each(function(d){
+
+      var container = d3.select(this);
+      var focus, callback;
+
+      if (typeof d.method === "string" && d.method in vars) {
+        focus = vars[d.method].value;
+        callback = function(value) {
+          if ( value !== vars[d.method].value ) {
+            vars.self[d.method](value).draw();
+          }
+        };
+      }
+      else {
+        focus = d.value[0];
+        if (validObject(focus)) focus = focus[d3.keys(focus)[0]];
+        if (typeof d.method === "function") {
+          callback = function(value) {
+            d.method(value, vars.self);
+          };
+        }
+      }
+
+      d.form = form()
+        .container(container)
+        .data({"sort": false})
+        .focus(d.value.length > 1 ? focus : false)
+        .focus({"callback": callback})
+        .id("id")
+        .text("text");
+
+    })
+    .each(create);
+
+  var drawerHeight = drawer.node().offsetHeight || drawer.node().getBoundingClientRect().height;
+
+  if ( drawerHeight ) {
+    vars.margin[position] += drawerHeight;
+  }
+
+  if ( vars.dev.value && enabled ) print.timeEnd("drawing custom UI elements");
+
+};
+
+},{"../../../core/console/print.coffee":53,"../../../form/form.js":103,"../../../object/validate.coffee":171,"../../../util/copy.coffee":206}],241:[function(require,module,exports){
+var events, lighter, print, stylesheet;
+
+events = require("../../../client/pointer.coffee");
+
+lighter = require("../../../color/lighter.coffee");
+
+print = require("../../../core/console/print.coffee");
+
+stylesheet = require("../../../client/css.coffee");
+
+module.exports = function(vars) {
+  var button, color, containerPadding, enter, family, left, min_height, padding, size, stripY, style, titleClass, titleGroup, top, weight;
+  if (!vars.small && vars.history.states.length > 0) {
+    if (vars.dev.value) {
+      print.time("drawing back button");
+    }
+    button = vars.container.value.selectAll("div#d3plus_back_button").data(["d3plus_back_button"]).style("position", "relative").style("z-index", 1900);
+    size = vars.title.sub.font.size;
+    color = vars.title.sub.font.color;
+    family = vars.title.sub.font.family.value;
+    weight = vars.title.sub.font.weight;
+    padding = vars.title.sub.padding;
+    titleClass = false;
+    if (vars.title.sub.value && ["start", "left"].indexOf(vars.title.sub.font.align) < 0) {
+      titleClass = "sub";
+    } else if (vars.title.total.value && ["start", "left"].indexOf(vars.title.total.font.align) < 0) {
+      titleClass = "total";
+    } else if (vars.title.value && ["start", "left"].indexOf(vars.title.font.align) < 0) {
+      titleClass = "title";
+    }
+    if (titleClass) {
+      stripY = function(elem) {
+        var y;
+        y = elem.attr("transform").split(",");
+        y = y[y.length - 1];
+        return parseFloat(y.substring(0, y.length - 1));
+      };
+      titleGroup = vars.svg.select(".d3plus_title." + titleClass);
+      top = stripY(titleGroup) + stripY(titleGroup.select("text"));
+    } else {
+      top = vars.margin.top - vars.title.padding;
+      min_height = size + padding * 2;
+      vars.margin.top += min_height;
+    }
+    containerPadding = parseFloat(vars.container.value.style("padding-top"), 10);
+    top += containerPadding;
+    containerPadding = parseFloat(vars.container.value.style("padding-left"), 10);
+    left = vars.margin.left + size / 2 + containerPadding;
+    style = function(elem) {
+      return elem.style("position", "absolute").style("left", left + "px").style("top", top + "px").style("color", color).style("font-family", family).style("font-weight", weight).style("font-size", size + "px");
+    };
+    enter = button.enter().append("div").attr("id", "d3plus_back_button").style("opacity", 0).call(style).html(function() {
+      var arrow;
+      if (stylesheet("font-awesome")) {
+        arrow = "<i class='fa fa-angle-left' style='margin-top:2px;margin-right:4px;'></i>";
+      } else {
+        arrow = "&laquo; ";
+      }
+      return arrow + vars.format.value(vars.format.locale.value.ui.back);
+    });
+    button.on(events.over, function() {
+      if (!vars.small && vars.history.states.length > 0) {
+        return d3.select(this).style("cursor", "pointer").transition().duration(vars.timing.mouseevents).style("color", lighter(color, .25));
+      }
+    }).on(events.out, function() {
+      if (!vars.small && vars.history.states.length > 0) {
+        return d3.select(this).style("cursor", "auto").transition().duration(vars.timing.mouseevents).style("color", color);
+      }
+    }).on(events.click, function() {
+      return vars.history.back();
+    }).transition().duration(vars.draw.timing).style("opacity", 1).call(style);
+    if (vars.dev.value) {
+      return print.timeEnd("drawing back button");
+    }
+  } else {
+    return vars.container.value.selectAll("div#d3plus_back_button").transition().duration(vars.draw.timing).style("opacity", 0).remove();
+  }
+};
+
+
+},{"../../../client/css.coffee":38,"../../../client/pointer.coffee":40,"../../../color/lighter.coffee":46,"../../../core/console/print.coffee":53}],242:[function(require,module,exports){
+var arraySort = require("../../../array/sort.coffee"),
+    buckets       = require("../../../util/buckets.coffee"),
+    copy          = require("../../../util/copy.coffee"),
+    createTooltip = require("../tooltip/create.js"),
+    dataNest      = require("../../../core/data/nest.js"),
+    dataURL       = require("../../../util/dataURL.coffee"),
+    events        = require("../../../client/pointer.coffee"),
+    fetchValue    = require("../../../core/fetch/value.coffee"),
+    fetchColor    = require("../../../core/fetch/color.coffee"),
+    fetchText     = require("../../../core/fetch/text.js"),
+    print         = require("../../../core/console/print.coffee"),
+    removeTooltip = require("../../../tooltip/remove.coffee"),
+    textColor     = require("../../../color/text.coffee"),
+    uniqueValues  = require("../../../util/uniques.coffee"),
+    stringStrip   = require("../../../string/strip.js"),
+    textWrap      = require("../../../textwrap/textwrap.coffee"),
+    touch         = require("../../../client/touch.coffee"),
+    validObject   = require("../../../object/validate.coffee");
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Creates color key
+//------------------------------------------------------------------------------
+module.exports = function(vars) {
+
+  var key_display = true,
+      square_size = 0;
+
+  if (!vars.error.internal && vars.color.value && !vars.small && vars.legend.value) {
+
+    if (!vars.color.valueScale) {
+
+      if ( vars.dev.value ) print.time("grouping data by colors");
+
+      var data;
+      if ( vars.nodes.value && vars.types[vars.type.value].requirements.indexOf("nodes") >= 0 ) {
+        data = copy(vars.nodes.restriced || vars.nodes.value);
+        if ( vars.data.viz.length ) {
+          for (var i = 0 ; i < data.length ; i++) {
+            var appData = vars.data.viz.filter(function(a){
+              return a[vars.id.value] === data[i][vars.id.value];
+            });
+            if (appData.length) {
+              data[i] = appData[0];
+            }
+          }
+        }
+      }
+      else {
+        data = vars.data.viz;
+      }
+
+      var colorFunction = function(d){
+            return fetchColor(vars, d, colorDepth);
+          },
+          colorDepth = 0,
+          colorKey = vars.id.value;
+
+      var colorIndex = vars.id.nesting.indexOf(vars.color.value);
+      if (colorIndex >= 0) {
+        colorDepth = colorIndex;
+        colorKey = vars.id.nesting[colorIndex];
+      }
+      else {
+
+        for (var n = 0; n <= vars.depth.value; n++) {
+
+          colorDepth = n;
+          colorKey   = vars.id.nesting[n];
+
+          var uniqueIDs = uniqueValues(data , function(d){
+                return fetchValue(vars, d, colorKey);
+              }),
+              uniqueColors = uniqueValues(data, colorFunction);
+
+          if (uniqueIDs.length >= uniqueColors.length && uniqueColors.length > 1) {
+            break;
+          }
+
+        }
+
+      }
+
+      var legendNesting = [vars.color.value];
+      // if (vars.icon.value && vars.legend.icons.value) legendNesting.push(vars.icon.value);
+      var colors = dataNest(vars, data, legendNesting, []);
+
+      if ( vars.dev.value ) print.timeEnd("grouping data by color")
+
+      var available_width = vars.width.value;
+
+      square_size = vars.legend.size;
+
+      var key_width = square_size*colors.length+vars.ui.padding*(colors.length+1)
+
+      if (square_size instanceof Array) {
+
+        if ( vars.dev.value ) print.time("calculating legend size")
+
+        for (var i = square_size[1]; i >= square_size[0]; i--) {
+          key_width = i*colors.length+vars.ui.padding*(colors.length+1)
+          if (available_width >= key_width) {
+            square_size = i;
+            break;
+          }
+        }
+
+        if ( vars.dev.value ) print.timeEnd("calculating legend size");
+
+      }
+      else if (typeof square_size != "number" && square_size !== false) {
+        square_size = 30;
+      }
+
+      if (available_width < key_width || colors.length == 1) {
+        key_display = false;
+      }
+      else {
+
+        key_width -= vars.ui.padding*2;
+
+        if ( vars.dev.value ) print.time("sorting legend");
+
+        var order = vars[vars.legend.order.value].value;
+
+        arraySort(colors, order, vars.legend.order.sort.value, vars.color.value, vars, colorDepth);
+
+        if ( vars.dev.value ) print.timeEnd("sorting legend");
+
+        if ( vars.dev.value ) print.time("drawing legend");
+
+        var start_x;
+
+        if (vars.legend.align == "start") {
+          start_x = vars.ui.padding;
+        }
+        else if (vars.legend.align == "end") {
+          start_x = available_width - vars.ui.padding - key_width;
+        }
+        else {
+          start_x = available_width/2 - key_width/2;
+        }
+
+        vars.g.legend.selectAll("g.d3plus_scale")
+          .transition().duration(vars.draw.timing)
+          .attr("opacity",0)
+          .remove();
+
+        function position(group) {
+
+          group
+            .attr("transform",function(g,i){
+              var x = start_x + (i*(vars.ui.padding+square_size))
+              return "translate("+x+","+vars.ui.padding+")"
+            })
+
+        }
+
+        function style(rect) {
+
+          rect
+            .attr("width", square_size)
+            .attr("height", square_size)
+            .attr("fill",function(g){
+
+              d3.select(this.parentNode).select("text").remove();
+
+              var icon = uniqueValues(g, vars.icon.value, fetchValue, vars, colorKey),
+                  color = fetchColor(vars, g, colorKey);
+
+              if (vars.legend.icons.value && icon.length === 1 &&
+                  typeof icon[0] === "string") {
+                icon = icon[0];
+                var short_url = stringStrip(icon+"_"+color),
+                    iconStyle = vars.icon.style.value,
+                    icon_style,
+                    pattern = vars.defs.selectAll("pattern#"+short_url)
+                      .data([short_url]);
+
+                if (typeof iconStyle === "string") {
+                  icon_style = vars.icon.style.value;
+                }
+                else if (validObject(iconStyle) && iconStyle[colorKey]) {
+                  icon_style = iconStyle[colorKey];
+                }
+                else {
+                  icon_style = "default";
+                }
+
+                color = icon_style == "knockout" ? color : "none";
+
+                pattern.select("rect").transition().duration(vars.draw.timing)
+                  .attr("fill",color)
+                  .attr("width",square_size)
+                  .attr("height",square_size);
+
+                pattern.select("image").transition().duration(vars.draw.timing)
+                  .attr("width",square_size)
+                  .attr("height",square_size);
+
+                var pattern_enter = pattern.enter().append("pattern")
+                  .attr("id",short_url)
+                  .attr("width",square_size)
+                  .attr("height",square_size);
+
+                pattern_enter.append("rect")
+                  .attr("fill",color)
+                  .attr("width",square_size)
+                  .attr("height",square_size);
+
+                pattern_enter.append("image")
+                  .attr("xlink:href",icon)
+                  .attr("width",square_size)
+                  .attr("height",square_size)
+                  .each(function(d){
+
+                    if (icon.indexOf("/") === 0 || icon.indexOf(window.location.hostname) >= 0) {
+                      dataURL(icon,function(base64){
+                        pattern.select("image").attr("xlink:href",base64);
+                      });
+                    }
+                    else {
+                      pattern.select("image").attr("xlink:href",icon);
+                    }
+
+                  });
+
+                return "url(#"+short_url+")";
+              }
+              else {
+
+                var names;
+                if (vars.legend.text.value) {
+                  names = [fetchValue(vars, g, vars.legend.text.value, colorDepth)];
+                }
+                else {
+                  names = fetchText(vars, g, colorDepth);
+                }
+
+                if (names.length === 1 && !(names[0] instanceof Array) && names[0].length) {
+
+                  var text = d3.select(this.parentNode).append("text");
+
+                  text
+                    .attr("font-size",vars.legend.font.size+"px")
+                    .attr("font-weight",vars.legend.font.weight)
+                    .attr("font-family",vars.legend.font.family.value)
+                    .attr("fill",textColor(color))
+                    .attr("x",0)
+                    .attr("y",0)
+                    .each(function(t){
+
+                      textWrap()
+                        .align("middle")
+                        .container( d3.select(this) )
+                        .height(square_size)
+                        .padding(vars.ui.padding)
+                        .resize( vars.labels.resize.value )
+                        .text( names[0] )
+                        .width(square_size)
+                        .valign("middle")
+                        .draw();
+
+                    })
+
+                  if (text.select("tspan").empty()) {
+                    text.remove();
+                  }
+
+                }
+
+                return color;
+              }
+
+            });
+
+        }
+
+        var colorInt = {};
+        var keys = vars.g.legend.selectAll("g.d3plus_color")
+          .data(colors,function(d){
+            var c = fetchColor(vars, d, colorKey);
+            if (!(c in colorInt)) colorInt[c] = -1;
+            colorInt[c]++;
+            return colorInt[c]+"_"+c;
+          });
+
+        keys.enter().append("g")
+          .attr("class","d3plus_color")
+          .attr("opacity",0)
+          .call(position)
+          .append("rect")
+            .attr("class","d3plus_color")
+            .call(style);
+
+        keys.order()
+          .transition().duration(vars.draw.timing)
+          .call(position)
+          .attr("opacity", 1)
+          .selectAll("rect.d3plus_color")
+            .call(style);
+
+        keys.exit()
+          .transition().duration(vars.draw.timing)
+          .attr("opacity",0)
+          .remove();
+
+        if (!touch && vars.legend.tooltip.value) {
+
+          keys
+            .on(events.over,function(d,i){
+
+              d3.select(this).style("cursor","pointer");
+
+              var bounds = this.getBoundingClientRect(),
+                  x = bounds.left + square_size/2 + window.scrollX,
+                  y = bounds.top + square_size/2 + window.scrollY + 5;
+
+              var id = fetchValue(vars, d, colorKey),
+                  idIndex = vars.id.nesting.indexOf(colorKey),
+                  title = idIndex >= 0 ? fetchText(vars,d,idIndex)[0] :
+                          vars.format.value(fetchValue(vars,d,vars.color.value,colorKey), {"key": vars.color.value, "vars": vars, "data": d});
+
+              var html, js;
+              if (vars.legend.filters.value && !(id instanceof Array)) {
+                html = "<div style='text-align:center;'>";
+                var loc = vars.format.locale.value;
+                html += "<div class='mute'>"+vars.format.value(loc.method.mute)+"</div>";
+                html += "<div class='solo'>"+vars.format.value(loc.method.solo)+"</div>";
+                html += "</div>"
+                js = function(tooltip) {
+                  var style = {
+                    "border": "1px solid #ccc",
+                    "display": "inline-block",
+                    "margin": "1px 2px",
+                    "padding": "3px 5px"
+                  }
+                  tooltip.select(".mute")
+                    .style(style)
+                    .on(events.over, function(){
+                      d3.select(this).style("cursor", "pointer");
+                    })
+                    .on(events.click, function(){
+                      var mute = vars.id.mute.value;
+                      vars.history.states.push(function(){
+                        vars.self.id({"mute": mute}).draw();
+                      })
+                      vars.self.id({"mute": id}).draw();
+                    });
+                  tooltip.select(".solo")
+                    .style(style)
+                    .on(events.over, function(){
+                      d3.select(this).style("cursor", "pointer");
+                    })
+                    .on(events.click, function(){
+                      var solo = vars.id.solo.value;
+                      vars.history.states.push(function(){
+                        vars.self.id({"solo": solo}).draw();
+                      })
+                      vars.self.id({"solo": id}).draw();
+                    });
+                }
+              }
+
+              createTooltip({
+                "data": d,
+                "html": html,
+                "js": js,
+                "depth": colorDepth,
+                "footer": false,
+                "vars": vars,
+                "x": x,
+                "y": y,
+                "mouseevents": this,
+                "title": title,
+                "offset": square_size*0.4
+              });
+
+            })
+            .on(events.out,function(d){
+              removeTooltip(vars.type.value);
+            });
+
+        }
+
+        if ( vars.dev.value ) print.timeEnd("drawing legend");
+
+      }
+
+    }
+    else if (vars.color.valueScale) {
+
+      if ( vars.dev.value ) print.time("drawing color scale");
+
+      vars.g.legend.selectAll("g.d3plus_color")
+        .transition().duration(vars.draw.timing)
+        .attr("opacity",0)
+        .remove();
+
+      var values = vars.color.valueScale.domain(),
+          colors = vars.color.valueScale.range();
+
+      if (values.length <= 2) {
+        values = buckets(values,6);
+      }
+
+      var scale = vars.g.legend.selectAll("g.d3plus_scale")
+        .data(["scale"]);
+
+      scale.enter().append("g")
+        .attr("class","d3plus_scale")
+        .attr("opacity",0);
+
+      var heatmap = scale.selectAll("#d3plus_legend_heatmap")
+        .data(["heatmap"]);
+
+      heatmap.enter().append("linearGradient")
+        .attr("id", "d3plus_legend_heatmap")
+        .attr("x1", "0%")
+        .attr("y1", "0%")
+        .attr("x2", "100%")
+        .attr("y2", "0%")
+        .attr("spreadMethod", "pad");
+
+      var stops = heatmap.selectAll("stop")
+        .data(d3.range(0,colors.length));
+
+      stops.enter().append("stop")
+        .attr("stop-opacity",1);
+
+      stops
+        .attr("offset",function(i){
+          return Math.round((i/(colors.length-1))*100)+"%";
+        })
+        .attr("stop-color",function(i){
+          return colors[i];
+        });
+
+      stops.exit().remove();
+
+      var gradient = scale.selectAll("rect#gradient")
+        .data(["gradient"]);
+
+      gradient.enter().append("rect")
+        .attr("id","gradient")
+        .attr("x",function(d){
+          if (vars.legend.align == "middle") {
+            return vars.width.value/2;
+          }
+          else if (vars.legend.align == "end") {
+            return vars.width.value;
+          }
+          else {
+            return 0;
+          }
+        })
+        .attr("y",vars.ui.padding)
+        .attr("width", 0)
+        .attr("height", vars.legend.gradient.height)
+        .attr("stroke",vars.legend.font.color)
+        .attr("stroke-width",1)
+        .style("fill", "url(#d3plus_legend_heatmap)");
+
+      var text = scale.selectAll("text.d3plus_tick")
+        .data(d3.range(0,values.length));
+
+      text.enter().append("text")
+        .attr("class","d3plus_tick")
+        .attr("x",function(d){
+          if (vars.legend.align == "middle") {
+            return vars.width.value/2;
+          }
+          else if (vars.legend.align == "end") {
+            return vars.width.value;
+          }
+          else {
+            return 0;
+          }
+        })
+        .attr("y",function(d){
+          return this.getBBox().height+vars.legend.gradient.height+vars.ui.padding*2;
+        });
+
+      var label_width = 0;
+
+      text
+        .order()
+        .attr("font-weight",vars.legend.font.weight)
+        .attr("font-family",vars.legend.font.family.value)
+        .attr("font-size",vars.legend.font.size+"px")
+        .style("text-anchor",vars.legend.font.align)
+        .attr("fill",vars.legend.font.color)
+        .text(function(d){
+          return vars.format.value(values[d], {"key": key, "vars": vars});
+        })
+        .attr("y",function(d){
+          return this.getBBox().height+vars.legend.gradient.height+vars.ui.padding*2;
+        })
+        .each(function(d){
+          var w = this.offsetWidth;
+          if (w > label_width) label_width = w;
+        });
+
+      label_width += vars.labels.padding*2;
+
+      var key_width = label_width * (values.length-1);
+
+      if (key_width+label_width < vars.width.value) {
+
+        if (key_width+label_width < vars.width.value/2) {
+          key_width = vars.width.value/2;
+          label_width = key_width/values.length;
+          key_width -= label_width;
+        }
+
+        var start_x;
+        if (vars.legend.align == "start") {
+          start_x = vars.ui.padding;
+        }
+        else if (vars.legend.align == "end") {
+          start_x = vars.width.value - vars.ui.padding - key_width;
+        }
+        else {
+          start_x = vars.width.value/2 - key_width/2;
+        }
+
+        text.transition().duration(vars.draw.timing)
+          .attr("x",function(d){
+            return start_x + (label_width*d);
+          });
+
+        text.exit().transition().duration(vars.draw.timing)
+          .attr("opacity",0)
+          .remove();
+
+        var ticks = scale.selectAll("rect.d3plus_tick")
+          .data(d3.range(0,values.length));
+
+        ticks.enter().append("rect")
+          .attr("class","d3plus_tick")
+          .attr("x",function(d){
+            if (vars.legend.align == "middle") {
+              return vars.width.value/2;
+            }
+            else if (vars.legend.align == "end") {
+              return vars.width.value;
+            }
+            else {
+              return 0;
+            }
+          })
+          .attr("y",vars.ui.padding)
+          .attr("width",0)
+          .attr("height",vars.ui.padding+vars.legend.gradient.height)
+          .attr("fill",vars.legend.font.color);
+
+        ticks.transition().duration(vars.draw.timing)
+          .attr("x",function(d){
+            var mod = d === 0 ? 1 : 0;
+            return start_x + (label_width*d) - mod;
+          })
+          .attr("y",vars.ui.padding)
+          .attr("width",1)
+          .attr("height",vars.ui.padding+vars.legend.gradient.height)
+          .attr("fill",vars.legend.font.color);
+
+        ticks.exit().transition().duration(vars.draw.timing)
+          .attr("width",0)
+          .remove();
+
+        gradient.transition().duration(vars.draw.timing)
+          .attr("x",function(d){
+            if (vars.legend.align == "middle") {
+              return vars.width.value/2 - key_width/2;
+            }
+            else if (vars.legend.align == "end") {
+              return vars.width.value - key_width - vars.ui.padding;
+            }
+            else {
+              return vars.ui.padding;
+            }
+          })
+          .attr("y",vars.ui.padding)
+          .attr("width", key_width)
+          .attr("height", vars.legend.gradient.height);
+
+        scale.transition().duration(vars.draw.timing)
+          .attr("opacity",1);
+
+        if ( vars.dev.value ) print.timeEnd("drawing color scale");
+
+      }
+      else {
+        key_display = false;
+      }
+
+    }
+    else {
+      key_display = false;
+    }
+
+  }
+  else {
+    key_display = false;
+  }
+  if (vars.legend.value && key && key_display) {
+
+    if ( vars.dev.value ) print.time("positioning legend");
+
+    if (square_size) {
+      var key_height = square_size+vars.ui.padding;
+    }
+    else {
+      var key_box = vars.g.legend.node().getBBox(),
+          key_height = key_box.height+key_box.y;
+    }
+
+    if (vars.margin.bottom === 0) {
+      vars.margin.bottom += vars.ui.padding;
+    }
+    vars.margin.bottom += key_height;
+
+    vars.g.legend.transition().duration(vars.draw.timing)
+      .attr("transform","translate(0,"+(vars.height.value-vars.margin.bottom)+")")
+
+    if ( vars.dev.value ) print.timeEnd("positioning legend")
+
+  }
+  else {
+
+    if ( vars.dev.value ) print.time("hiding legend")
+
+    vars.g.legend.transition().duration(vars.draw.timing)
+      .attr("transform","translate(0,"+vars.height.value+")")
+
+    if ( vars.dev.value ) print.timeEnd("hiding legend")
+
+  }
+
+}
+
+},{"../../../array/sort.coffee":36,"../../../client/pointer.coffee":40,"../../../client/touch.coffee":44,"../../../color/text.coffee":51,"../../../core/console/print.coffee":53,"../../../core/data/nest.js":61,"../../../core/fetch/color.coffee":64,"../../../core/fetch/text.js":67,"../../../core/fetch/value.coffee":68,"../../../object/validate.coffee":171,"../../../string/strip.js":174,"../../../textwrap/textwrap.coffee":199,"../../../tooltip/remove.coffee":202,"../../../util/buckets.coffee":203,"../../../util/copy.coffee":206,"../../../util/dataURL.coffee":208,"../../../util/uniques.coffee":209,"../tooltip/create.js":237}],243:[function(require,module,exports){
+var events = require("../../../client/pointer.coffee");
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Creates Centered Server Message
+//------------------------------------------------------------------------------
+module.exports = function(vars,message) {
+
+  message = vars.messages.value ? message : null;
+
+  var size = vars.messages.style.value || (message === vars.error.internal ?
+             "large" : vars.messages.style.backup);
+
+  if (size === "large") {
+    var font = vars.messages,
+        position = "center"
+  }
+  else {
+
+    if (vars.footer.value) {
+      var font = vars.footer
+    }
+    else if (vars.title.value) {
+      var font = vars.title
+    }
+    else if (vars.title.sub.value) {
+      var font = vars.title.sub
+    }
+    else if (vars.title.total.value) {
+      var font = vars.title.total
+    }
+    else {
+      var font = vars.title.sub
+    }
+
+    var position = font.position
+
+  }
+
+  var font = {
+    "color": font.font.color,
+    "font-family": font.font.family.value,
+    "font-weight": font.font.weight,
+    "font-size": font.font.size+"px",
+    "padding": font.padding+"px"
+  }
+
+  var bg = vars.background.value;
+  if (bg === "none") {
+    bg = "white";
+  }
+
+  function style(elem) {
+
+    elem
+      .style(font)
+      .style("position", "absolute")
+      .style("background-color", bg)
+      .style("text-align", "center")
+      .style("left",function(){
+        return position == "center" ? "50%" : "0px"
+      })
+      .style("width",function(){
+        return position == "center" ? "auto" : vars.width.value+"px"
+      })
+      .style("margin-left",function(){
+        return position == "center" ? -(this.offsetWidth/2)+"px" : "0px";
+      })
+      .style("top",function(){
+        if (position == "center") {
+          return "50%";
+        }
+        else if (position == "top") {
+          return "0px"
+        }
+        else {
+          return "auto"
+        }
+      })
+      .style("bottom",function(){
+        if (position == "bottom") {
+          return "0px"
+        }
+        else {
+          return "auto"
+        }
+      })
+      .style("margin-top",function(){
+        if (size == "large") {
+          var height = this.offsetHeight || this.getBoundingClientRect().height
+          return -height/2+"px"
+        }
+        return "0px"
+      })
+
+  }
+
+  // Enter Message Group
+  vars.g.message = vars.container.value.selectAll("div#d3plus_message")
+    .data(["message"])
+
+  var enter = vars.g.message.enter().append("div")
+    .attr("id","d3plus_message")
+    .attr("opacity",0);
+
+  enter.append("div")
+    .attr("class", "d3plus_message_text")
+    .style("display", "block");
+
+  vars.g.message.select(".d3plus_message_text")
+    .text(message ? message : vars.g.message.text())
+
+  var online = navigator.onLine, square = 75;
+
+  var branding = vars.g.message.selectAll(".d3plus_message_branding")
+    .data(vars.messages.branding.value && position === "center" ? [0] : []);
+
+  branding.enter().append("div")
+    .attr("class", "d3plus_message_branding")
+    .style("margin-top", "15px")
+    .style("padding-top", "0px")
+    .style("display", "block")
+    .style("font-size", "11px")
+    .style("background-size", square + "px")
+    .style("background-position", "center 10px")
+    .style("background-repeat", "no-repeat")
+    .style("cursor", "pointer")
+    .on(events.click, function(){
+      window.open("http://www.d3plus.org/", "_blank");
+    });
+
+  branding
+    .text(online ? "Powered by:" : "Powered by D3plus")
+    .style("background-color", online ? bg : "transparent")
+    .style("background-image", online ? "url('http://d3plus.org/assets/img/icon-transparent.png')" : "none")
+    .style("min-width", online ? square + "px" : "auto")
+    .style("height", online ? square + "px" : "auto");
+
+  branding.exit().remove();
+
+  vars.g.message
+    .style("display", message ? "inline-block" : "none")
+    .call(style).style("opacity", message ? 1 : 0)
+
+}
+
+},{"../../../client/pointer.coffee":40}],244:[function(require,module,exports){
+var closest, css, events, fontSizes, mix, playInterval, prefix, print, textColor, timeDetect;
+
+closest = require("../../../util/closest.coffee");
+
+css = require("../../../client/css.coffee");
+
+fontSizes = require("../../../font/sizes.coffee");
+
+events = require("../../../client/pointer.coffee");
+
+mix = require("../../../color/mix.coffee");
+
+prefix = require("../../../client/prefix.coffee");
+
+print = require("../../../core/console/print.coffee");
+
+textColor = require("../../../color/text.coffee");
+
+timeDetect = require("../../../core/data/time.coffee");
+
+playInterval = false;
+
+module.exports = function(vars) {
+  var availableWidth, background, brush, brushExtent, brush_group, brushed, brushend, d, end, handles, i, init, j, labelWidth, labels, len, max_index, min, min_index, oldWidth, playButton, playIcon, playIconChar, playIconStyle, playStyle, playUpdate, playbackWidth, setYears, start, start_x, step, stopPlayback, tallEnough, text, textFill, textStyle, tickColor, tickStep, ticks, timeFormat, timeReturn, timelineBox, timelineHeight, timelineOffset, timelineWidth, visible, x, yearHeight, yearMS, year_ticks, years;
+  if (vars.timeline.value && (!vars.error.internal || !vars.data.missing) && !vars.small && vars.data.time && vars.data.time.values.length > 1) {
+    if (vars.dev.value) {
+      print.time("drawing timeline");
+    }
+    textStyle = {
+      "font-weight": vars.ui.font.weight,
+      "font-family": vars.ui.font.family.value,
+      "font-size": vars.ui.font.size + "px",
+      "text-anchor": "middle"
+    };
+    years = vars.data.time.ticks.map(function(d) {
+      return new Date(d);
+    });
+    timeReturn = timeDetect(vars, {
+      values: years,
+      style: textStyle
+    });
+    visible = timeReturn.values.map(Number);
+    timeFormat = timeReturn.format;
+    if (vars.time.solo.value.length) {
+      init = d3.extent(vars.time.solo.value);
+      for (i = j = 0, len = init.length; j < len; i = ++j) {
+        d = init[i];
+        if (d.constructor !== Date) {
+          d += "";
+          if (d.length === 4 && parseInt(d) + "" === d) {
+            d += "/01/01";
+          }
+          d = new Date(d);
+          init[i] = d;
+        }
+      }
+    } else {
+      init = d3.extent(years);
+    }
+    year_ticks = years.slice();
+    yearHeight = d3.max(timeReturn.sizes.map(function(t) {
+      return t.height;
+    }));
+    labelWidth = ~~(d3.max(timeReturn.sizes.map(function(t) {
+      return t.width;
+    }))) + 1;
+    labelWidth += vars.ui.padding * 2;
+    timelineHeight = vars.timeline.height.value || yearHeight + vars.ui.padding * 2;
+    timelineWidth = labelWidth * years.length;
+    playbackWidth = labelWidth;
+    tallEnough = timelineHeight - vars.ui.padding * 2 >= yearHeight;
+    availableWidth = vars.width.value - vars.ui.padding * 2;
+    if (tallEnough && vars.timeline.play.value) {
+      availableWidth -= playbackWidth + vars.ui.padding;
+    }
+    if (!tallEnough || visible.length < years.length || availableWidth < labelWidth * visible.length) {
+      oldWidth = labelWidth;
+      labelWidth = (availableWidth - labelWidth) / years.length;
+      timelineWidth = labelWidth * years.length;
+      timelineOffset = 1;
+      tickStep = ~~(oldWidth / (timelineWidth / visible.length)) + 1;
+      while (tickStep < visible.length - 1) {
+        if ((visible.length - 1) % tickStep === 0) {
+          break;
+        }
+        tickStep++;
+      }
+      visible = visible.filter(function(t, i) {
+        return i % tickStep === 0;
+      });
+    } else {
+      timelineOffset = 0;
+      min = new Date(years[0]);
+      step = vars.data.time.stepType;
+      min["set" + step](min["get" + step]() + years.length);
+      year_ticks.push(min);
+    }
+    start = new Date(init[0]);
+    start = closest(year_ticks, start);
+    end = new Date(init[1]);
+    if (!timelineOffset) {
+      end["set" + vars.data.time.stepType](end["get" + vars.data.time.stepType]() + 1);
+    }
+    end = closest(year_ticks, end);
+    yearMS = year_ticks.map(Number);
+    min_index = yearMS.indexOf(+start);
+    max_index = yearMS.indexOf(+end);
+    brushExtent = [start, end];
+    if (vars.timeline.align === "start") {
+      start_x = vars.ui.padding;
+    } else if (vars.timeline.align === "end") {
+      start_x = vars.width.value - vars.ui.padding - timelineWidth;
+    } else {
+      start_x = vars.width.value / 2 - timelineWidth / 2;
+    }
+    if (tallEnough && vars.timeline.play.value) {
+      start_x += (playbackWidth + vars.ui.padding) / 2;
+    }
+    stopPlayback = function() {
+      clearInterval(playInterval);
+      playInterval = false;
+      return playIcon.call(playIconChar, "icon");
+    };
+    brushed = function() {
+      var extent, max_val, min_val;
+      if (d3.event.sourceEvent !== null) {
+        if (playInterval) {
+          stopPlayback();
+        }
+        brushExtent = brush.extent();
+        min_val = closest(year_ticks, brushExtent[0]);
+        max_val = closest(year_ticks, brushExtent[1]);
+        if (min_val === max_val) {
+          min_index = yearMS.indexOf(+min_val);
+          if (min_val < brushExtent[0] || min_index === 0) {
+            max_val = year_ticks[min_index + 1];
+          } else {
+            min_val = year_ticks[min_index - 1];
+          }
+        }
+        min_index = yearMS.indexOf(+min_val);
+        max_index = yearMS.indexOf(+max_val);
+        if (max_index - min_index >= 1) {
+          extent = [min_val, max_val];
+        } else if (min_index + 1 <= years.length) {
+          extent = [min_val, year_ticks[min_index + 1]];
+        } else {
+          extent = [min_val];
+          i = 1;
+          while (i <= 1) {
+            if (min_index + i <= years.length) {
+              extent.push(year_ticks[min_index + i]);
+            } else {
+              extent.unshift(year_ticks[min_index - ((min_index + i) - years.length)]);
+            }
+            i++;
+          }
+          extent = [extent[0], extent[extent.length - 1]];
+        }
+        brushExtent = extent;
+        text.attr("fill", textFill);
+        return d3.select(this).call(brush.extent(extent));
+      }
+    };
+    setYears = function() {
+      var newYears;
+      if (max_index - min_index === years.length - timelineOffset) {
+        newYears = [];
+      } else {
+        newYears = yearMS.filter(function(t, i) {
+          return i >= min_index && i < (max_index + timelineOffset);
+        });
+        newYears = newYears.map(function(t) {
+          return new Date(t);
+        });
+      }
+      playUpdate();
+      return vars.self.time({
+        "solo": newYears
+      }).draw();
+    };
+    brushend = function() {
+      var change, old_max, old_min, solo;
+      if (d3.event.sourceEvent !== null) {
+        if (vars.time.solo.value.length) {
+          solo = d3.extent(vars.time.solo.value);
+          old_min = yearMS.indexOf(+closest(year_ticks, solo[0]));
+          old_max = yearMS.indexOf(+closest(year_ticks, solo[1]));
+          change = old_min !== min_index || old_max !== max_index;
+        } else {
+          change = max_index - min_index !== years.length - timelineOffset;
+        }
+        if (change) {
+          return setYears();
+        }
+      }
+    };
+    playButton = vars.g.timeline.selectAll("rect.d3plus_timeline_play").data(tallEnough && vars.timeline.play.value ? [0] : []);
+    playStyle = function(btn) {
+      return btn.attr("width", playbackWidth + 1).attr("height", timelineHeight + 1).attr("fill", vars.ui.color.primary.value).attr("stroke", vars.ui.color.primary.value).attr("stroke-width", 1).attr("x", start_x - playbackWidth - 1 - vars.ui.padding).attr("y", vars.ui.padding);
+    };
+    playButton.enter().append("rect").attr("class", "d3plus_timeline_play").attr("shape-rendering", "crispEdges").attr("opacity", 0).call(playStyle);
+    playButton.transition().duration(vars.draw.timing).call(playStyle);
+    playButton.exit().transition().duration(vars.draw.timing).attr("opacity", 0).remove();
+    playIcon = vars.g.timeline.selectAll("text.d3plus_timeline_playIcon").data(tallEnough && vars.timeline.play.value ? [0] : []);
+    playIconChar = function(text, char) {
+      var font;
+      char = vars.timeline.play[char];
+      if (css("font-awesome")) {
+        char = char.awesome;
+        font = "FontAwesome";
+      } else {
+        char = char.fallback;
+        font = "inherit";
+      }
+      return text.style("font-family", font).text(char);
+    };
+    playIconStyle = function(text) {
+      var y;
+      y = timelineHeight / 2 + vars.ui.padding + 1;
+      return text.attr("fill", textColor(vars.ui.color.primary.value)).attr(textStyle).attr("x", start_x - (playbackWidth - 1) / 2 - vars.ui.padding).attr("y", y).attr("dy", "0.5ex").call(playIconChar, playInterval ? "pause" : "icon");
+    };
+    playIcon.enter().append("text").attr("class", "d3plus_timeline_playIcon").call(playIconStyle).style("pointer-events", "none").attr("opacity", 0);
+    playIcon.call(playIconStyle).transition().duration(vars.draw.timing).attr("opacity", 1);
+    playIcon.exit().transition().duration(vars.draw.timing).attr("opacity", 0).remove();
+    playUpdate = function() {
+      if (max_index - min_index === years.length - timelineOffset) {
+        playButton.on(events.hover, null).on(events.click, null).transition().duration(vars.draw.timing).attr("opacity", 0.3);
+        return playIcon.transition().duration(vars.draw.timing).attr("opacity", 0.3);
+      } else {
+        playButton.on(events.over, function() {
+          return d3.select(this).style("cursor", "pointer");
+        }).on(events.out, function() {
+          return d3.select(this).style("cursor", "auto");
+        }).on(events.click, function() {
+          if (playInterval) {
+            return stopPlayback();
+          } else {
+            playIcon.call(playIconChar, "pause");
+            if (max_index === years.length) {
+              max_index = max_index - min_index;
+              min_index = 0;
+            } else {
+              min_index++;
+              max_index++;
+            }
+            setYears();
+            return playInterval = setInterval(function() {
+              if (max_index === years.length - timelineOffset) {
+                return stopPlayback();
+              } else {
+                min_index++;
+                max_index++;
+                return setYears();
+              }
+            }, vars.timeline.play.timing.value);
+          }
+        }).transition().duration(vars.draw.timing).attr("opacity", 1);
+        return playIcon.transition().duration(vars.draw.timing).attr("opacity", 1);
+      }
+    };
+    playUpdate();
+    textFill = function(d) {
+      var color, less, opacity;
+      less = timelineOffset ? d <= brushExtent[1] : d < brushExtent[1];
+      if (d >= brushExtent[0] && less) {
+        opacity = 1;
+        color = textColor(vars.ui.color.secondary.value);
+      } else {
+        opacity = 0.5;
+        color = textColor(vars.ui.color.primary.value);
+      }
+      color = d3.rgb(color);
+      return "rgba(" + color.r + "," + color.g + "," + color.b + "," + opacity + ")";
+    };
+    background = vars.g.timeline.selectAll("rect.d3plus_timeline_background").data(["background"]);
+    background.enter().append("rect").attr("class", "d3plus_timeline_background").attr("shape-rendering", "crispEdges").attr("width", timelineWidth + 2).attr("height", timelineHeight + 2).attr("fill", vars.ui.color.primary.value).attr("x", start_x - 1).attr("y", vars.ui.padding);
+    background.transition().duration(vars.draw.timing).attr("width", timelineWidth + 2).attr("height", timelineHeight + 2).attr("fill", vars.ui.color.primary.value).attr("x", start_x - 1).attr("y", vars.ui.padding);
+    ticks = vars.g.timeline.selectAll("g#ticks").data(["ticks"]);
+    ticks.enter().append("g").attr("id", "ticks").attr("transform", "translate(" + vars.width.value / 2 + "," + vars.ui.padding + ")");
+    brush_group = vars.g.timeline.selectAll("g#brush").data(["brush"]);
+    brush_group.enter().append("g").attr("id", "brush");
+    labels = vars.g.timeline.selectAll("g#labels").data(["labels"]);
+    labels.enter().append("g").attr("id", "labels");
+    text = labels.selectAll("text").data(years, function(d, i) {
+      return i;
+    });
+    text.enter().append("text").attr("y", 0).attr("dy", "0.5ex").attr("x", 0);
+    x = d3.time.scale().domain(d3.extent(year_ticks)).rangeRound([0, timelineWidth]);
+    text.order().attr(textStyle).text(function(d, i) {
+      if (visible.indexOf(+d) >= 0) {
+        return timeFormat(d);
+      } else {
+        return "";
+      }
+    }).attr("opacity", function(d, i) {
+      if (vars.data.time.dataSteps.indexOf(i) >= 0) {
+        return 1;
+      } else {
+        return 0.4;
+      }
+    }).attr("fill", textFill).attr("transform", function(d, i) {
+      var dx, dy;
+      dx = start_x + x(d);
+      if (!timelineOffset) {
+        dx += labelWidth / 2;
+      }
+      dy = timelineHeight / 2 + vars.ui.padding + 1;
+      if (timelineOffset) {
+        dy += timelineHeight / 2 + yearHeight;
+      }
+      return "translate(" + Math.round(dx) + "," + Math.round(dy) + ")";
+    });
+    text.exit().transition().duration(vars.draw.timing).attr("opacity", 0).remove();
+    brush = d3.svg.brush().x(x).extent(brushExtent).on("brush", brushed).on("brushend", brushend);
+    if (vars.axes.discrete && vars[vars.axes.discrete].value === vars.time.value) {
+      tickColor = vars[vars.axes.discrete].ticks.color;
+    } else {
+      tickColor = vars.x.ticks.color;
+    }
+    ticks.attr("transform", "translate(" + start_x + "," + vars.ui.padding + ")").transition().duration(vars.draw.timing).call(d3.svg.axis().scale(x).orient("top").ticks(function() {
+      return year_ticks;
+    }).tickFormat("").tickSize(-timelineHeight).tickPadding(0)).selectAll("line").attr("stroke-width", 1).attr("shape-rendering", "crispEdges").attr("stroke", function(d) {
+      if (visible.indexOf(+d) >= 0) {
+        return tickColor;
+      } else {
+        return mix(tickColor, vars.background.value, 0.4, 1);
+      }
+    });
+    ticks.selectAll("path").attr("fill", "none");
+    brush_group.attr("transform", "translate(" + start_x + "," + vars.ui.padding + ")").attr("opacity", 1).call(brush);
+    text.attr("pointer-events", "none");
+    brush_group.selectAll("rect.background").attr("fill", "none").style("visibility", "visible").attr("height", timelineHeight).attr("shape-rendering", "crispEdges").on(events.move, function() {
+      var c;
+      c = vars.timeline.hover.value;
+      if (["grab", "grabbing"].indexOf(c) >= 0) {
+        c = prefix() + c;
+      }
+      return d3.select(this).style("cursor", c);
+    });
+    brush_group.selectAll("rect.extent").attr("opacity", 0.75).attr("height", timelineHeight).attr("fill", vars.ui.color.secondary.value).attr("shape-rendering", "crispEdges").on(events.move, function() {
+      var c;
+      c = vars.timeline.hover.value;
+      if (["grab", "grabbing"].indexOf(c) >= 0) {
+        c = prefix() + c;
+      }
+      return d3.select(this).style("cursor", c);
+    });
+    if (vars.timeline.handles.value) {
+      handles = brush_group.selectAll("g.resize").selectAll("rect.d3plus_handle").data(["d3plus_handle"]);
+      handles.enter().insert("rect", "rect").attr("class", "d3plus_handle");
+      handles.attr("fill", vars.timeline.handles.color).attr("transform", function(d) {
+        var mod;
+        if (this.parentNode.className.baseVal === "resize e") {
+          mod = -vars.timeline.handles.size;
+        } else {
+          mod = 0;
+        }
+        return "translate(" + mod + ",0)";
+      }).attr("width", vars.timeline.handles.size).style("visibility", "visible").attr("shape-rendering", "crispEdges").attr("opacity", vars.timeline.handles.opacity);
+      brush_group.selectAll("g.resize").selectAll("rect").attr("height", timelineHeight);
+    } else {
+      brush_group.selectAll("g.resize").remove();
+    }
+    timelineBox = vars.g.timeline.node().getBBox();
+    if (vars.margin.bottom === 0) {
+      vars.margin.bottom += vars.ui.padding;
+    }
+    vars.margin.bottom += timelineBox.height + timelineBox.y;
+    vars.g.timeline.transition().duration(vars.draw.timing).attr("transform", "translate(0," + Math.round(vars.height.value - vars.margin.bottom - vars.ui.padding / 2) + ")");
+    vars.margin.bottom += vars.ui.padding;
+    if (vars.dev.value) {
+      return print.time("drawing timeline");
+    }
+  } else {
+    return vars.g.timeline.transition().duration(vars.draw.timing).attr("transform", "translate(0," + vars.height.value + ")");
+  }
+};
+
+
+},{"../../../client/css.coffee":38,"../../../client/pointer.coffee":40,"../../../client/prefix.coffee":41,"../../../color/mix.coffee":47,"../../../color/text.coffee":51,"../../../core/console/print.coffee":53,"../../../core/data/time.coffee":63,"../../../font/sizes.coffee":101,"../../../util/closest.coffee":205}],245:[function(require,module,exports){
+var events = require("../../../client/pointer.coffee"),
+    fetchValue = require("../../../core/fetch/value.coffee"),
+    print      = require("../../../core/console/print.coffee"),
+    rtl        = require("../../../client/rtl.coffee"),
+    textWrap   = require("../../../textwrap/textwrap.coffee")
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Draws appropriate titles
+//------------------------------------------------------------------------------
+module.exports = function(vars) {
+
+  var total_key = vars.size.value ? vars.size.value
+    : vars.color.type === "number" ? vars.color.value : false
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // If there is no data or the title bar is not needed,
+  // set the total value to 'null'
+  //----------------------------------------------------------------------------
+  if (!vars.data.viz || !vars.title.total.value || vars.small) {
+    var total = false
+  }
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Otherwise, let's calculate it!
+  //----------------------------------------------------------------------------
+  else if (total_key) {
+
+    if ( vars.dev.value ) {
+      print.time("calculating total value")
+    }
+
+    var total_data = vars.data.pool;
+    if (vars.focus.value.length) {
+      total_data = vars.data.viz.filter(function(d){
+        return d[vars.id.value] == vars.focus.value[0];
+      });
+    }
+
+    var agg = vars.aggs.value[total_key] || "sum";
+    var total;
+    if (agg.constructor === Function) {
+      total = agg(total_data);
+    }
+    else {
+
+      total_data = total_data.reduce(function(arr, d){
+        var vals = fetchValue(vars, d, total_key);
+        if (vals instanceof Array) arr = arr.concat(vals);
+        else arr.push(vals);
+        return arr;
+      }, []);
+
+      total = d3[agg](total_data);
+    }
+
+    if (total === 0 || total === null || total === undefined) {
+      total = false
+    }
+
+    if (typeof total === "number") {
+
+      var pct = ""
+
+      if (vars.data.mute.length || vars.data.solo.length || vars.focus.value.length) {
+
+        var overall_total = d3.sum(vars.data.value, function(d){
+          if (vars.time.solo.value.length > 0) {
+            var match = vars.time.solo.value.indexOf(fetchValue(vars,d,vars.time.value)) >= 0
+          }
+          else if (vars.time.mute.value.length > 0) {
+            var match = vars.time.solo.value.indexOf(fetchValue(vars,d,vars.time.value)) < 0
+          }
+          else {
+            var match = true
+          }
+          if (match) {
+            return fetchValue(vars,d,total_key)
+          }
+        })
+
+        if (overall_total > total) {
+
+          var pct = (total/overall_total)*100,
+              ot = vars.format.value(overall_total, {"key": vars.size.value, "vars": vars});
+
+          pct = " ("+vars.format.value(pct,{"key": "share", "vars": vars})+" of "+ot+")";
+
+        }
+      }
+
+      total = vars.format.value(total, {"key": vars.size.value, "vars": vars})
+      var obj = vars.title.total.value
+        , prefix = obj.prefix || vars.format.value(vars.format.locale.value.ui.total)+": "
+      total = prefix + total
+      obj.suffix ? total = total + obj.suffix : null
+      total += pct
+
+    }
+
+    if ( vars.dev.value ) {
+      print.timeEnd("calculating total value")
+    }
+
+  }
+  else {
+    var total = false
+  }
+
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Initialize titles and detect footer
+  //----------------------------------------------------------------------------
+  var title_data = []
+
+  if (vars.footer.value) {
+    title_data.push({
+      "link": vars.footer.link,
+      "style": vars.footer,
+      "type": "footer",
+      "value": vars.footer.value
+    })
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // If not in "small" mode, detect titles available
+  //----------------------------------------------------------------------------
+  if (!vars.small) {
+
+    if (vars.title.value) {
+      var title = vars.title.value;
+      if (typeof title === "function") title = title(vars.self);
+      title_data.push({
+        "link": vars.title.link,
+        "style": vars.title,
+        "type": "title",
+        "value": title
+      })
+    }
+    if (vars.title.sub.value) {
+      var title = vars.title.sub.value;
+      if (typeof title === "function") title = title(vars.self);
+      title_data.push({
+        "link": vars.title.sub.link,
+        "style": vars.title.sub,
+        "type": "sub",
+        "value": title
+      })
+    }
+    if (vars.title.total.value && total) {
+      title_data.push({
+        "link": vars.title.total.link,
+        "style": vars.title.total,
+        "type": "total",
+        "value": total
+      })
+    }
+
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Enter Titles
+  //----------------------------------------------------------------------------
+  function style(title) {
+
+    title
+      .attr("font-size",function(t){
+        return t.style.font.size
+      })
+      .attr("fill",function(t){
+        return t.link ? vars.links.font.color : t.style.font.color
+      })
+      .attr("font-family",function(t){
+        return t.link ? vars.links.font.family.value : t.style.font.family.value
+      })
+      .attr("font-weight",function(t){
+        return t.link ? vars.links.font.weight : t.style.font.weight
+      })
+      .style("text-decoration",function(t){
+        return t.link ? vars.links.font.decoration.value : t.style.font.decoration.value
+      })
+      .style("text-transform",function(t){
+        return t.link ? vars.links.font.transform.value : t.style.font.transform.value
+      })
+
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Enter Titles
+  //----------------------------------------------------------------------------
+  if ( vars.dev.value ) print.time("drawing titles")
+  var titles = vars.svg.selectAll("g.d3plus_title")
+    .data(title_data,function(t){
+      return t.type
+    })
+
+  var titleWidth = vars.title.width || vars.width.value-vars.margin.left-vars.margin.right;
+
+  titles.enter().append("g")
+    .attr("class", function(t){
+      return "d3plus_title " + t.type;
+    })
+    .attr("opacity",0)
+    .append("text")
+      .call(style)
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Wrap text and calculate positions, then transition style and opacity
+  //----------------------------------------------------------------------------
+  function getAlign(d) {
+    var align = d.style.font.align;
+    if (align == "center") {
+      return "middle";
+    }
+    else if ((align == "left" && !rtl) || (align == "right" && rtl)) {
+      return "start";
+    }
+    else if ((align == "left" && rtl) || (align == "right" && !rtl)) {
+      return "end";
+    }
+    return align;
+  }
+  titles
+    .each(function(d){
+
+      var container = d3.select(this).select("text").call(style);
+
+      var align = getAlign(d);
+
+      textWrap()
+        .align(align)
+        .container(container)
+        .height(vars.height.value / 8)
+        .size(false)
+        .text(d.value)
+        .width(titleWidth)
+        .draw()
+
+      d.y = vars.margin[d.style.position]
+      vars.margin[d.style.position] += this.getBBox().height + d.style.padding*2
+
+    })
+    .on(events.over,function(t){
+      if (t.link) {
+        d3.select(this)
+          .transition().duration(vars.timing.mouseevents)
+          .style("cursor","pointer")
+          .select("text")
+            .attr("fill",vars.links.hover.color)
+            .attr("font-family",vars.links.hover.family.value)
+            .attr("font-weight",vars.links.hover.weight)
+            .style("text-decoration",vars.links.hover.decoration.value)
+            .style("text-transform",vars.links.hover.transform.value)
+      }
+    })
+    .on(events.out,function(t){
+      if (t.link) {
+        d3.select(this)
+          .transition().duration(vars.timing.mouseevents)
+          .style("cursor","auto")
+          .select("text")
+            .call(style)
+      }
+    })
+    .on(events.click,function(t){
+      if (t.link) {
+        var target = t.link.charAt(0) != "/" ? "_blank" : "_self"
+        window.open(t.link,target)
+      }
+    })
+    .attr("opacity",1)
+    .attr("transform",function(t){
+      var pos = t.style.position,
+          y = pos == "top" ? 0+t.y : vars.height.value-t.y
+      if (pos == "bottom") {
+        y -= this.getBBox().height+t.style.padding
+      }
+      else {
+        y += t.style.padding
+      }
+      var align = getAlign(t);
+      if (align === "start") {
+        var x = vars.margin.left + vars.title.padding;
+      }
+      else {
+        var w = d3.select(this).select("text").node().getBBox().width;
+        if (align === "middle") {
+          x = vars.width.value/2 - titleWidth/2;
+        }
+        else {
+          x = vars.width.value - titleWidth - vars.margin.right - vars.title.padding;
+        }
+      }
+      return "translate("+x+","+y+")";
+    })
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Exit unused titles
+  //----------------------------------------------------------------------------
+  titles.exit().transition().duration(vars.draw.timing)
+    .attr("opacity",0)
+    .remove()
+
+  if ( vars.margin.top > 0 ) {
+    vars.margin.top += vars.title.padding
+  }
+
+  if ( vars.margin.bottom > 0 ) {
+    vars.margin.bottom += vars.title.padding
+  }
+
+  var min = vars.title.height
+  if (min && vars.margin[vars.title.position] < min) {
+    vars.margin[vars.title.position] = min
+  }
+
+  if ( vars.dev.value ) print.timeEnd("drawing titles")
+
+}
+
+},{"../../../client/pointer.coffee":40,"../../../client/rtl.coffee":42,"../../../core/console/print.coffee":53,"../../../core/fetch/value.coffee":68,"../../../textwrap/textwrap.coffee":199}],246:[function(require,module,exports){
+var labels, transform;
+
+labels = require("./labels.coffee");
+
+transform = require("./transform.coffee");
+
+module.exports = function(vars, b, timing) {
+  var aspect, extent, fit, max_scale, min, padding, scale, translate, type;
+  if (!b) {
+    b = vars.zoom.bounds;
+  }
+  if (typeof timing !== "number") {
+    timing = vars.timing.transitions;
+  }
+  vars.zoom.size = {
+    height: b[1][1] - b[0][1],
+    width: b[1][0] - b[0][0]
+  };
+  type = vars.types[vars.type.value];
+  fit = vars.coords.fit.value;
+  if (fit === "auto" || type.requirements.indexOf("coords") < 0) {
+    aspect = d3.max([vars.zoom.size.width / vars.width.viz, vars.zoom.size.height / vars.height.viz]);
+  } else {
+    aspect = vars.zoom.size[fit] / vars["app_" + fit];
+  }
+  min = d3.min([vars.width.viz, vars.height.viz]);
+  padding = type.zoom ? vars.coords.padding * 2 : 0;
+  scale = ((min - padding) / min) / aspect;
+  extent = vars.zoom.behavior.scaleExtent();
+  if (extent[0] === extent[1] || b === vars.zoom.bounds) {
+    vars.zoom.behavior.scaleExtent([scale, scale * 16]);
+  }
+  max_scale = vars.zoom.behavior.scaleExtent()[1];
+  if (scale > max_scale) {
+    scale = max_scale;
+  }
+  vars.zoom.scale = scale;
+  translate = [vars.width.viz / 2 - (vars.zoom.size.width * scale) / 2 - (b[0][0] * scale), vars.height.viz / 2 - (vars.zoom.size.height * scale) / 2 - (b[0][1] * scale)];
+  vars.zoom.translate = translate;
+  vars.zoom.behavior.translate(translate).scale(scale);
+  vars.zoom.size = {
+    height: vars.zoom.bounds[1][1] - vars.zoom.bounds[0][1],
+    width: vars.zoom.bounds[1][0] - vars.zoom.bounds[0][0]
+  };
+  vars.zoom.reset = false;
+  labels(vars);
+  return transform(vars, timing);
+};
+
+
+},{"./labels.coffee":248,"./transform.coffee":251}],247:[function(require,module,exports){
+module.exports = function(data, vars) {
+  var depth, max_depth, nextDepth;
+  max_depth = vars.id.nesting.length - 1;
+  depth = vars.depth.value;
+  nextDepth = vars.id.nesting[vars.depth.value + 1];
+  if (vars.types[vars.type.value].nesting === false) {
+    return 0;
+  } else if ((data.d3plus.merged || (nextDepth in data && depth < max_depth)) && (!data || nextDepth in data)) {
+    return 1;
+  } else if ((depth === max_depth || (data && (!(nextDepth in data)))) && (vars.small || !vars.tooltip.html.value)) {
+    return -1;
+  } else {
+    return 0;
+  }
+};
+
+
+},{}],248:[function(require,module,exports){
+var print;
+
+print = require("../../../core/console/print.coffee");
+
+module.exports = function(vars) {
+  var opacity, scale;
+  if (vars.dev.value) {
+    print.time("determining label visibility");
+  }
+  scale = vars.zoom.behavior.scaleExtent();
+  opacity = function(text) {
+    return text.attr("opacity", function(d) {
+      var size;
+      if (!d) {
+        d = {};
+      }
+      size = parseFloat(d3.select(this).attr("font-size"), 10);
+      d.visible = size * (vars.zoom.scale / scale[1]) >= 2;
+      if (d.visible) {
+        return 1;
+      } else {
+        return 0;
+      }
+    });
+  };
+  if (vars.draw.timing) {
+    vars.g.viz.selectAll("text.d3plus_label").transition().duration(vars.draw.timing).call(opacity);
+  } else {
+    vars.g.viz.selectAll("text.d3plus_label").call(opacity);
+  }
+  if (vars.dev.value) {
+    return print.timeEnd("determining label visibility");
+  }
+};
+
+
+},{"../../../core/console/print.coffee":53}],249:[function(require,module,exports){
+var labels, transform;
+
+labels = require("./labels.coffee");
+
+transform = require("./transform.coffee");
+
+module.exports = function(vars) {
+  var delay, eventType, limits, scale, translate, xmax, xmin, xoffset, ymax, ymin, yoffset;
+  eventType = d3.event.sourceEvent ? d3.event.sourceEvent.type : null;
+  translate = d3.event.translate;
+  scale = d3.event.scale;
+  limits = vars.zoom.bounds;
+  xoffset = (vars.width.viz - (vars.zoom.size.width * scale)) / 2;
+  xmin = (xoffset > 0 ? xoffset : 0);
+  xmax = (xoffset > 0 ? vars.width.viz - xoffset : vars.width.viz);
+  yoffset = (vars.height.viz - (vars.zoom.size.height * scale)) / 2;
+  ymin = (yoffset > 0 ? yoffset : 0);
+  ymax = (yoffset > 0 ? vars.height.viz - yoffset : vars.height.viz);
+  if (translate[0] + limits[0][0] * scale > xmin) {
+    translate[0] = -limits[0][0] * scale + xmin;
+  } else if (translate[0] + limits[1][0] * scale < xmax) {
+    translate[0] = xmax - (limits[1][0] * scale);
+  }
+  if (translate[1] + limits[0][1] * scale > ymin) {
+    translate[1] = -limits[0][1] * scale + ymin;
+  } else if (translate[1] + limits[1][1] * scale < ymax) {
+    translate[1] = ymax - (limits[1][1] * scale);
+  }
+  vars.zoom.behavior.translate(translate).scale(scale);
+  vars.zoom.translate = translate;
+  vars.zoom.scale = scale;
+  if (eventType === "wheel") {
+    delay = (vars.draw.timing ? 100 : 250);
+    clearTimeout(vars.zoom.wheel);
+    vars.zoom.wheel = setTimeout(function() {
+      return labels(vars);
+    }, delay);
+  } else {
+    labels(vars);
+  }
+  if (eventType === "dblclick") {
+    return transform(vars, vars.timing.transitions);
+  } else {
+    return transform(vars, 0);
+  }
+};
+
+
+},{"./labels.coffee":248,"./transform.coffee":251}],250:[function(require,module,exports){
+module.exports = function(vars, event) {
+  var enabled, zoom, zoomable, zoomed;
+  zoom = vars.zoom;
+  if (!event) {
+    event = d3.event;
+  }
+  zoomed = zoom.scale > zoom.behavior.scaleExtent()[0];
+  enabled = vars.types[vars.type.value].zoom && zoom.value && zoom.scroll.value;
+  zoomable = event.touches && event.touches.length > 1 && enabled;
+  if (!zoomable && !zoomed) {
+    event.stopPropagation();
+  }
+};
+
+
+},{}],251:[function(require,module,exports){
+module.exports = function(vars, timing) {
+  var translate;
+  if (typeof timing !== "number") {
+    timing = vars.timing.transitions;
+  }
+  translate = "translate(" + vars.zoom.translate + ")";
+  translate += "scale(" + vars.zoom.scale + ")";
+  if (timing) {
+    return vars.g.viz.transition().duration(timing).attr("transform", translate);
+  } else {
+    return vars.g.viz.attr("transform", translate);
+  }
+};
+
+
+},{}],252:[function(require,module,exports){
+var filter;
+
+filter = require("../../core/methods/filter.coffee");
+
+module.exports = {
+  accepted: [false, Function, Object, String],
+  deprecates: "active_var",
+  mute: filter(true),
+  solo: filter(true),
+  spotlight: {
+    accepted: [Boolean],
+    deprecates: "spotlight",
+    value: false
+  },
+  value: false
+};
+
+
+},{"../../core/methods/filter.coffee":80}],253:[function(require,module,exports){
+module.exports = {
+  accepted: [Object],
+  deprecated: "nesting_aggs",
+  objectAccess: false,
+  value: {}
+};
+
+
+},{}],254:[function(require,module,exports){
+var process;
+
+process = require("../../core/methods/process/data.coffee");
+
+module.exports = {
+  accepted: [false, Array, Object, String],
+  delimiter: {
+    accepted: String,
+    value: "|"
+  },
+  filetype: {
+    accepted: [false, "json", "xml", "html", "csv", "dsv", "tsv", "txt"],
+    value: false
+  },
+  keys: {},
+  process: process,
+  value: false
+};
+
+
+},{"../../core/methods/process/data.coffee":86}],255:[function(require,module,exports){
+var rendering;
+
+rendering = require("../../core/methods/rendering.coffee");
+
+module.exports = {
+  background: {
+    color: "#fafafa",
+    rendering: rendering(),
+    stroke: {
+      color: "#ccc",
+      width: 1
+    }
+  },
+  mirror: {
+    accepted: [Boolean],
+    deprecates: ["mirror_axis", "mirror_axes"],
+    value: false
+  }
+};
+
+
+},{"../../core/methods/rendering.coffee":91}],256:[function(require,module,exports){
+module.exports = {
+  accepted: [String],
+  value: "#ffffff"
+};
+
+
+},{}],257:[function(require,module,exports){
+var filter, scale;
+
+filter = require("../../core/methods/filter.coffee");
+
+scale = require("../../color/scale.coffee");
+
+module.exports = {
+  accepted: [false, Array, Function, Object, String],
+  deprecates: "color_var",
+  focus: "#444444",
+  heatmap: ["#282F6B", "#419391", "#AFD5E8", "#EACE3F", "#B35C1E", "#B22200"],
+  missing: "#eeeeee",
+  mute: filter(true),
+  primary: "#d74b03",
+  range: ["#B22200", "#FFEE8D", "#759143"],
+  scale: {
+    accepted: [Array, Function, "d3plus", "category10", "category20", "category20b", "category20c"],
+    process: function(value) {
+      if (value instanceof Array) {
+        return d3.scale.ordinal().range(value);
+      } else if (value === "d3plus") {
+        return scale;
+      } else if (typeof value === "string") {
+        return d3.scale[value]();
+      } else {
+        return value;
+      }
+    },
+    value: "d3plus"
+  },
+  solo: filter(true),
+  secondary: "#e5b3bb",
+  value: false
+};
+
+
+},{"../../color/scale.coffee":49,"../../core/methods/filter.coffee":80}],258:[function(require,module,exports){
+module.exports = {
+  "accepted": [Array, Function, String],
+  "index": {
+    "accepted": [Boolean],
+    "value": true
+  },
+  "process": function(value, vars) {
+    if (typeof value === "string") value = [value]
+    return value
+  },
+  "value": false
+}
+
+},{}],259:[function(require,module,exports){
+module.exports = {
+  accepted: [Object],
+  objectAccess: false,
+  process: function(value, vars) {
+    var method, setting;
+    for (method in value) {
+      setting = value[method];
+      if (method in vars.self) {
+        vars.self[method](setting);
+      }
+    }
+    return value;
+  },
+  value: {}
+};
+
+
+},{}],260:[function(require,module,exports){
+var d3selection;
+
+d3selection = require("../../util/d3selection.coffee");
+
+module.exports = {
+  accepted: [false, Array, Object, String],
+  id: "default",
+  process: function(value, vars) {
+    if (value === false) {
+      return false;
+    }
+    if (vars.container.id === "default") {
+      vars.self.container({
+        id: "d3plus_" + +new Date()
+      });
+    }
+    if (d3selection(value)) {
+      return value;
+    } else if (value instanceof Array) {
+      return d3.select(value[0][0]);
+    } else {
+      return d3.select(value);
+    }
+  },
+  value: false
+};
+
+
+},{"../../util/d3selection.coffee":207}],261:[function(require,module,exports){
+var filter, process;
+
+filter = require("../../core/methods/filter.coffee");
+
+process = require("../../core/methods/process/data.coffee");
+
+module.exports = {
+  accepted: [false, Array, Function, Object, String],
+  center: [0, 0],
+  filetype: {
+    accepted: ["json"],
+    value: "json"
+  },
+  fit: {
+    accepted: ["auto", "height", "width"],
+    value: "auto"
+  },
+  mute: filter(false),
+  padding: 20,
+  process: process,
+  projection: {
+    accepted: ["mercator", "equirectangular"],
+    value: "mercator"
+  },
+  solo: filter(false),
+  threshold: {
+    accepted: [Number],
+    value: 0.9
+  },
+  value: false
+};
+
+
+},{"../../core/methods/filter.coffee":80,"../../core/methods/process/data.coffee":86}],262:[function(require,module,exports){
+var fetchValue, ie, stringStrip;
+
+fetchValue = require("../../core/fetch/value.coffee");
+
+ie = require("../../client/ie.js");
+
+stringStrip = require("../../string/strip.js");
+
+module.exports = {
+  accepted: [void 0, true, Array, String],
+  chainable: false,
+  data: [],
+  process: function(value, vars) {
+    var blob, c, col, columns, csv_data, csv_to_return, d, dataString, encodedUri, i, j, k, l, len, len1, len2, len3, len4, len5, len6, len7, link, m, max_filename_len, n, node, o, p, q, ref, ref1, ref2, row, title, titles, val;
+    if (vars.returned === void 0) {
+      return [];
+    }
+    value = value || vars.cols.value;
+    if (value instanceof Array) {
+      columns = value;
+    } else if (typeof value === "string") {
+      columns = [value];
+    }
+    csv_to_return = [];
+    titles = [];
+    if (vars.title.value) {
+      title = vars.title.value;
+      if (typeof title === "function") {
+        title = title(vars.self);
+      }
+      title = stringStrip(title);
+      max_filename_len = 250;
+      title = title.substr(0, max_filename_len);
+    } else {
+      title = "D3plus Visualization Data";
+    }
+    if (value === true) {
+      columns = d3.keys(vars.data.keys);
+      csv_to_return.push(columns);
+      ref = vars.data.value;
+      for (j = 0, len = ref.length; j < len; j++) {
+        d = ref[j];
+        row = [];
+        for (k = 0, len1 = columns.length; k < len1; k++) {
+          c = columns[k];
+          val = d[c];
+          if (vars.data.keys[c] === "string") {
+            val = '"' + val + '"';
+          }
+          row.push(val);
+        }
+        csv_to_return.push(row);
+      }
+    } else {
+      if (!columns) {
+        columns = [vars.id.value];
+        if (vars.time.value) {
+          columns.push(vars.time.value);
+        }
+        if (vars.size.value) {
+          columns.push(vars.size.value);
+        }
+        if (vars.text.value) {
+          columns.push(vars.text.value);
+        }
+      }
+      for (l = 0, len2 = columns.length; l < len2; l++) {
+        c = columns[l];
+        titles.push(vars.format.value(c));
+      }
+      csv_to_return.push(titles);
+      ref1 = vars.returned.nodes;
+      for (m = 0, len3 = ref1.length; m < len3; m++) {
+        node = ref1[m];
+        if ((node.values != null) && node.values instanceof Array) {
+          ref2 = node.values;
+          for (n = 0, len4 = ref2.length; n < len4; n++) {
+            val = ref2[n];
+            row = [];
+            for (o = 0, len5 = columns.length; o < len5; o++) {
+              col = columns[o];
+              val = fetchValue(vars, val, col);
+              if (typeof val === "string") {
+                val = '"' + val + '"';
+              }
+              row.push(val);
+            }
+            csv_to_return.push(row);
+          }
+        } else {
+          row = [];
+          for (p = 0, len6 = columns.length; p < len6; p++) {
+            col = columns[p];
+            row.push(fetchValue(vars, node, col));
+          }
+          csv_to_return.push(row);
+        }
+      }
+    }
+    csv_data = "data:text/csv;charset=utf-8,";
+    for (i = q = 0, len7 = csv_to_return.length; q < len7; i = ++q) {
+      c = csv_to_return[i];
+      dataString = c.join(",");
+      csv_data += (i < csv_to_return.length ? dataString + "\n" : dataString);
+    }
+    if (ie) {
+      blob = new Blob([csv_data], {
+        type: "text/csv;charset=utf-8;"
+      });
+      navigator.msSaveBlob(blob, title + ".csv");
+    } else {
+      encodedUri = encodeURI(csv_data);
+      link = document.createElement("a");
+      link.setAttribute("href", encodedUri);
+      link.setAttribute("download", title + ".csv");
+      link.click();
+    }
+    this.data = csv_to_return;
+    return columns;
+  },
+  value: void 0
+};
+
+
+},{"../../client/ie.js":39,"../../core/fetch/value.coffee":68,"../../string/strip.js":174}],263:[function(require,module,exports){
+var process;
+
+process = require("../../core/methods/process/data.coffee");
+
+module.exports = {
+  accepted: [false, Array, Function, String],
+  cache: {},
+  delimiter: {
+    accepted: [String],
+    value: "|"
+  },
+  donut: {
+    size: 0.35
+  },
+  filetype: {
+    accepted: [false, "json", "xml", "html", "csv", "dsv", "tsv", "txt"],
+    value: false
+  },
+  filters: [],
+  keys: {},
+  mute: [],
+  large: 400,
+  opacity: 0.9,
+  padding: {
+    accepted: [Number],
+    value: 1
+  },
+  process: function(value, vars) {
+    return process(value, vars, this);
+  },
+  solo: [],
+  stroke: {
+    width: 1
+  },
+  value: false
+};
+
+
+},{"../../core/methods/process/data.coffee":86}],264:[function(require,module,exports){
+module.exports = {
+  accepted: [Function, Number],
+  value: 0
+};
+
+
+},{}],265:[function(require,module,exports){
+module.exports = {
+  accepted: [false, Function, Object],
+  value: false
+};
+
+
+},{}],266:[function(require,module,exports){
+module.exports = {
+  accepted: [Boolean],
+  value: false
+};
+
+
+},{}],267:[function(require,module,exports){
+var print        = require("../../core/console/print.coffee"),
+    stringFormat = require("../../string/format.js")
+
+module.exports = {
+  "accepted" : [ undefined , Function ],
+  "first"    : true,
+  "frozen"   : false,
+  "process"  : function (value, vars) {
+
+    if ( this.initialized === false ) {
+      this.initialized = true
+      return value
+    }
+
+    if ( value === undefined && typeof this.value === "function" ) {
+      value = this.value
+    }
+
+    if ( vars.container.value === false ) {
+
+      var str = vars.format.locale.value.dev.setContainer
+      print.warning( str , "container" )
+
+    }
+    else if ( vars.container.value.empty() ) {
+
+      var str = vars.format.locale.value.dev.noContainer
+      print.warning( stringFormat(str,"\""+vars.container.value+"\"") , "container" )
+
+    }
+    else {
+
+      if ( vars.dev.value ) print.time("total draw time");
+
+      vars.container.value.call(vars.self);
+
+    }
+
+    if ( typeof value === "function" && vars.history.chain.length ) {
+
+      var changesObject = {}
+      changes.forEach(function(c){
+        var method = c.method
+        delete c.method
+        changesObject[method] = c
+      })
+
+      value(changesObject)
+
+      vars.history.chain = []
+
+    }
+
+    return value
+
+  },
+  "update"   : true,
+  "value"    : undefined
+}
+
+},{"../../core/console/print.coffee":53,"../../string/format.js":172}],268:[function(require,module,exports){
+var process = require("../../core/methods/process/data.coffee");
+
+module.exports = {
+  "accepted": [false, Array, Function, String],
+  "arrows":   {
+    "accepted":  [ Boolean , Number ],
+    "direction": {
+      "accepted": [ "source" , "target" ],
+      "value":    "target"
+    },
+    "value": false
+  },
+  "color":       "#d0d0d0",
+  "connections": function(focus,id,objects) {
+
+    var self = this
+
+    if (!self.value) {
+      return []
+    }
+
+    if (!id) var id = "id"
+
+    var edges = self.restricted || self.value,
+        targets = []
+
+    if (!focus) {
+      return edges
+    }
+
+    var connections = edges.filter(function(edge){
+
+      var match = false
+
+      if (edge[self.source][id] == focus) {
+        match = true
+        if (objects) {
+          targets.push(edge[self.target])
+        }
+      }
+      else if (edge[self.target][id] == focus) {
+        match = true
+        if (objects) {
+          targets.push(edge[self.source])
+        }
+      }
+
+      return match
+
+    })
+
+    return objects ? targets : connections
+
+  },
+  "delimiter": {
+    "accepted": [ String ],
+    "value":    "|"
+  },
+  "filetype": {
+    "accepted": [false, "json", "xml","html", "csv", "dsv", "tsv", "txt"],
+    "value":    false
+  },
+  "interpolate": {
+    "accepted": ["basis", "cardinal", "linear", "monotone", "step"],
+    "value":    "basis"
+  },
+  "label": false,
+  "large": 100,
+  "limit": {
+    "accepted": [false, Function, Number],
+    "value":    false
+  },
+  "opacity": {
+    "accepted": [Function, Number, String],
+    "min": {
+      "accepted": [Number],
+      "value": 0.25
+    },
+    "scale": {
+      "accepted": [Function],
+      "value": d3.scale.linear()
+    },
+    "value": 1
+  },
+  "process":  process,
+  "size": {
+    "accepted": [false, Number, String],
+    "min": 1,
+    "scale": 0.5,
+    "value": false
+  },
+  "source":   "source",
+  "strength": {
+    "accepted": [false, Function, Number, String],
+    "value":    false
+  },
+  "target": "target",
+  "value":  false
+};
+
+},{"../../core/methods/process/data.coffee":86}],269:[function(require,module,exports){
+module.exports = {
+  accepted: [Boolean, String],
+  value: false
+};
+
+
+},{}],270:[function(require,module,exports){
+module.exports = {
+  accepted: [false, Array, Function, Number, String],
+  deprecates: "highlight",
+  process: function(value) {
+    if (value === false) {
+      return [];
+    } else if (value instanceof Array) {
+      return value;
+    } else {
+      return [value];
+    }
+  },
+  tooltip: {
+    accepted: [Boolean],
+    value: true
+  },
+  value: []
+};
+
+
+},{}],271:[function(require,module,exports){
+var align, decoration, family, transform;
+
+align = require("../../core/methods/font/align.coffee");
+
+decoration = require("../../core/methods/font/decoration.coffee");
+
+family = require("../../core/methods/font/family.coffee");
+
+transform = require("../../core/methods/font/transform.coffee");
+
+module.exports = {
+  align: align(),
+  color: "#444444",
+  decoration: decoration(),
+  family: family(),
+  secondary: {
+    align: align(),
+    color: "#444444",
+    decoration: decoration(),
+    family: family(),
+    size: 12,
+    spacing: 0,
+    transform: transform(),
+    weight: 200
+  },
+  size: 12,
+  spacing: 0,
+  transform: transform(),
+  weight: 200
+};
+
+
+},{"../../core/methods/font/align.coffee":81,"../../core/methods/font/decoration.coffee":82,"../../core/methods/font/family.coffee":83,"../../core/methods/font/transform.coffee":85}],272:[function(require,module,exports){
+var decoration, family, transform;
+
+family = require("../../core/methods/font/family.coffee");
+
+decoration = require("../../core/methods/font/decoration.coffee");
+
+transform = require("../../core/methods/font/transform.coffee");
+
+module.exports = {
+  accepted: [false, Number, String],
+  font: {
+    align: "center",
+    color: "#444",
+    decoration: decoration(),
+    family: family(),
+    size: 11,
+    transform: transform(),
+    weight: 200
+  },
+  link: false,
+  padding: 0,
+  position: "bottom",
+  value: false
+};
+
+
+},{"../../core/methods/font/decoration.coffee":82,"../../core/methods/font/family.coffee":83,"../../core/methods/font/transform.coffee":85}],273:[function(require,module,exports){
+var formatNumber, locale, mergeObject, titleCase;
+
+formatNumber = require("../../number/format.coffee");
+
+locale = require("../../core/locale/locale.coffee");
+
+mergeObject = require("../../object/merge.coffee");
+
+titleCase = require("../../string/title.coffee");
+
+module.exports = {
+  accepted: [Function, String],
+  affixes: {
+    accepted: [Object],
+    objectAccess: false,
+    value: {}
+  },
+  deprecates: ["number_format", "text_format"],
+  locale: {
+    accepted: function() {
+      return d3.keys(locale);
+    },
+    process: function(value) {
+      var defaultLocale, returnObject;
+      defaultLocale = "en_US";
+      returnObject = locale[defaultLocale];
+      if (value !== defaultLocale) {
+        returnObject = mergeObject(returnObject, locale[value]);
+      }
+      this.language = value;
+      return returnObject;
+    },
+    value: "en_US"
+  },
+  number: {
+    accepted: [false, Function],
+    value: false
+  },
+  process: function(value, vars) {
+    if (typeof value === "string") {
+      vars.self.format({
+        locale: value
+      });
+    } else {
+      if (typeof value === "function") {
+        return value;
+      }
+    }
+    return this.value;
+  },
+  text: {
+    accepted: [false, Function],
+    value: false
+  },
+  value: function(value, opts) {
+    var f, v, vars;
+    if (!opts) {
+      opts = {};
+    }
+    if (!opts.locale) {
+      opts.locale = this.locale.value;
+    }
+    vars = opts.vars || {};
+    if (vars.time && vars.time.value && opts.key === vars.time.value) {
+      v = value.constructor === Date ? value : new Date(value);
+      return vars.data.time.format(v);
+    } else if (typeof value === "number") {
+      f = this.number.value || formatNumber;
+      return f(value, opts);
+    } else if (typeof value === "string") {
+      f = this.text.value || titleCase;
+      return f(value, opts);
+    } else {
+      return JSON.stringify(value);
+    }
+  }
+};
+
+
+},{"../../core/locale/locale.coffee":78,"../../number/format.coffee":169,"../../object/merge.coffee":170,"../../string/title.coffee":175}],274:[function(require,module,exports){
+module.exports = {
+  accepted: [false, Number],
+  max: 600,
+  secondary: false,
+  small: 200,
+  value: false
+};
+
+
+},{}],275:[function(require,module,exports){
+var align, decoration, family, filter, position, rendering, transform;
+
+align = require("../../../core/methods/font/align.coffee");
+
+decoration = require("../../../core/methods/font/decoration.coffee");
+
+family = require("../../../core/methods/font/family.coffee");
+
+filter = require("../../../core/methods/filter.coffee");
+
+position = require("../../../core/methods/font/position.coffee");
+
+rendering = require("../../../core/methods/rendering.coffee");
+
+transform = require("../../../core/methods/font/transform.coffee");
+
+module.exports = function(axis) {
+  return {
+    accepted: [Array, Boolean, Function, Object, String],
+    affixes: {
+      accepted: [Boolean],
+      separator: {
+        accepted: [Boolean, Array],
+        value: true
+      },
+      value: false
+    },
+    axis: {
+      accepted: [Boolean],
+      color: "#444",
+      font: {
+        color: false,
+        decoration: decoration(false),
+        family: family(""),
+        size: false,
+        transform: transform(false),
+        weight: false
+      },
+      rendering: rendering(),
+      value: true
+    },
+    dataFilter: true,
+    deprecates: [axis + "axis", axis + "axis_val", axis + "axis_var"],
+    domain: {
+      accepted: [false, Array],
+      value: false
+    },
+    grid: {
+      accepted: [Boolean],
+      color: "#ccc",
+      rendering: rendering(),
+      value: true
+    },
+    label: {
+      accepted: [Boolean, String],
+      fetch: function(vars) {
+        if (this.value === true) {
+          return vars.format.value(vars[axis].value, {
+            key: axis,
+            vars: vars
+          });
+        }
+        return this.value;
+      },
+      font: {
+        color: "#444",
+        decoration: decoration(),
+        family: family(),
+        size: 12,
+        transform: transform(),
+        weight: 200
+      },
+      padding: 3,
+      value: true
+    },
+    lines: {
+      accept: [false, Array, Number, Object],
+      dasharray: {
+        accepted: [Array, String],
+        process: function(value) {
+          if (value instanceof Array) {
+            value = value.filter(function(d) {
+              return !isNaN(d);
+            });
+            value = value.length ? value.join(", ") : "none";
+          }
+          return value;
+        },
+        value: "10, 10"
+      },
+      color: "#888",
+      font: {
+        align: align("right"),
+        color: "#444",
+        background: {
+          accepted: [Boolean],
+          value: true
+        },
+        decoration: decoration(),
+        family: family(),
+        padding: {
+          accepted: [Number],
+          value: 10
+        },
+        position: position("middle"),
+        size: 12,
+        transform: transform(),
+        weight: 200
+      },
+      process: Array,
+      rendering: rendering(),
+      width: 1,
+      value: []
+    },
+    mouse: {
+      accept: [Boolean],
+      dasharray: {
+        accepted: [Array, String],
+        process: function(value) {
+          if (value instanceof Array) {
+            value = value.filter(function(d) {
+              return !isNaN(d);
+            });
+            value = value.length ? value.join(", ") : "none";
+          }
+          return value;
+        },
+        value: "none"
+      },
+      rendering: rendering(),
+      width: 2,
+      value: true
+    },
+    mute: filter(true),
+    padding: {
+      accepted: [Number],
+      value: 0.1
+    },
+    range: {
+      accepted: [false, Array],
+      value: false
+    },
+    scale: {
+      accepted: ["linear", "log", "discrete", "share"],
+      deprecates: ["layout", "unique_axis", axis + "axis_scale"],
+      process: function(value, vars) {
+        var i, len, ref, scale;
+        ref = ["log", "discrete", "share"];
+        for (i = 0, len = ref.length; i < len; i++) {
+          scale = ref[i];
+          if (scale === value) {
+            vars.axes[scale] = axis;
+          } else {
+            if (vars.axes[scale] === axis) {
+              vars.axes[scale] = false;
+            }
+          }
+        }
+        if (value === "discrete") {
+          vars.axes.opposite = (axis === "x" ? "y" : "x");
+        }
+        return value;
+      },
+      value: "linear"
+    },
+    solo: filter(true),
+    stacked: {
+      accepted: [Boolean],
+      process: function(value, vars) {
+        if (!value && vars.axes.stacked === axis) {
+          vars.axes.stacked = false;
+        } else {
+          if (value) {
+            vars.axes.stacked = axis;
+          }
+        }
+        return value;
+      },
+      value: false
+    },
+    ticks: {
+      color: "#ccc",
+      font: {
+        color: "#666",
+        decoration: decoration(),
+        family: family(),
+        size: 10,
+        transform: transform(),
+        weight: 200
+      },
+      rendering: rendering(),
+      size: 10,
+      width: 1
+    },
+    value: false,
+    zerofill: {
+      accepted: [Boolean],
+      value: false
+    }
+  };
+};
+
+
+},{"../../../core/methods/filter.coffee":80,"../../../core/methods/font/align.coffee":81,"../../../core/methods/font/decoration.coffee":82,"../../../core/methods/font/family.coffee":83,"../../../core/methods/font/position.coffee":84,"../../../core/methods/font/transform.coffee":85,"../../../core/methods/rendering.coffee":91}],276:[function(require,module,exports){
+module.exports = {
+  accepted: [Boolean],
+  back: function() {
+    if (this.states.length) {
+      return this.states.pop()();
+    }
+  },
+  chain: [],
+  reset: function() {
+    var results;
+    results = [];
+    while (this.states.length) {
+      results.push(this.states.pop()());
+    }
+    return results;
+  },
+  states: [],
+  value: true
+};
+
+
+},{}],277:[function(require,module,exports){
+var process;
+
+process = require("../../core/methods/process/icon.coffee");
+
+module.exports = {
+  accepted: [false, Array, Function, Object, String],
+  back: {
+    accepted: [false, String],
+    fallback: "&#x276e;",
+    opacity: 1,
+    process: process,
+    rotate: 0,
+    value: "fa-angle-left"
+  },
+  deprecates: "icon_var",
+  style: {
+    accepted: [Object, String],
+    deprecates: "icon_style",
+    value: "default"
+  },
+  value: false
+};
+
+
+},{"../../core/methods/process/icon.coffee":88}],278:[function(require,module,exports){
+var filter;
+
+filter = require("../../core/methods/filter.coffee");
+
+module.exports = {
+  accepted: [Array, String],
+  dataFilter: true,
+  deprecates: ["id_var", "nesting"],
+  grouping: {
+    accepted: [Boolean],
+    value: true
+  },
+  mute: filter(true),
+  nesting: ["id"],
+  solo: filter(true),
+  value: "id"
+};
+
+
+},{"../../core/methods/filter.coffee":80}],279:[function(require,module,exports){
+var decoration, family, transform;
+
+decoration = require("../../core/methods/font/decoration.coffee");
+
+family = require("../../core/methods/font/family.coffee");
+
+transform = require("../../core/methods/font/transform.coffee");
+
+module.exports = {
+  accepted: [Boolean],
+  align: {
+    accepted: ["start", "middle", "end", "left", "center", "right"],
+    process: function(value) {
+      var css;
+      css = ["left", "center", "right"].indexOf(value);
+      if (css >= 0) {
+        value = this.accepted[css];
+      }
+      return value;
+    },
+    value: "middle"
+  },
+  font: {
+    decoration: decoration(),
+    family: family(),
+    size: 11,
+    transform: transform(),
+    weight: 200
+  },
+  padding: 7,
+  resize: {
+    accepted: [Boolean],
+    value: true
+  },
+  text: {
+    accepted: [false, Function, String],
+    value: false
+  },
+  segments: 2,
+  valign: {
+    accepted: [false, "top", "middle", "bottom"],
+    value: "middle"
+  },
+  value: true
+};
+
+
+},{"../../core/methods/font/decoration.coffee":82,"../../core/methods/font/family.coffee":83,"../../core/methods/font/transform.coffee":85}],280:[function(require,module,exports){
+var family;
+
+family = require("../../core/methods/font/family.coffee");
+
+module.exports = {
+  accepted: [Boolean],
+  align: "middle",
+  filters: {
+    accepted: [Boolean],
+    value: false
+  },
+  font: {
+    align: "middle",
+    color: "#444444",
+    family: family(),
+    size: 10,
+    weight: 200
+  },
+  gradient: {
+    height: 10
+  },
+  icons: {
+    accepted: [Boolean],
+    value: true
+  },
+  order: {
+    accepted: ["color", "id", "size", "text"],
+    sort: {
+      accepted: ["asc", "desc"],
+      value: "asc"
+    },
+    value: "color"
+  },
+  size: [8, 30],
+  tooltip: {
+    accepted: [Boolean],
+    value: true
+  },
+  text: {
+    accepted: [false, Function, String],
+    value: false
+  },
+  value: true
+};
+
+
+},{"../../core/methods/font/family.coffee":83}],281:[function(require,module,exports){
+var decoration, family, transform;
+
+decoration = require("../../core/methods/font/decoration.coffee");
+
+family = require("../../core/methods/font/family.coffee");
+
+transform = require("../../core/methods/font/transform.coffee");
+
+module.exports = {
+  font: {
+    color: "#444444",
+    decoration: decoration(),
+    family: family(),
+    transform: transform(),
+    weight: 200
+  },
+  hover: {
+    color: "#444444",
+    decoration: decoration(),
+    family: family(),
+    transform: transform(),
+    weight: 200
+  }
+};
+
+
+},{"../../core/methods/font/decoration.coffee":82,"../../core/methods/font/family.coffee":83,"../../core/methods/font/transform.coffee":85}],282:[function(require,module,exports){
+var process;
+
+process = require("../../core/methods/process/margin.coffee");
+
+module.exports = {
+  accepted: [Number, Object, String],
+  process: function(value) {
+    var userValue;
+    if (value === void 0) {
+      value = this.value;
+    }
+    userValue = value;
+    process(value, this);
+    return userValue;
+  },
+  value: 0
+};
+
+
+},{"../../core/methods/process/margin.coffee":89}],283:[function(require,module,exports){
+var decoration, family, transform;
+
+decoration = require("../../core/methods/font/decoration.coffee");
+
+family = require("../../core/methods/font/family.coffee");
+
+transform = require("../../core/methods/font/transform.coffee");
+
+module.exports = {
+  accepted: [Boolean, String],
+  branding: {
+    accepted: [Boolean],
+    value: false
+  },
+  font: {
+    color: "#444",
+    decoration: decoration(),
+    family: family(),
+    size: 16,
+    transform: transform(),
+    weight: 200
+  },
+  padding: 5,
+  style: {
+    accepted: [false, "small", "large"],
+    value: false
+  },
+  value: true
+};
+
+
+},{"../../core/methods/font/decoration.coffee":82,"../../core/methods/font/family.coffee":83,"../../core/methods/font/transform.coffee":85}],284:[function(require,module,exports){
+module.exports = {
+  accepted: [Boolean],
+  click: {
+    accepted: [Boolean, Function],
+    value: true
+  },
+  move: {
+    accepted: [Boolean, Function],
+    value: true
+  },
+  out: {
+    accepted: [Boolean, Function],
+    value: true
+  },
+  over: {
+    accepted: [Boolean, Function],
+    value: true
+  },
+  value: true
+};
+
+
+},{}],285:[function(require,module,exports){
+var process;
+
+process = require("../../core/methods/process/data.coffee");
+
+module.exports = {
+  accepted: [false, Array, Function, String],
+  delimiter: {
+    accepted: [String],
+    value: "|"
+  },
+  filetype: {
+    accepted: [false, "json", "xml", "html", "csv", "dsv", "tsv", "txt"],
+    value: false
+  },
+  overlap: 0.6,
+  process: process,
+  value: false
+};
+
+
+},{"../../core/methods/process/data.coffee":86}],286:[function(require,module,exports){
+module.exports = {
+  accepted: [Boolean, Function, String],
+  agg: {
+    accepted: [false, Function, "sum", "min", "max", "mean", "median"],
+    value: false
+  },
+  deprecates: ["sort"],
+  sort: {
+    accepted: ["asc", "desc"],
+    value: "desc"
+  },
+  value: false
+};
+
+
+},{}],287:[function(require,module,exports){
+var rendering;
+
+rendering = require("../../core/methods/rendering.coffee");
+
+module.exports = {
+  accepted: function(vars) {
+    var list;
+    list = vars.types[vars.type.value].shapes;
+    if (list && !(list instanceof Array)) {
+      list = [list];
+    }
+    if (list.length) {
+      return list;
+    } else {
+      return ["square"];
+    }
+  },
+  interpolate: {
+    accepted: ["basis", "basis-open", "cardinal", "cardinal-open", "linear", "monotone", "step", "step-before", "step-after"],
+    deprecates: "stack_type",
+    value: "linear"
+  },
+  rendering: rendering(),
+  value: false
+};
+
+
+},{"../../core/methods/rendering.coffee":91}],288:[function(require,module,exports){
+var filter;
+
+filter = require("../../core/methods/filter.coffee");
+
+module.exports = {
+  accepted: [false, Function, Number, Object, String],
+  dataFilter: true,
+  deprecates: ["value", "value_var"],
+  mute: filter(true),
+  scale: {
+    accepted: [Function],
+    deprecates: "size_scale",
+    max: {
+      accepted: [Function, Number],
+      value: function(vars) {
+        return Math.floor(d3.max([d3.min([vars.width.viz, vars.height.viz]) / 15, 6]));
+      }
+    },
+    min: {
+      accepted: [Function, Number],
+      value: 3
+    },
+    value: d3.scale.sqrt()
+  },
+  solo: filter(true),
+  threshold: {
+    accepted: [Boolean, Function, Number],
+    value: false
+  },
+  value: false
+};
+
+
+},{"../../core/methods/filter.coffee":80}],289:[function(require,module,exports){
+module.exports = {
+  value: false
+};
+
+
+},{}],290:[function(require,module,exports){
+var filter;
+
+filter = require("../../core/methods/filter.coffee");
+
+module.exports = {
+  accepted: [false, Function, Object, String],
+  deprecates: ["else_var", "else"],
+  mute: filter(true),
+  solo: filter(true),
+  value: false
+};
+
+
+},{"../../core/methods/filter.coffee":80}],291:[function(require,module,exports){
+var filter;
+
+filter = require("../../core/methods/filter.coffee");
+
+module.exports = {
+  accepted: [Array, Boolean, Function, Object, String],
+  deprecates: ["name_array", "text_var"],
+  nesting: true,
+  mute: filter(true),
+  solo: filter(true),
+  value: false
+};
+
+
+},{"../../core/methods/filter.coffee":80}],292:[function(require,module,exports){
+var filter;
+
+filter = require("../../core/methods/filter.coffee");
+
+module.exports = {
+  accepted: [Array, Boolean, Function, Object, String],
+  dataFilter: true,
+  deprecates: ["year", "year_var"],
+  fixed: {
+    accepted: [Boolean],
+    deprecates: ["static_axis", "static_axes"],
+    value: true
+  },
+  format: {
+    accepted: [false, Array, Function, String],
+    value: false
+  },
+  mute: filter(false),
+  solo: filter(false),
+  value: false
+};
+
+
+},{"../../core/methods/filter.coffee":80}],293:[function(require,module,exports){
+module.exports = {
+  accepted: [Boolean],
+  align: "middle",
+  hover: {
+    accepted: ["all-scroll", "col-resize", "crosshair", "default", "grab", "grabbing", "move", "pointer"],
+    value: "pointer"
+  },
+  handles: {
+    accepted: [Boolean],
+    color: "#666",
+    opacity: 1,
+    size: 3,
+    stroke: "#666",
+    value: true
+  },
+  height: {
+    accepted: [false, Number],
+    value: false
+  },
+  play: {
+    accepted: [Boolean],
+    icon: {
+      accepted: [false, String],
+      awesome: "",
+      fallback: "►"
+    },
+    pause: {
+      accepted: [false, String],
+      awesome: "",
+      fallback: "❚❚"
+    },
+    timing: {
+      accepted: [Number],
+      value: 1500
+    },
+    value: true
+  },
+  value: true
+};
+
+
+},{}],294:[function(require,module,exports){
+module.exports = {
+  mouseevents: 60,
+  transitions: 600,
+  ui: 200
+};
+
+
+},{}],295:[function(require,module,exports){
+var decoration, family, stringStrip, transform;
+
+decoration = require("../../core/methods/font/decoration.coffee");
+
+family = require("../../core/methods/font/family.coffee");
+
+transform = require("../../core/methods/font/transform.coffee");
+
+stringStrip = require("../../string/strip.js");
+
+module.exports = {
+  accepted: [false, Function, String],
+  font: {
+    align: "center",
+    color: "#444444",
+    decoration: decoration(),
+    family: family(),
+    size: 16,
+    transform: transform(),
+    weight: 400
+  },
+  height: false,
+  link: false,
+  padding: 2,
+  position: "top",
+  process: function(value, vars) {
+    var id;
+    if (vars.container.id.indexOf("default") === 0 && value) {
+      id = stringStrip(value).toLowerCase();
+      vars.self.container({
+        id: id
+      });
+    }
+    return value;
+  },
+  sub: {
+    accepted: [false, Function, String],
+    deprecates: "sub_title",
+    font: {
+      align: "center",
+      color: "#444444",
+      decoration: decoration(),
+      family: family(),
+      size: 12,
+      transform: transform(),
+      weight: 200
+    },
+    link: false,
+    padding: 1,
+    position: "top",
+    value: false
+  },
+  total: {
+    accepted: [Boolean, Object],
+    deprecates: "total_bar",
+    font: {
+      align: "center",
+      color: "#444444",
+      decoration: decoration(),
+      family: family(),
+      size: 12,
+      transform: transform(),
+      weight: 200,
+      value: false
+    },
+    link: false,
+    padding: 1,
+    position: "top",
+    value: false
+  },
+  width: false,
+  value: false
+};
+
+
+},{"../../core/methods/font/decoration.coffee":82,"../../core/methods/font/family.coffee":83,"../../core/methods/font/transform.coffee":85,"../../string/strip.js":174}],296:[function(require,module,exports){
+var family, transform;
+
+family = require("../../core/methods/font/family.coffee");
+
+transform = require("../../core/methods/font/transform.coffee");
+
+module.exports = {
+  accepted: [Boolean, Array, Function, Object, String],
+  anchor: "top center",
+  background: "#ffffff",
+  children: {
+    accepted: [Boolean],
+    value: true
+  },
+  connections: {
+    accepted: [Boolean],
+    value: true
+  },
+  curtain: {
+    color: "#ffffff",
+    opacity: 0.8
+  },
+  deprecates: "tooltip_info",
+  extent: {
+    accepted: [Boolean],
+    value: true
+  },
+  font: {
+    color: "#444",
+    family: family(),
+    size: 12,
+    transform: transform(),
+    weight: 200
+  },
+  html: {
+    accepted: [false, Function, Object, String],
+    deprecates: "click_function",
+    value: false
+  },
+  iqr: {
+    accepted: [Boolean],
+    value: true
+  },
+  large: 250,
+  share: {
+    accepted: [Boolean],
+    value: true
+  },
+  size: {
+    accepted: [Boolean],
+    value: true
+  },
+  small: 225,
+  sub: {
+    accepted: [false, Function, String],
+    value: false
+  },
+  value: true
+};
+
+
+},{"../../core/methods/font/family.coffee":83,"../../core/methods/font/transform.coffee":85}],297:[function(require,module,exports){
+var filter;
+
+filter = require("../../core/methods/filter.coffee");
+
+module.exports = {
+  accepted: [false, Function, Object, String],
+  deprecates: ["total_var"],
+  mute: filter(true),
+  solo: filter(true),
+  value: false
+};
+
+
+},{"../../core/methods/filter.coffee":80}],298:[function(require,module,exports){
+module.exports = {
+  accepted: function(vars) {
+    return d3.keys(vars.types);
+  },
+  mode: {
+    accepted: function(vars) {
+      return vars.types[vars.type.value].modes || [false];
+    },
+    value: false
+  },
+  value: "tree_map"
+};
+
+
+},{}],299:[function(require,module,exports){
+var align, decoration, family, transform;
+
+family = require("../../core/methods/font/family.coffee");
+
+align = require("../../core/methods/font/align.coffee");
+
+decoration = require("../../core/methods/font/decoration.coffee");
+
+transform = require("../../core/methods/font/transform.coffee");
+
+module.exports = {
+  accepted: [Array, Boolean],
+  align: align("center"),
+  border: 1,
+  color: {
+    primary: {
+      process: function(value, vars) {
+        var primary;
+        primary = this.value;
+        if (!vars.ui.color.secondary.value) {
+          vars.ui.color.secondary.value = d3.rgb(primary).darker(0.75).toString();
+        }
+        return value;
+      },
+      value: "#ffffff"
+    },
+    secondary: {
+      value: false
+    }
+  },
+  display: {
+    acceped: ["block", "inline-block"],
+    value: "inline-block"
+  },
+  font: {
+    align: "center",
+    color: "#444",
+    decoration: decoration(),
+    family: family(),
+    size: 11,
+    transform: transform(),
+    weight: 200
+  },
+  margin: 5,
+  padding: 5,
+  position: {
+    accepted: ["top", "right", "bottom", "left"],
+    value: "bottom"
+  },
+  value: false
+};
+
+
+},{"../../core/methods/font/align.coffee":81,"../../core/methods/font/decoration.coffee":82,"../../core/methods/font/family.coffee":83,"../../core/methods/font/transform.coffee":85}],300:[function(require,module,exports){
+module.exports = {
+  accepted: [false, Number],
+  secondary: false,
+  small: 200,
+  value: false
+};
+
+
+},{}],301:[function(require,module,exports){
+module.exports = {
+  "accepted"   : [ Boolean ],
+  "behavior"   : d3.behavior.zoom().scaleExtent([ 1 , 1 ]).duration(0),
+  "click"      : {
+    "accepted" : [ Boolean ],
+    "value"    : true
+  },
+  "pan"        : {
+    "accepted" : [ Boolean ],
+    "value"    : true
+  },
+  "scroll"     : {
+    "accepted"   : [ Boolean ],
+    "deprecates" : "scroll_zoom",
+    "value"      : true
+  },
+  "value"      : true
+}
+
+},{}],302:[function(require,module,exports){
+var bar, fetchValue, graph, nest, stack, uniques,
+  indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+fetchValue = require("../../core/fetch/value.coffee");
+
+graph = require("./helpers/graph/draw.coffee");
+
+nest = require("./helpers/graph/nest.coffee");
+
+stack = require("./helpers/graph/stack.coffee");
+
+uniques = require("../../util/uniques.coffee");
+
+bar = function(vars) {
+  var bars, base, cMargin, d, data, discrete, discreteVal, divisions, domains, h, i, j, k, len, len1, length, maxSize, mod, nested, oMargin, offset, oppVal, opposite, padding, point, ref, ref1, space, value, w, x, zero;
+  discrete = vars.axes.discrete;
+  h = discrete === "x" ? "height" : "width";
+  w = discrete === "x" ? "width" : "height";
+  opposite = vars.axes.opposite;
+  cMargin = discrete === "x" ? "left" : "top";
+  oMargin = discrete === "x" ? "top" : "left";
+  graph(vars, {
+    buffer: true,
+    zero: vars.axes.opposite
+  });
+  domains = vars.x.domain.viz.concat(vars.y.domain.viz);
+  if (domains.indexOf(void 0) >= 0) {
+    return [];
+  }
+  nested = vars.data.viz;
+  if (vars.axes.stacked) {
+    stack(vars, nested);
+  }
+  space = vars.axes[w] / vars[vars.axes.discrete].ticks.values.length;
+  padding = vars[vars.axes.discrete].padding.value;
+  if (padding < 1) {
+    padding *= space;
+  }
+  if (padding * 2 > space) {
+    padding = space * 0.1;
+  }
+  maxSize = space - padding * 2;
+  if (!vars.axes.stacked) {
+    if (ref = vars[discrete].value, indexOf.call(vars.id.nesting, ref) >= 0) {
+      bars = d3.nest().key(function(d) {
+        return fetchValue(vars, d, vars[discrete].value);
+      }).entries(nested);
+      divisions = d3.max(bars, function(b) {
+        return b.values.length;
+      });
+    } else {
+      bars = uniques(nested, vars.id.value, fetchValue, vars);
+      divisions = bars.length;
+    }
+    maxSize /= divisions;
+    offset = space / 2 - maxSize / 2 - padding;
+    x = d3.scale.linear().domain([0, divisions - 1]).range([-offset, offset]);
+  }
+  data = [];
+  zero = 0;
+  for (i = j = 0, len = nested.length; j < len; i = ++j) {
+    point = nested[i];
+    mod = vars.axes.stacked ? 0 : x(i % divisions);
+    ref1 = point.values;
+    for (k = 0, len1 = ref1.length; k < len1; k++) {
+      d = ref1[k];
+      if (vars.axes.stacked) {
+        value = d.d3plus[opposite];
+        base = d.d3plus[opposite + "0"];
+      } else {
+        oppVal = fetchValue(vars, d, vars[opposite].value);
+        if (oppVal === 0) {
+          continue;
+        }
+        if (vars[opposite].scale.value === "log") {
+          zero = oppVal < 0 ? -1 : 1;
+        }
+        value = vars[opposite].scale.viz(oppVal);
+        base = vars[opposite].scale.viz(zero);
+      }
+      discreteVal = fetchValue(vars, d, vars[discrete].value);
+      d.d3plus[discrete] = vars[discrete].scale.viz(discreteVal);
+      d.d3plus[discrete] += vars.axes.margin[cMargin] + mod;
+      length = base - value;
+      d.d3plus[opposite] = base - length / 2;
+      if (!vars.axes.stacked) {
+        d.d3plus[opposite] += vars.axes.margin[oMargin];
+      }
+      d.d3plus[w] = maxSize;
+      d.d3plus[h] = Math.abs(length);
+      d.d3plus.init = {};
+      d.d3plus.init[opposite] = vars[opposite].scale.viz(zero);
+      d.d3plus.init[opposite] -= d.d3plus[opposite];
+      d.d3plus.init[opposite] += vars.axes.margin[oMargin];
+      d.d3plus.init[w] = d.d3plus[w];
+      d.d3plus.label = false;
+      data.push(d);
+    }
+  }
+  return data;
+};
+
+bar.filter = function(vars, data) {
+  return nest(vars, data);
+};
+
+bar.requirements = ["data", "x", "y"];
+
+bar.setup = function(vars) {
+  var axis, size, y;
+  if (!vars.axes.discrete) {
+    axis = vars.time.value === vars.y.value ? "y" : "x";
+    vars.self[axis]({
+      scale: "discrete"
+    });
+  }
+  y = vars[vars.axes.opposite];
+  size = vars.size;
+  if ((!y.value && size.value) || (size.changed && size.previous === y.value)) {
+    return vars.self[vars.axes.opposite](size.value);
+  } else if ((!size.value && y.value) || (y.changed && y.previous === size.value)) {
+    return vars.self.size(y.value);
+  }
+};
+
+bar.shapes = ["square"];
+
+module.exports = bar;
+
+
+},{"../../core/fetch/value.coffee":68,"../../util/uniques.coffee":209,"./helpers/graph/draw.coffee":308,"./helpers/graph/nest.coffee":314,"./helpers/graph/stack.coffee":315}],303:[function(require,module,exports){
+var box, fetchValue, graph, strip, uniques;
+
+fetchValue = require("../../core/fetch/value.coffee");
+
+graph = require("./helpers/graph/draw.coffee");
+
+strip = require("../../string/strip.js");
+
+uniques = require("../../util/uniques.coffee");
+
+box = function(vars) {
+  var disMargin, discrete, domains, h, medians, mergeData, mode, noData, oppMargin, opposite, returnData, size, space, w;
+  graph(vars, {
+    buffer: true,
+    mouse: true
+  });
+  domains = vars.x.domain.viz.concat(vars.y.domain.viz);
+  if (domains.indexOf(void 0) >= 0) {
+    return [];
+  }
+  discrete = vars.axes.discrete;
+  opposite = vars.axes.opposite;
+  disMargin = discrete === "x" ? vars.axes.margin.left : vars.axes.margin.top;
+  oppMargin = opposite === "x" ? vars.axes.margin.left : vars.axes.margin.top;
+  h = discrete === "x" ? "height" : "width";
+  w = discrete === "x" ? "width" : "height";
+  space = vars.axes[w] / vars[discrete].ticks.values.length;
+  size = vars.size.value;
+  size = typeof size === "number" ? size : 100;
+  space = d3.min([space - vars.labels.padding * 2, size]);
+  mode = vars.type.mode.value;
+  if (!(mode instanceof Array)) {
+    mode = [mode, mode];
+  }
+  mergeData = function(arr) {
+    var key, obj, vals;
+    obj = {};
+    for (key in vars.data.keys) {
+      vals = uniques(arr, key, fetchValue, vars);
+      obj[key] = vals.length === 1 ? vals[0] : vals;
+    }
+    return obj;
+  };
+  noData = false;
+  medians = [];
+  returnData = [];
+  d3.nest().key(function(d) {
+    return fetchValue(vars, d, vars[discrete].value);
+  }).rollup(function(leaves) {
+    var bottom, bottomLabel, bottomWhisker, boxData, d, diff1, diff2, first, i, iqr, j, key, label, len, len1, median, medianBuffer, medianData, medianHeight, medianText, outliers, scale, second, tooltipData, top, topLabel, topWhisker, uniqs, val, values, x, y;
+    scale = vars[opposite].scale.viz;
+    values = leaves.map(function(d) {
+      return fetchValue(vars, d, vars[opposite].value);
+    });
+    values.sort(function(a, b) {
+      return a - b;
+    });
+    uniqs = uniques(values);
+    first = d3.quantile(values, 0.25);
+    median = d3.quantile(values, 0.50);
+    second = d3.quantile(values, 0.75);
+    tooltipData = {};
+    if (mode[1] === "tukey") {
+      iqr = first - second;
+      top = second - iqr * 1.5;
+      topLabel = "top tukey";
+    } else if (mode[1] === "extent") {
+      top = d3.max(values);
+      topLabel = "maximum";
+    } else if (typeof mode[1] === "number") {
+      top = d3.quantile(values, (100 - mode[1]) / 100);
+      topLabel = mode[1] + " percentile";
+    }
+    top = d3.min([d3.max(values), top]);
+    if (vars.tooltip.extent.value) {
+      tooltipData[topLabel] = {
+        key: vars[opposite].value,
+        value: top
+      };
+    }
+    if (vars.tooltip.iqr.value) {
+      tooltipData["third quartile"] = {
+        key: vars[opposite].value,
+        value: second
+      };
+      tooltipData["median"] = {
+        key: vars[opposite].value,
+        value: median
+      };
+      tooltipData["first quartile"] = {
+        key: vars[opposite].value,
+        value: first
+      };
+    }
+    if (mode[0] === "tukey") {
+      iqr = first - second;
+      bottom = first + iqr * 1.5;
+      bottomLabel = "bottom tukey";
+    } else if (mode[0] === "extent") {
+      bottom = d3.min(values);
+      bottomLabel = "minimum";
+    } else if (typeof mode[0] === "number") {
+      bottom = d3.quantile(values, mode[0] / 100);
+      bottomLabel = mode[0] + " percentile";
+    }
+    bottom = d3.max([d3.min(values), bottom]);
+    if (vars.tooltip.extent.value) {
+      tooltipData[bottomLabel] = {
+        key: vars[opposite].value,
+        value: bottom
+      };
+    }
+    boxData = [];
+    bottomWhisker = [];
+    topWhisker = [];
+    outliers = [];
+    for (i = 0, len = leaves.length; i < len; i++) {
+      d = leaves[i];
+      val = fetchValue(vars, d, vars[opposite].value);
+      if (val >= first && val <= second) {
+        boxData.push(d);
+      } else if (val >= bottom && val < first) {
+        bottomWhisker.push(d);
+      } else if (val <= top && val > second) {
+        topWhisker.push(d);
+      } else {
+        outliers.push(d);
+      }
+    }
+    key = fetchValue(vars, leaves[0], vars[discrete].value);
+    x = vars[discrete].scale.viz(key);
+    x += disMargin;
+    label = vars.format.value(key, {
+      key: vars[discrete].value,
+      vars: vars
+    });
+    if (key.constructor === Date) {
+      key = key.getTime();
+    }
+    key = strip(key);
+    boxData = mergeData(boxData);
+    boxData.d3plus = {
+      color: "white",
+      id: "box_" + key,
+      init: {},
+      label: false,
+      shape: "square",
+      stroke: "#444",
+      text: "Interquartile Range for " + label
+    };
+    boxData.d3plus[w] = space;
+    boxData.d3plus.init[w] = space;
+    boxData.d3plus[h] = Math.abs(scale(first) - scale(second));
+    boxData.d3plus[discrete] = x;
+    y = d3.min([scale(first), scale(second)]) + boxData.d3plus[h] / 2;
+    y += oppMargin;
+    boxData.d3plus[opposite] = y;
+    boxData.d3plus.tooltip = tooltipData;
+    returnData.push(boxData);
+    medianData = {
+      d3plus: {
+        id: "median_line_" + key,
+        position: h === "height" ? "top" : "right",
+        shape: "whisker",
+        "static": true
+      }
+    };
+    medianText = vars.format.value(median, {
+      key: vars[opposite].value,
+      vars: vars
+    });
+    label = {
+      background: "#fff",
+      names: [medianText],
+      padding: 0,
+      resize: false,
+      x: 0,
+      y: 0
+    };
+    diff1 = Math.abs(scale(median) - scale(first));
+    diff2 = Math.abs(scale(median) - scale(second));
+    medianHeight = d3.min([diff1, diff2]) * 2;
+    medianBuffer = vars.data.stroke.width * 2 + vars.labels.padding * 2;
+    label[w === "width" ? "w" : "h"] = space - medianBuffer;
+    label[h === "width" ? "w" : "h"] = medianHeight - medianBuffer;
+    medianData.d3plus.label = label;
+    medianData.d3plus[w] = space;
+    medianData.d3plus[discrete] = x;
+    medianData.d3plus[opposite] = scale(median) + oppMargin;
+    returnData.push(medianData);
+    bottomWhisker = mergeData(bottomWhisker);
+    bottomWhisker.d3plus = {
+      id: "bottom_whisker_line_" + key,
+      offset: boxData.d3plus[h] / 2,
+      position: h === "height" ? "bottom" : "left",
+      shape: "whisker",
+      "static": true
+    };
+    if (opposite === "x") {
+      bottomWhisker.d3plus.offset *= -1;
+    }
+    bottomWhisker.d3plus[h] = Math.abs(scale(bottom) - scale(first));
+    bottomWhisker.d3plus[w] = space;
+    bottomWhisker.d3plus[discrete] = x;
+    bottomWhisker.d3plus[opposite] = y;
+    returnData.push(bottomWhisker);
+    topWhisker = mergeData(topWhisker);
+    topWhisker.d3plus = {
+      id: "top_whisker_line_" + key,
+      offset: boxData.d3plus[h] / 2,
+      position: h === "height" ? "top" : "right",
+      shape: "whisker",
+      "static": true
+    };
+    if (opposite === "y") {
+      topWhisker.d3plus.offset *= -1;
+    }
+    topWhisker.d3plus[h] = Math.abs(scale(top) - scale(second));
+    topWhisker.d3plus[w] = space;
+    topWhisker.d3plus[discrete] = x;
+    topWhisker.d3plus[opposite] = y;
+    returnData.push(topWhisker);
+    for (j = 0, len1 = outliers.length; j < len1; j++) {
+      d = outliers[j];
+      d.d3plus[discrete] = x;
+      d.d3plus[opposite] = scale(fetchValue(vars, d, vars.y.value));
+      d.d3plus[opposite] += oppMargin;
+      d.d3plus.r = 4;
+      d.d3plus.shape = vars.shape.value;
+    }
+    noData = !outliers.length && top - bottom === 0;
+    medians.push(median);
+    returnData = returnData.concat(outliers);
+    return leaves;
+  }).entries(vars.data.viz);
+  if (noData && uniques(medians).length === 1) {
+    return [];
+  } else {
+    return returnData;
+  }
+};
+
+box.modes = ["tukey", "extent", Array, Number];
+
+box.requirements = ["data", "x", "y"];
+
+box.shapes = ["circle", "check", "cross", "diamond", "square", "triangle", "triangle_up", "triangle_down"];
+
+box.setup = function(vars) {
+  var axis;
+  if (!vars.axes.discrete) {
+    axis = vars.time.value === vars.y.value ? "y" : "x";
+    return vars.self[axis]({
+      scale: "discrete"
+    });
+  }
+};
+
+module.exports = box;
+
+
+},{"../../core/fetch/value.coffee":68,"../../string/strip.js":174,"../../util/uniques.coffee":209,"./helpers/graph/draw.coffee":308}],304:[function(require,module,exports){
+var arraySort, bubbles, fetchColor, fetchText, fetchValue, groupData, legible;
+
+arraySort = require("../../array/sort.coffee");
+
+fetchValue = require("../../core/fetch/value.coffee");
+
+fetchColor = require("../../core/fetch/color.coffee");
+
+fetchText = require("../../core/fetch/text.js");
+
+legible = require("../../color/legible.coffee");
+
+groupData = require("../../core/data/group.coffee");
+
+bubbles = function(vars) {
+  var column_height, column_width, columns, d, data, dataLength, domain, domainMax, domainMin, downscale, groupedData, i, j, k, l, labelHeight, len, len1, len2, obj, pack, padding, row, rows, screenRatio, size, size_max, size_min, t, temp, xPadding, xoffset, yMod, yPadding, yoffset;
+  groupedData = groupData(vars, vars.data.viz);
+  groupedData = arraySort(groupedData, null, null, null, vars);
+  dataLength = groupedData.length;
+  if (dataLength < 4) {
+    columns = dataLength;
+    rows = 1;
+  } else {
+    screenRatio = vars.width.viz / vars.height.viz;
+    columns = Math.ceil(Math.sqrt(dataLength * screenRatio));
+    rows = Math.ceil(Math.sqrt(dataLength / screenRatio));
+  }
+  if (dataLength > 0) {
+    while ((rows - 1) * columns >= dataLength) {
+      rows--;
+    }
+  }
+  column_width = vars.width.viz / columns;
+  column_height = vars.height.viz / rows;
+  if (vars.size.value) {
+    domainMin = d3.min(vars.data.viz, function(d) {
+      return fetchValue(vars, d, vars.size.value, vars.id.value, "min");
+    });
+    domainMax = d3.max(vars.data.viz, function(d) {
+      return fetchValue(vars, d, vars.size.value, vars.id.value);
+    });
+    domain = [domainMin, domainMax];
+  } else {
+    domain = [0, 0];
+  }
+  padding = 5;
+  size_max = (d3.min([column_width, column_height]) / 2) - (padding * 2);
+  labelHeight = vars.labels.value && !vars.small && size_max >= 40 ? d3.max([20, d3.min([size_max * 0.25, 50])]) : 0;
+  size_max -= labelHeight;
+  size_min = d3.min([size_max, vars.size.scale.min.value]);
+  size = vars.size.scale.value.domain(domain).rangeRound([size_min, size_max]);
+  pack = d3.layout.pack().children(function(d) {
+    return d.values;
+  }).padding(padding).radius(function(d) {
+    return size(d);
+  }).size([column_width - padding * 2, column_height - padding * 2 - labelHeight]).value(function(d) {
+    return d.value;
+  });
+  data = [];
+  row = 0;
+  for (i = j = 0, len = groupedData.length; j < len; i = ++j) {
+    d = groupedData[i];
+    temp = pack.nodes(d);
+    xoffset = (column_width * i) % vars.width.viz;
+    yoffset = column_height * row;
+    for (k = 0, len1 = temp.length; k < len1; k++) {
+      t = temp[k];
+      if (t.children) {
+        obj = {
+          d3plus: {}
+        };
+        obj[vars.id.value] = t.key;
+      } else {
+        obj = t.d3plus;
+      }
+      obj.d3plus.depth = vars.id.grouping.value ? t.depth : vars.depth.value;
+      obj.d3plus.x = t.x;
+      obj.d3plus.xOffset = xoffset;
+      obj.d3plus.y = t.y;
+      obj.d3plus.yOffset = yoffset + labelHeight;
+      obj.d3plus.r = t.r;
+      data.push(obj);
+    }
+    if ((i + 1) % columns === 0) {
+      row++;
+    }
+  }
+  downscale = size_max / d3.max(data, function(d) {
+    return d.d3plus.r;
+  });
+  xPadding = pack.size()[0] / 2;
+  yPadding = pack.size()[1] / 2;
+  for (l = 0, len2 = data.length; l < len2; l++) {
+    d = data[l];
+    d.d3plus.x = ((d.d3plus.x - xPadding) * downscale) + xPadding + d.d3plus.xOffset;
+    d.d3plus.y = ((d.d3plus.y - yPadding) * downscale) + yPadding + d.d3plus.yOffset;
+    d.d3plus.r = d.d3plus.r * downscale;
+    delete d.d3plus.xOffset;
+    delete d.d3plus.yOffset;
+    d.d3plus["static"] = d.d3plus.depth < vars.depth.value && vars.id.grouping.value;
+    if (labelHeight && (d.d3plus.depth === 0 || vars.id.grouping.value === false)) {
+      d.d3plus.text = fetchText(vars, d[vars.id.value], d.d3plus.depth);
+      yMod = labelHeight > vars.labels.padding * 3 ? vars.labels.padding : 0;
+      d.d3plus.label = {
+        x: 0,
+        y: -(size_max + yMod + labelHeight / 2),
+        w: size_max * 2,
+        h: labelHeight - yMod,
+        padding: 0,
+        resize: true,
+        color: legible(fetchColor(vars, d, d.d3plus.depth)),
+        force: true
+      };
+    } else {
+      delete d.d3plus.label;
+    }
+  }
+  return data.sort(function(a, b) {
+    return a.d3plus.depth - b.d3plus.depth;
+  });
+};
+
+bubbles.fill = true;
+
+bubbles.requirements = ["data"];
+
+bubbles.scale = 1.05;
+
+bubbles.shapes = ["circle", "donut"];
+
+module.exports = bubbles;
+
+
+},{"../../array/sort.coffee":36,"../../color/legible.coffee":45,"../../core/data/group.coffee":58,"../../core/fetch/color.coffee":64,"../../core/fetch/text.js":67,"../../core/fetch/value.coffee":68}],305:[function(require,module,exports){
+var chart, print;
+
+print = require("../../../core/console/print.coffee");
+
+chart = function(vars) {
+  var type, types;
+  types = {
+    circle: "scatter",
+    donut: "scatter",
+    line: "line",
+    square: "scatter",
+    area: "stacked"
+  };
+  type = types[vars.shape.value];
+  print.warning("The \"chart\" visualization type has been deprecated and will be removed in version 2.0. Please use the \"" + type + "\" visualization type.");
+  vars.self.type(type).draw();
+};
+
+chart.shapes = ["circle", "donut", "line", "square", "area"];
+
+module.exports = chart;
+
+
+},{"../../../core/console/print.coffee":53}],306:[function(require,module,exports){
+var geo_map;
+
+geo_map = function(vars) {
+  var coords, features, key, mute, solo, topo;
+  topojson.presimplify(vars.coords.value);
+  coords = vars.coords.value;
+  key = d3.keys(coords.objects)[0];
+  topo = topojson.feature(coords, coords.objects[key]);
+  features = topo.features;
+  solo = vars.coords.solo.value;
+  mute = vars.coords.mute.value;
+  features = features.filter(function(f) {
+    f[vars.id.value] = f.id;
+    if (solo.length) {
+      return solo.indexOf(f.id) >= 0;
+    } else if (mute.length) {
+      return mute.indexOf(f.id) < 0;
+    } else {
+      return true;
+    }
+  });
+  return features;
+};
+
+geo_map.libs = ["topojson"];
+
+geo_map.nesting = false;
+
+geo_map.requirements = ["coords"];
+
+geo_map.scale = 1;
+
+geo_map.shapes = ["coordinates"];
+
+geo_map.zoom = true;
+
+module.exports = geo_map;
+
+
+},{}],307:[function(require,module,exports){
+var color, legible, print;
+
+color = require("../../../../core/fetch/color.coffee");
+
+legible = require("../../../../color/legible.coffee");
+
+print = require("../../../../core/console/print.coffee");
+
+module.exports = function(vars) {
+  var axes, axis, axisData, data, i, len, ref, style, tick, ticks, timing;
+  axes = vars.axes;
+  data = axes.stacked ? [] : vars.data.viz;
+  timing = data.length * 2 > vars.data.large ? 0 : vars.draw.timing;
+  style = function(line, axis) {
+    if (axis === "y") {
+      line.attr("x1", -2).attr("x2", -8).attr("y1", function(d) {
+        return d.d3plus.y - axes.margin.top;
+      }).attr("y2", function(d) {
+        return d.d3plus.y - axes.margin.top;
+      });
+    } else {
+      line.attr("x1", function(d) {
+        return d.d3plus.x - axes.margin.left;
+      }).attr("x2", function(d) {
+        return d.d3plus.x - axes.margin.left;
+      }).attr("y1", axes.height + 2).attr("y2", axes.height + 8);
+    }
+    return line.style("stroke", function(d) {
+      return legible(color(vars, d));
+    }).style("stroke-width", vars.data.stroke.width).attr("shape-rendering", vars.shape.rendering.value);
+  };
+  if (vars.dev.value) {
+    print.time("creating axis tick groups");
+  }
+  ticks = vars.group.select("g#d3plus_graph_plane").selectAll("g.d3plus_data_tick").data(data, function(d) {
+    var mod;
+    mod = axes.discrete ? "_" + d.d3plus[axes.discrete] : "";
+    return "tick_" + d[vars.id.value] + "_" + d.d3plus.depth + mod;
+  });
+  ticks.enter().append("g").attr("class", "d3plus_data_tick").attr("opacity", 0);
+  if (vars.dev.value) {
+    print.timeEnd("creating axis tick groups");
+  }
+  ref = ["x", "y"];
+  for (i = 0, len = ref.length; i < len; i++) {
+    axis = ref[i];
+    if (vars.dev.value && timing) {
+      print.time("creating " + axis + " ticks");
+    }
+    axisData = timing && axis !== axes.discrete ? data : [];
+    tick = ticks.selectAll("line.d3plus_data_" + axis).data(axisData, function(d) {
+      return "tick_" + d[vars.id.value] + "_" + d.d3plus.depth;
+    });
+    if (vars.dev.value && timing) {
+      print.timeEnd("creating " + axis + " ticks");
+    }
+    if (vars.dev.value && timing) {
+      print.time("styling " + axis + " ticks");
+    }
+    if (timing > 0) {
+      tick.transition().duration(timing).call(style, axis);
+    } else {
+      tick.call(style, axis);
+    }
+    tick.enter().append("line").attr("class", "d3plus_data_" + axis).call(style, axis);
+    if (vars.dev.value && timing) {
+      print.timeEnd("styling " + axis + " ticks");
+    }
+  }
+  if (timing > 0) {
+    ticks.transition().duration(timing).attr("opacity", 1);
+    ticks.exit().transition().duration(timing).attr("opacity", 0).remove();
+  } else {
+    ticks.attr("opacity", 1);
+    ticks.exit().remove();
+  }
+};
+
+
+},{"../../../../color/legible.coffee":45,"../../../../core/console/print.coffee":53,"../../../../core/fetch/color.coffee":64}],308:[function(require,module,exports){
+var axes, draw, mouse, plot;
+
+axes = require("./includes/axes.coffee");
+
+draw = require("./includes/svg.coffee");
+
+mouse = require("./includes/mouse.coffee");
+
+plot = require("./includes/plot.coffee");
+
+module.exports = function(vars, opts) {
+  if (opts === void 0) {
+    opts = {};
+  }
+  axes(vars, opts);
+  plot(vars, opts);
+  draw(vars, opts);
+  vars.mouse.viz = opts.mouse === true ? mouse : false;
+};
+
+
+},{"./includes/axes.coffee":309,"./includes/mouse.coffee":311,"./includes/plot.coffee":312,"./includes/svg.coffee":313}],309:[function(require,module,exports){
+var arraySort, axisRange, buckets, buffer, dataChange, fetchData, fetchValue, getData, getScale, print, sizeScale, uniques;
+
+arraySort = require("../../../../../array/sort.coffee");
+
+buffer = require("./buffer.coffee");
+
+buckets = require("../../../../../util/buckets.coffee");
+
+fetchData = require("../../../../../core/fetch/data.js");
+
+fetchValue = require("../../../../../core/fetch/value.coffee");
+
+print = require("../../../../../core/console/print.coffee");
+
+uniques = require("../../../../../util/uniques.coffee");
+
+module.exports = function(vars, opts) {
+  var axes, axis, changed, domains, i, j, len, len1, oppAxis, range, reorder, zero;
+  changed = dataChange(vars);
+  if (changed || !vars.axes.dataset) {
+    vars.axes.dataset = getData(vars);
+  }
+  vars.axes.scale = opts.buffer && opts.buffer !== true ? sizeScale(vars, opts.buffer) : false;
+  axes = vars.width.viz > vars.height.viz ? ["y", "x"] : ["x", "y"];
+  for (i = 0, len = axes.length; i < len; i++) {
+    axis = axes[i];
+    oppAxis = axis === "x" ? "y" : "x";
+    reorder = vars.order.changed || vars.order.sort.changed || (vars.order.value === true && vars[oppAxis].changed);
+    if (!vars[axis].ticks.values || changed || reorder) {
+      if (vars.dev.value) {
+        print.time("calculating " + axis + " axis");
+      }
+      vars[axis].reset = true;
+      vars[axis].ticks.values = false;
+      if (axis === vars.axes.discrete && vars[axis].value !== vars.time.value) {
+        vars[axis].ticks.values = uniques(vars.axes.dataset, vars[axis].value, fetchValue, vars);
+      }
+      zero = [true, axis].indexOf(opts.zero) > 0 ? true : false;
+      range = axisRange(vars, axis, zero);
+      if (axis === "y") {
+        range = range.reverse();
+      }
+      vars[axis].scale.viz = getScale(vars, axis, range);
+      vars[axis].domain.viz = range;
+      if (vars.dev.value) {
+        print.timeEnd("calculating " + axis + " axis");
+      }
+    }
+  }
+  if (vars.axes.mirror.value) {
+    domains = d3.extent(vars.y.domain.viz.concat(vars.x.domain.viz));
+    vars.x.domain.viz = domains;
+    vars.x.scale.viz.domain(domains);
+    domains = domains.slice().reverse();
+    vars.y.domain.viz = domains;
+    vars.y.scale.viz.domain(domains);
+  }
+  if (opts.buffer) {
+    for (j = 0, len1 = axes.length; j < len1; j++) {
+      axis = axes[j];
+      if (axis !== vars.axes.discrete) {
+        buffer(vars, axis, opts.buffer);
+      }
+    }
+  }
+};
+
+dataChange = function(vars) {
+  var axis, changed, check, i, j, k, l, len, len1, len2, ref, sub, subs;
+  changed = vars.time.fixed.value && (vars.time.solo.changed || vars.time.mute.changed);
+  if (!changed) {
+    changed = vars.id.solo.changed || vars.id.mute.changed;
+  }
+  if (changed) {
+    return changed;
+  }
+  check = ["data", "time", "id", "depth", "type", "x", "y"];
+  for (i = 0, len = check.length; i < len; i++) {
+    k = check[i];
+    if (vars[k].changed) {
+      changed = true;
+      break;
+    }
+  }
+  if (changed) {
+    return changed;
+  }
+  subs = ["mute", "range", "scale", "solo", "stacked", "zerofill"];
+  ref = ["x", "y"];
+  for (j = 0, len1 = ref.length; j < len1; j++) {
+    axis = ref[j];
+    for (l = 0, len2 = subs.length; l < len2; l++) {
+      sub = subs[l];
+      if (vars[axis][sub].changed) {
+        changed = true;
+        break;
+      }
+    }
+  }
+  return changed;
+};
+
+getData = function(vars) {
+  var d, depths;
+  if (vars.time.fixed.value) {
+    return vars.data.viz;
+  } else {
+    depths = d3.range(0, vars.id.nesting.length);
+    return d3.merge([
+      (function() {
+        var i, len, results;
+        results = [];
+        for (i = 0, len = depths.length; i < len; i++) {
+          d = depths[i];
+          results.push(fetchData(vars, "all", d));
+        }
+        return results;
+      })()
+    ]);
+  }
+};
+
+axisRange = function(vars, axis, zero, buffer) {
+  var agg, aggType, allNegative, allPositive, axisSums, counts, d, group, i, j, k, l, len, len1, len2, len3, m, min, oppAxis, ref, ref1, ref2, ref3, sort, sortKey, splitData, v, val, values;
+  oppAxis = axis === "x" ? "y" : "x";
+  if (vars[axis].range.value && vars[axis].range.value.length === 2) {
+    return vars[axis].range.value.slice();
+  } else if (vars[axis].scale.value === "share") {
+    vars[axis].ticks.values = d3.range(0, 1.1, 0.1);
+    return [0, 1];
+  } else if (vars[axis].stacked.value) {
+    splitData = [];
+    ref = vars.axes.dataset;
+    for (i = 0, len = ref.length; i < len; i++) {
+      d = ref[i];
+      if (d.values) {
+        splitData = splitData.concat(d.values);
+      } else {
+        splitData.push(d);
+      }
+    }
+    axisSums = d3.nest().key(function(d) {
+      return fetchValue(vars, d, vars[oppAxis].value);
+    }).rollup(function(leaves) {
+      var negatives, positives;
+      positives = d3.sum(leaves, function(d) {
+        var val;
+        val = fetchValue(vars, d, vars[axis].value);
+        if (val > 0) {
+          return val;
+        } else {
+          return 0;
+        }
+      });
+      negatives = d3.sum(leaves, function(d) {
+        var val;
+        val = fetchValue(vars, d, vars[axis].value);
+        if (val < 0) {
+          return val;
+        } else {
+          return 0;
+        }
+      });
+      return [negatives, positives];
+    }).entries(splitData);
+    values = d3.merge(axisSums.map(function(d) {
+      return d.values;
+    }));
+    return d3.extent(values);
+  } else if (vars[axis].value === vars.time.value) {
+    if (vars.time.solo.value.length) {
+      return d3.extent(vars.time.solo.value).map(function(v) {
+        if (v.constructor !== Date) {
+          v = v + "";
+          if (v.length === 4 && parseInt(v) + "" === v) {
+            v += "/01/01";
+          }
+          return new Date(v);
+        } else {
+          return v;
+        }
+      });
+    } else {
+      return d3.extent(vars.data.time.ticks);
+    }
+  } else {
+    values = [];
+    ref1 = vars.axes.dataset;
+    for (j = 0, len1 = ref1.length; j < len1; j++) {
+      d = ref1[j];
+      val = fetchValue(vars, d, vars[axis].value);
+      if (val instanceof Array) {
+        values = values.concat(val);
+      } else {
+        values.push(val);
+      }
+    }
+    if (typeof values[0] === "string") {
+      if (vars.order.value === true) {
+        sortKey = vars[oppAxis].value;
+      } else {
+        sortKey = vars.order.value;
+      }
+      if (sortKey) {
+        sort = vars.order.sort.value;
+        agg = vars.order.agg.value || vars.aggs.value[sortKey] || "max";
+        aggType = typeof agg;
+        counts = values.reduce(function(obj, val) {
+          obj[val] = [];
+          return obj;
+        }, {});
+        ref2 = vars.axes.dataset;
+        for (l = 0, len2 = ref2.length; l < len2; l++) {
+          d = ref2[l];
+          if (d.values) {
+            ref3 = d.values;
+            for (m = 0, len3 = ref3.length; m < len3; m++) {
+              v = ref3[m];
+              group = fetchValue(vars, v, vars[axis].value);
+              counts[group].push(fetchValue(vars, v, sortKey));
+            }
+          } else {
+            group = fetchValue(vars, d, vars[axis].value);
+            counts[group].push(fetchValue(vars, d, sortKey));
+          }
+        }
+        for (k in counts) {
+          v = counts[k];
+          if (aggType === "string") {
+            counts[k] = d3[agg](v);
+          } else if (aggType === "function") {
+            counts[k] = agg(v, sortKey);
+          }
+        }
+        counts = arraySort(d3.entries(counts), "value", sort);
+        counts = counts.reduce(function(arr, v) {
+          arr.push(v.key);
+          return arr;
+        }, []);
+        return counts;
+      } else {
+        return uniques(values);
+      }
+    } else {
+      values.sort(function(a, b) {
+        return a - b;
+      });
+      if (vars[axis].scale.value === "log") {
+        if (values[0] === 0) {
+          values[0] = 1;
+        }
+        if (values[values.length - 1] === 0) {
+          values[values.length - 1] = -1;
+        }
+      }
+      if (zero) {
+        allPositive = values.every(function(v) {
+          return v > 0;
+        });
+        allNegative = values.every(function(v) {
+          return v < 0;
+        });
+        if (allPositive || allNegative) {
+          min = allPositive ? 1 : -1;
+          values.push(vars[axis].scale.value === "log" ? min : 0);
+        }
+      }
+      return d3.extent(values);
+    }
+  }
+};
+
+getScale = function(vars, axis, range) {
+  var rangeArray, rangeMax, scaleType;
+  rangeMax = axis === "x" ? vars.width.viz : vars.height.viz;
+  scaleType = vars[axis].scale.value;
+  if (["discrete", "share"].indexOf(scaleType) >= 0) {
+    scaleType = "linear";
+  }
+  if (typeof range[0] === "string") {
+    scaleType = "ordinal";
+    rangeArray = buckets([0, rangeMax], range.length);
+  } else {
+    rangeArray = [0, rangeMax];
+  }
+  return d3.scale[scaleType]().domain(range).range(rangeArray);
+};
+
+sizeScale = function(vars, value) {
+  var domain, max, min;
+  if (value === true) {
+    value = "size";
+  }
+  if (value in vars) {
+    value = vars[value].value;
+  }
+  min = vars.size.scale.min.value;
+  if (typeof min === "function") {
+    min = min(vars);
+  }
+  max = vars.size.scale.max.value;
+  if (typeof max === "function") {
+    max = max(vars);
+  }
+  if (value === false) {
+    return vars.size.scale.value.rangeRound([max, max]);
+  } else if (typeof value === "number") {
+    return vars.size.scale.value.rangeRound([value, value]);
+  } else if (value) {
+    if (vars.dev.value) {
+      print.time("calculating buffer scale");
+    }
+    domain = d3.extent(vars.axes.dataset, function(d) {
+      var val;
+      val = fetchValue(vars, d, value);
+      if (!val) {
+        return 0;
+      } else {
+        return val;
+      }
+    });
+    if (domain[0] === domain[1]) {
+      min = max;
+    }
+    if (vars.dev.value) {
+      print.timeEnd("calculating buffer scale");
+    }
+    return vars.size.scale.value.domain(domain).rangeRound([min, max]);
+  }
+};
+
+
+},{"../../../../../array/sort.coffee":36,"../../../../../core/console/print.coffee":53,"../../../../../core/fetch/data.js":65,"../../../../../core/fetch/value.coffee":68,"../../../../../util/buckets.coffee":203,"../../../../../util/uniques.coffee":209,"./buffer.coffee":310}],310:[function(require,module,exports){
+var buckets, closest;
+
+buckets = require("../../../../../util/buckets.coffee");
+
+closest = require("../../../../../util/closest.coffee");
+
+module.exports = function(vars, axis, buffer) {
+  var additional, allNegative, allPositive, closestTime, copy, diff, difference, domain, domainCompare, domainHigh, domainLow, i, lowerDiff, lowerMod, lowerScale, lowerValue, maxSize, opp, range, rangeMax, second, strings, timeIndex, upperDiff, upperMod, upperScale, upperValue, zero;
+  if (vars[axis].scale.value !== "share" && !vars[axis].range.value && vars[axis].reset) {
+    if (axis === vars.axes.discrete) {
+      domain = vars[axis].scale.viz.domain();
+      if (typeof domain[0] === "string") {
+        i = domain.length;
+        while (i >= 0) {
+          domain.splice(i, 0, "d3plus_buffer_" + i);
+          i--;
+        }
+        range = vars[axis].scale.viz.range();
+        range = buckets(d3.extent(range), domain.length);
+        return vars[axis].scale.viz.domain(domain).range(range);
+      } else {
+        if (axis === "y") {
+          domain = domain.slice().reverse();
+        }
+        if (vars[axis].ticks.values.length === 1) {
+          if (vars[axis].value === vars.time.value && vars.data.time.ticks.length !== 1) {
+            closestTime = closest(vars.data.time.ticks, domain[0]);
+            timeIndex = vars.data.time.ticks.indexOf(closestTime);
+            if (timeIndex > 0) {
+              domain[0] = vars.data.time.ticks[timeIndex - 1];
+            } else {
+              diff = vars.data.time.ticks[timeIndex + 1] - closestTime;
+              domain[0] = new Date(closestTime.getTime() - diff);
+            }
+            if (timeIndex < vars.data.time.ticks.length - 1) {
+              domain[1] = vars.data.time.ticks[timeIndex + 1];
+            } else {
+              diff = closestTime - vars.data.time.ticks[timeIndex - 1];
+              domain[1] = new Date(closestTime.getTime() + diff);
+            }
+          } else {
+            domain[0] -= 1;
+            domain[1] += 1;
+          }
+        } else if (vars.axes.scale) {
+          difference = Math.abs(domain[1] - domain[0]);
+          additional = difference / (vars[axis].ticks.values.length - 1);
+          additional = additional / 2;
+          rangeMax = vars[axis].scale.viz.range()[1];
+          maxSize = vars.axes.scale.range()[1] * 1.5;
+          domainLow = vars[axis].scale.viz.invert(-maxSize);
+          domainHigh = vars[axis].scale.viz.invert(rangeMax + maxSize);
+          if (domain[0] - additional < domainLow) {
+            domain[0] = domain[0] - additional;
+            domain[1] = domain[1] + additional;
+          } else {
+            domain = [domainLow, domainHigh];
+            if (axis === "y") {
+              domain = domain.reverse();
+            }
+            domainCompare = vars[axis].scale.viz.domain();
+            domainCompare = domainCompare[1] - domainCompare[0];
+            if (!domainCompare) {
+              domain[0] -= 1;
+              domain[1] += 1;
+            }
+          }
+        } else {
+          difference = Math.abs(domain[1] - domain[0]);
+          additional = difference / (vars[axis].ticks.values.length - 1);
+          additional = additional / 2;
+          domain[0] = domain[0] - additional;
+          domain[1] = domain[1] + additional;
+        }
+        if (axis === "y") {
+          domain = domain.reverse();
+        }
+        return vars[axis].scale.viz.domain(domain);
+      }
+    } else if ((buffer === "x" && axis === "x") || (buffer === "y" && axis === "y") || (buffer === true)) {
+      domain = vars[axis].scale.viz.domain();
+      allPositive = domain[0] >= 0 && domain[1] >= 0;
+      allNegative = domain[0] <= 0 && domain[1] <= 0;
+      if (vars[axis].scale.value === "log") {
+        zero = allPositive ? 1 : -1;
+        if (allPositive && axis === "y") {
+          domain = domain.slice().reverse();
+        }
+        lowerScale = Math.pow(10, parseInt(Math.abs(domain[0])).toString().length - 1) * zero;
+        lowerMod = domain[0] % lowerScale;
+        lowerDiff = lowerMod;
+        if (lowerMod && lowerDiff / lowerScale <= 0.1) {
+          lowerDiff += lowerScale * zero;
+        }
+        lowerValue = lowerMod === 0 ? lowerScale : lowerDiff;
+        domain[0] -= lowerValue;
+        if (domain[0] === 0) {
+          domain[0] = zero;
+        }
+        upperScale = Math.pow(10, parseInt(Math.abs(domain[1])).toString().length - 1) * zero;
+        upperMod = domain[1] % upperScale;
+        upperDiff = Math.abs(upperScale - upperMod);
+        if (upperMod && upperDiff / upperScale <= 0.1) {
+          upperDiff += upperScale * zero;
+        }
+        upperValue = upperMod === 0 ? upperScale : upperDiff;
+        domain[1] += upperValue;
+        if (domain[1] === 0) {
+          domain[1] = zero;
+        }
+        if (allPositive && axis === "y") {
+          domain = domain.reverse();
+        }
+      } else {
+        zero = 0;
+        if (axis === "y") {
+          domain = domain.slice().reverse();
+        }
+        strings = domain.filter(function(d) {
+          return d.constructor === String;
+        });
+        additional = Math.abs(domain[1] - domain[0]) * 0.05 || 1;
+        if (!strings.length) {
+          domain[0] = domain[0] - additional;
+          domain[1] = domain[1] + additional;
+          if ((allPositive && domain[0] < zero) || (allNegative && domain[0] > zero)) {
+            domain[0] = zero;
+          }
+          if ((allPositive && domain[1] < zero) || (allNegative && domain[1] > zero)) {
+            domain[1] = zero;
+          }
+        }
+        if (axis === "y") {
+          domain = domain.reverse();
+        }
+      }
+      return vars[axis].scale.viz.domain(domain);
+    } else if (vars.axes.scale) {
+      copy = false;
+      if (vars.axes.mirror.value) {
+        opp = axis === "y" ? "x" : "y";
+        copy = vars[opp].scale.viz;
+        second = vars.width.viz > vars.height.viz ? "x" : "y";
+      }
+      if (axis === second && copy) {
+        domain = copy.domain().slice().reverse();
+      } else {
+        rangeMax = vars[axis].scale.viz.range()[1];
+        maxSize = vars.axes.scale.range()[1];
+        domainLow = vars[axis].scale.viz.invert(-maxSize * 1.5);
+        domainHigh = vars[axis].scale.viz.invert(rangeMax + maxSize * 1.5);
+        domain = [domainLow, domainHigh];
+        if (axis === "y") {
+          domain = domain.reverse();
+        }
+        domainCompare = vars[axis].scale.viz.domain();
+        domainCompare = domainCompare[1] - domainCompare[0];
+        if (!domainCompare) {
+          domain[0] -= 1;
+          domain[1] += 1;
+        }
+        if (axis === "y") {
+          domain = domain.reverse();
+        }
+      }
+      return vars[axis].scale.viz.domain(domain);
+    }
+  }
+};
+
+
+},{"../../../../../util/buckets.coffee":203,"../../../../../util/closest.coffee":205}],311:[function(require,module,exports){
+var copy, events, fetchColor, fetchValue, legible;
+
+copy = require("../../../../../util/copy.coffee");
+
+events = require("../../../../../client/pointer.coffee");
+
+fetchColor = require("../../../../../core/fetch/color.coffee");
+
+fetchValue = require("../../../../../core/fetch/value.coffee");
+
+legible = require("../../../../../color/legible.coffee");
+
+module.exports = function(node, vars) {
+  var clickRemove, color, create, graph, lineData, lineInit, lineStyle, lineUpdate, lines, r, rectStyle, rects, s, textStyle, texts, timing, x, y;
+  clickRemove = d3.event.type === events.click && (vars.tooltip.value.long || vars.tooltip.html.value);
+  create = [events.over, events.move].indexOf(d3.event.type) >= 0;
+  x = node.d3plus.x;
+  y = node.d3plus.y;
+  r = node.d3plus.r || 0;
+  s = vars.types[vars.type.value].scale || 1;
+  r = r * s;
+  graph = vars.axes;
+  timing = vars.draw.timing ? vars.timing.mouseevents : 0;
+  if (!clickRemove && create) {
+    color = legible(fetchColor(vars, node));
+    lineData = ["x", "y"].filter(function(axis) {
+      var val;
+      val = fetchValue(vars, node, vars[axis].value);
+      return !(val instanceof Array) && axis !== vars.axes.stacked && vars[axis].mouse.value && axis !== vars.axes.discrete;
+    });
+  } else {
+    lineData = [];
+  }
+  lineInit = function(line) {
+    return line.attr("x1", function(d) {
+      if (d === "x") {
+        return x;
+      } else {
+        return x - r;
+      }
+    }).attr("y1", function(d) {
+      if (d === "y") {
+        return y;
+      } else {
+        return y + r;
+      }
+    }).attr("x2", function(d) {
+      if (d === "x") {
+        return x;
+      } else {
+        return x - r;
+      }
+    }).attr("y2", function(d) {
+      if (d === "y") {
+        return y;
+      } else {
+        return y + r;
+      }
+    }).attr("opacity", 0);
+  };
+  lineStyle = function(line) {
+    return line.style("stroke", function(d) {
+      if (vars.shape.value === "area") {
+        return "white";
+      } else {
+        return color;
+      }
+    }).attr("stroke-dasharray", function(d) {
+      return vars[d].mouse.dasharray.value;
+    }).attr("shape-rendering", function(d) {
+      return vars[d].mouse.rendering.value;
+    }).style("stroke-width", function(d) {
+      return vars[d].mouse.width;
+    });
+  };
+  lineUpdate = function(line) {
+    return line.attr("x1", function(d) {
+      if (d === "x") {
+        return x;
+      } else {
+        return x - r;
+      }
+    }).attr("y1", function(d) {
+      if (d === "y") {
+        return y;
+      } else {
+        return y + r;
+      }
+    }).attr("x2", function(d) {
+      if (d === "x") {
+        return x;
+      } else {
+        return node.d3plus.x0 || graph.margin.left - vars[d].ticks.size;
+      }
+    }).attr("y2", function(d) {
+      if (d === "y") {
+        return y;
+      } else {
+        return node.d3plus.y0 || graph.height + graph.margin.top + vars[d].ticks.size;
+      }
+    }).style("opacity", 1);
+  };
+  lines = vars.g.labels.selectAll("line.d3plus_mouse_axis_label").data(lineData);
+  if (timing) {
+    lines.enter().append("line").attr("class", "d3plus_mouse_axis_label").attr("pointer-events", "none").call(lineInit).call(lineStyle);
+    lines.transition().duration(timing).call(lineUpdate).call(lineStyle);
+    lines.exit().transition().duration(timing).call(lineInit).remove();
+  } else {
+    lines.call(lineUpdate).call(lineStyle);
+    lines.enter().append("line").attr("class", "d3plus_mouse_axis_label").attr("pointer-events", "none").call(lineInit).call(lineStyle);
+    lines.exit().remove();
+  }
+  textStyle = function(text) {
+    return text.attr("font-size", function(d) {
+      return vars[d].ticks.font.size + "px";
+    }).attr("fill", function(d) {
+      return vars[d].ticks.font.color;
+    }).attr("font-family", function(d) {
+      return vars[d].ticks.font.family.value;
+    }).attr("font-weight", function(d) {
+      return vars[d].ticks.font.weight;
+    }).attr("x", function(d) {
+      if (d === "x") {
+        return x;
+      } else {
+        return graph.margin.left - 5 - vars[d].ticks.size;
+      }
+    }).attr("y", function(d) {
+      if (d === "y") {
+        return y;
+      } else {
+        if (node.d3plus.y0) {
+          return node.d3plus.y + (node.d3plus.y0 - node.d3plus.y) / 2 + graph.margin.top - 6;
+        } else {
+          return graph.height + graph.margin.top + 5 + vars[d].ticks.size;
+        }
+      }
+    }).attr("fill", vars.shape.value === "area" ? "white" : color);
+  };
+  texts = vars.g.labels.selectAll("text.d3plus_mouse_axis_label").data(lineData);
+  texts.enter().append("text").attr("class", "d3plus_mouse_axis_label").attr("id", function(d) {
+    return d + "_d3plusmouseaxislabel";
+  }).attr("dy", function(d) {
+    if (d === "y") {
+      return vars[d].ticks.font.size * 0.35;
+    } else {
+      return vars[d].ticks.font.size;
+    }
+  }).style("text-anchor", function(d) {
+    if (d === "y") {
+      return "end";
+    } else {
+      return "middle";
+    }
+  }).attr("opacity", 0).attr("pointer-events", "none").call(textStyle);
+  texts.text(function(d) {
+    var axis, val;
+    axis = vars.axes.stacked || d;
+    val = fetchValue(vars, node, vars[axis].value);
+    return vars.format.value(val, {
+      key: vars[axis].value,
+      vars: vars,
+      labels: vars[axis].affixes.value
+    });
+  });
+  if (timing) {
+    texts.transition().duration(timing).delay(timing).attr("opacity", 1).call(textStyle);
+    texts.exit().transition().duration(timing).attr("opacity", 0).remove();
+  } else {
+    texts.attr("opacity", 1).call(textStyle);
+    texts.exit().remove();
+  }
+  rectStyle = function(rect) {
+    var getText;
+    getText = function(axis) {
+      return d3.select("text#" + axis + "_d3plusmouseaxislabel").node().getBBox();
+    };
+    return rect.attr("x", function(d) {
+      var width;
+      width = getText(d).width;
+      if (d === "x") {
+        return x - width / 2 - 5;
+      } else {
+        return graph.margin.left - vars[d].ticks.size - width - 10;
+      }
+    }).attr("y", function(d) {
+      var mod;
+      mod = getText(d).height / 2 + 5;
+      if (d === "y") {
+        return y - mod;
+      } else {
+        if (node.d3plus.y0) {
+          return node.d3plus.y + (node.d3plus.y0 - node.d3plus.y) / 2 + graph.margin.top - mod;
+        } else {
+          return graph.height + graph.margin.top + vars[d].ticks.size;
+        }
+      }
+    }).attr("width", function(d) {
+      return getText(d).width + 10;
+    }).attr("height", function(d) {
+      return getText(d).height + 10;
+    }).style("stroke", vars.shape.value === "area" ? "transparent" : color).attr("fill", vars.shape.value === "area" ? color : vars.background.value).attr("shape-rendering", function(d) {
+      return vars[d].mouse.rendering.value;
+    }).style("stroke-width", function(d) {
+      return vars[d].mouse.width;
+    });
+  };
+  rects = vars.g.labels.selectAll("rect.d3plus_mouse_axis_label").data(lineData);
+  if (timing) {
+    rects.enter().insert("rect", "text.d3plus_mouse_axis_label").attr("class", "d3plus_mouse_axis_label").attr("pointer-events", "none").attr("opacity", 0).call(rectStyle);
+    rects.transition().duration(timing).delay(timing).attr("opacity", 1).call(rectStyle);
+    return rects.exit().transition().duration(timing).attr("opacity", 0).remove();
+  } else {
+    rects.attr("opacity", 1).call(rectStyle);
+    rects.enter().insert("rect", "text.d3plus_mouse_axis_label").attr("class", "d3plus_mouse_axis_label").attr("pointer-events", "none").call(rectStyle);
+    return rects.exit().remove();
+  }
+};
+
+
+},{"../../../../../client/pointer.coffee":40,"../../../../../color/legible.coffee":45,"../../../../../core/fetch/color.coffee":64,"../../../../../core/fetch/value.coffee":68,"../../../../../util/copy.coffee":206}],312:[function(require,module,exports){
+var buckets, buffer, createAxis, fetchValue, fontSizes, formatPower, labelPadding, resetMargins, superscript, textwrap, timeDetect, uniques;
+
+buckets = require("../../../../../util/buckets.coffee");
+
+buffer = require("./buffer.coffee");
+
+fetchValue = require("../../../../../core/fetch/value.coffee");
+
+fontSizes = require("../../../../../font/sizes.coffee");
+
+textwrap = require("../../../../../textwrap/textwrap.coffee");
+
+timeDetect = require("../../../../../core/data/time.coffee");
+
+uniques = require("../../../../../util/uniques.coffee");
+
+module.exports = function(vars, opts) {
+  var axes, axis, axisStyle, extent, j, k, len, len1, newtick, opp, ref, step, tens, tick, ticks, timeReturn, values;
+  vars.axes.margin = resetMargins(vars);
+  vars.axes.height = vars.height.viz;
+  vars.axes.width = vars.width.viz;
+  axes = vars.width.viz > vars.height.viz ? ["y", "x"] : ["x", "y"];
+  for (j = 0, len = axes.length; j < len; j++) {
+    axis = axes[j];
+    if (vars[axis].ticks.values === false) {
+      if (vars[axis].value === vars.time.value) {
+        ticks = vars.time.solo.value;
+        if (ticks.length) {
+          ticks = ticks.map(function(d) {
+            if (d.constructor !== Date) {
+              d = d + "";
+              if (d.length === 4 && parseInt(d) + "" === d) {
+                d += "/01/01";
+              }
+              d = new Date(d);
+            }
+            return d;
+          });
+        } else {
+          ticks = vars.data.time.values;
+        }
+        extent = d3.extent(ticks);
+        step = vars.data.time.stepType;
+        ticks = [extent[0]];
+        tick = extent[0];
+        while (tick < extent[1]) {
+          newtick = new Date(tick);
+          tick = new Date(newtick["set" + step](newtick["get" + step]() + 1));
+          ticks.push(tick);
+        }
+        vars[axis].ticks.values = ticks;
+      } else {
+        vars[axis].ticks.values = vars[axis].scale.viz.ticks();
+      }
+    }
+    if (!vars[axis].ticks.values.length) {
+      values = fetchValue(vars, vars.data.viz, vars[axis].value);
+      if (!(values instanceof Array)) {
+        values = [values];
+      }
+      vars[axis].ticks.values = values;
+    }
+    opp = axis === "x" ? "y" : "x";
+    if (vars[axis].ticks.values.length === 1 || (opts.buffer && opts.buffer !== opp && axis === vars.axes.discrete && vars[axis].reset === true)) {
+      buffer(vars, axis, opts.buffer);
+    }
+    vars[axis].reset = false;
+    if (vars[axis].value === vars.time.value) {
+      axisStyle = {
+        "font-family": vars[axis].ticks.font.family.value,
+        "font-weight": vars[axis].ticks.font.weight,
+        "font-size": vars[axis].ticks.font.size + "px"
+      };
+      timeReturn = timeDetect(vars, {
+        values: vars[axis].ticks.values,
+        limit: vars.width.viz,
+        style: axisStyle
+      });
+      vars[axis].ticks.visible = timeReturn.values.map(Number);
+      vars[axis].ticks.format = timeReturn.format;
+    } else if (vars[axis].scale.value === "log") {
+      ticks = vars[axis].ticks.values;
+      tens = ticks.filter(function(t) {
+        return Math.abs(t).toString().charAt(0) === "1";
+      });
+      if (tens.length < 3) {
+        vars[axis].ticks.visible = ticks;
+      } else {
+        vars[axis].ticks.visible = tens;
+      }
+    } else {
+      vars[axis].ticks.visible = vars[axis].ticks.values;
+    }
+  }
+  if (!vars.small) {
+    labelPadding(vars);
+  }
+  ref = ["x", "y"];
+  for (k = 0, len1 = ref.length; k < len1; k++) {
+    axis = ref[k];
+    vars[axis].axis.svg = createAxis(vars, axis);
+  }
+};
+
+resetMargins = function(vars) {
+  if (vars.small) {
+    return {
+      top: 0,
+      right: 0,
+      bottom: 0,
+      left: 0
+    };
+  } else {
+    return {
+      top: 10,
+      right: 10,
+      bottom: 10,
+      left: 10
+    };
+  }
+};
+
+labelPadding = function(vars) {
+  var lastTick, rightLabel, rightMod, xAttrs, xAxisHeight, xAxisWidth, xDomain, xLabel, xLabelAttrs, xMaxWidth, xSizes, xText, xValues, yAttrs, yAxisWidth, yDomain, yLabel, yLabelAttrs, yText, yValues;
+  xDomain = vars.x.scale.viz.domain();
+  yDomain = vars.y.scale.viz.domain();
+  yAttrs = {
+    "font-size": vars.y.ticks.font.size + "px",
+    "font-family": vars.y.ticks.font.family.value,
+    "font-weight": vars.y.ticks.font.weight
+  };
+  yValues = vars.y.ticks.visible;
+  if (vars.y.scale.value === "log") {
+    yText = yValues.map(function(d) {
+      return formatPower(d);
+    });
+  } else if (vars.y.scale.value === "share") {
+    yText = yValues.map(function(d) {
+      return vars.format.value(d * 100, {
+        key: "share",
+        vars: vars
+      });
+    });
+  } else if (vars.y.value === vars.time.value) {
+    yText = yValues.map(function(d, i) {
+      return vars.y.ticks.format(new Date(d));
+    });
+  } else {
+    if (typeof yValues[0] === "string") {
+      yValues = vars.y.scale.viz.domain().filter(function(d) {
+        return d.indexOf("d3plus_buffer_") !== 0;
+      });
+    }
+    yText = yValues.map(function(d) {
+      return vars.format.value(d, {
+        key: vars.y.value,
+        vars: vars,
+        labels: vars.y.affixes.value
+      });
+    });
+  }
+  yAxisWidth = d3.max(fontSizes(yText, yAttrs), function(d) {
+    return d.width;
+  });
+  yAxisWidth = Math.ceil(yAxisWidth + vars.labels.padding);
+  vars.axes.margin.left += yAxisWidth;
+  yLabel = vars.y.label.fetch(vars);
+  if (yLabel) {
+    yLabelAttrs = {
+      "font-family": vars.y.label.font.family.value,
+      "font-weight": vars.y.label.font.weight,
+      "font-size": vars.y.label.font.size + "px"
+    };
+    vars.y.label.height = fontSizes([yLabel], yLabelAttrs)[0].height;
+  } else {
+    vars.y.label.height = 0;
+  }
+  if (vars.y.label.value) {
+    vars.axes.margin.left += vars.y.label.height;
+    vars.axes.margin.left += vars.y.label.padding * 2;
+  }
+  vars.axes.width -= vars.axes.margin.left + vars.axes.margin.right;
+  vars.x.scale.viz.range(buckets([0, vars.axes.width], xDomain.length));
+  xAttrs = {
+    "font-size": vars.x.ticks.font.size + "px",
+    "font-family": vars.x.ticks.font.family.value,
+    "font-weight": vars.x.ticks.font.weight
+  };
+  xValues = vars.x.ticks.visible;
+  if (vars.x.scale.value === "log") {
+    xText = xValues.map(function(d) {
+      return formatPower(d);
+    });
+  } else if (vars.x.scale.value === "share") {
+    xText = xValues.map(function(d) {
+      return vars.format.value(d * 100, {
+        key: "share",
+        vars: vars
+      });
+    });
+  } else if (vars.x.value === vars.time.value) {
+    xText = xValues.map(function(d, i) {
+      return vars.x.ticks.format(new Date(d));
+    });
+  } else {
+    if (typeof xValues[0] === "string") {
+      xValues = vars.x.scale.viz.domain().filter(function(d) {
+        return d.indexOf("d3plus_buffer_") !== 0;
+      });
+    }
+    xText = xValues.map(function(d) {
+      return vars.format.value(d, {
+        key: vars.x.value,
+        vars: vars,
+        labels: vars.x.affixes.value
+      });
+    });
+  }
+  xSizes = fontSizes(xText, xAttrs);
+  xAxisWidth = d3.max(xSizes, function(d) {
+    return d.width;
+  });
+  xAxisHeight = d3.max(xSizes, function(d) {
+    return d.height;
+  });
+  if (xValues.length === 1) {
+    xMaxWidth = vars.axes.width;
+  } else {
+    xMaxWidth = vars.x.scale.viz(xValues[1]) - vars.x.scale.viz(xValues[0]);
+    xMaxWidth = Math.abs(xMaxWidth);
+  }
+  if (xAxisWidth > xMaxWidth && xText.join("").indexOf(" ") > 0) {
+    vars.x.ticks.wrap = true;
+    xSizes = fontSizes(xText, xAttrs, {
+      mod: function(elem) {
+        return textwrap().container(d3.select(elem)).height(vars.axes.height / 2).width(xMaxWidth).draw();
+      }
+    });
+    xAxisWidth = d3.max(xSizes, function(d) {
+      return d.width;
+    });
+    xAxisHeight = d3.max(xSizes, function(d) {
+      return d.height;
+    });
+  } else {
+    vars.x.ticks.wrap = false;
+  }
+  vars.x.ticks.hidden = false;
+  vars.x.ticks.baseline = "auto";
+  if (xAxisWidth <= xMaxWidth) {
+    vars.x.ticks.rotate = 0;
+  } else if (xAxisWidth < vars.axes.height / 2) {
+    xSizes = fontSizes(xText, xAttrs, {
+      mod: function(elem) {
+        return textwrap().container(d3.select(elem)).width(vars.axes.height / 2).height(xMaxWidth).draw();
+      }
+    });
+    xAxisHeight = d3.max(xSizes, function(d) {
+      return d.width;
+    });
+    xAxisWidth = d3.max(xSizes, function(d) {
+      return d.height;
+    });
+    vars.x.ticks.rotate = -90;
+  } else {
+    xAxisWidth = 0;
+    xAxisHeight = 0;
+  }
+  if (!(xAxisWidth && xAxisHeight)) {
+    vars.x.ticks.hidden = true;
+    vars.x.ticks.rotate = 0;
+  }
+  xAxisWidth = Math.ceil(xAxisWidth);
+  xAxisHeight = Math.ceil(xAxisHeight);
+  xAxisWidth++;
+  xAxisHeight++;
+  vars.x.ticks.maxHeight = xAxisHeight;
+  vars.x.ticks.maxWidth = xAxisWidth;
+  vars.axes.margin.bottom += xAxisHeight + vars.labels.padding;
+  lastTick = vars.x.ticks.visible[vars.x.ticks.visible.length - 1];
+  rightLabel = vars.x.scale.viz(lastTick);
+  rightLabel += xAxisWidth / 2 + vars.axes.margin.left;
+  if (rightLabel > vars.width.value) {
+    rightMod = rightLabel - vars.width.value + vars.axes.margin.right;
+    vars.axes.width -= rightMod;
+    vars.axes.margin.right += rightMod;
+  }
+  xLabel = vars.x.label.fetch(vars);
+  if (xLabel) {
+    xLabelAttrs = {
+      "font-family": vars.x.label.font.family.value,
+      "font-weight": vars.x.label.font.weight,
+      "font-size": vars.x.label.font.size + "px"
+    };
+    vars.x.label.height = fontSizes([xLabel], xLabelAttrs)[0].height;
+  } else {
+    vars.x.label.height = 0;
+  }
+  if (vars.x.label.value) {
+    vars.axes.margin.bottom += vars.x.label.height;
+    vars.axes.margin.bottom += vars.x.label.padding * 2;
+  }
+  vars.axes.height -= vars.axes.margin.top + vars.axes.margin.bottom;
+  vars.x.scale.viz.range(buckets([0, vars.axes.width], xDomain.length));
+  return vars.y.scale.viz.range(buckets([0, vars.axes.height], yDomain.length));
+};
+
+createAxis = function(vars, axis) {
+  return d3.svg.axis().tickSize(vars[axis].ticks.size).tickPadding(5).orient(axis === "x" ? "bottom" : "left").scale(vars[axis].scale.viz).tickValues(vars[axis].ticks.values).tickFormat(function(d, i) {
+    var c, scale;
+    if (vars[axis].ticks.hidden) {
+      return null;
+    }
+    scale = vars[axis].scale.value;
+    c = d.constructor === Date ? +d : d;
+    if (vars[axis].ticks.visible.indexOf(c) >= 0) {
+      if (scale === "share") {
+        return vars.format.value(d * 100, {
+          key: "share",
+          vars: vars,
+          labels: vars[axis].affixes.value
+        });
+      } else if (d.constructor === Date) {
+        return vars[axis].ticks.format(d);
+      } else if (scale === "log") {
+        return formatPower(d);
+      } else {
+        return vars.format.value(d, {
+          key: vars[axis].value,
+          vars: vars,
+          labels: vars[axis].affixes.value
+        });
+      }
+    } else {
+      return null;
+    }
+  });
+};
+
+superscript = "⁰¹²³⁴⁵⁶⁷⁸⁹";
+
+formatPower = function(d) {
+  var n, p, t;
+  p = Math.round(Math.log(Math.abs(d)) / Math.LN10);
+  t = Math.abs(d).toString().charAt(0);
+  n = 10 + " " + (p + "").split("").map(function(c) {
+    return superscript[c];
+  }).join("");
+  if (t !== "1") {
+    n = t + " x " + n;
+  }
+  if (d < 0) {
+    return "-" + n;
+  } else {
+    return n;
+  }
+};
+
+
+},{"../../../../../core/data/time.coffee":63,"../../../../../core/fetch/value.coffee":68,"../../../../../font/sizes.coffee":101,"../../../../../textwrap/textwrap.coffee":199,"../../../../../util/buckets.coffee":203,"../../../../../util/uniques.coffee":209,"./buffer.coffee":310}],313:[function(require,module,exports){
+var mix, textwrap, validObject;
+
+mix = require("../../../../../color/mix.coffee");
+
+textwrap = require("../../../../../textwrap/textwrap.coffee");
+
+validObject = require("../../../../../object/validate.coffee");
+
+module.exports = function(vars) {
+  var affixes, alignMap, axis, axisData, axisLabel, bg, bgStyle, d, domain, domains, getFontStyle, grid, gridData, j, k, l, label, labelData, labelStyle, len, len1, len2, line, lineData, lineFont, lineGroup, lineRects, lineStyle, lines, linetexts, mirror, plane, planeTrans, position, rectData, rectStyle, ref, ref1, rotated, sep, textData, textPad, textPos, tickFont, tickPosition, tickStyle, userLines, xAxis, xEnter, xStyle, yAxis, yEnter, yStyle;
+  domains = vars.x.domain.viz.concat(vars.y.domain.viz);
+  if (domains.indexOf(void 0) >= 0) {
+    return null;
+  }
+  bgStyle = {
+    width: vars.axes.width,
+    height: vars.axes.height,
+    fill: vars.axes.background.color,
+    stroke: vars.axes.background.stroke.color,
+    "stroke-width": vars.axes.background.stroke.width,
+    "shape-rendering": vars.axes.background.rendering.value
+  };
+  alignMap = {
+    left: "start",
+    center: "middle",
+    right: "end"
+  };
+  axisData = vars.small ? [] : [0];
+  tickPosition = function(tick, axis) {
+    return tick.attr("x1", function(d) {
+      if (axis === "x") {
+        return vars.x.scale.viz(d);
+      } else {
+        return 0;
+      }
+    }).attr("x2", function(d) {
+      if (axis === "x") {
+        return vars.x.scale.viz(d);
+      } else {
+        return vars.axes.width;
+      }
+    }).attr("y1", function(d) {
+      if (axis === "y") {
+        return vars.y.scale.viz(d);
+      } else {
+        return 0;
+      }
+    }).attr("y2", function(d) {
+      if (axis === "y") {
+        return vars.y.scale.viz(d);
+      } else {
+        return vars.axes.height;
+      }
+    });
+  };
+  tickStyle = function(tick, axis, grid) {
+    var color, log;
+    color = grid ? vars[axis].grid.color : vars[axis].ticks.color;
+    log = vars[axis].scale.value === "log";
+    return tick.attr("stroke", function(d) {
+      var visible;
+      if (d === 0) {
+        return vars[axis].axis.color;
+      }
+      if (d.constructor === Date) {
+        d = +d;
+      }
+      visible = vars[axis].ticks.visible.indexOf(d) >= 0;
+      if (visible && (!log || Math.abs(d).toString().charAt(0) === "1")) {
+        return color;
+      } else if (grid) {
+        return mix(color, vars.axes.background.color, 0.4, 1);
+      } else {
+        return mix(color, vars.background.value, 0.4, 1);
+      }
+    }).attr("stroke-width", vars[axis].ticks.width).attr("shape-rendering", vars[axis].ticks.rendering.value);
+  };
+  getFontStyle = function(axis, val, style) {
+    var type;
+    type = val === 0 ? "axis" : "ticks";
+    val = vars[axis][type].font[style];
+    if (val && (val.length || typeof val === "number")) {
+      return val;
+    } else {
+      return vars[axis].ticks.font[style];
+    }
+  };
+  tickFont = function(tick, axis) {
+    var log;
+    log = vars[axis].scale.value === "log";
+    return tick.attr("font-size", function(d) {
+      return getFontStyle(axis, d, "size") + "px";
+    }).attr("fill", function(d) {
+      var color;
+      color = getFontStyle(axis, d, "color");
+      if (!log || Math.abs(d).toString().charAt(0) === "1") {
+        return color;
+      } else {
+        return mix(color, vars.background.value, 0.4, 1);
+      }
+    }).attr("font-family", function(d) {
+      return getFontStyle(axis, d, "family").value;
+    }).attr("font-weight", function(d) {
+      return getFontStyle(axis, d, "weight");
+    });
+  };
+  lineStyle = function(line, axis) {
+    var max, opp;
+    max = axis === "x" ? "height" : "width";
+    opp = axis === "x" ? "y" : "x";
+    return line.attr(opp + "1", 0).attr(opp + "2", vars.axes[max]).attr(axis + "1", function(d) {
+      return d.coords.line;
+    }).attr(axis + "2", function(d) {
+      return d.coords.line;
+    }).attr("stroke", function(d) {
+      return d.color || vars[axis].lines.color;
+    }).attr("stroke-width", vars[axis].lines.width).attr("shape-rendering", vars[axis].lines.rendering.value).attr("stroke-dasharray", vars[axis].lines.dasharray.value);
+  };
+  lineFont = function(text, axis) {
+    var opp;
+    opp = axis === "x" ? "y" : "x";
+    return text.attr(opp, function(d) {
+      return d.coords.text[opp] + "px";
+    }).attr(axis, function(d) {
+      return d.coords.text[axis] + "px";
+    }).attr("dy", vars[axis].lines.font.position.value).attr("text-anchor", alignMap[vars[axis].lines.font.align.value]).attr("transform", function(d) {
+      return d.transform;
+    }).attr("font-size", vars[axis].lines.font.size + "px").attr("fill", function(d) {
+      return d.color || vars[axis].lines.color;
+    }).attr("font-family", vars[axis].lines.font.family.value).attr("font-weight", vars[axis].lines.font.weight);
+  };
+  planeTrans = "translate(" + vars.axes.margin.left + "," + vars.axes.margin.top + ")";
+  plane = vars.group.selectAll("g#d3plus_graph_plane").data([0]);
+  plane.transition().duration(vars.draw.timing).attr("transform", planeTrans);
+  plane.enter().append("g").attr("id", "d3plus_graph_plane").attr("transform", planeTrans);
+  bg = plane.selectAll("rect#d3plus_graph_background").data([0]);
+  bg.transition().duration(vars.draw.timing).attr(bgStyle);
+  bg.enter().append("rect").attr("id", "d3plus_graph_background").attr("x", 0).attr("y", 0).attr(bgStyle);
+  mirror = plane.selectAll("path#d3plus_graph_mirror").data([0]);
+  mirror.enter().append("path").attr("id", "d3plus_graph_mirror").attr("fill", "#000").attr("fill-opacity", 0.03).attr("stroke-width", 1).attr("stroke", "#ccc").attr("stroke-dasharray", "10,10").attr("opacity", 0);
+  mirror.transition().duration(vars.draw.timing).attr("opacity", function() {
+    if (vars.axes.mirror.value) {
+      return 1;
+    } else {
+      return 0;
+    }
+  }).attr("d", function() {
+    var h, w;
+    w = bgStyle.width;
+    h = bgStyle.height;
+    return "M " + w + " " + h + " L 0 " + h + " L " + w + " 0 Z";
+  });
+  rotated = vars.x.ticks.rotate !== 0;
+  xStyle = function(axis) {
+    var groups;
+    groups = axis.attr("transform", "translate(0," + vars.axes.height + ")").call(vars.x.axis.svg.scale(vars.x.scale.viz)).selectAll("g.tick");
+    groups.selectAll("line").attr("y2", function(d) {
+      var y2;
+      if (d.constructor === Date) {
+        d = +d;
+      }
+      y2 = d3.select(this).attr("y2");
+      if (vars.x.ticks.visible.indexOf(d) >= 0) {
+        return y2;
+      } else {
+        return y2 / 2;
+      }
+    });
+    return groups.select("text").attr("dy", "").style("text-anchor", rotated ? "end" : "middle").call(tickFont, "x").each("end", function(d) {
+      if (d.constructor === Date) {
+        d = +d;
+      }
+      if (!vars.x.ticks.hidden && vars.x.ticks.visible.indexOf(d) >= 0) {
+        return textwrap().container(d3.select(this)).rotate(vars.x.ticks.rotate).valign(rotated ? "middle" : "top").width(vars.x.ticks.maxWidth).height(vars.x.ticks.maxHeight).padding(0).x(-vars.x.ticks.maxWidth / 2).draw();
+      }
+    });
+  };
+  xAxis = plane.selectAll("g#d3plus_graph_xticks").data(axisData);
+  xAxis.transition().duration(vars.draw.timing).call(xStyle);
+  xAxis.selectAll("line").transition().duration(vars.draw.timing).call(tickStyle, "x");
+  xEnter = xAxis.enter().append("g").attr("id", "d3plus_graph_xticks").transition().duration(0).call(xStyle);
+  xEnter.selectAll("path").attr("fill", "none");
+  xEnter.selectAll("line").call(tickStyle, "x");
+  xAxis.exit().transition().duration(vars.data.timing).attr("opacity", 0).remove();
+  yStyle = function(axis) {
+    var groups;
+    groups = axis.call(vars.y.axis.svg.scale(vars.y.scale.viz)).selectAll("g.tick");
+    groups.selectAll("line").attr("y2", function(d) {
+      var y2;
+      if (d.constructor === Date) {
+        d = +d;
+      }
+      y2 = d3.select(this).attr("y2");
+      if (vars.x.ticks.visible.indexOf(d) >= 0) {
+        return y2;
+      } else {
+        return y2 / 2;
+      }
+    });
+    return groups.select("text").call(tickFont, "y");
+  };
+  yAxis = plane.selectAll("g#d3plus_graph_yticks").data(axisData);
+  yAxis.transition().duration(vars.draw.timing).call(yStyle);
+  yAxis.selectAll("line").transition().duration(vars.draw.timing).call(tickStyle, "y");
+  yEnter = yAxis.enter().append("g").attr("id", "d3plus_graph_yticks").call(yStyle);
+  yEnter.selectAll("path").attr("fill", "none");
+  yEnter.selectAll("line").call(tickStyle, "y");
+  yAxis.exit().transition().duration(vars.data.timing).attr("opacity", 0).remove();
+  labelStyle = function(label, axis) {
+    return label.attr("x", axis === "x" ? vars.width.viz / 2 : -(vars.axes.height / 2 + vars.axes.margin.top)).attr("y", axis === "x" ? vars.height.viz - vars[axis].label.height / 2 - vars[axis].label.padding : vars[axis].label.height / 2 + vars[axis].label.padding).attr("transform", axis === "y" ? "rotate(-90)" : null).attr("font-family", vars[axis].label.font.family.value).attr("font-weight", vars[axis].label.font.weight).attr("font-size", vars[axis].label.font.size + "px").attr("fill", vars[axis].label.font.color).style("text-anchor", "middle").attr("dominant-baseline", "central");
+  };
+  ref = ["x", "y"];
+  for (j = 0, len = ref.length; j < len; j++) {
+    axis = ref[j];
+    if (vars[axis].grid.value) {
+      gridData = vars[axis].ticks.values;
+    } else {
+      gridData = [];
+      if (vars[axis].ticks.values.indexOf(0) >= 0 && vars[axis].axis.value) {
+        gridData = [0];
+      }
+    }
+    grid = plane.selectAll("g#d3plus_graph_" + axis + "grid").data([0]);
+    grid.enter().append("g").attr("id", "d3plus_graph_" + axis + "grid");
+    lines = grid.selectAll("line").data(gridData, function(d, i) {
+      if (d.constructor === Date) {
+        return d.getTime();
+      } else {
+        return d;
+      }
+    });
+    lines.transition().duration(vars.draw.timing).call(tickPosition, axis).call(tickStyle, axis, true);
+    lines.enter().append("line").style("opacity", 0).call(tickPosition, axis).call(tickStyle, axis, true).transition().duration(vars.draw.timing).delay(vars.draw.timing / 2).style("opacity", 1);
+    lines.exit().transition().duration(vars.draw.timing / 2).style("opacity", 0).remove();
+    axisLabel = vars[axis].label.fetch(vars);
+    labelData = axisData && axisLabel ? [0] : [];
+    affixes = vars.format.affixes.value[vars[axis].value];
+    if (axisLabel && !vars[axis].affixes.value && affixes) {
+      sep = vars[axis].affixes.separator.value;
+      if (sep === true) {
+        sep = ["[", "]"];
+      } else if (sep === false) {
+        sep = ["", ""];
+      }
+      axisLabel += " " + sep[0] + affixes[0] + " " + affixes[1] + sep[1];
+    }
+    label = vars.group.selectAll("text#d3plus_graph_" + axis + "label").data(labelData);
+    label.text(axisLabel).transition().duration(vars.draw.timing).call(labelStyle, axis);
+    label.enter().append("text").attr("id", "d3plus_graph_" + axis + "label").text(axisLabel).call(labelStyle, axis);
+    label.exit().transition().duration(vars.data.timing).attr("opacity", 0).remove();
+  }
+  ref1 = ["x", "y"];
+  for (k = 0, len1 = ref1.length; k < len1; k++) {
+    axis = ref1[k];
+    lineGroup = plane.selectAll("g#d3plus_graph_" + axis + "_userlines").data([0]);
+    lineGroup.enter().append("g").attr("id", "d3plus_graph_" + axis + "_userlines");
+    domain = vars[axis].scale.viz.domain();
+    if (axis === "y") {
+      domain = domain.slice().reverse();
+    }
+    textData = [];
+    lineData = [];
+    userLines = vars[axis].lines.value || [];
+    for (l = 0, len2 = userLines.length; l < len2; l++) {
+      line = userLines[l];
+      d = validObject(line) ? line.position : line;
+      if (!isNaN(d)) {
+        d = parseFloat(d);
+        if (d > domain[0] && d < domain[1]) {
+          d = !validObject(line) ? {
+            "position": d
+          } : line;
+          d.coords = {
+            line: vars[axis].scale.viz(d.position)
+          };
+          lineData.push(d);
+          if (d.text) {
+            d.axis = axis;
+            d.padding = vars[axis].lines.font.padding.value * 0.5;
+            d.align = vars[axis].lines.font.align.value;
+            position = vars[axis].lines.font.position.text;
+            textPad = position === "middle" ? 0 : d.padding * 2;
+            if (position === "top") {
+              textPad = -textPad;
+            }
+            if (axis === "x") {
+              textPos = d.align === "left" ? vars.axes.height : d.align === "center" ? vars.axes.height / 2 : 0;
+              if (d.align === "left") {
+                textPos -= d.padding * 2;
+              }
+              if (d.align === "right") {
+                textPos += d.padding * 2;
+              }
+            } else {
+              textPos = d.align === "left" ? 0 : d.align === "center" ? vars.axes.width / 2 : vars.axes.width;
+              if (d.align === "right") {
+                textPos -= d.padding * 2;
+              }
+              if (d.align === "left") {
+                textPos += d.padding * 2;
+              }
+            }
+            d.coords.text = {};
+            d.coords.text[axis === "x" ? "y" : "x"] = textPos;
+            d.coords.text[axis] = vars[axis].scale.viz(d.position) + textPad;
+            d.transform = axis === "x" ? "rotate(-90," + d.coords.text.x + "," + d.coords.text.y + ")" : null;
+            textData.push(d);
+          }
+        }
+      }
+    }
+    lines = lineGroup.selectAll("line.d3plus_graph_" + axis + "line").data(lineData, function(d) {
+      return d.position;
+    });
+    lines.enter().append("line").attr("class", "d3plus_graph_" + axis + "line").attr("opacity", 0).call(lineStyle, axis);
+    lines.transition().duration(vars.draw.timing).attr("opacity", 1).call(lineStyle, axis);
+    lines.exit().transition().duration(vars.draw.timing).attr("opacity", 0).remove();
+    linetexts = lineGroup.selectAll("text.d3plus_graph_" + axis + "line_text").data(textData, function(d) {
+      return d.position;
+    });
+    linetexts.enter().append("text").attr("class", "d3plus_graph_" + axis + "line_text").attr("id", function(d) {
+      var id;
+      id = d.position + "";
+      id = id.replace("-", "neg");
+      id = id.replace(".", "p");
+      return "d3plus_graph_" + axis + "line_text_" + id;
+    }).attr("opacity", 0).call(lineFont, axis);
+    linetexts.text(function(d) {
+      return d.text;
+    }).transition().duration(vars.draw.timing).attr("opacity", 1).call(lineFont, axis);
+    linetexts.exit().transition().duration(vars.draw.timing).attr("opacity", 0).remove();
+    rectStyle = function(rect) {
+      var getText;
+      getText = function(d) {
+        var id;
+        id = d.position + "";
+        id = id.replace("-", "neg");
+        id = id.replace(".", "p");
+        return plane.select("text#d3plus_graph_" + d.axis + "line_text_" + id).node().getBBox();
+      };
+      return rect.attr("x", function(d) {
+        return getText(d).x - d.padding;
+      }).attr("y", function(d) {
+        return getText(d).y - d.padding;
+      }).attr("transform", function(d) {
+        return d.transform;
+      }).attr("width", function(d) {
+        return getText(d).width + (d.padding * 2);
+      }).attr("height", function(d) {
+        return getText(d).height + (d.padding * 2);
+      }).attr("fill", vars.axes.background.color);
+    };
+    rectData = vars[axis].lines.font.background.value ? textData : [];
+    lineRects = lineGroup.selectAll("rect.d3plus_graph_" + axis + "line_rect").data(rectData, function(d) {
+      return d.position;
+    });
+    lineRects.enter().insert("rect", "text.d3plus_graph_" + axis + "line_text").attr("class", "d3plus_graph_" + axis + "line_rect").attr("pointer-events", "none").attr("opacity", 0).call(rectStyle);
+    lineRects.transition().delay(vars.draw.timing).each("end", function(d) {
+      return d3.select(this).transition().duration(vars.draw.timing).attr("opacity", 1).call(rectStyle);
+    });
+    lineRects.exit().transition().duration(vars.draw.timing).attr("opacity", 0).remove();
+  }
+};
+
+
+},{"../../../../../color/mix.coffee":47,"../../../../../object/validate.coffee":171,"../../../../../textwrap/textwrap.coffee":199}],314:[function(require,module,exports){
+var fetchValue, stringStrip, uniqueValues;
+
+fetchValue = require("../../../../core/fetch/value.coffee");
+
+stringStrip = require("../../../../string/strip.js");
+
+uniqueValues = require("../../../../util/uniques.coffee");
+
+module.exports = function(vars, data) {
+  var discrete, key, opposite, serialized, ticks, timeAxis;
+  if (!data) {
+    data = vars.data.viz;
+  }
+  discrete = vars[vars.axes.discrete];
+  opposite = vars[vars.axes.opposite];
+  timeAxis = discrete.value === vars.time.value;
+  if (timeAxis) {
+    ticks = vars.data.time.ticks;
+    key = vars.time.solo.value.length ? "solo" : "mute";
+    if (vars.time[key].value.length) {
+      serialized = vars.time[key].value.slice().map(function(f) {
+        if (f.constructor !== Date) {
+          f = f + "";
+          if (f.length === 4 && parseInt(f) + "" === f) {
+            f += "/01/01";
+          }
+          f = new Date(f);
+        }
+        return +f;
+      });
+      ticks = ticks.filter(function(f) {
+        if (key === "solo") {
+          return serialized.indexOf(+f) >= 0;
+        } else {
+          return serialized.indexOf(+f) < 0;
+        }
+      });
+    }
+  } else if (discrete.ticks.values) {
+    ticks = discrete.ticks.values;
+  } else {
+    ticks = uniqueValues(data, discrete.value, fetchValue, vars);
+  }
+  return d3.nest().key(function(d) {
+    var id, j, len, ref, return_id, val;
+    return_id = "nesting";
+    ref = vars.id.nesting.slice(0, vars.depth.value + 1);
+    for (j = 0, len = ref.length; j < len; j++) {
+      id = ref[j];
+      val = fetchValue(vars, d, id);
+      if (val instanceof Array) {
+        val = val.join("_");
+      }
+      return_id += "_" + stringStrip(val);
+    }
+    return return_id;
+  }).rollup(function(leaves) {
+    var availables, filler, i, j, k, len, len1, obj, ref, tester, tick, timeVar;
+    availables = uniqueValues(leaves, discrete.value, fetchValue, vars);
+    timeVar = availables.length && availables[0].constructor === Date;
+    if (timeVar) {
+      availables = availables.map(Number);
+    }
+    if (discrete.zerofill.value) {
+      if (discrete.scale.value === "log") {
+        if (opposite.scale.viz.domain().every(function(d) {
+          return d < 0;
+        })) {
+          filler = -1;
+        } else {
+          filler = 1;
+        }
+      } else {
+        filler = 0;
+      }
+      for (i = j = 0, len = ticks.length; j < len; i = ++j) {
+        tick = ticks[i];
+        tester = timeAxis ? +tick : tick;
+        if (availables.indexOf(tester) < 0) {
+          obj = {
+            d3plus: {}
+          };
+          ref = vars.id.nesting;
+          for (k = 0, len1 = ref.length; k < len1; k++) {
+            key = ref[k];
+            if (key in leaves[0]) {
+              obj[key] = leaves[0][key];
+            }
+          }
+          obj[discrete.value] = tick;
+          obj[opposite.value] = 0;
+          obj[opposite.value] = filler;
+          leaves.splice(i, 0, obj);
+        }
+      }
+    }
+    if (typeof leaves[0][discrete.value] === "string") {
+      return leaves;
+    } else {
+      return leaves.sort(function(a, b) {
+        var ad, ao, bd, bo, xsort;
+        ad = fetchValue(vars, a, discrete.value);
+        bd = fetchValue(vars, b, discrete.value);
+        xsort = ad - bd;
+        if (xsort) {
+          return xsort;
+        }
+        ao = fetchValue(vars, a, opposite.value);
+        bo = fetchValue(vars, b, opposite.value);
+        return ao - bo;
+      });
+    }
+  }).entries(data);
+};
+
+
+},{"../../../../core/fetch/value.coffee":68,"../../../../string/strip.js":174,"../../../../util/uniques.coffee":209}],315:[function(require,module,exports){
+var fetchValue;
+
+fetchValue = require("../../../../core/fetch/value.coffee");
+
+module.exports = function(vars, data) {
+  var d, flip, i, j, len, len1, margin, neg, negativeData, offset, opposite, positiveData, scale, stack, stacked, v, val;
+  stacked = vars.axes.stacked;
+  flip = vars[stacked].scale.viz(0);
+  scale = vars[stacked].scale.value;
+  opposite = stacked === "x" ? "y" : "x";
+  margin = stacked === "y" ? vars.axes.margin.top : vars.axes.margin.left;
+  offset = scale === "share" ? "expand" : "zero";
+  stack = d3.layout.stack().values(function(d) {
+    return d.values;
+  }).offset(offset).x(function(d) {
+    return d.d3plus[opposite];
+  }).y(function(d) {
+    return flip - vars[stacked].scale.viz(fetchValue(vars, d, vars[stacked].value));
+  }).out(function(d, y0, y) {
+    var negative, value;
+    value = fetchValue(vars, d, vars[stacked].value);
+    negative = value < 0;
+    if (scale === "share") {
+      d.d3plus[stacked + "0"] = (1 - y0) * flip;
+      d.d3plus[stacked] = d.d3plus[stacked + "0"] - (y * flip);
+    } else {
+      d.d3plus[stacked + "0"] = flip - y0;
+      d.d3plus[stacked] = d.d3plus[stacked + "0"] - y;
+    }
+    d.d3plus[stacked] += margin;
+    return d.d3plus[stacked + "0"] += margin;
+  });
+  positiveData = [];
+  negativeData = [];
+  for (i = 0, len = data.length; i < len; i++) {
+    d = data[i];
+    val = fetchValue(vars, d, vars[stacked].value);
+    if (val instanceof Array) {
+      neg = true;
+      for (j = 0, len1 = val.length; j < len1; j++) {
+        v = val[j];
+        if (v >= 0) {
+          neg = false;
+          break;
+        }
+      }
+      if (neg) {
+        negativeData.push(d);
+      } else {
+        positiveData.push(d);
+      }
+    } else {
+      if (val >= 0) {
+        positiveData.push(d);
+      }
+      if (val < 0) {
+        negativeData.push(d);
+      }
+    }
+  }
+  if (!(positiveData.length || negativeData.length)) {
+    return stack(data);
+  } else {
+    if (positiveData.length) {
+      positiveData = stack(positiveData);
+    }
+    if (negativeData.length) {
+      negativeData = stack(negativeData);
+    }
+    return positiveData.concat(negativeData);
+  }
+};
+
+
+},{"../../../../core/fetch/value.coffee":68}],316:[function(require,module,exports){
+var fetchValue, graph, line, nest, stack;
+
+fetchValue = require("../../core/fetch/value.coffee");
+
+graph = require("./helpers/graph/draw.coffee");
+
+nest = require("./helpers/graph/nest.coffee");
+
+stack = require("./helpers/graph/stack.coffee");
+
+line = function(vars) {
+  var d, data, domains, i, j, len, len1, point, ref;
+  graph(vars, {
+    buffer: vars.axes.opposite,
+    mouse: true
+  });
+  domains = vars.x.domain.viz.concat(vars.y.domain.viz);
+  if (domains.indexOf(void 0) >= 0) {
+    return [];
+  }
+  data = vars.data.viz;
+  for (i = 0, len = data.length; i < len; i++) {
+    point = data[i];
+    ref = point.values;
+    for (j = 0, len1 = ref.length; j < len1; j++) {
+      d = ref[j];
+      d.d3plus.x = vars.x.scale.viz(fetchValue(vars, d, vars.x.value));
+      d.d3plus.x += vars.axes.margin.left;
+      d.d3plus.y = vars.y.scale.viz(fetchValue(vars, d, vars.y.value));
+      d.d3plus.y += vars.axes.margin.top;
+    }
+  }
+  if (vars.axes.stacked) {
+    return stack(vars, data);
+  } else {
+    return data;
+  }
+};
+
+line.filter = function(vars, data) {
+  return nest(vars, data);
+};
+
+line.requirements = ["data", "x", "y"];
+
+line.setup = function(vars) {
+  var axis, size, y;
+  if (!vars.axes.discrete) {
+    axis = vars.time.value === vars.y.value ? "y" : "x";
+    vars.self[axis]({
+      scale: "discrete"
+    });
+  }
+  y = vars[vars.axes.opposite];
+  size = vars.size;
+  if ((!y.value && size.value) || (size.changed && size.previous === y.value)) {
+    vars.self[vars.axes.opposite](size.value);
+  } else if ((!size.value && y.value) || (y.changed && y.previous === size.value)) {
+    vars.self.size(y.value);
+  }
+};
+
+line.shapes = ["line"];
+
+line.tooltip = "static";
+
+module.exports = line;
+
+
+},{"../../core/fetch/value.coffee":68,"./helpers/graph/draw.coffee":308,"./helpers/graph/nest.coffee":314,"./helpers/graph/stack.coffee":315}],317:[function(require,module,exports){
+var smallestGap = require("../../network/smallestGap.coffee"),
+    fetchValue = require("../../core/fetch/value.coffee");
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Network
+//------------------------------------------------------------------------------
+var network = function(vars) {
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Use filtered lists if they are available
+  //----------------------------------------------------------------------------
+  var nodes = vars.nodes.restricted || vars.nodes.value,
+      edges = vars.edges.restricted || vars.edges.value
+
+  var x_range = d3.extent(nodes,function(n){return n.x}),
+      y_range = d3.extent(nodes,function(n){return n.y})
+
+  var val_range = [ 1 , 1 ]
+  if (typeof vars.size.value === "number"){
+    val_range = [vars.size.value, vars.size.value]
+  }
+  else if (vars.size.value){
+    val_range = d3.extent(nodes, function(d){
+      var val = fetchValue( vars , d , vars.size.value )
+      return val === 0 ? null : val
+    })
+  }
+  if (typeof val_range[0] == "undefined") val_range = [1,1]
+
+  if (typeof vars.size.value === "number"){
+    var max_size = vars.size.value;
+    var min_size = vars.size.value;
+  }
+  else {
+
+    var max_size = smallestGap(nodes, {"accessor": function(n){
+      return [n.x, n.y];
+    }});
+
+    var limit = max_size/2;
+
+    var overlap = vars.size.value ? vars.nodes.overlap : 0.4
+    max_size = max_size * overlap;
+
+    if (vars.edges.arrows.value) {
+      max_size = max_size * 0.5;
+    }
+
+    if (val_range[0] === val_range[1]) {
+      var min_size = limit;
+      max_size = limit;
+    }
+    else {
+
+      var width = (x_range[1]+max_size*1.1)-(x_range[0]-max_size*1.1),
+          height = (y_range[1]+max_size*1.1)-(y_range[0]-max_size*1.1),
+          aspect = width/height,
+          app = vars.width.viz/vars.height.viz;
+
+      if ( app > aspect ) {
+        var scale = vars.height.viz/height;
+      }
+      else {
+        var scale = vars.width.viz/width;
+      }
+      var min_size = max_size * 0.25;
+      if ( min_size * scale < 2 ) {
+        min_size = 2/scale;
+      }
+
+    }
+  }
+
+  // Create size scale
+  var radius = vars.size.scale.value
+    .domain(val_range)
+    .range([min_size, max_size])
+
+  vars.zoom.bounds = [ [ x_range[0]-max_size*1.1 , y_range[0]-max_size*1.1 ]
+                     , [ x_range[1]+max_size*1.1 , y_range[1]+max_size*1.1 ] ]
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Match nodes to data
+  //----------------------------------------------------------------------------
+  var data = [], lookup = {}
+  nodes.forEach(function(n){
+
+    var d = vars.data.viz.filter(function(a){
+      return a[vars.id.value] == n[vars.id.value]
+    })[0]
+
+    var obj = d || {}
+
+    obj[vars.id.value] = n[vars.id.value]
+
+    obj.d3plus = {}
+    obj.d3plus.x = n.x
+    obj.d3plus.y = n.y
+    var val = fetchValue(vars,obj,vars.size.value)
+    obj.d3plus.r = val ? radius(val) : radius.range()[0]
+    lookup[obj[vars.id.value]] = {
+      "x": obj.d3plus.x,
+      "y": obj.d3plus.y,
+      "r": obj.d3plus.r
+    }
+
+    data.push(obj)
+  })
+
+  data.sort(function(a,b){
+    return b.d3plus.r - a.d3plus.r
+  })
+
+  edges.forEach(function(l,i){
+
+    if (l.d3plus) {
+      delete l.d3plus.spline
+    }
+
+    l[vars.edges.source].d3plus = {}
+    var source = lookup[l[vars.edges.source][vars.id.value]]
+    l[vars.edges.source].d3plus.r = source.r
+    l[vars.edges.source].d3plus.x = source.x
+    l[vars.edges.source].d3plus.y = source.y
+
+    l[vars.edges.target].d3plus = {}
+    var target = lookup[l[vars.edges.target][vars.id.value]]
+    l[vars.edges.target].d3plus.r = target.r
+    l[vars.edges.target].d3plus.x = target.x
+    l[vars.edges.target].d3plus.y = target.y
+
+  })
+
+  return {"nodes": data, "edges": edges}
+
+}
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Visualization Settings and Helper Functions
+//------------------------------------------------------------------------------
+network.nesting      = false
+network.requirements = ["nodes","edges"]
+network.scale        = 1.05
+network.shapes       = [ "circle" , "square" , "donut" ]
+network.tooltip      = "static"
+network.zoom         = true
+
+module.exports = network
+
+},{"../../core/fetch/value.coffee":68,"../../network/smallestGap.coffee":167}],318:[function(require,module,exports){
+var fetchValue, shortestPath, uniqueValues, viz,
+  indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+shortestPath = require("../../network/shortestPath.coffee");
+
+fetchValue = require("../../core/fetch/value.coffee");
+
+uniqueValues = require("../../util/uniques.coffee");
+
+viz = function(vars) {
+  var base, base1, base2, base3, col, colIndex, columnWidth, columns, edge, edgeInt, edges, i, id, j, k, l, labelSpace, lastDir, lastHop, len, len1, len2, len3, len4, len5, len6, len7, m, maxRadius, minRadius, n, newPath, next, nextDir, nextHop, nextIndex, node, o, p, path, pathInt, pathLookup, paths, prev, prevIndex, q, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, rowHeight, rows, size, sizeDomain, val, x, xDiff, y, yDomain;
+  edges = [];
+  pathLookup = {};
+  pathLookup[vars.focus.value[0]] = 0;
+  pathLookup[vars.focus.value[1]] = 0;
+  paths = {
+    all: [[vars.focus.value[0]], [vars.focus.value[1]]]
+  };
+  ref = viz.paths;
+  for (pathInt = j = 0, len = ref.length; j < len; pathInt = ++j) {
+    path = ref[pathInt];
+    edges = edges.concat(path.edges);
+    lastHop = vars.focus.value[0];
+    paths[pathInt] = [lastHop];
+    ref1 = path.edges;
+    for (edgeInt = k = 0, len1 = ref1.length; k < len1; edgeInt = ++k) {
+      edge = ref1[edgeInt];
+      edge[vars.edges.source] = vars.data.viz.filter(function(d) {
+        return edge[vars.edges.source][vars.id.value] === d[vars.id.value];
+      })[0];
+      edge[vars.edges.target] = vars.data.viz.filter(function(d) {
+        return edge[vars.edges.target][vars.id.value] === d[vars.id.value];
+      })[0];
+      nextDir = edge[vars.edges.source][vars.id.value] === lastHop ? "target" : "source";
+      nextHop = edge[vars.edges[nextDir]][vars.id.value];
+      if (pathLookup[nextHop] === void 0) {
+        pathLookup[nextHop] = pathInt;
+      }
+      paths[pathInt].push(nextHop);
+      lastHop = nextHop;
+    }
+  }
+  rows = 0;
+  for (pathInt in paths) {
+    path = paths[pathInt];
+    if (pathInt !== "all") {
+      newPath = 0;
+      for (i = l = 0, len2 = path.length; l < len2; i = ++l) {
+        id = path[i];
+        if ((i !== 0 && i !== (path.length - 1)) && pathLookup[id] === parseFloat(pathInt)) {
+          newPath = 1;
+          prev = path[i - 1];
+          next = path[i + 1];
+          prevIndex = null;
+          nextIndex = null;
+          ref2 = paths.all;
+          for (colIndex = m = 0, len3 = ref2.length; m < len3; colIndex = ++m) {
+            col = ref2[colIndex];
+            if (indexOf.call(col, prev) >= 0) {
+              prevIndex = colIndex;
+            }
+            if (indexOf.call(col, next) >= 0) {
+              nextIndex = colIndex;
+            }
+          }
+          if (prevIndex !== null && nextIndex === null) {
+            if (prevIndex + 1 === paths.all.length - 1) {
+              paths.all.splice(prevIndex + 1, 0, [id]);
+            } else {
+              paths.all[prevIndex + 1].push(id);
+            }
+          } else if (nextIndex - prevIndex === 1) {
+            paths.all.splice(nextIndex, 0, [id]);
+          } else if (nextIndex - prevIndex > 1) {
+            paths.all[nextIndex - 1].push(id);
+          }
+        }
+      }
+      rows += newPath;
+    }
+  }
+  rowHeight = Math.floor(vars.height.viz / rows);
+  yDomain = [];
+  i = 0;
+  while (i < rows) {
+    if (i % 2 === 0) {
+      yDomain.push(i);
+    } else {
+      yDomain.unshift(i);
+    }
+    i++;
+  }
+  labelSpace = vars.size.value && !vars.small ? 30 : 0;
+  y = d3.scale.ordinal().domain(yDomain).range(d3.range(rowHeight / 2 - labelSpace, vars.height.viz + rowHeight / 2 - labelSpace, (vars.height.viz - rowHeight) / (rows - 1)));
+  columns = paths["all"].length;
+  columnWidth = Math.floor(vars.width.viz / columns);
+  x = d3.scale.linear().domain([0, columns - 1]).rangeRound([columnWidth / 2, vars.width.viz - columnWidth / 2]);
+  minRadius = 5;
+  maxRadius = d3.min([columnWidth, rowHeight - labelSpace]) * 0.4;
+  sizeDomain = d3.extent(vars.data.viz, function(node) {
+    var val;
+    val = fetchValue(vars, node, vars.size.value);
+    return val || 0;
+  });
+  size = vars.size.scale.value.domain(sizeDomain).rangeRound([minRadius, maxRadius]);
+  ref3 = vars.data.viz;
+  for (n = 0, len4 = ref3.length; n < len4; n++) {
+    node = ref3[n];
+    if (node.d3plus == null) {
+      node.d3plus = {};
+    }
+    ref4 = paths["all"];
+    for (colIndex = o = 0, len5 = ref4.length; o < len5; colIndex = ++o) {
+      col = ref4[colIndex];
+      if (ref5 = node[vars.id.value], indexOf.call(col, ref5) >= 0) {
+        node.d3plus.x = x(colIndex);
+      }
+    }
+    node.d3plus.y = y(pathLookup[node[vars.id.value]]);
+    if (vars.size.value) {
+      val = fetchValue(vars, node, vars.size.value);
+      node.d3plus.r = val ? size(val) : minRadius;
+    } else {
+      node.d3plus.r = maxRadius;
+    }
+    if (node.d3plus.r < columnWidth * 0.1 && !vars.small) {
+      node.d3plus.label = {
+        x: 0,
+        y: node.d3plus.r + vars.labels.padding * 2,
+        w: columnWidth * 0.6,
+        h: labelSpace + maxRadius - node.d3plus.r,
+        resize: false
+      };
+    } else {
+      delete node.d3plus.label;
+    }
+  }
+  ref6 = viz.paths;
+  for (pathInt = p = 0, len6 = ref6.length; p < len6; pathInt = ++p) {
+    path = ref6[pathInt];
+    lastHop = vars.focus.value[0];
+    ref7 = path.edges;
+    for (edgeInt = q = 0, len7 = ref7.length; q < len7; edgeInt = ++q) {
+      edge = ref7[edgeInt];
+      nextDir = edge[vars.edges.source][vars.id.value] === lastHop ? "target" : "source";
+      lastDir = nextDir === "target" ? "source" : "target";
+      nextHop = edge[vars.edges[nextDir]][vars.id.value];
+      if (pathLookup[lastHop] !== pathLookup[nextHop]) {
+        edge.d3plus = {
+          spline: true
+        };
+        if ((base = edge[vars.edges.source]).d3plus == null) {
+          base.d3plus = {};
+        }
+        if ((base1 = edge[vars.edges.source].d3plus).edges == null) {
+          base1.edges = {};
+        }
+        if ((base2 = edge[vars.edges.target]).d3plus == null) {
+          base2.d3plus = {};
+        }
+        if ((base3 = edge[vars.edges.target].d3plus).edges == null) {
+          base3.edges = {};
+        }
+        xDiff = edge[nextDir].d3plus.x - edge[lastDir].d3plus.x;
+        edge[lastDir].d3plus.edges[edge[nextDir][vars.id.value]] = {
+          angle: Math.PI,
+          radius: columnWidth / 2
+        };
+        edge[nextDir].d3plus.edges[edge[lastDir][vars.id.value]] = {
+          angle: 0,
+          radius: columnWidth / 2,
+          offset: xDiff - columnWidth
+        };
+      } else {
+        delete edge.d3plus;
+      }
+      lastHop = nextHop;
+    }
+  }
+  return {
+    nodes: vars.data.viz,
+    edges: edges
+  };
+};
+
+viz.filter = function(vars, data) {
+  var added, d, edge, edges, id, ids, j, k, l, len, len1, len2, obj, path, ref, ref1, returnData, source, target;
+  edges = vars.edges.filtered || vars.edges.value;
+  viz.paths = shortestPath(edges, vars.focus.value[0], {
+    target: vars.focus.value[1],
+    distance: vars.edges.size.value || void 0,
+    nodeid: vars.id.value,
+    startpoint: vars.edges.source,
+    endpoint: vars.edges.target,
+    K: vars.edges.limit.value || 5
+  });
+  viz.nodes = [];
+  added = [];
+  ref = viz.paths;
+  for (j = 0, len = ref.length; j < len; j++) {
+    path = ref[j];
+    ref1 = path.edges;
+    for (k = 0, len1 = ref1.length; k < len1; k++) {
+      edge = ref1[k];
+      source = edge[vars.edges.source];
+      target = edge[vars.edges.target];
+      if (added.indexOf(source[vars.id.value]) < 0) {
+        viz.nodes.push(source);
+        added.push(source[vars.id.value]);
+      }
+      if (added.indexOf(target[vars.id.value]) < 0) {
+        viz.nodes.push(target);
+        added.push(target[vars.id.value]);
+      }
+    }
+  }
+  ids = uniqueValues(viz.nodes, vars.id.value, fetchValue, vars);
+  returnData = [];
+  for (l = 0, len2 = ids.length; l < len2; l++) {
+    id = ids[l];
+    d = data.filter(function(d) {
+      return d[vars.id.value] === id;
+    });
+    if (!d[0]) {
+      obj = {
+        d3plus: {}
+      };
+      obj[vars.id.value] = id;
+      returnData.push(obj);
+    } else {
+      returnData.push(d[0]);
+    }
+  }
+  return returnData;
+};
+
+viz.nesting = false;
+
+viz.requirements = [
+  function(vars) {
+    return {
+      status: vars.focus.value.length === 2,
+      text: vars.format.locale.value.method.focus + " x 2"
+    };
+  }, "edges"
+];
+
+viz.scale = 1;
+
+viz.shapes = ["circle", "square", "donut"];
+
+viz.tooltip = "static";
+
+module.exports = viz;
+
+
+},{"../../core/fetch/value.coffee":68,"../../network/shortestPath.coffee":166,"../../util/uniques.coffee":209}],319:[function(require,module,exports){
+var comparator, dataThreshold, fetchValue, groupData, order, pie;
+
+comparator = require("../../array/comparator.coffee");
+
+dataThreshold = require("../../core/data/threshold.js");
+
+fetchValue = require("../../core/fetch/value.coffee");
+
+groupData = require("../../core/data/group.coffee");
+
+order = {};
+
+pie = function(vars) {
+  var d, groupedData, i, item, len, pieData, pieLayout, radius, returnData;
+  pieLayout = d3.layout.pie().value(function(d) {
+    return d.value;
+  }).sort(function(a, b) {
+    var aID, bID;
+    if (vars.order.value) {
+      return comparator(a.d3plus, b.d3plus, [vars.order.value], vars.order.sort.value, [], vars);
+    } else {
+      aID = fetchValue(vars, a.d3plus, vars.id.value);
+      if (order[aID] === void 0) {
+        order[aID] = a.value;
+      }
+      bID = fetchValue(vars, b.d3plus, vars.id.value);
+      if (order[bID] === void 0) {
+        order[bID] = b.value;
+      }
+      if (order[bID] < order[aID]) {
+        return -1;
+      } else {
+        return 1;
+      }
+    }
+  });
+  groupedData = groupData(vars, vars.data.viz, []);
+  pieData = pieLayout(groupedData);
+  returnData = [];
+  radius = d3.min([vars.width.viz, vars.height.viz]) / 2 - vars.labels.padding * 2;
+  for (i = 0, len = pieData.length; i < len; i++) {
+    d = pieData[i];
+    item = d.data.d3plus;
+    item.d3plus.startAngle = d.startAngle;
+    item.d3plus.endAngle = d.endAngle;
+    item.d3plus.r = radius;
+    item.d3plus.x = vars.width.viz / 2;
+    item.d3plus.y = vars.height.viz / 2;
+    returnData.push(item);
+  }
+  return returnData;
+};
+
+pie.filter = dataThreshold;
+
+pie.requirements = ["data", "size"];
+
+pie.shapes = ["arc"];
+
+pie.threshold = function(vars) {
+  return (40 * 40) / (vars.width.viz * vars.height.viz);
+};
+
+module.exports = pie;
+
+
+},{"../../array/comparator.coffee":34,"../../core/data/group.coffee":58,"../../core/data/threshold.js":62,"../../core/fetch/value.coffee":68}],320:[function(require,module,exports){
+var arraySort     = require("../../array/sort.coffee"),
+    events        = require("../../client/pointer.coffee"),
+    fetchValue    = require("../../core/fetch/value.coffee"),
+    fetchColor    = require("../../core/fetch/color.coffee"),
+    legible       = require("../../color/legible.coffee"),
+    removeTooltip = require("../../tooltip/remove.coffee"),
+    smallestGap   = require("../../network/smallestGap.coffee"),
+    uniqueValues  = require("../../util/uniques.coffee")
+
+var rings = function(vars) {
+
+  var radius = d3.min([vars.height.viz,vars.width.viz])/2
+    , ring_width = vars.small || !vars.labels.value
+                 ? (radius-vars.labels.padding*2)/2 : radius/3
+    , primaryRing = vars.small || !vars.labels.value
+                  ? ring_width*1.4 : ring_width
+    , secondaryRing = ring_width*2
+    , edges = []
+    , nodes = []
+
+  var center = vars.data.viz.filter(function(d){
+    return d[vars.id.value] === vars.focus.value[0]
+  })[0]
+
+  if ( !center ) {
+    center = { "d3plus" : {} }
+    center[vars.id.value] = vars.focus.value[0]
+  }
+
+  center.d3plus.x = vars.width.viz/2
+  center.d3plus.y = vars.height.viz/2
+  center.d3plus.r = primaryRing*.65
+
+  var primaries = [], claimed = [vars.focus.value[0]]
+  vars.edges.connections(vars.focus.value[0],vars.id.value).forEach(function(edge){
+
+    var c = edge[vars.edges.source][vars.id.value] == vars.focus.value[0] ? edge[vars.edges.target] : edge[vars.edges.source]
+    var n = vars.data.viz.filter(function(d){
+      return d[vars.id.value] === c[vars.id.value]
+    })[0]
+
+    if ( !n ) {
+      n = { "d3plus" : {} }
+      n[vars.id.value] = c[vars.id.value]
+    }
+
+    n.d3plus.edges = vars.edges.connections(n[vars.id.value],vars.id.value).filter(function(c){
+      return c[vars.edges.source][vars.id.value] != vars.focus.value[0] && c[vars.edges.target][vars.id.value] != vars.focus.value[0]
+    })
+    n.d3plus.edge = edge
+    claimed.push(n[vars.id.value])
+    primaries.push(n)
+
+  })
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Sort primary nodes by children (smallest to largest) and then by sort
+  // order.
+  //--------------------------------------------------------------------------
+  var sort = vars.order.value || vars.color.value
+          || vars.size.value || vars.id.value
+
+  primaries.sort(function(a,b){
+
+    var lengthdiff = a.d3plus.edges.length - b.d3plus.edges.length
+
+    if ( lengthdiff ) {
+
+      return lengthdiff
+
+    }
+    else {
+
+      return arraySort( [a,b] , sort , vars.order.sort.value
+                              , vars.color.value || [] , vars)
+
+    }
+
+  })
+
+  if (typeof vars.edges.limit.value == "number") {
+    primaries = primaries.slice(0,vars.edges.limit.value)
+  }
+  else if (typeof vars.edges.limit.value == "function") {
+    primaries = vars.edges.limit.value(primaries)
+  }
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Check for similar children and give preference to nodes with less
+  // overall children.
+  //----------------------------------------------------------------------------
+  var secondaries = [], total = 0
+  primaries.forEach(function(p){
+
+    var primaryId = p[vars.id.value]
+
+    p.d3plus.edges = p.d3plus.edges.filter(function(c){
+
+      var source = c[vars.edges.source][vars.id.value]
+        , target = c[vars.edges.target][vars.id.value]
+      return (claimed.indexOf(source) < 0 && target == primaryId)
+          || (claimed.indexOf(target) < 0 && source == primaryId)
+
+    })
+
+    total += p.d3plus.edges.length || 1
+
+    p.d3plus.edges.forEach(function(c){
+
+      var source = c[vars.edges.source]
+        , target = c[vars.edges.target]
+      var claim = target[vars.id.value] == primaryId ? source : target
+      claimed.push(claim[vars.id.value])
+
+    })
+  })
+
+  arraySort( primaries , sort , vars.order.sort.value
+                   , vars.color.value || [] , vars)
+
+  var offset = 0,
+      radian = Math.PI*2,
+      start = 0
+
+  primaries.forEach(function(p,i){
+
+    var children = p.d3plus.edges.length || 1,
+        space = (radian/total)*children
+
+    if (i == 0) {
+      start = angle
+      offset -= space/2
+    }
+
+    var angle = offset+(space/2)
+    angle -= radian/4
+
+    p.d3plus.radians = angle
+    p.d3plus.x = vars.width.viz/2 + (primaryRing * Math.cos(angle))
+    p.d3plus.y = vars.height.viz/2 + (primaryRing * Math.sin(angle))
+
+    offset += space
+    p.d3plus.edges.sort(function(a,b){
+
+      var a = a[vars.edges.source][vars.id.value] == p[vars.id.value]
+            ? a[vars.edges.target] : a[vars.edges.source]
+        , b = b[vars.edges.source][vars.id.value] == p[vars.id.value]
+            ? b[vars.edges.target] : b[vars.edges.source]
+
+      return arraySort( [a,b] , sort , vars.order.sort.value
+                              , vars.color.value || [] , vars)
+
+    })
+
+    p.d3plus.edges.forEach(function(edge,i){
+
+      var c = edge[vars.edges.source][vars.id.value] == p[vars.id.value]
+          ? edge[vars.edges.target] : edge[vars.edges.source]
+        , s = radian/total
+
+      var d = vars.data.viz.filter(function(a){
+        return a[vars.id.value] === c[vars.id.value]
+      })[0]
+
+      if ( !d ) {
+        d = { "d3plus" : {} }
+        d[vars.id.value] = c[vars.id.value]
+      }
+
+      a = (angle-(s*children/2)+(s/2))+((s)*i)
+      d.d3plus.radians = a
+      d.d3plus.x = vars.width.viz/2 + ((secondaryRing) * Math.cos(a))
+      d.d3plus.y = vars.height.viz/2 + ((secondaryRing) * Math.sin(a))
+      secondaries.push(d)
+    })
+
+  })
+
+  var primaryDistance = smallestGap(primaries,{"accessor": function(n){
+        return [n.d3plus.x, n.d3plus.y]
+      }})
+    , secondaryDistance = smallestGap(secondaries,{"accessor": function(n){
+        return [n.d3plus.x, n.d3plus.y]
+      }})
+
+  if (!primaryDistance) {
+    primaryDistance = ring_width/2
+  }
+
+  if (!secondaryDistance) {
+    secondaryDistance = ring_width/4
+  }
+
+  if (primaryDistance/2 - 4 < 8) {
+    var primaryMax = d3.min([primaryDistance/2,8])
+  }
+  else {
+    var primaryMax = primaryDistance/2 - 4
+  }
+
+  if (secondaryDistance/2 - 4 < 4) {
+    var secondaryMax = d3.min([secondaryDistance/2,4])
+  }
+  else {
+    var secondaryMax = secondaryDistance/2 - 4
+  }
+
+  if (secondaryMax > ring_width/10) {
+    secondaryMax = ring_width/10
+  }
+
+  if (secondaryMax > primaryMax && secondaryMax > 10) {
+    secondaryMax = primaryMax*.75
+  }
+  if (primaryMax > secondaryMax*1.5) {
+    primaryMax = secondaryMax*1.5
+  }
+
+  primaryMax = Math.floor(primaryMax)
+  secondaryMax = Math.floor(secondaryMax)
+
+  var ids = uniqueValues(primaries, vars.id.value, fetchValue, vars)
+  ids = ids.concat(uniqueValues(secondaries, vars.id.value, fetchValue, vars))
+  ids.push(vars.focus.value[0])
+
+  var data = vars.data.viz.filter(function(d){
+    return ids.indexOf(d[vars.id.value]) >= 0
+  })
+
+  if (vars.size.value) {
+
+    var domain = d3.extent(data,function(d){
+      return fetchValue(vars,d,vars.size.value)
+    })
+
+    if (domain[0] == domain[1]) {
+      domain[0] = 0
+    }
+
+    var radius = d3.scale.linear()
+      .domain(domain)
+      .rangeRound([3,d3.min([primaryMax,secondaryMax])])
+
+    var val = fetchValue(vars,center,vars.size.value)
+    center.d3plus.r = radius(val)
+
+  }
+  else {
+
+    var radius = d3.scale.linear()
+      .domain([1,2])
+      .rangeRound([primaryMax,secondaryMax])
+
+
+    if (vars.edges.label) {
+      center.d3plus.r = radius(1)*1.5
+    }
+
+  }
+
+  secondaries.forEach(function(s){
+    s.d3plus.ring = 2
+    var val = vars.size.value ? fetchValue(vars,s,vars.size.value) : 2
+    s.d3plus.r = radius(val)
+  })
+
+  primaries.forEach(function(p){
+    p.d3plus.ring = 1
+    var val = vars.size.value ? fetchValue(vars,p,vars.size.value) : 1
+    p.d3plus.r = radius(val)
+  })
+
+  nodes = [center].concat(primaries).concat(secondaries)
+
+  primaries.forEach(function(p,i){
+
+    var check = [vars.edges.source,vars.edges.target]
+      , edge = p.d3plus.edge
+
+    check.forEach(function(node){
+
+      edge[node] = nodes.filter(function(n){
+        return n[vars.id.value] == edge[node][vars.id.value]
+      })[0]
+
+    })
+
+    delete edge.d3plus
+    edges.push(edge)
+
+    vars.edges.connections(p[vars.id.value],vars.id.value).forEach(function(edge){
+
+      var c = edge[vars.edges.source][vars.id.value] == p[vars.id.value]
+            ? edge[vars.edges.target] : edge[vars.edges.source]
+
+      if (c[vars.id.value] != center[vars.id.value]) {
+
+        var target = secondaries.filter(function(s){
+          return s[vars.id.value] == c[vars.id.value]
+        })[0]
+
+        if (!target) {
+          var r = primaryRing
+          target = primaries.filter(function(s){
+            return s[vars.id.value] == c[vars.id.value]
+          })[0]
+        }
+        else {
+          var r = secondaryRing
+        }
+
+        if (target) {
+
+          edge.d3plus = {
+            "spline": true,
+            "translate": {
+              "x": vars.width.viz/2,
+              "y": vars.height.viz/2
+            }
+          }
+
+          var check = [vars.edges.source,vars.edges.target]
+
+          check.forEach(function(node,i){
+
+            edge[node] = nodes.filter(function(n){
+              return n[vars.id.value] == edge[node][vars.id.value]
+            })[0]
+
+            if (edge[node].d3plus.edges === undefined) edge[node].d3plus.edges = {}
+
+            var oppID = i === 0 ? edge[vars.edges.target][vars.id.value] : edge[vars.edges.source][vars.id.value]
+
+            if (edge[node][vars.id.value] == p[vars.id.value]) {
+
+              edge[node].d3plus.edges[oppID] = {
+                "angle": p.d3plus.radians + Math.PI,
+                "radius": ring_width/2
+              }
+
+            }
+            else {
+
+              edge[node].d3plus.edges[oppID] = {
+                "angle": target.d3plus.radians,
+                "radius": ring_width/2
+              }
+
+            }
+          })
+
+          edges.push(edge)
+
+        }
+
+      }
+
+    })
+
+  })
+
+  nodes.forEach(function(n) {
+
+    if (!vars.small && vars.labels.value) {
+
+      if (n[vars.id.value] != vars.focus.value[0]) {
+
+        n.d3plus.rotate = n.d3plus.radians*(180/Math.PI)
+
+        var angle = n.d3plus.rotate,
+            width = ring_width-(vars.labels.padding*3)-n.d3plus.r
+
+        if (angle < -90 || angle > 90) {
+          angle = angle-180
+          var buffer = -(n.d3plus.r+width/2+vars.labels.padding),
+              anchor = "end"
+        }
+        else {
+          var buffer = n.d3plus.r+width/2+vars.labels.padding,
+              anchor = "start"
+        }
+
+        var background = primaries.indexOf(n) >= 0 ? true : false
+
+        var height = n.d3plus.ring == 1 ? primaryDistance : secondaryDistance
+
+        n.d3plus.label = {
+          "x": buffer,
+          "y": 0,
+          "w": width,
+          "h": height,
+          "angle": angle,
+          "anchor": anchor,
+          "valign": "center",
+          "color": legible(fetchColor(vars,n)),
+          "resize": [8, vars.labels.font.size],
+          "background": background,
+          "mouse": true
+        }
+
+      }
+      else if (vars.size.value || vars.edges.label) {
+
+        var height = primaryRing-n.d3plus.r*2-vars.labels.padding*2
+
+        n.d3plus.label = {
+          "x": 0,
+          "y": n.d3plus.r+height/2,
+          "w": primaryRing,
+          "h": height,
+          "color": legible(fetchColor(vars,n)),
+          "resize": [10,40],
+          "background": true,
+          "mouse": true
+        }
+
+      }
+      else {
+        delete n.d3plus.rotate
+        delete n.d3plus.label
+      }
+
+    }
+    else {
+      delete n.d3plus.rotate
+      delete n.d3plus.label
+    }
+
+  })
+
+  vars.mouse.viz = {};
+  vars.mouse.viz[events.click] = function(d) {
+    if (d[vars.id.value] != vars.focus.value[0]) {
+      removeTooltip(vars.type.value)
+      vars.self.focus(d[vars.id.value]).draw()
+    }
+  }
+
+  return {"edges": edges, "nodes": nodes, "data": data}
+
+};
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Visualization Settings and Helper Functions
+//------------------------------------------------------------------------------
+rings.filter       = function( vars , data ) {
+
+  var primaries = vars.edges.connections(vars.focus.value[0],vars.id.value,true)
+    , secondaries = []
+
+  primaries.forEach(function(p){
+    secondaries = secondaries.concat(vars.edges.connections(p[vars.id.value],vars.id.value,true))
+  })
+
+  var connections = primaries.concat(secondaries)
+    , ids = uniqueValues(connections, vars.id.value, fetchValue, vars)
+    , returnData = []
+
+  ids.forEach(function(id){
+
+    var d = data.filter(function(d){
+      return d[vars.id.value] == id
+    })[0]
+
+    if ( !d ) {
+      var obj = {"d3plus": {}}
+      obj[vars.id.value] = id
+      returnData.push(obj)
+    }
+    else {
+      returnData.push(d)
+    }
+
+  })
+
+  return returnData
+
+}
+rings.nesting      = false
+rings.scale        = 1
+rings.shapes       = [ "circle" , "square" , "donut" ]
+rings.requirements = [ "edges" , "focus" ]
+rings.tooltip      = "static"
+
+module.exports = rings
+
+},{"../../array/sort.coffee":36,"../../client/pointer.coffee":40,"../../color/legible.coffee":45,"../../core/fetch/color.coffee":64,"../../core/fetch/value.coffee":68,"../../network/smallestGap.coffee":167,"../../tooltip/remove.coffee":202,"../../util/uniques.coffee":209}],321:[function(require,module,exports){
+var fetchValue, graph, print, scatter, sort, ticks;
+
+fetchValue = require("../../core/fetch/value.coffee");
+
+graph = require("./helpers/graph/draw.coffee");
+
+print = require("../../core/console/print.coffee");
+
+sort = require("../../array/sort.coffee");
+
+ticks = require("./helpers/graph/dataTicks.coffee");
+
+scatter = function(vars) {
+  var d, domains, i, len, ref;
+  graph(vars, {
+    buffer: "size",
+    mouse: true
+  });
+  domains = vars.x.domain.viz.concat(vars.y.domain.viz);
+  if (domains.indexOf(void 0) >= 0) {
+    return [];
+  }
+  ref = vars.data.viz;
+  for (i = 0, len = ref.length; i < len; i++) {
+    d = ref[i];
+    d.d3plus.x = vars.x.scale.viz(fetchValue(vars, d, vars.x.value));
+    d.d3plus.x += vars.axes.margin.left;
+    d.d3plus.y = vars.y.scale.viz(fetchValue(vars, d, vars.y.value));
+    d.d3plus.y += vars.axes.margin.top;
+    if (typeof vars.size.value === "number" || !vars.size.value) {
+      d.d3plus.r = vars.axes.scale(0);
+    } else {
+      d.d3plus.r = vars.axes.scale(fetchValue(vars, d, vars.size.value));
+    }
+  }
+  ticks(vars);
+  return sort(vars.data.viz, vars.order.value || vars.size.value || vars.id.value, vars.order.sort.value === "desc" ? "asc" : "desc", vars.color.value || [], vars);
+};
+
+scatter.fill = true;
+
+scatter.requirements = ["data", "x", "y"];
+
+scatter.scale = 1.1;
+
+scatter.setup = function(vars) {
+  if (vars.time.value && !vars.axes.discrete) {
+    if (vars.time.value === vars.x.value) {
+      vars.self.x({
+        scale: "discrete"
+      });
+    }
+    if (vars.time.value === vars.y.value) {
+      return vars.self.y({
+        scale: "discrete"
+      });
+    }
+  }
+};
+
+scatter.shapes = ["circle", "square", "donut"];
+
+scatter.tooltip = "static";
+
+module.exports = scatter;
+
+
+},{"../../array/sort.coffee":36,"../../core/console/print.coffee":53,"../../core/fetch/value.coffee":68,"./helpers/graph/dataTicks.coffee":307,"./helpers/graph/draw.coffee":308}],322:[function(require,module,exports){
+var closest, fetchValue, graph, nest, sort, stack, stacked, threshold;
+
+closest = require("../../util/closest.coffee");
+
+fetchValue = require("../../core/fetch/value.coffee");
+
+graph = require("./helpers/graph/draw.coffee");
+
+nest = require("./helpers/graph/nest.coffee");
+
+sort = require("../../array/sort.coffee");
+
+stack = require("./helpers/graph/stack.coffee");
+
+threshold = require("../../core/data/threshold.js");
+
+stacked = function(vars) {
+  var d, data, discrete, domains, i, j, len, len1, opposite, point, ref;
+  graph(vars, {
+    buffer: vars.axes.opposite
+  });
+  domains = vars.x.domain.viz.concat(vars.y.domain.viz);
+  if (domains.indexOf(void 0) >= 0) {
+    return [];
+  }
+  data = sort(vars.data.viz, null, null, null, vars);
+  discrete = vars[vars.axes.discrete];
+  opposite = vars[vars.axes.opposite];
+  for (i = 0, len = data.length; i < len; i++) {
+    point = data[i];
+    if (!point.d3plus) {
+      point.d3plus = {};
+    }
+    ref = point.values;
+    for (j = 0, len1 = ref.length; j < len1; j++) {
+      d = ref[j];
+      if (!d.d3plus) {
+        d.d3plus = {};
+      }
+      d.d3plus.x = discrete.scale.viz(fetchValue(vars, d, discrete.value));
+      d.d3plus.x += vars.axes.margin.left;
+      d.d3plus.y = opposite.scale.viz(fetchValue(vars, d, opposite.value));
+      d.d3plus.y += vars.axes.margin.top;
+      if (d.d3plus.merged instanceof Array) {
+        if (!point.d3plus.merged) {
+          point.d3plus.merged = [];
+        }
+        point.d3plus.merged = point.d3plus.merged.concat(d.d3plus.merged);
+      }
+      if (d.d3plus.text && !point.d3plus.text) {
+        point.d3plus.text = d.d3plus.text;
+      }
+    }
+  }
+  return stack(vars, data);
+};
+
+stacked.filter = function(vars, data) {
+  return nest(vars, threshold(vars, data, vars[vars.axes.discrete].value));
+};
+
+stacked.requirements = ["data", "x", "y"];
+
+stacked.setup = function(vars) {
+  var axis, size, y;
+  if (!vars.axes.discrete) {
+    axis = vars.time.value === vars.y.value ? "y" : "x";
+    vars.self[axis]({
+      scale: "discrete"
+    });
+  }
+  if (!vars[vars.axes.discrete].zerofill.value) {
+    vars.self[vars.axes.discrete]({
+      zerofill: true
+    });
+  }
+  if (!vars[vars.axes.opposite].stacked.value) {
+    vars.self[vars.axes.opposite]({
+      stacked: true
+    });
+  }
+  y = vars[vars.axes.opposite];
+  size = vars.size;
+  if ((!y.value && size.value) || (size.changed && size.previous === y.value)) {
+    vars.self[vars.axes.opposite](size.value);
+  } else if ((!size.value && y.value) || (y.changed && y.previous === size.value)) {
+    vars.self.size(y.value);
+  }
+};
+
+stacked.shapes = ["area"];
+
+stacked.threshold = function(vars) {
+  return 20 / vars.height.viz;
+};
+
+stacked.tooltip = "static";
+
+module.exports = stacked;
+
+
+},{"../../array/sort.coffee":36,"../../core/data/threshold.js":62,"../../core/fetch/value.coffee":68,"../../util/closest.coffee":205,"./helpers/graph/draw.coffee":308,"./helpers/graph/nest.coffee":314,"./helpers/graph/stack.coffee":315}],323:[function(require,module,exports){
+var fetchValue = require("../../core/fetch/value.coffee");
+var uniques    = require("../../util/uniques.coffee");
+var copy       = require("../../util/copy.coffee");
+var rand_col   = require("../../color/random.coffee");
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Table
+//------------------------------------------------------------------------------
+
+var table = function(vars) {
+
+  // get unique IDs and columns
+  var ids = uniques(vars.data.viz, vars.id.value, fetchValue, vars);
+  var cols = uniques(vars.cols.value);
+
+  // if user wants to show the row labels (default behavior) add this as a col
+  if (cols.indexOf("label") < 0 && vars.cols.index.value){
+    cols.unshift("label");
+  }
+
+  // width/height are a function of number of IDs and columns
+  var item_height = vars.height.viz / (ids.length+1); // add 1 for header offset
+  var item_width = vars.width.viz / cols.length;
+
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  // Setup background
+  //----------------------------------------------------------------------------
+  vars.group.selectAll("rect").data([0]).enter()
+    .append("rect")
+    .attr("class", "background")
+    .attr("height", vars.height.viz)
+    .attr("width", vars.width.viz)
+    .style("fill", vars.color.missing)
+  // draw line separater w/ enter/update/exit
+  var lines_horiz = vars.group.selectAll("line.horiz").data(vars.data.viz);
+  lines_horiz.enter().append("line").attr("class", "horiz")
+  lines_horiz
+    .attr("x1", 0)
+    .attr("y1", function(d, row_i){ return (item_height * row_i) + item_height })
+    .attr("x2", vars.width.viz)
+    .attr("y2", function(d, row_i){ return (item_height * row_i) + item_height })
+    .style("fill", "#fff")
+    .style("stroke", "#fff")
+  lines_horiz.exit().remove()
+  // draw line separater w/ enter/update/exit
+  var lines_vert = vars.group.selectAll("line.vert").data(cols);
+  lines_vert.enter().append("line").attr("class", "vert")
+  lines_vert
+    .attr("x1", function(d, col_i){ return (item_width * col_i) + item_width })
+    .attr("y1", 0)
+    .attr("x2", function(d, col_i){ return (item_width * col_i) + item_width })
+    .attr("y2", vars.height.viz)
+    .style("fill", "#fff")
+    .style("stroke", "#fff")
+  lines_vert.exit().remove()
+
+  var ret = []
+  var colors = {}
+
+  // doing 2 things here, first we add our column headers to our ret array as
+  // items dor d3plus to draw. We also compute the color scales for each column
+  cols.forEach(function(col, col_i){
+    // add columns
+    var header = {"d3plus":{
+      "x": (item_width * col_i) + item_width/2,
+      "y": item_height/2,
+      "width": item_width,
+      "height": item_height,
+      "id": "d3p_header_"+col.toString().replace(/ /g,"_"),
+      "shape": "square",
+      "color": "#fff",
+      "text": col
+    }}
+    if(col == vars.id.value){
+      header.d3plus.color = "#fff";
+    }
+    if(col == "label"){
+      header.d3plus.label = false;
+      header.d3plus.color = "#fff";
+      header.d3plus.stroke = "#fff";
+    }
+    ret.push(header)
+
+    // set up color scales
+    if(vars.data.keys[col] == "number"){
+      var domain_extent = d3.extent(vars.data.viz, function(d){ return d[col]; })
+      if(domain_extent[0] == domain_extent[1]){
+        domain_extent = [domain_extent[0]-1, domain_extent[1]]
+      }
+      colors[col] = d3.scale.linear().domain(domain_extent).range([vars.color.missing,rand_col(col)])
+    }
+    else if(vars.data.keys[col] == "boolean"){
+      colors[col] = function(bool){
+        return bool ? rand_col(col) : vars.color.missing;
+      }
+    }
+  })
+
+  vars.data.viz.forEach(function(d, row_i){
+    // offset for column headers
+    row_i += 1;
+
+    // loop through each user defined column to create new "object" to draw
+    cols.forEach(function(col, col_i){
+
+      // need to clone data since we'll be dupliating it for each column
+      var d_clone = copy(d);
+
+      // set unique ID otherwise it'd be the same in each column
+      d_clone.d3plus.id = "d3p_"+d_clone[vars.id.value].toString().replace(/ /g,"_")+"_"+col;
+      d_clone.d3plus.x = (item_width * col_i) + item_width/2;
+      d_clone.d3plus.y = (item_height * row_i) + item_height/2;
+      d_clone.d3plus.width = item_width;
+      d_clone.d3plus.height = item_height;
+
+      if(col == "label"){
+        d_clone.d3plus.shape = "square";
+        d_clone.d3plus.color = "#fff";
+        // special case for top left corner
+        ret.push(d_clone)
+      }
+
+      // be sure that this column is actually in this data item
+      if(d3.keys(d).indexOf(col) >= 0 && col in d){
+        if(colors[col]){
+          d_clone.d3plus.color = colors[col](d_clone[col]);
+        }
+        d_clone.d3plus.text = d_clone[col];
+        if(vars.data.keys[col] == "boolean"){
+          d_clone.d3plus.label = false;
+        }
+        else if(vars.data.keys[col] == "string"){
+          d_clone.d3plus.color = vars.color.missing;
+          d_clone.d3plus.stroke = "#fff";
+          d_clone.d3plus.shape = "square";
+        }
+        ret.push(d_clone)
+      }
+    })
+
+  })
+
+  return ret
+
+};
+
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// Visualization Settings and Helper Functions
+//------------------------------------------------------------------------------
+table.shapes = ["check", "cross", "diamond", "square", "triangle", "triangle_up", "triangle_down"]
+table.requirements = ["data", "cols"]
+
+module.exports = table
+
+},{"../../color/random.coffee":48,"../../core/fetch/value.coffee":68,"../../util/copy.coffee":206,"../../util/uniques.coffee":209}],324:[function(require,module,exports){
+var dataThreshold, groupData, mergeObject, tree_map;
+
+dataThreshold = require("../../core/data/threshold.js");
+
+groupData = require("../../core/data/group.coffee");
+
+mergeObject = require("../../object/merge.coffee");
+
+tree_map = function(vars) {
+  var d, data, groupedData, i, len, returnData, root;
+  groupedData = groupData(vars, vars.data.viz);
+  data = d3.layout.treemap().mode(vars.type.mode.value).round(true).size([vars.width.viz, vars.height.viz]).children(function(d) {
+    return d.values;
+  }).padding(vars.data.padding.value).sort(function(a, b) {
+    var sizeDiff;
+    sizeDiff = a.value - b.value;
+    if (sizeDiff === 0) {
+      return a.id < b.id;
+    } else {
+      return sizeDiff;
+    }
+  }).nodes({
+    name: "root",
+    values: groupedData
+  }).filter(function(d) {
+    return !d.values && d.area;
+  });
+  if (data.length) {
+    root = data[0];
+    while (root.parent) {
+      root = root.parent;
+    }
+    returnData = [];
+    for (i = 0, len = data.length; i < len; i++) {
+      d = data[i];
+      d.d3plus.d3plus = mergeObject(d.d3plus.d3plus, {
+        x: d.x + d.dx / 2,
+        y: d.y + d.dy / 2,
+        width: d.dx,
+        height: d.dy,
+        share: d.value / root.value
+      });
+      returnData.push(d.d3plus);
+    }
+  }
+  return returnData;
+};
+
+tree_map.filter = dataThreshold;
+
+tree_map.modes = ["squarify", "slice", "dice", "slice-dice"];
+
+tree_map.requirements = ["data", "size"];
+
+tree_map.shapes = ["square"];
+
+tree_map.threshold = function(vars) {
+  return (40 * 40) / (vars.width.viz * vars.height.viz);
+};
+
+module.exports = tree_map;
+
+
+},{"../../core/data/group.coffee":58,"../../core/data/threshold.js":62,"../../object/merge.coffee":170}],325:[function(require,module,exports){
+var attach, axis, container, flash, getSteps, print, validObject;
+
+attach = require("../core/methods/attach.coffee");
+
+axis = require("./methods/helpers/axis.coffee");
+
+flash = require("./helpers/ui/message.js");
+
+getSteps = require("./helpers/drawSteps.js");
+
+print = require("../core/console/print.coffee");
+
+container = require("./helpers/container.coffee");
+
+validObject = require("../object/validate.coffee");
+
+module.exports = function() {
+  var vars;
+  vars = {
+    g: {
+      apps: {}
+    },
+    types: {
+      bar: require("./types/bar.coffee"),
+      bubbles: require("./types/bubbles.coffee"),
+      box: require("./types/box.coffee"),
+      chart: require("./types/deprecated/chart.coffee"),
+      geo_map: require("./types/geo_map.coffee"),
+      line: require("./types/line.coffee"),
+      network: require("./types/network.js"),
+      paths: require("./types/paths.coffee"),
+      pie: require("./types/pie.coffee"),
+      rings: require("./types/rings.js"),
+      scatter: require("./types/scatter.coffee"),
+      stacked: require("./types/stacked.coffee"),
+      table: require("./types/table.js"),
+      tree_map: require("./types/tree_map.coffee")
+    }
+  };
+  vars.self = function(selection) {
+    selection.each(function() {
+      var lastMessage, nextStep, runFunction, runStep, small_height, small_width, steps;
+      vars.draw.frozen = true;
+      vars.error.internal = null;
+      if (!("timing" in vars.draw)) {
+        vars.draw.timing = vars.timing.transitions;
+      }
+      if (vars.error.value) {
+        vars.draw.timing = 0;
+      }
+      if (vars.container.changed) {
+        container(vars);
+      }
+      small_width = vars.width.value <= vars.width.small;
+      small_height = vars.height.value <= vars.height.small;
+      vars.small = small_width || small_height;
+      vars.width.viz = vars.width.value;
+      vars.height.viz = vars.height.value;
+      lastMessage = false;
+      nextStep = function() {
+        if (steps.length) {
+          runStep();
+        } else {
+          if (vars.dev.value) {
+            print.groupEnd();
+            print.timeEnd("total draw time");
+            print.log("\n");
+          }
+        }
+      };
+      runFunction = function(step, name) {
+        name = name || "function";
+        if (step[name] instanceof Array) {
+          step[name].forEach(function(f) {
+            f(vars, nextStep);
+          });
+        } else {
+          if (typeof step[name] === "function") {
+            step[name](vars, nextStep);
+          }
+        }
+        if (!step.wait) {
+          nextStep();
+        }
+      };
+      runStep = function() {
+        var message, run, same, step;
+        step = steps.shift();
+        same = vars.g.message && lastMessage === step.message;
+        run = "check" in step ? step.check : true;
+        if (typeof run === "function") {
+          run = run(vars);
+        }
+        if (run) {
+          if (!same) {
+            if (vars.dev.value) {
+              if (lastMessage !== false) {
+                print.groupEnd();
+              }
+              print.group(step.message);
+            }
+            if (typeof vars.messages.value === "string") {
+              lastMessage = vars.messages.value;
+              message = vars.messages.value;
+            } else {
+              lastMessage = step.message;
+              message = vars.format.value(step.message);
+            }
+            if (vars.draw.update) {
+              flash(vars, message);
+              if (vars.error.value) {
+                runFunction(step);
+              } else {
+                setTimeout((function() {
+                  return runFunction(step);
+                }), 10);
+              }
+            } else {
+              runFunction(step);
+            }
+          } else {
+            runFunction(step);
+          }
+        } else {
+          if ("otherwise" in step) {
+            if (vars.error.value) {
+              runFunction(step, "otherwise");
+            } else {
+              setTimeout((function() {
+                return runFunction(step, "otherwise");
+              }), 10);
+            }
+          } else {
+            nextStep();
+          }
+        }
+      };
+      vars.messages.style.backup = vars.group && vars.group.attr("opacity") === "1" ? "small" : "large";
+      steps = getSteps(vars);
+      runStep();
+    });
+    return vars.self;
+  };
+  attach(vars, {
+    active: require("./methods/active.coffee"),
+    aggs: require("./methods/aggs.coffee"),
+    attrs: require("./methods/attrs.coffee"),
+    axes: require("./methods/axes.coffee"),
+    background: require("./methods/background.coffee"),
+    color: require("./methods/color.coffee"),
+    cols: require("./methods/cols.js"),
+    config: require("./methods/config.coffee"),
+    container: require("./methods/container.coffee"),
+    coords: require("./methods/coords.coffee"),
+    csv: require("./methods/csv.coffee"),
+    data: require("./methods/data.coffee"),
+    depth: require("./methods/depth.coffee"),
+    descs: require("./methods/descs.coffee"),
+    dev: require("./methods/dev.coffee"),
+    draw: require("./methods/draw.js"),
+    edges: require("./methods/edges.js"),
+    error: require("./methods/error.coffee"),
+    focus: require("./methods/focus.coffee"),
+    font: require("./methods/font.coffee"),
+    footer: require("./methods/footer.coffee"),
+    format: require("./methods/format.coffee"),
+    height: require("./methods/height.coffee"),
+    history: require("./methods/history.coffee"),
+    icon: require("./methods/icon.coffee"),
+    id: require("./methods/id.coffee"),
+    labels: require("./methods/labels.coffee"),
+    legend: require("./methods/legend.coffee"),
+    links: require("./methods/links.coffee"),
+    margin: require("./methods/margin.coffee"),
+    messages: require("./methods/messages.coffee"),
+    mouse: require("./methods/mouse.coffee"),
+    nodes: require("./methods/nodes.coffee"),
+    order: require("./methods/order.coffee"),
+    shape: require("./methods/shape.coffee"),
+    size: require("./methods/size.coffee"),
+    style: require("./methods/style.coffee"),
+    temp: require("./methods/temp.coffee"),
+    text: require("./methods/text.coffee"),
+    time: require("./methods/time.coffee"),
+    timeline: require("./methods/timeline.coffee"),
+    timing: require("./methods/timing.coffee"),
+    title: require("./methods/title.coffee"),
+    tooltip: require("./methods/tooltip.coffee"),
+    total: require("./methods/total.coffee"),
+    type: require("./methods/type.coffee"),
+    ui: require("./methods/ui.coffee"),
+    width: require("./methods/width.coffee"),
+    x: axis("x"),
+    y: axis("y"),
+    zoom: require("./methods/zoom.js")
+  });
+  return vars.self;
+};
+
+
+},{"../core/console/print.coffee":53,"../core/methods/attach.coffee":79,"../object/validate.coffee":171,"./helpers/container.coffee":210,"./helpers/drawSteps.js":211,"./helpers/ui/message.js":243,"./methods/active.coffee":252,"./methods/aggs.coffee":253,"./methods/attrs.coffee":254,"./methods/axes.coffee":255,"./methods/background.coffee":256,"./methods/color.coffee":257,"./methods/cols.js":258,"./methods/config.coffee":259,"./methods/container.coffee":260,"./methods/coords.coffee":261,"./methods/csv.coffee":262,"./methods/data.coffee":263,"./methods/depth.coffee":264,"./methods/descs.coffee":265,"./methods/dev.coffee":266,"./methods/draw.js":267,"./methods/edges.js":268,"./methods/error.coffee":269,"./methods/focus.coffee":270,"./methods/font.coffee":271,"./methods/footer.coffee":272,"./methods/format.coffee":273,"./methods/height.coffee":274,"./methods/helpers/axis.coffee":275,"./methods/history.coffee":276,"./methods/icon.coffee":277,"./methods/id.coffee":278,"./methods/labels.coffee":279,"./methods/legend.coffee":280,"./methods/links.coffee":281,"./methods/margin.coffee":282,"./methods/messages.coffee":283,"./methods/mouse.coffee":284,"./methods/nodes.coffee":285,"./methods/order.coffee":286,"./methods/shape.coffee":287,"./methods/size.coffee":288,"./methods/style.coffee":289,"./methods/temp.coffee":290,"./methods/text.coffee":291,"./methods/time.coffee":292,"./methods/timeline.coffee":293,"./methods/timing.coffee":294,"./methods/title.coffee":295,"./methods/tooltip.coffee":296,"./methods/total.coffee":297,"./methods/type.coffee":298,"./methods/ui.coffee":299,"./methods/width.coffee":300,"./methods/zoom.js":301,"./types/bar.coffee":302,"./types/box.coffee":303,"./types/bubbles.coffee":304,"./types/deprecated/chart.coffee":305,"./types/geo_map.coffee":306,"./types/line.coffee":316,"./types/network.js":317,"./types/paths.coffee":318,"./types/pie.coffee":319,"./types/rings.js":320,"./types/scatter.coffee":321,"./types/stacked.coffee":322,"./types/table.js":323,"./types/tree_map.coffee":324}]},{},[162]);