Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

traversty

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

traversty - npm Package Compare versions

Comparing version
0.0.7
to
1.0.0
+30
.jshintrc
{
"predef": [ "assert", "refute", "define" ]
, "boss": true
, "bitwise": false
, "shadow": true
, "trailing": true
, "immed": true
, "latedef": true
, "forin": false
, "curly": false
, "debug": true
, "devel": false
, "evil": true
, "regexp": false
, "undef": true
, "sub": true
, "white": false
, "trailing": true
, "asi": true
, "laxbreak": true
, "eqnull": true
, "browser": true
, "node": true
, "laxcomma": true
, "proto": true
, "expr": true
, "es5": true
, "strict": false
, "onevar": true
}
/*global ender:true*/
(function ($) {
var t = require('traversty')
, integrated = false
, integrate = function (meth) {
// this crazyness is for lazy initialisation because we can't be guaranteed
// that a selector engine has been installed *before* traversty in an ender build
var fn = function (self, selector, index) {
if (!integrated) {
try {
t.setSelectorEngine($)
} catch (ex) { } // ignore exception, we may have an ender build with no selector engine
integrated = true
}
fn = meth == 'is'
? function (self, slfn) {
return t(self)[meth](slfn) // boolean
}
: function (self, selector, index) {
return $(t(self)[meth](selector, index)) // collection
}
return fn(self, selector, index)
}
return function (selector, index) { return fn(this, selector, index) }
}
, methods = 'up down next previous prev parents closest siblings children first last eq slice filter not is has'.split(' ')
, b = {}, i = methods.length
// does this build have an .is()? if so, shift it to _is() for traversty to use and
// allow us to integrate a new is(), wrapped around it
if ($.fn.is) $.fn._is = $.fn.is
while (--i >= 0) b[methods[i]] = integrate(methods[i])
$.ender(b, true)
$.fn.is.__ignore = true
}(ender))
/*global self:true, traversty:true */
// Augment Traversty with a feature-complete `css()` method
// This is ripped straight out of Bonzo with minimal modification
// https://github.com/ded/bonzo (c) Dustin Diaz 2012, Licence: MIT
(function (T) {
var win = window
, doc = win.document
, html = doc.documentElement
, ie = /msie/i.test(navigator.userAgent)
, digit = /^-?[\d\.]+$/
, unitless = { lineHeight: 1, zoom: 1, zIndex: 1, opacity: 1, boxFlex: 1, WebkitBoxFlex: 1, MozBoxFlex: 1 }
, px = 'px'
, features = (function() {
var e = doc.createElement('p')
e.innerHTML = '<a href="#x">x</a><table style="float:left;"></table>'
return {
cssFloat: e.getElementsByTagName('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]
}
}())
}
}())
, camelize = function (s) {
return s.replace(/-(.)/g, function (m, m1) {
return m1.toUpperCase()
})
}
, viewportdim = function () {
return {
width: ie ? html.clientWidth : self.innerWidth
, height: ie ? html.clientHeight : self.innerHeight
}
}
, docdim = function () {
var vp = viewportdim()
return {
width: Math.max(doc.body.scrollWidth, html.scrollWidth, vp.width)
, height: Math.max(doc.body.scrollHeight, html.scrollHeight, vp.height)
}
}
, setter = function (el, v) {
return typeof v == 'function' ? v(el) : v
}
, styleProperty = function (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
}
, 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)
? function (el, property) {
var value = 100
if (property == 'opacity' && !features.opasity) {
try {
value = el['filters']['DXImageTransform.Microsoft.Alpha'].opacity
} catch (e1) {
try {
value = el['filters']('alpha').opacity
} catch (e2) {}
}
return value / 100
}
value = el.currentStyle ? el.currentStyle[property] : null
return el.style[property] || value
}
: function (el, property) {
return el.style[property]
}
, 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) ? docdim() : viewportdim()
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)
}
// This is the bit we actually care about for Traversty
T.aug({ css: css })
}(traversty))
Copyright 2012, Rod Vagg (the "Original Author")
All rights reserved.
MIT +no-false-attribs License
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
Distributions of all or part of the Software intended to be used
by the recipients as they would use the unmodified Software,
containing modifications that substantially alter, remove, or
disable functionality of the Software, outside of the documented
configuration mechanisms provided by the Software, shall be
modified such that the Original Author's bug reporting email
addresses and urls are either replaced with the contact information
of the parties responsible for the changes, or removed entirely.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except where noted, this license applies to any and all software
programs and associated documentation files created by the
Original Author, when distributed with the Software.
/*global Q:true, T:true, assert:true*/
// note: `T` is `traversty` and `Q` is `qwery` (selector engine), see setup.js
this.filterTests = {
'first()': {
'first() of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).first()
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
, 'first() on a collection returns only the first element'
)
}
, 'first() of one': function () {
assert.hasExactElements(
T(Q('#fixtures > ul:nth-child(1) > li:nth-child(1)')).first()
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
, 'first() on a collection of one returns the one element'
)
}
, 'first() of none': function () {
assert.hasExactElements(
T(Q('#foobar')).first()
, '#doobar'
, 'first() on an empty collection returns an empty collection'
)
}
}
, 'last()': {
'last() of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).last()
, '#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'last() on a collection returns only the last element'
)
}
, 'last() of one': function () {
assert.hasExactElements(
T(Q('#fixtures > ul:nth-child(1) > li:nth-child(1)')).last()
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
, 'last() on a collection of one returns the one element'
)
}
, 'last() of none': function () {
assert.hasExactElements(
T(Q('#foobar')).last()
, '#doobar'
, 'last() on an empty collection returns an empty collection'
)
}
}
, 'eq()': {
'eq(0) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).eq(0)
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
, 'eq(0) on a collection returns only the first element'
)
}
, 'eq(2) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).eq(2)
, '#fixtures > ul:nth-child(1) > li:nth-child(3)'
, 'eq(2) on a collection returns only the 3rd element'
)
}
, 'eq(last index) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).eq(9)
, '#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'eq(last index) on a collection returns only the last element'
)
}
, 'eq(-1) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).eq(-1)
, '#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'eq(-1) on a collection returns only the last element'
)
}
, 'eq(-2) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).eq(-2)
, '#fixtures > ul:nth-child(2) > li:nth-child(4)'
, 'eq(-2) on a collection returns only the second last element'
)
}
, 'eq() of one': function () {
assert.hasExactElements(
T(Q('#fixtures > ul:nth-child(1) > li:nth-child(1)')).eq()
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
, 'eq() on a collection of one returns the one element'
)
}
, 'eq(0) of none': function () {
assert.hasExactElements(
T(Q('#foobar')).eq(0)
, '#doobar'
, 'eq() on an empty collection returns an empty collection'
)
}
, 'eq(100) of none': function () {
assert.hasExactElements(
T(Q('#foobar')).eq(100)
, '#doobar'
, 'eq(100) on an empty collection returns an empty collection'
)
}
, 'eq(100) of < 100': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).eq(100)
, '#doobar'
, 'eq(100) on a collection of < 100 returns empty collection'
)
}
, 'eq() of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).eq()
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
, 'eq() on a collection returns only the first element'
)
}
}
, 'get()': {
'get(0) of many': function () {
assert.isExactElement(
T(Q('#fixtures > ul > li')).get(0)
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
, 'get(0) on a collection returns only the first element'
)
}
, 'get(2) of many': function () {
assert.isExactElement(
T(Q('#fixtures > ul > li')).get(2)
, '#fixtures > ul:nth-child(1) > li:nth-child(3)'
, 'get(2) on a collection returns only the 3rd element'
)
}
, 'get(last index) of many': function () {
assert.isExactElement(
T(Q('#fixtures > ul > li')).get(9)
, '#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'get(last index) on a collection returns only the last element'
)
}
, 'get(-1) of many': function () {
assert.isExactElement(
T(Q('#fixtures > ul > li')).get(-1)
, '#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'get(-1) on a collection returns only the last element'
)
}
, 'get(-2) of many': function () {
assert.isExactElement(
T(Q('#fixtures > ul > li')).get(-2)
, '#fixtures > ul:nth-child(2) > li:nth-child(4)'
, 'get(-2) on a collection returns only the second last element'
)
}
, 'get() of one': function () {
assert.isExactElement(
T(Q('#fixtures > ul:nth-child(1) > li:nth-child(1)')).get()
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
, 'get() on a collection of one returns the one element'
)
}
, 'get(0) of none': function () {
assert.isExactElement(
T(Q('#foobar')).get(0)
, '#doobar'
, 'get() on an empty collection returns an empty collection'
)
}
, 'get(100) of none': function () {
assert.isExactElement(
T(Q('#foobar')).get(100)
, '#doobar'
, 'get(100) on an empty collection returns an empty collection'
)
}
, 'get(100) of < 100': function () {
assert.isExactElement(
T(Q('#fixtures > ul > li')).get(100)
, '#doobar'
, 'get(100) on a collection of < 100 returns empty collection'
)
}
, 'get() of many': function () {
assert.isExactElement(
T(Q('#fixtures > ul > li')).get()
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
, 'get() on a collection returns only the first element'
)
}
}
, 'slice()': {
'slice(0) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(0)
, '#fixtures > ul > li'
, 'slice(0) on a collection returns all elements'
)
}
, 'slice(1) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(1)
, '#fixtures > ul:nth-child(1) > li:nth-child(2)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(3)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(5)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(1)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(2)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(3)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'slice(1) on a collection returns all but first element'
)
}
, 'slice(5) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(5)
, '#fixtures > ul:nth-child(2) > li:nth-child(1)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(2)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(3)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'slice(5) on a collection returns half of the collection'
)
}
, 'slice(9) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(9)
, '#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'slice(9) on a collection returns last element'
)
}
, 'slice(10) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(10)
, '#foobar'
, 'slice(10) on a collection returns empty collection'
)
}
, 'slice(100) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(100)
, '#foobar'
, 'slice(100) on a collection returns empty collection'
)
}
, 'slice(-1) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(-1)
, '#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'slice(-1) on a collection returns last element'
)
}
, 'slice(-9) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(-9)
, '#fixtures > ul:nth-child(1) > li:nth-child(2)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(3)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(5)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(1)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(2)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(3)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'slice(-9) on a collection returns all but first element'
)
}
, 'slice(-10) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(-10)
, '#fixtures > ul > li'
, 'slice(-10) on a collection returns complete collection'
)
}
, 'slice(-100) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(-100)
, '#fixtures > ul > li'
, 'slice(-100) on a collection returns complete collection'
)
}
, 'slice(0, length) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(0, 10)
, '#fixtures > ul > li'
, 'slice(0, length) on a collection returns complete collection'
)
}
, 'slice(0, length - 2) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(0, 8)
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(2)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(3)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(5)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(1)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(2)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(3)'
, 'slice(0, length - 2) on a collection returns all but last 2'
)
}
, 'slice(2, length) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(2, 10)
, '#fixtures > ul:nth-child(1) > li:nth-child(3)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(5)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(1)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(2)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(3)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'slice(2, length) on a collection returns all but first 2'
)
}
, 'slice(2, length - 2) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(2, 8)
, '#fixtures > ul:nth-child(1) > li:nth-child(3)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(5)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(1)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(2)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(3)'
, 'slice(2, length - 2) on a collection returns all but first and last 2'
)
}
, 'slice(0, 0) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(0, 0)
, '#foobar'
, 'slice(0, 0) on a collection returns empty collection'
)
}
, 'slice(2, 2) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(2, 2)
, '#foobar'
, 'slice(2, 2) on a collection returns empty collection'
)
}
, 'slice(0, 1) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(0, 1)
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
, 'slice(0, 1) on a collection returns first element'
)
}
, 'slice(2, 3) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(2, 3)
, '#fixtures > ul:nth-child(1) > li:nth-child(3)'
, 'slice(2, 3) on a collection returns correct element'
)
}
, 'slice(100, 200) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(100, 200)
, '#foobar'
, 'slice(100, 200) on a collection returns empty collection'
)
}
, 'slice(0, 100) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(0, 100)
, '#fixtures > ul > li'
, 'slice(0, 100) on a collection returns entire collection'
)
}
, 'slice(-1, length) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(-1, 10)
, '#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'slice(-1, length) on a collection returns last element'
)
}
, 'slice(-1, length - 1) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(-1, 9)
, '#foobar'
, 'slice(-1, length - 1) on a collection returns empty collection'
)
}
, 'slice(-2, -2) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(-2, -2)
, '#foobar'
, 'slice(-2, -2) on a collection returns empty collection'
)
}
, 'slice(-length, length) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(-10, 10)
, '#fixtures > ul > li'
, 'slice(-length, length) on a collection returns entire collection'
)
}
, 'slice(-100, length) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(-100, 10)
, '#fixtures > ul > li'
, 'slice(-100, length) on a collection returns entire collection'
)
}
, 'slice(-100, -100) of many': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).slice(-100, -100)
, '#foobar'
, 'slice(-100, -100) on a collection returns empty collection'
)
}
, 'slice(-100, -100) of none': function () {
assert.hasExactElements(
T(Q('#foobar')).slice(-100, -100)
, '#foobar'
, 'slice(-100, -100) on an empty collection returns empty collection'
)
}
}
, 'filter()': {
'filter() with no arguments on multi': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).filter()
, '#foobar'
, 'filter() on a collection returns an empty collection'
)
}
, 'filter() with no arguments on empty collection': function () {
assert.hasExactElements(
T([]).filter()
, '#foobar'
, 'filter() on empty collection returns an empty collection'
)
}
, 'filter(fn) on empty collection': function () {
assert.hasExactElements(
T([]).filter(function() { return true })
, '#foobar'
, 'filter(fn) on empty collection returns an empty collection'
)
}
, 'filter(selector) on empty collection': function () {
assert.hasExactElements(
T([]).filter('*')
, '#foobar'
, 'filter(selector) on empty collection returns an empty collection'
)
}
, 'filter(elsewhere element) on empty collection': function () {
assert.hasExactElements(
T([]).filter(Q('#fixtures')[0])
, '#foobar'
, 'filter(selector) on empty collection returns an empty collection'
)
}
, 'filter(fn) `this` and arguments check': function () {
var spy = this.spy()
, elements = Q('#fixtures > ul > li')
, i = 0
T(Q('#fixtures > ul > li')).filter(spy)
assert.equals(spy.callCount, elements.length)
for (; i < elements.length; i++) {
assert.equals(elements[i], spy.getCall(i).thisValue)
assert.equals(1, spy.getCall(i).args.length)
assert.equals(i, spy.getCall(i).args[0])
}
}
, 'filter() with non-returning function': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).filter(function () {})
, '#foobar'
, 'filter(function () {}) on a collection returns an empty collection'
)
}
, 'filter() with function returning false': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).filter(function () { return false })
, '#foobar'
, 'filter(function () { return false }) on a collection returns an empty collection'
)
}
, 'filter() with function returning true': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).filter(function () { return true })
, '#fixtures > ul > li'
, 'filter(function () { return true }) on a collection returns entire collection'
)
}
, 'filter() with function returning true and false': function () {
var b = false
assert.hasExactElements(
T(Q('#fixtures > ul > li')).filter(function () { return b = !b })
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(3)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(5)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(2)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(4)'
, 'filter(function () { return true&false }) on a collection returns correct element'
)
}
, 'filter("")': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).filter('')
, '#foobar'
, 'filter("") on a collection returns empty collection'
)
}
, 'filter("*")': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).filter('*')
, '#fixtures > ul > li'
, 'filter("*") on a collection returns entire collection'
)
}
, 'filter("li")': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).filter('li')
, '#fixtures > ul > li'
, 'filter("li") on a collection returns entire collection'
)
}
, 'filter(":nth-child(1)")': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).filter(':nth-child(1)')
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(1)'
, 'filter(":nth-child(1)") on a collection returns correct elements'
)
}
, 'filter(element)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).filter(Q('#fixtures > ul:nth-child(1) > li:nth-child(2)')[0])
, '#fixtures > ul:nth-child(1) > li:nth-child(2)'
, 'filter(element) on a collection returns correct element'
)
}
}
, 'not()': {
'not() with no arguments on multi': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).not()
, '#fixtures > ul > li'
, 'not() on a collection returns an empty collection'
)
}
, 'not() with no arguments on empty collection': function () {
assert.hasExactElements(
T([]).not()
, '#foobar'
, 'not() on empty collection returns an empty collection'
)
}
, 'not(fn) on empty collection': function () {
assert.hasExactElements(
T([]).not(function() { return true })
, '#foobar'
, 'not(fn) on empty collection returns an empty collection'
)
}
, 'not(selector) on empty collection': function () {
assert.hasExactElements(
T([]).not('*')
, '#foobar'
, 'not(selector) on empty collection returns an empty collection'
)
}
, 'not(elsewhere element) on empty collection': function () {
assert.hasExactElements(
T([]).not(Q('#fixtures')[0])
, '#foobar'
, 'not(selector) on empty collection returns an empty collection'
)
}
, 'not(fn) `this` and arguments check': function () {
var spy = this.spy()
, elements = Q('#fixtures > ul > li')
, i = 0
T(Q('#fixtures > ul > li')).not(spy)
assert.equals(spy.callCount, elements.length)
for (; i < elements.length; i++) {
assert.equals(elements[i], spy.getCall(i).thisValue)
assert.equals(1, spy.getCall(i).args.length)
assert.equals(i, spy.getCall(i).args[0])
}
}
, 'not() with non-returning function': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).not(function () {})
, '#fixtures > ul > li'
, 'not(function () {}) on a collection returns an empty collection'
)
}
, 'not() with function returning false': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).not(function () { return false })
, '#fixtures > ul > li'
, 'not(function () { return false }) on a collection returns an empty collection'
)
}
, 'not() with function returning true': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).not(function () { return true })
, '#foobar'
, 'not(function () { return true }) on a collection returns entire collection'
)
}
, 'not() with function returning true and false': function () {
var b = false
assert.hasExactElements(
T(Q('#fixtures > ul > li')).not(function () { return b = !b })
, '#fixtures > ul:nth-child(1) > li:nth-child(2)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(1)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(3)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'not(function () { return true&false }) on a collection returns correct element'
)
}
, 'not("")': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).not('')
, '#fixtures > ul > li'
, 'not("") on a collection returns empty collection'
)
}
, 'not("*")': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).not('*')
, '#foobar'
, 'not("*") on a collection returns entire collection'
)
}
, 'not("li")': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).not('li')
, '#foobar'
, 'not("li") on a collection returns entire collection'
)
}
, 'not(":nth-child(1)")': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).not(':nth-child(1)')
, '#fixtures > ul:nth-child(1) > li:nth-child(2)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(3)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(5)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(2)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(3)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'not(":nth-child(1)") on a collection returns correct elements'
)
}
, 'not(element)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).not(Q('#fixtures > ul:nth-child(1) > li:nth-child(2)')[0])
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(3)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(1) > li:nth-child(5)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(1)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(2)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(3)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'not(element) on a collection returns correct element'
)
}
}
, 'has()': {
'has() on multiples': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).has()
, '#foobar'
, 'has() on collection returns empty collection'
)
}
, 'has(selector) on empty collection': function () {
assert.hasExactElements(
T([]).has('*')
, '#foobar'
, 'has(selector) on collection returns empty collection'
)
}
, 'has(element) on empty collection': function () {
assert.hasExactElements(
T([]).has(Q('#fixtures')[0])
, '#foobar'
, 'has(element) on collection returns empty collection'
)
}
, 'has(*) on multiples': function () {
assert.hasExactElements(
T(Q('#fixtures > ul')).has('*')
, '#fixtures > ul'
, 'has(*) on collection returns entire collection'
)
}
, 'has(li) on multiples': function () {
assert.hasExactElements(
T(Q('#fixtures > ul')).has('li')
, '#fixtures > ul'
, 'has(li) on collection returns entire collection'
)
}
, 'has(span) on multiples': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).has('span')
, '#fixtures > ul > li:nth-child(4)'
, 'has(span) on collection returns correct elements'
)
}
, 'has(elsewhere element) on multiples': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).has(Q('#fixtures')[0])
, '#foobar'
, 'has(elsewhere element) on collection returns empty collection'
)
}
, 'has(element) on multiples': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).has(Q('#fixtures > ul > li:nth-child(4) span')[0])
, '#fixtures > ul:nth-child(1) > li:nth-child(4)'
, 'has(element) on collection returns correct element'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li')).has(Q('#fixtures > ul > li:nth-child(4) span')[1])
, '#fixtures > ul:nth-child(2) > li:nth-child(4)'
, 'has(element) on collection returns correct element'
)
}
}
, 'is()': {
'is() on empty collection': function () {
assert(T([]).is() === false)
}
, 'is() on multi collection': function () {
assert(T(Q('#fixtures > ul > li')).is() === false)
}
, 'is(fn=false) on multi collection': function () {
assert(T(Q('#fixtures > ul > li')).is(function () { return false }) === false)
}
, 'is(fn=true) on multi collection': function () {
assert(T(Q('#fixtures > ul > li')).is(function () { return true }) === true)
}
, 'is(fn=true) on empty collection': function () {
assert(T([]).is(function () { return true }) === false)
}
, 'is(fn) `this` and arguments check': function () {
var spy = this.spy()
, elements = Q('#fixtures > ul > li')
, i = 0
T(Q('#fixtures > ul > li')).is(spy)
assert.equals(spy.callCount, elements.length)
for (; i < elements.length; i++) {
assert.equals(elements[i], spy.getCall(i).thisValue)
assert.equals(1, spy.getCall(i).args.length)
assert.equals(i, spy.getCall(i).args[0])
}
}
, 'is(nonmatch selector) on multi collection': function () {
assert(T(Q('#fixtures > ul > li')).is('ul') === false)
}
, 'is(selector) on multi collection': function () {
assert(T(Q('#fixtures > ul > li')).is('li') === true)
}
, 'is(nonmatch element) on multi collection': function () {
assert(T(Q('#fixtures > ul > li')).is(Q('#fixtures')[0]) === false)
}
, 'is(element) on multi collection': function () {
assert(T(Q('#fixtures > ul > li')).is(Q('#fixtures > ul > li')[0]) === true)
assert(T(Q('#fixtures > ul > li')).is(Q('#fixtures > ul > li')[2]) === true)
assert(T(Q('#fixtures > ul > li')).is(Q('#fixtures > ul > li')[6]) === true)
}
}
}

Sorry, the diff of this file is not supported yet

