html5 boiler plate
[scannr.git] / js / flotr2 / spec / js / flotr2.stable.js
blob:a/js/flotr2/spec/js/flotr2.stable.js -> blob:b/js/flotr2/spec/js/flotr2.stable.js
  /*!
  * bean.js - copyright Jacob Thornton 2011
  * https://github.com/fat/bean
  * MIT License
  * special thanks to:
  * dean edwards: http://dean.edwards.name/
  * dperini: https://github.com/dperini/nwevents
  * the entire mootools team: github.com/mootools/mootools-core
  */
  /*global module:true, define:true*/
  !function (name, context, definition) {
  if (typeof module !== 'undefined') module.exports = definition(name, context);
  else if (typeof define === 'function' && typeof define.amd === 'object') define(definition);
  else context[name] = definition(name, context);
  }('bean', this, function (name, context) {
  var win = window
  , old = context[name]
  , overOut = /over|out/
  , namespaceRegex = /[^\.]*(?=\..*)\.|.*/
  , nameRegex = /\..*/
  , addEvent = 'addEventListener'
  , attachEvent = 'attachEvent'
  , removeEvent = 'removeEventListener'
  , detachEvent = 'detachEvent'
  , doc = document || {}
  , root = doc.documentElement || {}
  , W3C_MODEL = root[addEvent]
  , eventSupport = W3C_MODEL ? addEvent : attachEvent
  , slice = Array.prototype.slice
  , mouseTypeRegex = /click|mouse|menu|drag|drop/i
  , touchTypeRegex = /^touch|^gesture/i
  , ONE = { one: 1 } // singleton for quick matching making add() do one()
   
  , nativeEvents = (function (hash, events, i) {
  for (i = 0; i < events.length; i++)
  hash[events[i]] = 1
  return hash
  })({}, (
  'click dblclick mouseup mousedown contextmenu ' + // mouse buttons
  'mousewheel DOMMouseScroll ' + // mouse wheel
  'mouseover mouseout mousemove selectstart selectend ' + // mouse movement
  'keydown keypress keyup ' + // keyboard
  'orientationchange ' + // mobile
  'focus blur change reset select submit ' + // form elements
  'load unload beforeunload resize move DOMContentLoaded readystatechange ' + // window
  'error abort scroll ' + // misc
  (W3C_MODEL ? // element.fireEvent('onXYZ'... is not forgiving if we try to fire an event
  // that doesn't actually exist, so make sure we only do these on newer browsers
  'show ' + // mouse buttons
  'input invalid ' + // form elements
  'touchstart touchmove touchend touchcancel ' + // touch
  'gesturestart gesturechange gestureend ' + // gesture
  'message readystatechange pageshow pagehide popstate ' + // window
  'hashchange offline online ' + // window
  'afterprint beforeprint ' + // printing
  'dragstart dragenter dragover dragleave drag drop dragend ' + // dnd
  'loadstart progress suspend emptied stalled loadmetadata ' + // media
  'loadeddata canplay canplaythrough playing waiting seeking ' + // media
  'seeked ended durationchange timeupdate play pause ratechange ' + // media
  'volumechange cuechange ' + // media
  'checking noupdate downloading cached updateready obsolete ' + // appcache
  '' : '')
  ).split(' ')
  )
   
  , customEvents = (function () {
  function isDescendant(parent, node) {
  while ((node = node.parentNode) !== null) {
  if (node === parent) return true
  }
  return false
  }
   
  function check(event) {
  var related = event.relatedTarget
  if (!related) return related === null
  return (related !== this && related.prefix !== 'xul' && !/document/.test(this.toString()) && !isDescendant(this, related))
  }
   
  return {
  mouseenter: { base: 'mouseover', condition: check }
  , mouseleave: { base: 'mouseout', condition: check }
  , mousewheel: { base: /Firefox/.test(navigator.userAgent) ? 'DOMMouseScroll' : 'mousewheel' }
  }
  })()
   
  , fixEvent = (function () {
  var commonProps = 'altKey attrChange attrName bubbles cancelable ctrlKey currentTarget detail eventPhase getModifierState isTrusted metaKey relatedNode relatedTarget shiftKey srcElement target timeStamp type view which'.split(' ')
  , mouseProps = commonProps.concat('button buttons clientX clientY dataTransfer fromElement offsetX offsetY pageX pageY screenX screenY toElement'.split(' '))
  , keyProps = commonProps.concat('char charCode key keyCode'.split(' '))
  , touchProps = commonProps.concat('touches targetTouches changedTouches scale rotation'.split(' '))
  , preventDefault = 'preventDefault'
  , createPreventDefault = function (event) {
  return function () {
  if (event[preventDefault])
  event[preventDefault]()
  else
  event.returnValue = false
  }
  }
  , stopPropagation = 'stopPropagation'
  , createStopPropagation = function (event) {
  return function () {
  if (event[stopPropagation])
  event[stopPropagation]()
  else
  event.cancelBubble = true
  }
  }
  , createStop = function (synEvent) {
  return function () {
  synEvent[preventDefault]()
  synEvent[stopPropagation]()
  synEvent.stopped = true
  }
  }
  , copyProps = function (event, result, props) {
  var i, p
  for (i = props.length; i--;) {
  p = props[i]
  if (!(p in result) && p in event) result[p] = event[p]
  }
  }
   
  return function (event, isNative) {
  var result = { originalEvent: event, isNative: isNative }
  if (!event)
  return result
   
  var props
  , type = event.type
  , target = event.target || event.srcElement
   
  result[preventDefault] = createPreventDefault(event)
  result[stopPropagation] = createStopPropagation(event)
  result.stop = createStop(result)
  result.target = target && target.nodeType === 3 ? target.parentNode : target
   
  if (isNative) { // we only need basic augmentation on custom events, the rest is too expensive
  if (type.indexOf('key') !== -1) {
  props = keyProps
  result.keyCode = event.which || event.keyCode
  } else if (mouseTypeRegex.test(type)) {
  props = mouseProps
  result.rightClick = event.which === 3 || event.button === 2
  result.pos = { x: 0, y: 0 }
  if (event.pageX || event.pageY) {
  result.clientX = event.pageX
  result.clientY = event.pageY
  } else if (event.clientX || event.clientY) {
  result.clientX = event.clientX + doc.body.scrollLeft + root.scrollLeft
  result.clientY = event.clientY + doc.body.scrollTop + root.scrollTop
  }
  if (overOut.test(type))
  result.relatedTarget = event.relatedTarget || event[(type === 'mouseover' ? 'from' : 'to') + 'Element']
  } else if (touchTypeRegex.test(type)) {
  props = touchProps
  }
  copyProps(event, result, props || commonProps)
  }
  return result
  }
  })()
   
  // if we're in old IE we can't do onpropertychange on doc or win so we use doc.documentElement for both
  , targetElement = function (element, isNative) {
  return !W3C_MODEL && !isNative && (element === doc || element === win) ? root : element
  }
   
  // we use one of these per listener, of any type
  , RegEntry = (function () {
  function entry(element, type, handler, original, namespaces) {
  this.element = element
  this.type = type
  this.handler = handler
  this.original = original
  this.namespaces = namespaces
  this.custom = customEvents[type]
  this.isNative = nativeEvents[type] && element[eventSupport]
  this.eventType = W3C_MODEL || this.isNative ? type : 'propertychange'
  this.customType = !W3C_MODEL && !this.isNative && type
  this.target = targetElement(element, this.isNative)
  this.eventSupport = this.target[eventSupport]
  }
   
  entry.prototype = {
  // given a list of namespaces, is our entry in any of them?
  inNamespaces: function (checkNamespaces) {
  var i, j
  if (!checkNamespaces)
  return true
  if (!this.namespaces)
  return false
  for (i = checkNamespaces.length; i--;) {
  for (j = this.namespaces.length; j--;) {
  if (checkNamespaces[i] === this.namespaces[j])
  return true
  }
  }
  return false
  }
   
  // match by element, original fn (opt), handler fn (opt)
  , matches: function (checkElement, checkOriginal, checkHandler) {
  return this.element === checkElement &&
  (!checkOriginal || this.original === checkOriginal) &&
  (!checkHandler || this.handler === checkHandler)
  }
  }
   
  return entry
  })()
   
  , registry = (function () {
  // our map stores arrays by event type, just because it's better than storing
  // everything in a single array. uses '$' as a prefix for the keys for safety
  var map = {}
   
  // generic functional search of our registry for matching listeners,
  // `fn` returns false to break out of the loop
  , forAll = function (element, type, original, handler, fn) {
  if (!type || type === '*') {
  // search the whole registry
  for (var t in map) {
  if (t.charAt(0) === '$')
  forAll(element, t.substr(1), original, handler, fn)
  }
  } else {
  var i = 0, l, list = map['$' + type], all = element === '*'
  if (!list)
  return
  for (l = list.length; i < l; i++) {
  if (all || list[i].matches(element, original, handler))
  if (!fn(list[i], list, i, type))
  return
  }
  }
  }
   
  , has = function (element, type, original) {
  // we're not using forAll here simply because it's a bit slower and this
  // needs to be fast
  var i, list = map['$' + type]
  if (list) {
  for (i = list.length; i--;) {
  if (list[i].matches(element, original, null))
  return true
  }
  }
  return false
  }
   
  , get = function (element, type, original) {
  var entries = []
  forAll(element, type, original, null, function (entry) { return entries.push(entry) })
  return entries
  }
   
  , put = function (entry) {
  (map['$' + entry.type] || (map['$' + entry.type] = [])).push(entry)
  return entry
  }
   
  , del = function (entry) {
  forAll(entry.element, entry.type, null, entry.handler, function (entry, list, i) {
  list.splice(i, 1)
  if (list.length === 0)
  delete map['$' + entry.type]
  return false
  })
  }
   
  // dump all entries, used for onunload
  , entries = function () {
  var t, entries = []
  for (t in map) {
  if (t.charAt(0) === '$')
  entries = entries.concat(map[t])
  }
  return entries
  }
   
  return { has: has, get: get, put: put, del: del, entries: entries }
  })()
   
  // add and remove listeners to DOM elements
  , listener = W3C_MODEL ? function (element, type, fn, add) {
  element[add ? addEvent : removeEvent](type, fn, false)
  } : function (element, type, fn, add, custom) {
  if (custom && add && element['_on' + custom] === null)
  element['_on' + custom] = 0
  element[add ? attachEvent : detachEvent]('on' + type, fn)
  }
   
  , nativeHandler = function (element, fn, args) {
  return function (event) {
  event = fixEvent(event || ((this.ownerDocument || this.document || this).parentWindow || win).event, true)
  return fn.apply(element, [event].concat(args))
  }
  }
   
  , customHandler = function (element, fn, type, condition, args, isNative) {
  return function (event) {
  if (condition ? condition.apply(this, arguments) : W3C_MODEL ? true : event && event.propertyName === '_on' + type || !event) {
  if (event)
  event = fixEvent(event || ((this.ownerDocument || this.document || this).parentWindow || win).event, isNative)
  fn.apply(element, event && (!args || args.length === 0) ? arguments : slice.call(arguments, event ? 0 : 1).concat(args))
  }
  }
  }
   
  , once = function (rm, element, type, fn, originalFn) {
  // wrap the handler in a handler that does a remove as well
  return function () {
  rm(element, type, originalFn)
  fn.apply(this, arguments)
  }
  }
   
  , removeListener = function (element, orgType, handler, namespaces) {
  var i, l, entry
  , type = (orgType && orgType.replace(nameRegex, ''))
  , handlers = registry.get(element, type, handler)
   
  for (i = 0, l = handlers.length; i < l; i++) {
  if (handlers[i].inNamespaces(namespaces)) {
  if ((entry = handlers[i]).eventSupport)
  listener(entry.target, entry.eventType, entry.handler, false, entry.type)
  // TODO: this is problematic, we have a registry.get() and registry.del() that
  // both do registry searches so we waste cycles doing this. Needs to be rolled into
  // a single registry.forAll(fn) that removes while finding, but the catch is that
  // we'll be splicing the arrays that we're iterating over. Needs extra tests to
  // make sure we don't screw it up. @rvagg
  registry.del(entry)
  }
  }
  }
   
  , addListener = function (element, orgType, fn, originalFn, args) {
  var entry
  , type = orgType.replace(nameRegex, '')
  , namespaces = orgType.replace(namespaceRegex, '').split('.')
   
  if (registry.has(element, type, fn))
  return element // no dupe
  if (type === 'unload')
  fn = once(removeListener, element, type, fn, originalFn) // self clean-up
  if (customEvents[type]) {</