My personal blog
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3257 lines
108 KiB

/*!
* =============================================================
* Ender: open module JavaScript framework (https://ender.no.de)
* Build: ender build jeesh reqwest
* =============================================================
*/
/*!
* Ender: open module JavaScript framework (client-lib)
* copyright Dustin Diaz & Jacob Thornton 2011-2012 (@ded @fat)
* http://ender.jit.su
* License MIT
*/
(function (context) {
// a global object for node.js module compatiblity
// ============================================
context['global'] = context
// Implements simple module system
// losely based on CommonJS Modules spec v1.1.1
// ============================================
var modules = {}
, old = context['$']
, oldEnder = context['ender']
, oldRequire = context['require']
, oldProvide = context['provide']
function require (identifier) {
// modules can be required from ender's build system, or found on the window
var module = modules['$' + identifier] || window[identifier]
if (!module) throw new Error("Ender Error: Requested module '" + identifier + "' has not been defined.")
return module
}
function provide (name, what) {
return (modules['$' + name] = what)
}
context['provide'] = provide
context['require'] = require
function aug(o, o2) {
for (var k in o2) k != 'noConflict' && k != '_VERSION' && (o[k] = o2[k])
return o
}
/**
* main Ender return object
* @constructor
* @param {Array|Node|string} s a CSS selector or DOM node(s)
* @param {Array.|Node} r a root node(s)
*/
function Ender(s, r) {
var elements
, i
this.selector = s
// string || node || nodelist || window
if (typeof s == 'undefined') {
elements = []
this.selector = ''
} else if (typeof s == 'string' || s.nodeName || (s.length && 'item' in s) || s == window) {
elements = ender._select(s, r)
} else {
elements = isFinite(s.length) ? s : [s]
}
this.length = elements.length
for (i = this.length; i--;) this[i] = elements[i]
}
/**
* @param {function(el, i, inst)} fn
* @param {Object} opt_scope
* @returns {Ender}
*/
Ender.prototype['forEach'] = function (fn, opt_scope) {
var i, l
// opt out of native forEach so we can intentionally call our own scope
// defaulting to the current item and be able to return self
for (i = 0, l = this.length; i < l; ++i) i in this && fn.call(opt_scope || this[i], this[i], i, this)
// return self for chaining
return this
}
Ender.prototype.$ = ender // handy reference to self
function ender(s, r) {
return new Ender(s, r)
}
ender['_VERSION'] = '0.4.3-dev'
ender.fn = Ender.prototype // for easy compat to jQuery plugins
ender.ender = function (o, chain) {
aug(chain ? Ender.prototype : ender, o)
}
ender._select = function (s, r) {
if (typeof s == 'string') return (r || document).querySelectorAll(s)
if (s.nodeName) return [s]
return s
}
// use callback to receive Ender's require & provide and remove them from global
ender.noConflict = function (callback) {
context['$'] = old
if (callback) {
context['provide'] = oldProvide
context['require'] = oldRequire
context['ender'] = oldEnder
if (typeof callback == 'function') callback(require, provide, this)
}
return this
}
if (typeof module !== 'undefined' && module.exports) module.exports = ender
// use subscript notation as extern for Closure compilation
context['ender'] = context['$'] = ender
}(this));
(function () {
var module = { exports: {} }, exports = module.exports;
/*!
* Reqwest! A general purpose XHR connection manager
* (c) Dustin Diaz 2012
* https://github.com/ded/reqwest
* license MIT
*/
!function (name, definition) {
if (typeof module != 'undefined') module.exports = definition()
else if (typeof define == 'function' && define.amd) define(definition)
else this[name] = definition()
}('reqwest', function () {
var win = window
, doc = document
, twoHundo = /^20\d$/
, byTag = 'getElementsByTagName'
, readyState = 'readyState'
, contentType = 'Content-Type'
, requestedWith = 'X-Requested-With'
, head = doc[byTag]('head')[0]
, uniqid = 0
, callbackPrefix = 'reqwest_' + (+new Date())
, lastValue // data stored by the most recent JSONP callback
, xmlHttpRequest = 'XMLHttpRequest'
var isArray = typeof Array.isArray == 'function' ? Array.isArray : function (a) {
return a instanceof Array
}
var defaultHeaders = {
contentType: 'application/x-www-form-urlencoded'
, requestedWith: xmlHttpRequest
, accept: {
'*': 'text/javascript, text/html, application/xml, text/xml, */*'
, xml: 'application/xml, text/xml'
, html: 'text/html'
, text: 'text/plain'
, json: 'application/json, text/javascript'
, js: 'application/javascript, text/javascript'
}
}
var xhr = win[xmlHttpRequest] ?
function () {
return new XMLHttpRequest()
} :
function () {
return new ActiveXObject('Microsoft.XMLHTTP')
}
function handleReadyState(o, success, error) {
return function () {
if (o && o[readyState] == 4) {
if (twoHundo.test(o.status)) {
success(o)
} else {
error(o)
}
}
}
}
function setHeaders(http, o) {
var headers = o.headers || {}, h
headers.Accept = headers.Accept || defaultHeaders.accept[o.type] || defaultHeaders.accept['*']
// breaks cross-origin requests with legacy browsers
if (!o.crossOrigin && !headers[requestedWith]) headers[requestedWith] = defaultHeaders.requestedWith
if (!headers[contentType]) headers[contentType] = o.contentType || defaultHeaders.contentType
for (h in headers) {
headers.hasOwnProperty(h) && http.setRequestHeader(h, headers[h])
}
}
function setCredentials(http, o) {
if (typeof o.withCredentials !== "undefined" && typeof http.withCredentials !== "undefined") {
http.withCredentials = !!o.withCredentials
}
}
function generalCallback(data) {
lastValue = data
}
function urlappend(url, s) {
return url + (/\?/.test(url) ? '&' : '?') + s
}
function handleJsonp(o, fn, err, url) {
var reqId = uniqid++
, cbkey = o.jsonpCallback || 'callback' // the 'callback' key
, cbval = o.jsonpCallbackName || reqwest.getcallbackPrefix(reqId)
// , cbval = o.jsonpCallbackName || ('reqwest_' + reqId) // the 'callback' value
, cbreg = new RegExp('((^|\\?|&)' + cbkey + ')=([^&]+)')
, match = url.match(cbreg)
, script = doc.createElement('script')
, loaded = 0
if (match) {
if (match[3] === '?') {
url = url.replace(cbreg, '$1=' + cbval) // wildcard callback func name
} else {
cbval = match[3] // provided callback func name
}
} else {
url = urlappend(url, cbkey + '=' + cbval) // no callback details, add 'em
}
win[cbval] = generalCallback
script.type = 'text/javascript'
script.src = url
script.async = true
if (typeof script.onreadystatechange !== 'undefined') {
// need this for IE due to out-of-order onreadystatechange(), binding script
// execution to an event listener gives us control over when the script
// is executed. See http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html
script.event = 'onclick'
script.htmlFor = script.id = '_reqwest_' + reqId
}
script.onload = script.onreadystatechange = function () {
if ((script[readyState] && script[readyState] !== 'complete' && script[readyState] !== 'loaded') || loaded) {
return false
}
script.onload = script.onreadystatechange = null
script.onclick && script.onclick()
// Call the user callback with the last value stored and clean up values and scripts.
o.success && o.success(lastValue)
lastValue = undefined
head.removeChild(script)
loaded = 1
}
// Add the script to the DOM head
head.appendChild(script)
}
function getRequest(o, fn, err) {
var method = (o.method || 'GET').toUpperCase()
, url = typeof o === 'string' ? o : o.url
// convert non-string objects to query-string form unless o.processData is false
, data = (o.processData !== false && o.data && typeof o.data !== 'string')
? reqwest.toQueryString(o.data)
: (o.data || null)
, http
// if we're working on a GET request and we have data then we should append
// query string to end of URL and not post data
if ((o.type == 'jsonp' || method == 'GET') && data) {
url = urlappend(url, data)
data = null
}
if (o.type == 'jsonp') return handleJsonp(o, fn, err, url)
http = xhr()
http.open(method, url, true)
setHeaders(http, o)
setCredentials(http, o)
http.onreadystatechange = handleReadyState(http, fn, err)
o.before && o.before(http)
http.send(data)
return http
}
function Reqwest(o, fn) {
this.o = o
this.fn = fn
init.apply(this, arguments)
}
function setType(url) {
var m = url.match(/\.(json|jsonp|html|xml)(\?|$)/)
return m ? m[1] : 'js'
}
function init(o, fn) {
this.url = typeof o == 'string' ? o : o.url
this.timeout = null
// whether request has been fulfilled for purpose
// of tracking the Promises
this._fulfilled = false
// success handlers
this._fulfillmentHandlers = []
// error handlers
this._errorHandlers = []
// complete (both success and fail) handlers
this._completeHandlers = []
this._erred = false
this._responseArgs = {}
var self = this
, type = o.type || setType(this.url)
fn = fn || function () {}
if (o.timeout) {
this.timeout = setTimeout(function () {
self.abort()
}, o.timeout)
}
if (o.success) {
this._fulfillmentHandlers.push(function () {
o.success.apply(o, arguments)
})
}
if (o.error) {
this._errorHandlers.push(function () {
o.error.apply(o, arguments)
})
}
if (o.complete) {
this._completeHandlers.push(function () {
o.complete.apply(o, arguments)
})
}
function complete(resp) {
o.timeout && clearTimeout(self.timeout)
self.timeout = null
while (self._completeHandlers.length > 0) {
self._completeHandlers.shift()(resp)
}
}
function success(resp) {
var r = resp.responseText
if (r) {
switch (type) {
case 'json':
try {
resp = win.JSON ? win.JSON.parse(r) : eval('(' + r + ')')
} catch (err) {
return error(resp, 'Could not parse JSON in response', err)
}
break;
case 'js':
resp = eval(r)
break;
case 'html':
resp = r
break;
case 'xml':
resp = resp.responseXML;
break;
}
}
self._responseArgs.resp = resp
self._fulfilled = true
fn(resp)
while (self._fulfillmentHandlers.length > 0) {
self._fulfillmentHandlers.shift()(resp)
}
complete(resp)
}
function error(resp, msg, t) {
self._responseArgs.resp = resp
self._responseArgs.msg = msg
self._responseArgs.t = t
self._erred = true
while (self._errorHandlers.length > 0) {
self._errorHandlers.shift()(resp, msg, t)
}
complete(resp)
}
this.request = getRequest(o, success, error)
}
Reqwest.prototype = {
abort: function () {
this.request.abort()
}
, retry: function () {
init.call(this, this.o, this.fn)
}
/**
* Small deviation from the Promises A CommonJs specification
* http://wiki.commonjs.org/wiki/Promises/A
*/
/**
* `then` will execute upon successful requests
*/
, then: function (success, fail) {
if (this._fulfilled) {
success(this._responseArgs.resp)
} else if (this._erred) {
fail(this._responseArgs.resp, this._responseArgs.msg, this._responseArgs.t)
} else {
this._fulfillmentHandlers.push(success)
this._errorHandlers.push(fail)
}
return this
}
/**
* `always` will execute whether the request succeeds or fails
*/
, always: function (fn) {
if (this._fulfilled || this._erred) {
fn(this._responseArgs.resp)
} else {
this._completeHandlers.push(fn)
}
return this
}
/**
* `fail` will execute when the request fails
*/
, fail: function (fn) {
if (this._erred) {
fn(this._responseArgs.resp, this._responseArgs.msg, this._responseArgs.t)
} else {
this._errorHandlers.push(fn)
}
return this
}
}
function reqwest(o, fn) {
return new Reqwest(o, fn)
}
// normalize newline variants according to spec -> CRLF
function normalize(s) {
return s ? s.replace(/\r?\n/g, '\r\n') : ''
}
function serial(el, cb) {
var n = el.name
, t = el.tagName.toLowerCase()
, optCb = function (o) {
// IE gives value="" even where there is no value attribute
// 'specified' ref: http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-862529273
if (o && !o.disabled)
cb(n, normalize(o.attributes.value && o.attributes.value.specified ? o.value : o.text))
}
// don't serialize elements that are disabled or without a name
if (el.disabled || !n) return;
switch (t) {
case 'input':
if (!/reset|button|image|file/i.test(el.type)) {
var ch = /checkbox/i.test(el.type)
, ra = /radio/i.test(el.type)
, val = el.value;
// WebKit gives us "" instead of "on" if a checkbox has no value, so correct it here
(!(ch || ra) || el.checked) && cb(n, normalize(ch && val === '' ? 'on' : val))
}
break;
case 'textarea':
cb(n, normalize(el.value))
break;
case 'select':
if (el.type.toLowerCase() === 'select-one') {
optCb(el.selectedIndex >= 0 ? el.options[el.selectedIndex] : null)
} else {
for (var i = 0; el.length && i < el.length; i++) {
el.options[i].selected && optCb(el.options[i])
}
}
break;
}
}
// collect up all form elements found from the passed argument elements all
// the way down to child elements; pass a '<form>' or form fields.
// called with 'this'=callback to use for serial() on each element
function eachFormElement() {
var cb = this
, e, i, j
, serializeSubtags = function (e, tags) {
for (var i = 0; i < tags.length; i++) {
var fa = e[byTag](tags[i])
for (j = 0; j < fa.length; j++) serial(fa[j], cb)
}
}
for (i = 0; i < arguments.length; i++) {
e = arguments[i]
if (/input|select|textarea/i.test(e.tagName)) serial(e, cb)
serializeSubtags(e, [ 'input', 'select', 'textarea' ])
}
}
// standard query string style serialization
function serializeQueryString() {
return reqwest.toQueryString(reqwest.serializeArray.apply(null, arguments))
}
// { 'name': 'value', ... } style serialization
function serializeHash() {
var hash = {}
eachFormElement.apply(function (name, value) {
if (name in hash) {
hash[name] && !isArray(hash[name]) && (hash[name] = [hash[name]])
hash[name].push(value)
} else hash[name] = value
}, arguments)
return hash
}
// [ { name: 'name', value: 'value' }, ... ] style serialization
reqwest.serializeArray = function () {
var arr = []
eachFormElement.apply(function (name, value) {
arr.push({name: name, value: value})
}, arguments)
return arr
}
reqwest.serialize = function () {
if (arguments.length === 0) return ''
var opt, fn
, args = Array.prototype.slice.call(arguments, 0)
opt = args.pop()
opt && opt.nodeType && args.push(opt) && (opt = null)
opt && (opt = opt.type)
if (opt == 'map') fn = serializeHash
else if (opt == 'array') fn = reqwest.serializeArray
else fn = serializeQueryString
return fn.apply(null, args)
}
reqwest.toQueryString = function (o) {
var qs = '', i
, enc = encodeURIComponent
, push = function (k, v) {
qs += enc(k) + '=' + enc(v) + '&'
}
if (isArray(o)) {
for (i = 0; o && i < o.length; i++) push(o[i].name, o[i].value)
} else {
for (var k in o) {
if (!Object.hasOwnProperty.call(o, k)) continue;
var v = o[k]
if (isArray(v)) {
for (i = 0; i < v.length; i++) push(k, v[i])
} else push(k, o[k])
}
}
// spaces should be + according to spec
return qs.replace(/&$/, '').replace(/%20/g, '+')
}
reqwest.getcallbackPrefix = function (reqId) {
return callbackPrefix
}
// jQuery and Zepto compatibility, differences can be remapped here so you can call
// .ajax.compat(options, callback)
reqwest.compat = function (o, fn) {
if (o) {
o.type && (o.method = o.type) && delete o.type
o.dataType && (o.type = o.dataType)
o.jsonpCallback && (o.jsonpCallbackName = o.jsonpCallback) && delete o.jsonpCallback
o.jsonp && (o.jsonpCallback = o.jsonp)
}
return new Reqwest(o, fn)
}
return reqwest
});
provide("reqwest", module.exports);
!function ($) {
var r = require('reqwest')
, integrate = function(method) {
return function() {
var args = Array.prototype.slice.call(arguments, 0)
, i = (this && this.length) || 0
while (i--) args.unshift(this[i])
return r[method].apply(null, args)
}
}
, s = integrate('serialize')
, sa = integrate('serializeArray')
$.ender({
ajax: r
, serialize: r.serialize
, serializeArray: r.serializeArray
, toQueryString: r.toQueryString
})
$.ender({
serialize: s
, serializeArray: sa
}, true)
}(ender);
}());
(function () {
var module = { exports: {} }, exports = module.exports;
/*!
* Bean - copyright (c) Jacob Thornton 2011-2012
* https://github.com/fat/bean
* MIT license
*/
!(function (name, context, definition) {
if (typeof module != 'undefined' && module.exports) 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]
, namespaceRegex = /[^\.]*(?=\..*)\.|.*/
, nameRegex = /\..*/
, addEvent = 'addEventListener'
, removeEvent = 'removeEventListener'
, doc = document || {}
, root = doc.documentElement || {}
, W3C_MODEL = root[addEvent]
, eventSupport = W3C_MODEL ? addEvent : 'attachEvent'
, ONE = {} // singleton for quick matching making add() do one()
, slice = Array.prototype.slice
, str2arr = function (s, d) { return s.split(d || ' ') }
, isString = function (o) { return typeof o == 'string' }
, isFunction = function (o) { return typeof o == 'function' }
// events that we consider to be 'native', anything not in this list will
// be treated as a custom event
, standardNativeEvents =
'click dblclick mouseup mousedown contextmenu ' + // mouse buttons
'mousewheel mousemultiwheel 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 ' + // window
'readystatechange message ' + // window
'error abort scroll ' // misc
// 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
, w3cNativeEvents =
'show ' + // mouse buttons
'input invalid ' + // form elements
'touchstart touchmove touchend touchcancel ' + // touch
'gesturestart gesturechange gestureend ' + // gesture
'textinput' + // TextEvent
'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
// convert to a hash for quick lookups
, nativeEvents = (function (hash, events, i) {
for (i = 0; i < events.length; i++) events[i] && (hash[events[i]] = 1)
return hash
}({}, str2arr(standardNativeEvents + (W3C_MODEL ? w3cNativeEvents : ''))))
// custom events are events that we *fake*, they are not provided natively but
// we can use native events to generate them
, customEvents = (function () {
var isAncestor = 'compareDocumentPosition' in root
? function (element, container) {
return container.compareDocumentPosition && (container.compareDocumentPosition(element) & 16) === 16
}
: 'contains' in root
? function (element, container) {
container = container.nodeType === 9 || container === window ? root : container
return container !== element && container.contains(element)
}
: function (element, container) {
while (element = element.parentNode) if (element === container) return 1
return 0
}
, check = function (event) {
var related = event.relatedTarget
return !related
? related == null
: (related !== this && related.prefix !== 'xul' && !/document/.test(this.toString())
&& !isAncestor(related, this))
}
return {
mouseenter: { base: 'mouseover', condition: check }
, mouseleave: { base: 'mouseout', condition: check }
, mousewheel: { base: /Firefox/.test(navigator.userAgent) ? 'DOMMouseScroll' : 'mousewheel' }
}
}())
// we provide a consistent Event object across browsers by taking the actual DOM
// event object and generating a new one from its properties.
, Event = (function () {
// a whitelist of properties (for different event types) tells us what to check for and copy
var commonProps = str2arr('altKey attrChange attrName bubbles cancelable ctrlKey currentTarget ' +
'detail eventPhase getModifierState isTrusted metaKey relatedNode relatedTarget shiftKey ' +
'srcElement target timeStamp type view which propertyName')
, mouseProps = commonProps.concat(str2arr('button buttons clientX clientY dataTransfer ' +
'fromElement offsetX offsetY pageX pageY screenX screenY toElement'))
, mouseWheelProps = mouseProps.concat(str2arr('wheelDelta wheelDeltaX wheelDeltaY wheelDeltaZ ' +
'axis')) // 'axis' is FF specific
, keyProps = commonProps.concat(str2arr('char charCode key keyCode keyIdentifier ' +
'keyLocation location'))
, textProps = commonProps.concat(str2arr('data'))
, touchProps = commonProps.concat(str2arr('touches targetTouches changedTouches scale rotation'))
, messageProps = commonProps.concat(str2arr('data origin source'))
, stateProps = commonProps.concat(str2arr('state'))
, overOutRegex = /over|out/
// some event types need special handling and some need special properties, do that all here
, typeFixers = [
{ // key events
reg: /key/i
, fix: function (event, newEvent) {
newEvent.keyCode = event.keyCode || event.which
return keyProps
}
}
, { // mouse events
reg: /click|mouse(?!(.*wheel|scroll))|menu|drag|drop/i
, fix: function (event, newEvent, type) {
newEvent.rightClick = event.which === 3 || event.button === 2
newEvent.pos = { x: 0, y: 0 }
if (event.pageX || event.pageY) {
newEvent.clientX = event.pageX
newEvent.clientY = event.pageY
} else if (event.clientX || event.clientY) {
newEvent.clientX = event.clientX + doc.body.scrollLeft + root.scrollLeft
newEvent.clientY = event.clientY + doc.body.scrollTop + root.scrollTop
}
if (overOutRegex.test(type)) {
newEvent.relatedTarget = event.relatedTarget
|| event[(type == 'mouseover' ? 'from' : 'to') + 'Element']
}
return mouseProps
}
}
, { // mouse wheel events
reg: /mouse.*(wheel|scroll)/i
, fix: function () { return mouseWheelProps }
}
, { // TextEvent
reg: /^text/i
, fix: function () { return textProps }
}
, { // touch and gesture events
reg: /^touch|^gesture/i
, fix: function () { return touchProps }
}
, { // message events
reg: /^message$/i
, fix: function () { return messageProps }
}
, { // popstate events
reg: /^popstate$/i
, fix: function () { return stateProps }
}
, { // everything else
reg: /.*/
, fix: function () { return commonProps }
}
]
, typeFixerMap = {} // used to map event types to fixer functions (above), a basic cache mechanism
, Event = function (event, element, isNative) {
if (!arguments.length) return
event = event || ((element.ownerDocument || element.document || element).parentWindow || win).event
this.originalEvent = event
this.isNative = isNative
this.isBean = true
if (!event) return
var type = event.type
, target = event.target || event.srcElement
, i, l, p, props, fixer
this.target = target && target.nodeType === 3 ? target.parentNode : target
if (isNative) { // we only need basic augmentation on custom events, the rest expensive & pointless
fixer = typeFixerMap[type]
if (!fixer) { // haven't encountered this event type before, map a fixer function for it
for (i = 0, l = typeFixers.length; i < l; i++) {
if (typeFixers[i].reg.test(type)) { // guaranteed to match at least one, last is .*
typeFixerMap[type] = fixer = typeFixers[i].fix
break
}
}
}
props = fixer(event, this, type)
for (i = props.length; i--;) {
if (!((p = props[i]) in this) && p in event) this[p] = event[p]
}
}
}
// preventDefault() and stopPropagation() are a consistent interface to those functions
// on the DOM, stop() is an alias for both of them together
Event.prototype.preventDefault = function () {
if (this.originalEvent.preventDefault) this.originalEvent.preventDefault()
else this.originalEvent.returnValue = false
}
Event.prototype.stopPropagation = function () {
if (this.originalEvent.stopPropagation) this.originalEvent.stopPropagation()
else this.originalEvent.cancelBubble = true
}
Event.prototype.stop = function () {
this.preventDefault()
this.stopPropagation()
this.stopped = true
}
// stopImmediatePropagation() has to be handled internally because we manage the event list for
// each element
// note that originalElement may be a Bean#Event object in some situations
Event.prototype.stopImmediatePropagation = function () {
if (this.originalEvent.stopImmediatePropagation) this.originalEvent.stopImmediatePropagation()
this.isImmediatePropagationStopped = function () { return true }
}
Event.prototype.isImmediatePropagationStopped = function () {
return this.originalEvent.isImmediatePropagationStopped && this.originalEvent.isImmediatePropagationStopped()
}
Event.prototype.clone = function (currentTarget) {
//TODO: this is ripe for optimisation, new events are *expensive*
// improving this will speed up delegated events
var ne = new Event(this, this.element, this.isNative)
ne.currentTarget = currentTarget
return ne
}
return Event
}())
// 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
}
/**
* Bean maintains an internal registry for event listeners. We don't touch elements, objects
* or functions to identify them, instead we store everything in the registry.
* Each event listener has a RegEntry object, we have one 'registry' for the whole instance.
*/
, RegEntry = (function () {
// each handler is wrapped so we can handle delegation and custom events
var wrappedHandler = function (element, fn, condition, args) {
var call = function (event, eargs) {
return fn.apply(element, args ? slice.call(eargs, event ? 0 : 1).concat(args) : eargs)
}
, findTarget = function (event, eventElement) {
return fn.__beanDel ? fn.__beanDel.ft(event.target, element) : eventElement
}
, handler = condition
? function (event) {
var target = findTarget(event, this) // deleated event
if (condition.apply(target, arguments)) {
if (event) event.currentTarget = target
return call(event, arguments)
}
}
: function (event) {
if (fn.__beanDel) event = event.clone(findTarget(event)) // delegated event, fix the fix
return call(event, arguments)
}
handler.__beanDel = fn.__beanDel
return handler
}
, RegEntry = function (element, type, handler, original, namespaces, args, root) {
var customType = customEvents[type]
, isNative
if (type == 'unload') {
// self clean-up
handler = once(removeListener, element, type, handler, original)
}
if (customType) {
if (customType.condition) {
handler = wrappedHandler(element, handler, customType.condition, args)
}
type = customType.base || type
}
this.isNative = isNative = nativeEvents[type] && !!element[eventSupport]
this.customType = !W3C_MODEL && !isNative && type
this.element = element
this.type = type
this.original = original
this.namespaces = namespaces
this.eventType = W3C_MODEL || isNative ? type : 'propertychange'
this.target = targetElement(element, isNative)
this[eventSupport] = !!this.target[eventSupport]
this.root = root
this.handler = wrappedHandler(element, handler, null, args)
}
// given a list of namespaces, is our entry in any of them?
RegEntry.prototype.inNamespaces = function (checkNamespaces) {
var i, j, c = 0
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]) c++
}
}
return checkNamespaces.length === c
}
// match by element, original fn (opt), handler fn (opt)
RegEntry.prototype.matches = function (checkElement, checkOriginal, checkHandler) {
return this.element === checkElement &&
(!checkOriginal || this.original === checkOriginal) &&
(!checkHandler || this.handler === checkHandler)
}
return RegEntry
}())
, 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 and 'r' as a special prefix for
// rootListeners so we can look them up fast
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, root, fn) {
var pfx = root ? 'r' : '$'
if (!type || type == '*') {
// search the whole registry
for (var t in map) {
if (t.charAt(0) == pfx) {
forAll(element, t.substr(1), original, handler, root, fn)
}
}
} else {
var i = 0, l, list = map[pfx + type], all = element == '*'
if (!list) return
for (l = list.length; i < l; i++) {
if ((all || list[i].matches(element, original, handler)) && !fn(list[i], list, i, type)) return
}
}
}
, has = function (element, type, original, root) {
// we're not using forAll here simply because it's a bit slower and this
// needs to be fast
var i, list = map[(root ? 'r' : '$') + type]
if (list) {
for (i = list.length; i--;) {
if (!list[i].root && list[i].matches(element, original, null)) return true
}
}
return false
}
, get = function (element, type, original, root) {
var entries = []
forAll(element, type, original, null, root, function (entry) {
return entries.push(entry)
})
return entries
}
, put = function (entry) {
var has = !entry.root && !this.has(entry.element, entry.type, null, false)
, key = (entry.root ? 'r' : '$') + entry.type
;(map[key] || (map[key] = [])).push(entry)
return has
}
, del = function (entry) {
forAll(entry.element, entry.type, null, entry.handler, entry.root, function (entry, list, i) {
list.splice(i, 1)
entry.removed = true
if (list.length === 0) delete map[(entry.root ? 'r' : '$') + 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 }
}())
// we need a selector engine for delegated events, use querySelectorAll if it exists
// but for older browsers we need Qwery, Sizzle or similar
, selectorEngine
, setSelectorEngine = function (e) {
if (!arguments.length) {
selectorEngine = doc.querySelectorAll
? function (s, r) {
return r.querySelectorAll(s)
}
: function () {
throw new Error('Bean: No selector engine installed') // eeek
}
} else {
selectorEngine = e
}
}
// we attach this listener to each DOM event that we need to listen to, only once
// per event type per DOM element
, rootListener = function (event, type) {
if (!W3C_MODEL && type && event && event.propertyName != '_on' + type) return
var listeners = registry.get(this, type || event.type, null, false)
, l = listeners.length
, i = 0
event = new Event(event, this, true)
if (type) event.type = type
// iterate through all handlers registered for this type, calling them unless they have
// been removed by a previous handler or stopImmediatePropagation() has been called
for (; i < l && !event.isImmediatePropagationStopped(); i++) {
if (!listeners[i].removed) listeners[i].handler.call(this, event)
}
}
// add and remove listeners to DOM elements
, listener = W3C_MODEL
? function (element, type, add) {
// new browsers
element[add ? addEvent : removeEvent](type, rootListener, false)
}
: function (element, type, add, custom) {
// IE8 and below, use attachEvent/detachEvent and we have to piggy-back propertychange events
// to simulate event bubbling etc.
var entry
if (add) {
registry.put(entry = new RegEntry(
element
, custom || type
, function (event) { // handler
rootListener.call(element, event, custom)
}
, rootListener
, null
, null
, true // is root
))
if (custom && element['_on' + custom] == null) element['_on' + custom] = 0
entry.target.attachEvent('on' + entry.eventType, entry.handler)
} else {
entry = registry.get(element, custom || type, rootListener, true)[0]
if (entry) {
entry.target.detachEvent('on' + entry.eventType, entry.handler)
registry.del(entry)
}
}
}
, once = function (rm, element, type, fn, originalFn) {
// wrap the handler in a handler that does a remove as well
return function () {
fn.apply(this, arguments)
rm(element, type, originalFn)
}
}
, removeListener = function (element, orgType, handler, namespaces) {
var type = orgType && orgType.replace(nameRegex, '')
, handlers = registry.get(element, type, null, false)
, removed = {}
, i, l
for (i = 0, l = handlers.length; i < l; i++) {
if ((!handler || handlers[i].original === handler) && handlers[i].inNamespaces(namespaces)) {
// 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(handlers[i])
if (!removed[handlers[i].eventType] && handlers[i][eventSupport])
removed[handlers[i].eventType] = { t: handlers[i].eventType, c: handlers[i].type }
}
}
// check each type/element for removed listeners and remove the rootListener where it's no longer needed
for (i in removed) {
if (!registry.has(element, removed[i].t, null, false)) {
// last listener of this type, remove the rootListener
listener(element, removed[i].t, false, removed[i].c)
}
}
}
// set up a delegate helper using the given selector, wrap the handler function
, delegate = function (selector, fn) {
//TODO: findTarget (therefore $) is called twice, once for match and once for
// setting e.currentTarget, fix this so it's only needed once
var findTarget = function (target, root) {
var i, array = isString(selector) ? selectorEngine(selector, root) : selector
for (; target && target !== root; target = target.parentNode) {
for (i = array.length; i--;) {
if (array[i] === target) return target
}
}
}
, handler = function (e) {
var match = findTarget(e.target, this)
if (match) fn.apply(match, arguments)
}
// __beanDel isn't pleasant but it's a private function, not exposed outside of Bean
handler.__beanDel = {
ft : findTarget // attach it here for customEvents to use too
, selector : selector
}
return handler
}
, fireListener = W3C_MODEL ? function (isNative, type, element) {
// modern browsers, do a proper dispatchEvent()
var evt = doc.createEvent(isNative ? 'HTMLEvents' : 'UIEvents')
evt[isNative ? 'initEvent' : 'initUIEvent'](type, true, true, win, 1)
element.dispatchEvent(evt)
} : function (isNative, type, element) {
// old browser use onpropertychange, just increment a custom property to trigger the event
element = targetElement(element, isNative)
isNative ? element.fireEvent('on' + type, doc.createEventObject()) : element['_on' + type]++
}
/**
* Public API: off(), on(), add(), (remove()), one(), fire(), clone()
*/
/**
* off(element[, eventType(s)[, handler ]])
*/
, off = function (element, typeSpec, fn) {
var isTypeStr = isString(typeSpec)
, k, type, namespaces, i
if (isTypeStr && typeSpec.indexOf(' ') > 0) {
// off(el, 't1 t2 t3', fn) or off(el, 't1 t2 t3')
typeSpec = str2arr(typeSpec)
for (i = typeSpec.length; i--;)
off(element, typeSpec[i], fn)
return element
}
type = isTypeStr && typeSpec.replace(nameRegex, '')
if (type && customEvents[type]) type = customEvents[type].base
if (!typeSpec || isTypeStr) {
// off(el) or off(el, t1.ns) or off(el, .ns) or off(el, .ns1.ns2.ns3)
if (namespaces = isTypeStr && typeSpec.replace(namespaceRegex, '')) namespaces = str2arr(namespaces, '.')
removeListener(element, type, fn, namespaces)
} else if (isFunction(typeSpec)) {
// off(el, fn)
removeListener(element, null, typeSpec)
} else {
// off(el, { t1: fn1, t2, fn2 })
for (k in typeSpec) {
if (typeSpec.hasOwnProperty(k)) off(element, k, typeSpec[k])
}
}
return element
}
/**
* on(element, eventType(s)[, selector], handler[, args ])
*/
, on = function(element, events, selector, fn) {
var originalFn, type, types, i, args, entry, first
//TODO: the undefined check means you can't pass an 'args' argument, fix this perhaps?
if (selector === undefined && typeof events == 'object') {
//TODO: this can't handle delegated events
for (type in events) {
if (events.hasOwnProperty(type)) {
on.call(this, element, type, events[type])
}
}
return
}
if (!isFunction(selector)) {
// delegated event
originalFn = fn
args = slice.call(arguments, 4)
fn = delegate(selector, originalFn, selectorEngine)
} else {
args = slice.call(arguments, 3)
fn = originalFn = selector
}
types = str2arr(events)
// special case for one(), wrap in a self-removing handler
if (this === ONE) {
fn = once(off, element, events, fn, originalFn)
}
for (i = types.length; i--;) {
// add new handler to the registry and check if it's the first for this element/type
first = registry.put(entry = new RegEntry(
element
, types[i].replace(nameRegex, '') // event type
, fn
, originalFn
, str2arr(types[i].replace(namespaceRegex, ''), '.') // namespaces
, args
, false // not root
))
if (entry[eventSupport] && first) {
// first event of this type on this element, add root listener
listener(element, entry.eventType, true, entry.customType)
}
}
return element
}
/**
* add(element[, selector], eventType(s), handler[, args ])
*
* Deprecated: kept (for now) for backward-compatibility
*/
, add = function (element, events, fn, delfn) {
return on.apply(
null
, !isString(fn)
? slice.call(arguments)
: [ element, fn, events, delfn ].concat(arguments.length > 3 ? slice.call(arguments, 5) : [])
)
}
/**
* one(element, eventType(s)[, selector], handler[, args ])
*/
, one = function () {
return on.apply(ONE, arguments)
}
/**
* fire(element, eventType(s)[, args ])
*
* The optional 'args' argument must be an array, if no 'args' argument is provided
* then we can use the browser's DOM event system, otherwise we trigger handlers manually
*/
, fire = function (element, type, args) {
var types = str2arr(type)
, i, j, l, names, handlers
for (i = types.length; i--;) {
type = types[i].replace(nameRegex, '')
if (names = types[i].replace(namespaceRegex, '')) names = str2arr(names, '.')
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, null, false)
args = [false].concat(args)
for (j = 0, l = handlers.length; j < l; j++) {
if (handlers[j].inNamespaces(names)) {
handlers[j].handler.apply(element, args)
}
}
}
}
return element
}
/**
* clone(dstElement, srcElement[, eventType ])
*
* TODO: perhaps for consistency we should allow the same flexibility in type specifiers?
*/
, clone = function (element, from, type) {
var handlers = registry.get(from, type, null, false)
, l = handlers.length
, i = 0
, args, beanDel
for (; i < l; i++) {
if (handlers[i].original) {
args = [ element, handlers[i].type ]
if (beanDel = handlers[i].handler.__beanDel) args.push(beanDel.selector)
args.push(handlers[i].original)
on.apply(null, args)
}
}
return element
}
, bean = {
on : on
, add : add
, one : one
, off : off
, remove : off
, clone : clone
, fire : fire
, setSelectorEngine : setSelectorEngine
, noConflict : function () {
context[name] = old
return this
}
}
// for IE, clean up on unload to avoid leaks
if (win.attachEvent) {
var cleanup = function () {
var i, entries = registry.entries()
for (i in entries) {
if (entries[i].type && entries[i].type !== 'unload') off(entries[i].element, entries[i].type)
}
win.detachEvent('onunload', cleanup)
win.CollectGarbage && win.CollectGarbage()
}
win.attachEvent('onunload', cleanup)
}
// initialize selector engine to internal default (qSA or throw Error)
setSelectorEngine()
return bean
}));
provide("bean", module.exports);
!function ($) {
var b = require('bean')
, integrate = function (method, type, method2) {
var _args = type ? [type] : []
return function () {
for (var i = 0, l = this.length; i < l; i++) {
if (!arguments.length && method == 'on' && type) method = 'fire'
b[method].apply(this, [this[i]].concat(_args, Array.prototype.slice.call(arguments, 0)))
}
return this
}
}
, add = integrate('add')
, on = integrate('on')
, one = integrate('one')
, off = integrate('off')
, fire = integrate('fire')
, clone = integrate('clone')
, hover = function (enter, leave, i) { // i for internal
for (i = this.length; i--;) {
b.on.call(this, this[i], 'mouseenter', enter)
b.on.call(this, this[i], 'mouseleave', leave)
}
return this
}
, methods = {
on : on
, addListener : on
, bind : on
, listen : on
, delegate : add // jQuery compat, same arg order as add()
, one : one
, off : off
, unbind : off
, unlisten : off
, removeListener : off
, undelegate : off
, emit : fire
, trigger : fire
, cloneEvents : clone
, hover : hover
}
, shortcuts =
('blur change click dblclick error focus focusin focusout keydown keypress '
+ 'keyup load mousedown mouseenter mouseleave mouseout mouseover mouseup '
+ 'mousemove resize scroll select submit unload').split(' ')
for (var i = shortcuts.length; i--;) {
methods[shortcuts[i]] = integrate('on', shortcuts[i])
}
b.setSelectorEngine($)
$.ender(methods, true)
}(ender);
}());
(function () {
var module = { exports: {} }, exports = module.exports;
/*!
* Bonzo: DOM Utility (c) Dustin Diaz 2012
* https://github.com/ded/bonzo
* License MIT
*/
(function (name, context, definition) {
if (typeof module != 'undefined' && module.exports) module.exports = definition()
else if (typeof context['define'] == 'function' && context['define']['amd']) define(definition)
else context[name] = definition()
})('bonzo', this, function() {
var win = window
, doc = win.document
, html = doc.documentElement
, parentNode = 'parentNode'
, specialAttributes = /^(checked|value|selected|disabled)$/i
, specialTags = /^(select|fieldset|table|tbody|tfoot|td|tr|colgroup)$/i // tags that we have trouble inserting *into*
, simpleScriptTagRe = /\s*<script +src=['"]([^'"]+)['"]>/
, table = ['<table>', '</table>', 1]
, td = ['<table><tbody><tr>', '</tr></tbody></table>', 3]
, option = ['<select>', '</select>', 1]
, noscope = ['_', '', 0, 1]
, tagMap = { // tags that we have trouble *inserting*
thead: table, tbody: table, tfoot: table, colgroup: table, caption: table
, tr: ['<table><tbody>', '</tbody></table>', 2]
, th: td , td: td
, col: ['<table><colgroup>', '</colgroup></table>', 2]
, fieldset: ['<form>', '</form>', 1]
, legend: ['<form><fieldset>', '</fieldset></form>', 2]
, option: option, optgroup: option
, script: noscope, style: noscope, link: noscope, param: noscope, base: noscope
}
, stateAttributes = /^(checked|selected|disabled)$/
, ie = /msie/i.test(navigator.userAgent)
, hasClass, addClass, removeClass
, uidMap = {}
, uuids = 0
, digit = /^-?[\d\.]+$/
, dattr = /^data-(.+)$/
, px = 'px'
, setAttribute = 'setAttribute'
, getAttribute = 'getAttribute'
, byTag = 'getElementsByTagName'
, features = function() {
var e = doc.createElement('p')
e.innerHTML = '<a href="#x">x</a><table style="float:left;"></table>'
return {
hrefExtended: e[byTag]('a')[0][getAttribute]('href') != '#x' // IE < 8
, autoTbody: e[byTag]('tbody').length !== 0 // IE < 8
, computedStyle: doc.defaultView && doc.defaultView.getComputedStyle
, cssFloat: e[byTag]('table')[0].style.styleFloat ? 'styleFloat' : 'cssFloat'
, transform: function () {
var props = ['transform', 'webkitTransform', 'MozTransform', 'OTransform', 'msTransform'], i
for (i = 0; i < props.length; i++) {
if (props[i] in e.style) return props[i]
}
}()
, classList: 'classList' in e
, opasity: function () {
return typeof doc.createElement('a').style.opacity !== 'undefined'
}()
}
}()
, trimReplace = /(^\s*|\s*$)/g
, whitespaceRegex = /\s+/
, toString = String.prototype.toString
, unitless = { lineHeight: 1, zoom: 1, zIndex: 1, opacity: 1, boxFlex: 1, WebkitBoxFlex: 1, MozBoxFlex: 1 }
, query = doc.querySelectorAll && function (selector) { return doc.querySelectorAll(selector) }
, trim = String.prototype.trim ?
function (s) {
return s.trim()
} :
function (s) {
return s.replace(trimReplace, '')
}
function isNode(node) {
return node && node.nodeName && (node.nodeType == 1 || node.nodeType == 11)
}
function normalize(node, host, clone) {
var i, l, ret
if (typeof node == 'string') return bonzo.create(node)
if (isNode(node)) node = [ node ]
if (clone) {
ret = [] // don't change original array
for (i = 0, l = node.length; i < l; i++) ret[i] = cloneNode(host, node[i])
return ret
}
return node
}
/**
* @param {string} c a class name to test
* @return {boolean}
*/
function classReg(c) {
return new RegExp("(^|\\s+)" + c + "(\\s+|$)")
}
/**
* @param {Bonzo|Array} ar
* @param {function(Object, number, (Bonzo|Array))} fn
* @param {Object=} opt_scope
* @param {boolean=} opt_rev
* @return {Bonzo|Array}
*/
function each(ar, fn, opt_scope, opt_rev) {
var ind, i = 0, l = ar.length
for (; i < l; i++) {
ind = opt_rev ? ar.length - i - 1 : i
fn.call(opt_scope || ar[ind], ar[ind], ind, ar)
}
return ar
}
/**
* @param {Bonzo|Array} ar
* @param {function(Object, number, (Bonzo|Array))} fn
* @param {Object=} opt_scope
* @return {Bonzo|Array}
*/
function deepEach(ar, fn, opt_scope) {
for (var i = 0, l = ar.length; i < l; i++) {
if (isNode(ar[i])) {
deepEach(ar[i].childNodes, fn, opt_scope)
fn.call(opt_scope || ar[i], ar[i], i, ar)
}
}
return ar
}
/**
* @param {string} s
* @return {string}
*/
function camelize(s) {
return s.replace(/-(.)/g, function (m, m1) {
return m1.toUpperCase()
})
}
/**
* @param {string} s
* @return {string}
*/
function decamelize(s) {
return s ? s.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() : s
}
/**
* @param {Element} el
* @return {*}
*/
function data(el) {
el[getAttribute]('data-node-uid') || el[setAttribute]('data-node-uid', ++uuids)
var uid = el[getAttribute]('data-node-uid')
return uidMap[uid] || (uidMap[uid] = {})
}
/**
* removes the data associated with an element
* @param {Element} el
*/
function clearData(el) {
var uid = el[getAttribute]('data-node-uid')
if (uid) delete uidMap[uid]
}
function dataValue(d) {
var f
try {
return (d === null || d === undefined) ? undefined :
d === 'true' ? true :
d === 'false' ? false :
d === 'null' ? null :
(f = parseFloat(d)) == d ? f : d;
} catch(e) {}
return undefined
}
/**
* @param {Bonzo|Array} ar
* @param {function(Object, number, (Bonzo|Array))} fn
* @param {Object=} opt_scope
* @return {boolean} whether `some`thing was found
*/
function some(ar, fn, opt_scope) {
for (var i = 0, j = ar.length; i < j; ++i) if (fn.call(opt_scope || null, ar[i], i, ar)) return true
return false
}
/**
* this could be a giant enum of CSS properties
* but in favor of file size sans-closure deadcode optimizations
* we're just asking for any ol string
* then it gets transformed into the appropriate style property for JS access
* @param {string} p
* @return {string}
*/
function styleProperty(p) {
(p == 'transform' && (p = features.transform)) ||
(/^transform-?[Oo]rigin$/.test(p) && (p = features.transform + 'Origin')) ||
(p == 'float' && (p = features.cssFloat))
return p ? camelize(p) : null
}
var getStyle = features.computedStyle ?
function (el, property) {
var value = null
, computed = doc.defaultView.getComputedStyle(el, '')
computed && (value = computed[property])
return el.style[property] || value
} :
(ie && html.currentStyle) ?
/**
* @param {Element} el
* @param {string} property
* @return {string|number}
*/
function (el, property) {
if (property == 'opacity' && !features.opasity) {
var val = 100
try {
val = el['filters']['DXImageTransform.Microsoft.Alpha'].opacity
} catch (e1) {
try {
val = el['filters']('alpha').opacity
} catch (e2) {}
}
return val / 100
}
var value = el.currentStyle ? el.currentStyle[property] : null
return el.style[property] || value
} :
function (el, property) {
return el.style[property]
}
// this insert method is intense
function insert(target, host, fn, rev) {
var i = 0, self = host || this, r = []
// target nodes could be a css selector if it's a string and a selector engine is present
// otherwise, just use target
, nodes = query && typeof target == 'string' && target.charAt(0) != '<' ? query(target) : target
// normalize each node in case it's still a string and we need to create nodes on the fly
each(normalize(nodes), function (t, j) {
each(self, function (el) {
fn(t, r[i++] = j > 0 ? cloneNode(self, el) : el)
}, null, rev)
}, this, rev)
self.length = i
each(r, function (e) {
self[--i] = e
}, null, !rev)
return self
}
/**
* sets an element to an explicit x/y position on the page
* @param {Element} el
* @param {?number} x
* @param {?number} y
*/
function xy(el, x, y) {
var $el = bonzo(el)
, style = $el.css('position')
, offset = $el.offset()
, rel = 'relative'
, isRel = style == rel
, delta = [parseInt($el.css('left'), 10), parseInt($el.css('top'), 10)]
if (style == 'static') {
$el.css('position', rel)
style = rel
}
isNaN(delta[0]) && (delta[0] = isRel ? 0 : el.offsetLeft)
isNaN(delta[1]) && (delta[1] = isRel ? 0 : el.offsetTop)
x != null && (el.style.left = x - offset.left + delta[0] + px)
y != null && (el.style.top = y - offset.top + delta[1] + px)
}
// classList support for class management
// altho to be fair, the api sucks because it won't accept multiple classes at once
if (features.classList) {
hasClass = function (el, c) {
return el.classList.contains(c)
}
addClass = function (el, c) {
el.classList.add(c)
}
removeClass = function (el, c) {
el.classList.remove(c)
}
}
else {
hasClass = function (el, c) {
return classReg(c).test(el.className)
}
addClass = function (el, c) {
el.className = trim(el.className + ' ' + c)
}
removeClass = function (el, c) {
el.className = trim(el.className.replace(classReg(c), ' '))
}
}
/**
* this allows method calling for setting values
*
* @example
* bonzo(elements).css('color', function (el) {
* return el.getAttribute('data-original-color')
* })
*
* @param {Element} el
* @param {function (Element)|string}
* @return {string}
*/
function setter(el, v) {
return typeof v == 'function' ? v(el) : v
}
/**
* @constructor
* @param {Array.<Element>|Element|Node|string} elements
*/
function Bonzo(elements) {
this.length = 0
if (elements) {
elements = typeof elements !== 'string' &&
!elements.nodeType &&
typeof elements.length !== 'undefined' ?
elements :
[elements]
this.length = elements.length
for (var i = 0; i < elements.length; i++) this[i] = elements[i]
}
}
Bonzo.prototype = {
/**
* @param {number} index
* @return {Element|Node}
*/
get: function (index) {
return this[index] || null
}
// itetators
/**
* @param {function(Element|Node)} fn
* @param {Object=} opt_scope
* @return {Bonzo}
*/
, each: function (fn, opt_scope) {
return each(this, fn, opt_scope)
}
/**
* @param {Function} fn
* @param {Object=} opt_scope
* @return {Bonzo}
*/
, deepEach: function (fn, opt_scope) {
return deepEach(this, fn, opt_scope)
}
/**
* @param {Function} fn
* @param {Function=} opt_reject
* @return {Array}
*/
, map: function (fn, opt_reject) {
var m = [], n, i
for (i = 0; i < this.length; i++) {
n = fn.call(this, this[i], i)
opt_reject ? (opt_reject(n) && m.push(n)) : m.push(n)
}
return m
}
// text and html inserters!
/**
* @param {string} h the HTML to insert
* @param {boolean=} opt_text whether to set or get text content
* @return {Bonzo|string}
*/
, html: function (h, opt_text) {
var method = opt_text
? html.textContent === undefined ? 'innerText' : 'textContent'
: 'innerHTML'
, that = this
, append = function (el, i) {
each(normalize(h, that, i), function (node) {
el.appendChild(node)
})
}
, updateElement = function (el, i) {
try {
if (opt_text || (typeof h == 'string' && !specialTags.test(el.tagName))) {
return el[method] = h
}
} catch (e) {}
append(el, i)
}
return typeof h != 'undefined'
? this.empty().each(updateElement)
: this[0] ? this[0][method] : ''
}
/**
* @param {string=} opt_text the text to set, otherwise this is a getter
* @return {Bonzo|string}
*/
, text: function (opt_text) {
return this.html(opt_text, true)
}
// more related insertion methods
/**
* @param {Bonzo|string|Element|Array} node
* @return {Bonzo}
*/
, append: function (node) {
var that = this
return this.each(function (el, i) {
each(normalize(node, that, i), function (i) {
el.appendChild(i)
})
})
}
/**
* @param {Bonzo|string|Element|Array} node
* @return {Bonzo}
*/
, prepend: function (node) {
var that = this
return this.each(function (el, i) {
var first = el.firstChild
each(normalize(node, that, i), function (i) {
el.insertBefore(i, first)
})
})
}
/**
* @param {Bonzo|string|Element|Array} target the location for which you'll insert your new content
* @param {Object=} opt_host an optional host scope (primarily used when integrated with Ender)
* @return {Bonzo}
*/
, appendTo: function (target, opt_host) {
return insert.call(this, target, opt_host, function (t, el) {
t.appendChild(el)
})
}
/**
* @param {Bonzo|string|Element|Array} target the location for which you'll insert your new content
* @param {Object=} opt_host an optional host scope (primarily used when integrated with Ender)
* @return {Bonzo}
*/
, prependTo: function (target, opt_host) {
return insert.call(this, target, opt_host, function (t, el) {
t.insertBefore(el, t.firstChild)
}, 1)
}
/**
* @param {Bonzo|string|Element|Array} node
* @return {Bonzo}
*/
, before: function (node) {
var that = this
return this.each(function (el, i) {
each(normalize(node, that, i), function (i) {
el[parentNode].insertBefore(i, el)
})
})
}
/**
* @param {Bonzo|string|Element|Array} node
* @return {Bonzo}
*/
, after: function (node) {
var that = this
return this.each(function (el, i) {
each(normalize(node, that, i), function (i) {
el[parentNode].insertBefore(i, el.nextSibling)
}, null, 1)
})
}
/**
* @param {Bonzo|string|Element|Array} target the location for which you'll insert your new content
* @param {Object=} opt_host an optional host scope (primarily used when integrated with Ender)
* @return {Bonzo}
*/
, insertBefore: function (target, opt_host) {
return insert.call(this, target, opt_host, function (t, el) {
t[parentNode].insertBefore(el, t)
})
}
/**
* @param {Bonzo|string|Element|Array} target the location for which you'll insert your new content
* @param {Object=} opt_host an optional host scope (primarily used when integrated with Ender)
* @return {Bonzo}
*/
, insertAfter: function (target, opt_host) {
return insert.call(this, target, opt_host, function (t, el) {
var sibling = t.nextSibling
sibling ?
t[parentNode].insertBefore(el, sibling) :
t[parentNode].appendChild(el)
}, 1)
}
/**
* @param {Bonzo|string|Element|Array} node
* @return {Bonzo}
*/
, replaceWith: function (node) {
bonzo(normalize(node)).insertAfter(this)
return this.remove()
}
// class management
/**
* @param {string} c
* @return {Bonzo}
*/
, addClass: function (c) {
c = toString.call(c).split(whitespaceRegex)
return this.each(function (el) {
// we `each` here so you can do $el.addClass('foo bar')
each(c, function (c) {
if (c && !hasClass(el, setter(el, c)))
addClass(el, setter(el, c))
})
})
}
/**
* @param {string} c
* @return {Bonzo}
*/
, removeClass: function (c) {
c = toString.call(c).split(whitespaceRegex)
return this.each(function (el) {
each(c, function (c) {
if (c && hasClass(el, setter(el, c)))
removeClass(el, setter(el, c))
})
})
}
/**
* @param {string} c
* @return {boolean}
*/
, hasClass: function (c) {
c = toString.call(c).split(whitespaceRegex)
return some(this, function (el) {
return some(c, function (c) {
return c && hasClass(el, c)
})
})
}
/**
* @param {string} c classname to toggle
* @param {boolean=} opt_condition whether to add or remove the class straight away
* @return {Bonzo}
*/
, toggleClass: function (c, opt_condition) {
c = toString.call(c).split(whitespaceRegex)
return this.each(function (el) {
each(c, function (c) {
if (c) {
typeof opt_condition !== 'undefined' ?
opt_condition ? addClass(el, c) : removeClass(el, c) :
hasClass(el, c) ? removeClass(el, c) : addClass(el, c)
}
})
})
}
// display togglers
/**
* @param {string=} opt_type useful to set back to anything other than an empty string
* @return {Bonzo}
*/
, show: function (opt_type) {
opt_type = typeof opt_type == 'string' ? opt_type : ''
return this.each(function (el) {
el.style.display = opt_type
})
}
/**
* @return {Bonzo}
*/
, hide: function () {
return this.each(function (el) {
el.style.display = 'none'
})
}
/**
* @param {Function=} opt_callback
* @param {string=} opt_type
* @return {Bonzo}
*/
, toggle: function (opt_callback, opt_type) {
opt_type = typeof opt_type == 'string' ? opt_type : '';
typeof opt_callback != 'function' && (opt_callback = null)
return this.each(function (el) {
el.style.display = (el.offsetWidth || el.offsetHeight) ? 'none' : opt_type;
opt_callback && opt_callback.call(el)
})
}
// DOM Walkers & getters
/**
* @return {Element|Node}
*/
, first: function () {
return bonzo(this.length ? this[0] : [])
}
/**
* @return {Element|Node}
*/
, last: function () {
return bonzo(this.length ? this[this.length - 1] : [])
}
/**
* @return {Element|Node}
*/
, next: function () {
return this.related('nextSibling')
}
/**
* @return {Element|Node}
*/
, previous: function () {
return this.related('previousSibling')
}
/**
* @return {Element|Node}
*/
, parent: function() {
return this.related(parentNode)
}
/**
* @private
* @param {string} method the directional DOM method
* @return {Element|Node}
*/
, related: function (method) {
return this.map(
function (el) {
el = el[method]
while (el && el.nodeType !== 1) {
el = el[method]
}
return el || 0
},
function (el) {
return el
}
)
}
/**
* @return {Bonzo}
*/
, focus: function () {
this.length && this[0].focus()
return this
}
/**
* @return {Bonzo}
*/
, blur: function () {
this.length && this[0].blur()
return this
}
// style getter setter & related methods
/**
* @param {Object|string} o
* @param {string=} opt_v
* @return {Bonzo|string}
*/
, css: function (o, opt_v) {
var p, iter = o
// is this a request for just getting a style?
if (opt_v === undefined && typeof o == 'string') {
// repurpose 'v'
opt_v = this[0]
if (!opt_v) return null
if (opt_v === doc || opt_v === win) {
p = (opt_v === doc) ? bonzo.doc() : bonzo.viewport()
return o == 'width' ? p.width : o == 'height' ? p.height : ''
}
return (o = styleProperty(o)) ? getStyle(opt_v, o) : null
}
if (typeof o == 'string') {
iter = {}
iter[o] = opt_v
}
if (ie && iter.opacity) {
// oh this 'ol gamut
iter.filter = 'alpha(opacity=' + (iter.opacity * 100) + ')'
// give it layout
iter.zoom = o.zoom || 1;
delete iter.opacity;
}
function fn(el, p, v) {
for (var k in iter) {
if (iter.hasOwnProperty(k)) {
v = iter[k];
// change "5" to "5px" - unless you're line-height, which is allowed
(p = styleProperty(k)) && digit.test(v) && !(p in unitless) && (v += px)
try { el.style[p] = setter(el, v) } catch(e) {}
}
}
}
return this.each(fn)
}
/**
* @param {number=} opt_x
* @param {number=} opt_y
* @return {Bonzo|number}
*/
, offset: function (opt_x, opt_y) {
if (opt_x && typeof opt_x == 'object' && (typeof opt_x.top == 'number' || typeof opt_x.left == 'number')) {
return this.each(function (el) {
xy(el, opt_x.left, opt_x.top)
})
} else if (typeof opt_x == 'number' || typeof opt_y == 'number') {
return this.each(function (el) {
xy(el, opt_x, opt_y)
})
}
if (!this[0]) return {
top: 0
, left: 0
, height: 0
, width: 0
}
var el = this[0]
, de = el.ownerDocument.documentElement
, bcr = el.getBoundingClientRect()
, scroll = getWindowScroll()
, width = el.offsetWidth
, height = el.offsetHeight
, top = bcr.top + scroll.y - Math.max(0, de && de.clientTop, doc.body.clientTop)
, left = bcr.left + scroll.x - Math.max(0, de && de.clientLeft, doc.body.clientLeft)
return {
top: top
, left: left
, height: height
, width: width
}
}
/**
* @return {number}
*/
, dim: function () {
if (!this.length) return { height: 0, width: 0 }
var el = this[0]
, de = el.nodeType == 9 && el.documentElement // document
, orig = !de && !!el.style && !el.offsetWidth && !el.offsetHeight ?
// el isn't visible, can't be measured properly, so fix that
function (t) {
var s = {
position: el.style.position || ''
, visibility: el.style.visibility || ''
, display: el.style.display || ''
}
t.first().css({
position: 'absolute'
, visibility: 'hidden'
, display: 'block'
})
return s
}(this) : null
, width = de
? Math.max(el.body.scrollWidth, el.body.offsetWidth, de.scrollWidth, de.offsetWidth, de.clientWidth)
: el.offsetWidth
, height = de
? Math.max(el.body.scrollHeight, el.body.offsetHeight, de.scrollWidth, de.offsetWidth, de.clientHeight)
: el.offsetHeight
orig && this.first().css(orig)
return {
height: height
, width: width
}
}
// attributes are hard. go shopping
/**
* @param {string} k an attribute to get or set
* @param {string=} opt_v the value to set
* @return {Bonzo|string}
*/
, attr: function (k, opt_v) {
var el = this[0]
if (typeof k != 'string' && !(k instanceof String)) {
for (var n in k) {
k.hasOwnProperty(n) && this.attr(n, k[n])
}
return this
}
return typeof opt_v == 'undefined' ?
!el ? null : specialAttributes.test(k) ?
stateAttributes.test(k) && typeof el[k] == 'string' ?
true : el[k] : (k == 'href' || k =='src') && features.hrefExtended ?
el[getAttribute](k, 2) : el[getAttribute](k) :
this.each(function (el) {
specialAttributes.test(k) ? (el[k] = setter(el, opt_v)) : el[setAttribute](k, setter(el, opt_v))
})
}
/**
* @param {string} k
* @return {Bonzo}
*/
, removeAttr: function (k) {
return this.each(function (el) {
stateAttributes.test(k) ? (el[k] = false) : el.removeAttribute(k)
})
}
/**
* @param {string=} opt_s
* @return {Bonzo|string}
*/
, val: function (s) {
return (typeof s == 'string') ?
this.attr('value', s) :
this.length ? this[0].value : null
}
// use with care and knowledge. this data() method uses data attributes on the DOM nodes
// to do this differently costs a lot more code. c'est la vie
/**
* @param {string|Object=} opt_k the key for which to get or set data
* @param {Object=} opt_v
* @return {Bonzo|Object}
*/
, data: function (opt_k, opt_v) {
var el = this[0], o, m
if (typeof opt_v === 'undefined') {
if (!el) return null
o = data(el)
if (typeof opt_k === 'undefined') {
each(el.attributes, function (a) {
(m = ('' + a.name).match(dattr)) && (o[camelize(m[1])] = dataValue(a.value))
})
return o
} else {
if (typeof o[opt_k] === 'undefined')
o[opt_k] = dataValue(this.attr('data-' + decamelize(opt_k)))
return o[opt_k]
}
} else {
return this.each(function (el) { data(el)[opt_k] = opt_v })
}
}
// DOM detachment & related
/**
* @return {Bonzo}
*/
, remove: function () {
this.deepEach(clearData)
return this.detach()
}
/**
* @return {Bonzo}
*/
, empty: function () {
return this.each(function (el) {
deepEach(el.childNodes, clearData)
while (el.firstChild) {
el.removeChild(el.firstChild)
}
})
}
/**
* @return {Bonzo}
*/
, detach: function () {
return this.each(function (el) {
el[parentNode] && el[parentNode].removeChild(el)
})
}
// who uses a mouse anyway? oh right.
/**
* @param {number} y
*/
, scrollTop: function (y) {
return scroll.call(this, null, y, 'y')
}
/**
* @param {number} x
*/
, scrollLeft: function (x) {
return scroll.call(this, x, null, 'x')
}
}
function cloneNode(host, el) {
var c = el.cloneNode(true)
, cloneElems
, elElems
// check for existence of an event cloner
// preferably https://github.com/fat/bean
// otherwise Bonzo won't do this for you
if (host.$ && typeof host.cloneEvents == 'function') {
host.$(c).cloneEvents(el)
// clone events from every child node
cloneElems = host.$(c).find('*')
elElems = host.$(el).find('*')
for (var i = 0; i < elElems.length; i++)
host.$(cloneElems[i]).cloneEvents(elElems[i])
}
return c
}
function scroll(x, y, type) {
var el = this[0]
if (!el) return this
if (x == null && y == null) {
return (isBody(el) ? getWindowScroll() : { x: el.scrollLeft, y: el.scrollTop })[type]
}
if (isBody(el)) {
win.scrollTo(x, y)
} else {
x != null && (el.scrollLeft = x)
y != null && (el.scrollTop = y)
}
return this
}
function isBody(element) {
return element === win || (/^(?:body|html)$/i).test(element.tagName)
}
function getWindowScroll() {
return { x: win.pageXOffset || html.scrollLeft, y: win.pageYOffset || html.scrollTop }
}
function createScriptFromHtml(html) {
var scriptEl = document.createElement('script')
, matches = html.match(simpleScriptTagRe)
scriptEl.src = matches[1]
return scriptEl
}
/**
* @param {Array.<Element>|Element|Node|string} els
* @return {Bonzo}
*/
function bonzo(els) {
return new Bonzo(els)
}
bonzo.setQueryEngine = function (q) {
query = q;
delete bonzo.setQueryEngine
}
bonzo.aug = function (o, target) {
// for those standalone bonzo users. this love is for you.
for (var k in o) {
o.hasOwnProperty(k) && ((target || Bonzo.prototype)[k] = o[k])
}
}
bonzo.create = function (node) {
// hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
return typeof node == 'string' && node !== '' ?
function () {
if (simpleScriptTagRe.test(node)) return [createScriptFromHtml(node)]
var tag = node.match(/^\s*<([^\s>]+)/)
, el = doc.createElement('div')
, els = []
, p = tag ? tagMap[tag[1].toLowerCase()] : null
, dep = p ? p[2] + 1 : 1
, ns = p && p[3]
, pn = parentNode
, tb = features.autoTbody && p && p[0] == '<table>' && !(/<tbody/i).test(node)
el.innerHTML = p ? (p[0] + node + p[1]) : node
while (dep--) el = el.firstChild
// for IE NoScope, we may insert cruft at the begining just to get it to work
if (ns && el && el.nodeType !== 1) el = el.nextSibling
do {
// tbody special case for IE<8, creates tbody on any empty table
// we don't want it if we're just after a <thead>, <caption>, etc.
if ((!tag || el.nodeType == 1) && (!tb || el.tagName.toLowerCase() != 'tbody')) {
els.push(el)
}
} while (el = el.nextSibling)
// IE < 9 gives us a parentNode which messes up insert() check for cloning
// `dep` > 1 can also cause problems with the insert() check (must do this last)
each(els, function(el) { el[pn] && el[pn].removeChild(el) })
return els
}() : isNode(node) ? [node.cloneNode(true)] : []
}
bonzo.doc = function () {
var vp = bonzo.viewport()
return {
width: Math.max(doc.body.scrollWidth, html.scrollWidth, vp.width)
, height: Math.max(doc.body.scrollHeight, html.scrollHeight, vp.height)
}
}
bonzo.firstChild = function (el) {
for (var c = el.childNodes, i = 0, j = (c && c.length) || 0, e; i < j; i++) {
if (c[i].nodeType === 1) e = c[j = i]
}
return e
}
bonzo.viewport = function () {
return {
width: ie ? html.clientWidth : self.innerWidth
, height: ie ? html.clientHeight : self.innerHeight
}
}
bonzo.isAncestor = 'compareDocumentPosition' in html ?
function (container, element) {
return (container.compareDocumentPosition(element) & 16) == 16
} : 'contains' in html ?
function (container, element) {
return container !== element && container.contains(element);
} :
function (container, element) {
while (element = element[parentNode]) {
if (element === container) {
return true
}
}
return false
}
return bonzo
}); // the only line we care about using a semi-colon. placed here for concatenation tools
provide("bonzo", module.exports);
(function ($) {
var b = require('bonzo')
b.setQueryEngine($)
$.ender(b)
$.ender(b(), true)
$.ender({
create: function (node) {
return $(b.create(node))
}
})
$.id = function (id) {
return $([document.getElementById(id)])
}
function indexOf(ar, val) {
for (var i = 0; i < ar.length; i++) if (ar[i] === val) return i
return -1
}
function uniq(ar) {
var r = [], i = 0, j = 0, k, item, inIt
for (; item = ar[i]; ++i) {
inIt = false
for (k = 0; k < r.length; ++k) {
if (r[k] === item) {
inIt = true; break
}
}
if (!inIt) r[j++] = item
}
return r
}
$.ender({
parents: function (selector, closest) {
if (!this.length) return this
if (!selector) selector = '*'
var collection = $(selector), j, k, p, r = []
for (j = 0, k = this.length; j < k; j++) {
p = this[j]
while (p = p.parentNode) {
if (~indexOf(collection, p)) {
r.push(p)
if (closest) break;
}
}
}
return $(uniq(r))
}
, parent: function() {
return $(uniq(b(this).parent()))
}
, closest: function (selector) {
return this.parents(selector, true)
}
, first: function () {
return $(this.length ? this[0] : this)
}
, last: function () {
return $(this.length ? this[this.length - 1] : [])
}
, next: function () {
return $(b(this).next())
}
, previous: function () {
return $(b(this).previous())
}
, appendTo: function (t) {
return b(this.selector).appendTo(t, this)
}
, prependTo: function (t) {
return b(this.selector).prependTo(t, this)
}
, insertAfter: function (t) {
return b(this.selector).insertAfter(t, this)
}
, insertBefore: function (t) {
return b(this.selector).insertBefore(t, this)
}
, siblings: function () {
var i, l, p, r = []
for (i = 0, l = this.length; i < l; i++) {
p = this[i]
while (p = p.previousSibling) p.nodeType == 1 && r.push(p)
p = this[i]
while (p = p.nextSibling) p.nodeType == 1 && r.push(p)
}
return $(r)
}
, children: function () {
var i, l, el, r = []
for (i = 0, l = this.length; i < l; i++) {
if (!(el = b.firstChild(this[i]))) continue;
r.push(el)
while (el = el.nextSibling) el.nodeType == 1 && r.push(el)
}
return $(uniq(r))
}
, height: function (v) {
return dimension.call(this, 'height', v)
}
, width: function (v) {
return dimension.call(this, 'width', v)
}
}, true)
/**
* @param {string} type either width or height
* @param {number=} opt_v becomes a setter instead of a getter
* @return {number}
*/
function dimension(type, opt_v) {
return typeof opt_v == 'undefined'
? b(this).dim()[type]
: this.css(type, opt_v)
}
}(ender));
}());
(function () {
var module = { exports: {} }, exports = module.exports;
/*!
* domready (c) Dustin Diaz 2012 - License MIT
*/
!function (name, definition) {
if (typeof module != 'undefined') module.exports = definition()
else if (typeof define == 'function' && typeof define.amd == 'object') define(definition)
else this[name] = definition()
}('domready', function (ready) {
var fns = [], fn, f = false
, doc = document
, testEl = doc.documentElement
, hack = testEl.doScroll
, domContentLoaded = 'DOMContentLoaded'
, addEventListener = 'addEventListener'
, onreadystatechange = 'onreadystatechange'
, readyState = 'readyState'
, loaded = /^loade|c/.test(doc[readyState])
function flush(f) {
loaded = 1
while (f = fns.shift()) f()
}
doc[addEventListener] && doc[addEventListener](domContentLoaded, fn = function () {
doc.removeEventListener(domContentLoaded, fn, f)
flush()
}, f)
hack && doc.attachEvent(onreadystatechange, fn = function () {
if (/^c/.test(doc[readyState])) {
doc.detachEvent(onreadystatechange, fn)
flush()
}
})
return (ready = hack ?
function (fn) {
self != top ?
loaded ? fn() : fns.push(fn) :
function () {
try {
testEl.doScroll('left')
} catch (e) {
return setTimeout(function() { ready(fn) }, 50)
}
fn()
}()
} :
function (fn) {
loaded ? fn() : fns.push(fn)
})
})
provide("domready", module.exports);
!function ($) {
var ready = require('domready')
$.ender({domReady: ready})
$.ender({
ready: function (f) {
ready(f)
return this
}
}, true)
}(ender);
}());
(function () {
var module = { exports: {} }, exports = module.exports;
/*!
* @preserve Qwery - A Blazing Fast query selector engine
* https://github.com/ded/qwery
* copyright Dustin Diaz 2012
* MIT License
*/
(function (name, context, definition) {
if (typeof module != 'undefined' && module.exports) module.exports = definition()
else if (typeof context['define'] == 'function' && context['define']['amd']) define(definition)
else context[name] = definition()
})('qwery', this, function () {
var doc = document
, html = doc.documentElement
, byClass = 'getElementsByClassName'
, byTag = 'getElementsByTagName'
, qSA = 'querySelectorAll'
, useNativeQSA = 'useNativeQSA'
, tagName = 'tagName'
, nodeType = 'nodeType'
, select // main select() method, assign later
, id = /#([\w\-]+)/
, clas = /\.[\w\-]+/g
, idOnly = /^#([\w\-]+)$/
, classOnly = /^\.([\w\-]+)$/
, tagOnly = /^([\w\-]+)$/
, tagAndOrClass = /^([\w]+)?\.([\w\-]+)$/
, splittable = /(^|,)\s*[>~+]/
, normalizr = /^\s+|\s*([,\s\+\~>]|$)\s*/g
, splitters = /[\s\>\+\~]/
, splittersMore = /(?![\s\w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^'"]*\]|[\s\w\+\-]*\))/
, specialChars = /([.*+?\^=!:${}()|\[\]\/\\])/g
, simple = /^(\*|[a-z0-9]+)?(?:([\.\#]+[\w\-\.#]+)?)/
, attr = /\[([\w\-]+)(?:([\|\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/
, pseudo = /:([\w\-]+)(\(['"]?([^()]+)['"]?\))?/
, easy = new RegExp(idOnly.source + '|' + tagOnly.source + '|' + classOnly.source)
, dividers = new RegExp('(' + splitters.source + ')' + splittersMore.source, 'g')
, tokenizr = new RegExp(splitters.source + splittersMore.source)
, chunker = new RegExp(simple.source + '(' + attr.source + ')?' + '(' + pseudo.source + ')?')
var walker = {
' ': function (node) {
return node && node !== html && node.parentNode
}
, '>': function (node, contestant) {
return node && node.parentNode == contestant.parentNode && node.parentNode
}
, '~': function (node) {
return node && node.previousSibling
}
, '+': function (node, contestant, p1, p2) {
if (!node) return false
return (p1 = previous(node)) && (p2 = previous(contestant)) && p1 == p2 && p1
}
}
function cache() {
this.c = {}
}
cache.prototype = {
g: function (k) {
return this.c[k] || undefined
}
, s: function (k, v, r) {
v = r ? new RegExp(v) : v
return (this.c[k] = v)
}
}
var classCache = new cache()
, cleanCache = new cache()
, attrCache = new cache()
, tokenCache = new cache()
function classRegex(c) {
return classCache.g(c) || classCache.s(c, '(^|\\s+)' + c + '(\\s+|$)', 1)
}
// not quite as fast as inline loops in older browsers so don't use liberally
function each(a, fn) {
var i = 0, l = a.length
for (; i < l; i++) fn(a[i])
}
function flatten(ar) {
for (var r = [], i = 0, l = ar.length; i < l; ++i) arrayLike(ar[i]) ? (r = r.concat(ar[i])) : (r[r.length] = ar[i])
return r
}
function arrayify(ar) {
var i = 0, l = ar.length, r = []
for (; i < l; i++) r[i] = ar[i]
return r
}
function previous(n) {
while (n = n.previousSibling) if (n[nodeType] == 1) break;
return n
}
function q(query) {
return query.match(chunker)
}
// called using `this` as element and arguments from regex group results.
// given => div.hello[title="world"]:foo('bar')
// div.hello[title="world"]:foo('bar'), div, .hello, [title="world"], title, =, world, :foo('bar'), foo, ('bar'), bar]
function interpret(whole, tag, idsAndClasses, wholeAttribute, attribute, qualifier, value, wholePseudo, pseudo, wholePseudoVal, pseudoVal) {
var i, m, k, o, classes
if (this[nodeType] !== 1) return false
if (tag && tag !== '*' && this[tagName] && this[tagName].toLowerCase() !== tag) return false
if (idsAndClasses && (m = idsAndClasses.match(id)) && m[1] !== this.id) return false
if (idsAndClasses && (classes = idsAndClasses.match(clas))) {
for (i = classes.length; i--;) if (!classRegex(classes[i].slice(1)).test(this.className)) return false
}
if (pseudo && qwery.pseudos[pseudo] && !qwery.pseudos[pseudo](this, pseudoVal)) return false
if (wholeAttribute && !value) { // select is just for existance of attrib
o = this.attributes
for (k in o) {
if (Object.prototype.hasOwnProperty.call(o, k) && (o[k].name || k) == attribute) {
return this
}
}
}
if (wholeAttribute && !checkAttr(qualifier, getAttr(this, attribute) || '', value)) {
// select is for attrib equality
return false
}
return this
}
function clean(s) {
return cleanCache.g(s) || cleanCache.s(s, s.replace(specialChars, '\\$1'))
}
function checkAttr(qualify, actual, val) {
switch (qualify) {
case '=':
return actual == val
case '^=':
return actual.match(attrCache.g('^=' + val) || attrCache.s('^=' + val, '^' + clean(val), 1))
case '$=':
return actual.match(attrCache.g('$=' + val) || attrCache.s('$=' + val, clean(val) + '$', 1))
case '*=':
return actual.match(attrCache.g(val) || attrCache.s(val, clean(val), 1))
case '~=':
return actual.match(attrCache.g('~=' + val) || attrCache.s('~=' + val, '(?:^|\\s+)' + clean(val) + '(?:\\s+|$)', 1))
case '|=':
return actual.match(attrCache.g('|=' + val) || attrCache.s('|=' + val, '^' + clean(val) + '(-|$)', 1))
}
return 0
}
// given a selector, first check for simple cases then collect all base candidate matches and filter
function _qwery(selector, _root) {
var r = [], ret = [], i, l, m, token, tag, els, intr, item, root = _root
, tokens = tokenCache.g(selector) || tokenCache.s(selector, selector.split(tokenizr))
, dividedTokens = selector.match(dividers)
if (!tokens.length) return r
token = (tokens = tokens.slice(0)).pop() // copy cached tokens, take the last one
if (tokens.length && (m = tokens[tokens.length - 1].match(idOnly))) root = byId(_root, m[1])
if (!root) return r
intr = q(token)
// collect base candidates to filter
els = root !== _root && root[nodeType] !== 9 && dividedTokens && /^[+~]$/.test(dividedTokens[dividedTokens.length - 1]) ?
function (r) {
while (root = root.nextSibling) {
root[nodeType] == 1 && (intr[1] ? intr[1] == root[tagName].toLowerCase() : 1) && (r[r.length] = root)
}
return r
}([]) :
root[byTag](intr[1] || '*')
// filter elements according to the right-most part of the selector
for (i = 0, l = els.length; i < l; i++) {
if (item = interpret.apply(els[i], intr)) r[r.length] = item
}
if (!tokens.length) return r
// filter further according to the rest of the selector (the left side)
each(r, function (e) { if (ancestorMatch(e, tokens, dividedTokens)) ret[ret.length] = e })
return ret
}
// compare element to a selector
function is(el, selector, root) {
if (isNode(selector)) return el == selector
if (arrayLike(selector)) return !!~flatten(selector).indexOf(el) // if selector is an array, is el a member?
var selectors = selector.split(','), tokens, dividedTokens
while (selector = selectors.pop()) {
tokens = tokenCache.g(selector) || tokenCache.s(selector, selector.split(tokenizr))
dividedTokens = selector.match(dividers)
tokens = tokens.slice(0) // copy array
if (interpret.apply(el, q(tokens.pop())) && (!tokens.length || ancestorMatch(el, tokens, dividedTokens, root))) {
return true
}
}
return false
}
// given elements matching the right-most part of a selector, filter out any that don't match the rest
function ancestorMatch(el, tokens, dividedTokens, root) {
var cand
// recursively work backwards through the tokens and up the dom, covering all options
function crawl(e, i, p) {
while (p = walker[dividedTokens[i]](p, e)) {
if (isNode(p) && (interpret.apply(p, q(tokens[i])))) {
if (i) {
if (cand = crawl(p, i - 1, p)) return cand
} else return p
}
}
}
return (cand = crawl(el, tokens.length - 1, el)) && (!root || isAncestor(cand, root))
}
function isNode(el, t) {
return el && typeof el === 'object' && (t = el[nodeType]) && (t == 1 || t == 9)
}
function uniq(ar) {
var a = [], i, j;
o:
for (i = 0; i < ar.length; ++i) {
for (j = 0; j < a.length; ++j) if (a[j] == ar[i]) continue o
a[a.length] = ar[i]
}
return a
}
function arrayLike(o) {
return (typeof o === 'object' && isFinite(o.length))
}
function normalizeRoot(root) {
if (!root) return doc
if (typeof root == 'string') return qwery(root)[0]
if (!root[nodeType] && arrayLike(root)) return root[0]
return root
}
function byId(root, id, el) {
// if doc, query on it, else query the parent doc or if a detached fragment rewrite the query and run on the fragment
return root[nodeType] === 9 ? root.getElementById(id) :
root.ownerDocument &&
(((el = root.ownerDocument.getElementById(id)) && isAncestor(el, root) && el) ||
(!isAncestor(root, root.ownerDocument) && select('[id="' + id + '"]', root)[0]))
}
function qwery(selector, _root) {
var m, el, root = normalizeRoot(_root)
// easy, fast cases that we can dispatch with simple DOM calls
if (!root || !selector) return []
if (selector === window || isNode(selector)) {
return !_root || (selector !== window && isNode(root) && isAncestor(selector, root)) ? [selector] : []
}
if (selector && arrayLike(selector)) return flatten(selector)
if (m = selector.match(easy)) {
if (m[1]) return (el = byId(root, m[1])) ? [el] : []
if (m[2]) return arrayify(root[byTag](m[2]))
if (hasByClass && m[3]) return arrayify(root[byClass](m[3]))
}
return select(selector, root)
}
// where the root is not document and a relationship selector is first we have to
// do some awkward adjustments to get it to work, even with qSA
function collectSelector(root, collector) {
return function (s) {
var oid, nid
if (splittable.test(s)) {
if (root[nodeType] !== 9) {
// make sure the el has an id, rewrite the query, set root to doc and run it
if (!(nid = oid = root.getAttribute('id'))) root.setAttribute('id', nid = '__qwerymeupscotty')
s = '[id="' + nid + '"]' + s // avoid byId and allow us to match context element
collector(root.parentNode || root, s, true)
oid || root.removeAttribute('id')
}
return;
}
s.length && collector(root, s, false)
}
}
var isAncestor = 'compareDocumentPosition' in html ?
function (element, container) {
return (container.compareDocumentPosition(element) & 16) == 16
} : 'contains' in html ?
function (element, container) {
container = container[nodeType] === 9 || container == window ? html : container
return container !== element && container.contains(element)
} :
function (element, container) {
while (element = element.parentNode) if (element === container) return 1
return 0
}
, getAttr = function () {
// detect buggy IE src/href getAttribute() call
var e = doc.createElement('p')
return ((e.innerHTML = '<a href="#x">x</a>') && e.firstChild.getAttribute('href') != '#x') ?
function (e, a) {
return a === 'class' ? e.className : (a === 'href' || a === 'src') ?
e.getAttribute(a, 2) : e.getAttribute(a)
} :
function (e, a) { return e.getAttribute(a) }
}()
, hasByClass = !!doc[byClass]
// has native qSA support
, hasQSA = doc.querySelector && doc[qSA]
// use native qSA
, selectQSA = function (selector, root) {
var result = [], ss, e
try {
if (root[nodeType] === 9 || !splittable.test(selector)) {
// most work is done right here, defer to qSA
return arrayify(root[qSA](selector))
}
// special case where we need the services of `collectSelector()`
each(ss = selector.split(','), collectSelector(root, function (ctx, s) {
e = ctx[qSA](s)
if (e.length == 1) result[result.length] = e.item(0)
else if (e.length) result = result.concat(arrayify(e))
}))
return ss.length > 1 && result.length > 1 ? uniq(result) : result
} catch (ex) { }
return selectNonNative(selector, root)
}
// no native selector support
, selectNonNative = function (selector, root) {
var result = [], items, m, i, l, r, ss
selector = selector.replace(normalizr, '$1')
if (m = selector.match(tagAndOrClass)) {
r = classRegex(m[2])
items = root[byTag](m[1] || '*')
for (i = 0, l = items.length; i < l; i++) {
if (r.test(items[i].className)) result[result.length] = items[i]
}
return result
}
// more complex selector, get `_qwery()` to do the work for us
each(ss = selector.split(','), collectSelector(root, function (ctx, s, rewrite) {
r = _qwery(s, ctx)
for (i = 0, l = r.length; i < l; i++) {
if (ctx[nodeType] === 9 || rewrite || isAncestor(r[i], root)) result[result.length] = r[i]
}
}))
return ss.length > 1 && result.length > 1 ? uniq(result) : result
}
, configure = function (options) {
// configNativeQSA: use fully-internal selector or native qSA where present
if (typeof options[useNativeQSA] !== 'undefined')
select = !options[useNativeQSA] ? selectNonNative : hasQSA ? selectQSA : selectNonNative
}
configure({ useNativeQSA: true })
qwery.configure = configure
qwery.uniq = uniq
qwery.is = is
qwery.pseudos = {}
return qwery
});
provide("qwery", module.exports);
(function ($) {
var q = function () {
var r
try {
r = require('qwery')
} catch (ex) {
r = require('qwery-mobile')
} finally {
return r
}
}()
$.pseudos = q.pseudos
$._select = function (s, r) {
// detect if sibling module 'bonzo' is available at run-time
// rather than load-time since technically it's not a dependency and
// can be loaded in any order
// hence the lazy function re-definition
return ($._select = (function () {
var b
if (typeof $.create == 'function') return function (s, r) {
return /^\s*</.test(s) ? $.create(s, r) : q(s, r)
}
try {
b = require('bonzo')
return function (s, r) {
return /^\s*</.test(s) ? b.create(s, r) : q(s, r)
}
} catch (e) { }
return q
})())(s, r)
}
$.ender({
find: function (s) {
var r = [], i, l, j, k, els
for (i = 0, l = this.length; i < l; i++) {
els = q(s, this[i])
for (j = 0, k = els.length; j < k; j++) r.push(els[j])
}
return $(q.uniq(r))
}
, and: function (s) {
var plus = $(s)
for (var i = this.length, j = 0, l = this.length + plus.length; i < l; i++, j++) {
this[i] = plus[j]
}
this.length += plus.length
return this
}
, is: function(s, r) {
var i, l
for (i = 0, l = this.length; i < l; i++) {
if (q.is(this[i], s, r)) {
return true
}
}
return false
}
}, true)
}(ender));
}());