/*!
* @preserve Qwery - A Blazing Fast query selector engine
* https://github.com/ded/qwery
* copyright Dustin Diaz & Jacob Thornton 2012
* MIT License
*/
!function () {
var q, pseudos, i, l, p, r, nodes, m, nthPattern = /\s*((?:\+|\-)?(\d*))n\s*((?:\+|\-)\s*\d+)?\s*/
if (typeof module != 'undefined' && typeof 'require' != 'undefined')
q = require('qwery')
else if (typeof qwery != 'undefined')
q = qwery
else
return
pseudos = q.pseudos
function children(node, ofType) {
var r = []
nodes = node.childNodes
for (i = 0, l = nodes.length; i < l; i++) {
if (nodes[i].nodeType == 1 && (!ofType || nodes[i].nodeName == ofType)) r.push(nodes[i])
}
return r
}
function checkNthExpr(el, nodes, a, b) {
if (!a) return (nodes[b-1] == el)
for (i = b, l = nodes.length; ((a > 0) ? (i <= l) : (i >= 1)); i += a) if (el == nodes[i-1]) return true
return false
}
function checkNth(el, nodes, val) {
if (isFinite(val)) return nodes[val - 1] == el
else if (val == 'odd') return checkNthExpr(el, nodes, 2, 1)
else if (val == 'even') return checkNthExpr(el, nodes, 2, 0)
else if (m = nthPattern.exec(val))
return checkNthExpr(el, nodes,
(m[2] ? parseInt(m[1], 10) : parseInt(m[1] + '1', 10)), // Check case where coefficient is omitted
(m[3] ? parseInt(m[3].replace(/\s*/, ''), 10) : 0)) // Check case where constant is omitted
return false
}
function text(el, s) {
if (el.nodeType === 3 || el.nodeType === 4) return el.nodeValue;
if (el.nodeType !== 1 && el.nodeType !== 9) return '';
for (s = '', el = el.firstChild; el; el = el.nextSibling) {
if (el.nodeType !== 8) s += el.textContent || el.innerText || text(el)
}
return s
}
// *was* going to be in CSS3, didn't quite make it
pseudos.contains = function(el, val) { return text(el).indexOf(val) != -1 }
pseudos.not = function(el, val) { return !q.is(el, val) }
pseudos['nth-child'] = function (el, val) {
if (!val || !(p = el.parentNode)) return false
return checkNth(el, children(p), val)
}
pseudos['nth-last-child'] = function (el, val) {
if (!val || !(p = el.parentNode)) return false
return checkNth(el, children(p).reverse(), val)
}
pseudos['nth-of-type'] = function (el, val) {
if (!val || !(p = el.parentNode)) return false
return checkNth(el, children(p, el.nodeName), val)
}
pseudos['nth-last-of-type'] = function (el, val) {
if (!val || !(p = el.parentNode)) return false
return checkNth(el, children(p, el.nodeName).reverse(), val)
}
pseudos['first-child'] = function (el) { return pseudos['nth-child'](el, 1) }
pseudos['last-child'] = function (el) { return pseudos['nth-last-child'](el, 1) }
pseudos['first-of-type'] = function (el) { return pseudos['nth-of-type'](el, 1) }
pseudos['last-of-type'] = function (el) { return pseudos['nth-last-of-type'](el, 1) }
pseudos['only-child'] = function (el) {
return (p = el.parentNode) && (nodes = children(p)) && (nodes.length == 1) && (el == nodes[0])
};
pseudos['only-of-type'] = function (el) {
return (p = el.parentNode) && (nodes = children(p, el.nodeName)) && (nodes.length == 1) && (el == nodes[0])
}
pseudos.target = function (el) {
return (el.getAttribute('id') == location.hash.substr(1))
}
pseudos.checked = function (el) { return el.checked }
pseudos.enabled = function (el) { return !el.disabled }
pseudos.disabled = function (el) { return el.disabled }
pseudos.empty = function (el) { return !el.childNodes.length }
}();
/*!
* @preserve Qwery - A Blazing Fast query selector engine
* https://github.com/ded/qwery
* copyright Dustin Diaz & Jacob Thornton 2012
* MIT License
*/
(function (name, definition, context) {
if (typeof module != 'undefined' && module.exports) module.exports = definition()
else if (typeof context['define'] == 'function' && context['define']['amd']) define(name, definition)
else context[name] = definition()
})('qwery', 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 + ')?')
, 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
}, this);
<!doctype html>
<html>
<head>
<title>Traversty with Qwery and css() augmentation Integration Test</title>
<script src="../../traversty.js"></script>
<script src="qwery.js"></script>
<script src="qwery-pseudos.js"></script>
<script src="../../examples/aug-css.js"></script>
</head>
<body>
<h1>Traversty with Qwery and css() augmentation Integration Test</h1>
<p>This is vanilla Traversty with Qwery plugged in as <code>setSelectorEngine()</code> and a <code>css()</code> method added by using <code>aug()</code>. See the <i>/examples/aug-css.js</i> file for how this achieved.</p>
<div id="fixtures">
<ul>
<li>ONE (red)</li>
<li class="c">TWO</li>
<li>THREE (green)</li>
<li class="c">FOUR
<ul class="second">
<li>i</li>
<li class="c">ii</li>
<li>iii (blue)</li>
<li class="c">iv
<span class="c">SPAN (yellow)</span>
</li>
</ul>
</li>
<li class="c">FIVE (purple)</li>
</ul>
<ul>
<li>one (red)</li>
<li class="c">two</li>
<li>three (green)</li>
<li class="c">four
<ul class="second">
<li>1</li>
<li class="c">2</li>
<li>3 (blue)</li>
<li class="c">4
<span class="c">span (yellow)</span>
</li>
</ul>
</li>
<li class="c">five (purple)</li>
</ul>
</div>
<div id="reference">
<h2>Reference screenshot</h2>
<p>The above block should look similar to this:</p>
<img src="integration_reference.png" style="border: 1px solid rgb(100,100,100); box-shadow: 2px 2px 15px rgb(100,100,100);">
</div>
<p>See also:</p>
<ul>
<li><a href="ender_qwery.html">Traversty Ender (with Qwery) Integration Test</a></li>
<li><a href="ender_sel.html">Traversty Ender (with Sel) Integration Test</a></li>
<li><a href="ender_sizzle.html">Traversty Ender (with Sizzle) Integration Test</a></li>
<li><a href="ender_nwmatcher.html">Traversty Ender (with NWMatcher) Integration Test</a></li>
<li><a href="ender_noselector.html">Traversty Ender (with no selector engine) Integration Test</a></li>
</ul>
<script>
var $ = traversty
$.setSelectorEngine(qwery)
$('#fixtures > ul')
.down(0).css('color', 'red')
.next('li', 1).css('color', 'green')
.next().down('li', 2).css('color', 'blue')
.next().down().css('color', 'yellow')
.up(2).next().css('color', 'purple')
.siblings(3).css('fontWeight', 'bold')
.children().css('textDecoration', 'underline')
.children(1).css('borderLeft', 'solid 5px red')
.parents('*').filter('ul').css('borderTop', 'dashed 2px green')
.not('.second').css('borderBottom', 'solid 3px blue')
.down('.second li').has('span').css('marginTop', '10px')
.up('ul').eq(-1).css('borderLeft', 'solid 5px orange')
.closest('#fixtures').down('li').slice(-10,-9).css('fontSize', '25px')
$.aug({ prepend: function (element) {
return this.each(function (el, i) {
el.insertBefore(i > 0 ? element.cloneNode(true) : element, el.firstChild)
})
}})
var div = document.createElement('div')
div.innerHTML = 'INTEGRATION TEST ALL DONE!'
if ($('li').is('.c') === true) $('#fixtures').prepend(div)
</script>
</body>
</html>
/*global Q:true, T:true, assert:true*/
// note: `T` is `traversty` and `Q` is `qwery` (selector engine), see setup.js
this.traversalTests = {
'Simple no-arg traversal': {
'next()': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(1)')).next()
, '#fixtures > ul > li:nth-child(2)'
, 'next() on two elements moved to nextSibling on both'
)
}
, 'previous()': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(4)')).previous()
, '#fixtures > ul > li:nth-child(3)'
, 'previous() on two elements moved to previousSibling on both'
)
}
, 'up()': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(3)')).up()
, '#fixtures > ul'
, 'up() on two elements moved to parentNode on both'
)
}
, 'down()': function () {
assert.hasExactElements(
T(Q('#fixtures > ul')).down()
, '#fixtures > ul > li:nth-child(1)'
, 'down() on two elements moved to the first childNode on both'
)
}
}
, 'Index argument traversal': {
'next(index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(1)')).next(0)
, '#fixtures > ul > li:nth-child(2)'
, 'next(0) on two elements moved to 1st nextSibling element on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(1)')).next(1)
, '#fixtures > ul > li:nth-child(3)'
, 'next(1) on two elements moved to 2nd nextSibling element on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(1)')).next(3)
, '#fixtures > ul > li:nth-child(5)'
, 'next(3) on two elements moved to 3rd nextSibling element on both'
)
}
, 'previous(index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).previous(0)
, '#fixtures > ul > li:nth-child(4)'
, 'previous(0) on two elements moved to 1st previousSibling element on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).previous(1)
, '#fixtures > ul > li:nth-child(3)'
, 'previous(1) on two elements moved to 2nd previousSibling element on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).previous(3)
, '#fixtures > ul > li:nth-child(1)'
, 'previous(3) on two elements moved to 3rd previousSibling element on both'
)
}
, 'up(index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up(0)
, '#fixtures > ul > li > ul > li:nth-child(4)'
, 'up(0) on two elements moved to 1st parentNode on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up(3)
, '#fixtures > ul'
, 'up(3) on two elements moved to 3rd parentNode on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up(4)
, '#fixtures'
, 'up(4) on two elements moved to *single* common ancestor node for both'
)
}
, 'down(index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul')).down(0)
, '#fixtures > ul > li:nth-child(1)'
, 'down(0) on two elements moved to first childNode on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).down(1)
, '#fixtures > ul > li:nth-child(2)'
, 'down(1) on two elements moved to second childNode on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).down(9)
, '#fixtures > ul > li > ul > li > span'
, 'down(9) on two elements moved down to 10th descendent in document order'
)
}
}
, 'Selector and index argument traversal': {
'next(selector, index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(1)')).next('li', 1)
, '#fixtures > ul > li:nth-child(3)'
, 'next("li", 1) moves to 2nd nextSibling, both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(1)')).next('.c', 1)
, '#fixtures > ul > li:nth-child(4)'
, 'next(".c", 1) moves to the second nextSibling with class "c", both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(1)')).next('li.c', 2)
, '#fixtures > ul > li:nth-child(5)'
, 'next("li.c", 2) moves to the 3rd nextSibling li with class "c", both elements'
)
assert.hasExactElements(
T(Q('#flat *:nth-child(2)')).next('div, p', 2)
, '#flat *:nth-child(6)'
, 'next("div, p", 2) matches 3rd following <div> or <p>'
)
}
, 'next(selector, index) returns unique elements': function () {
assert.hasExactElements(
T(Q('#flat *:nth-child(-n+2)')).next('div', 1)
, '#flat *:nth-child(6)'
, 'next("div", 1) on two elements matches single 2nd following <div>'
)
}
, 'previous(selector, index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).previous('li', 1)
, '#fixtures > ul > li:nth-child(3)'
, 'previous("li", 1) moves to 2nd previousSibling, both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).previous('.c', 0)
, '#fixtures > ul > li:nth-child(4)'
, 'previous(".c", 0) moves to the first previousSibling with class "c", both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).previous('li.c', 1)
, '#fixtures > ul > li:nth-child(2)'
, 'previous("li.c", 2) moves to the 2nd previousSibling li with class "c", both elements'
)
assert.hasExactElements(
T(Q('#flat *:nth-child(5)')).previous('div, p', 2)
, '#flat *:nth-child(1)'
, 'previous("div, p", 2) matches 3rd preceeding <div> or <p>'
)
}
, 'previous(selector, index) returns unique elements': function () {
assert.hasExactElements(
T(Q('#flat *:nth-child(n+5)')).previous('p', 1)
, '#flat *:nth-child(1)'
, 'previous("p", 1) on two elements matches single 2nd preceeding <p>'
)
}
, 'up(selector, index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up('li', 0)
, '#fixtures > ul > li > ul > li:nth-child(4)'
, 'up("li", 0) moves to first parentNode of both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up('li', 1)
, '#fixtures > ul > li:nth-child(4)'
, 'up("li", 1) moves to second li parentNode (3rd actual parentNode) of both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up('li.c', 1)
, '#fixtures > ul > li:nth-child(4)'
, 'up("li.c", 0) moves to second li parentNode with class "c" (3rd actual parentNode) of both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up('li, ul', 2)
, '#fixtures > ul > li:nth-child(4)'
, 'up("li, ul", 2) moves to 3rd parentNode, either <li> or <ul> of both elements'
)
}
, 'up(selector, index) returns unique elements': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up('#fixtures', 0)
, '#fixtures'
, 'up("#fixtures", 0) moves up to common (single) parent node of both elements'
)
}
, 'down(selector, index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul')).down('li', 0)
, '#fixtures > ul > li:nth-child(1)'
, 'down("li", 0) moves to first li element in document-order on both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).down('li', 2)
, '#fixtures > ul > li:nth-child(3)'
, 'down("li", 2) moves to third li element in document-order on both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).down('.c', 4)
, '#fixtures > ul > li > ul > li > span'
, 'down(".c", 4) moves to 4th element with class "c" in document-order on both elements'
)
assert.hasExactElements(
T(Q('#fixtures')).down('li', 0)
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
, 'down("li", 0) moves to first li element in document-order on first branch only'
)
assert.hasExactElements(
T(Q('#fixtures')).down('li', 2)
, '#fixtures > ul:nth-child(1) > li:nth-child(3)'
, 'down("li", 2) moves to third li element in document-order on first branch only'
)
assert.hasExactElements(
T(Q('#fixtures')).down('.c', 4)
, '#fixtures > ul:nth-child(1) > li > ul > li > span'
, 'down(".c", 4) moves to 4th element with class "c" in document-order on first branch only'
)
assert.hasExactElements(
T(Q('#fixtures')).down('ul, .c', 3)
, '#fixtures > ul:nth-child(1) > li > ul'
, 'down("ul, .c", 3) moves to 4th <ul> element or element with class "c" in document-order on first branch only'
)
}
, 'down(selector, index) returns unique elements': function () {
assert.hasExactElements(
T(Q('#fixtures, #fixtures > ul:nth-child(1)')).down('li', 0)
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
, 'down("li", 0) from both root and first child of root moves to first li element in document-order on first branch only'
)
}
}
, 'Selector argument traversal': {
'next(selector)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(1)')).next('li')
, '#fixtures > ul > li:nth-child(n+2)'
, 'next("li") on two first-elements matches all following sibling elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(3)')).next('li')
, '#fixtures > ul > li:nth-child(n+4)'
, 'next("li") on two second-elements matches all following sibling elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(2)')).next('.c')
, '#fixtures > ul > li:nth-child(n+4).c' // nth-child doesn't look for .c children but actual children, so 4 is our next .c (note we have to write our selector with the trailling .c rather than the nicer li.c cause WebKit's nth-child is garbage
, 'next(".c") on two second-elements matches all following sibling elements with class "c"'
)
assert.hasExactElements(
T(Q('#flat *:nth-child(2)')).next('span, p')
, '#flat *:nth-child(4),#flat *:nth-child(5)'
, 'next("span, p") matches all following <span> and <p> sibling elements'
)
}
, 'previous(selector)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).previous('li')
, '#fixtures > ul > li:nth-child(-n+4)' // all but last
, 'previous("li") on two first-elements matches all preceeding sibling elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(3)')).previous('li')
, '#fixtures > ul > li:nth-child(-n+2)' // first 2
, 'previous("li") on two second-elements matches all preceeding sibling elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).previous('.c')
, '#fixtures > ul > li.c:nth-child(-n+4)' // nth-child doesn't look for .c children but actual children, so 4 is our previous .c
, 'previous(".c") on two second-elements matches all preceeding sibling elements with class "c"'
)
assert.hasExactElements(
T(Q('#flat *:nth-child(5)')).previous('span, p')
, '#flat *:nth-child(-n+2),#flat *:nth-child(4)'
, 'previous("span, p") matches all preceeding <span> and <p> sibling elements'
)
}
, 'up(selector)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up('li')
, '#fixtures > ul:nth-child(1) > li:nth-child(4), #fixtures > ul:nth-child(1) > li > ul > li:nth-child(4),#fixtures > ul > li:nth-child(4), #fixtures > ul > li > ul > li:nth-child(4)'
, 'up("li") on two deep elements matches all <li> ancestor elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up('*')
, 'html, body, #fixtures, #fixtures > ul:nth-child(1), #fixtures > ul:nth-child(1) > li:nth-child(4), #fixtures > ul:nth-child(1) > li:nth-child(4) > ul, #fixtures > ul:nth-child(1) > li > ul > li:nth-child(4), #fixtures > ul, #fixtures > ul > li:nth-child(4), #fixtures > ul > li:nth-child(4) > ul, #fixtures > ul > li > ul > li:nth-child(4)'
, 'up("*") on two deep elements matches all ancestor elements up to <html>'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up('ul, li')
, '#fixtures > ul:nth-child(1), #fixtures > ul:nth-child(1) > li:nth-child(4), #fixtures > ul:nth-child(1) > li:nth-child(4) > ul, #fixtures > ul:nth-child(1) > li > ul > li:nth-child(4),#fixtures > ul, #fixtures > ul > li:nth-child(4), #fixtures > ul > li > ul, #fixtures > ul > li > ul > li:nth-child(4)'
, 'up("ul, li") on two deep elements matches all <ul> and <li> ancestor elements'
)
}
, 'down(selector)': function () {
assert.hasExactElements(
T(Q('#fixtures')).down('li')
, '#fixtures li'
, 'down("li") selects all descendent <li> elements, same as qSA'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li')).down('*')
, '#fixtures > ul > li *'
, 'down("*") selects all descendent elements, same as qSA'
)
assert.hasExactElements(
T(Q('#fixtures > ul:nth-child(1)')).down('li, span')
, '#fixtures > ul:nth-child(1) > li:nth-child(-n+4), #fixtures > ul:nth-child(1) > li > ul > li, #fixtures > ul:nth-child(1) > li > ul > li > span, #fixtures > ul:nth-child(1) > li.five'
, 'down("li, span") selects all descendent <li> and <span> elements, same as qSA'
)
}
}
, 'parents()': {
'parents() is the same as up(*)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).parents()
, 'html, body, #fixtures, #fixtures > ul:nth-child(1), #fixtures > ul:nth-child(1) > li:nth-child(4), #fixtures > ul:nth-child(1) > li:nth-child(4) > ul, #fixtures > ul:nth-child(1) > li > ul > li:nth-child(4), #fixtures > ul, #fixtures > ul > li:nth-child(4), #fixtures > ul > li:nth-child(4) > ul, #fixtures > ul > li > ul > li:nth-child(4)'
, 'parents() on two deep elements matches all ancestor elements up to <html>'
)
}
, 'parents(index) === up(index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).parents(0)
, '#fixtures > ul > li > ul > li:nth-child(4)'
, 'parents(0) on two elements moved to 1st parentNode on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).parents(3)
, '#fixtures > ul'
, 'parents(3) on two elements moved to 3rd parentNode on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).parents(4)
, '#fixtures'
, 'parents(4) on two elements moved to *single* common ancestor node for both'
)
}
, 'parents(selector, index) === up(selector, index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).parents('li', 0)
, '#fixtures > ul > li > ul > li:nth-child(4)'
, 'parents("li", 0) moves to first parentNode of both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).parents('li', 1)
, '#fixtures > ul > li:nth-child(4)'
, 'parents("li", 1) moves to second li parentNode (3rd actual parentNode) of both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).parents('li.c', 1)
, '#fixtures > ul > li:nth-child(4)'
, 'parents("li.c", 0) moves to second li parentNode with class "c" (3rd actual parentNode) of both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).parents('li, ul', 2)
, '#fixtures > ul > li:nth-child(4)'
, 'parents("li, ul", 2) moves to 3rd parentNode, either <li> or <ul> of both elements'
)
}
, 'parents(selector, index) === up(selector, index) returns unique elements': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).parents('#fixtures', 0)
, '#fixtures'
, 'parents("#fixtures", 0) moves up to common (single) parent node of both elements'
)
}
, 'parents(selector) === up(selector)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).parents('li')
, '#fixtures > ul:nth-child(1) > li:nth-child(4), #fixtures > ul:nth-child(1) > li > ul > li:nth-child(4),#fixtures > ul > li:nth-child(4), #fixtures > ul > li > ul > li:nth-child(4)'
, 'parents("li") on two deep elements matches all <li> ancestor elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).parents('*')
, 'html, body, #fixtures, #fixtures > ul:nth-child(1), #fixtures > ul:nth-child(1) > li:nth-child(4), #fixtures > ul:nth-child(1) > li:nth-child(4) > ul, #fixtures > ul:nth-child(1) > li > ul > li:nth-child(4), #fixtures > ul, #fixtures > ul > li:nth-child(4), #fixtures > ul > li:nth-child(4) > ul, #fixtures > ul > li > ul > li:nth-child(4)'
, 'parents("*") on two deep elements matches all ancestor elements up to <html>'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).parents('ul, li')
, '#fixtures > ul:nth-child(1), #fixtures > ul:nth-child(1) > li:nth-child(4), #fixtures > ul:nth-child(1) > li:nth-child(4) > ul, #fixtures > ul:nth-child(1) > li > ul > li:nth-child(4),#fixtures > ul, #fixtures > ul > li:nth-child(4), #fixtures > ul > li > ul, #fixtures > ul > li > ul > li:nth-child(4)'
, 'parents("ul, li") on two deep elements matches all <ul> and <li> ancestor elements'
)
}
}
, 'siblings()': {
'siblings() of empty collection': function () {
assert.hasExactElements(
T([]).siblings()
, '#foobar'
, 'siblings() on empty collection returned empty collection'
)
}
, 'siblings() with no argument returns all siblings': function () {
assert.hasExactElements(
T(Q('#fixtures > ul:first-child > li:first-child')).siblings()
, '#fixtures > ul:nth-child(1) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(5)'
, 'siblings() with no-arg returns all siblings (single collection, firstChild)'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:first-child')).siblings()
, '#fixtures > ul:nth-child(1) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(5),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'siblings() with no-arg returns all siblings (multi collection, firstChildren)'
)
assert.hasExactElements(
T(Q('#fixtures > ul:first-child > li:nth-child(5)')).siblings()
, '#fixtures > ul:nth-child(1) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4)'
, 'siblings() with no-arg returns all siblings (single collection, lastChild)'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).siblings()
, '#fixtures > ul:nth-child(1) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(4)'
, 'siblings() with no-arg returns all siblings (multi collection, lastChildren)'
)
assert.hasExactElements(
T(Q('#fixtures > ul:first-child > li:nth-child(2)')).siblings()
, '#fixtures > ul:nth-child(1) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(5)'
, 'siblings() with no-arg returns all siblings (single collection, midChild)'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(2)')).siblings()
, '#fixtures > ul:nth-child(1) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(5),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'siblings() with no-arg returns all siblings (multi collection, midChildren)'
)
}
, 'siblings() on siblings should include those siblings': function () {
assert.hasExactElementsUnordered(
T(Q('#fixtures > ul:first-child > li:nth-child(1),#fixtures > ul:first-child > li:nth-child(3)')).siblings()
, '#fixtures > ul:nth-child(1) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(5)'
, 'siblings() no-arg with sibs 1 & 5 should also include 1 & 5 in result'
)
assert.hasExactElementsUnordered(
T(Q('#fixtures > ul > li:nth-child(1),#fixtures > ul > li:nth-child(5)')).siblings()
, '#fixtures > ul:nth-child(1) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(5),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'siblings() no-arg with sibs 1s & 5s should also include 1s & 5s in result'
)
}
, 'siblings(selector) returns correct elements': function () {
assert.hasExactElements(
T(Q('#fixtures > ul:first-child > li:first-child')).siblings('li')
, '#fixtures > ul:nth-child(1) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(5)'
, 'siblings(selector) returns all siblings (single collection, firstChild)'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:first-child')).siblings('li')
, '#fixtures > ul:nth-child(1) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(5),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'siblings(selector) returns all siblings (multi collection, firstChildren)'
)
assert.hasExactElements(
T(Q('#fixtures > ul:first-child > li:nth-child(5)')).siblings('li')
, '#fixtures > ul:nth-child(1) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4)'
, 'siblings(selector) returns all siblings (single collection, lastChild)'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).siblings('li')
, '#fixtures > ul:nth-child(1) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(4)'
, 'siblings(selector) returns all siblings (multi collection, lastChildren)'
)
assert.hasExactElements(
T(Q('#fixtures > ul:first-child > li:nth-child(2)')).siblings('li')
, '#fixtures > ul:nth-child(1) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(5)'
, 'siblings(selector) returns all siblings (single collection, midChild)'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(2)')).siblings('li')
, '#fixtures > ul:nth-child(1) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(5),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'siblings(selector) returns all siblings (multi collection, midChildren)'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(2)')).siblings('*')
, '#fixtures > ul:nth-child(1) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(5),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'siblings(*) returns all siblings (multi collection, midChildren)'
)
}
, 'siblings(selector) on matching siblings should include those siblings': function () {
assert.hasExactElementsUnordered(
T(Q('#fixtures > ul:first-child > li:nth-child(1),#fixtures > ul:first-child > li:nth-child(5)')).siblings('li')
, '#fixtures > ul:nth-child(1) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(5)'
, 'siblings() no-arg with sibs 1 & 5 should also include 1 & 5 in result'
)
assert.hasExactElementsUnordered(
T(Q('#fixtures > ul > li:nth-child(1),#fixtures > ul > li:nth-child(5)')).siblings('*')
, '#fixtures > ul:nth-child(1) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(1) > li:nth-child(5),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(1),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(2),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'siblings() no-arg with sibs 1s & 5s should also include 1s & 5s in result'
)
}
, 'siblings(index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul:first-child > li:first-child')).siblings(2)
, '#fixtures > ul:nth-child(1) > li:nth-child(4)'
, 'siblings(index) returns correct sibling (single collection, firstChild)'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:first-child')).siblings(3)
, '#fixtures > ul:nth-child(1) > li:nth-child(5),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(5)'
, 'siblings(index) returns correct siblings (multi collection, firstChildren)'
)
assert.hasExactElements(
T(Q('#fixtures > ul:first-child > li:nth-child(5)')).siblings(1)
, '#fixtures > ul:nth-child(1) > li:nth-child(2),'
, 'siblings(index) returns correct sibling (single collection, lastChild)'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).siblings(2)
, '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(3),'
, 'siblings(index) returns correct siblings (multi collection, lastChildren)'
)
assert.hasExactElements(
T(Q('#fixtures > ul:first-child > li:nth-child(2)')).siblings(3)
, '#fixtures > ul:nth-child(1) > li:nth-child(5),'
, 'siblings(index) returns correct sibling (single collection, midChild)'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(2)')).siblings(2)
, '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(4),'
, 'siblings(index) returns siblings (multi collection, midChildren)'
)
}
, 'siblings(selector, index)': function () {
assert.hasExactElements(
T([]).siblings('*', 0)
, '#foobar'
, 'siblings(*,0) on empty collection returns empty collection'
)
assert.hasExactElements(
T([]).siblings('*', 10)
, '#foobar'
, 'siblings(*,10) on empty collection returns empty collection'
)
assert.hasExactElements(
T(Q('#fixtures > ul:first-child > li:first-child')).siblings('*', 1)
, '#fixtures > ul:first-child > li:nth-child(3)'
, 'siblings(*,1) on returns correct element (after)'
)
assert.hasExactElements(
T(Q('#fixtures > ul:first-child > li:nth-child(4)')).siblings('*', 1)
, '#fixtures > ul:first-child > li:nth-child(2)'
, 'siblings(*,1) on returns correct element (before)'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:first-child')).siblings('*', 1)
, '#fixtures > ul:nth-child(1) > li:nth-child(3)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(3)'
, 'siblings(*,1) on returns correct element (after, multi)'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(4)')).siblings('*', 1)
, '#fixtures > ul:nth-child(1) > li:nth-child(2)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(2)'
, 'siblings(*,1) on returns correct element (before, multi)'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(4)')).siblings('*', 20)
, '#foobar'
, 'siblings(*, 29) on returns empty collection'
)
assert.hasExactElements(
T(Q('#fixtures > ul li:nth-child(3)')).siblings('.c', 1)
, '#fixtures > ul:nth-child(1) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(1) li li:nth-child(4)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(2) > li li:nth-child(4)'
, 'siblings(.c, 2) on returns correct elements (complex, multi-depth selector)'
)
}
}
, 'children()': {
'children() of empty collection': function () {
assert.hasExactElements(
T([]).children()
, '#foobar'
, 'children() on empty collection returned empty collection'
)
}
, 'children() with no argument returns all children': function () {
assert.hasExactElements(
T(Q('#fixtures > ul:first-child')).children()
, '#fixtures > ul:nth-child(1) > li'
, 'sublings() with no-arg returns all children (single collection, firstChild)'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).children()
, '#fixtures > ul > li'
, 'sublings() with no-arg returns all children (multi collection, firstChildren)'
)
}
, 'children(selector) returns correct elements': function () {
assert.hasExactElements(
T(Q('#fixtures > ul:first-child')).children('li')
, '#fixtures > ul:nth-child(1) > li'
, 'sublings(selector) returns all children (single collection, firstChild)'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).children('li')
, '#fixtures > ul > li'
, 'sublings(selector) returns all children (multi collection, firstChildren)'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).children('*')
, '#fixtures > ul > li'
, 'sublings(selector) returns all children (multi collection, firstChildren)'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).children('.c')
, '#fixtures > ul > li.c'
, 'sublings(selector) returns correct children'
)
}
, 'children(index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul:first-child')).children(2)
, '#fixtures > ul:nth-child(1) > li:nth-child(3)'
, 'sublings(index) returns correct sibling (single collection, firstChild)'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).children(3)
, '#fixtures > ul:nth-child(1) > li:nth-child(4),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(4)'
, 'sublings(index) returns correct children (multi collection, firstChildren)'
)
assert.hasExactElements(
T(Q('#fixtures > ul:first-child')).children(1)
, '#fixtures > ul:nth-child(1) > li:nth-child(2),'
, 'sublings(index) returns correct sibling (single collection, lastChild)'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).children(2)
, '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(3),'
, 'sublings(index) returns correct children (multi collection, lastChildren)'
)
assert.hasExactElements(
T(Q('#fixtures > ul:first-child')).children(3)
, '#fixtures > ul:nth-child(1) > li:nth-child(4),'
, 'sublings(index) returns correct sibling (single collection, midChild)'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).children(2)
, '#fixtures > ul:nth-child(1) > li:nth-child(3),'
+ '#fixtures > ul:nth-child(2) > li:nth-child(3),'
, 'sublings(index) returns children (multi collection, midChildren)'
)
}
, 'children(selector, index)': function () {
assert.hasExactElements(
T([]).children('*', 0)
, '#foobar'
, 'children(*,0) on empty collection returns empty collection'
)
assert.hasExactElements(
T([]).children('*', 10)
, '#foobar'
, 'children(*,10) on empty collection returns empty collection'
)
assert.hasExactElements(
T(Q('#fixtures > ul:first-child')).children('*', 1)
, '#fixtures > ul:first-child > li:nth-child(2)'
, 'children(*,1) on returns correct element (after)'
)
assert.hasExactElements(
T(Q('#fixtures > ul:first-child')).children('*', 1)
, '#fixtures > ul:first-child > li:nth-child(2)'
, 'children(*,1) on returns correct element (before)'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).children('*', 1)
, '#fixtures > ul:nth-child(1) > li:nth-child(2)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(2)'
, 'children(*,1) on returns correct element (after, multi)'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).children('*', 20)
, '#foobar'
, 'children(*, 29) on returns empty collection'
)
assert.hasExactElements(
T(Q('#fixtures ul')).children('.c', 1)
, '#fixtures > ul:nth-child(1) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(1) li li:nth-child(4)'
+ ',#fixtures > ul:nth-child(2) > li:nth-child(4)'
+ ',#fixtures > ul:nth-child(2) > li li:nth-child(4)'
, 'children(.c, 2) on returns correct elements (complex, multi-depth selector)'
)
}
}
, 'closest()': {
'closest() no-arg returns empty set': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).closest()
, '#foobar'
, 'closest() with no arguments returns empty set'
)
assert.hasExactElements(
T(Q('#foobar')).closest()
, '#foobar'
, 'closest() on empty set with no arguments returns empty set'
)
assert.hasExactElements(
T(Q('#foobar')).closest('*')
, '#foobar'
, 'closest(*) on empty set with no arguments returns empty set'
)
}
, 'closest(index) === up(index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li')).closest(0)
, '#fixtures > ul > li'
, 'closest(0) returns same elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).closest(1)
, '#fixtures > ul > li > ul > li:nth-child(4)'
, 'closest(1) moves up to parent node'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).closest(5)
, '#fixtures'
, 'closest(5) on two elements moved to *single* common ancestor node for both'
)
}
, 'closest(selector, index) === up(selector, index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).closest('span', 0)
, '#fixtures > ul > li > ul > li > span'
, 'closest("span", 0) returns same elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).closest('li', 0)
, '#fixtures > ul > li > ul > li:nth-child(4)'
, 'closest("li", 0) returns empty set'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).closest('li', 1)
, '#fixtures > ul > li:nth-child(4)'
, 'closest("li", 1) moves to second li parentNode (3rd actual parentNode) of both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).closest('li.c', 1)
, '#fixtures > ul > li:nth-child(4)'
, 'closest("li.c", 1) moves to second li parentNode with class "c" (3rd actual parentNode) of both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).closest('li, ul', 2)
, '#fixtures > ul > li:nth-child(4)'
, 'closest("li, ul", 2) moves to 3rd parentNode, either <li> or <ul> of both elements'
)
}
, 'closest(selector, index) === up(selector, index) returns unique elements': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).closest('#fixtures', 0)
, '#fixtures'
, 'closest("#fixtures", 0) moves up to common (single) parent node of both elements'
)
}
, 'closest(selector) === up(selector)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).closest('li')
, '#fixtures > ul:nth-child(1) > li > ul > li:nth-child(4), #fixtures > ul > li > ul > li:nth-child(4)'
, 'closest("li") on two deep elements matches parent <li> ancestor elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).closest('*')
, '#fixtures > ul > li > ul > li > span'
, 'closest("*") returns same elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).closest('ul, li')
, '#fixtures > ul:nth-child(1) > li > ul > li:nth-child(4), #fixtures > ul > li > ul > li:nth-child(4)'
, 'closest("ul, li") on two deep elements matches parent <li> ancestor elements'
)
}
}
}
+3
-2

