--- a/js/flotr2/spec/js/flotr2.stable.js +++ b/js/flotr2/spec/js/flotr2.stable.js @@ -1,505 +1,500 @@ /*! - * 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 - */ + * 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); + 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) + 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 - 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 - }) - } + } + + 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]) { - if (customEvents[type].condition) - fn = customHandler(element, fn, type, customEvents[type].condition, true) - type = customEvents[type].base || type - } - entry = registry.put(new RegEntry(element, type, fn, originalFn, namespaces[0] && namespaces)) - entry.handler = entry.isNative ? - nativeHandler(element, entry.handler, args) : - customHandler(element, entry.handler, type, false, args, false) - if (entry.eventSupport) - listener(entry.target, entry.eventType, entry.handler, true, entry.customType) - } - - , del = function (selector, fn, $) { - return function (e) { - var target, i, array = typeof selector === 'string' ? $(selector, this) : selector - for (target = e.target; target && target !== this; target = target.parentNode) { - for (i = array.length; i--;) { - if (array[i] === target) { - return fn.apply(target, arguments) - } - } - } - } - } - - , remove = function (element, typeSpec, fn) { - var k, m, type, namespaces, i - , rm = removeListener - , isString = typeSpec && typeof typeSpec === 'string' - - if (isString && typeSpec.indexOf(' ') > 0) { - // remove(el, 't1 t2 t3', fn) or remove(el, 't1 t2 t3') - typeSpec = typeSpec.split(' ') - for (i = typeSpec.length; i--;) - remove(element, typeSpec[i], fn) - return element - } - type = isString && typeSpec.replace(nameRegex, '') - if (type && customEvents[type]) - type = customEvents[type].type - if (!typeSpec || isString) { - // remove(el) or remove(el, t1.ns) or remove(el, .ns) or remove(el, .ns1.ns2.ns3) - if (namespaces = isString && typeSpec.replace(namespaceRegex, '')) - namespaces = namespaces.split('.') - rm(element, type, fn, namespaces) - } else if (typeof typeSpec === 'function') { - // remove(el, fn) - rm(element, null, typeSpec) - } else { - // remove(el, { t1: fn1, t2, fn2 }) - for (k in typeSpec) { - if (typeSpec.hasOwnProperty(k)) - remove(element, k, typeSpec[k]) - } - } - return element - } - - , add = function (element, events, fn, delfn, $) { - var type, types, i, args - , originalFn = fn - , isDel = fn && typeof fn === 'string' - - if (events && !fn && typeof events === 'object') { - for (type in events) { - if (events.hasOwnProperty(type)) - add.apply(this, [ element, type, events[type] ]) - } - } else { - args = arguments.length > 3 ? slice.call(arguments, 3) : [] - types = (isDel ? fn : events).split(' ') - isDel && (fn = del(events, (originalFn = delfn), $)) && (args = slice.call(args, 1)) - // special case for one() - this === ONE && (fn = once(remove, element, events, fn, originalFn)) - for (i = types.length; i--;) addListener(element, types[i], fn, originalFn, args) - } - return element - } - - , one = function () { - return add.apply(ONE, arguments) - } - - , fireListener = W3C_MODEL ? function (isNative, type, element) { - var evt = doc.createEvent(isNative ? 'HTMLEvents' : 'UIEvents') - evt[isNative ? 'initEvent' : 'initUIEvent'](type, true, true, win, 1) - element.dispatchEvent(evt) - } : function (isNative, type, element) { - element = targetElement(element, isNative) - // if not-native then we're using onpropertychange so we just increment a custom property - isNative ? element.fireEvent('on' + type, doc.createEventObject()) : element['_on' + type]++ - } - - , fire = function (element, type, args) { - var i, j, l, names, handlers - , types = type.split(' ') - - for (i = types.length; i--;) { - type = types[i].replace(nameRegex, '') - if (names = types[i].replace(namespaceRegex, '')) - names = names.split('.') - if (!names && !args && element[eventSupport]) { - fireListener(nativeEvents[type], type, element) - } else { - // non-native event, either because of a namespace, arguments or a non DOM element - // iterate over all listeners and manually 'fire' - handlers = registry.get(element, type) - args = [false].concat(args) <