@@ -13,5 +13,6 @@ var config = module.exports

, './test/noconflict.js'
, './src/traversty.js'
, './traversty.js'
, './test/setup.js'
, './test/common.js'
, './test/traversal.js'
, './test/filters.js'
]

@@ -18,0 +19,0 @@ , tests: [

+16
-1
.PHONY: build test server
build:
@node build.js
@echo "Minified size before: "
@echo -n "\t"
@du -b ./traversty.min.js
@gzip ./traversty.min.js
@echo -n "\t"
@du -b ./traversty.min.js.gz
@gunzip ./traversty.min.js.gz
@jshint ./traversty.js
@uglifyjs ./traversty.js > ./traversty.min.js
@echo "Minified size after: "
@echo -n "\t"
@du -b ./traversty.min.js
@gzip ./traversty.min.js
@echo -n "\t"
@du -b ./traversty.min.js.gz
@gunzip ./traversty.min.js.gz

@@ -6,0 +21,0 @@ test:

{
"name": "traversty"
, "description": "Library agnostic utility for traversing the DOM"
, "version": "0.0.7"
, "homepage": "https://github.com/rvagg/traversty"
, "author": "Rod Vagg <rod@vagg.org> @rvagg"
, "keywords": ["ender", "dom", "nodes"]
, "main": "./traversty.js"
, "ender": "./src/ender.js"
, "repository": {
"type": "git"
, "url": "https://github.com/rvagg/traversty.git"
"name" : "traversty"
, "description" : "Library agnostic utility for DOM collection management and traversal"
, "version" : "1.0.0"
, "homepage" : "https://github.com/rvagg/traversty"
, "authors" : [
"Rod Vagg @rvagg <rod@vagg.org> (https://github.com/rvagg)"
]
, "keywords" : ["ender", "dom", "nodes", "traversal"]
, "main" : "./traversty.js"
, "ender" : "./ender_bridge.js"
, "repository" : {
"type" : "git"
, "url" : "https://github.com/rvagg/traversty.git"
}
, "devDependencies": {
"buster": "*"
, "devDependencies" : {
"buster" : "*"
}
, "license" : "MIT"
}
+439
-94

@@ -1,17 +0,29 @@

Traversty &mdash; headache-free DOM traversal
=============================================
# Traversty &mdash; headache-free DOM collection management and traversal
Traversty is a library-agnostic DOM traversal utility giving you 4 flexible methods for moving around the DOM.
Traversty is a library-agnostic DOM utility for traversal and element collection manipulation. Traversty doesn't provide any DOM manipulation features, instead, Traversty is used for managing collections of DOM elements and navigating the DOM.
Inspired by [Prototype](http://prototypejs.org)'s excelent "DOM traversal toolkit", you get `up()`, `down()`, `next()` and `previous()` with optional `selector` and `index` arguments, all in a multi-element environment (jQuery-like rather than Prototype's single-element implementation).
<a href="#api"><i>Just show me the API!</i></a>
Traversty is designed primarily to be integrated in an [Ender](http://ender.no.de/) build, to augment what's already available in [Bonzo](https://github.com/ded/bonzo) but can just as easily be used as a stand-alone utility.
## Traversal
Example usage
-------------
The core DOM traversal methods are inspired by [Prototype](http://prototypejs.org)'s excelent "DOM traversal toolkit", you get <a href="#up"><code>up()</code></a>, <a href="#down"><code>down()</code></a>, <a href="#next"><code>next()</code></a> and <a href="#previous"><code>previous()</code></a> with optional `selector` and `index` arguments, all in a multi-element environment&mdash;jQuery-like rather than Prototype's single-element implementation.
*This code is used Traversty Ender integration tests and depends on Bonzo*
In addition, jQuery-compatible traversal methods extend this functionality: <a href="#parents"><code>parents()</code></a>, <a href="#closest"><code>closest()</code></a>, <a href="#children"><code>children()</code></a>, <a href="#siblings"><code>siblings()</code></a> and <a href="#prev"><code>prev()</code></a> a simple alias for <a href="#previous"><code>previous()</code></a>.
## Collection filtering
Traversty operates on DOM element collections, jQuery-style, so it also gives you methods to filter and manipulate that collection. The filtering methods are designed to be jQuery-compatible. You get: <a href="#first"><code>first()</code></a>, <a href="#last"><code>last()</code></a>, <a href="#eq"><code>eq()</code></a>, <a href="#not"><code>not()</code></a>, <a href="#slice"><code>slice()</code></a>, <a href="#filter"><code>filter()</code></a>, <a href="#has"><code>has()</code></a> and <a href="#is"><code>is()</code></a> (this last method returns a boolean rather than a collection).
Traversty emulates an Array and includes additional methods to help you manage it as if it were one: <a href="#get"><code>get()</code></a>, <a href="#toArray"><code>toArray()</code></a>, <a href="#size"><code>size()</code></a>, <a href="#push"><code>push()</code></a>, <a href="#sort"><code>sort()</code></a>, <a href="#splice"><code>splice()</code></a>.
Traversty is designed to be integrated in an [Ender](http://ender.no.de/) build, to augment what's already available in [Bonzo](https://github.com/ded/bonzo) but can just as easily be used as a stand-alone utility.
## Example usage
This bit of crazyness comes from Traversty's integration tests. The bulk of this code is used to test Traversty's integration with Ender where the `css()` method is provided by [Bonzo](https://github.com/ded/bonzo) but there is also a [vanilla version](https://github.com/rvagg/traversty/blob/master/test/integration/traversty_css_qwery.html) with only [Qwery](https://github.com/ded/qwery) for the selector engine and a `css()` method added using Traversty's <a href="#aug"><code>aug()</code></a> method (see the [/examples/aug-css.js](https://github.com/rvagg/traversty/blob/master/examples/aug-css.js) file for how this is done).
```js
$('#root > ul') // can match multiple elements
var $ = traversty
$.setSelectorEngine(qwery)
$('#fixtures > ul') // Traversty operates on collecitons of elements
.down(0).css('color', 'red')

@@ -21,25 +33,70 @@ .next('li', 1).css('color', 'green')

.next().down().css('color', 'yellow')
.up(2).next().css('color', 'purple');
.up(2).next().css('color', 'purple')
.siblings(3).css('fontWeight', 'bold')
.children().css('textDecoration', 'underline')
.children(1).css('borderLeft', 'solid 5px red')
.parents('*').filter('ul').css('borderTop', 'dashed 2px green')
.not('.second').css('borderBottom', 'solid 3px blue')
.down('.second li').has('span').css('marginTop', '10px')
.up('ul').eq(-1).css('borderLeft', 'solid 5px orange')
.closest('#fixtures').down('li').slice(-10,-9).css('fontSize', '25px')
// Note: the css() method is not native to Traversty but is added with aug()
```
The return type from the `traversty()` method is not a true `Array` but can be used like an array in almost all respects, it has `.length` and `[]` subscript element access and other standard `Array` methods.
API
---
<a href="#api"></a>
## API
### Main: `traversty(elements || selector)` ###
* <a href="#ctor"><code><b>traversty()</b></code></a>
* <a href="#next"><code>traversty().<b>next()</b></code></a>
* <a href="#previous"><code>traversty().<b>previous()</b></code></a>
* <a href="#previous"><code>traversty().<b>prev()</b></code></a>
* <a href="#up"><code>traversty().<b>up()</b></code></a>
* <a href="#parents"><code>traversty().<b>parents()</b></code></a>
* <a href="#closest"><code>traversty().<b>closest()</b></code></a>
* <a href="#down"><code>traversty().<b>down()</b></code></a>
* <a href="#children"><code>traversty().<b>children()</b></code></a>
* <a href="#siblings"><code>traversty().<b>siblings()</b></code></a>
* <a href="#first"><code>traversty().<b>first()</b></code></a>
* <a href="#last"><code>traversty().<b>last()</b></code></a>
* <a href="#eq"><code>traversty().<b>eq()</b></code></a>
* <a href="#slice"><code>traversty().<b>slice()</b></code></a>
* <a href="#filter"><code>traversty().<b>filter()</b></code></a>
* <a href="#not"><code>traversty().<b>not()</b></code></a>
* <a href="#has"><code>traversty().<b>has()</b></code></a>
* <a href="#is"><code>traversty().<b>is()</b></code></a>
* <a href="#get"><code>traversty().<b>get()</b></code></a>
* <a href="#each"><code>traversty().<b>each()</b></code></a>
* <a href="#toArray"><code>traversty().<b>toArray()</b></code></a>
* <a href="#size"><code>traversty().<b>size()</b></code></a>
* <a href="#push"><code>traversty().<b>push()</b></code></a>
* <a href="#sort"><code>traversty().<b>sort()</b></code></a>
* <a href="#splice"><code>traversty().<b>splice()</b></code></a>
* <a href="#aug"><code>traversty.<b>aug()</b></code></a>
* <a href="#setSelectorEngine"><code>traversty.<b>setSelectorEngine()</b></code></a>
* <a href="#noConflict"><code>traversty.<b>noConflict()</b></code></a>
Gives you a new Traversty instance containing the DOM elements you provide, allowing you to call any of the following methods. You can give a single DOM element or an array of DOM elements. If you provide a string argument it will be used as a selector to either query the DOM via the browser's native `querySelectorAll()` implementation or use a selector engine which you provide (see below).
--------------------------------------------------------
<a name="ctor"></a>
### traversty(element | elements | selector)
<code>traversty()</code> gives you a new Traversty instance containing the elements you provide.
Individual elements are available with array accessors, e.g. `traversty(document.body)[0] // → document.body`
Once you have a collection, you can call any of the Traversty methods on that collection. You can give a single DOM element or an array of DOM elements. If you provide a string argument it will be used as a selector to either query the DOM via the browser's native `querySelectorAll()` implementation or use a selector engine which you provide (see <a href="#setSelectorEngine"><code>setSelectorEngine()</code></a>).
When included in an Ender build, `$(elements || selector)` does the same thing.
You can pluck individual elements with array accessors (subscript), e.g. `traversty(document.body)[0] // → document.body`
### Next: `traversty(elements).next([selector = "*"[, index = 0]])` ###
When included in an Ender build, `$(element | elements | selector)` does the same thing and all the Traversty methods will be available on the resulting Ender object.
* `selector` *(String)* is an optional CSS selector (defaults to `'*'`, i.e. match all elements)
--------------------------------------------------------
<a name="next"></a>
### next([selector [, index = 0]])
<code>traversty(elements).next()</code> returns a new Traversty instance containing *nextSibling* elements according to the arguments provided.
* `selector` *(String)* is an optional CSS selector
* `index` *(Number)* is an optional array-ish index argument (defaults to `0`, i.e. first match)
Returns a new Traversty instance wrapped around the resulting DOM elements. You will get elements that match the given *selector* (or '*') starting from the *nextSibling* of the starting element(s), all the way across to the last *nextSibling*.
You will get elements that match the given *selector* (if provided) starting from the *nextSibling* of the starting element(s), all the way across to the last *nextSibling*.
If no `index` or `selector` is given then you get just the *nextSibling*s of the elements.
If no `index` or `selector` is given then you get just the *nextSibling*s of the elements; i.e. you shift *across* by one.

@@ -53,14 +110,19 @@ If just an `index` is provided then you'll get the `index+1` *nextSibling*s of the element(s). i.e. `index` is 0-based, like arrays, 0 is *nextSibling* and 1 is *nextSibling.nextSibling*, unless you provide a `selector` of course, in which case it'll skip over non-matching elements.

```js
traversty('li:first-child').next(); // → returns the second `<li>` of every list in the document
traversty('li.allstarts').next('li', 1); // → returns the `nextSibling` of the `nextSibling` of the starting elements
traversty('li:first-child').next('li'); // → returns all `<li>` elements, except for the first-children of every lits in the document
traversty('li:first-child').next();
// → returns the second `<li>` of every list in the document
traversty('li.allstarts').next('li', 1);
// → returns the `nextSibling` of the `nextSibling` of the starting elements
traversty('li:first-child').next('li');
// → returns all `<li>` elements, except for the first-children of every lits in the document
```
--------------------------------------------------------
<a name="previous"></a>
### previous([selector [, index = 0]])
<code>traversty(elements).previous()</code> returns a new Traversty instance containing *previousSibling* elements according to the arguments provided.
### Previous: `traversty(elements).previous([selector = "*"[, index = 0]])` ###
* `selector` *(String)* is an optional CSS selector (defaults to `'*'`, i.e. match all elements)
* `selector` *(String)* is an optional CSS selector
* `index` *(Number)* is an optional array-ish index argument (defaults to `0`, i.e. first match)
Exactly the same as `.next()` except it works on *previousSibling*, so you move backwards amongst sibling elements.
Exactly the same as <a href="#next"><code>next()</code></a> except it works on *previousSibling*, so you move *backwards* amongst sibling elements.

@@ -70,13 +132,25 @@ #### Examples ####

```js
traversty('li:nth-child(20)').previous(); // → returns 19th child of the every list in the document (where it exists)
traversty('li.allstarts').previous('li', 1); // → returns the `previousSibling` of the `previousSibling` of the starting element
traversty('li:nth-child(20)').previous('.interesting'); // → returns all `<li>` elements with class "interesting" up to the 19th child of every list in the document where there are at least 20 children.
traversty('li:nth-child(20)').previous();
// → returns 19th child of the every list in the document (where it exists)
traversty('li.allstarts').previous('li', 1);
// → returns the `previousSibling` of the `previousSibling` of the starting element
traversty('li:nth-child(20)').previous('.interesting');
// → returns all `<li>` elements with class "interesting" up to the 19th child of every list
// in the document where there are at least 20 children.
```
### Up: `traversty(elements).up([selector = "*"[, index = 0]])` ###
--------------------------------------------------------
<a name="prev"></a>
### prev([selector [, index = 0]])
<code>traversty(elements).prev()</code> is a simple alias for <a href="#previous"><code>previous()</code></a>, provided mainly for jQuery compatibility.
* `selector` *(String)* is an optional CSS selector (defaults to `'*'`, i.e. match all elements)
--------------------------------------------------------
<a name="up"></a>
### up([selector [, index = 0]])
<code>traversty(elements).up()</code> returns a new Traversty instance containing *parentNode* elements according to the arguments provided.
* `selector` *(String)* is an optional CSS selector
* `index` *(Number)* is an optional array-ish index argument (defaults to `0`, i.e. first match)
Similar to `next()` and `previous()` except that it works on *parentNode*s and will continue all the up to the document root depending on what you're asking for.
Similar to <a href="#next"><code>next()</code></a> and <a href="#previous"><code>previous()</code></a> except that it works on *parentNode*s and will continue all the up to the document root depending on what you're asking for.

@@ -89,16 +163,44 @@ If no `index` or `selector` is given then you get just the `parentNode*s of the elements.

#### Examples ####
```js
traversty('li#start').up(); // → returns the `<ul>` parent element
traversty('li.allstarts').up('ul', 1); // → returns the grandparent `<ul>` elements if the start elements are nested at two levels
traversty('li.allstarts').up('ul'); // → returns all ancestor `<ul>` elements, no matter how deep the nesting
traversty('li#start').up();
// → returns the `<ul>` parent element
traversty('li.allstarts').up('ul', 1);
// → returns the grandparent `<ul>` elements if the start elements are nested at two levels
traversty('li.allstarts').up('ul');
// → returns all ancestor `<ul>` elements, no matter how deep the nesting
```
### Down: `traversty(elements).down([selector = "*"[, index = 0]])` ###
--------------------------------------------------------
<a name="parents"></a>
### parents([selector = '*' [, index ]])
<code>traversty(elements).parents()</code> returns a new Traversty instance containing *parentNode* elements according to the arguments provided, similar, but not identical to <a href="#up"><code>up()</code></a>.
* `selector` *(String)* is an optional CSS selector (defaults to `'*'`, i.e. match all elements)
* `selector` *(String)* is an optional CSS selector (defaults to `'*'`, i.e. match *all* ancestor elements)
* `index` *(Number)* is an optional array-ish index argument (defaults to `0`, i.e. first match)
Performs exactly the same as <a href="#up"><code>up()</code></a>, *except*, the `'selector'` argument defaults to `'*'` which has the effect of matching *all* ancestor elements, not just the first one. `parents()` will return exactly the same collection as `up('*')`. Provided mainly for jQuery compatibility.
--------------------------------------------------------
<a name="closest"></a>
### closest([selector = '*' [, index = 0]])
<code>traversty(elements).closest()</code> returns a new Traversty instance containing the elements and/or *parentNode* elements according to the arguments provided, similar, but not identical to <a href="#parents"><code>parents()</code></a>.
* `selector` *(String)* is an optional CSS selector (defaults to `'*'`, i.e. match *all* ancestor elements)
* `index` *(Number)* is an optional array-ish index argument (defaults to `0`, i.e. the current element)
Performs exactly the same operation as <a href="#parents"><code>parents()</code></a> except for two important differences:
* Matching starts at the **current** elements rather than the direct parent elements. So a `closest('*')` will return the current elements because they match the selector `'*'`.
* The `index` argument defaults to `0`, just like <a href="#up"><code>up()</code></a>, so you will only get the first match. An index of `n`, you will get the *nth* match, start with the current elements.
--------------------------------------------------------
<a name="down"></a>
### down([selector [, index = 0]])
<code>traversty(elements).down()</code> returns a new Traversty instance containing descendent elements according to the arguments provided.
* `selector` *(String)* is an optional CSS selector
* `index` *(Number)* is an optional array-ish index argument (defaults to `0`, i.e. first match)
While `down()` is very similar to the other methods, it's perhaps best to think of it as what you might get with a `find()` method from a selector engine.

@@ -112,3 +214,3 @@

<ul id="root">
<li>fisrt</li> <!-- 0 -->
<li>first</li> <!-- 0 -->
<li>second</li> <!-- 1 -->

@@ -121,3 +223,3 @@ <li>third <!-- 2 -->

</ul>
</ul>
</li>
<li>fourth</li> <!-- 7 -->

@@ -130,4 +232,6 @@ </ul>

```js
traversty('#root').down(5) // → will give you `<li>ii</li>`
traversty('#root').down('li', 5) // → will give you `<li>i</li>` because the `<ul>` is ignored:w
traversty('#root').down(5)
// → will give you `<li>ii</li>`
traversty('#root').down('li', 5)
// → will give you `<li>i</li>` because the `<ul>` is ignored
```

@@ -138,27 +242,281 @@

I want a demo!
--------------
--------------------------------------------------------
<a name="children"></a>
### children([selector [, index = 0]])
<code>traversty(elements).children()</code> returns a new Traversty instance containing direct descendent (child) elements according to the arguments provided.
You'll have to make do with the integration tests. [Here](http://rvagg.github.com/traversty/test/integration/ender_qwery.html) is Traversty running in an Ender build with Qwery and Bonzo. You can also see it running with [Sel](http://rvagg.github.com/traversty/test/integration/ender_sel.html), [Sizzle](http://rvagg.github.com/traversty/test/integration/ender_sizzle.html), [NWMatcher](http://rvagg.github.com/traversty/test/integration/ender_nwmatcher.html) and [without a selector engine](http://rvagg.github.com/traversty/test/integration/ender_sel.html) (works in modern browsers, including IE9+).
```html
<ul id="root">
<li>first
<ul>
<li><a href="#">i</a></li>
<li>ii
<ul>
<li>a</li>
<li>b</li>
</ul>
</li>
<li>iii</li>
<li>iv</li>
</ul>
</li>
<li>second</li>
</ul>
```
View-source to see what it's doing, note that it's operating on 2 lists at the same time.
```js
traversty('#root > li').children()
// → will give you *only* the second level `<ul>` element as it's
// the only direct descendent of the top `<li>` elements
traversty('#root > li').children().children()
// → will give you *only* the second level `<li>` elements and none
// of their children
```
--------------------------------------------------------
<a name="siblings"></a>
### siblings([selector [, index = 0]])
<code>traversty(elements).siblings()</code> returns a new Traversty instance containing *previousSibling* and *nextSibling* elements according to the arguments provided. It's important to note that the resulting collection **will not** include the original elements unless they are siblings of each other. To illustrate:
Things to note
--------------
```html
<ul id="root">
<li>first</li>
<li>second</li>
<li>third</li>
<li>fourth</li>
</ul>
```
* Traversty always does a **uniqueness** check on its collection of elements so you should never end up with duplicates. If you did a `traversty('body,ul').down('li')` you would still only get a unique list of all *<li>* elements in the document.
```js
traversty('#root :nth-child(2)').siblings()
// → will give you all `<li>` elements except the second
traversty('#root :nth-child(2n)').siblings()
// → will give you all `<li>` elements because they are all siblings of
// the original collection's elements
```
* Traversty ignores text and comment nodes and should only ever operate on the DOM element nodes you would expect (i.e. with *nodeType==1*).
`siblings()` is the only method in Traversty that is not guaranteed to return a collection of elements in document-order (i.e. in the order they appear in the HTML). If you call `siblings()` on elements that are already siblings then the collection mechanism may mean that the results are out of order. Generally this shouldn't matter but you are warned if order matters to you for some reason.
* Traversty currently orders results (for each element in the starting list) in document-order, so `previous('*')` will give you results starting from the *firstChild* of the parent element up to the *previousSibling* of the starting element, rather than starting with the *previousSibling* and listing backwards (this doesn't impact on indexing, which still works backwards, only the order of result lists). This may change, I haven't decided yet!
### Supported browsers ###
--------------------------------------------------------
<a name="first"></a>
### first()
<code>traversty(elements).first()</code> returns a new Traversty instance containing *only* the first element in the original collection.
Traversty is tested with IE6+, Firefox 3+, Safari 4+, Opera current and Chrome current. You'll need a supported selector engine to operate on some of these older browsers. See below.
--------------------------------------------------------
<a name="last"></a>
### last()
<code>traversty(elements).last()</code> returns a new Traversty instance containing *only* the last element in the original collection.
--------------------------------------------------------
<a name="eq"></a>
### eq(index)
<code>traversty(elements).eq()</code> returns a new Traversty instance containing *only* the element at the index specified.
Selector engines
----------------
Indexes are zero-based and can also be negative. A negative index will count backwards from the end of the collection.
```html
<ul id="root">
<li>first</li>
<li>second</li>
<li>third</li>
<li>fourth</li>
</ul>
```
```js
traversty('#root li').eq(1)
// → will give you `<li>second</li>`
traversty('#root li').eq(-2)
// → will give you `<li>third</li>`
```
--------------------------------------------------------
<a name="slice"></a>
### slice(start [, end])
<code>traversty(elements).slice()</code> returns a new Traversty instance containing *only* the elements between the `start` and `end` indexes. The `end` is optional, if left out then elements from `start` to the end of the collection are included.
Indexes are zero-based and can also be negative. A negative index will count backwards from the end of the collection. See the example above for <a href="#eq"><code>eq()</code></a> for how this works.
--------------------------------------------------------
<a name="filter"></a>
### filter(selector | function | element)
<code>traversty(elements).filter()</code> returns a new Traversty instance containing *only* the elements that satisfy the filter condition.
A `selector` string argument will simply check each element against the selector and return only elements that match.
A `function` argument will execute that function for each element in the collection and return only elements for which it receives a *truthy* response from the function. `this` within the function will be the element being checked and the single argument to the function will be the index within the collection.
An `element` argument will return a collection containing only that DOM element *only if * it exists within the collection.
```html
<ul id="root">
<li>first
<ul>
<li><a href="#">i</a></li>
<li>ii
<ul>
<li>a</li>
<li>b</li>
</ul>
</li>
<li>iii</li>
<li>iv</li>
</ul>
</li>
<li>second</li>
</ul>
```
```js
var els = traversty('#root *')
// → start off with all 12 descendent elements under #root
els = els.filter('li')
// → returns only the 8 `<li>` elements within the collection
els = els.filter(function () { return /^i/.test(this.innerHTML) })
// → returns only the 3 `<li>` elements start have content starting with 'i'
// i.e. only 'ii', 'iii' and 'iv' (not 'i')
els = els.filter(traversty('#root ul > li')[1])
// → we're using `traversty()` here as a simple selector to fetch the 'iii' element
// which we pass in to `filter()`. Because this element is in the collection we get
// back a collection with only this element.
```
--------------------------------------------------------
<a name="not"></a>
### not(selector | function | element)
<code>traversty(elements).not()</code> returns a new Traversty instance containing *only* the elements that **do not** satisfy the filter condition.
`not()` is the exact inverse of <a href="#filter"><code>filter()</code></a>, it takes the same arguments but returns only elements that don't match your conditions.
--------------------------------------------------------
<a name="has"></a>
### has(selector | element)
<code>traversty(elements).has()</code> returns a new Traversty instance containing *only* the elements that have descendent elements that match the provided `selector` argument, or have `element` as a descendent element.
If a `selector` string argument is provided, each element in the collection effectively has a `find(selector)`-type operation performed on it, if any matching descendent elements are found, the parent element is retained for the new collection; otherwise it is not included.
If an `element` argument is provided then the only element included in the resulting collection is an ancestor of that `element`, if the `element` is not a descendent of any of the elements in the collection then the resulting collection will be empty.
```html
<ul id="root">
<li>first
<ul>
<li><a href="#">i</a></li>
<li>ii
<ul>
<li>a</li>
<li>b</li>
</ul>
</li>
<li>iii</li>
<li>iv</li>
</ul>
</li>
<li>second</li>
</ul>
```
```js
var els = traversty('#root *')
// → start off with all 12 descendent elements under #root
els = els.has('li')
// → returns a collection of 4 elements which have `<li>` descendents: the 'first' `<li>`,
// the `<ul>` directly under it, the 'ii' `<li>` and the `<ul>` directly under that.
els.has(traversty('#root a')[0])
// → we're using `traversty()` here as a simple selector to fetch the `<a>` element
// which we pass in to `has()`. There are two elements that have this single element
// as a descendent, the 'first' `<li>` element and the `<ul>` directly under it.
```
--------------------------------------------------------
<a name="is"></a>
### is(selector | function | element)
<code>traversty(elements).is()</code> returns a **boolean** indicating whether at least one of the elements within the collection matches the condition. The method should be thought of as a version of <a href="#filter"><code>filter()</code></a> that returns a boolean if the resulting collection has at least one element; i.e. `traversty(elements).filter(condition).length > 0`.
--------------------------------------------------------
<a name="each"></a>
### each(function [, thisContext])
<code>traversty(elements).each()</code> will execute the provided `function` on each of the elements in the current collection. `each()` will return the original collection so you can continue chaining method calls.
Your `function` will be called with `this` equal to the individual elements or the `thisContext` argument if supplied. The arguments provided to the function are:
1. `element`: the current element in the collection
2. `index`: the index of the current element in the collection
3. `collection`: the entire Traversty object for this collection
Note the ordering of arguments 1 and 2 are different to the <a href="http://api.jquery.com/each/"><code>jQuery().each()</code></a>, instead Traversty is closer to ES5 <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach"><code>Array.prototype.forEach</code></a>.
```js
traversty('li').each(function (el, i) {
this.innerHTML += ' (I am ' + i + ')'
})
```
--------------------------------------------------------
<a name="get"></a>
### get(index)
<code>traversty(elements).get()</code> returns a single DOM element at the specified index of the collection. Indexes are zero-based and can be negative. See <a href="#eq"><code>eq()</code></a> for specifics.
--------------------------------------------------------
<a name="toArray"></a>
### toArray()
<code>traversty(elements).toArray()</code> returns a true `Array` object containing elements within the collection. See [MDN](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array) for details on what you get.
--------------------------------------------------------
<a name="size"></a>
### size()
<code>traversty(elements).size()</code> returns an number indicating the number of elements in the collection. Works exactly the same as `.length` on an `Array` (indeed, you can call `.length` on a Traversty object and get the same value).
--------------------------------------------------------
<a name="push"></a>
### push(element1 [, element2 [...]])
<code>traversty(elements).push()</code> reuses `Array.prototype.push`. See [MDN](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/push) for details.
Beware of pushing non-DOM elements onto a Traversty object! This is not supported behaviour.
--------------------------------------------------------
<a name="sort"></a>
### sort([compareFunction])
<code>traversty(elements).sort()</code> reuses `Array.prototype.sort` to sort the collection. See [MDN](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/sort) for details.
--------------------------------------------------------
<a name="splice"></a>
### splice(index, howMany [, element1 [...]])
<code>traversty(elements).splice()</code> reuses `Array.prototype.splice` to splice the collection. See [MDN](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/splice) for details.
--------------------------------------------------------
<a name="aug"></a>
### aug(methodMap)
<code>traversty.aug()</code> extends Traversty's functionality with custom methods off the main Traversty prototype. The `methodMap` is simply a map of method names to functions. The functions will respond when called off a collection: `traversty().method(args)`.
```js
traversty.aug({ append: function (element) {
// make sure we return 'this', which we can get from each()
return this.each(function (el, i) {
// append original to first element, append a clone to the rest
el.appendChild(i > 0 ? element.cloneNode(true) : element)
})
}})
var span = document.createElement('span')
span.innerHTML = 'BOOM!'
traversty('li').append(span)
```
--------------------------------------------------------
<a name="setSelectorEngine"></a>
### setSelectorEngine(selectorEngine)
<code>traversty.setSelectorEngine()</code> injects a selector engine for Traversty to use. See the next section for details.
## Selector engines
Traversty should work out-of-the-box on modern browsers as it leverages native `querySelectorAll()` and `matchesSelector()` where they exist. This means that you should be able to use Traversty without a selector engine on most smartphone browsers without any problems.

@@ -168,6 +526,4 @@

### `traversty.setSelectorEngine(engine)` ###
Traversty allows you to plug in your favourite selector engine so it can work on whatever browsers your engine supports. Traversty is tested to support [Qwery](https://github.com/ded/qwery), [Sel](https://github.com/amccollum/sel), [Sizzle](https://github.com/jquery/sizzle) and [NWMatcher](https://github.com/dperini/nwmatcher).
Traversty allows you to plug in your favourite selector engine so it can work on whatever browser your engine supports. Out of the box, Traversty is tested to support [Qwery](https://github.com/ded/qwery), [Sel](https://github.com/amccollum/sel), [Sizzle](https://github.com/jquery/sizzle) and [NWMatcher](https://github.com/dperini/nwmatcher).
Traversty uses *feature detection* to figure out how to use your selector engine, it tries to find the method used to *find* elements given a element root and the method used to determine if an element *matches* a given selector. If it can't figure out how to use your selector engine then you just need to pretend that it works like one of the supported ones and it should be OK.

@@ -193,65 +549,54 @@

Ender integration
-----------------
## I want a demo!
Traversty is designed to be inserted into an Ender build. It's in NPM so simply include it in your build command, something like: `ender build sel bonzo traversty`
You'll have to make do with the integration tests. [Here](http://rvagg.github.com/traversty/test/integration/ender_qwery.html) is Traversty running in an Ender build with Qwery and Bonzo. You can also see it running with [Sel](http://rvagg.github.com/traversty/test/integration/ender_sel.html), [Sizzle](http://rvagg.github.com/traversty/test/integration/ender_sizzle.html), [NWMatcher](http://rvagg.github.com/traversty/test/integration/ender_nwmatcher.html) and [without a selector engine](http://rvagg.github.com/traversty/test/integration/ender_sel.html) (works in modern browsers, including IE9+).
Traversty will attempt to use whatever selector engine you've included in your Ender build.
View-source to see what it's doing, note that it's operating on 2 lists at the same time.
### What about Bonzo? ###
Traversty is designed to add to the goodness you get in Bonzo, although Bonzo isn't a dependency. Bonzo has `next()` and `previous()` already and it is intended that Traversty replace these in your ender build. Argument-less they should do exactly the same thing but Traversty adds the extra arguments for greater flexibility. If you are using Bonzo in Ender along with Traversty then you should make sure Traversty is included *after* Bonzo. Unfortunately, [Ender doesn't guarantee order](https://github.com/ender-js/Ender/issues/63) so you may have to fiddle a bit.
## Things to note
### Additional sugar ###
* Traversty always does a **uniqueness** check on its collection of elements so you should never end up with duplicates. If you do a `traversty('body,ul').down('li')` you would still only get a unique list of all *<li>* elements in the document.
In addition to `up()`, `down()`, `next()`, and `previous()` you'll also get aliases which take the same argument types: `parent()` (same as `up()`), `prev()` (same as `previous()`).
* Traversty ignores text and comment nodes and should only ever operate on the DOM element nodes you would expect (i.e. with `.nodeType === 1`).
Contributing
------------
* Traversty currently orders results (for each element in the starting list) in document-order, so `previous('*')` will give you results starting from the *firstChild* of the parent element up to the *previousSibling* of the starting element, rather than starting with the *previousSibling* and listing backwards (this doesn't impact on indexing, which still works backwards, only the order of result lists). The single **exception** to this is <a href="#siblings"><code>siblings()</code></a>, see the note in that section for details.
Awesome! Just do it, fork and submit your pull requests and they will be promptly considered.
## Supported browsers
I'd also love it if you could contribute tests for bugs you find or features you add.
Traversty is tested with IE6+, Firefox 3+, Safari 4+, Opera current and Chrome current. You'll need a supported selector engine to operate on some of these older browsers.
While I'm not a coding-style nazi but I do like consistency. I've chosen a particular style for this project (not my usual style, I have a Java background, I'm experimenting with style!) and I'd prefer to keep it consistent.
### Tests ###
## Ender integration
Traversty uses [Buster](http://busterjs.org) for unit testing.
Traversty is designed to be inserted into an Ender build. It's in npm so simply include it in your build command, something like: `ender build sel bonzo traversty`
#### Client/server ####
Traversty will attempt to use whatever selector engine you've included in your Ender build.
This works by running a server for you to attach browsers to so you can submit all tests to be run in all of the attached browsers right from the command-line.
### What about Bonzo?
Simply do this:
Traversty is designed to add to the goodness you get in Bonzo, although Bonzo isn't a dependency. Bonzo has `next()` and `previous()` and a few other methods already and it is intended that Traversty replace these in your Ender build (because they are way-better!). Argument-less they should do exactly the same thing but Traversty adds the extra arguments for greater flexibility. If you are using Bonzo in Ender along with Traversty then you should make sure Traversty is included *after* Bonzo. Unfortunately, [Ender doesn't guarantee order](https://github.com/ender-js/Ender/issues/63) so you may have to fiddle a bit. The Ender 1.0 CLI does correct ordering but that's not formally released yet, you can use it by installing ender via npm with `npm install ender@dev`.
```
$ sudo npm install buster -g # install Buster if you haven't already got it
$ make server # will start the Buster server for you on port 1111.
$ # point a bunch of browsers to that server, including older versions of IE (start your VMs!)
$ make test # will submit the tests to the Buster server to be run on those browsers
```
You'll see a nice output with the results of the tests as they happen.
## Contributing
#### Static ####
Awesome! Just do it, fork and submit your pull requests and they will be promptly considered.
Since Buster is still in Beta, the capture-server is a bit buggy and can be frustrating. So, an alternative testing method is to simply run the *index.html* file in the *tests* directory in each of the browsers you need to test. It'll load and run the same tests as the capture-server approach.
I'd also love it if you could contribute tests for bugs you find or features you add.
### Where are your semi-colons? ###
### Tests
Oh, you noticed that? Just think of this as my [The Cat in the Hat](http://en.wikipedia.org/wiki/The_Cat_in_the_Hat) project. It's an experiment in how difficult it is to write valid JavaScript devoid of semi-colons. There's only a couple of awkward constructions that could do with a `for` loop, but I don't think it's a big deal.
Traversty uses [Buster](http://busterjs.org) for unit testing.
Since Buster is still in Beta, the capture-server/client is a bit buggy and can be frustrating. So, instead, simply run *index.html* file in the *tests* directory in each of the browsers you need to test. It'll load and run all of the tests.
Credits
-------
## Credits
* Firstly, much credit should go to the awesome Prototype guys and their excellent API that I've ripped off.
* Thanks to [@ded](http://github.com/ded) and [@fat](http://github.com/fat) for Ender, particularly @ded for Bonzo, upon which Traversty is designed to build.
The bulk of the work is done by me, Rod Vagg, [@rvagg](http://twitter.com/rvagg)
Licence
-------
## Licence
Blah, Blah, MIT
Traversty is Copyright (c) 2012 Rod Vagg [@rvagg](https://twitter.com/rvagg) and licenced under the MIT licence. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.
/*global Q:true, T:true, traversty:true, buster:true, assert:true, __matchesSelector:true*/
buster.testCase('traversty', {
'noConflict': function () {

@@ -45,3 +44,51 @@ assert.equals(traversty(), 'success')

}
}
)
, 'toArray()': function () {
var a = T(Q('#foobar')).toArray()
assert(a instanceof Array)
assert.equals(a, [])
a = T(Q('#fixtures')).toArray()
assert(a instanceof Array)
assert.equals(a, [ Q('#fixtures')[0] ])
a = T(Q('#fixtures > ul > li:nth-child(2)')).toArray()
assert(a instanceof Array)
assert.equals(a, [ Q('#fixtures > ul:nth-child(1) > li:nth-child(2)')[0], Q('#fixtures > ul:nth-child(2) > li:nth-child(2)')[0] ])
}
, 'size()': function () {
assert.same(T(Q('#foobar')).size(), 0)
assert.same(T(Q('#fixtures')).size(), 1)
assert.same(T(Q('#fixtures > ul > li:nth-child(2)')).size(), 2)
assert.same(T(Q('#fixtures > ul > li')).size(), 10)
}
, 'aug()': function () {
T.aug({ 'foobar': function () {
for (var i = 0; i < this.length; i++) {
this[i].setAttribute('data-foobar', String(i))
}
return this
}})
T(Q('#fixtures li')).foobar()
var els = Q('#fixtures li'), i = 0
for (i = 0; i < els.length; i++)
assert.equals(els[i].getAttribute('data-foobar'), String(i))
}
, 'each()': function () {
var els = Q('#fixtures li')
, spy = this.spy()
, i = 0
, t = T(Q('#fixtures li')).each(spy)
assert.equals(t.length, els.length)
assert.equals(spy.callCount, els.length)
for (; i < els.length; i++) {
assert.same(spy.getCall(i).thisValue, els[i], 'call ' + i + ' called with correct `this`')
assert.same(spy.getCall(i).args[0], els[i], 'call ' + i + ' called with correct first arg')
assert.same(spy.getCall(i).args[1], i, 'call ' + i + ' called with correct first arg')
assert.same(spy.getCall(i).args[2], t, 'call ' + i + ' called with correct first arg')
}
}
})

@@ -1,2 +0,2 @@

/*global commonTests:true, buster:true, T:true, Q:true, Sizzle:true, NW:true, sel:true, loadES5Basic:true, __matchesSelector:true*/
/*global traversalTests:true, filterTests:true, buster:true, T:true, Q:true, Sizzle:true, NW:true, sel:true, loadES5Basic:true, __matchesSelector:true*/

@@ -10,4 +10,19 @@ var own = Object.prototype.hasOwnProperty

}
, linkTests = function (engine, name, setUp, tests) {
var test, tc
for (test in tests) {
if (own.call(tests, test)) {
// *copy* from tests
tc = extend(tests[test], {})
// don't set a setUp if we're native
if (!!engine) tc.setUp = setUp
buster.testCase('(' + name + ') ' + test, tc)
}
}
}
, engineTest = function (engine, name, customSetUp) {
var test, tc, performedSetUp = false
var performedSetUp = false
// setUp for each test calls setSelectorEngine() with the given engine

@@ -27,11 +42,4 @@ , setUp = function () {

for (test in commonTests) {
if (own.call(commonTests, test)) {
// *copy* from commonTests
tc = extend(commonTests[test], {})
// don't set a setUp if we're native
if (!!engine) tc.setUp = setUp
buster.testCase('(' + name + ') ' + test, tc)
}
}
linkTests(engine, name, setUp, traversalTests)
linkTests(engine, name, setUp, filterTests)
}

@@ -38,0 +46,0 @@

@@ -20,6 +20,7 @@ <!DOCTYPE HTML>

<script src="../src/traversty.js"></script>
<script src="../traversty.js"></script>
<script src="setup.js"></script>
<script src="common.js"></script>
<script src="traversal.js"></script>
<script src="filters.js"></script>

@@ -26,0 +27,0 @@ <script src="core-test.js"></script>

@@ -14,2 +14,12 @@ <!doctype html>

.up(2).next().css('color', 'purple')
.siblings(3).css('fontWeight', 'bold')
.children().css('textDecoration', 'underline')
.children(1).css('borderLeft', 'solid 5px red')
.parents('*').filter('ul').css('borderTop', 'dashed 2px green')
.not('.second').css('borderBottom', 'solid 3px blue')
.down('.second li').has('span').css('marginTop', '10px')
.up('ul').eq(-1).css('borderLeft', 'solid 5px orange')
.closest('#fixtures').down('li').slice(-10,-9).css('fontSize', '25px')
if ($('li').is('.c') === true) $.create('<div>INTEGRATION TEST ALL DONE!</div>').prependTo('#fixtures')
})

@@ -29,3 +39,3 @@ </script>

<li class="c">FOUR
<ul>
<ul class="second">
<li>i</li>

@@ -46,3 +56,3 @@ <li class="c">ii</li>

<li class="c">four
<ul>
<ul class="second">
<li>1</li>

@@ -58,12 +68,10 @@ <li class="c">2</li>

</ul>
<div id="flat">
<p>P1</p>
<span>S1</span>
<div>D1</div>
<p>P2</p>
<span>S2</span>
<div>D2</div>
</div>
</div>
<div id="reference">
<h2>Reference screenshot</h2>
<p>The above block should look similar to this:</p>
<img src="integration_reference.png" style="border: 1px solid rgb(100,100,100); box-shadow: 2px 2px 15px rgb(100,100,100);">
</div>
<p>See also:</p>

@@ -70,0 +78,0 @@ <ul>

@@ -5,2 +5,3 @@ /*!

* Build: ender build domready bonzo ../.. --output ender_noselector
* Packages: ender-js@0.4.4 domready@0.2.11 bonzo@1.2.4 traversty@0.0.7
* =============================================================

@@ -11,7 +12,7 @@ */

* Ender: open module JavaScript framework (client-lib)
* copyright Dustin Diaz & Jacob Thornton 2011 (@ded @fat)
* copyright Dustin Diaz & Jacob Thornton 2011-2012 (@ded @fat)
* http://ender.no.de
* License MIT
*/
!function (context) {
(function (context) {

@@ -28,8 +29,11 @@ // a global object for node.js module compatiblity

var modules = {}
, old = context.$
, 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("Requested module '" + identifier + "' has not been defined.")
var module = modules['$' + identifier] || window[identifier]
if (!module) throw new Error("Ender Error: Requested module '" + identifier + "' has not been defined.")
return module

@@ -39,3 +43,3 @@ }

function provide (name, what) {
return (modules[name] = what)
return (modules['$' + name] = what)
}

@@ -51,39 +55,71 @@

function boosh(s, r, els) {
/**
* 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 == 'string' || s.nodeName || (s.length && 'item' in s) || s == window) {
els = ender._select(s, r)
els.selector = s
} else els = isFinite(s.length) ? s : [s]
return aug(els, boosh)
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 boosh(s, r)
return new Ender(s, r)
}
aug(ender, {
_VERSION: '0.3.6'
, fn: boosh // for easy compat to jQuery plugins
, ender: function (o, chain) {
aug(chain ? boosh : ender, o)
}
, _select: function (s, r) {
return (r || document).querySelectorAll(s)
}
})
ender['_VERSION'] = '0.4.3-dev'
aug(boosh, {
forEach: function (fn, scope, i) {
// 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(scope || this[i], this[i], i, this)
// return self for chaining
return this
},
$: ender // handy reference to self
})
ender.fn = Ender.prototype // for easy compat to jQuery plugins
ender.noConflict = function () {
context.$ = old
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

@@ -94,7 +130,7 @@ }

// use subscript notation as extern for Closure compilation
context['ender'] = context['$'] = context['ender'] || ender
context['ender'] = context['$'] = ender
}(this);
}(this));
!function () {
(function () {

@@ -104,32 +140,105 @@ var module = { exports: {} }, exports = module.exports;

/*!
* Bonzo: DOM Utility (c) Dustin Diaz 2011
* https://github.com/ded/bonzo
* License MIT
* domready (c) Dustin Diaz 2012 - License MIT
*/
!function (name, definition) {
if (typeof module != 'undefined') module.exports = definition()
else if (typeof define == 'function' && define.amd) define(name, definition)
else if (typeof define == 'function' && typeof define.amd == 'object') define(definition)
else this[name] = definition()
}('bonzo', function() {
var context = this
, win = window
}('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;
/*!
* Bonzo: DOM Utility (c) Dustin Diaz 2012
* https://github.com/ded/bonzo
* License MIT
*/
(function (name, definition, context) {
if (typeof module != 'undefined' && module.exports) module.exports = definition()
else if (typeof context['define'] == 'function' && context['define']['amd']) define(name, definition)
else context[name] = definition()
})('bonzo', function() {
var win = window
, doc = win.document
, html = doc.documentElement
, parentNode = 'parentNode'
, query = null
, specialAttributes = /^checked|value|selected$/
, specialTags = /select|fieldset|table|tbody|tfoot|td|tr|colgroup/i
, table = [ '<table>', '</table>', 1 ]
, td = [ '<table><tbody><tr>', '</tr></tbody></table>', 3 ]
, option = [ '<select>', '</select>', 1 ]
, tagMap = {
thead: table, tbody: table, tfoot: table, colgroup: table, caption: table
, tr: [ '<table><tbody>', '</tbody></table>', 2 ]
, query = null // used for setting a selector engine host
, specialAttributes = /^(checked|value|selected|disabled)$/i
, specialTags = /^(select|fieldset|table|tbody|tfoot|td|tr|colgroup)$/i // tags that we have trouble inserting *into*
, 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 }
, stateAttributes = /^checked|selected$/
, 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)

@@ -154,3 +263,3 @@ , hasClass, addClass, removeClass

, transform: function () {
var props = ['webkitTransform', 'MozTransform', 'OTransform', 'msTransform', 'Transform'], i
var props = ['transform', 'webkitTransform', 'MozTransform', 'OTransform', 'msTransform'], i
for (i = 0; i < props.length; i++) {

@@ -161,6 +270,11 @@ 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
, unitless = { lineHeight: 1, zoom: 1, zIndex: 1, opacity: 1 }
, whitespaceRegex = /\s+/
, toString = String.prototype.toString
, unitless = { lineHeight: 1, zoom: 1, zIndex: 1, opacity: 1, boxFlex: 1, WebkitBoxFlex: 1, MozBoxFlex: 1 }
, trim = String.prototype.trim ?

@@ -173,17 +287,41 @@ function (s) {

}
/**
* @param {string} c a class name to test
* @return {boolean}
*/
function classReg(c) {
return new RegExp("(^|\\s+)" + c + "(\\s+|$)")
}
function each(ar, fn, scope) {
for (var i = 0, l = ar.length; i < l; i++) fn.call(scope || ar[i], ar[i], i, ar)
/**
* @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
}
function deepEach(ar, fn, scope) {
/**
* @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, scope)
fn.call(scope || ar[i], ar[i], i, ar)
deepEach(ar[i].childNodes, fn, opt_scope)
fn.call(opt_scope || ar[i], ar[i], i, ar)
}

@@ -193,3 +331,8 @@ }

}
/**
* @param {string} s
* @return {string}
*/
function camelize(s) {

@@ -200,41 +343,78 @@ return s.replace(/-(.)/g, function (m, m1) {

}
/**
* @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)
uid = el[getAttribute]('data-node-uid')
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) {
uid = el[getAttribute]('data-node-uid')
uid && (delete uidMap[uid])
var uid = el[getAttribute]('data-node-uid')
if (uid) delete uidMap[uid]
}
function dataValue(d) {
var f
try {
return d === 'true' ? true : d === 'false' ? false : d === 'null' ? null : !isNaN(d) ? parseFloat(d) : d;
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
}
function isNode(node) {
return node && node.nodeName && node.nodeType == 1
return node && node.nodeName && (node.nodeType == 1 || node.nodeType == 11)
}
function some(ar, fn, scope, i) {
for (i = 0, j = ar.length; i < j; ++i) if (fn.call(scope, ar[i], i, ar)) return true
/**
* @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")) ||
(/^transform-?[Oo]rigin$/.test(p) && (p = features.transform + 'Origin')) ||
(p == 'float' && (p = features.cssFloat))
return p ? camelize(p) : null
}
var getStyle = features.computedStyle ?

@@ -247,13 +427,18 @@ function (el, property) {

} :
(ie && html.currentStyle) ?
/**
* @param {Element} el
* @param {string} property
* @return {string|number}
*/
function (el, property) {
if (property == 'opacity') {
if (property == 'opacity' && !features.opasity) {
var val = 100
try {
val = el.filters['DXImageTransform.Microsoft.Alpha'].opacity
val = el['filters']['DXImageTransform.Microsoft.Alpha'].opacity
} catch (e1) {
try {
val = el.filters('alpha').opacity
val = el['filters']('alpha').opacity
} catch (e2) {}

@@ -266,9 +451,9 @@ }

} :
function (el, property) {
return el.style[property]
}
// this insert method is intense
function insert(target, host, fn) {
function insert(target, host, fn, rev) {
var i = 0, self = host || this, r = []

@@ -279,25 +464,21 @@ // target nodes could be a css selector if it's a string and a selector engine is present

// normalize each node in case it's still a string and we need to create nodes on the fly
each(normalize(nodes), function (t) {
each(normalize(nodes), function (t, j) {
each(self, function (el) {
var n = !el[parentNode] || (el[parentNode] && !el[parentNode][parentNode]) ?
function () {
var c = el.cloneNode(true)
// check for existence of an event cloner
// preferably https://github.com/fat/bean
// otherwise Bonzo won't do this for you
self.$ && self.cloneEvents && self.$(c).cloneEvents(el)
return c
}() : el
fn(t, n)
r[i] = n
i++
})
}, this)
each(r, function (e, i) {
self[i] = e
})
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) {

@@ -310,3 +491,3 @@ var $el = bonzo(el)

, delta = [parseInt($el.css('left'), 10), parseInt($el.css('top'), 10)]
if (style == 'static') {

@@ -316,43 +497,57 @@ $el.css('position', 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,
// so we have to iterate. bullshit
// altho to be fair, the api sucks because it won't accept multiple classes at once
if (features.classList) {
hasClass = function (el, c) {
return some(c.toString().split(' '), function (c) {
return el.classList.contains(c)
})
return el.classList.contains(c)
}
addClass = function (el, c) {
each(c.toString().split(' '), function (c) {
el.classList.add(c)
})
el.classList.add(c)
}
removeClass = function (el, c) { el.classList.remove(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), ' ')) }
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')
// })
/**
* 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) {

@@ -367,65 +562,98 @@ this.length = 0

this.length = elements.length
for (var i = 0; i < elements.length; i++) {
this[i] = elements[i]
}
for (var i = 0; i < elements.length; i++) this[i] = elements[i]
}
}
Bonzo.prototype = {
// indexr method, because jQueriers want this method
/**
* @param {number} index
* @return {Element|Node}
*/
get: function (index) {
return this[index] || null
}
// itetators
, each: function (fn, scope) {
return each(this, fn, scope)
/**
* @param {function(Element|Node)} fn
* @param {Object=} opt_scope
* @return {Bonzo}
*/
, each: function (fn, opt_scope) {
return each(this, fn, opt_scope)
}
, deepEach: function (fn, scope) {
return deepEach(this, fn, scope)
/**
* @param {Function} fn
* @param {Object=} opt_scope
* @return {Bonzo}
*/
, deepEach: function (fn, opt_scope) {
return deepEach(this, fn, opt_scope)
}
, map: function (fn, reject) {
/**
* @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)
reject ? (reject(n) && m.push(n)) : m.push(n)
opt_reject ? (opt_reject(n) && m.push(n)) : m.push(n)
}
return m
}
// text and html inserters!
, html: function (h, text) {
var method = text ?
html.textContent === undefined ?
'innerText' :
'textContent' :
'innerHTML', m;
function append(el) {
each(normalize(h), function (node) {
el.appendChild(node)
})
}
return typeof h !== 'undefined' ?
this.empty().each(function (el) {
!text && (m = el.tagName.match(specialTags)) ?
append(el, m[0]) :
!function() {
try { (el[method] = h) }
catch(e) { append(el) }
}();
}) :
this[0] ? this[0][method] : ''
/**
* @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] : ''
}
, text: function (text) {
return this.html(text, 1)
/**
* @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) {
return this.each(function (el) {
each(normalize(node), function (i) {
var that = this
return this.each(function (el, i) {
each(normalize(node, that, i), function (i) {
el.appendChild(i)

@@ -435,7 +663,13 @@ })

}
/**
* @param {Bonzo|string|Element|Array} node
* @return {Bonzo}
*/
, prepend: function (node) {
return this.each(function (el) {
var that = this
return this.each(function (el, i) {
var first = el.firstChild
each(normalize(node), function (i) {
each(normalize(node, that, i), function (i) {
el.insertBefore(i, first)

@@ -445,18 +679,36 @@ })

}
, appendTo: function (target, host) {
return insert.call(this, target, host, function (t, 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}
*/
, appendTo: function (target, opt_host) {
return insert.call(this, target, opt_host, function (t, el) {
t.appendChild(el)
})
}
, prependTo: function (target, host) {
return insert.call(this, target, host, function (t, 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) {
return this.each(function (el) {
each(bonzo.create(node), function (i) {
var that = this
return this.each(function (el, i) {
each(normalize(node, that, i), function (i) {
el[parentNode].insertBefore(i, el)

@@ -466,71 +718,136 @@ })

}
/**
* @param {Bonzo|string|Element|Array} node
* @return {Bonzo}
*/
, after: function (node) {
return this.each(function (el) {
each(bonzo.create(node), function (i) {
var that = this
return this.each(function (el, i) {
each(normalize(node, that, i), function (i) {
el[parentNode].insertBefore(i, el.nextSibling)
})
}, null, 1)
})
}
, insertBefore: function (target, host) {
return insert.call(this, target, host, function (t, 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}
*/
, insertBefore: function (target, opt_host) {
return insert.call(this, target, opt_host, function (t, el) {
t[parentNode].insertBefore(el, t)
})
}
, insertAfter: function (target, host) {
return insert.call(this, target, host, function (t, 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}
*/
, insertAfter: function (target, opt_host) {
return insert.call(this, target, opt_host, function (t, el) {
var sibling = t.nextSibling
if (sibling) {
t[parentNode].insertBefore(el, sibling);
}
else {
sibling ?
t[parentNode].insertBefore(el, sibling) :
t[parentNode].appendChild(el)
}
})
}, 1)
}
, replaceWith: function(html) {
this.deepEach(clearData)
return this.each(function (el) {
el.parentNode.replaceChild(bonzo.create(html)[0], el)
})
/**
* @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) {
hasClass(el, setter(el, c)) || addClass(el, setter(el, c))
// 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) {
hasClass(el, setter(el, c)) && removeClass(el, setter(el, c))
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 hasClass(el, c)
return some(c, function (c) {
return c && hasClass(el, c)
})
})
}
, toggleClass: function (c, condition) {
/**
* @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) {
typeof condition !== 'undefined' ?
condition ? addClass(el, c) : removeClass(el, c) :
hasClass(el, c) ? removeClass(el, c) : addClass(el, c)
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
, show: function (type) {
/**
* @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 = type || ''
el.style.display = opt_type
})
}
/**
* @return {Bonzo}
*/
, hide: function () {

@@ -541,32 +858,66 @@ return this.each(function (el) {

}
, toggle: function (callback, type) {
this.each(function (el) {
el.style.display = (el.offsetWidth || el.offsetHeight) ? 'none' : type || ''
/**
* @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)
})
callback && callback()
return this
}
// 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')
}
return this.related(parentNode)
}
/**
* @private
* @param {string} method the directional DOM method
* @return {Element|Node}
*/
, related: function (method) {

@@ -586,35 +937,47 @@ return this.map(

}
// meh. use with care. the ones in Bean are better
/**
* @return {Bonzo}
*/
, focus: function () {
return this.length > 0 ? this[0].focus() : null
this.length && this[0].focus()
return this
}
/**
* @return {Bonzo}
*/
, blur: function () {
return this.each(function (el) {
el.blur()
})
this.length && this[0].blur()
return this
}
// style getter setter & related methods
, css: function (o, v, p) {
/**
* @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 (v === undefined && typeof o == 'string') {
if (opt_v === undefined && typeof o == 'string') {
// repurpose 'v'
v = this[0]
if (!v) {
return null
}
if (v === doc || v === win) {
p = (v === doc) ? bonzo.doc() : bonzo.viewport()
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(v, o) : null
return (o = styleProperty(o)) ? getStyle(opt_v, o) : null
}
var iter = o
if (typeof o == 'string') {
iter = {}
iter[o] = v
iter[o] = opt_v
}
if (ie && iter.opacity) {

@@ -627,3 +990,3 @@ // oh this 'ol gamut

}
function fn(el, p, v) {

@@ -635,3 +998,3 @@ for (var k in iter) {

(p = styleProperty(k)) && digit.test(v) && !(p in unitless) && (v += px)
el.style[p] = setter(el, v)
try { el.style[p] = setter(el, v) } catch(e) {}
}

@@ -642,7 +1005,13 @@ }

}
, offset: function (x, y) {
if (typeof x == 'number' || typeof y == 'number') {
/**
* @param {number=} opt_x
* @param {number=} opt_y
* @return {Bonzo|number}
*/
, offset: function (opt_x, opt_y) {
if (typeof opt_x == 'number' || typeof opt_y == 'number') {
return this.each(function (el) {
xy(el, x, y)
xy(el, opt_x, opt_y)
})

@@ -664,4 +1033,9 @@ }

left = left + el.offsetLeft
if (el != doc.body) {
top -= el.scrollTop
left -= el.scrollLeft
}
}
return {

@@ -674,23 +1048,33 @@ top: top

}
/**
* @return {number}
*/
, dim: function () {
if (!this.length) return { height: 0, width: 0 }
var el = this[0]
, orig = !el.offsetWidth && !el.offsetHeight ?
, 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, s) {
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 = el.offsetWidth
, height = el.offsetHeight
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)

@@ -702,5 +1086,11 @@ return {

}
// attributes are hard. go shopping
, attr: function (k, v) {
/**
* @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]

@@ -713,4 +1103,4 @@ if (typeof k != 'string' && !(k instanceof String)) {

}
return typeof v == 'undefined' ?
specialAttributes.test(k) ?
return typeof opt_v == 'undefined' ?
!el ? null : specialAttributes.test(k) ?
stateAttributes.test(k) && typeof el[k] == 'string' ?

@@ -720,6 +1110,11 @@ true : el[k] : (k == 'href' || k =='src') && features.hrefExtended ?

this.each(function (el) {
specialAttributes.test(k) ? (el[k] = setter(el, v)) : el[setAttribute](k, setter(el, v))
specialAttributes.test(k) ? (el[k] = setter(el, opt_v)) : el[setAttribute](k, setter(el, opt_v))
})
}
/**
* @param {string} k
* @return {Bonzo}
*/
, removeAttr: function (k) {

@@ -730,31 +1125,49 @@ return this.each(function (el) {

}
/**
* @param {string=} opt_s
* @return {Bonzo|string}
*/
, val: function (s) {
return (typeof s == 'string') ? this.attr('value', s) : this[0].value
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
, data: function (k, v) {
var el = this[0], uid, o, m
if (typeof v === 'undefined') {
/**
* @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 k === 'undefined') {
each(el.attributes, function(a) {
(m = (''+a.name).match(dattr)) && (o[camelize(m[1])] = dataValue(a.value))
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 {
return typeof o[k] === 'undefined' ?
(o[k] = dataValue(this.attr('data-' + decamelize(k)))) : o[k]
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)[k] = v })
return this.each(function (el) { data(el)[opt_k] = opt_v })
}
}
// DOM detachment & related
/**
* @return {Bonzo}
*/
, remove: function () {
this.deepEach(clearData)
return this.each(function (el) {

@@ -764,7 +1177,11 @@ el[parentNode] && el[parentNode].removeChild(el)

}
/**
* @return {Bonzo}
*/
, empty: function () {
return this.each(function (el) {
deepEach(el.childNodes, clearData)
while (el.firstChild) {

@@ -775,26 +1192,68 @@ el.removeChild(el.firstChild)

}
/**
* @return {Bonzo}
*/
, detach: function () {
return this.map(function (el) {
return el[parentNode].removeChild(el)
return this.each(function (el) {
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 normalize(node) {
return typeof node == 'string' ? bonzo.create(node) : isNode(node) ? [node] : node // assume [nodes]
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
}
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) {

@@ -811,15 +1270,19 @@ return (isBody(el) ? getWindowScroll() : { x: el.scrollLeft, y: el.scrollTop })[type]

}
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 bonzo(els, host) {
return new Bonzo(els, host)
/**
* @param {Array.<Element>|Element|Node|string} els
* @return {Bonzo}
*/
function bonzo(els) {
return new Bonzo(els)
}
bonzo.setQueryEngine = function (q) {

@@ -829,3 +1292,3 @@ query = q;

}
bonzo.aug = function (o, target) {

@@ -837,3 +1300,3 @@ // for those standalone bonzo users. this love is for you.

}
bonzo.create = function (node) {

@@ -848,7 +1311,10 @@ // hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh

, 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 {

@@ -865,6 +1331,5 @@ // tbody special case for IE<8, creates tbody on any empty table

return els
}() : isNode(node) ? [node.cloneNode(true)] : []
}
bonzo.doc = function () {

@@ -877,3 +1342,3 @@ var vp = bonzo.viewport()

}
bonzo.firstChild = function (el) {

@@ -885,3 +1350,3 @@ for (var c = el.childNodes, i = 0, j = (c && c.length) || 0, e; i < j; i++) {

}
bonzo.viewport = function () {

@@ -893,3 +1358,3 @@ return {

}
bonzo.isAncestor = 'compareDocumentPosition' in html ?

@@ -910,11 +1375,10 @@ function (container, element) {

}
return bonzo
})
}, this); // the only line we care about using a semi-colon. placed here for concatenation tools
provide("bonzo", module.exports);
!function ($) {
(function ($) {
var b = require('bonzo')

@@ -929,7 +1393,7 @@ b.setQueryEngine($)

})
$.id = function (id) {
return $([document.getElementById(id)])
}
function indexOf(ar, val) {

@@ -939,3 +1403,3 @@ for (var i = 0; i < ar.length; i++) if (ar[i] === val) return i

}
function uniq(ar) {

@@ -954,5 +1418,7 @@ var r = [], i = 0, j = 0, k, item, inIt

}
$.ender({
parents: function (selector, closest) {
if (!this.length) return this
if (!selector) selector = '*'
var collection = $(selector), j, k, p, r = []

@@ -970,43 +1436,43 @@ for (j = 0, k = this.length; j < k; j++) {

}
, 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 () {

@@ -1022,5 +1488,5 @@ var i, l, p, r = []

}
, children: function () {
var i, el, r = []
var i, l, el, r = []
for (i = 0, l = this.length; i < l; i++) {

@@ -1033,107 +1499,35 @@ if (!(el = b.firstChild(this[i]))) continue;

}
, height: function (v) {
return dimension(v, this, 'height')
return dimension.call(this, 'height', v)
}
, width: function (v) {
return dimension(v, this, 'width')
return dimension.call(this, 'width', v)
}
}, true)
function dimension(v, self, which) {
return v ?
self.css(which, v) :
function (r) {
if (!self[0]) return 0
r = parseInt(self.css(which), 10);
return isNaN(r) ? self[0]['offset' + which.replace(/^\w/, function (m) {return m.toUpperCase()})] : r
}()
}
}(ender);
}();
!function () {
var module = { exports: {} }, exports = module.exports;
!function (name, definition) {
if (typeof define == 'function') define(definition)
else if (typeof module != 'undefined') module.exports = definition()
else this[name] = this['domReady'] = definition()
}('domready', function (ready) {
var fns = [], fn, f = false
, doc = document
, testEl = doc.documentElement
, hack = testEl.doScroll
, domContentLoaded = 'DOMContentLoaded'
, addEventListener = 'addEventListener'
, onreadystatechange = 'onreadystatechange'
, loaded = /^loade|c/.test(doc.readyState)
function flush(f) {
loaded = 1
while (f = fns.shift()) f()
/**
* @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)
}
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)
})
})
}(ender));
}());
provide("domready", module.exports);
(function () {
!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;
/**************************************************************
* Traversty: DOM Traversal Utility (c) Rod Vagg (@rvagg) 2011
* Traversty: DOM Traversal Utility (c) Rod Vagg (@rvagg) 2012
* https://github.com/rvagg/traversty
* License: MIT
*/
!(function (name, definition) {

@@ -1144,3 +1538,3 @@ if (typeof module !== 'undefined') module.exports = definition()

}('traversty', function () {
var context = this

@@ -1156,25 +1550,24 @@ , old = context.traversty

if (el[ms = pfx[i++] + name]) return ms
if (el[name = 'm' + name.substring(1)]) return name
}(html, [ 'ms', 'webkit', 'moz', 'o' ], 'MatchesSelector', 0))
}(html, [ 'msM', 'webkitM', 'mozM', 'oM', 'm' ], 'atchesSelector', 0))
, isNumber = function (o) {
return toString.call(o) === '[object Number]'
}
, isString = function (o) {
return toString.call(o) === '[object String]'
}
, isFunction = function (o) {
return toString.call(o) === '[object Function]'
}
, isUndefined = function (o) {
return o === void 0
}
, isElement = function (o) {
return o && o.nodeType === 1
}
// figure out which argument, if any, is our 'index'

@@ -1185,3 +1578,3 @@ , getIndex = function (selector, index) {

}
// figure out which argument, if any, is our 'selector'

@@ -1191,15 +1584,15 @@ , getSelector = function (selector) {

}
, nativeSelectorFind = function (selector, el) {
return slice.call(el.querySelectorAll(selector), 0)
}
, nativeSelectorMatches = function (selector, el) {
return selector === '*' || el[matchesSelector](selector)
}
, selectorFind = nativeSelectorFind
, selectorMatches = nativeSelectorMatches
// used in the case where our selector engine does out-of-order element returns for

@@ -1220,3 +1613,19 @@ // grouped selectors, e.g. '.class, tag', we need our elements in document-order

}
// is 'element' underneath 'container' somewhere
, 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) { // old smelly browser
while (element = element.parentNode) if (element === container) return 1
return 0
}
// return an array containing only unique elements
, unique = function (ar) {

@@ -1237,22 +1646,30 @@ var a = [], i = -1, j, has

}
// for each element of 'els' execute 'fn' to get an array of elements to collect
, collect = function (els, fn) {
var ret = [], i = 0, l = els.length
while (i < l) ret = ret.concat(fn(els[i++]))
var ret = [], res, i = 0, j, l = els.length, l2
while (i < l) {
j = 0
l2 = (res = fn(els[i], i++)).length
while (j < l2) ret.push(res[j++])
}
return ret
}
, move = function (els, method, selector, index) {
// generic DOM navigator to move multiple elements around the DOM
, move = function (els, method, selector, index, filterFn) {
index = getIndex(selector, index)
selector = getSelector(selector)
return collect(els
, function (el) {
, function (el, elind) {
var i = index || 0, ret = []
if (!filterFn)
el = el[method]
while (el && (index === null || i >= 0)) {
el = el[method]
// ignore non-elements, only consider selector-matching elements
// handle both the index and no-index (selector-only) cases
if (isElement(el) &&
selectorMatches(selector, el) &&
(index === null || i-- === 0)) {
if (isElement(el)
&& (!filterFn || (filterFn === true || filterFn(el, elind)))
&& selectorMatches(selector, el)
&& (index === null || i-- === 0)) {
// this concat vs push is to make sure we add elements to the result array

@@ -1262,2 +1679,3 @@ // in reverse order when doing a previous(selector) and up(selector)

}
el = el[method]
}

@@ -1268,3 +1686,38 @@ return ret

}
// given an index & length, return a 'fixed' index, fixes non-numbers & neative indexes
, eqIndex = function (length, index, def) {
if (index < 0) index = length + index
if (index < 0 || index >= length) return null
return !index && index !== 0 ? def : index
}
// collect elements of an array that match a filter function
, filter = function (els, fn) {
var arr = [], i = 0, l = els.length
for (; i < l; i++)
fn(els[i], i) && arr.push(els[i])
return arr
}
// create a filter function, for use by filter(), is() & not()
// allows the argument to be an element, a function or a selector
, filterFn = function (slfn) {
var to
return isElement(slfn)
? function (el) { return el === slfn }
: (to = typeof slfn) == 'function'
? function (el, i) { return slfn.call(el, i) }
: to == 'string' && slfn.length
? function (el) { return selectorMatches(slfn, el) }
: function () { return false }
}
// fn = !fn
, inv = function (fn) {
return function () {
return !fn.apply(this, arguments)
}
}
, traversty = (function () {

@@ -1279,3 +1732,3 @@ function T(els) {

}
T.prototype = {

@@ -1292,20 +1745,109 @@ down: function (selector, index) {

}
, up: function (selector, index) {
return traversty(move(this, 'parentNode', selector, index))
}
, parents: function () {
return T.prototype.up.apply(this, arguments.length ? arguments : [ '*' ])
}
, closest: function (selector, index) {
if (isNumber(selector)) {
index = selector
selector = '*'
} else if (!isString(selector)) {
return traversty([])
} else if (!isNumber(index)) {
index = 0
}
return traversty(move(this, 'parentNode', selector, index, true))
}
, previous: function (selector, index) {
return traversty(move(this, 'previousSibling', selector, index))
}
, next: function (selector, index) {
return traversty(move(this, 'nextSibling', selector, index))
}
, siblings: function (selector, index) {
var self = this
, arr = slice.call(this, 0)
, i = 0, l = arr.length
for (; i < l; i++) {
arr[i] = arr[i].parentNode.firstChild
while (!isElement(arr[i])) arr[i] = arr[i].nextSibling
}
if (isUndefined(selector))
selector = '*'
return traversty(move(arr, 'nextSibling', selector || '*', index
, function (el, i) { return el !== self[i] } // filter
))
}
, children: function (selector, index) {
return traversty(move(T.prototype.down.call(this), 'nextSibling', selector || '*', index, true))
}
, first: function () {
return T.prototype.eq.call(this, 0)
}
, last: function () {
return T.prototype.eq.call(this, -1)
}
, eq: function (index) {
return traversty((index = eqIndex(this.length, index, 0)) === null ? [] : this[index])
}
// a crazy man wrote this, don't try to understand it, see the tests
, slice: function (start, end) {
var e = end, l = this.length, arr = []
start = eqIndex(l, Math.max(-this.length, start), 0)
e = eqIndex(end < 0 ? l : l + 1, end, l)
end = e === null || e > l ? end < 0 ? 0 : l : e
while (start !== null && start < end)
arr.push(this[start++])
return traversty(arr)
}
, filter: function (slfn) {
return traversty(filter(this, filterFn(slfn)))
}
, not: function (slfn) {
return traversty(filter(this, inv(filterFn(slfn))))
}
// same as filter() but return a boolean so quick-return after first successful find
, is: function (slfn) {
var i = 0, l = this.length
, fn = filterFn(slfn)
for (; i < l; i++)
if (fn(this[i], i)) return true
return false
}
// similar to filter() but cares about descendent elements
, has: function (slel) {
return traversty(filter(
this
, isElement(slel)
? function (el) { return isAncestor(slel, el) }
: typeof slel == 'string' && slel.length
? function (el) { return selectorFind(slel, el).length } //TODO: performance
: function () { return false }
))
}
}
T.prototype.prev = T.prototype.previous
function t(els) {
return new T(isString(els) ? selectorFind(els, doc) : els)
}
t.setSelectorEngine = function (s) {

@@ -1316,2 +1858,3 @@ // feature testing the selector engine like a boss

, select = s.select || s.sel || s
e.innerHTML = '<a/><i/><b/>'

@@ -1326,3 +1869,3 @@ a = e.firstChild

isFunction(s.match) ? function (selector, el) { return s.match(el, selector) } : null
if (!_selectorMatches) {

@@ -1332,15 +1875,16 @@ // perhaps it's an selector(x).is(y) type selector?

_selectorMatches =
isFunction(ss.matching) ? function (selector, el) { return s(el).matching(selector).length > 0 } :
isFunction(ss.is) ? function (selector, el) { return s(el).is(selector) } :
isFunction(ss.matchesSelector) ? function (selector, el) { return s(el).matchesSelector(selector) } :
isFunction(ss.match) ? function (selector, el) { return s(el).match(selector) } : null
isFunction(ss._is) ? function (selector, el) { return s(el)._is(selector) } : // original .is(), replaced by Enderbridge
isFunction(ss.matching) ? function (selector, el) { return s(el).matching(selector).length > 0 } :
isFunction(ss.is) && !ss.is.__ignore ? function (selector, el) { return s(el).is(selector) } :
isFunction(ss.matchesSelector) ? function (selector, el) { return s(el).matchesSelector(selector) } :
isFunction(ss.match) ? function (selector, el) { return s(el).match(selector) } : null
}
if (!_selectorMatches)
throw 'Traversty: couldn\'t find selector engine\'s `matchesSelector`'
// verify that we have a working `matchesSelector`
if (_selectorMatches('x,y', e) || !_selectorMatches('a,p', e))
throw 'Traversty: couldn\'t make selector engine\'s `matchesSelector` work'
// basic select

@@ -1354,3 +1898,3 @@ if ((r = select('b,a', e)).length !== 2) throw 'Traversty: don\'t know how to use this selector engine'

throw 'Traversty: couldn\'t make selector engine work'
selectorMatches = _selectorMatches

@@ -1365,3 +1909,3 @@ selectorFind = _selectorFind

}
t.noConflict = function () {

@@ -1371,20 +1915,19 @@ context.traversty = old

}
return t
}())
return traversty
}))
}));
provide("traversty", module.exports);
/*global ender:true*/
(function ($) {
var t = require('traversty')
, integrated = false
, integrate = function(meth) {
, integrate = function (meth) {
// this crazyness is for lazy initialisation because we can't be guaranteed
// that a selector engine has been installed *before* traversty in an ender build
var fn = function(self, selector, index) {
var fn = function (self, selector, index) {
if (!integrated) {

@@ -1396,28 +1939,23 @@ try {

}
fn = function(self, selector, index) { return $(t(self)[meth](selector, index)) }
fn = meth == 'is'
? function (self, slfn) {
return t(self)[meth](slfn) // boolean
}
: function (self, selector, index) {
return $(t(self)[meth](selector, index)) // collection
}
return fn(self, selector, index)
}
return function(selector, index) { return fn(this, selector, index) }
return function (selector, index) { return fn(this, selector, index) }
}
, up = integrate('up')
, down = integrate('down')
, next = integrate('next')
, previous = integrate('previous')
$.ender(
{
// core
up: up
, down: down
, next: next
, previous: previous
// aliases
, parent: up
, prev: previous
}
, true
)
, methods = 'up down next previous prev parents closest siblings children first last eq slice filter not is has'.split(' ')
, b = {}, i = methods.length
// does this build have an .is()? if so, shift it to _is() for traversty to use and
// allow us to integrate a new is(), wrapped around it
if ($.fn.is) $.fn._is = $.fn.is
while (--i >= 0) b[methods[i]] = integrate(methods[i])
$.ender(b, true)
$.fn.is.__ignore = true
}(ender))
}();
}());

@@ -14,2 +14,12 @@ <!doctype html>

.up(2).next().css('color', 'purple')
.siblings(3).css('fontWeight', 'bold')
.children().css('textDecoration', 'underline')
.children(1).css('borderLeft', 'solid 5px red')
.parents('*').filter('ul').css('borderTop', 'dashed 2px green')
.not('.second').css('borderBottom', 'solid 3px blue')
.down('.second li').has('span').css('marginTop', '10px')
.up('ul').eq(-1).css('borderLeft', 'solid 5px orange')
.closest('#fixtures').down('li').slice(-10,-9).css('fontSize', '25px')
if ($('li').is('.c') === true) $('<div>INTEGRATION TEST ALL DONE!</div>').prependTo('#fixtures')
})

@@ -28,3 +38,3 @@ </script>

<li class="c">FOUR
<ul>
<ul class="second">
<li>i</li>

@@ -45,3 +55,3 @@ <li class="c">ii</li>

<li class="c">four
<ul>
<ul class="second">
<li>1</li>

@@ -57,12 +67,10 @@ <li class="c">2</li>

</ul>
<div id="flat">
<p>P1</p>
<span>S1</span>
<div>D1</div>
<p>P2</p>
<span>S2</span>
<div>D2</div>
</div>
</div>
<div id="reference">
<h2>Reference screenshot</h2>
<p>The above block should look similar to this:</p>
<img src="integration_reference.png" style="border: 1px solid rgb(100,100,100); box-shadow: 2px 2px 15px rgb(100,100,100);">
</div>
<p>See also:</p>

@@ -69,0 +77,0 @@ <ul>

@@ -14,2 +14,12 @@ <!doctype html>

.up(2).next().css('color', 'purple')
.siblings(3).css('fontWeight', 'bold')
.children().css('textDecoration', 'underline')
.children(1).css('borderLeft', 'solid 5px red')
.parents('*').filter('ul').css('borderTop', 'dashed 2px green')
.not('.second').css('borderBottom', 'solid 3px blue')
.down('.second li').has('span').css('marginTop', '10px')
.up('ul').eq(-1).css('borderLeft', 'solid 5px orange')
.closest('#fixtures').down('li').slice(-10,-9).css('fontSize', '25px')
if ($('li').is('.c') === true) $('<div>INTEGRATION TEST ALL DONE!</div>').prependTo('#fixtures')
})

@@ -28,3 +38,3 @@ </script>

<li class="c">FOUR
<ul>
<ul class="second">
<li>i</li>

@@ -45,3 +55,3 @@ <li class="c">ii</li>

<li class="c">four
<ul>
<ul class="second">
<li>1</li>

@@ -57,12 +67,10 @@ <li class="c">2</li>

</ul>
<div id="flat">
<p>P1</p>
<span>S1</span>
<div>D1</div>
<p>P2</p>
<span>S2</span>
<div>D2</div>
</div>
</div>
<div id="reference">
<h2>Reference screenshot</h2>
<p>The above block should look similar to this:</p>
<img src="integration_reference.png" style="border: 1px solid rgb(100,100,100); box-shadow: 2px 2px 15px rgb(100,100,100);">
</div>
<p>See also:</p>

@@ -69,0 +77,0 @@ <ul>

@@ -14,2 +14,12 @@ <!doctype html>

.up(2).next().css('color', 'purple')
.siblings(3).css('fontWeight', 'bold')
.children().css('textDecoration', 'underline')
.children(1).css('borderLeft', 'solid 5px red')
.parents('*').filter('ul').css('borderTop', 'dashed 2px green')
.not('.second').css('borderBottom', 'solid 3px blue')
.down('.second li').has('span').css('marginTop', '10px')
.up('ul').eq(-1).css('borderLeft', 'solid 5px orange')
.closest('#fixtures').down('li').slice(-10,-9).css('fontSize', '25px')
if ($('li').is('.c') === true) $('<div>INTEGRATION TEST ALL DONE!</div>').prependTo('#fixtures')
})

@@ -28,3 +38,3 @@ </script>

<li class="c">FOUR
<ul>
<ul class="second">
<li>i</li>

@@ -45,3 +55,3 @@ <li class="c">ii</li>

<li class="c">four
<ul>
<ul class="second">
<li>1</li>

@@ -57,12 +67,10 @@ <li class="c">2</li>

</ul>
<div id="flat">
<p>P1</p>
<span>S1</span>
<div>D1</div>
<p>P2</p>
<span>S2</span>
<div>D2</div>
</div>
</div>
<div id="reference">
<h2>Reference screenshot</h2>
<p>The above block should look similar to this:</p>
<img src="integration_reference.png" style="border: 1px solid rgb(100,100,100); box-shadow: 2px 2px 15px rgb(100,100,100);">
</div>
<p>See also:</p>

@@ -69,0 +77,0 @@ <ul>

@@ -14,2 +14,12 @@ <!doctype html>

.up(2).next().css('color', 'purple')
.siblings(3).css('fontWeight', 'bold')
.children().css('textDecoration', 'underline')
.children(1).css('borderLeft', 'solid 5px red')
.parents('*').filter('ul').css('borderTop', 'dashed 2px green')
.not('.second').css('borderBottom', 'solid 3px blue')
.down('.second li').has('span').css('marginTop', '10px')
.up('ul').eq(-1).css('borderLeft', 'solid 5px orange')
.closest('#fixtures').down('li').slice(-10,-9).css('fontSize', '25px')
if ($('li').is('.c') === true) $('<div>INTEGRATION TEST ALL DONE!</div>').prependTo('#fixtures')
})

@@ -28,3 +38,3 @@ </script>

<li class="c">FOUR
<ul>
<ul class="second">
<li>i</li>

@@ -45,3 +55,3 @@ <li class="c">ii</li>

<li class="c">four
<ul>
<ul class="second">
<li>1</li>

@@ -57,12 +67,10 @@ <li class="c">2</li>

</ul>
<div id="flat">
<p>P1</p>
<span>S1</span>
<div>D1</div>
<p>P2</p>
<span>S2</span>
<div>D2</div>
</div>
</div>
<div id="reference">
<h2>Reference screenshot</h2>
<p>The above block should look similar to this:</p>
<img src="integration_reference.png" style="border: 1px solid rgb(100,100,100); box-shadow: 2px 2px 15px rgb(100,100,100);">
</div>
<p>See also:</p>

@@ -69,0 +77,0 @@ <ul>

@@ -1,6 +0,6 @@

/*global qwery:true, traversty:true, assert: true, buster:true*/
/*global qwery:true, traversty:true, buster:true*/
var Q = qwery.noConflict()
, T = traversty.noConflict()
, __matchesSelector = (function (el, pfx, name, i, ms) {
this.Q = qwery.noConflict()
this.T = traversty.noConflict()
this.__matchesSelector = (function (el, pfx, name, i, ms) {
while (i < pfx.length)

@@ -11,7 +11,7 @@ if (el[ms = pfx[i++] + name]) return ms

assert.equals.message += ": ${2}";
assert.same.message += ": ${2}";
//assert.equals.message += ": ${2}";
//assert.same.message += ": ${2}";
buster.assertions.add("hasExactElements", {
assert: function (actual, expectedSelector, message) {
assert: function (actual, expectedSelector) {
var i

@@ -28,5 +28,31 @@ this.elements = Q(expectedSelector)

, assertMessage: "Expected ${actual} to be ${elements} (selector: ${1}): ${2}"
});
})
buster.assertions.add("isExactElement", {
assert: function (actual, expectedSelector) {
var i
this.element = Q(expectedSelector)[0]
this.actual = actual
return this.actual === this.element
}
, assertMessage: "Expected ${actual} to be ${element} (selector: ${1}): ${2}"
})
buster.assertions.add("hasExactElementsUnordered", {
assert: function (actual, expectedSelector) {
var i, j, found = 0
this.elements = Q(expectedSelector)
this.actual = []
for (i = 0; i < actual.length; i++)
this.actual.push(actual[i])
if (this.elements.length !== this.actual.length) return false
for (i = 0; i < this.elements.length; i++)
for (j = 0; j < actual.length; j++)
if (this.elements[i] === actual[j]) found++
return found == actual.length
}
, assertMessage: "Expected ${actual} to be ${elements} (selector: ${1}): ${2}"
})
document.body.appendChild((function() {

@@ -87,2 +113,2 @@ var fixtures = document.createElement('div')

return fixtures
}()))
}()))
/**************************************************************
* Traversty: DOM Traversal Utility (c) Rod Vagg (@rvagg) 2011
* Traversty: DOM Traversal Utility (c) Rod Vagg (@rvagg) 2012
* https://github.com/rvagg/traversty

@@ -18,3 +18,4 @@ * License: MIT

, toString = Object.prototype.toString
, slice = Array.prototype.slice
, Ap = Array.prototype
, slice = Ap.slice
// feature test to find native matchesSelector()

@@ -26,2 +27,4 @@ , matchesSelector = (function (el, pfx, name, i, ms) {

, Kfalse = function () { return false }
, isNumber = function (o) {

@@ -86,2 +89,18 @@ return toString.call(o) === '[object Number]'

// is 'element' underneath 'container' somewhere
, 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) { // old smelly browser
while (element = element.parentNode) if (element === container) return 1
return 0
}
// return an array containing only unique elements
, unique = function (ar) {

@@ -103,2 +122,3 @@ var a = [], i = -1, j, has

// for each element of 'els' execute 'fn' to get an array of elements to collect
, collect = function (els, fn) {

@@ -108,3 +128,3 @@ var ret = [], res, i = 0, j, l = els.length, l2

j = 0
l2 = (res = fn(els[i++])).length
l2 = (res = fn(els[i], i++)).length
while (j < l2) ret.push(res[j++])

@@ -115,15 +135,18 @@ }

, move = function (els, method, selector, index) {
// generic DOM navigator to move multiple elements around the DOM
, move = function (els, method, selector, index, filterFn) {
index = getIndex(selector, index)
selector = getSelector(selector)
return collect(els
, function (el) {
, function (el, elind) {
var i = index || 0, ret = []
if (!filterFn)
el = el[method]
while (el && (index === null || i >= 0)) {
el = el[method]
// ignore non-elements, only consider selector-matching elements
// handle both the index and no-index (selector-only) cases
if (isElement(el) &&
selectorMatches(selector, el) &&
(index === null || i-- === 0)) {
if (isElement(el)
&& (!filterFn || filterFn === true || filterFn(el, elind))
&& selectorMatches(selector, el)
&& (index === null || i-- === 0)) {
// this concat vs push is to make sure we add elements to the result array

@@ -133,2 +156,3 @@ // in reverse order when doing a previous(selector) and up(selector)

}
el = el[method]
}

@@ -140,2 +164,37 @@ return ret

// given an index & length, return a 'fixed' index, fixes non-numbers & neative indexes
, eqIndex = function (length, index, def) {
if (index < 0) index = length + index
if (index < 0 || index >= length) return null
return !index && index !== 0 ? def : index
}
// collect elements of an array that match a filter function
, filter = function (els, fn) {
var arr = [], i = 0, l = els.length
for (; i < l; i++)
fn(els[i], i) && arr.push(els[i])
return arr
}
// create a filter function, for use by filter(), is() & not()
// allows the argument to be an element, a function or a selector
, filterFn = function (slfn) {
var to
return isElement(slfn)
? function (el) { return el === slfn }
: (to = typeof slfn) == 'function'
? function (el, i) { return slfn.call(el, i) }
: to == 'string' && slfn.length
? function (el) { return selectorMatches(slfn, el) }
: Kfalse
}
// fn = !fn
, inv = function (fn) {
return function () {
return !fn.apply(this, arguments)
}
}
, traversty = (function () {

@@ -167,2 +226,18 @@ function T(els) {

, parents: function () {
return T.prototype.up.apply(this, arguments.length ? arguments : [ '*' ])
}
, closest: function (selector, index) {
if (isNumber(selector)) {
index = selector
selector = '*'
} else if (!isString(selector)) {
return traversty([])
} else if (!isNumber(index)) {
index = 0
}
return traversty(move(this, 'parentNode', selector, index, true))
}
, previous: function (selector, index) {

@@ -175,4 +250,98 @@ return traversty(move(this, 'previousSibling', selector, index))

}
, siblings: function (selector, index) {
var self = this
, arr = slice.call(this, 0)
, i = 0, l = arr.length
for (; i < l; i++) {
arr[i] = arr[i].parentNode.firstChild
while (!isElement(arr[i])) arr[i] = arr[i].nextSibling
}
if (isUndefined(selector))
selector = '*'
return traversty(move(arr, 'nextSibling', selector || '*', index
, function (el, i) { return el !== self[i] } // filter
))
}
, children: function (selector, index) {
return traversty(move(T.prototype.down.call(this), 'nextSibling', selector || '*', index, true))
}
, first: function () {
return T.prototype.eq.call(this, 0)
}
, last: function () {
return T.prototype.eq.call(this, -1)
}
, eq: function (index) {
return traversty(this.get(index))
}
, get: function (index) {
return this[eqIndex(this.length, index, 0)]
}
// a crazy man wrote this, don't try to understand it, see the tests
, slice: function (start, end) {
var e = end, l = this.length, arr = []
start = eqIndex(l, Math.max(-this.length, start), 0)
e = eqIndex(end < 0 ? l : l + 1, end, l)
end = e === null || e > l ? end < 0 ? 0 : l : e
while (start !== null && start < end)
arr.push(this[start++])
return traversty(arr)
}
, filter: function (slfn) {
return traversty(filter(this, filterFn(slfn)))
}
, not: function (slfn) {
return traversty(filter(this, inv(filterFn(slfn))))
}
// similar to filter() but cares about descendent elements
, has: function (slel) {
return traversty(filter(
this
, isElement(slel)
? function (el) { return isAncestor(slel, el) }
: typeof slel == 'string' && slel.length
? function (el) { return selectorFind(slel, el).length } //TODO: performance
: Kfalse
))
}
// same as filter() but return a boolean so quick-return after first successful find
, is: function (slfn) {
var i = 0, l = this.length
, fn = filterFn(slfn)
for (; i < l; i++)
if (fn(this[i], i)) return true
return false
}
, toArray: function () { return Ap.slice.call(this) }
, size: function () { return this.length }
, each: function (fn, ctx) {
var i = 0, l = this.length
for (; i < l; i++)
fn.call(ctx || this[i], this[i], i, this)
return this
}
// quack like a duck (Array)
, push: Ap.push
, sort: Ap.sort
, splice: Ap.splice
}
T.prototype.prev = T.prototype.previous
function t(els) {

@@ -182,2 +351,14 @@ return new T(isString(els) ? selectorFind(els, doc) : els)

// extend traversty functionality with custom methods
t.aug = function (methods) {
var key, method
for (key in methods) {
method = methods[key]
if (typeof method == 'function') {
T.prototype[key] = method
}
}
}
t.setSelectorEngine = function (s) {

@@ -188,2 +369,3 @@ // feature testing the selector engine like a boss

, select = s.select || s.sel || s
e.innerHTML = '<a/><i/><b/>'

@@ -203,6 +385,7 @@ a = e.firstChild

_selectorMatches =
isFunction(ss.matching) ? function (selector, el) { return s(el).matching(selector).length > 0 } :
isFunction(ss.is) ? function (selector, el) { return s(el).is(selector) } :
isFunction(ss.matchesSelector) ? function (selector, el) { return s(el).matchesSelector(selector) } :
isFunction(ss.match) ? function (selector, el) { return s(el).match(selector) } : null
isFunction(ss._is) ? function (selector, el) { return s(el)._is(selector) } : // original .is(), replaced by Enderbridge
isFunction(ss.matching) ? function (selector, el) { return s(el).matching(selector).length > 0 } :
isFunction(ss.is) && !ss.is.__ignore ? function (selector, el) { return s(el).is(selector) } :
isFunction(ss.matchesSelector) ? function (selector, el) { return s(el).matchesSelector(selector) } :
isFunction(ss.match) ? function (selector, el) { return s(el).match(selector) } : null
}

@@ -245,2 +428,2 @@

return traversty
}))
}));
/**************************************************************
* Traversty: DOM Traversal Utility (c) Rod Vagg (@rvagg) 2011
* Traversty: DOM Traversal Utility (c) Rod Vagg (@rvagg) 2012
* https://github.com/rvagg/traversty
* License: MIT
*/
!function(a,b){typeof module!="undefined"?module.exports=b():typeof define=="function"&&define.amd?define(a,b):this[a]=b()}("traversty",function(){var a=this,b=a.traversty,c=window.document,d=c.documentElement,e=Object.prototype.toString,f=Array.prototype.slice,g=function(a,b,c,d,e){while(d<b.length)if(a[e=b[d++]+c])return e}(d,["msM","webkitM","mozM","oM","m"],"atchesSelector",0),h=function(a){return e.call(a)==="[object Number]"},i=function(a){return e.call(a)==="[object String]"},j=function(a){return e.call(a)==="[object Function]"},k=function(a){return a===void 0},l=function(a){return a&&a.nodeType===1},m=function(a,b){return k(a)&&!h(b)?0:h(a)?a:h(b)?b:null},n=function(a){return i(a)?a:"*"},o=function(a,b){return f.call(b.querySelectorAll(a),0)},p=function(a,b){return a==="*"||b[g](a)},q=o,r=p,s=function(a,b){return function(c,d){if(/,/.test(c)){var e=[],f=-1,g=d.getElementsByTagName("*");while(++f<g.length)l(g[f])&&b(c,g[f])&&e.push(g[f]);return e}return a(c,d)}},t=function(a){var b=[],c=-1,d,e;while(++c<a.length){d=-1,e=!1;while(++d<b.length)if(b[d]===a[c]){e=!0;break}e||b.push(a[c])}return b},u=function(a,b){var c=[],d,e=0,f,g=a.length,h;while(e<g){f=0,h=(d=b(a[e++])).length;while(f<h)c.push(d[f++])}return c},v=function(a,b,c,d){return d=m(c,d),c=n(c),u(a,function(a){var e=d||0,f=[];while(a&&(d===null||e>=0))a=a[b],l(a)&&r(c,a)&&(d===null||e--===0)&&(d===null&&b!=="nextSibling"?f=[a].concat(f):f.push(a));return f})},w=function(){function d(a){this.length=0;if(a){a=t(!a.nodeType&&!k(a.length)?a:[a]);var b=this.length=a.length;while(b--)this[b]=a[b]}}function e(a){return new d(i(a)?q(a,c):a)}return d.prototype={down:function(a,b){return b=m(a,b),a=n(a),w(u(this,function(c){var d=q(a,c);return b===null?d:[d[b]]||[]}))},up:function(a,b){return w(v(this,"parentNode",a,b))},previous:function(a,b){return w(v(this,"previousSibling",a,b))},next:function(a,b){return w(v(this,"nextSibling",a,b))}},e.setSelectorEngine=function(a){var b,d,e,f,g,h=c.createElement("p"),k=a.select||a.sel||a;h.innerHTML="<a/><i/><b/>",e=h.firstChild;try{f=j(a.matching)?function(b,c){return a.matching([c],b).length>0}:j(a.is)?function(b,c){return a.is(c,b)}:j(a.matchesSelector)?function(b,c){return a.matchesSelector(c,b)}:j(a.match)?function(b,c){return a.match(c,b)}:null,f||(b=a("a",h),f=j(b.matching)?function(b,c){return a(c).matching(b).length>0}:j(b.is)?function(b,c){return a(c).is(b)}:j(b.matchesSelector)?function(b,c){return a(c).matchesSelector(b)}:j(b.match)?function(b,c){return a(c).match(b)}:null);if(!f)throw"Traversty: couldn't find selector engine's `matchesSelector`";if(f("x,y",h)||!f("a,p",h))throw"Traversty: couldn't make selector engine's `matchesSelector` work";if((d=k("b,a",h)).length!==2)throw"Traversty: don't know how to use this selector engine";g=d[0]===e?k:s(k,f);if((d=g("b,a",h)).length!==2||d[0]!==e)throw"Traversty: couldn't make selector engine work";r=f,q=g}catch(l){throw i(l)?l:"Traversty: error while figuring out how the selector engine works: "+(l.message||l)}finally{h=null}},e.noConflict=function(){return a.traversty=b,this},e}();return w})
*/!function(e,t){typeof module!="undefined"?module.exports=t():typeof define=="function"&&define.amd?define(e,t):this[e]=t()}("traversty",function(){var e=this,t=e.traversty,n=window.document,r=n.documentElement,i=Object.prototype.toString,s=Array.prototype,o=s.slice,u=function(e,t,n,r,i){while(r<t.length)if(e[i=t[r++]+n])return i}(r,["msM","webkitM","mozM","oM","m"],"atchesSelector",0),a=function(){return!1},f=function(e){return i.call(e)==="[object Number]"},l=function(e){return i.call(e)==="[object String]"},c=function(e){return i.call(e)==="[object Function]"},h=function(e){return e===void 0},p=function(e){return e&&e.nodeType===1},d=function(e,t){return h(e)&&!f(t)?0:f(e)?e:f(t)?t:null},v=function(e){return l(e)?e:"*"},m=function(e,t){return o.call(t.querySelectorAll(e),0)},g=function(e,t){return e==="*"||t[u](e)},y=m,b=g,w=function(e,t){return function(n,r){if(/,/.test(n)){var i=[],s=-1,o=r.getElementsByTagName("*");while(++s<o.length)p(o[s])&&t(n,o[s])&&i.push(o[s]);return i}return e(n,r)}},E="compareDocumentPosition"in r?function(e,t){return(t.compareDocumentPosition(e)&16)==16}:"contains"in r?function(e,t){return t=t.nodeType===9||t==window?r:t,t!==e&&t.contains(e)}:function(e,t){while(e=e.parentNode)if(e===t)return 1;return 0},S=function(e){var t=[],n=-1,r,i;while(++n<e.length){r=-1,i=!1;while(++r<t.length)if(t[r]===e[n]){i=!0;break}i||t.push(e[n])}return t},x=function(e,t){var n=[],r,i=0,s,o=e.length,u;while(i<o){s=0,u=(r=t(e[i],i++)).length;while(s<u)n.push(r[s++])}return n},T=function(e,t,n,r,i){return r=d(n,r),n=v(n),x(e,function(e,s){var o=r||0,u=[];i||(e=e[t]);while(e&&(r===null||o>=0))p(e)&&(!i||i===!0||i(e,s))&&b(n,e)&&(r===null||o--===0)&&(r===null&&t!=="nextSibling"?u=[e].concat(u):u.push(e)),e=e[t];return u})},N=function(e,t,n){return t<0&&(t=e+t),t<0||t>=e?null:!t&&t!==0?n:t},C=function(e,t){var n=[],r=0,i=e.length;for(;r<i;r++)t(e[r],r)&&n.push(e[r]);return n},k=function(e){var t;return p(e)?function(t){return t===e}:(t=typeof e)=="function"?function(t,n){return e.call(t,n)}:t=="string"&&e.length?function(t){return b(e,t)}:a},L=function(e){return function(){return!e.apply(this,arguments)}},A=function(){function r(e){this.length=0;if(e){e=S(!e.nodeType&&!h(e.length)?e:[e]);var t=this.length=e.length;while(t--)this[t]=e[t]}}function i(e){return new r(l(e)?y(e,n):e)}return r.prototype={down:function(e,t){return t=d(e,t),e=v(e),A(x(this,function(n){var r=y(e,n);return t===null?r:[r[t]]||[]}))},up:function(e,t){return A(T(this,"parentNode",e,t))},parents:function(){return r.prototype.up.apply(this,arguments.length?arguments:["*"])},closest:function(e,t){if(f(e))t=e,e="*";else{if(!l(e))return A([]);f(t)||(t=0)}return A(T(this,"parentNode",e,t,!0))},previous:function(e,t){return A(T(this,"previousSibling",e,t))},next:function(e,t){return A(T(this,"nextSibling",e,t))},siblings:function(e,t){var n=this,r=o.call(this,0),i=0,s=r.length;for(;i<s;i++){r[i]=r[i].parentNode.firstChild;while(!p(r[i]))r[i]=r[i].nextSibling}return h(e)&&(e="*"),A(T(r,"nextSibling",e||"*",t,function(e,t){return e!==n[t]}))},children:function(e,t){return A(T(r.prototype.down.call(this),"nextSibling",e||"*",t,!0))},first:function(){return r.prototype.eq.call(this,0)},last:function(){return r.prototype.eq.call(this,-1)},eq:function(e){return A(this.get(e))},get:function(e){return this[N(this.length,e,0)]},slice:function(e,t){var n=t,r=this.length,i=[];e=N(r,Math.max(-this.length,e),0),n=N(t<0?r:r+1,t,r),t=n===null||n>r?t<0?0:r:n;while(e!==null&&e<t)i.push(this[e++]);return A(i)},filter:function(e){return A(C(this,k(e)))},not:function(e){return A(C(this,L(k(e))))},has:function(e){return A(C(this,p(e)?function(t){return E(e,t)}:typeof e=="string"&&e.length?function(t){return y(e,t).length}:a))},is:function(e){var t=0,n=this.length,r=k(e);for(;t<n;t++)if(r(this[t],t))return!0;return!1},toArray:function(){return s.slice.call(this)},size:function(){return this.length},each:function(e,t){var n=0,r=this.length;for(;n<r;n++)e.call(t||this[n],this[n],n,this);return this},push:s.push,sort:s.sort,splice:s.splice},r.prototype.prev=r.prototype.previous,i.aug=function(e){var t,n;for(t in e)n=e[t],typeof n=="function"&&(r.prototype[t]=n)},i.setSelectorEngine=function(e){var t,r,i,s,o,u=n.createElement("p"),a=e.select||e.sel||e;u.innerHTML="<a/><i/><b/>",i=u.firstChild;try{s=c(e.matching)?function(t,n){return e.matching([n],t).length>0}:c(e.is)?function(t,n){return e.is(n,t)}:c(e.matchesSelector)?function(t,n){return e.matchesSelector(n,t)}:c(e.match)?function(t,n){return e.match(n,t)}:null,s||(t=e("a",u),s=c(t._is)?function(t,n){return e(n)._is(t)}:c(t.matching)?function(t,n){return e(n).matching(t).length>0}:c(t.is)&&!t.is.__ignore?function(t,n){return e(n).is(t)}:c(t.matchesSelector)?function(t,n){return e(n).matchesSelector(t)}:c(t.match)?function(t,n){return e(n).match(t)}:null);if(!s)throw"Traversty: couldn't find selector engine's `matchesSelector`";if(s("x,y",u)||!s("a,p",u))throw"Traversty: couldn't make selector engine's `matchesSelector` work";if((r=a("b,a",u)).length!==2)throw"Traversty: don't know how to use this selector engine";o=r[0]===i?a:w(a,s);if((r=o("b,a",u)).length!==2||r[0]!==i)throw"Traversty: couldn't make selector engine work";b=s,y=o}catch(f){throw l(f)?f:"Traversty: error while figuring out how the selector engine works: "+(f.message||f)}finally{u=null}},i.noConflict=function(){return e.traversty=t,this},i}();return A});
var jshintOptions = {
'predef': [ 'define' ]
, 'boss': true
, 'bitwise': true
, 'shadow': true
, 'trailing': true
, 'immed': true
, 'latedef': true
, 'forin': true
, 'curly': false
, 'debug': true
, 'devel': false
, 'evil': false
, 'regexp': false
, 'undef': true
, 'sub': true
, 'white': false
, 'indent': 2
, 'asi': true
, 'laxbreak': true
, 'eqeqeq': true
, 'eqnull': true
, 'browser': true
, 'node': true
, 'laxcomma': true
, 'strict': false
}
require('smoosh')
.config({
'JAVASCRIPT': {
'DIST_DIR': './'
, 'traversty': [
'./src/copyright.js'
, './src/traversty.js'
]
}
, 'JSHINT_OPTS': jshintOptions
}).run().build().analyze()
.config({
'JAVASCRIPT': {
'DIST_DIR': './'
, 'ender': [ './src/ender.js' ]
, 'tests': [
'./buster.js'
, './test/common.js'
, './test/core-test.js'
, './test/engines-test.js'
, './test/noconflict.js'
, './test/setup.js'
]
}
, 'JSHINT_OPTS': jshintOptions
}).run()
/**************************************************************
* Traversty: DOM Traversal Utility (c) Rod Vagg (@rvagg) 2011
* https://github.com/rvagg/traversty
* License: MIT
*/
/*global ender:true*/
(function ($) {
var t = require('traversty')
, integrated = false
, integrate = function(meth) {
// this crazyness is for lazy initialisation because we can't be guaranteed
// that a selector engine has been installed *before* traversty in an ender build
var fn = function(self, selector, index) {
if (!integrated) {
try {
t.setSelectorEngine($)
} catch (ex) { } // ignore exception, we may have an ender build with no selector engine
integrated = true
}
fn = function(self, selector, index) { return $(t(self)[meth](selector, index)) }
return fn(self, selector, index)
}
return function(selector, index) { return fn(this, selector, index) }
}
, up = integrate('up')
, down = integrate('down')
, next = integrate('next')
, previous = integrate('previous')
$.ender(
{
// core
up: up
, down: down
, next: next
, previous: previous
// aliases
, parent: up
, prev: previous
}
, true
)
}(ender))
!(function (name, definition) {
if (typeof module !== 'undefined') module.exports = definition()
else if (typeof define === 'function' && define.amd) define(name, definition)
else this[name] = definition()
}('traversty', function () {
var context = this
, old = context.traversty
, doc = window.document
, html = doc.documentElement
, toString = Object.prototype.toString
, slice = Array.prototype.slice
// feature test to find native matchesSelector()
, matchesSelector = (function (el, pfx, name, i, ms) {
while (i < pfx.length)
if (el[ms = pfx[i++] + name]) return ms
}(html, [ 'msM', 'webkitM', 'mozM', 'oM', 'm' ], 'atchesSelector', 0))
, isNumber = function (o) {
return toString.call(o) === '[object Number]'
}
, isString = function (o) {
return toString.call(o) === '[object String]'
}
, isFunction = function (o) {
return toString.call(o) === '[object Function]'
}
, isUndefined = function (o) {
return o === void 0
}
, isElement = function (o) {
return o && o.nodeType === 1
}
// figure out which argument, if any, is our 'index'
, getIndex = function (selector, index) {
return isUndefined(selector) && !isNumber(index) ? 0 :
isNumber(selector) ? selector : isNumber(index) ? index : null
}
// figure out which argument, if any, is our 'selector'
, getSelector = function (selector) {
return isString(selector) ? selector : '*'
}
, nativeSelectorFind = function (selector, el) {
return slice.call(el.querySelectorAll(selector), 0)
}
, nativeSelectorMatches = function (selector, el) {
return selector === '*' || el[matchesSelector](selector)
}
, selectorFind = nativeSelectorFind
, selectorMatches = nativeSelectorMatches
// used in the case where our selector engine does out-of-order element returns for
// grouped selectors, e.g. '.class, tag', we need our elements in document-order
// so we do it ourselves if need be
, createUnorderedEngineSelectorFind = function(engineSelect, selectorMatches) {
return function (selector, el) {
if (/,/.test(selector)) {
var ret = [], i = -1, els = el.getElementsByTagName('*')
while (++i < els.length) {
if (isElement(els[i]) && selectorMatches(selector, els[i])) ret.push(els[i])
}
return ret
}
return engineSelect(selector, el)
}
}
, unique = function (ar) {
var a = [], i = -1, j, has
while (++i < ar.length) {
j = -1
has = false
while (++j < a.length) {
if (a[j] === ar[i]) {
has = true
break
}
}
if (!has) a.push(ar[i])
}
return a
}
, collect = function (els, fn) {
var ret = [], res, i = 0, j, l = els.length, l2
while (i < l) {
j = 0
l2 = (res = fn(els[i++])).length
while (j < l2) ret.push(res[j++])
}
return ret
}
, move = function (els, method, selector, index) {
index = getIndex(selector, index)
selector = getSelector(selector)
return collect(els
, function (el) {
var i = index || 0, ret = []
while (el && (index === null || i >= 0)) {
el = el[method]
// ignore non-elements, only consider selector-matching elements
// handle both the index and no-index (selector-only) cases
if (isElement(el) &&
selectorMatches(selector, el) &&
(index === null || i-- === 0)) {
// this concat vs push is to make sure we add elements to the result array
// in reverse order when doing a previous(selector) and up(selector)
index === null && method !== 'nextSibling' ? ret = [el].concat(ret) : ret.push(el)
}
}
return ret
}
)
}
, traversty = (function () {
function T(els) {
this.length = 0
if (els) {
els = unique(!els.nodeType && !isUndefined(els.length) ? els : [ els ])
var i = this.length = els.length
while (i--) this[i] = els[i]
}
}
T.prototype = {
down: function (selector, index) {
index = getIndex(selector, index)
selector = getSelector(selector)
return traversty(collect(this
, function (el) {
var f = selectorFind(selector, el)
return index === null ? f : ([ f[index] ] || [])
}
))
}
, up: function (selector, index) {
return traversty(move(this, 'parentNode', selector, index))
}
, previous: function (selector, index) {
return traversty(move(this, 'previousSibling', selector, index))
}
, next: function (selector, index) {
return traversty(move(this, 'nextSibling', selector, index))
}
}
function t(els) {
return new T(isString(els) ? selectorFind(els, doc) : els)
}
t.setSelectorEngine = function (s) {
// feature testing the selector engine like a boss
var ss, r, a, _selectorMatches, _selectorFind
, e = doc.createElement('p')
, select = s.select || s.sel || s
e.innerHTML = '<a/><i/><b/>'
a = e.firstChild
try {
// check to see how we do a matchesSelector
_selectorMatches =
isFunction(s.matching) ? function (selector, el) { return s.matching([el], selector).length > 0 } :
isFunction(s.is) ? function (selector, el) { return s.is(el, selector) } :
isFunction(s.matchesSelector) ? function (selector, el) { return s.matchesSelector(el, selector) } :
isFunction(s.match) ? function (selector, el) { return s.match(el, selector) } : null
if (!_selectorMatches) {
// perhaps it's an selector(x).is(y) type selector?
ss = s('a', e)
_selectorMatches =
isFunction(ss.matching) ? function (selector, el) { return s(el).matching(selector).length > 0 } :
isFunction(ss.is) ? function (selector, el) { return s(el).is(selector) } :
isFunction(ss.matchesSelector) ? function (selector, el) { return s(el).matchesSelector(selector) } :
isFunction(ss.match) ? function (selector, el) { return s(el).match(selector) } : null
}
if (!_selectorMatches)
throw 'Traversty: couldn\'t find selector engine\'s `matchesSelector`'
// verify that we have a working `matchesSelector`
if (_selectorMatches('x,y', e) || !_selectorMatches('a,p', e))
throw 'Traversty: couldn\'t make selector engine\'s `matchesSelector` work'
// basic select
if ((r = select('b,a', e)).length !== 2) throw 'Traversty: don\'t know how to use this selector engine'
// check to see if the selector engine has given us the results in document-order
// and if not, work around it
_selectorFind = r[0] === a ? select : createUnorderedEngineSelectorFind(select, _selectorMatches)
// have we done enough to get a working `selectorFind`?
if ((r = _selectorFind('b,a', e)).length !== 2 || r[0] !== a)
throw 'Traversty: couldn\'t make selector engine work'
selectorMatches = _selectorMatches
selectorFind = _selectorFind
} catch (ex) {
if (isString(ex)) throw ex
throw 'Traversty: error while figuring out how the selector engine works: ' + (ex.message || ex)
} finally {
e = null
}
}
t.noConflict = function () {
context.traversty = old
return this
}
return t
}())
return traversty
}))
/*global Q:true, T:true, buster:true, assert:true*/
// note: `T` is `traversty` and `Q` is `qwery` (selector engine), see setup.js
var commonTests = {
'Simple no-arg traversal': {
'next()': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(1)')).next()
, '#fixtures > ul > li:nth-child(2)'
, 'next() on two elements moved to nextSibling on both'
)
}
, 'previous()': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(4)')).previous()
, '#fixtures > ul > li:nth-child(3)'
, 'previous() on two elements moved to previousSibling on both'
)
}
, 'up()': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(3)')).up()
, '#fixtures > ul'
, 'up() on two elements moved to parentNode on both'
)
}
, 'down()': function () {
assert.hasExactElements(
T(Q('#fixtures > ul')).down()
, '#fixtures > ul > li:nth-child(1)'
, 'down() on two elements moved to the first childNode on both'
)
}
}
, 'Index argument traversal': {
'next(index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(1)')).next(0)
, '#fixtures > ul > li:nth-child(2)'
, 'next(0) on two elements moved to 1st nextSibling element on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(1)')).next(1)
, '#fixtures > ul > li:nth-child(3)'
, 'next(1) on two elements moved to 2nd nextSibling element on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(1)')).next(3)
, '#fixtures > ul > li:nth-child(5)'
, 'next(3) on two elements moved to 3rd nextSibling element on both'
)
}
, 'previous(index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).previous(0)
, '#fixtures > ul > li:nth-child(4)'
, 'previous(0) on two elements moved to 1st previousSibling element on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).previous(1)
, '#fixtures > ul > li:nth-child(3)'
, 'previous(1) on two elements moved to 2nd previousSibling element on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).previous(3)
, '#fixtures > ul > li:nth-child(1)'
, 'previous(3) on two elements moved to 3rd previousSibling element on both'
)
}
, 'up(index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up(0)
, '#fixtures > ul > li > ul > li:nth-child(4)'
, 'up(0) on two elements moved to 1st parentNode on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up(3)
, '#fixtures > ul'
, 'up(3) on two elements moved to 3rd parentNode on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up(4)
, '#fixtures'
, 'up(4) on two elements moved to *single* common ancestor node for both'
)
}
, 'down(index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul')).down(0)
, '#fixtures > ul > li:nth-child(1)'
, 'down(0) on two elements moved to first childNode on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).down(1)
, '#fixtures > ul > li:nth-child(2)'
, 'down(1) on two elements moved to second childNode on both'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).down(9)
, '#fixtures > ul > li > ul > li > span'
, 'down(9) on two elements moved down to 10th descendent in document order'
)
}
}
, 'Selector and index argument traversal': {
'next(selector, index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(1)')).next('li', 1)
, '#fixtures > ul > li:nth-child(3)'
, 'next("li", 1) moves to 2nd nextSibling, both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(1)')).next('.c', 1)
, '#fixtures > ul > li:nth-child(4)'
, 'next(".c", 1) moves to the second nextSibling with class "c", both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(1)')).next('li.c', 2)
, '#fixtures > ul > li:nth-child(5)'
, 'next("li.c", 2) moves to the 3rd nextSibling li with class "c", both elements'
)
assert.hasExactElements(
T(Q('#flat *:nth-child(2)')).next('div, p', 2)
, '#flat *:nth-child(6)'
, 'next("div, p", 2) matches 3rd following <div> or <p>'
)
}
, 'next(selector, index) returns unique elements': function () {
assert.hasExactElements(
T(Q('#flat *:nth-child(-n+2)')).next('div', 1)
, '#flat *:nth-child(6)'
, 'next("div", 1) on two elements matches single 2nd following <div>'
)
}
, 'previous(selector, index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).previous('li', 1)
, '#fixtures > ul > li:nth-child(3)'
, 'previous("li", 1) moves to 2nd previousSibling, both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).previous('.c', 0)
, '#fixtures > ul > li:nth-child(4)'
, 'previous(".c", 0) moves to the first previousSibling with class "c", both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).previous('li.c', 1)
, '#fixtures > ul > li:nth-child(2)'
, 'previous("li.c", 2) moves to the 2nd previousSibling li with class "c", both elements'
)
assert.hasExactElements(
T(Q('#flat *:nth-child(5)')).previous('div, p', 2)
, '#flat *:nth-child(1)'
, 'previous("div, p", 2) matches 3rd preceeding <div> or <p>'
)
}
, 'previous(selector, index) returns unique elements': function () {
assert.hasExactElements(
T(Q('#flat *:nth-child(n+5)')).previous('p', 1)
, '#flat *:nth-child(1)'
, 'previous("p", 1) on two elements matches single 2nd preceeding <p>'
)
}
, 'up(selector, index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up('li', 0)
, '#fixtures > ul > li > ul > li:nth-child(4)'
, 'up("li", 0) moves to first parentNode of both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up('li', 1)
, '#fixtures > ul > li:nth-child(4)'
, 'up("li", 1) moves to second li parentNode (3rd actual parentNode) of both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up('li.c', 1)
, '#fixtures > ul > li:nth-child(4)'
, 'up("li.c", 0) moves to second li parentNode with class "c" (3rd actual parentNode) of both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up('li, ul', 2)
, '#fixtures > ul > li:nth-child(4)'
, 'up("li, ul", 2) moves to 3rd parentNode, either <li> or <ul> of both elements'
)
}
, 'up(selector, index) returns unique elements': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up('#fixtures', 0)
, '#fixtures'
, 'up("#fixtures", 0) moves up to common (single) parent node of both elements'
)
}
, 'down(selector, index)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul')).down('li', 0)
, '#fixtures > ul > li:nth-child(1)'
, 'down("li", 0) moves to first li element in document-order on both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).down('li', 2)
, '#fixtures > ul > li:nth-child(3)'
, 'down("li", 2) moves to third li element in document-order on both elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul')).down('.c', 4)
, '#fixtures > ul > li > ul > li > span'
, 'down(".c", 4) moves to 4th element with class "c" in document-order on both elements'
)
assert.hasExactElements(
T(Q('#fixtures')).down('li', 0)
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
, 'down("li", 0) moves to first li element in document-order on first branch only'
)
assert.hasExactElements(
T(Q('#fixtures')).down('li', 2)
, '#fixtures > ul:nth-child(1) > li:nth-child(3)'
, 'down("li", 2) moves to third li element in document-order on first branch only'
)
assert.hasExactElements(
T(Q('#fixtures')).down('.c', 4)
, '#fixtures > ul:nth-child(1) > li > ul > li > span'
, 'down(".c", 4) moves to 4th element with class "c" in document-order on first branch only'
)
assert.hasExactElements(
T(Q('#fixtures')).down('ul, .c', 3)
, '#fixtures > ul:nth-child(1) > li > ul'
, 'down("ul, .c", 3) moves to 4th <ul> element or element with class "c" in document-order on first branch only'
)
}
, 'down(selector, index) returns unique elements': function () {
assert.hasExactElements(
T(Q('#fixtures, #fixtures > ul:nth-child(1)')).down('li', 0)
, '#fixtures > ul:nth-child(1) > li:nth-child(1)'
, 'down("li", 0) from both root and first child of root moves to first li element in document-order on first branch only'
)
}
}
, 'Selector argument traversal': {
'next(selector)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(1)')).next('li')
, '#fixtures > ul > li:nth-child(n+2)'
, 'next("li") on two first-elements matches all following sibling elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(3)')).next('li')
, '#fixtures > ul > li:nth-child(n+4)'
, 'next("li") on two second-elements matches all following sibling elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(2)')).next('.c')
, '#fixtures > ul > li:nth-child(n+4).c' // nth-child doesn't look for .c children but actual children, so 4 is our next .c (note we have to write our selector with the trailling .c rather than the nicer li.c cause WebKit's nth-child is garbage
, 'next(".c") on two second-elements matches all following sibling elements with class "c"'
)
assert.hasExactElements(
T(Q('#flat *:nth-child(2)')).next('span, p')
, '#flat *:nth-child(4),#flat *:nth-child(5)'
, 'next("span, p") matches all following <span> and <p> sibling elements'
)
}
, 'previous(selector)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).previous('li')
, '#fixtures > ul > li:nth-child(-n+4)' // all but last
, 'previous("li") on two first-elements matches all preceeding sibling elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(3)')).previous('li')
, '#fixtures > ul > li:nth-child(-n+2)' // first 2
, 'previous("li") on two second-elements matches all preceeding sibling elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li:nth-child(5)')).previous('.c')
, '#fixtures > ul > li.c:nth-child(-n+4)' // nth-child doesn't look for .c children but actual children, so 4 is our previous .c
, 'previous(".c") on two second-elements matches all preceeding sibling elements with class "c"'
)
assert.hasExactElements(
T(Q('#flat *:nth-child(5)')).previous('span, p')
, '#flat *:nth-child(-n+2),#flat *:nth-child(4)'
, 'previous("span, p") matches all preceeding <span> and <p> sibling elements'
)
}
, 'up(selector)': function () {
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up('li')
, '#fixtures > ul:nth-child(1) > li:nth-child(4), #fixtures > ul:nth-child(1) > li > ul > li:nth-child(4),#fixtures > ul > li:nth-child(4), #fixtures > ul > li > ul > li:nth-child(4)'
, 'up("li") on two deep elements matches all <li> ancestor elements'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up('*')
, 'html, body, #fixtures, #fixtures > ul:nth-child(1), #fixtures > ul:nth-child(1) > li:nth-child(4), #fixtures > ul:nth-child(1) > li:nth-child(4) > ul, #fixtures > ul:nth-child(1) > li > ul > li:nth-child(4), #fixtures > ul, #fixtures > ul > li:nth-child(4), #fixtures > ul > li:nth-child(4) > ul, #fixtures > ul > li > ul > li:nth-child(4)'
, 'up("*") on two deep elements matches all ancestor elements up to <html>'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li > ul > li > span')).up('ul, li')
, '#fixtures > ul:nth-child(1), #fixtures > ul:nth-child(1) > li:nth-child(4), #fixtures > ul:nth-child(1) > li:nth-child(4) > ul, #fixtures > ul:nth-child(1) > li > ul > li:nth-child(4),#fixtures > ul, #fixtures > ul > li:nth-child(4), #fixtures > ul > li > ul, #fixtures > ul > li > ul > li:nth-child(4)'
, 'up("ul, li") on two deep elements matches all <ul> and <li> ancestor elements'
)
}
, 'down(selector)': function () {
assert.hasExactElements(
T(Q('#fixtures')).down('li')
, '#fixtures li'
, 'down("li") selects all descendent <li> elements, same as qSA'
)
assert.hasExactElements(
T(Q('#fixtures > ul > li')).down('*')
, '#fixtures > ul > li *'
, 'down("*") selects all descendent elements, same as qSA'
)
assert.hasExactElements(
T(Q('#fixtures > ul:nth-child(1)')).down('li, span')
, '#fixtures > ul:nth-child(1) > li:nth-child(-n+4), #fixtures > ul:nth-child(1) > li > ul > li, #fixtures > ul:nth-child(1) > li > ul > li > span, #fixtures > ul:nth-child(1) > li.five'
, 'down("li, span") selects all descendent <li> and <span> elements, same as qSA'
)
}
}
}
/*!
* =============================================================
* Ender: open module JavaScript framework (https://ender.no.de)
* Build: ender build domready qwery bonzo ../.. --output ender_qwery
* Packages: ender-js@0.4.3-dev domready@0.2.11 qwery@3.3.8 bonzo@1.0.6 traversty@0.0.7
* =============================================================
*/
;
/*!
* Ender: open module JavaScript framework (client-lib)
* copyright Dustin Diaz & Jacob Thornton 2011-2012 (@ded @fat)
* http://ender.no.de
* License MIT
*/
(function(e){function s(e){var n=t["$"+e]||window[e];if(!n)throw new Error("Ender Error: Requested module '"+e+"' has not been defined.");return n}function o(e,n){return t["$"+e]=n}function u(e,t){for(var n in t)n!="noConflict"&&n!="_VERSION"&&(e[n]=t[n]);return e}function a(e,t){var n,r;this.selector=e,typeof e=="undefined"?(n=[],this.selector=""):typeof e=="string"||e.nodeName||e.length&&"item"in e||e==window?n=f._select(e,t):n=isFinite(e.length)?e:[e],this.length=n.length;for(r=this.length;r--;)this[r]=n[r]}function f(e,t){return new a(e,t)}e.global=e;var t={},n=e.$,r=e.require,i=e.provide;e.provide=o,e.require=s,a.prototype.forEach=function(e,t){var n,r;for(n=0,r=this.length;n<r;++n)n in this&&e.call(t||this[n],this[n],n,this);return this},a.prototype.$=f,f._VERSION="0.4.3-dev",f.fn=a.prototype,f.ender=function(e,t){u(t?a.prototype:f,e)},f._select=function(e,t){return typeof e=="string"?(t||document).querySelectorAll(e):e.nodeName?[e]:e},f.noConflict=function(t){return e.$=n,t&&(e.provide=i,e.require=r,t(s,o,this)),this},typeof module!="undefined"&&module.exports&&(module.exports=f),e.ender=e.$=e.ender||f}(this)),function(){var e={exports:{}},t=e.exports;
/*!
* domready (c) Dustin Diaz 2012 - License MIT
*/
!function(t,n){typeof e!="undefined"?e.exports=n():typeof define=="function"&&typeof define.amd=="object"?define(n):this[t]=n()}("domready",function(e){function h(e){c=1;while(e=t.shift())e()}var t=[],n,r=!1,i=document,s=i.documentElement,o=s.doScroll,u="DOMContentLoaded",a="addEventListener",f="onreadystatechange",l="readyState",c=/^loade|c/.test(i[l]);return i[a]&&i[a](u,n=function(){i.removeEventListener(u,n,r),h()},r),o&&i.attachEvent(f,n=function(){/^c/.test(i[l])&&(i.detachEvent(f,n),h())}),e=o?function(n){self!=top?c?n():t.push(n):function(){try{s.doScroll("left")}catch(t){return setTimeout(function(){e(n)},50)}n()}()}:function(e){c?e():t.push(e)}}),provide("domready",e.exports),!function(e){var t=require("domready");e.ender({domReady:t}),e.ender({ready:function(e){return t(e),this}},!0)}(ender)}(),function(){var e={exports:{}},t=e.exports;
/*!
* Qwery - A Blazing Fast query selector engine
* https://github.com/ded/qwery
* copyright Dustin Diaz & Jacob Thornton 2012
* MIT License
*/
(function(t,n,r){typeof e!="undefined"&&e.exports?e.exports=n():typeof r["define"]!="undefined"&&r["define"]=="function"&&r.define.amd?define(t,n):r[t]=n()})("qwery",function(){function L(){this.c={}}function D(e){return A.g(e)||A.s(e,"(^|\\s+)"+e+"(\\s+|$)",1)}function P(e,t){var n=0,r=e.length;for(;n<r;n++)t(e[n])}function H(e){for(var t=[],n=0,r=e.length;n<r;++n)$(e[n])?t=t.concat(e[n]):t[t.length]=e[n];return t}function B(e){var t=0,n=e.length,r=[];for(;t<n;t++)r[t]=e[t];return r}function j(e){while(e=e.previousSibling)if(e[u]==1)break;return e}function F(e){return e.match(C)}function I(e,t,n,r,i,s,a,c,h,p,d){var v,m,g,y,b;if(this[u]!==1)return!1;if(t&&t!=="*"&&this[o]&&this[o].toLowerCase()!==t)return!1;if(n&&(m=n.match(f))&&m[1]!==this.id)return!1;if(n&&(b=n.match(l)))for(v=b.length;v--;)if(!D(b[v].slice(1)).test(this.className))return!1;if(h&&Q.pseudos[h]&&!Q.pseudos[h](this,d))return!1;if(r&&!a){y=this.attributes;for(g in y)if(Object.prototype.hasOwnProperty.call(y,g)&&(y[g].name||g)==i)return this}return r&&!R(s,Z(this,i)||"",a)?!1:this}function q(e){return O.g(e)||O.s(e,e.replace(b,"\\$1"))}function R(e,t,n){switch(e){case"=":return t==n;case"^=":return t.match(M.g("^="+n)||M.s("^="+n,"^"+q(n),1));case"$=":return t.match(M.g("$="+n)||M.s("$="+n,q(n)+"$",1));case"*=":return t.match(M.g(n)||M.s(n,q(n),1));case"~=":return t.match(M.g("~="+n)||M.s("~="+n,"(?:^|\\s+)"+q(n)+"(?:\\s+|$)",1));case"|=":return t.match(M.g("|="+n)||M.s("|="+n,"^"+q(n)+"(-|$)",1))}return 0}function U(e,t){var n=[],i=[],s,a,f,l,h,p,d,v,m=t,g=_.g(e)||_.s(e,e.split(N)),y=e.match(T);if(!g.length)return n;l=(g=g.slice(0)).pop(),g.length&&(f=g[g.length-1].match(c))&&(m=K(t,f[1]));if(!m)return n;d=F(l),p=m!==t&&m[u]!==9&&y&&/^[+~]$/.test(y[y.length-1])?function(e){while(m=m.nextSibling)m[u]==1&&(d[1]?d[1]==m[o].toLowerCase():1)&&(e[e.length]=m);return e}([]):m[r](d[1]||"*");for(s=0,a=p.length;s<a;s++)if(v=I.apply(p[s],d))n[n.length]=v;return g.length?(P(n,function(e){W(e,g,y)&&(i[i.length]=e)}),i):n}function z(e,t,n){if(X(t))return e==t;if($(t))return!!~H(t).indexOf(e);var r=t.split(","),i,s;while(t=r.pop()){i=_.g(t)||_.s(t,t.split(N)),s=t.match(T),i=i.slice(0);if(I.apply(e,F(i.pop()))&&(!i.length||W(e,i,s,n)))return!0}return!1}function W(e,t,n,r){function s(e,r,o){while(o=k[n[r]](o,e))if(X(o)&&I.apply(o,F(t[r]))){if(!r)return o;if(i=s(o,r-1,o))return i}}var i;return(i=s(e,t.length-1,e))&&(!r||Y(i,r))}function X(e,t){return e&&typeof e=="object"&&(t=e[u])&&(t==1||t==9)}function V(e){var t=[],n,r;e:for(n=0;n<e.length;++n){for(r=0;r<t.length;++r)if(t[r]==e[n])continue e;t[t.length]=e[n]}return t}function $(e){return typeof e=="object"&&isFinite(e.length)}function J(t){return t?typeof t=="string"?Q(t)[0]:!t[u]&&$(t)?t[0]:t:e}function K(e,t,n){return e[u]===9?e.getElementById(t):e.ownerDocument&&((n=e.ownerDocument.getElementById(t))&&Y(n,e)&&n||!Y(e,e.ownerDocument)&&a('[id="'+t+'"]',e)[0])}function Q(e,t){var i,s,o=J(t);if(!o||!e)return[];if(e===window||X(e))return!t||e!==window&&X(o)&&Y(e,o)?[e]:[];if(e&&$(e))return H(e);if(i=e.match(x)){if(i[1])return(s=K(o,i[1]))?[s]:[];if(i[2])return B(o[r](i[2]));if(et&&i[3])return B(o[n](i[3]))}return a(e,o)}function G(e,t){return function(n){var r,i;if(v.test(n)){e[u]!==9&&((i=r=e.getAttribute("id"))||e.setAttribute("id",i="__qwerymeupscotty"),n='[id="'+i+'"]'+n,t(e.parentNode||e,n,!0),r||e.removeAttribute("id"));return}n.length&&t(e,n,!1)}}var e=document,t=e.documentElement,n="getElementsByClassName",r="getElementsByTagName",i="querySelectorAll",s="useNativeQSA",o="tagName",u="nodeType",a,f=/#([\w\-]+)/,l=/\.[\w\-]+/g,c=/^#([\w\-]+)$/,h=/^\.([\w\-]+)$/,p=/^([\w\-]+)$/,d=/^([\w]+)?\.([\w\-]+)$/,v=/(^|,)\s*[>~+]/,m=/^\s+|\s*([,\s\+\~>]|$)\s*/g,g=/[\s\>\+\~]/,y=/(?![\s\w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^'"]*\]|[\s\w\+\-]*\))/,b=/([.*+?\^=!:${}()|\[\]\/\\])/g,w=/^(\*|[a-z0-9]+)?(?:([\.\#]+[\w\-\.#]+)?)/,E=/\[([\w\-]+)(?:([\|\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/,S=/:([\w\-]+)(\(['"]?([^()]+)['"]?\))?/,x=new RegExp(c.source+"|"+p.source+"|"+h.source),T=new RegExp("("+g.source+")"+y.source,"g"),N=new RegExp(g.source+y.source),C=new RegExp(w.source+"("+E.source+")?"+"("+S.source+")?"),k={" ":function(e){return e&&e!==t&&e.parentNode},">":function(e,t){return e&&e.parentNode==t.parentNode&&e.parentNode},"~":function(e){return e&&e.previousSibling},"+":function(e,t,n,r){return e?(n=j(e))&&(r=j(t))&&n==r&&n:!1}};L.prototype={g:function(e){return this.c[e]||undefined},s:function(e,t,n){return t=n?new RegExp(t):t,this.c[e]=t}};var A=new L,O=new L,M=new L,_=new L,Y="compareDocumentPosition"in t?function(e,t){return(t.compareDocumentPosition(e)&16)==16}:"contains"in t?function(e,n){return n=n[u]===9||n==window?t:n,n!==e&&n.contains(e)}:function(e,t){while(e=e.parentNode)if(e===t)return 1;return 0},Z=function(){var t=e.createElement("p");return(t.innerHTML='<a href="#x">x</a>')&&t.firstChild.getAttribute("href")!="#x"?function(e,t){return t==="class"?e.className:t==="href"||t==="src"?e.getAttribute(t,2):e.getAttribute(t)}:function(e,t){return e.getAttribute(t)}}(),et=!!e[n],tt=e.querySelector&&e[i],nt=function(e,t){var n=[],r,s;try{return t[u]===9||!v.test(e)?B(t[i](e)):(P(r=e.split(","),G(t,function(e,t){s=e[i](t),s.length==1?n[n.length]=s.item(0):s.length&&(n=n.concat(B(s)))})),r.length>1&&n.length>1?V(n):n)}catch(o){}return rt(e,t)},rt=function(e,t){var n=[],i,s,o,a,f,l;e=e.replace(m,"$1");if(s=e.match(d)){f=D(s[2]),i=t[r](s[1]||"*");for(o=0,a=i.length;o<a;o++)f.test(i[o].className)&&(n[n.length]=i[o]);return n}return P(l=e.split(","),G(t,function(e,r,i){f=U(r,e);for(o=0,a=f.length;o<a;o++)if(e[u]===9||i||Y(f[o],t))n[n.length]=f[o]})),l.length>1&&n.length>1?V(n):n},it=function(e){typeof e[s]!="undefined"&&(a=e[s]?tt?nt:rt:rt)};return it({useNativeQSA:!0}),Q.configure=it,Q.uniq=V,Q.is=z,Q.pseudos={},Q},this),provide("qwery",e.exports),function(e){var t=function(e){try{e=require("qwery")}catch(t){e=require("qwery-mobile")}finally{return e}}();e.pseudos=t.pseudos,e._select=function(n,r){return(e._select=function(e){try{return e=require("bonzo"),function(n,r){return/^\s*</.test(n)?e.create(n,r):t(n,r)}}catch(n){}return t}())(n,r)},e.ender({find:function(n){var r=[],i,s,o,u,a;for(i=0,s=this.length;i<s;i++){a=t(n,this[i]);for(o=0,u=a.length;o<u;o++)r.push(a[o])}return e(t.uniq(r))},and:function(t){var n=e(t);for(var r=this.length,i=0,s=this.length+n.length;r<s;r++,i++)this[r]=n[i];return this.length+=n.length,this},is:function(e,n){var r,i;for(r=0,i=this.length;r<i;r++)if(t.is(this[r],e,n))return!0;return!1}},!0)}(ender)}(),function(){var e={exports:{}},t=e.exports;
/*!
* Bonzo: DOM Utility (c) Dustin Diaz 2012
* https://github.com/ded/bonzo
* License MIT
*/
(function(t,n,r){typeof e!="undefined"&&e.exports?e.exports=n():typeof r["define"]!="undefined"&&r["define"]=="function"&&r.define.amd?define(t,n):r[t]=n()})("bonzo",function(){function _(e){return new RegExp("(^|\\s+)"+e+"(\\s+|$)")}function D(e,t,n){for(var r=0,i=e.length;r<i;r++)t.call(n||e[r],e[r],r,e);return e}function P(e,t,n){for(var r=0,i=e.length;r<i;r++)q(e[r])&&(P(e[r].childNodes,t,n),t.call(n||e[r],e[r],r,e));return e}function H(e){return e.replace(/-(.)/g,function(e,t){return t.toUpperCase()})}function B(e){return e?e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase():e}function j(e){e[T]("data-node-uid")||e[x]("data-node-uid",++b);var t=e[T]("data-node-uid");return y[t]||(y[t]={})}function F(e){var t=e[T]("data-node-uid");t&&delete y[t]}function I(e,t){try{return e===null||e===undefined?undefined:e==="true"?!0:e==="false"?!1:e==="null"?null:(t=parseFloat(e))==e?t:e}catch(n){}return undefined}function q(e){return e&&e.nodeName&&e.nodeType==1}function R(e,t,n,r,i){for(r=0,i=e.length;r<i;++r)if(t.call(n,e[r],r,e))return!0;return!1}function U(e){return e=="transform"&&(e=C.transform)||/^transform-?[Oo]rigin$/.test(e)&&(e=C.transform+"Origin")||e=="float"&&(e=C.cssFloat),e?H(e):null}function W(e,t,n){var r=0,o=t||this,u=[],a=s&&typeof e=="string"&&e.charAt(0)!="<"?s(e):e;return D(J(a),function(e){D(o,function(t){var s=!t[i]||t[i]&&!t[i][i]?function(){var e=t.cloneNode(!0),n,r;if(o.$&&o.cloneEvents){o.$(e).cloneEvents(t),n=o.$(e).find("*"),r=o.$(t).find("*");for(var i=0;i<r.length;i++)o.$(n[i]).cloneEvents(r[i])}return e}():t;n(e,s),u[r]=s,r++})},this),D(u,function(e,t){o[t]=e}),o.length=r,o}function X(e,t,n){var r=Y(e),i=r.css("position"),s=r.offset(),o="relative",u=i==o,a=[parseInt(r.css("left"),10),parseInt(r.css("top"),10)];i=="static"&&(r.css("position",o),i=o),isNaN(a[0])&&(a[0]=u?0:e.offsetLeft),isNaN(a[1])&&(a[1]=u?0:e.offsetTop),t!=null&&(e.style.left=t-s.left+a[0]+S),n!=null&&(e.style.top=n-s.top+a[1]+S)}function V(e,t){return typeof t=="function"?t(e):t}function $(e){this.length=0;if(e){e=typeof e!="string"&&!e.nodeType&&typeof e.length!="undefined"?e:[e],this.length=e.length;for(var t=0;t<e.length;t++)this[t]=e[t]}}function J(e){return typeof e=="string"?Y.create(e):q(e)?[e]:e}function K(e,n,r){var i=this[0];return i?e==null&&n==null?(Q(i)?G():{x:i.scrollLeft,y:i.scrollTop})[r]:(Q(i)?t.scrollTo(e,n):(e!=null&&(i.scrollLeft=e),n!=null&&(i.scrollTop=n)),this):this}function Q(e){return e===t||/^(?:body|html)$/i.test(e.tagName)}function G(){return{x:t.pageXOffset||r.scrollLeft,y:t.pageYOffset||r.scrollTop}}function Y(e,t){return new $(e,t)}var e=this,t=window,n=t.document,r=n.documentElement,i="parentNode",s=null,o=/^(checked|value|selected)$/i,u=/^(select|fieldset|table|tbody|tfoot|td|tr|colgroup)$/i,a=["<table>","</table>",1],f=["<table><tbody><tr>","</tr></tbody></table>",3],l=["<select>","</select>",1],c=["_","",0,1],h={thead:a,tbody:a,tfoot:a,colgroup:a,caption:a,tr:["<table><tbody>","</tbody></table>",2],th:f,td:f,col:["<table><colgroup>","</colgroup></table>",2],fieldset:["<form>","</form>",1],legend:["<form><fieldset>","</fieldset></form>",2],option:l,optgroup:l,script:c,style:c,link:c,param:c,base:c},p=/^(checked|selected)$/,d=/msie/i.test(navigator.userAgent),v,m,g,y={},b=0,w=/^-?[\d\.]+$/,E=/^data-(.+)$/,S="px",x="setAttribute",T="getAttribute",N="getElementsByTagName",C=function(){var e=n.createElement("p");return e.innerHTML='<a href="#x">x</a><table style="float:left;"></table>',{hrefExtended:e[N]("a")[0][T]("href")!="#x",autoTbody:e[N]("tbody").length!==0,computedStyle:n.defaultView&&n.defaultView.getComputedStyle,cssFloat:e[N]("table")[0].style.styleFloat?"styleFloat":"cssFloat",transform:function(){var t=["webkitTransform","MozTransform","OTransform","msTransform","Transform"],n;for(n=0;n<t.length;n++)if(t[n]in e.style)return t[n]}(),classList:"classList"in e}}(),k=/(^\s*|\s*$)/g,L=/\s+/,A=String.prototype.toString,O={lineHeight:1,zoom:1,zIndex:1,opacity:1,boxFlex:1,WebkitBoxFlex:1,MozBoxFlex:1},M=String.prototype.trim?function(e){return e.trim()}:function(e){return e.replace(k,"")},z=C.computedStyle?function(e,t){var r=null,i=n.defaultView.getComputedStyle(e,"");return i&&(r=i[t]),e.style[t]||r}:d&&r.currentStyle?function(e,t){if(t=="opacity"){var n=100;try{n=e.filters["DXImageTransform.Microsoft.Alpha"].opacity}catch(r){try{n=e.filters("alpha").opacity}catch(i){}}return n/100}var s=e.currentStyle?e.currentStyle[t]:null;return e.style[t]||s}:function(e,t){return e.style[t]};return C.classList?(v=function(e,t){return e.classList.contains(t)},m=function(e,t){e.classList.add(t)},g=function(e,t){e.classList.remove(t)}):(v=function(e,t){return _(t).test(e.className)},m=function(e,t){e.className=M(e.className+" "+t)},g=function(e,t){e.className=M(e.className.replace(_(t)," "))}),$.prototype={get:function(e){return this[e]||null},each:function(e,t){return D(this,e,t)},deepEach:function(e,t){return P(this,e,t)},map:function(e,t){var n=[],r,i;for(i=0;i<this.length;i++)r=e.call(this,this[i],i),t?t(r)&&n.push(r):n.push(r);return n},html:function(e,t){function i(t){D(J(e),function(e){t.appendChild(e)})}var n=t?r.textContent===undefined?"innerText":"textContent":"innerHTML";return typeof e!="undefined"?this.empty().each(function(r){!t&&u.test(r.tagName)?i(r):function(){try{r[n]=e}catch(t){i(r)}}()}):this[0]?this[0][n]:""},text:function(e){return this.html(e,1)},append:function(e){return this.each(function(t){D(J(e),function(e){t.appendChild(e)})})},prepend:function(e){return this.each(function(t){var n=t.firstChild;D(J(e),function(e){t.insertBefore(e,n)})})},appendTo:function(e,t){return W.call(this,e,t,function(e,t){e.appendChild(t)})},prependTo:function(e,t){return W.call(this,e,t,function(e,t){e.insertBefore(t,e.firstChild)})},before:function(e){return this.each(function(t){D(Y.create(e),function(e){t[i].insertBefore(e,t)})})},after:function(e){return this.each(function(t){D(Y.create(e),function(e){t[i].insertBefore(e,t.nextSibling)})})},insertBefore:function(e,t){return W.call(this,e,t,function(e,t){e[i].insertBefore(t,e)})},insertAfter:function(e,t){return W.call(this,e,t,function(e,t){var n=e.nextSibling;n?e[i].insertBefore(t,n):e[i].appendChild(t)})},replaceWith:function(e){return this.deepEach(F),this.each(function(t){t.parentNode.replaceChild(Y.create(e)[0],t)})},addClass:function(e){return e=A.call(e).split(L),this.each(function(t){D(e,function(e){e&&!v(t,V(t,e))&&m(t,V(t,e))})})},removeClass:function(e){return e=A.call(e).split(L),this.each(function(t){D(e,function(e){e&&v(t,V(t,e))&&g(t,V(t,e))})})},hasClass:function(e){return e=A.call(e).split(L),R(this,function(t){return R(e,function(e){return e&&v(t,e)})})},toggleClass:function(e,t){return e=A.call(e).split(L),this.each(function(n){D(e,function(e){e&&(typeof t!="undefined"?t?m(n,e):g(n,e):v(n,e)?g(n,e):m(n,e))})})},show:function(e){return this.each(function(t){t.style.display=e||""})},hide:function(){return this.each(function(e){e.style.display="none"})},toggle:function(e,t){return this.each(function(e){e.style.display=e.offsetWidth||e.offsetHeight?"none":t||""}),e&&e(),this},first:function(){return Y(this.length?this[0]:[])},last:function(){return Y(this.length?this[this.length-1]:[])},next:function(){return this.related("nextSibling")},previous:function(){return this.related("previousSibling")},parent:function(){return this.related(i)},related:function(e){return this.map(function(t){t=t[e];while(t&&t.nodeType!==1)t=t[e];return t||0},function(e){return e})},focus:function(){return this.length&&this[0].focus(),this},blur:function(){return this.each(function(e){e.blur()})},css:function(e,r,i){function o(e,t,n){for(var r in s)s.hasOwnProperty(r)&&(n=s[r],(t=U(r))&&w.test(n)&&!(t in O)&&(n+=S),e.style[t]=V(e,n))}if(r===undefined&&typeof e=="string")return r=this[0],r?r===n||r===t?(i=r===n?Y.doc():Y.viewport(),e=="width"?i.width:e=="height"?i.height:""):(e=U(e))?z(r,e):null:null;var s=e;return typeof e=="string"&&(s={},s[e]=r),d&&s.opacity&&(s.filter="alpha(opacity="+s.opacity*100+")",s.zoom=e.zoom||1,delete s.opacity),this.each(o)},offset:function(e,t){if(typeof e=="number"||typeof t=="number")return this.each(function(n){X(n,e,t)});if(!this[0])return{top:0,left:0,height:0,width:0};var n=this[0],r=n.offsetWidth,i=n.offsetHeight,s=n.offsetTop,o=n.offsetLeft;while(n=n.offsetParent)s+=n.offsetTop,o+=n.offsetLeft,n!=document.body&&(s-=n.scrollTop,o-=n.scrollLeft);return{top:s,left:o,height:i,width:r}},dim:function(){if(!this.length)return{height:0,width:0};var e=this[0],t=!e.offsetWidth&&!e.offsetHeight?function(t,n){return n={position:e.style.position||"",visibility:e.style.visibility||"",display:e.style.display||""},t.first().css({position:"absolute",visibility:"hidden",display:"block"}),n}(this):null,n=e.offsetWidth,r=e.offsetHeight;return t&&this.first().css(t),{height:r,width:n}},attr:function(e,t){var n=this[0];if(typeof e=="string"||e instanceof String)return typeof t=="undefined"?n?o.test(e)?p.test(e)&&typeof n[e]=="string"?!0:n[e]:e!="href"&&e!="src"||!C.hrefExtended?n[T](e):n[T](e,2):null:this.each(function(n){o.test(e)?n[e]=V(n,t):n[x](e,V(n,t))});for(var r in e)e.hasOwnProperty(r)&&this.attr(r,e[r]);return this},removeAttr:function(e){return this.each(function(t){p.test(e)?t[e]=!1:t.removeAttribute(e)})},val:function(e){return typeof e=="string"?this.attr("value",e):this.length?this[0].value:null},data:function(e,t){var n=this[0],r,i,s;return typeof t=="undefined"?n?(i=j(n),typeof e=="undefined"?(D(n.attributes,function(e){(s=(""+e.name).match(E))&&(i[H(s[1])]=I(e.value))}),i):(typeof i[e]=="undefined"&&(i[e]=I(this.attr("data-"+B(e)))),i[e])):null:this.each(function(n){j(n)[e]=t})},remove:function(){return this.deepEach(F),this.each(function(e){e[i]&&e[i].removeChild(e)})},empty:function(){return this.each(function(e){P(e.childNodes,F);while(e.firstChild)e.removeChild(e.firstChild)})},detach:function(){return this.map(function(e){return e[i].removeChild(e)})},scrollTop:function(e){return K.call(this,null,e,"y")},scrollLeft:function(e){return K.call(this,e,null,"x")}},Y.setQueryEngine=function(e){s=e,delete Y.setQueryEngine},Y.aug=function(e,t){for(var n in e)e.hasOwnProperty(n)&&((t||$.prototype)[n]=e[n])},Y.create=function(e){return typeof e=="string"&&e!==""?function(){var t=/^\s*<([^\s>]+)/.exec(e),r=n.createElement("div"),s=[],o=t?h[t[1].toLowerCase()]:null,u=o?o[2]+1:1,a=o&&o[3],f=i,l=C.autoTbody&&o&&o[0]=="<table>"&&!/<tbody/i.test(e);r.innerHTML=o?o[0]+e+o[1]:e;while(u--)r=r.firstChild;a&&r&&r.nodeType!==1&&(r=r.nextSibling);do(!t||r.nodeType==1)&&(!l||r.tagName.toLowerCase()!="tbody")&&s.push(r);while(r=r.nextSibling);return D(s,function(e){e[f]&&e[f].removeChild(e)}),s}():q(e)?[e.cloneNode(!0)]:[]},Y.doc=function(){var e=Y.viewport();return{width:Math.max(n.body.scrollWidth,r.scrollWidth,e.width),height:Math.max(n.body.scrollHeight,r.scrollHeight,e.height)}},Y.firstChild=function(e){for(var t=e.childNodes,n=0,r=t&&t.length||0,i;n<r;n++)t[n].nodeType===1&&(i=t[r=n]);return i},Y.viewport=function(){return{width:d?r.clientWidth:self.innerWidth,height:d?r.clientHeight:self.innerHeight}},Y.isAncestor="compareDocumentPosition"in r?function(e,t){return(e.compareDocumentPosition(t)&16)==16}:"contains"in r?function(e,t){return e!==t&&e.contains(t)}:function(e,t){while(t=t[i])if(t===e)return!0;return!1},Y},this),provide("bonzo",e.exports),function(e){function n(e,t){for(var n=0;n<e.length;n++)if(e[n]===t)return n;return-1}function r(e){var t=[],n=0,r=0,i,s,o;for(;s=e[n];++n){o=!1;for(i=0;i<t.length;++i)if(t[i]===s){o=!0;break}o||(t[r++]=s)}return t}function i(e,n){return typeof n=="undefined"?t(this).dim()[e]:this.css(e,n)}var t=require("bonzo");t.setQueryEngine(e),e.ender(t),e.ender(t(),!0),e.ender({create:function(n){return e(t.create(n))}}),e.id=function(t){return e([document.getElementById(t)])},e.ender({parents:function(t,i){if(!this.length)return this;var s=e(t),o,u,a,f=[];for(o=0,u=this.length;o<u;o++){a=this[o];while(a=a.parentNode)if(~n(s,a)){f.push(a);if(i)break}}return e(r(f))},parent:function(){return e(r(t(this).parent()))},closest:function(e){return this.parents(e,!0)},first:function(){return e(this.length?this[0]:this)},last:function(){return e(this.length?this[this.length-1]:[])},next:function(){return e(t(this).next())},previous:function(){return e(t(this).previous())},appendTo:function(e){return t(this.selector).appendTo(e,this)},prependTo:function(e){return t(this.selector).prependTo(e,this)},insertAfter:function(e){return t(this.selector).insertAfter(e,this)},insertBefore:function(e){return t(this.selector).insertBefore(e,this)},siblings:function(){var t,n,r,i=[];for(t=0,n=this.length;t<n;t++){r=this[t];while(r=r.previousSibling)r.nodeType==1&&i.push(r);r=this[t];while(r=r.nextSibling)r.nodeType==1&&i.push(r)}return e(i)},children:function(){var n,i,s,o=[];for(n=0,i=this.length;n<i;n++){if(!(s=t.firstChild(this[n])))continue;o.push(s);while(s=s.nextSibling)s.nodeType==1&&o.push(s)}return e(r(o))},height:function(e){return i.call(this,"height",e)},width:function(e){return i.call(this,"width",e)}},!0)}(ender)}(),function(){var e={exports:{}},t=e.exports;!function(t,n){typeof e!="undefined"?e.exports=n():typeof define=="function"&&define.amd?define(t,n):this[t]=n()}("traversty",function(){var e=this,t=e.traversty,n=window.document,r=n.documentElement,i=Object.prototype.toString,s=Array.prototype.slice,o=function(e,t,n,r,i){while(r<t.length)if(e[i=t[r++]+n])return i}(r,["msM","webkitM","mozM","oM","m"],"atchesSelector",0),u=function(e){return i.call(e)==="[object Number]"},a=function(e){return i.call(e)==="[object String]"},f=function(e){return i.call(e)==="[object Function]"},l=function(e){return e===void 0},c=function(e){return e&&e.nodeType===1},h=function(e,t){return l(e)&&!u(t)?0:u(e)?e:u(t)?t:null},p=function(e){return a(e)?e:"*"},d=function(e,t){return s.call(t.querySelectorAll(e),0)},v=function(e,t){return e==="*"||t[o](e)},m=d,g=v,y=function(e,t){return function(n,r){if(/,/.test(n)){var i=[],s=-1,o=r.getElementsByTagName("*");while(++s<o.length)c(o[s])&&t(n,o[s])&&i.push(o[s]);return i}return e(n,r)}},b=function(e){var t=[],n=-1,r,i;while(++n<e.length){r=-1,i=!1;while(++r<t.length)if(t[r]===e[n]){i=!0;break}i||t.push(e[n])}return t},w=function(e,t){var n=[],r,i=0,s,o=e.length,u;while(i<o){s=0,u=(r=t(e[i++])).length;while(s<u)n.push(r[s++])}return n},E=function(e,t,n,r){return r=h(n,r),n=p(n),w(e,function(e){var i=r||0,s=[];while(e&&(r===null||i>=0))e=e[t],c(e)&&g(n,e)&&(r===null||i--===0)&&(r===null&&t!=="nextSibling"?s=[e].concat(s):s.push(e));return s})},S=function(){function r(e){this.length=0;if(e){e=b(!e.nodeType&&!l(e.length)?e:[e]);var t=this.length=e.length;while(t--)this[t]=e[t]}}function i(e){return new r(a(e)?m(e,n):e)}return r.prototype={down:function(e,t){return t=h(e,t),e=p(e),S(w(this,function(n){var r=m(e,n);return t===null?r:[r[t]]||[]}))},up:function(e,t){return S(E(this,"parentNode",e,t))},previous:function(e,t){return S(E(this,"previousSibling",e,t))},next:function(e,t){return S(E(this,"nextSibling",e,t))}},i.setSelectorEngine=function(e){var t,r,i,s,o,u=n.createElement("p"),l=e.select||e.sel||e;u.innerHTML="<a/><i/><b/>",i=u.firstChild;try{s=f(e.matching)?function(t,n){return e.matching([n],t).length>0}:f(e.is)?function(t,n){return e.is(n,t)}:f(e.matchesSelector)?function(t,n){return e.matchesSelector(n,t)}:f(e.match)?function(t,n){return e.match(n,t)}:null,s||(t=e("a",u),s=f(t.matching)?function(t,n){return e(n).matching(t).length>0}:f(t.is)?function(t,n){return e(n).is(t)}:f(t.matchesSelector)?function(t,n){return e(n).matchesSelector(t)}:f(t.match)?function(t,n){return e(n).match(t)}:null);if(!s)throw"Traversty: couldn't find selector engine's `matchesSelector`";if(s("x,y",u)||!s("a,p",u))throw"Traversty: couldn't make selector engine's `matchesSelector` work";if((r=l("b,a",u)).length!==2)throw"Traversty: don't know how to use this selector engine";o=r[0]===i?l:y(l,s);if((r=o("b,a",u)).length!==2||r[0]!==i)throw"Traversty: couldn't make selector engine work";g=s,m=o}catch(c){throw a(c)?c:"Traversty: error while figuring out how the selector engine works: "+(c.message||c)}finally{u=null}},i.noConflict=function(){return e.traversty=t,this},i}();return S}),provide("traversty",e.exports),function(e){var t=require("traversty"),n=!1,r=function(r){var i=function(s,o,u){if(!n){try{t.setSelectorEngine(e)}catch(a){}n=!0}return i=function(n,i,s){return e(t(n)[r](i,s))},i(s,o,u)};return function(e,t){return i(this,e,t)}},i=r("up"),s=r("down"),o=r("next"),u=r("previous");e.ender({up:i,down:s,next:o,previous:u,parent:i,prev:u},!0)}(ender)}()

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display