rails-i18nterface 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +22 -0
  3. data/README.md +109 -0
  4. data/Rakefile +23 -0
  5. data/app/assets/javascripts/rails_i18nterface/application.js +8 -0
  6. data/app/assets/javascripts/rails_i18nterface/base.js +62 -0
  7. data/app/assets/javascripts/rails_i18nterface/ender.js +3260 -0
  8. data/app/assets/javascripts/rails_i18nterface/ender.min.js +45 -0
  9. data/app/assets/stylesheets/rails_i18nterface/application.css +450 -0
  10. data/app/controllers/rails_i18nterface/application_controller.rb +4 -0
  11. data/app/controllers/rails_i18nterface/translate_controller.rb +255 -0
  12. data/app/helpers/rails_i18nterface/application_helper.rb +4 -0
  13. data/app/helpers/rails_i18nterface/translate_helper.rb +74 -0
  14. data/app/models/translation.rb +4 -0
  15. data/app/views/layouts/rails_i18nterface/translate.html.erb +13 -0
  16. data/app/views/rails_i18nterface/translate/_namespaces.html.erb +1 -0
  17. data/app/views/rails_i18nterface/translate/_pagination.html.erb +18 -0
  18. data/app/views/rails_i18nterface/translate/index.html.erb +132 -0
  19. data/config/routes.rb +7 -0
  20. data/db/migrate/20110921112044_create_translations.rb +18 -0
  21. data/lib/rails-i18nterface.rb +8 -0
  22. data/lib/rails-i18nterface/engine.rb +7 -0
  23. data/lib/rails-i18nterface/file.rb +35 -0
  24. data/lib/rails-i18nterface/keys.rb +192 -0
  25. data/lib/rails-i18nterface/log.rb +35 -0
  26. data/lib/rails-i18nterface/storage.rb +29 -0
  27. data/lib/rails-i18nterface/version.rb +3 -0
  28. data/lib/tasks/rails-i18nterface.rake +4 -0
  29. data/spec/controllers/translate_controller_spec.rb +135 -0
  30. data/spec/internal/app/assets/javascripts/application.js +2 -0
  31. data/spec/internal/app/assets/stylesheets/application.css +3 -0
  32. data/spec/internal/app/controllers/application_controller.rb +4 -0
  33. data/spec/internal/app/models/article.rb +11 -0
  34. data/spec/internal/app/views/application/index.html.erb +5 -0
  35. data/spec/internal/app/views/categories/category.erb +1 -0
  36. data/spec/internal/app/views/categories/category.html +1 -0
  37. data/spec/internal/app/views/categories/category.html.erb +1 -0
  38. data/spec/internal/app/views/categories/category.rhtml +5 -0
  39. data/spec/internal/config/database.yml +3 -0
  40. data/spec/internal/config/routes.rb +4 -0
  41. data/spec/internal/db/combustion_test.sqlite +0 -0
  42. data/spec/internal/db/schema.rb +3 -0
  43. data/spec/internal/log/test.log +521 -0
  44. data/spec/internal/public/favicon.ico +0 -0
  45. data/spec/lib/file_spec.rb +53 -0
  46. data/spec/lib/keys_spec.rb +179 -0
  47. data/spec/lib/log_spec.rb +46 -0
  48. data/spec/lib/storage_spec.rb +33 -0
  49. data/spec/requests/search_spec.rb +62 -0
  50. data/spec/spec_helper.rb +37 -0
  51. metadata +200 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9f7afb70be8d0c0bf696b8b490be4b1314119b2c
4
+ data.tar.gz: 78d9b7b1cb33eb49c9f67d133181b9282b3802a4
5
+ SHA512:
6
+ metadata.gz: 65280e7d68f0b1b2d5e28804ba53ff669d50b57bb6b398e78fbd68cb6fd214ad9519015ed710358a249ba7b01529fecdfea97873d5879b6a309da6f48043b160
7
+ data.tar.gz: ab47fa811503def3de2abd0dce9099bab87389ac1ea77440d1fa8d2392ba65a2caba0e16bf0969d10517cd22ff1ae41bc084dbd437c269f593b406b393489e46
data/MIT-LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright 2009 Peter Marklund, Joakim Westerlund, Claudius Coenen
2
+ Copyright 2011 Larry Sprock, Artin Boghosain, Michal Hantl
3
+ Copyright 2013 Mose
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,109 @@
1
+ # Rails I18nterface
2
+
3
+ [![Build Status](https://secure.travis-ci.org/mose/rails-i18nterface.png?branch=master)](http://travis-ci.org/mose/rails-i18nterface)
4
+ [![Code Climate](https://codeclimate.com/github/mose/rails-i18nterface.png)](https://codeclimate.com/github/mose/rails-i18nterface)
5
+
6
+ This is a fork of an overhaul of a fork of a fork if rails-translate.
7
+
8
+ It was originally created by [Peter Marklund and Joakim Westerlund @ mynewsdesk](https://github.com/mynewsdesk/translate)
9
+ and later adapted to rails 3.0 by [Claudius Coenen](https://github.com/ccoenen/rails-translate).
10
+ This version is a spinoff of Claudius Coenen's version by [Larry Sprock](https://github.com/lardawge/rails-i18nterface).
11
+ It was renamed, refactored and prepared for rails 3.1 as an Engine. Over this work
12
+ [Michal Hantl](https://github.com/hakunin/rails-i18nterface) made a bunch of nice UI modifications
13
+ on his fork. Since then it was mroe or less abandonned.
14
+
15
+ I took over the evolution with some new features:
16
+
17
+ * testing using combustion and rspec
18
+ * redesign of the layout
19
+ * navigation overhaul, spliting of the namespaces in a foldable menu
20
+ * gathering of first-level translations under a ROOT container
21
+ * gemification and release of a version 0.0.2
22
+ * (the 0.0.1 was the original work from Larry Sprock but was not published as a gem)
23
+ * compatibility with rails 4 and ruby 2
24
+
25
+ ![rails-i18nterface](http://mose.fr/rails-i18nterface.png)
26
+
27
+ ## Usage
28
+
29
+ In Gemfile
30
+
31
+ ```ruby
32
+ gem 'rails-i18nterface'
33
+ ```
34
+ In routes.rb
35
+
36
+ ```ruby
37
+ mount RailsI18nterface::Engine => "/translate", :as => "translate_engine"
38
+ ```
39
+ Copy migration to store translated values and migrate
40
+ ```
41
+ rake railties:install:migrations
42
+ rake db:migrate
43
+ ```
44
+ ### Protect access
45
+
46
+ You may want to protect the translation engine to admin and create a constraint
47
+ in your route:
48
+ ```ruby
49
+ constraints AdminConstraint.new do
50
+ mount RailsI18nterface::Engine => "/translate", :as => "translate_engine"
51
+ end
52
+ ```
53
+
54
+ Then create a `config/initializers/admin_constraint.rb` containing:
55
+ ```ruby
56
+ class AdminConstraint
57
+ def matches?(request)
58
+ current_user && current_user.is_admin?
59
+ end
60
+ end
61
+ ```
62
+ (this example is for devise users, but you can adjust it to return true or false
63
+ according to your own context).
64
+
65
+ ### Confifuration
66
+
67
+ You can configure `from_locales` and `to_locales` explicitly in your
68
+ `environments/development.rb` by adding
69
+ ```ruby
70
+ config.from_locales = [:en]
71
+ config.to_locales = [:ja, :es, :fr]
72
+ ```
73
+ Where `[:en]` and `[:ja, :es, :fr]` could be replaced by locale list of your choice.
74
+
75
+ ## Todo
76
+
77
+ * fix the code smell reported by code climate
78
+ ** extract code from the controller to a lib
79
+ ** refactor the libs in a cleaner way
80
+ ** apply rubocop and follow his law
81
+ * extend testing to refactored libs
82
+ * change navigation to an ajax-driven reload
83
+
84
+ ## License
85
+
86
+ ```
87
+ Copyright 2009 Peter Marklund, Joakim Westerlund, Claudius Coenen
88
+ Copyright 2011 Larry Sprock, Artin Boghosain, Michal Hantl
89
+ Copyright 2013 Mose
90
+
91
+ Permission is hereby granted, free of charge, to any person obtaining
92
+ a copy of this software and associated documentation files (the
93
+ "Software"), to deal in the Software without restriction, including
94
+ without limitation the rights to use, copy, modify, merge, publish,
95
+ distribute, sublicense, and/or sell copies of the Software, and to
96
+ permit persons to whom the Software is furnished to do so, subject to
97
+ the following conditions:
98
+
99
+ The above copyright notice and this permission notice shall be
100
+ included in all copies or substantial portions of the Software.
101
+
102
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
103
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
104
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
105
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
106
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
107
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
108
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
109
+ ```
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ require 'bundler/setup'
8
+
9
+ require "bundler/gem_tasks"
10
+ Bundler::GemHelper.install_tasks
11
+
12
+ require "rake/testtask"
13
+
14
+
15
+ require "rspec/core/rake_task" # RSpec 2.0
16
+ task :spec do
17
+ RSpec::Core::RakeTask.new(:spec) do |t|
18
+ t.rspec_opts = ["-c", "-f progress", "-r ./spec/spec_helper.rb"]
19
+ t.pattern = 'spec/**/*_spec.rb'
20
+ end
21
+ end
22
+
23
+ task :default => :spec
@@ -0,0 +1,8 @@
1
+ // This is a manifest file that'll be compiled into including all the files listed below.
2
+ // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
3
+ // be included in the compiled file accessible from http://example.com/assets/application.js
4
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
5
+ // the compiled file.
6
+ //
7
+ //= require rails_i18nterface/ender
8
+ //= require rails_i18nterface/base
@@ -0,0 +1,62 @@
1
+ $.domReady(function() {
2
+ function getFocus() {
3
+ url = window.location.href;
4
+ m = url.indexOf("key_pattern");
5
+ if (m !== -1) {
6
+ focus = url.slice(url.indexOf("=", m)+1, url.indexOf("&", m));
7
+ } else {
8
+ focus = false;
9
+ }
10
+ return focus;
11
+ }
12
+ function openNav(focus) {
13
+ if (focus) {
14
+ if (focus === '.') {
15
+ items = ['.'];
16
+ } else if (!focus.indexOf('.')) {
17
+ items = ['ROOT',focus];
18
+ } else {
19
+ items = focus.split(/\./);
20
+ }
21
+ namespace = [];
22
+ while (it = items.shift()) {
23
+ namespace.push(it);
24
+ join = namespace.join('.');
25
+ it = $("#namespaces span[data-id='"+join+"']");
26
+ if (it.length > 0) {
27
+ $(it.selector).siblings("ul").toggleClass("view");
28
+ }
29
+ }
30
+ }
31
+ return;
32
+ }
33
+ var focus = getFocus();
34
+ openNav(focus);
35
+ function filterThat(s,start) {
36
+ if (start) {
37
+ $("#key_type").val("starts_with");
38
+ } else {
39
+ $("#key_type").val("contains");
40
+ }
41
+ $("#key_pattern_value").val(s);
42
+ document.forms['filter_form'].submit();
43
+ }
44
+ $("#namespaces ul li").on("click", function(e) {
45
+ e.preventDefault();
46
+ e.stopPropagation();
47
+ $(this).children("ul").toggleClass("view");
48
+ });
49
+ $("#namespaces ul li .display").on("click", function(e) {
50
+ e.preventDefault();
51
+ e.stopPropagation();
52
+ filter = $(this).data("id");
53
+ filterThat(filter,true);
54
+ });
55
+ $("#namespaces ul li.item").on("click", function(e) {
56
+ e.preventDefault();
57
+ e.stopPropagation();
58
+ filter = $(this).data("id");
59
+ filterThat(filter,false);
60
+ });
61
+
62
+ });
@@ -0,0 +1,3260 @@
1
+ /*!
2
+ * =============================================================
3
+ * Ender: open module JavaScript framework (https://ender.no.de)
4
+ * Build: ender build jeesh reqwest --output app/assets/javascripts/rails_i18nterface/ender
5
+ * =============================================================
6
+ */
7
+
8
+ /*!
9
+ * Ender: open module JavaScript framework (client-lib)
10
+ * copyright Dustin Diaz & Jacob Thornton 2011-2012 (@ded @fat)
11
+ * http://ender.jit.su
12
+ * License MIT
13
+ */
14
+ (function (context) {
15
+
16
+ // a global object for node.js module compatiblity
17
+ // ============================================
18
+
19
+ context['global'] = context
20
+
21
+ // Implements simple module system
22
+ // losely based on CommonJS Modules spec v1.1.1
23
+ // ============================================
24
+
25
+ var modules = {}
26
+ , old = context['$']
27
+ , oldEnder = context['ender']
28
+ , oldRequire = context['require']
29
+ , oldProvide = context['provide']
30
+
31
+ function require (identifier) {
32
+ // modules can be required from ender's build system, or found on the window
33
+ var module = modules['$' + identifier] || window[identifier]
34
+ if (!module) throw new Error("Ender Error: Requested module '" + identifier + "' has not been defined.")
35
+ return module
36
+ }
37
+
38
+ function provide (name, what) {
39
+ return (modules['$' + name] = what)
40
+ }
41
+
42
+ context['provide'] = provide
43
+ context['require'] = require
44
+
45
+ function aug(o, o2) {
46
+ for (var k in o2) k != 'noConflict' && k != '_VERSION' && (o[k] = o2[k])
47
+ return o
48
+ }
49
+
50
+ /**
51
+ * main Ender return object
52
+ * @constructor
53
+ * @param {Array|Node|string} s a CSS selector or DOM node(s)
54
+ * @param {Array.|Node} r a root node(s)
55
+ */
56
+ function Ender(s, r) {
57
+ var elements
58
+ , i
59
+
60
+ this.selector = s
61
+ // string || node || nodelist || window
62
+ if (typeof s == 'undefined') {
63
+ elements = []
64
+ this.selector = ''
65
+ } else if (typeof s == 'string' || s.nodeName || (s.length && 'item' in s) || s == window) {
66
+ elements = ender._select(s, r)
67
+ } else {
68
+ elements = isFinite(s.length) ? s : [s]
69
+ }
70
+ this.length = elements.length
71
+ for (i = this.length; i--;) this[i] = elements[i]
72
+ }
73
+
74
+ /**
75
+ * @param {function(el, i, inst)} fn
76
+ * @param {Object} opt_scope
77
+ * @returns {Ender}
78
+ */
79
+ Ender.prototype['forEach'] = function (fn, opt_scope) {
80
+ var i, l
81
+ // opt out of native forEach so we can intentionally call our own scope
82
+ // defaulting to the current item and be able to return self
83
+ for (i = 0, l = this.length; i < l; ++i) i in this && fn.call(opt_scope || this[i], this[i], i, this)
84
+ // return self for chaining
85
+ return this
86
+ }
87
+
88
+ Ender.prototype.$ = ender // handy reference to self
89
+
90
+
91
+ function ender(s, r) {
92
+ return new Ender(s, r)
93
+ }
94
+
95
+ ender['_VERSION'] = '0.4.3-dev'
96
+
97
+ ender.fn = Ender.prototype // for easy compat to jQuery plugins
98
+
99
+ ender.ender = function (o, chain) {
100
+ aug(chain ? Ender.prototype : ender, o)
101
+ }
102
+
103
+ ender._select = function (s, r) {
104
+ if (typeof s == 'string') return (r || document).querySelectorAll(s)
105
+ if (s.nodeName) return [s]
106
+ return s
107
+ }
108
+
109
+
110
+ // use callback to receive Ender's require & provide and remove them from global
111
+ ender.noConflict = function (callback) {
112
+ context['$'] = old
113
+ if (callback) {
114
+ context['provide'] = oldProvide
115
+ context['require'] = oldRequire
116
+ context['ender'] = oldEnder
117
+ if (typeof callback == 'function') callback(require, provide, this)
118
+ }
119
+ return this
120
+ }
121
+
122
+ if (typeof module !== 'undefined' && module.exports) module.exports = ender
123
+ // use subscript notation as extern for Closure compilation
124
+ context['ender'] = context['$'] = ender
125
+
126
+ }(this));
127
+
128
+ (function () {
129
+
130
+ var module = { exports: {} }, exports = module.exports;
131
+
132
+ /*!
133
+ * Reqwest! A general purpose XHR connection manager
134
+ * (c) Dustin Diaz 2012
135
+ * https://github.com/ded/reqwest
136
+ * license MIT
137
+ */
138
+ !function (name, definition) {
139
+ if (typeof module != 'undefined' && module.exports) module.exports = definition()
140
+ else if (typeof define == 'function' && define.amd) define(definition)
141
+ else this[name] = definition()
142
+ }('reqwest', function () {
143
+
144
+ var win = window
145
+ , doc = document
146
+ , twoHundo = /^20\d$/
147
+ , byTag = 'getElementsByTagName'
148
+ , readyState = 'readyState'
149
+ , contentType = 'Content-Type'
150
+ , requestedWith = 'X-Requested-With'
151
+ , head = doc[byTag]('head')[0]
152
+ , uniqid = 0
153
+ , callbackPrefix = 'reqwest_' + (+new Date())
154
+ , lastValue // data stored by the most recent JSONP callback
155
+ , xmlHttpRequest = 'XMLHttpRequest'
156
+
157
+ var isArray = typeof Array.isArray == 'function' ? Array.isArray : function (a) {
158
+ return a instanceof Array
159
+ }
160
+ var defaultHeaders = {
161
+ contentType: 'application/x-www-form-urlencoded'
162
+ , requestedWith: xmlHttpRequest
163
+ , accept: {
164
+ '*': 'text/javascript, text/html, application/xml, text/xml, */*'
165
+ , xml: 'application/xml, text/xml'
166
+ , html: 'text/html'
167
+ , text: 'text/plain'
168
+ , json: 'application/json, text/javascript'
169
+ , js: 'application/javascript, text/javascript'
170
+ }
171
+ }
172
+ var xhr = win[xmlHttpRequest] ?
173
+ function () {
174
+ return new XMLHttpRequest()
175
+ } :
176
+ function () {
177
+ return new ActiveXObject('Microsoft.XMLHTTP')
178
+ }
179
+
180
+ function handleReadyState(o, success, error) {
181
+ return function () {
182
+ if (o && o[readyState] == 4) {
183
+ o.onreadystatechange = undefined;
184
+ if (twoHundo.test(o.status)) {
185
+ success(o)
186
+ } else {
187
+ error(o)
188
+ }
189
+ }
190
+ }
191
+ }
192
+
193
+ function setHeaders(http, o) {
194
+ var headers = o.headers || {}, h
195
+ headers.Accept = headers.Accept || defaultHeaders.accept[o.type] || defaultHeaders.accept['*']
196
+ // breaks cross-origin requests with legacy browsers
197
+ if (!o.crossOrigin && !headers[requestedWith]) headers[requestedWith] = defaultHeaders.requestedWith
198
+ if (!headers[contentType]) headers[contentType] = o.contentType || defaultHeaders.contentType
199
+ for (h in headers) {
200
+ headers.hasOwnProperty(h) && http.setRequestHeader(h, headers[h])
201
+ }
202
+ }
203
+
204
+ function setCredentials(http, o) {
205
+ if (typeof o.withCredentials !== "undefined" && typeof http.withCredentials !== "undefined") {
206
+ http.withCredentials = !!o.withCredentials
207
+ }
208
+ }
209
+
210
+ function generalCallback(data) {
211
+ lastValue = data
212
+ }
213
+
214
+ function urlappend(url, s) {
215
+ return url + (/\?/.test(url) ? '&' : '?') + s
216
+ }
217
+
218
+ function handleJsonp(o, fn, err, url) {
219
+ var reqId = uniqid++
220
+ , cbkey = o.jsonpCallback || 'callback' // the 'callback' key
221
+ , cbval = o.jsonpCallbackName || reqwest.getcallbackPrefix(reqId)
222
+ // , cbval = o.jsonpCallbackName || ('reqwest_' + reqId) // the 'callback' value
223
+ , cbreg = new RegExp('((^|\\?|&)' + cbkey + ')=([^&]+)')
224
+ , match = url.match(cbreg)
225
+ , script = doc.createElement('script')
226
+ , loaded = 0
227
+ , isIE10 = navigator.userAgent.indexOf('MSIE 10.0') !== -1
228
+
229
+ if (match) {
230
+ if (match[3] === '?') {
231
+ url = url.replace(cbreg, '$1=' + cbval) // wildcard callback func name
232
+ } else {
233
+ cbval = match[3] // provided callback func name
234
+ }
235
+ } else {
236
+ url = urlappend(url, cbkey + '=' + cbval) // no callback details, add 'em
237
+ }
238
+
239
+ win[cbval] = generalCallback
240
+
241
+ script.type = 'text/javascript'
242
+ script.src = url
243
+ script.async = true
244
+ if (typeof script.onreadystatechange !== 'undefined' && !isIE10) {
245
+ // need this for IE due to out-of-order onreadystatechange(), binding script
246
+ // execution to an event listener gives us control over when the script
247
+ // is executed. See http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html
248
+ //
249
+ // if this hack is used in IE10 jsonp callback are never called
250
+ script.event = 'onclick'
251
+ script.htmlFor = script.id = '_reqwest_' + reqId
252
+ }
253
+
254
+ script.onload = script.onreadystatechange = function () {
255
+ if ((script[readyState] && script[readyState] !== 'complete' && script[readyState] !== 'loaded') || loaded) {
256
+ return false
257
+ }
258
+ script.onload = script.onreadystatechange = null
259
+ script.onclick && script.onclick()
260
+ // Call the user callback with the last value stored and clean up values and scripts.
261
+ o.success && o.success(lastValue)
262
+ lastValue = undefined
263
+ head.removeChild(script)
264
+ loaded = 1
265
+ }
266
+
267
+ // Add the script to the DOM head
268
+ head.appendChild(script)
269
+ }
270
+
271
+ function getRequest(o, fn, err) {
272
+ var method = (o.method || 'GET').toUpperCase()
273
+ , url = typeof o === 'string' ? o : o.url
274
+ // convert non-string objects to query-string form unless o.processData is false
275
+ , data = (o.processData !== false && o.data && typeof o.data !== 'string')
276
+ ? reqwest.toQueryString(o.data)
277
+ : (o.data || null)
278
+ , http
279
+
280
+ // if we're working on a GET request and we have data then we should append
281
+ // query string to end of URL and not post data
282
+ if ((o.type == 'jsonp' || method == 'GET') && data) {
283
+ url = urlappend(url, data)
284
+ data = null
285
+ }
286
+
287
+ if (o.type == 'jsonp') return handleJsonp(o, fn, err, url)
288
+
289
+ http = xhr()
290
+ http.open(method, url, true)
291
+ setHeaders(http, o)
292
+ setCredentials(http, o)
293
+ http.onreadystatechange = handleReadyState(http, fn, err)
294
+ o.before && o.before(http)
295
+ http.send(data)
296
+ return http
297
+ }
298
+
299
+ function Reqwest(o, fn) {
300
+ this.o = o
301
+ this.fn = fn
302
+
303
+ init.apply(this, arguments)
304
+ }
305
+
306
+ function setType(url) {
307
+ var m = url.match(/\.(json|jsonp|html|xml)(\?|$)/)
308
+ return m ? m[1] : 'js'
309
+ }
310
+
311
+ function init(o, fn) {
312
+
313
+ this.url = typeof o == 'string' ? o : o.url
314
+ this.timeout = null
315
+
316
+ // whether request has been fulfilled for purpose
317
+ // of tracking the Promises
318
+ this._fulfilled = false
319
+ // success handlers
320
+ this._fulfillmentHandlers = []
321
+ // error handlers
322
+ this._errorHandlers = []
323
+ // complete (both success and fail) handlers
324
+ this._completeHandlers = []
325
+ this._erred = false
326
+ this._responseArgs = {}
327
+
328
+ var self = this
329
+ , type = o.type || setType(this.url)
330
+
331
+ fn = fn || function () {}
332
+
333
+ if (o.timeout) {
334
+ this.timeout = setTimeout(function () {
335
+ self.abort()
336
+ }, o.timeout)
337
+ }
338
+
339
+ if (o.success) {
340
+ this._fulfillmentHandlers.push(function () {
341
+ o.success.apply(o, arguments)
342
+ })
343
+ }
344
+
345
+ if (o.error) {
346
+ this._errorHandlers.push(function () {
347
+ o.error.apply(o, arguments)
348
+ })
349
+ }
350
+
351
+ if (o.complete) {
352
+ this._completeHandlers.push(function () {
353
+ o.complete.apply(o, arguments)
354
+ })
355
+ }
356
+
357
+ function complete(resp) {
358
+ o.timeout && clearTimeout(self.timeout)
359
+ self.timeout = null
360
+ while (self._completeHandlers.length > 0) {
361
+ self._completeHandlers.shift()(resp)
362
+ }
363
+ }
364
+
365
+ function success(resp) {
366
+ var r = resp.responseText
367
+ if (r) {
368
+ switch (type) {
369
+ case 'json':
370
+ try {
371
+ resp = win.JSON ? win.JSON.parse(r) : eval('(' + r + ')')
372
+ } catch (err) {
373
+ return error(resp, 'Could not parse JSON in response', err)
374
+ }
375
+ break;
376
+ case 'js':
377
+ resp = eval(r)
378
+ break;
379
+ case 'html':
380
+ resp = r
381
+ break;
382
+ case 'xml':
383
+ resp = resp.responseXML;
384
+ break;
385
+ }
386
+ }
387
+
388
+ self._responseArgs.resp = resp
389
+ self._fulfilled = true
390
+ fn(resp)
391
+ while (self._fulfillmentHandlers.length > 0) {
392
+ self._fulfillmentHandlers.shift()(resp)
393
+ }
394
+
395
+ complete(resp)
396
+ }
397
+
398
+ function error(resp, msg, t) {
399
+ self._responseArgs.resp = resp
400
+ self._responseArgs.msg = msg
401
+ self._responseArgs.t = t
402
+ self._erred = true
403
+ while (self._errorHandlers.length > 0) {
404
+ self._errorHandlers.shift()(resp, msg, t)
405
+ }
406
+ complete(resp)
407
+ }
408
+
409
+ this.request = getRequest(o, success, error)
410
+ }
411
+
412
+ Reqwest.prototype = {
413
+ abort: function () {
414
+ this.request.abort()
415
+ }
416
+
417
+ , retry: function () {
418
+ init.call(this, this.o, this.fn)
419
+ }
420
+
421
+ /**
422
+ * Small deviation from the Promises A CommonJs specification
423
+ * http://wiki.commonjs.org/wiki/Promises/A
424
+ */
425
+
426
+ /**
427
+ * `then` will execute upon successful requests
428
+ */
429
+ , then: function (success, fail) {
430
+ if (this._fulfilled) {
431
+ success(this._responseArgs.resp)
432
+ } else if (this._erred) {
433
+ fail(this._responseArgs.resp, this._responseArgs.msg, this._responseArgs.t)
434
+ } else {
435
+ this._fulfillmentHandlers.push(success)
436
+ this._errorHandlers.push(fail)
437
+ }
438
+ return this
439
+ }
440
+
441
+ /**
442
+ * `always` will execute whether the request succeeds or fails
443
+ */
444
+ , always: function (fn) {
445
+ if (this._fulfilled || this._erred) {
446
+ fn(this._responseArgs.resp)
447
+ } else {
448
+ this._completeHandlers.push(fn)
449
+ }
450
+ return this
451
+ }
452
+
453
+ /**
454
+ * `fail` will execute when the request fails
455
+ */
456
+ , fail: function (fn) {
457
+ if (this._erred) {
458
+ fn(this._responseArgs.resp, this._responseArgs.msg, this._responseArgs.t)
459
+ } else {
460
+ this._errorHandlers.push(fn)
461
+ }
462
+ return this
463
+ }
464
+ }
465
+
466
+ function reqwest(o, fn) {
467
+ return new Reqwest(o, fn)
468
+ }
469
+
470
+ // normalize newline variants according to spec -> CRLF
471
+ function normalize(s) {
472
+ return s ? s.replace(/\r?\n/g, '\r\n') : ''
473
+ }
474
+
475
+ function serial(el, cb) {
476
+ var n = el.name
477
+ , t = el.tagName.toLowerCase()
478
+ , optCb = function (o) {
479
+ // IE gives value="" even where there is no value attribute
480
+ // 'specified' ref: http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-862529273
481
+ if (o && !o.disabled)
482
+ cb(n, normalize(o.attributes.value && o.attributes.value.specified ? o.value : o.text))
483
+ }
484
+
485
+ // don't serialize elements that are disabled or without a name
486
+ if (el.disabled || !n) return;
487
+
488
+ switch (t) {
489
+ case 'input':
490
+ if (!/reset|button|image|file/i.test(el.type)) {
491
+ var ch = /checkbox/i.test(el.type)
492
+ , ra = /radio/i.test(el.type)
493
+ , val = el.value;
494
+ // WebKit gives us "" instead of "on" if a checkbox has no value, so correct it here
495
+ (!(ch || ra) || el.checked) && cb(n, normalize(ch && val === '' ? 'on' : val))
496
+ }
497
+ break;
498
+ case 'textarea':
499
+ cb(n, normalize(el.value))
500
+ break;
501
+ case 'select':
502
+ if (el.type.toLowerCase() === 'select-one') {
503
+ optCb(el.selectedIndex >= 0 ? el.options[el.selectedIndex] : null)
504
+ } else {
505
+ for (var i = 0; el.length && i < el.length; i++) {
506
+ el.options[i].selected && optCb(el.options[i])
507
+ }
508
+ }
509
+ break;
510
+ }
511
+ }
512
+
513
+ // collect up all form elements found from the passed argument elements all
514
+ // the way down to child elements; pass a '<form>' or form fields.
515
+ // called with 'this'=callback to use for serial() on each element
516
+ function eachFormElement() {
517
+ var cb = this
518
+ , e, i, j
519
+ , serializeSubtags = function (e, tags) {
520
+ for (var i = 0; i < tags.length; i++) {
521
+ var fa = e[byTag](tags[i])
522
+ for (j = 0; j < fa.length; j++) serial(fa[j], cb)
523
+ }
524
+ }
525
+
526
+ for (i = 0; i < arguments.length; i++) {
527
+ e = arguments[i]
528
+ if (/input|select|textarea/i.test(e.tagName)) serial(e, cb)
529
+ serializeSubtags(e, [ 'input', 'select', 'textarea' ])
530
+ }
531
+ }
532
+
533
+ // standard query string style serialization
534
+ function serializeQueryString() {
535
+ return reqwest.toQueryString(reqwest.serializeArray.apply(null, arguments))
536
+ }
537
+
538
+ // { 'name': 'value', ... } style serialization
539
+ function serializeHash() {
540
+ var hash = {}
541
+ eachFormElement.apply(function (name, value) {
542
+ if (name in hash) {
543
+ hash[name] && !isArray(hash[name]) && (hash[name] = [hash[name]])
544
+ hash[name].push(value)
545
+ } else hash[name] = value
546
+ }, arguments)
547
+ return hash
548
+ }
549
+
550
+ // [ { name: 'name', value: 'value' }, ... ] style serialization
551
+ reqwest.serializeArray = function () {
552
+ var arr = []
553
+ eachFormElement.apply(function (name, value) {
554
+ arr.push({name: name, value: value})
555
+ }, arguments)
556
+ return arr
557
+ }
558
+
559
+ reqwest.serialize = function () {
560
+ if (arguments.length === 0) return ''
561
+ var opt, fn
562
+ , args = Array.prototype.slice.call(arguments, 0)
563
+
564
+ opt = args.pop()
565
+ opt && opt.nodeType && args.push(opt) && (opt = null)
566
+ opt && (opt = opt.type)
567
+
568
+ if (opt == 'map') fn = serializeHash
569
+ else if (opt == 'array') fn = reqwest.serializeArray
570
+ else fn = serializeQueryString
571
+
572
+ return fn.apply(null, args)
573
+ }
574
+
575
+ reqwest.toQueryString = function (o) {
576
+ var qs = '', i
577
+ , enc = encodeURIComponent
578
+ , push = function (k, v) {
579
+ qs += enc(k) + '=' + enc(v) + '&'
580
+ }
581
+
582
+ if (isArray(o)) {
583
+ for (i = 0; o && i < o.length; i++) push(o[i].name, o[i].value)
584
+ } else {
585
+ for (var k in o) {
586
+ if (!Object.hasOwnProperty.call(o, k)) continue;
587
+ var v = o[k]
588
+ if (isArray(v)) {
589
+ for (i = 0; i < v.length; i++) push(k, v[i])
590
+ } else push(k, o[k])
591
+ }
592
+ }
593
+
594
+ // spaces should be + according to spec
595
+ return qs.replace(/&$/, '').replace(/%20/g, '+')
596
+ }
597
+
598
+ reqwest.getcallbackPrefix = function (reqId) {
599
+ return callbackPrefix
600
+ }
601
+
602
+ // jQuery and Zepto compatibility, differences can be remapped here so you can call
603
+ // .ajax.compat(options, callback)
604
+ reqwest.compat = function (o, fn) {
605
+ if (o) {
606
+ o.type && (o.method = o.type) && delete o.type
607
+ o.dataType && (o.type = o.dataType)
608
+ o.jsonpCallback && (o.jsonpCallbackName = o.jsonpCallback) && delete o.jsonpCallback
609
+ o.jsonp && (o.jsonpCallback = o.jsonp)
610
+ }
611
+ return new Reqwest(o, fn)
612
+ }
613
+
614
+ return reqwest
615
+ });
616
+
617
+
618
+ provide("reqwest", module.exports);
619
+
620
+ !function ($) {
621
+ var r = require('reqwest')
622
+ , integrate = function(method) {
623
+ return function() {
624
+ var args = Array.prototype.slice.call(arguments, 0)
625
+ , i = (this && this.length) || 0
626
+ while (i--) args.unshift(this[i])
627
+ return r[method].apply(null, args)
628
+ }
629
+ }
630
+ , s = integrate('serialize')
631
+ , sa = integrate('serializeArray')
632
+
633
+ $.ender({
634
+ ajax: r
635
+ , serialize: r.serialize
636
+ , serializeArray: r.serializeArray
637
+ , toQueryString: r.toQueryString
638
+ })
639
+
640
+ $.ender({
641
+ serialize: s
642
+ , serializeArray: sa
643
+ }, true)
644
+ }(ender);
645
+
646
+
647
+ }());
648
+
649
+ (function () {
650
+
651
+ var module = { exports: {} }, exports = module.exports;
652
+
653
+ /*!
654
+ * Bean - copyright (c) Jacob Thornton 2011-2012
655
+ * https://github.com/fat/bean
656
+ * MIT license
657
+ */
658
+ !(function (name, context, definition) {
659
+ if (typeof module != 'undefined' && module.exports) module.exports = definition(name, context);
660
+ else if (typeof define == 'function' && typeof define.amd == 'object') define(definition);
661
+ else context[name] = definition(name, context);
662
+ }('bean', this, function (name, context) {
663
+ var win = window
664
+ , old = context[name]
665
+ , namespaceRegex = /[^\.]*(?=\..*)\.|.*/
666
+ , nameRegex = /\..*/
667
+ , addEvent = 'addEventListener'
668
+ , removeEvent = 'removeEventListener'
669
+ , doc = document || {}
670
+ , root = doc.documentElement || {}
671
+ , W3C_MODEL = root[addEvent]
672
+ , eventSupport = W3C_MODEL ? addEvent : 'attachEvent'
673
+ , ONE = {} // singleton for quick matching making add() do one()
674
+
675
+ , slice = Array.prototype.slice
676
+ , str2arr = function (s, d) { return s.split(d || ' ') }
677
+ , isString = function (o) { return typeof o == 'string' }
678
+ , isFunction = function (o) { return typeof o == 'function' }
679
+
680
+ // events that we consider to be 'native', anything not in this list will
681
+ // be treated as a custom event
682
+ , standardNativeEvents =
683
+ 'click dblclick mouseup mousedown contextmenu ' + // mouse buttons
684
+ 'mousewheel mousemultiwheel DOMMouseScroll ' + // mouse wheel
685
+ 'mouseover mouseout mousemove selectstart selectend ' + // mouse movement
686
+ 'keydown keypress keyup ' + // keyboard
687
+ 'orientationchange ' + // mobile
688
+ 'focus blur change reset select submit ' + // form elements
689
+ 'load unload beforeunload resize move DOMContentLoaded ' + // window
690
+ 'readystatechange message ' + // window
691
+ 'error abort scroll ' // misc
692
+ // element.fireEvent('onXYZ'... is not forgiving if we try to fire an event
693
+ // that doesn't actually exist, so make sure we only do these on newer browsers
694
+ , w3cNativeEvents =
695
+ 'show ' + // mouse buttons
696
+ 'input invalid ' + // form elements
697
+ 'touchstart touchmove touchend touchcancel ' + // touch
698
+ 'gesturestart gesturechange gestureend ' + // gesture
699
+ 'textinput' + // TextEvent
700
+ 'readystatechange pageshow pagehide popstate ' + // window
701
+ 'hashchange offline online ' + // window
702
+ 'afterprint beforeprint ' + // printing
703
+ 'dragstart dragenter dragover dragleave drag drop dragend ' + // dnd
704
+ 'loadstart progress suspend emptied stalled loadmetadata ' + // media
705
+ 'loadeddata canplay canplaythrough playing waiting seeking ' + // media
706
+ 'seeked ended durationchange timeupdate play pause ratechange ' + // media
707
+ 'volumechange cuechange ' + // media
708
+ 'checking noupdate downloading cached updateready obsolete ' // appcache
709
+
710
+ // convert to a hash for quick lookups
711
+ , nativeEvents = (function (hash, events, i) {
712
+ for (i = 0; i < events.length; i++) events[i] && (hash[events[i]] = 1)
713
+ return hash
714
+ }({}, str2arr(standardNativeEvents + (W3C_MODEL ? w3cNativeEvents : ''))))
715
+
716
+ // custom events are events that we *fake*, they are not provided natively but
717
+ // we can use native events to generate them
718
+ , customEvents = (function () {
719
+ var isAncestor = 'compareDocumentPosition' in root
720
+ ? function (element, container) {
721
+ return container.compareDocumentPosition && (container.compareDocumentPosition(element) & 16) === 16
722
+ }
723
+ : 'contains' in root
724
+ ? function (element, container) {
725
+ container = container.nodeType === 9 || container === window ? root : container
726
+ return container !== element && container.contains(element)
727
+ }
728
+ : function (element, container) {
729
+ while (element = element.parentNode) if (element === container) return 1
730
+ return 0
731
+ }
732
+ , check = function (event) {
733
+ var related = event.relatedTarget
734
+ return !related
735
+ ? related == null
736
+ : (related !== this && related.prefix !== 'xul' && !/document/.test(this.toString())
737
+ && !isAncestor(related, this))
738
+ }
739
+
740
+ return {
741
+ mouseenter: { base: 'mouseover', condition: check }
742
+ , mouseleave: { base: 'mouseout', condition: check }
743
+ , mousewheel: { base: /Firefox/.test(navigator.userAgent) ? 'DOMMouseScroll' : 'mousewheel' }
744
+ }
745
+ }())
746
+
747
+ // we provide a consistent Event object across browsers by taking the actual DOM
748
+ // event object and generating a new one from its properties.
749
+ , Event = (function () {
750
+ // a whitelist of properties (for different event types) tells us what to check for and copy
751
+ var commonProps = str2arr('altKey attrChange attrName bubbles cancelable ctrlKey currentTarget ' +
752
+ 'detail eventPhase getModifierState isTrusted metaKey relatedNode relatedTarget shiftKey ' +
753
+ 'srcElement target timeStamp type view which propertyName')
754
+ , mouseProps = commonProps.concat(str2arr('button buttons clientX clientY dataTransfer ' +
755
+ 'fromElement offsetX offsetY pageX pageY screenX screenY toElement'))
756
+ , mouseWheelProps = mouseProps.concat(str2arr('wheelDelta wheelDeltaX wheelDeltaY wheelDeltaZ ' +
757
+ 'axis')) // 'axis' is FF specific
758
+ , keyProps = commonProps.concat(str2arr('char charCode key keyCode keyIdentifier ' +
759
+ 'keyLocation location'))
760
+ , textProps = commonProps.concat(str2arr('data'))
761
+ , touchProps = commonProps.concat(str2arr('touches targetTouches changedTouches scale rotation'))
762
+ , messageProps = commonProps.concat(str2arr('data origin source'))
763
+ , stateProps = commonProps.concat(str2arr('state'))
764
+ , overOutRegex = /over|out/
765
+ // some event types need special handling and some need special properties, do that all here
766
+ , typeFixers = [
767
+ { // key events
768
+ reg: /key/i
769
+ , fix: function (event, newEvent) {
770
+ newEvent.keyCode = event.keyCode || event.which
771
+ return keyProps
772
+ }
773
+ }
774
+ , { // mouse events
775
+ reg: /click|mouse(?!(.*wheel|scroll))|menu|drag|drop/i
776
+ , fix: function (event, newEvent, type) {
777
+ newEvent.rightClick = event.which === 3 || event.button === 2
778
+ newEvent.pos = { x: 0, y: 0 }
779
+ if (event.pageX || event.pageY) {
780
+ newEvent.clientX = event.pageX
781
+ newEvent.clientY = event.pageY
782
+ } else if (event.clientX || event.clientY) {
783
+ newEvent.clientX = event.clientX + doc.body.scrollLeft + root.scrollLeft
784
+ newEvent.clientY = event.clientY + doc.body.scrollTop + root.scrollTop
785
+ }
786
+ if (overOutRegex.test(type)) {
787
+ newEvent.relatedTarget = event.relatedTarget
788
+ || event[(type == 'mouseover' ? 'from' : 'to') + 'Element']
789
+ }
790
+ return mouseProps
791
+ }
792
+ }
793
+ , { // mouse wheel events
794
+ reg: /mouse.*(wheel|scroll)/i
795
+ , fix: function () { return mouseWheelProps }
796
+ }
797
+ , { // TextEvent
798
+ reg: /^text/i
799
+ , fix: function () { return textProps }
800
+ }
801
+ , { // touch and gesture events
802
+ reg: /^touch|^gesture/i
803
+ , fix: function () { return touchProps }
804
+ }
805
+ , { // message events
806
+ reg: /^message$/i
807
+ , fix: function () { return messageProps }
808
+ }
809
+ , { // popstate events
810
+ reg: /^popstate$/i
811
+ , fix: function () { return stateProps }
812
+ }
813
+ , { // everything else
814
+ reg: /.*/
815
+ , fix: function () { return commonProps }
816
+ }
817
+ ]
818
+ , typeFixerMap = {} // used to map event types to fixer functions (above), a basic cache mechanism
819
+
820
+ , Event = function (event, element, isNative) {
821
+ if (!arguments.length) return
822
+ event = event || ((element.ownerDocument || element.document || element).parentWindow || win).event
823
+ this.originalEvent = event
824
+ this.isNative = isNative
825
+ this.isBean = true
826
+
827
+ if (!event) return
828
+
829
+ var type = event.type
830
+ , target = event.target || event.srcElement
831
+ , i, l, p, props, fixer
832
+
833
+ this.target = target && target.nodeType === 3 ? target.parentNode : target
834
+
835
+ if (isNative) { // we only need basic augmentation on custom events, the rest expensive & pointless
836
+ fixer = typeFixerMap[type]
837
+ if (!fixer) { // haven't encountered this event type before, map a fixer function for it
838
+ for (i = 0, l = typeFixers.length; i < l; i++) {
839
+ if (typeFixers[i].reg.test(type)) { // guaranteed to match at least one, last is .*
840
+ typeFixerMap[type] = fixer = typeFixers[i].fix
841
+ break
842
+ }
843
+ }
844
+ }
845
+
846
+ props = fixer(event, this, type)
847
+ for (i = props.length; i--;) {
848
+ if (!((p = props[i]) in this) && p in event) this[p] = event[p]
849
+ }
850
+ }
851
+ }
852
+
853
+ // preventDefault() and stopPropagation() are a consistent interface to those functions
854
+ // on the DOM, stop() is an alias for both of them together
855
+ Event.prototype.preventDefault = function () {
856
+ if (this.originalEvent.preventDefault) this.originalEvent.preventDefault()
857
+ else this.originalEvent.returnValue = false
858
+ }
859
+ Event.prototype.stopPropagation = function () {
860
+ if (this.originalEvent.stopPropagation) this.originalEvent.stopPropagation()
861
+ else this.originalEvent.cancelBubble = true
862
+ }
863
+ Event.prototype.stop = function () {
864
+ this.preventDefault()
865
+ this.stopPropagation()
866
+ this.stopped = true
867
+ }
868
+ // stopImmediatePropagation() has to be handled internally because we manage the event list for
869
+ // each element
870
+ // note that originalElement may be a Bean#Event object in some situations
871
+ Event.prototype.stopImmediatePropagation = function () {
872
+ if (this.originalEvent.stopImmediatePropagation) this.originalEvent.stopImmediatePropagation()
873
+ this.isImmediatePropagationStopped = function () { return true }
874
+ }
875
+ Event.prototype.isImmediatePropagationStopped = function () {
876
+ return this.originalEvent.isImmediatePropagationStopped && this.originalEvent.isImmediatePropagationStopped()
877
+ }
878
+ Event.prototype.clone = function (currentTarget) {
879
+ //TODO: this is ripe for optimisation, new events are *expensive*
880
+ // improving this will speed up delegated events
881
+ var ne = new Event(this, this.element, this.isNative)
882
+ ne.currentTarget = currentTarget
883
+ return ne
884
+ }
885
+
886
+ return Event
887
+ }())
888
+
889
+ // if we're in old IE we can't do onpropertychange on doc or win so we use doc.documentElement for both
890
+ , targetElement = function (element, isNative) {
891
+ return !W3C_MODEL && !isNative && (element === doc || element === win) ? root : element
892
+ }
893
+
894
+ /**
895
+ * Bean maintains an internal registry for event listeners. We don't touch elements, objects
896
+ * or functions to identify them, instead we store everything in the registry.
897
+ * Each event listener has a RegEntry object, we have one 'registry' for the whole instance.
898
+ */
899
+ , RegEntry = (function () {
900
+ // each handler is wrapped so we can handle delegation and custom events
901
+ var wrappedHandler = function (element, fn, condition, args) {
902
+ var call = function (event, eargs) {
903
+ return fn.apply(element, args ? slice.call(eargs, event ? 0 : 1).concat(args) : eargs)
904
+ }
905
+ , findTarget = function (event, eventElement) {
906
+ return fn.__beanDel ? fn.__beanDel.ft(event.target, element) : eventElement
907
+ }
908
+ , handler = condition
909
+ ? function (event) {
910
+ var target = findTarget(event, this) // deleated event
911
+ if (condition.apply(target, arguments)) {
912
+ if (event) event.currentTarget = target
913
+ return call(event, arguments)
914
+ }
915
+ }
916
+ : function (event) {
917
+ if (fn.__beanDel) event = event.clone(findTarget(event)) // delegated event, fix the fix
918
+ return call(event, arguments)
919
+ }
920
+ handler.__beanDel = fn.__beanDel
921
+ return handler
922
+ }
923
+
924
+ , RegEntry = function (element, type, handler, original, namespaces, args, root) {
925
+ var customType = customEvents[type]
926
+ , isNative
927
+
928
+ if (type == 'unload') {
929
+ // self clean-up
930
+ handler = once(removeListener, element, type, handler, original)
931
+ }
932
+
933
+ if (customType) {
934
+ if (customType.condition) {
935
+ handler = wrappedHandler(element, handler, customType.condition, args)
936
+ }
937
+ type = customType.base || type
938
+ }
939
+
940
+ this.isNative = isNative = nativeEvents[type] && !!element[eventSupport]
941
+ this.customType = !W3C_MODEL && !isNative && type
942
+ this.element = element
943
+ this.type = type
944
+ this.original = original
945
+ this.namespaces = namespaces
946
+ this.eventType = W3C_MODEL || isNative ? type : 'propertychange'
947
+ this.target = targetElement(element, isNative)
948
+ this[eventSupport] = !!this.target[eventSupport]
949
+ this.root = root
950
+ this.handler = wrappedHandler(element, handler, null, args)
951
+ }
952
+
953
+ // given a list of namespaces, is our entry in any of them?
954
+ RegEntry.prototype.inNamespaces = function (checkNamespaces) {
955
+ var i, j, c = 0
956
+ if (!checkNamespaces) return true
957
+ if (!this.namespaces) return false
958
+ for (i = checkNamespaces.length; i--;) {
959
+ for (j = this.namespaces.length; j--;) {
960
+ if (checkNamespaces[i] == this.namespaces[j]) c++
961
+ }
962
+ }
963
+ return checkNamespaces.length === c
964
+ }
965
+
966
+ // match by element, original fn (opt), handler fn (opt)
967
+ RegEntry.prototype.matches = function (checkElement, checkOriginal, checkHandler) {
968
+ return this.element === checkElement &&
969
+ (!checkOriginal || this.original === checkOriginal) &&
970
+ (!checkHandler || this.handler === checkHandler)
971
+ }
972
+
973
+ return RegEntry
974
+ }())
975
+
976
+ , registry = (function () {
977
+ // our map stores arrays by event type, just because it's better than storing
978
+ // everything in a single array.
979
+ // uses '$' as a prefix for the keys for safety and 'r' as a special prefix for
980
+ // rootListeners so we can look them up fast
981
+ var map = {}
982
+
983
+ // generic functional search of our registry for matching listeners,
984
+ // `fn` returns false to break out of the loop
985
+ , forAll = function (element, type, original, handler, root, fn) {
986
+ var pfx = root ? 'r' : '$'
987
+ if (!type || type == '*') {
988
+ // search the whole registry
989
+ for (var t in map) {
990
+ if (t.charAt(0) == pfx) {
991
+ forAll(element, t.substr(1), original, handler, root, fn)
992
+ }
993
+ }
994
+ } else {
995
+ var i = 0, l, list = map[pfx + type], all = element == '*'
996
+ if (!list) return
997
+ for (l = list.length; i < l; i++) {
998
+ if ((all || list[i].matches(element, original, handler)) && !fn(list[i], list, i, type)) return
999
+ }
1000
+ }
1001
+ }
1002
+
1003
+ , has = function (element, type, original, root) {
1004
+ // we're not using forAll here simply because it's a bit slower and this
1005
+ // needs to be fast
1006
+ var i, list = map[(root ? 'r' : '$') + type]
1007
+ if (list) {
1008
+ for (i = list.length; i--;) {
1009
+ if (!list[i].root && list[i].matches(element, original, null)) return true
1010
+ }
1011
+ }
1012
+ return false
1013
+ }
1014
+
1015
+ , get = function (element, type, original, root) {
1016
+ var entries = []
1017
+ forAll(element, type, original, null, root, function (entry) {
1018
+ return entries.push(entry)
1019
+ })
1020
+ return entries
1021
+ }
1022
+
1023
+ , put = function (entry) {
1024
+ var has = !entry.root && !this.has(entry.element, entry.type, null, false)
1025
+ , key = (entry.root ? 'r' : '$') + entry.type
1026
+ ;(map[key] || (map[key] = [])).push(entry)
1027
+ return has
1028
+ }
1029
+
1030
+ , del = function (entry) {
1031
+ forAll(entry.element, entry.type, null, entry.handler, entry.root, function (entry, list, i) {
1032
+ list.splice(i, 1)
1033
+ entry.removed = true
1034
+ if (list.length === 0) delete map[(entry.root ? 'r' : '$') + entry.type]
1035
+ return false
1036
+ })
1037
+ }
1038
+
1039
+ // dump all entries, used for onunload
1040
+ , entries = function () {
1041
+ var t, entries = []
1042
+ for (t in map) {
1043
+ if (t.charAt(0) == '$') entries = entries.concat(map[t])
1044
+ }
1045
+ return entries
1046
+ }
1047
+
1048
+ return { has: has, get: get, put: put, del: del, entries: entries }
1049
+ }())
1050
+
1051
+ // we need a selector engine for delegated events, use querySelectorAll if it exists
1052
+ // but for older browsers we need Qwery, Sizzle or similar
1053
+ , selectorEngine
1054
+ , setSelectorEngine = function (e) {
1055
+ if (!arguments.length) {
1056
+ selectorEngine = doc.querySelectorAll
1057
+ ? function (s, r) {
1058
+ return r.querySelectorAll(s)
1059
+ }
1060
+ : function () {
1061
+ throw new Error('Bean: No selector engine installed') // eeek
1062
+ }
1063
+ } else {
1064
+ selectorEngine = e
1065
+ }
1066
+ }
1067
+
1068
+ // we attach this listener to each DOM event that we need to listen to, only once
1069
+ // per event type per DOM element
1070
+ , rootListener = function (event, type) {
1071
+ if (!W3C_MODEL && type && event && event.propertyName != '_on' + type) return
1072
+
1073
+ var listeners = registry.get(this, type || event.type, null, false)
1074
+ , l = listeners.length
1075
+ , i = 0
1076
+
1077
+ event = new Event(event, this, true)
1078
+ if (type) event.type = type
1079
+
1080
+ // iterate through all handlers registered for this type, calling them unless they have
1081
+ // been removed by a previous handler or stopImmediatePropagation() has been called
1082
+ for (; i < l && !event.isImmediatePropagationStopped(); i++) {
1083
+ if (!listeners[i].removed) listeners[i].handler.call(this, event)
1084
+ }
1085
+ }
1086
+
1087
+ // add and remove listeners to DOM elements
1088
+ , listener = W3C_MODEL
1089
+ ? function (element, type, add) {
1090
+ // new browsers
1091
+ element[add ? addEvent : removeEvent](type, rootListener, false)
1092
+ }
1093
+ : function (element, type, add, custom) {
1094
+ // IE8 and below, use attachEvent/detachEvent and we have to piggy-back propertychange events
1095
+ // to simulate event bubbling etc.
1096
+ var entry
1097
+ if (add) {
1098
+ registry.put(entry = new RegEntry(
1099
+ element
1100
+ , custom || type
1101
+ , function (event) { // handler
1102
+ rootListener.call(element, event, custom)
1103
+ }
1104
+ , rootListener
1105
+ , null
1106
+ , null
1107
+ , true // is root
1108
+ ))
1109
+ if (custom && element['_on' + custom] == null) element['_on' + custom] = 0
1110
+ entry.target.attachEvent('on' + entry.eventType, entry.handler)
1111
+ } else {
1112
+ entry = registry.get(element, custom || type, rootListener, true)[0]
1113
+ if (entry) {
1114
+ entry.target.detachEvent('on' + entry.eventType, entry.handler)
1115
+ registry.del(entry)
1116
+ }
1117
+ }
1118
+ }
1119
+
1120
+ , once = function (rm, element, type, fn, originalFn) {
1121
+ // wrap the handler in a handler that does a remove as well
1122
+ return function () {
1123
+ fn.apply(this, arguments)
1124
+ rm(element, type, originalFn)
1125
+ }
1126
+ }
1127
+
1128
+ , removeListener = function (element, orgType, handler, namespaces) {
1129
+ var type = orgType && orgType.replace(nameRegex, '')
1130
+ , handlers = registry.get(element, type, null, false)
1131
+ , removed = {}
1132
+ , i, l
1133
+
1134
+ for (i = 0, l = handlers.length; i < l; i++) {
1135
+ if ((!handler || handlers[i].original === handler) && handlers[i].inNamespaces(namespaces)) {
1136
+ // TODO: this is problematic, we have a registry.get() and registry.del() that
1137
+ // both do registry searches so we waste cycles doing this. Needs to be rolled into
1138
+ // a single registry.forAll(fn) that removes while finding, but the catch is that
1139
+ // we'll be splicing the arrays that we're iterating over. Needs extra tests to
1140
+ // make sure we don't screw it up. @rvagg
1141
+ registry.del(handlers[i])
1142
+ if (!removed[handlers[i].eventType] && handlers[i][eventSupport])
1143
+ removed[handlers[i].eventType] = { t: handlers[i].eventType, c: handlers[i].type }
1144
+ }
1145
+ }
1146
+ // check each type/element for removed listeners and remove the rootListener where it's no longer needed
1147
+ for (i in removed) {
1148
+ if (!registry.has(element, removed[i].t, null, false)) {
1149
+ // last listener of this type, remove the rootListener
1150
+ listener(element, removed[i].t, false, removed[i].c)
1151
+ }
1152
+ }
1153
+ }
1154
+
1155
+ // set up a delegate helper using the given selector, wrap the handler function
1156
+ , delegate = function (selector, fn) {
1157
+ //TODO: findTarget (therefore $) is called twice, once for match and once for
1158
+ // setting e.currentTarget, fix this so it's only needed once
1159
+ var findTarget = function (target, root) {
1160
+ var i, array = isString(selector) ? selectorEngine(selector, root) : selector
1161
+ for (; target && target !== root; target = target.parentNode) {
1162
+ for (i = array.length; i--;) {
1163
+ if (array[i] === target) return target
1164
+ }
1165
+ }
1166
+ }
1167
+ , handler = function (e) {
1168
+ var match = findTarget(e.target, this)
1169
+ if (match) fn.apply(match, arguments)
1170
+ }
1171
+
1172
+ // __beanDel isn't pleasant but it's a private function, not exposed outside of Bean
1173
+ handler.__beanDel = {
1174
+ ft : findTarget // attach it here for customEvents to use too
1175
+ , selector : selector
1176
+ }
1177
+ return handler
1178
+ }
1179
+
1180
+ , fireListener = W3C_MODEL ? function (isNative, type, element) {
1181
+ // modern browsers, do a proper dispatchEvent()
1182
+ var evt = doc.createEvent(isNative ? 'HTMLEvents' : 'UIEvents')
1183
+ evt[isNative ? 'initEvent' : 'initUIEvent'](type, true, true, win, 1)
1184
+ element.dispatchEvent(evt)
1185
+ } : function (isNative, type, element) {
1186
+ // old browser use onpropertychange, just increment a custom property to trigger the event
1187
+ element = targetElement(element, isNative)
1188
+ isNative ? element.fireEvent('on' + type, doc.createEventObject()) : element['_on' + type]++
1189
+ }
1190
+
1191
+ /**
1192
+ * Public API: off(), on(), add(), (remove()), one(), fire(), clone()
1193
+ */
1194
+
1195
+ /**
1196
+ * off(element[, eventType(s)[, handler ]])
1197
+ */
1198
+ , off = function (element, typeSpec, fn) {
1199
+ var isTypeStr = isString(typeSpec)
1200
+ , k, type, namespaces, i
1201
+
1202
+ if (isTypeStr && typeSpec.indexOf(' ') > 0) {
1203
+ // off(el, 't1 t2 t3', fn) or off(el, 't1 t2 t3')
1204
+ typeSpec = str2arr(typeSpec)
1205
+ for (i = typeSpec.length; i--;)
1206
+ off(element, typeSpec[i], fn)
1207
+ return element
1208
+ }
1209
+
1210
+ type = isTypeStr && typeSpec.replace(nameRegex, '')
1211
+ if (type && customEvents[type]) type = customEvents[type].base
1212
+
1213
+ if (!typeSpec || isTypeStr) {
1214
+ // off(el) or off(el, t1.ns) or off(el, .ns) or off(el, .ns1.ns2.ns3)
1215
+ if (namespaces = isTypeStr && typeSpec.replace(namespaceRegex, '')) namespaces = str2arr(namespaces, '.')
1216
+ removeListener(element, type, fn, namespaces)
1217
+ } else if (isFunction(typeSpec)) {
1218
+ // off(el, fn)
1219
+ removeListener(element, null, typeSpec)
1220
+ } else {
1221
+ // off(el, { t1: fn1, t2, fn2 })
1222
+ for (k in typeSpec) {
1223
+ if (typeSpec.hasOwnProperty(k)) off(element, k, typeSpec[k])
1224
+ }
1225
+ }
1226
+
1227
+ return element
1228
+ }
1229
+
1230
+ /**
1231
+ * on(element, eventType(s)[, selector], handler[, args ])
1232
+ */
1233
+ , on = function(element, events, selector, fn) {
1234
+ var originalFn, type, types, i, args, entry, first
1235
+
1236
+ //TODO: the undefined check means you can't pass an 'args' argument, fix this perhaps?
1237
+ if (selector === undefined && typeof events == 'object') {
1238
+ //TODO: this can't handle delegated events
1239
+ for (type in events) {
1240
+ if (events.hasOwnProperty(type)) {
1241
+ on.call(this, element, type, events[type])
1242
+ }
1243
+ }
1244
+ return
1245
+ }
1246
+
1247
+ if (!isFunction(selector)) {
1248
+ // delegated event
1249
+ originalFn = fn
1250
+ args = slice.call(arguments, 4)
1251
+ fn = delegate(selector, originalFn, selectorEngine)
1252
+ } else {
1253
+ args = slice.call(arguments, 3)
1254
+ fn = originalFn = selector
1255
+ }
1256
+
1257
+ types = str2arr(events)
1258
+
1259
+ // special case for one(), wrap in a self-removing handler
1260
+ if (this === ONE) {
1261
+ fn = once(off, element, events, fn, originalFn)
1262
+ }
1263
+
1264
+ for (i = types.length; i--;) {
1265
+ // add new handler to the registry and check if it's the first for this element/type
1266
+ first = registry.put(entry = new RegEntry(
1267
+ element
1268
+ , types[i].replace(nameRegex, '') // event type
1269
+ , fn
1270
+ , originalFn
1271
+ , str2arr(types[i].replace(namespaceRegex, ''), '.') // namespaces
1272
+ , args
1273
+ , false // not root
1274
+ ))
1275
+ if (entry[eventSupport] && first) {
1276
+ // first event of this type on this element, add root listener
1277
+ listener(element, entry.eventType, true, entry.customType)
1278
+ }
1279
+ }
1280
+
1281
+ return element
1282
+ }
1283
+
1284
+ /**
1285
+ * add(element[, selector], eventType(s), handler[, args ])
1286
+ *
1287
+ * Deprecated: kept (for now) for backward-compatibility
1288
+ */
1289
+ , add = function (element, events, fn, delfn) {
1290
+ return on.apply(
1291
+ null
1292
+ , !isString(fn)
1293
+ ? slice.call(arguments)
1294
+ : [ element, fn, events, delfn ].concat(arguments.length > 3 ? slice.call(arguments, 5) : [])
1295
+ )
1296
+ }
1297
+
1298
+ /**
1299
+ * one(element, eventType(s)[, selector], handler[, args ])
1300
+ */
1301
+ , one = function () {
1302
+ return on.apply(ONE, arguments)
1303
+ }
1304
+
1305
+ /**
1306
+ * fire(element, eventType(s)[, args ])
1307
+ *
1308
+ * The optional 'args' argument must be an array, if no 'args' argument is provided
1309
+ * then we can use the browser's DOM event system, otherwise we trigger handlers manually
1310
+ */
1311
+ , fire = function (element, type, args) {
1312
+ var types = str2arr(type)
1313
+ , i, j, l, names, handlers
1314
+
1315
+ for (i = types.length; i--;) {
1316
+ type = types[i].replace(nameRegex, '')
1317
+ if (names = types[i].replace(namespaceRegex, '')) names = str2arr(names, '.')
1318
+ if (!names && !args && element[eventSupport]) {
1319
+ fireListener(nativeEvents[type], type, element)
1320
+ } else {
1321
+ // non-native event, either because of a namespace, arguments or a non DOM element
1322
+ // iterate over all listeners and manually 'fire'
1323
+ handlers = registry.get(element, type, null, false)
1324
+ args = [false].concat(args)
1325
+ for (j = 0, l = handlers.length; j < l; j++) {
1326
+ if (handlers[j].inNamespaces(names)) {
1327
+ handlers[j].handler.apply(element, args)
1328
+ }
1329
+ }
1330
+ }
1331
+ }
1332
+ return element
1333
+ }
1334
+
1335
+ /**
1336
+ * clone(dstElement, srcElement[, eventType ])
1337
+ *
1338
+ * TODO: perhaps for consistency we should allow the same flexibility in type specifiers?
1339
+ */
1340
+ , clone = function (element, from, type) {
1341
+ var handlers = registry.get(from, type, null, false)
1342
+ , l = handlers.length
1343
+ , i = 0
1344
+ , args, beanDel
1345
+
1346
+ for (; i < l; i++) {
1347
+ if (handlers[i].original) {
1348
+ args = [ element, handlers[i].type ]
1349
+ if (beanDel = handlers[i].handler.__beanDel) args.push(beanDel.selector)
1350
+ args.push(handlers[i].original)
1351
+ on.apply(null, args)
1352
+ }
1353
+ }
1354
+ return element
1355
+ }
1356
+
1357
+ , bean = {
1358
+ on : on
1359
+ , add : add
1360
+ , one : one
1361
+ , off : off
1362
+ , remove : off
1363
+ , clone : clone
1364
+ , fire : fire
1365
+ , setSelectorEngine : setSelectorEngine
1366
+ , noConflict : function () {
1367
+ context[name] = old
1368
+ return this
1369
+ }
1370
+ }
1371
+
1372
+ // for IE, clean up on unload to avoid leaks
1373
+ if (win.attachEvent) {
1374
+ var cleanup = function () {
1375
+ var i, entries = registry.entries()
1376
+ for (i in entries) {
1377
+ if (entries[i].type && entries[i].type !== 'unload') off(entries[i].element, entries[i].type)
1378
+ }
1379
+ win.detachEvent('onunload', cleanup)
1380
+ win.CollectGarbage && win.CollectGarbage()
1381
+ }
1382
+ win.attachEvent('onunload', cleanup)
1383
+ }
1384
+
1385
+ // initialize selector engine to internal default (qSA or throw Error)
1386
+ setSelectorEngine()
1387
+
1388
+ return bean
1389
+ }));
1390
+
1391
+
1392
+ provide("bean", module.exports);
1393
+
1394
+ !function ($) {
1395
+ var b = require('bean')
1396
+
1397
+ , integrate = function (method, type, method2) {
1398
+ var _args = type ? [type] : []
1399
+ return function () {
1400
+ for (var i = 0, l = this.length; i < l; i++) {
1401
+ if (!arguments.length && method == 'on' && type) method = 'fire'
1402
+ b[method].apply(this, [this[i]].concat(_args, Array.prototype.slice.call(arguments, 0)))
1403
+ }
1404
+ return this
1405
+ }
1406
+ }
1407
+
1408
+ , add = integrate('add')
1409
+ , on = integrate('on')
1410
+ , one = integrate('one')
1411
+ , off = integrate('off')
1412
+ , fire = integrate('fire')
1413
+ , clone = integrate('clone')
1414
+
1415
+ , hover = function (enter, leave, i) { // i for internal
1416
+ for (i = this.length; i--;) {
1417
+ b.on.call(this, this[i], 'mouseenter', enter)
1418
+ b.on.call(this, this[i], 'mouseleave', leave)
1419
+ }
1420
+ return this
1421
+ }
1422
+
1423
+ , methods = {
1424
+ on : on
1425
+ , addListener : on
1426
+ , bind : on
1427
+ , listen : on
1428
+ , delegate : add // jQuery compat, same arg order as add()
1429
+
1430
+ , one : one
1431
+
1432
+ , off : off
1433
+ , unbind : off
1434
+ , unlisten : off
1435
+ , removeListener : off
1436
+ , undelegate : off
1437
+
1438
+ , emit : fire
1439
+ , trigger : fire
1440
+
1441
+ , cloneEvents : clone
1442
+
1443
+ , hover : hover
1444
+ }
1445
+
1446
+ , shortcuts =
1447
+ ('blur change click dblclick error focus focusin focusout keydown keypress '
1448
+ + 'keyup load mousedown mouseenter mouseleave mouseout mouseover mouseup '
1449
+ + 'mousemove resize scroll select submit unload').split(' ')
1450
+
1451
+ for (var i = shortcuts.length; i--;) {
1452
+ methods[shortcuts[i]] = integrate('on', shortcuts[i])
1453
+ }
1454
+
1455
+ b.setSelectorEngine($)
1456
+
1457
+ $.ender(methods, true)
1458
+ }(ender);
1459
+
1460
+ }());
1461
+
1462
+ (function () {
1463
+
1464
+ var module = { exports: {} }, exports = module.exports;
1465
+
1466
+ /*!
1467
+ * domready (c) Dustin Diaz 2012 - License MIT
1468
+ */
1469
+ !function (name, definition) {
1470
+ if (typeof module != 'undefined') module.exports = definition()
1471
+ else if (typeof define == 'function' && typeof define.amd == 'object') define(definition)
1472
+ else this[name] = definition()
1473
+ }('domready', function (ready) {
1474
+
1475
+ var fns = [], fn, f = false
1476
+ , doc = document
1477
+ , testEl = doc.documentElement
1478
+ , hack = testEl.doScroll
1479
+ , domContentLoaded = 'DOMContentLoaded'
1480
+ , addEventListener = 'addEventListener'
1481
+ , onreadystatechange = 'onreadystatechange'
1482
+ , readyState = 'readyState'
1483
+ , loaded = /^loade|c/.test(doc[readyState])
1484
+
1485
+ function flush(f) {
1486
+ loaded = 1
1487
+ while (f = fns.shift()) f()
1488
+ }
1489
+
1490
+ doc[addEventListener] && doc[addEventListener](domContentLoaded, fn = function () {
1491
+ doc.removeEventListener(domContentLoaded, fn, f)
1492
+ flush()
1493
+ }, f)
1494
+
1495
+
1496
+ hack && doc.attachEvent(onreadystatechange, fn = function () {
1497
+ if (/^c/.test(doc[readyState])) {
1498
+ doc.detachEvent(onreadystatechange, fn)
1499
+ flush()
1500
+ }
1501
+ })
1502
+
1503
+ return (ready = hack ?
1504
+ function (fn) {
1505
+ self != top ?
1506
+ loaded ? fn() : fns.push(fn) :
1507
+ function () {
1508
+ try {
1509
+ testEl.doScroll('left')
1510
+ } catch (e) {
1511
+ return setTimeout(function() { ready(fn) }, 50)
1512
+ }
1513
+ fn()
1514
+ }()
1515
+ } :
1516
+ function (fn) {
1517
+ loaded ? fn() : fns.push(fn)
1518
+ })
1519
+ })
1520
+
1521
+ provide("domready", module.exports);
1522
+
1523
+ !function ($) {
1524
+ var ready = require('domready')
1525
+ $.ender({domReady: ready})
1526
+ $.ender({
1527
+ ready: function (f) {
1528
+ ready(f)
1529
+ return this
1530
+ }
1531
+ }, true)
1532
+ }(ender);
1533
+
1534
+ }());
1535
+
1536
+ (function () {
1537
+
1538
+ var module = { exports: {} }, exports = module.exports;
1539
+
1540
+ /*!
1541
+ * @preserve Qwery - A Blazing Fast query selector engine
1542
+ * https://github.com/ded/qwery
1543
+ * copyright Dustin Diaz 2012
1544
+ * MIT License
1545
+ */
1546
+
1547
+ (function (name, context, definition) {
1548
+ if (typeof module != 'undefined' && module.exports) module.exports = definition()
1549
+ else if (typeof context['define'] == 'function' && context['define']['amd']) define(definition)
1550
+ else context[name] = definition()
1551
+ })('qwery', this, function () {
1552
+ var doc = document
1553
+ , html = doc.documentElement
1554
+ , byClass = 'getElementsByClassName'
1555
+ , byTag = 'getElementsByTagName'
1556
+ , qSA = 'querySelectorAll'
1557
+ , useNativeQSA = 'useNativeQSA'
1558
+ , tagName = 'tagName'
1559
+ , nodeType = 'nodeType'
1560
+ , select // main select() method, assign later
1561
+
1562
+ , id = /#([\w\-]+)/
1563
+ , clas = /\.[\w\-]+/g
1564
+ , idOnly = /^#([\w\-]+)$/
1565
+ , classOnly = /^\.([\w\-]+)$/
1566
+ , tagOnly = /^([\w\-]+)$/
1567
+ , tagAndOrClass = /^([\w]+)?\.([\w\-]+)$/
1568
+ , splittable = /(^|,)\s*[>~+]/
1569
+ , normalizr = /^\s+|\s*([,\s\+\~>]|$)\s*/g
1570
+ , splitters = /[\s\>\+\~]/
1571
+ , splittersMore = /(?![\s\w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^'"]*\]|[\s\w\+\-]*\))/
1572
+ , specialChars = /([.*+?\^=!:${}()|\[\]\/\\])/g
1573
+ , simple = /^(\*|[a-z0-9]+)?(?:([\.\#]+[\w\-\.#]+)?)/
1574
+ , attr = /\[([\w\-]+)(?:([\|\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/
1575
+ , pseudo = /:([\w\-]+)(\(['"]?([^()]+)['"]?\))?/
1576
+ , easy = new RegExp(idOnly.source + '|' + tagOnly.source + '|' + classOnly.source)
1577
+ , dividers = new RegExp('(' + splitters.source + ')' + splittersMore.source, 'g')
1578
+ , tokenizr = new RegExp(splitters.source + splittersMore.source)
1579
+ , chunker = new RegExp(simple.source + '(' + attr.source + ')?' + '(' + pseudo.source + ')?')
1580
+
1581
+ var walker = {
1582
+ ' ': function (node) {
1583
+ return node && node !== html && node.parentNode
1584
+ }
1585
+ , '>': function (node, contestant) {
1586
+ return node && node.parentNode == contestant.parentNode && node.parentNode
1587
+ }
1588
+ , '~': function (node) {
1589
+ return node && node.previousSibling
1590
+ }
1591
+ , '+': function (node, contestant, p1, p2) {
1592
+ if (!node) return false
1593
+ return (p1 = previous(node)) && (p2 = previous(contestant)) && p1 == p2 && p1
1594
+ }
1595
+ }
1596
+
1597
+ function cache() {
1598
+ this.c = {}
1599
+ }
1600
+ cache.prototype = {
1601
+ g: function (k) {
1602
+ return this.c[k] || undefined
1603
+ }
1604
+ , s: function (k, v, r) {
1605
+ v = r ? new RegExp(v) : v
1606
+ return (this.c[k] = v)
1607
+ }
1608
+ }
1609
+
1610
+ var classCache = new cache()
1611
+ , cleanCache = new cache()
1612
+ , attrCache = new cache()
1613
+ , tokenCache = new cache()
1614
+
1615
+ function classRegex(c) {
1616
+ return classCache.g(c) || classCache.s(c, '(^|\\s+)' + c + '(\\s+|$)', 1)
1617
+ }
1618
+
1619
+ // not quite as fast as inline loops in older browsers so don't use liberally
1620
+ function each(a, fn) {
1621
+ var i = 0, l = a.length
1622
+ for (; i < l; i++) fn(a[i])
1623
+ }
1624
+
1625
+ function flatten(ar) {
1626
+ for (var r = [], i = 0, l = ar.length; i < l; ++i) arrayLike(ar[i]) ? (r = r.concat(ar[i])) : (r[r.length] = ar[i])
1627
+ return r
1628
+ }
1629
+
1630
+ function arrayify(ar) {
1631
+ var i = 0, l = ar.length, r = []
1632
+ for (; i < l; i++) r[i] = ar[i]
1633
+ return r
1634
+ }
1635
+
1636
+ function previous(n) {
1637
+ while (n = n.previousSibling) if (n[nodeType] == 1) break;
1638
+ return n
1639
+ }
1640
+
1641
+ function q(query) {
1642
+ return query.match(chunker)
1643
+ }
1644
+
1645
+ // called using `this` as element and arguments from regex group results.
1646
+ // given => div.hello[title="world"]:foo('bar')
1647
+ // div.hello[title="world"]:foo('bar'), div, .hello, [title="world"], title, =, world, :foo('bar'), foo, ('bar'), bar]
1648
+ function interpret(whole, tag, idsAndClasses, wholeAttribute, attribute, qualifier, value, wholePseudo, pseudo, wholePseudoVal, pseudoVal) {
1649
+ var i, m, k, o, classes
1650
+ if (this[nodeType] !== 1) return false
1651
+ if (tag && tag !== '*' && this[tagName] && this[tagName].toLowerCase() !== tag) return false
1652
+ if (idsAndClasses && (m = idsAndClasses.match(id)) && m[1] !== this.id) return false
1653
+ if (idsAndClasses && (classes = idsAndClasses.match(clas))) {
1654
+ for (i = classes.length; i--;) if (!classRegex(classes[i].slice(1)).test(this.className)) return false
1655
+ }
1656
+ if (pseudo && qwery.pseudos[pseudo] && !qwery.pseudos[pseudo](this, pseudoVal)) return false
1657
+ if (wholeAttribute && !value) { // select is just for existance of attrib
1658
+ o = this.attributes
1659
+ for (k in o) {
1660
+ if (Object.prototype.hasOwnProperty.call(o, k) && (o[k].name || k) == attribute) {
1661
+ return this
1662
+ }
1663
+ }
1664
+ }
1665
+ if (wholeAttribute && !checkAttr(qualifier, getAttr(this, attribute) || '', value)) {
1666
+ // select is for attrib equality
1667
+ return false
1668
+ }
1669
+ return this
1670
+ }
1671
+
1672
+ function clean(s) {
1673
+ return cleanCache.g(s) || cleanCache.s(s, s.replace(specialChars, '\\$1'))
1674
+ }
1675
+
1676
+ function checkAttr(qualify, actual, val) {
1677
+ switch (qualify) {
1678
+ case '=':
1679
+ return actual == val
1680
+ case '^=':
1681
+ return actual.match(attrCache.g('^=' + val) || attrCache.s('^=' + val, '^' + clean(val), 1))
1682
+ case '$=':
1683
+ return actual.match(attrCache.g('$=' + val) || attrCache.s('$=' + val, clean(val) + '$', 1))
1684
+ case '*=':
1685
+ return actual.match(attrCache.g(val) || attrCache.s(val, clean(val), 1))
1686
+ case '~=':
1687
+ return actual.match(attrCache.g('~=' + val) || attrCache.s('~=' + val, '(?:^|\\s+)' + clean(val) + '(?:\\s+|$)', 1))
1688
+ case '|=':
1689
+ return actual.match(attrCache.g('|=' + val) || attrCache.s('|=' + val, '^' + clean(val) + '(-|$)', 1))
1690
+ }
1691
+ return 0
1692
+ }
1693
+
1694
+ // given a selector, first check for simple cases then collect all base candidate matches and filter
1695
+ function _qwery(selector, _root) {
1696
+ var r = [], ret = [], i, l, m, token, tag, els, intr, item, root = _root
1697
+ , tokens = tokenCache.g(selector) || tokenCache.s(selector, selector.split(tokenizr))
1698
+ , dividedTokens = selector.match(dividers)
1699
+
1700
+ if (!tokens.length) return r
1701
+
1702
+ token = (tokens = tokens.slice(0)).pop() // copy cached tokens, take the last one
1703
+ if (tokens.length && (m = tokens[tokens.length - 1].match(idOnly))) root = byId(_root, m[1])
1704
+ if (!root) return r
1705
+
1706
+ intr = q(token)
1707
+ // collect base candidates to filter
1708
+ els = root !== _root && root[nodeType] !== 9 && dividedTokens && /^[+~]$/.test(dividedTokens[dividedTokens.length - 1]) ?
1709
+ function (r) {
1710
+ while (root = root.nextSibling) {
1711
+ root[nodeType] == 1 && (intr[1] ? intr[1] == root[tagName].toLowerCase() : 1) && (r[r.length] = root)
1712
+ }
1713
+ return r
1714
+ }([]) :
1715
+ root[byTag](intr[1] || '*')
1716
+ // filter elements according to the right-most part of the selector
1717
+ for (i = 0, l = els.length; i < l; i++) {
1718
+ if (item = interpret.apply(els[i], intr)) r[r.length] = item
1719
+ }
1720
+ if (!tokens.length) return r
1721
+
1722
+ // filter further according to the rest of the selector (the left side)
1723
+ each(r, function (e) { if (ancestorMatch(e, tokens, dividedTokens)) ret[ret.length] = e })
1724
+ return ret
1725
+ }
1726
+
1727
+ // compare element to a selector
1728
+ function is(el, selector, root) {
1729
+ if (isNode(selector)) return el == selector
1730
+ if (arrayLike(selector)) return !!~flatten(selector).indexOf(el) // if selector is an array, is el a member?
1731
+
1732
+ var selectors = selector.split(','), tokens, dividedTokens
1733
+ while (selector = selectors.pop()) {
1734
+ tokens = tokenCache.g(selector) || tokenCache.s(selector, selector.split(tokenizr))
1735
+ dividedTokens = selector.match(dividers)
1736
+ tokens = tokens.slice(0) // copy array
1737
+ if (interpret.apply(el, q(tokens.pop())) && (!tokens.length || ancestorMatch(el, tokens, dividedTokens, root))) {
1738
+ return true
1739
+ }
1740
+ }
1741
+ return false
1742
+ }
1743
+
1744
+ // given elements matching the right-most part of a selector, filter out any that don't match the rest
1745
+ function ancestorMatch(el, tokens, dividedTokens, root) {
1746
+ var cand
1747
+ // recursively work backwards through the tokens and up the dom, covering all options
1748
+ function crawl(e, i, p) {
1749
+ while (p = walker[dividedTokens[i]](p, e)) {
1750
+ if (isNode(p) && (interpret.apply(p, q(tokens[i])))) {
1751
+ if (i) {
1752
+ if (cand = crawl(p, i - 1, p)) return cand
1753
+ } else return p
1754
+ }
1755
+ }
1756
+ }
1757
+ return (cand = crawl(el, tokens.length - 1, el)) && (!root || isAncestor(cand, root))
1758
+ }
1759
+
1760
+ function isNode(el, t) {
1761
+ return el && typeof el === 'object' && (t = el[nodeType]) && (t == 1 || t == 9)
1762
+ }
1763
+
1764
+ function uniq(ar) {
1765
+ var a = [], i, j;
1766
+ o:
1767
+ for (i = 0; i < ar.length; ++i) {
1768
+ for (j = 0; j < a.length; ++j) if (a[j] == ar[i]) continue o
1769
+ a[a.length] = ar[i]
1770
+ }
1771
+ return a
1772
+ }
1773
+
1774
+ function arrayLike(o) {
1775
+ return (typeof o === 'object' && isFinite(o.length))
1776
+ }
1777
+
1778
+ function normalizeRoot(root) {
1779
+ if (!root) return doc
1780
+ if (typeof root == 'string') return qwery(root)[0]
1781
+ if (!root[nodeType] && arrayLike(root)) return root[0]
1782
+ return root
1783
+ }
1784
+
1785
+ function byId(root, id, el) {
1786
+ // if doc, query on it, else query the parent doc or if a detached fragment rewrite the query and run on the fragment
1787
+ return root[nodeType] === 9 ? root.getElementById(id) :
1788
+ root.ownerDocument &&
1789
+ (((el = root.ownerDocument.getElementById(id)) && isAncestor(el, root) && el) ||
1790
+ (!isAncestor(root, root.ownerDocument) && select('[id="' + id + '"]', root)[0]))
1791
+ }
1792
+
1793
+ function qwery(selector, _root) {
1794
+ var m, el, root = normalizeRoot(_root)
1795
+
1796
+ // easy, fast cases that we can dispatch with simple DOM calls
1797
+ if (!root || !selector) return []
1798
+ if (selector === window || isNode(selector)) {
1799
+ return !_root || (selector !== window && isNode(root) && isAncestor(selector, root)) ? [selector] : []
1800
+ }
1801
+ if (selector && arrayLike(selector)) return flatten(selector)
1802
+ if (m = selector.match(easy)) {
1803
+ if (m[1]) return (el = byId(root, m[1])) ? [el] : []
1804
+ if (m[2]) return arrayify(root[byTag](m[2]))
1805
+ if (hasByClass && m[3]) return arrayify(root[byClass](m[3]))
1806
+ }
1807
+
1808
+ return select(selector, root)
1809
+ }
1810
+
1811
+ // where the root is not document and a relationship selector is first we have to
1812
+ // do some awkward adjustments to get it to work, even with qSA
1813
+ function collectSelector(root, collector) {
1814
+ return function (s) {
1815
+ var oid, nid
1816
+ if (splittable.test(s)) {
1817
+ if (root[nodeType] !== 9) {
1818
+ // make sure the el has an id, rewrite the query, set root to doc and run it
1819
+ if (!(nid = oid = root.getAttribute('id'))) root.setAttribute('id', nid = '__qwerymeupscotty')
1820
+ s = '[id="' + nid + '"]' + s // avoid byId and allow us to match context element
1821
+ collector(root.parentNode || root, s, true)
1822
+ oid || root.removeAttribute('id')
1823
+ }
1824
+ return;
1825
+ }
1826
+ s.length && collector(root, s, false)
1827
+ }
1828
+ }
1829
+
1830
+ var isAncestor = 'compareDocumentPosition' in html ?
1831
+ function (element, container) {
1832
+ return (container.compareDocumentPosition(element) & 16) == 16
1833
+ } : 'contains' in html ?
1834
+ function (element, container) {
1835
+ container = container[nodeType] === 9 || container == window ? html : container
1836
+ return container !== element && container.contains(element)
1837
+ } :
1838
+ function (element, container) {
1839
+ while (element = element.parentNode) if (element === container) return 1
1840
+ return 0
1841
+ }
1842
+ , getAttr = function () {
1843
+ // detect buggy IE src/href getAttribute() call
1844
+ var e = doc.createElement('p')
1845
+ return ((e.innerHTML = '<a href="#x">x</a>') && e.firstChild.getAttribute('href') != '#x') ?
1846
+ function (e, a) {
1847
+ return a === 'class' ? e.className : (a === 'href' || a === 'src') ?
1848
+ e.getAttribute(a, 2) : e.getAttribute(a)
1849
+ } :
1850
+ function (e, a) { return e.getAttribute(a) }
1851
+ }()
1852
+ , hasByClass = !!doc[byClass]
1853
+ // has native qSA support
1854
+ , hasQSA = doc.querySelector && doc[qSA]
1855
+ // use native qSA
1856
+ , selectQSA = function (selector, root) {
1857
+ var result = [], ss, e
1858
+ try {
1859
+ if (root[nodeType] === 9 || !splittable.test(selector)) {
1860
+ // most work is done right here, defer to qSA
1861
+ return arrayify(root[qSA](selector))
1862
+ }
1863
+ // special case where we need the services of `collectSelector()`
1864
+ each(ss = selector.split(','), collectSelector(root, function (ctx, s) {
1865
+ e = ctx[qSA](s)
1866
+ if (e.length == 1) result[result.length] = e.item(0)
1867
+ else if (e.length) result = result.concat(arrayify(e))
1868
+ }))
1869
+ return ss.length > 1 && result.length > 1 ? uniq(result) : result
1870
+ } catch (ex) { }
1871
+ return selectNonNative(selector, root)
1872
+ }
1873
+ // no native selector support
1874
+ , selectNonNative = function (selector, root) {
1875
+ var result = [], items, m, i, l, r, ss
1876
+ selector = selector.replace(normalizr, '$1')
1877
+ if (m = selector.match(tagAndOrClass)) {
1878
+ r = classRegex(m[2])
1879
+ items = root[byTag](m[1] || '*')
1880
+ for (i = 0, l = items.length; i < l; i++) {
1881
+ if (r.test(items[i].className)) result[result.length] = items[i]
1882
+ }
1883
+ return result
1884
+ }
1885
+ // more complex selector, get `_qwery()` to do the work for us
1886
+ each(ss = selector.split(','), collectSelector(root, function (ctx, s, rewrite) {
1887
+ r = _qwery(s, ctx)
1888
+ for (i = 0, l = r.length; i < l; i++) {
1889
+ if (ctx[nodeType] === 9 || rewrite || isAncestor(r[i], root)) result[result.length] = r[i]
1890
+ }
1891
+ }))
1892
+ return ss.length > 1 && result.length > 1 ? uniq(result) : result
1893
+ }
1894
+ , configure = function (options) {
1895
+ // configNativeQSA: use fully-internal selector or native qSA where present
1896
+ if (typeof options[useNativeQSA] !== 'undefined')
1897
+ select = !options[useNativeQSA] ? selectNonNative : hasQSA ? selectQSA : selectNonNative
1898
+ }
1899
+
1900
+ configure({ useNativeQSA: true })
1901
+
1902
+ qwery.configure = configure
1903
+ qwery.uniq = uniq
1904
+ qwery.is = is
1905
+ qwery.pseudos = {}
1906
+
1907
+ return qwery
1908
+ });
1909
+
1910
+
1911
+ provide("qwery", module.exports);
1912
+
1913
+ (function ($) {
1914
+ var q = function () {
1915
+ var r
1916
+ try {
1917
+ r = require('qwery')
1918
+ } catch (ex) {
1919
+ r = require('qwery-mobile')
1920
+ } finally {
1921
+ return r
1922
+ }
1923
+ }()
1924
+
1925
+ $.pseudos = q.pseudos
1926
+
1927
+ $._select = function (s, r) {
1928
+ // detect if sibling module 'bonzo' is available at run-time
1929
+ // rather than load-time since technically it's not a dependency and
1930
+ // can be loaded in any order
1931
+ // hence the lazy function re-definition
1932
+ return ($._select = (function () {
1933
+ var b
1934
+ if (typeof $.create == 'function') return function (s, r) {
1935
+ return /^\s*</.test(s) ? $.create(s, r) : q(s, r)
1936
+ }
1937
+ try {
1938
+ b = require('bonzo')
1939
+ return function (s, r) {
1940
+ return /^\s*</.test(s) ? b.create(s, r) : q(s, r)
1941
+ }
1942
+ } catch (e) { }
1943
+ return q
1944
+ })())(s, r)
1945
+ }
1946
+
1947
+ $.ender({
1948
+ find: function (s) {
1949
+ var r = [], i, l, j, k, els
1950
+ for (i = 0, l = this.length; i < l; i++) {
1951
+ els = q(s, this[i])
1952
+ for (j = 0, k = els.length; j < k; j++) r.push(els[j])
1953
+ }
1954
+ return $(q.uniq(r))
1955
+ }
1956
+ , and: function (s) {
1957
+ var plus = $(s)
1958
+ for (var i = this.length, j = 0, l = this.length + plus.length; i < l; i++, j++) {
1959
+ this[i] = plus[j]
1960
+ }
1961
+ this.length += plus.length
1962
+ return this
1963
+ }
1964
+ , is: function(s, r) {
1965
+ var i, l
1966
+ for (i = 0, l = this.length; i < l; i++) {
1967
+ if (q.is(this[i], s, r)) {
1968
+ return true
1969
+ }
1970
+ }
1971
+ return false
1972
+ }
1973
+ }, true)
1974
+ }(ender));
1975
+
1976
+
1977
+ }());
1978
+
1979
+ (function () {
1980
+
1981
+ var module = { exports: {} }, exports = module.exports;
1982
+
1983
+ /*!
1984
+ * Bonzo: DOM Utility (c) Dustin Diaz 2012
1985
+ * https://github.com/ded/bonzo
1986
+ * License MIT
1987
+ */
1988
+ (function (name, context, definition) {
1989
+ if (typeof module != 'undefined' && module.exports) module.exports = definition()
1990
+ else if (typeof context['define'] == 'function' && context['define']['amd']) define(definition)
1991
+ else context[name] = definition()
1992
+ })('bonzo', this, function() {
1993
+ var win = window
1994
+ , doc = win.document
1995
+ , html = doc.documentElement
1996
+ , parentNode = 'parentNode'
1997
+ , specialAttributes = /^(checked|value|selected|disabled)$/i
1998
+ , specialTags = /^(select|fieldset|table|tbody|tfoot|td|tr|colgroup)$/i // tags that we have trouble inserting *into*
1999
+ , simpleScriptTagRe = /\s*<script +src=['"]([^'"]+)['"]>/
2000
+ , table = ['<table>', '</table>', 1]
2001
+ , td = ['<table><tbody><tr>', '</tr></tbody></table>', 3]
2002
+ , option = ['<select>', '</select>', 1]
2003
+ , noscope = ['_', '', 0, 1]
2004
+ , tagMap = { // tags that we have trouble *inserting*
2005
+ thead: table, tbody: table, tfoot: table, colgroup: table, caption: table
2006
+ , tr: ['<table><tbody>', '</tbody></table>', 2]
2007
+ , th: td , td: td
2008
+ , col: ['<table><colgroup>', '</colgroup></table>', 2]
2009
+ , fieldset: ['<form>', '</form>', 1]
2010
+ , legend: ['<form><fieldset>', '</fieldset></form>', 2]
2011
+ , option: option, optgroup: option
2012
+ , script: noscope, style: noscope, link: noscope, param: noscope, base: noscope
2013
+ }
2014
+ , stateAttributes = /^(checked|selected|disabled)$/
2015
+ , ie = /msie/i.test(navigator.userAgent)
2016
+ , hasClass, addClass, removeClass
2017
+ , uidMap = {}
2018
+ , uuids = 0
2019
+ , digit = /^-?[\d\.]+$/
2020
+ , dattr = /^data-(.+)$/
2021
+ , px = 'px'
2022
+ , setAttribute = 'setAttribute'
2023
+ , getAttribute = 'getAttribute'
2024
+ , byTag = 'getElementsByTagName'
2025
+ , features = function() {
2026
+ var e = doc.createElement('p')
2027
+ e.innerHTML = '<a href="#x">x</a><table style="float:left;"></table>'
2028
+ return {
2029
+ hrefExtended: e[byTag]('a')[0][getAttribute]('href') != '#x' // IE < 8
2030
+ , autoTbody: e[byTag]('tbody').length !== 0 // IE < 8
2031
+ , computedStyle: doc.defaultView && doc.defaultView.getComputedStyle
2032
+ , cssFloat: e[byTag]('table')[0].style.styleFloat ? 'styleFloat' : 'cssFloat'
2033
+ , transform: function () {
2034
+ var props = ['transform', 'webkitTransform', 'MozTransform', 'OTransform', 'msTransform'], i
2035
+ for (i = 0; i < props.length; i++) {
2036
+ if (props[i] in e.style) return props[i]
2037
+ }
2038
+ }()
2039
+ , classList: 'classList' in e
2040
+ , opasity: function () {
2041
+ return typeof doc.createElement('a').style.opacity !== 'undefined'
2042
+ }()
2043
+ }
2044
+ }()
2045
+ , trimReplace = /(^\s*|\s*$)/g
2046
+ , whitespaceRegex = /\s+/
2047
+ , toString = String.prototype.toString
2048
+ , unitless = { lineHeight: 1, zoom: 1, zIndex: 1, opacity: 1, boxFlex: 1, WebkitBoxFlex: 1, MozBoxFlex: 1 }
2049
+ , query = doc.querySelectorAll && function (selector) { return doc.querySelectorAll(selector) }
2050
+ , trim = String.prototype.trim ?
2051
+ function (s) {
2052
+ return s.trim()
2053
+ } :
2054
+ function (s) {
2055
+ return s.replace(trimReplace, '')
2056
+ }
2057
+
2058
+
2059
+ function isNode(node) {
2060
+ return node && node.nodeName && (node.nodeType == 1 || node.nodeType == 11)
2061
+ }
2062
+
2063
+
2064
+ function normalize(node, host, clone) {
2065
+ var i, l, ret
2066
+ if (typeof node == 'string') return bonzo.create(node)
2067
+ if (isNode(node)) node = [ node ]
2068
+ if (clone) {
2069
+ ret = [] // don't change original array
2070
+ for (i = 0, l = node.length; i < l; i++) ret[i] = cloneNode(host, node[i])
2071
+ return ret
2072
+ }
2073
+ return node
2074
+ }
2075
+
2076
+
2077
+ /**
2078
+ * @param {string} c a class name to test
2079
+ * @return {boolean}
2080
+ */
2081
+ function classReg(c) {
2082
+ return new RegExp("(^|\\s+)" + c + "(\\s+|$)")
2083
+ }
2084
+
2085
+
2086
+ /**
2087
+ * @param {Bonzo|Array} ar
2088
+ * @param {function(Object, number, (Bonzo|Array))} fn
2089
+ * @param {Object=} opt_scope
2090
+ * @param {boolean=} opt_rev
2091
+ * @return {Bonzo|Array}
2092
+ */
2093
+ function each(ar, fn, opt_scope, opt_rev) {
2094
+ var ind, i = 0, l = ar.length
2095
+ for (; i < l; i++) {
2096
+ ind = opt_rev ? ar.length - i - 1 : i
2097
+ fn.call(opt_scope || ar[ind], ar[ind], ind, ar)
2098
+ }
2099
+ return ar
2100
+ }
2101
+
2102
+
2103
+ /**
2104
+ * @param {Bonzo|Array} ar
2105
+ * @param {function(Object, number, (Bonzo|Array))} fn
2106
+ * @param {Object=} opt_scope
2107
+ * @return {Bonzo|Array}
2108
+ */
2109
+ function deepEach(ar, fn, opt_scope) {
2110
+ for (var i = 0, l = ar.length; i < l; i++) {
2111
+ if (isNode(ar[i])) {
2112
+ deepEach(ar[i].childNodes, fn, opt_scope)
2113
+ fn.call(opt_scope || ar[i], ar[i], i, ar)
2114
+ }
2115
+ }
2116
+ return ar
2117
+ }
2118
+
2119
+
2120
+ /**
2121
+ * @param {string} s
2122
+ * @return {string}
2123
+ */
2124
+ function camelize(s) {
2125
+ return s.replace(/-(.)/g, function (m, m1) {
2126
+ return m1.toUpperCase()
2127
+ })
2128
+ }
2129
+
2130
+
2131
+ /**
2132
+ * @param {string} s
2133
+ * @return {string}
2134
+ */
2135
+ function decamelize(s) {
2136
+ return s ? s.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() : s
2137
+ }
2138
+
2139
+
2140
+ /**
2141
+ * @param {Element} el
2142
+ * @return {*}
2143
+ */
2144
+ function data(el) {
2145
+ el[getAttribute]('data-node-uid') || el[setAttribute]('data-node-uid', ++uuids)
2146
+ var uid = el[getAttribute]('data-node-uid')
2147
+ return uidMap[uid] || (uidMap[uid] = {})
2148
+ }
2149
+
2150
+
2151
+ /**
2152
+ * removes the data associated with an element
2153
+ * @param {Element} el
2154
+ */
2155
+ function clearData(el) {
2156
+ var uid = el[getAttribute]('data-node-uid')
2157
+ if (uid) delete uidMap[uid]
2158
+ }
2159
+
2160
+
2161
+ function dataValue(d) {
2162
+ var f
2163
+ try {
2164
+ return (d === null || d === undefined) ? undefined :
2165
+ d === 'true' ? true :
2166
+ d === 'false' ? false :
2167
+ d === 'null' ? null :
2168
+ (f = parseFloat(d)) == d ? f : d;
2169
+ } catch(e) {}
2170
+ return undefined
2171
+ }
2172
+
2173
+
2174
+ /**
2175
+ * @param {Bonzo|Array} ar
2176
+ * @param {function(Object, number, (Bonzo|Array))} fn
2177
+ * @param {Object=} opt_scope
2178
+ * @return {boolean} whether `some`thing was found
2179
+ */
2180
+ function some(ar, fn, opt_scope) {
2181
+ for (var i = 0, j = ar.length; i < j; ++i) if (fn.call(opt_scope || null, ar[i], i, ar)) return true
2182
+ return false
2183
+ }
2184
+
2185
+
2186
+ /**
2187
+ * this could be a giant enum of CSS properties
2188
+ * but in favor of file size sans-closure deadcode optimizations
2189
+ * we're just asking for any ol string
2190
+ * then it gets transformed into the appropriate style property for JS access
2191
+ * @param {string} p
2192
+ * @return {string}
2193
+ */
2194
+ function styleProperty(p) {
2195
+ (p == 'transform' && (p = features.transform)) ||
2196
+ (/^transform-?[Oo]rigin$/.test(p) && (p = features.transform + 'Origin')) ||
2197
+ (p == 'float' && (p = features.cssFloat))
2198
+ return p ? camelize(p) : null
2199
+ }
2200
+
2201
+ var getStyle = features.computedStyle ?
2202
+ function (el, property) {
2203
+ var value = null
2204
+ , computed = doc.defaultView.getComputedStyle(el, '')
2205
+ computed && (value = computed[property])
2206
+ return el.style[property] || value
2207
+ } :
2208
+
2209
+ (ie && html.currentStyle) ?
2210
+
2211
+ /**
2212
+ * @param {Element} el
2213
+ * @param {string} property
2214
+ * @return {string|number}
2215
+ */
2216
+ function (el, property) {
2217
+ if (property == 'opacity' && !features.opasity) {
2218
+ var val = 100
2219
+ try {
2220
+ val = el['filters']['DXImageTransform.Microsoft.Alpha'].opacity
2221
+ } catch (e1) {
2222
+ try {
2223
+ val = el['filters']('alpha').opacity
2224
+ } catch (e2) {}
2225
+ }
2226
+ return val / 100
2227
+ }
2228
+ var value = el.currentStyle ? el.currentStyle[property] : null
2229
+ return el.style[property] || value
2230
+ } :
2231
+
2232
+ function (el, property) {
2233
+ return el.style[property]
2234
+ }
2235
+
2236
+ // this insert method is intense
2237
+ function insert(target, host, fn, rev) {
2238
+ var i = 0, self = host || this, r = []
2239
+ // target nodes could be a css selector if it's a string and a selector engine is present
2240
+ // otherwise, just use target
2241
+ , nodes = query && typeof target == 'string' && target.charAt(0) != '<' ? query(target) : target
2242
+ // normalize each node in case it's still a string and we need to create nodes on the fly
2243
+ each(normalize(nodes), function (t, j) {
2244
+ each(self, function (el) {
2245
+ fn(t, r[i++] = j > 0 ? cloneNode(self, el) : el)
2246
+ }, null, rev)
2247
+ }, this, rev)
2248
+ self.length = i
2249
+ each(r, function (e) {
2250
+ self[--i] = e
2251
+ }, null, !rev)
2252
+ return self
2253
+ }
2254
+
2255
+
2256
+ /**
2257
+ * sets an element to an explicit x/y position on the page
2258
+ * @param {Element} el
2259
+ * @param {?number} x
2260
+ * @param {?number} y
2261
+ */
2262
+ function xy(el, x, y) {
2263
+ var $el = bonzo(el)
2264
+ , style = $el.css('position')
2265
+ , offset = $el.offset()
2266
+ , rel = 'relative'
2267
+ , isRel = style == rel
2268
+ , delta = [parseInt($el.css('left'), 10), parseInt($el.css('top'), 10)]
2269
+
2270
+ if (style == 'static') {
2271
+ $el.css('position', rel)
2272
+ style = rel
2273
+ }
2274
+
2275
+ isNaN(delta[0]) && (delta[0] = isRel ? 0 : el.offsetLeft)
2276
+ isNaN(delta[1]) && (delta[1] = isRel ? 0 : el.offsetTop)
2277
+
2278
+ x != null && (el.style.left = x - offset.left + delta[0] + px)
2279
+ y != null && (el.style.top = y - offset.top + delta[1] + px)
2280
+
2281
+ }
2282
+
2283
+ // classList support for class management
2284
+ // altho to be fair, the api sucks because it won't accept multiple classes at once
2285
+ if (features.classList) {
2286
+ hasClass = function (el, c) {
2287
+ return el.classList.contains(c)
2288
+ }
2289
+ addClass = function (el, c) {
2290
+ el.classList.add(c)
2291
+ }
2292
+ removeClass = function (el, c) {
2293
+ el.classList.remove(c)
2294
+ }
2295
+ }
2296
+ else {
2297
+ hasClass = function (el, c) {
2298
+ return classReg(c).test(el.className)
2299
+ }
2300
+ addClass = function (el, c) {
2301
+ el.className = trim(el.className + ' ' + c)
2302
+ }
2303
+ removeClass = function (el, c) {
2304
+ el.className = trim(el.className.replace(classReg(c), ' '))
2305
+ }
2306
+ }
2307
+
2308
+
2309
+ /**
2310
+ * this allows method calling for setting values
2311
+ *
2312
+ * @example
2313
+ * bonzo(elements).css('color', function (el) {
2314
+ * return el.getAttribute('data-original-color')
2315
+ * })
2316
+ *
2317
+ * @param {Element} el
2318
+ * @param {function (Element)|string}
2319
+ * @return {string}
2320
+ */
2321
+ function setter(el, v) {
2322
+ return typeof v == 'function' ? v(el) : v
2323
+ }
2324
+
2325
+ /**
2326
+ * @constructor
2327
+ * @param {Array.<Element>|Element|Node|string} elements
2328
+ */
2329
+ function Bonzo(elements) {
2330
+ this.length = 0
2331
+ if (elements) {
2332
+ elements = typeof elements !== 'string' &&
2333
+ !elements.nodeType &&
2334
+ typeof elements.length !== 'undefined' ?
2335
+ elements :
2336
+ [elements]
2337
+ this.length = elements.length
2338
+ for (var i = 0; i < elements.length; i++) this[i] = elements[i]
2339
+ }
2340
+ }
2341
+
2342
+ Bonzo.prototype = {
2343
+
2344
+ /**
2345
+ * @param {number} index
2346
+ * @return {Element|Node}
2347
+ */
2348
+ get: function (index) {
2349
+ return this[index] || null
2350
+ }
2351
+
2352
+ // itetators
2353
+ /**
2354
+ * @param {function(Element|Node)} fn
2355
+ * @param {Object=} opt_scope
2356
+ * @return {Bonzo}
2357
+ */
2358
+ , each: function (fn, opt_scope) {
2359
+ return each(this, fn, opt_scope)
2360
+ }
2361
+
2362
+ /**
2363
+ * @param {Function} fn
2364
+ * @param {Object=} opt_scope
2365
+ * @return {Bonzo}
2366
+ */
2367
+ , deepEach: function (fn, opt_scope) {
2368
+ return deepEach(this, fn, opt_scope)
2369
+ }
2370
+
2371
+
2372
+ /**
2373
+ * @param {Function} fn
2374
+ * @param {Function=} opt_reject
2375
+ * @return {Array}
2376
+ */
2377
+ , map: function (fn, opt_reject) {
2378
+ var m = [], n, i
2379
+ for (i = 0; i < this.length; i++) {
2380
+ n = fn.call(this, this[i], i)
2381
+ opt_reject ? (opt_reject(n) && m.push(n)) : m.push(n)
2382
+ }
2383
+ return m
2384
+ }
2385
+
2386
+ // text and html inserters!
2387
+
2388
+ /**
2389
+ * @param {string} h the HTML to insert
2390
+ * @param {boolean=} opt_text whether to set or get text content
2391
+ * @return {Bonzo|string}
2392
+ */
2393
+ , html: function (h, opt_text) {
2394
+ var method = opt_text
2395
+ ? html.textContent === undefined ? 'innerText' : 'textContent'
2396
+ : 'innerHTML'
2397
+ , that = this
2398
+ , append = function (el, i) {
2399
+ each(normalize(h, that, i), function (node) {
2400
+ el.appendChild(node)
2401
+ })
2402
+ }
2403
+ , updateElement = function (el, i) {
2404
+ try {
2405
+ if (opt_text || (typeof h == 'string' && !specialTags.test(el.tagName))) {
2406
+ return el[method] = h
2407
+ }
2408
+ } catch (e) {}
2409
+ append(el, i)
2410
+ }
2411
+ return typeof h != 'undefined'
2412
+ ? this.empty().each(updateElement)
2413
+ : this[0] ? this[0][method] : ''
2414
+ }
2415
+
2416
+ /**
2417
+ * @param {string=} opt_text the text to set, otherwise this is a getter
2418
+ * @return {Bonzo|string}
2419
+ */
2420
+ , text: function (opt_text) {
2421
+ return this.html(opt_text, true)
2422
+ }
2423
+
2424
+ // more related insertion methods
2425
+
2426
+ /**
2427
+ * @param {Bonzo|string|Element|Array} node
2428
+ * @return {Bonzo}
2429
+ */
2430
+ , append: function (node) {
2431
+ var that = this
2432
+ return this.each(function (el, i) {
2433
+ each(normalize(node, that, i), function (i) {
2434
+ el.appendChild(i)
2435
+ })
2436
+ })
2437
+ }
2438
+
2439
+
2440
+ /**
2441
+ * @param {Bonzo|string|Element|Array} node
2442
+ * @return {Bonzo}
2443
+ */
2444
+ , prepend: function (node) {
2445
+ var that = this
2446
+ return this.each(function (el, i) {
2447
+ var first = el.firstChild
2448
+ each(normalize(node, that, i), function (i) {
2449
+ el.insertBefore(i, first)
2450
+ })
2451
+ })
2452
+ }
2453
+
2454
+
2455
+ /**
2456
+ * @param {Bonzo|string|Element|Array} target the location for which you'll insert your new content
2457
+ * @param {Object=} opt_host an optional host scope (primarily used when integrated with Ender)
2458
+ * @return {Bonzo}
2459
+ */
2460
+ , appendTo: function (target, opt_host) {
2461
+ return insert.call(this, target, opt_host, function (t, el) {
2462
+ t.appendChild(el)
2463
+ })
2464
+ }
2465
+
2466
+
2467
+ /**
2468
+ * @param {Bonzo|string|Element|Array} target the location for which you'll insert your new content
2469
+ * @param {Object=} opt_host an optional host scope (primarily used when integrated with Ender)
2470
+ * @return {Bonzo}
2471
+ */
2472
+ , prependTo: function (target, opt_host) {
2473
+ return insert.call(this, target, opt_host, function (t, el) {
2474
+ t.insertBefore(el, t.firstChild)
2475
+ }, 1)
2476
+ }
2477
+
2478
+
2479
+ /**
2480
+ * @param {Bonzo|string|Element|Array} node
2481
+ * @return {Bonzo}
2482
+ */
2483
+ , before: function (node) {
2484
+ var that = this
2485
+ return this.each(function (el, i) {
2486
+ each(normalize(node, that, i), function (i) {
2487
+ el[parentNode].insertBefore(i, el)
2488
+ })
2489
+ })
2490
+ }
2491
+
2492
+
2493
+ /**
2494
+ * @param {Bonzo|string|Element|Array} node
2495
+ * @return {Bonzo}
2496
+ */
2497
+ , after: function (node) {
2498
+ var that = this
2499
+ return this.each(function (el, i) {
2500
+ each(normalize(node, that, i), function (i) {
2501
+ el[parentNode].insertBefore(i, el.nextSibling)
2502
+ }, null, 1)
2503
+ })
2504
+ }
2505
+
2506
+
2507
+ /**
2508
+ * @param {Bonzo|string|Element|Array} target the location for which you'll insert your new content
2509
+ * @param {Object=} opt_host an optional host scope (primarily used when integrated with Ender)
2510
+ * @return {Bonzo}
2511
+ */
2512
+ , insertBefore: function (target, opt_host) {
2513
+ return insert.call(this, target, opt_host, function (t, el) {
2514
+ t[parentNode].insertBefore(el, t)
2515
+ })
2516
+ }
2517
+
2518
+
2519
+ /**
2520
+ * @param {Bonzo|string|Element|Array} target the location for which you'll insert your new content
2521
+ * @param {Object=} opt_host an optional host scope (primarily used when integrated with Ender)
2522
+ * @return {Bonzo}
2523
+ */
2524
+ , insertAfter: function (target, opt_host) {
2525
+ return insert.call(this, target, opt_host, function (t, el) {
2526
+ var sibling = t.nextSibling
2527
+ sibling ?
2528
+ t[parentNode].insertBefore(el, sibling) :
2529
+ t[parentNode].appendChild(el)
2530
+ }, 1)
2531
+ }
2532
+
2533
+
2534
+ /**
2535
+ * @param {Bonzo|string|Element|Array} node
2536
+ * @return {Bonzo}
2537
+ */
2538
+ , replaceWith: function (node) {
2539
+ bonzo(normalize(node)).insertAfter(this)
2540
+ return this.remove()
2541
+ }
2542
+
2543
+ // class management
2544
+
2545
+ /**
2546
+ * @param {string} c
2547
+ * @return {Bonzo}
2548
+ */
2549
+ , addClass: function (c) {
2550
+ c = toString.call(c).split(whitespaceRegex)
2551
+ return this.each(function (el) {
2552
+ // we `each` here so you can do $el.addClass('foo bar')
2553
+ each(c, function (c) {
2554
+ if (c && !hasClass(el, setter(el, c)))
2555
+ addClass(el, setter(el, c))
2556
+ })
2557
+ })
2558
+ }
2559
+
2560
+
2561
+ /**
2562
+ * @param {string} c
2563
+ * @return {Bonzo}
2564
+ */
2565
+ , removeClass: function (c) {
2566
+ c = toString.call(c).split(whitespaceRegex)
2567
+ return this.each(function (el) {
2568
+ each(c, function (c) {
2569
+ if (c && hasClass(el, setter(el, c)))
2570
+ removeClass(el, setter(el, c))
2571
+ })
2572
+ })
2573
+ }
2574
+
2575
+
2576
+ /**
2577
+ * @param {string} c
2578
+ * @return {boolean}
2579
+ */
2580
+ , hasClass: function (c) {
2581
+ c = toString.call(c).split(whitespaceRegex)
2582
+ return some(this, function (el) {
2583
+ return some(c, function (c) {
2584
+ return c && hasClass(el, c)
2585
+ })
2586
+ })
2587
+ }
2588
+
2589
+
2590
+ /**
2591
+ * @param {string} c classname to toggle
2592
+ * @param {boolean=} opt_condition whether to add or remove the class straight away
2593
+ * @return {Bonzo}
2594
+ */
2595
+ , toggleClass: function (c, opt_condition) {
2596
+ c = toString.call(c).split(whitespaceRegex)
2597
+ return this.each(function (el) {
2598
+ each(c, function (c) {
2599
+ if (c) {
2600
+ typeof opt_condition !== 'undefined' ?
2601
+ opt_condition ? !hasClass(el, c) && addClass(el, c) : removeClass(el, c) :
2602
+ hasClass(el, c) ? removeClass(el, c) : addClass(el, c)
2603
+ }
2604
+ })
2605
+ })
2606
+ }
2607
+
2608
+ // display togglers
2609
+
2610
+ /**
2611
+ * @param {string=} opt_type useful to set back to anything other than an empty string
2612
+ * @return {Bonzo}
2613
+ */
2614
+ , show: function (opt_type) {
2615
+ opt_type = typeof opt_type == 'string' ? opt_type : ''
2616
+ return this.each(function (el) {
2617
+ el.style.display = opt_type
2618
+ })
2619
+ }
2620
+
2621
+
2622
+ /**
2623
+ * @return {Bonzo}
2624
+ */
2625
+ , hide: function () {
2626
+ return this.each(function (el) {
2627
+ el.style.display = 'none'
2628
+ })
2629
+ }
2630
+
2631
+
2632
+ /**
2633
+ * @param {Function=} opt_callback
2634
+ * @param {string=} opt_type
2635
+ * @return {Bonzo}
2636
+ */
2637
+ , toggle: function (opt_callback, opt_type) {
2638
+ opt_type = typeof opt_type == 'string' ? opt_type : '';
2639
+ typeof opt_callback != 'function' && (opt_callback = null)
2640
+ return this.each(function (el) {
2641
+ el.style.display = (el.offsetWidth || el.offsetHeight) ? 'none' : opt_type;
2642
+ opt_callback && opt_callback.call(el)
2643
+ })
2644
+ }
2645
+
2646
+
2647
+ // DOM Walkers & getters
2648
+
2649
+ /**
2650
+ * @return {Element|Node}
2651
+ */
2652
+ , first: function () {
2653
+ return bonzo(this.length ? this[0] : [])
2654
+ }
2655
+
2656
+
2657
+ /**
2658
+ * @return {Element|Node}
2659
+ */
2660
+ , last: function () {
2661
+ return bonzo(this.length ? this[this.length - 1] : [])
2662
+ }
2663
+
2664
+
2665
+ /**
2666
+ * @return {Element|Node}
2667
+ */
2668
+ , next: function () {
2669
+ return this.related('nextSibling')
2670
+ }
2671
+
2672
+
2673
+ /**
2674
+ * @return {Element|Node}
2675
+ */
2676
+ , previous: function () {
2677
+ return this.related('previousSibling')
2678
+ }
2679
+
2680
+
2681
+ /**
2682
+ * @return {Element|Node}
2683
+ */
2684
+ , parent: function() {
2685
+ return this.related(parentNode)
2686
+ }
2687
+
2688
+
2689
+ /**
2690
+ * @private
2691
+ * @param {string} method the directional DOM method
2692
+ * @return {Element|Node}
2693
+ */
2694
+ , related: function (method) {
2695
+ return this.map(
2696
+ function (el) {
2697
+ el = el[method]
2698
+ while (el && el.nodeType !== 1) {
2699
+ el = el[method]
2700
+ }
2701
+ return el || 0
2702
+ },
2703
+ function (el) {
2704
+ return el
2705
+ }
2706
+ )
2707
+ }
2708
+
2709
+
2710
+ /**
2711
+ * @return {Bonzo}
2712
+ */
2713
+ , focus: function () {
2714
+ this.length && this[0].focus()
2715
+ return this
2716
+ }
2717
+
2718
+
2719
+ /**
2720
+ * @return {Bonzo}
2721
+ */
2722
+ , blur: function () {
2723
+ this.length && this[0].blur()
2724
+ return this
2725
+ }
2726
+
2727
+ // style getter setter & related methods
2728
+
2729
+ /**
2730
+ * @param {Object|string} o
2731
+ * @param {string=} opt_v
2732
+ * @return {Bonzo|string}
2733
+ */
2734
+ , css: function (o, opt_v) {
2735
+ var p, iter = o
2736
+ // is this a request for just getting a style?
2737
+ if (opt_v === undefined && typeof o == 'string') {
2738
+ // repurpose 'v'
2739
+ opt_v = this[0]
2740
+ if (!opt_v) return null
2741
+ if (opt_v === doc || opt_v === win) {
2742
+ p = (opt_v === doc) ? bonzo.doc() : bonzo.viewport()
2743
+ return o == 'width' ? p.width : o == 'height' ? p.height : ''
2744
+ }
2745
+ return (o = styleProperty(o)) ? getStyle(opt_v, o) : null
2746
+ }
2747
+
2748
+ if (typeof o == 'string') {
2749
+ iter = {}
2750
+ iter[o] = opt_v
2751
+ }
2752
+
2753
+ if (ie && iter.opacity) {
2754
+ // oh this 'ol gamut
2755
+ iter.filter = 'alpha(opacity=' + (iter.opacity * 100) + ')'
2756
+ // give it layout
2757
+ iter.zoom = o.zoom || 1;
2758
+ delete iter.opacity;
2759
+ }
2760
+
2761
+ function fn(el, p, v) {
2762
+ for (var k in iter) {
2763
+ if (iter.hasOwnProperty(k)) {
2764
+ v = iter[k];
2765
+ // change "5" to "5px" - unless you're line-height, which is allowed
2766
+ (p = styleProperty(k)) && digit.test(v) && !(p in unitless) && (v += px)
2767
+ try { el.style[p] = setter(el, v) } catch(e) {}
2768
+ }
2769
+ }
2770
+ }
2771
+ return this.each(fn)
2772
+ }
2773
+
2774
+
2775
+ /**
2776
+ * @param {number=} opt_x
2777
+ * @param {number=} opt_y
2778
+ * @return {Bonzo|number}
2779
+ */
2780
+ , offset: function (opt_x, opt_y) {
2781
+ if (opt_x && typeof opt_x == 'object' && (typeof opt_x.top == 'number' || typeof opt_x.left == 'number')) {
2782
+ return this.each(function (el) {
2783
+ xy(el, opt_x.left, opt_x.top)
2784
+ })
2785
+ } else if (typeof opt_x == 'number' || typeof opt_y == 'number') {
2786
+ return this.each(function (el) {
2787
+ xy(el, opt_x, opt_y)
2788
+ })
2789
+ }
2790
+ if (!this[0]) return {
2791
+ top: 0
2792
+ , left: 0
2793
+ , height: 0
2794
+ , width: 0
2795
+ }
2796
+ var el = this[0]
2797
+ , de = el.ownerDocument.documentElement
2798
+ , bcr = el.getBoundingClientRect()
2799
+ , scroll = getWindowScroll()
2800
+ , width = el.offsetWidth
2801
+ , height = el.offsetHeight
2802
+ , top = bcr.top + scroll.y - Math.max(0, de && de.clientTop, doc.body.clientTop)
2803
+ , left = bcr.left + scroll.x - Math.max(0, de && de.clientLeft, doc.body.clientLeft)
2804
+
2805
+ return {
2806
+ top: top
2807
+ , left: left
2808
+ , height: height
2809
+ , width: width
2810
+ }
2811
+ }
2812
+
2813
+
2814
+ /**
2815
+ * @return {number}
2816
+ */
2817
+ , dim: function () {
2818
+ if (!this.length) return { height: 0, width: 0 }
2819
+ var el = this[0]
2820
+ , de = el.nodeType == 9 && el.documentElement // document
2821
+ , orig = !de && !!el.style && !el.offsetWidth && !el.offsetHeight ?
2822
+ // el isn't visible, can't be measured properly, so fix that
2823
+ function (t) {
2824
+ var s = {
2825
+ position: el.style.position || ''
2826
+ , visibility: el.style.visibility || ''
2827
+ , display: el.style.display || ''
2828
+ }
2829
+ t.first().css({
2830
+ position: 'absolute'
2831
+ , visibility: 'hidden'
2832
+ , display: 'block'
2833
+ })
2834
+ return s
2835
+ }(this) : null
2836
+ , width = de
2837
+ ? Math.max(el.body.scrollWidth, el.body.offsetWidth, de.scrollWidth, de.offsetWidth, de.clientWidth)
2838
+ : el.offsetWidth
2839
+ , height = de
2840
+ ? Math.max(el.body.scrollHeight, el.body.offsetHeight, de.scrollWidth, de.offsetWidth, de.clientHeight)
2841
+ : el.offsetHeight
2842
+
2843
+ orig && this.first().css(orig)
2844
+ return {
2845
+ height: height
2846
+ , width: width
2847
+ }
2848
+ }
2849
+
2850
+ // attributes are hard. go shopping
2851
+
2852
+ /**
2853
+ * @param {string} k an attribute to get or set
2854
+ * @param {string=} opt_v the value to set
2855
+ * @return {Bonzo|string}
2856
+ */
2857
+ , attr: function (k, opt_v) {
2858
+ var el = this[0]
2859
+ if (typeof k != 'string' && !(k instanceof String)) {
2860
+ for (var n in k) {
2861
+ k.hasOwnProperty(n) && this.attr(n, k[n])
2862
+ }
2863
+ return this
2864
+ }
2865
+ return typeof opt_v == 'undefined' ?
2866
+ !el ? null : specialAttributes.test(k) ?
2867
+ stateAttributes.test(k) && typeof el[k] == 'string' ?
2868
+ true : el[k] : (k == 'href' || k =='src') && features.hrefExtended ?
2869
+ el[getAttribute](k, 2) : el[getAttribute](k) :
2870
+ this.each(function (el) {
2871
+ specialAttributes.test(k) ? (el[k] = setter(el, opt_v)) : el[setAttribute](k, setter(el, opt_v))
2872
+ })
2873
+ }
2874
+
2875
+
2876
+ /**
2877
+ * @param {string} k
2878
+ * @return {Bonzo}
2879
+ */
2880
+ , removeAttr: function (k) {
2881
+ return this.each(function (el) {
2882
+ stateAttributes.test(k) ? (el[k] = false) : el.removeAttribute(k)
2883
+ })
2884
+ }
2885
+
2886
+
2887
+ /**
2888
+ * @param {string=} opt_s
2889
+ * @return {Bonzo|string}
2890
+ */
2891
+ , val: function (s) {
2892
+ return (typeof s == 'string') ?
2893
+ this.attr('value', s) :
2894
+ this.length ? this[0].value : null
2895
+ }
2896
+
2897
+ // use with care and knowledge. this data() method uses data attributes on the DOM nodes
2898
+ // to do this differently costs a lot more code. c'est la vie
2899
+ /**
2900
+ * @param {string|Object=} opt_k the key for which to get or set data
2901
+ * @param {Object=} opt_v
2902
+ * @return {Bonzo|Object}
2903
+ */
2904
+ , data: function (opt_k, opt_v) {
2905
+ var el = this[0], o, m
2906
+ if (typeof opt_v === 'undefined') {
2907
+ if (!el) return null
2908
+ o = data(el)
2909
+ if (typeof opt_k === 'undefined') {
2910
+ each(el.attributes, function (a) {
2911
+ (m = ('' + a.name).match(dattr)) && (o[camelize(m[1])] = dataValue(a.value))
2912
+ })
2913
+ return o
2914
+ } else {
2915
+ if (typeof o[opt_k] === 'undefined')
2916
+ o[opt_k] = dataValue(this.attr('data-' + decamelize(opt_k)))
2917
+ return o[opt_k]
2918
+ }
2919
+ } else {
2920
+ return this.each(function (el) { data(el)[opt_k] = opt_v })
2921
+ }
2922
+ }
2923
+
2924
+ // DOM detachment & related
2925
+
2926
+ /**
2927
+ * @return {Bonzo}
2928
+ */
2929
+ , remove: function () {
2930
+ this.deepEach(clearData)
2931
+ return this.detach()
2932
+ }
2933
+
2934
+
2935
+ /**
2936
+ * @return {Bonzo}
2937
+ */
2938
+ , empty: function () {
2939
+ return this.each(function (el) {
2940
+ deepEach(el.childNodes, clearData)
2941
+
2942
+ while (el.firstChild) {
2943
+ el.removeChild(el.firstChild)
2944
+ }
2945
+ })
2946
+ }
2947
+
2948
+
2949
+ /**
2950
+ * @return {Bonzo}
2951
+ */
2952
+ , detach: function () {
2953
+ return this.each(function (el) {
2954
+ el[parentNode] && el[parentNode].removeChild(el)
2955
+ })
2956
+ }
2957
+
2958
+ // who uses a mouse anyway? oh right.
2959
+
2960
+ /**
2961
+ * @param {number} y
2962
+ */
2963
+ , scrollTop: function (y) {
2964
+ return scroll.call(this, null, y, 'y')
2965
+ }
2966
+
2967
+
2968
+ /**
2969
+ * @param {number} x
2970
+ */
2971
+ , scrollLeft: function (x) {
2972
+ return scroll.call(this, x, null, 'x')
2973
+ }
2974
+
2975
+ }
2976
+
2977
+
2978
+ function cloneNode(host, el) {
2979
+ var c = el.cloneNode(true)
2980
+ , cloneElems
2981
+ , elElems
2982
+
2983
+ // check for existence of an event cloner
2984
+ // preferably https://github.com/fat/bean
2985
+ // otherwise Bonzo won't do this for you
2986
+ if (host.$ && typeof host.cloneEvents == 'function') {
2987
+ host.$(c).cloneEvents(el)
2988
+
2989
+ // clone events from every child node
2990
+ cloneElems = host.$(c).find('*')
2991
+ elElems = host.$(el).find('*')
2992
+
2993
+ for (var i = 0; i < elElems.length; i++)
2994
+ host.$(cloneElems[i]).cloneEvents(elElems[i])
2995
+ }
2996
+ return c
2997
+ }
2998
+
2999
+ function scroll(x, y, type) {
3000
+ var el = this[0]
3001
+ if (!el) return this
3002
+ if (x == null && y == null) {
3003
+ return (isBody(el) ? getWindowScroll() : { x: el.scrollLeft, y: el.scrollTop })[type]
3004
+ }
3005
+ if (isBody(el)) {
3006
+ win.scrollTo(x, y)
3007
+ } else {
3008
+ x != null && (el.scrollLeft = x)
3009
+ y != null && (el.scrollTop = y)
3010
+ }
3011
+ return this
3012
+ }
3013
+
3014
+ function isBody(element) {
3015
+ return element === win || (/^(?:body|html)$/i).test(element.tagName)
3016
+ }
3017
+
3018
+ function getWindowScroll() {
3019
+ return { x: win.pageXOffset || html.scrollLeft, y: win.pageYOffset || html.scrollTop }
3020
+ }
3021
+
3022
+ function createScriptFromHtml(html) {
3023
+ var scriptEl = document.createElement('script')
3024
+ , matches = html.match(simpleScriptTagRe)
3025
+ scriptEl.src = matches[1]
3026
+ return scriptEl
3027
+ }
3028
+
3029
+ /**
3030
+ * @param {Array.<Element>|Element|Node|string} els
3031
+ * @return {Bonzo}
3032
+ */
3033
+ function bonzo(els) {
3034
+ return new Bonzo(els)
3035
+ }
3036
+
3037
+ bonzo.setQueryEngine = function (q) {
3038
+ query = q;
3039
+ delete bonzo.setQueryEngine
3040
+ }
3041
+
3042
+ bonzo.aug = function (o, target) {
3043
+ // for those standalone bonzo users. this love is for you.
3044
+ for (var k in o) {
3045
+ o.hasOwnProperty(k) && ((target || Bonzo.prototype)[k] = o[k])
3046
+ }
3047
+ }
3048
+
3049
+ bonzo.create = function (node) {
3050
+ // hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
3051
+ return typeof node == 'string' && node !== '' ?
3052
+ function () {
3053
+ if (simpleScriptTagRe.test(node)) return [createScriptFromHtml(node)]
3054
+ var tag = node.match(/^\s*<([^\s>]+)/)
3055
+ , el = doc.createElement('div')
3056
+ , els = []
3057
+ , p = tag ? tagMap[tag[1].toLowerCase()] : null
3058
+ , dep = p ? p[2] + 1 : 1
3059
+ , ns = p && p[3]
3060
+ , pn = parentNode
3061
+ , tb = features.autoTbody && p && p[0] == '<table>' && !(/<tbody/i).test(node)
3062
+
3063
+ el.innerHTML = p ? (p[0] + node + p[1]) : node
3064
+ while (dep--) el = el.firstChild
3065
+ // for IE NoScope, we may insert cruft at the begining just to get it to work
3066
+ if (ns && el && el.nodeType !== 1) el = el.nextSibling
3067
+ do {
3068
+ // tbody special case for IE<8, creates tbody on any empty table
3069
+ // we don't want it if we're just after a <thead>, <caption>, etc.
3070
+ if ((!tag || el.nodeType == 1) && (!tb || (el.tagName && el.tagName != 'TBODY'))) {
3071
+ els.push(el)
3072
+ }
3073
+ } while (el = el.nextSibling)
3074
+ // IE < 9 gives us a parentNode which messes up insert() check for cloning
3075
+ // `dep` > 1 can also cause problems with the insert() check (must do this last)
3076
+ each(els, function(el) { el[pn] && el[pn].removeChild(el) })
3077
+ return els
3078
+ }() : isNode(node) ? [node.cloneNode(true)] : []
3079
+ }
3080
+
3081
+ bonzo.doc = function () {
3082
+ var vp = bonzo.viewport()
3083
+ return {
3084
+ width: Math.max(doc.body.scrollWidth, html.scrollWidth, vp.width)
3085
+ , height: Math.max(doc.body.scrollHeight, html.scrollHeight, vp.height)
3086
+ }
3087
+ }
3088
+
3089
+ bonzo.firstChild = function (el) {
3090
+ for (var c = el.childNodes, i = 0, j = (c && c.length) || 0, e; i < j; i++) {
3091
+ if (c[i].nodeType === 1) e = c[j = i]
3092
+ }
3093
+ return e
3094
+ }
3095
+
3096
+ bonzo.viewport = function () {
3097
+ return {
3098
+ width: ie ? html.clientWidth : self.innerWidth
3099
+ , height: ie ? html.clientHeight : self.innerHeight
3100
+ }
3101
+ }
3102
+
3103
+ bonzo.isAncestor = 'compareDocumentPosition' in html ?
3104
+ function (container, element) {
3105
+ return (container.compareDocumentPosition(element) & 16) == 16
3106
+ } : 'contains' in html ?
3107
+ function (container, element) {
3108
+ return container !== element && container.contains(element);
3109
+ } :
3110
+ function (container, element) {
3111
+ while (element = element[parentNode]) {
3112
+ if (element === container) {
3113
+ return true
3114
+ }
3115
+ }
3116
+ return false
3117
+ }
3118
+
3119
+ return bonzo
3120
+ }); // the only line we care about using a semi-colon. placed here for concatenation tools
3121
+
3122
+
3123
+ provide("bonzo", module.exports);
3124
+
3125
+ (function ($) {
3126
+
3127
+ var b = require('bonzo')
3128
+ b.setQueryEngine($)
3129
+ $.ender(b)
3130
+ $.ender(b(), true)
3131
+ $.ender({
3132
+ create: function (node) {
3133
+ return $(b.create(node))
3134
+ }
3135
+ })
3136
+
3137
+ $.id = function (id) {
3138
+ return $([document.getElementById(id)])
3139
+ }
3140
+
3141
+ function indexOf(ar, val) {
3142
+ for (var i = 0; i < ar.length; i++) if (ar[i] === val) return i
3143
+ return -1
3144
+ }
3145
+
3146
+ function uniq(ar) {
3147
+ var r = [], i = 0, j = 0, k, item, inIt
3148
+ for (; item = ar[i]; ++i) {
3149
+ inIt = false
3150
+ for (k = 0; k < r.length; ++k) {
3151
+ if (r[k] === item) {
3152
+ inIt = true; break
3153
+ }
3154
+ }
3155
+ if (!inIt) r[j++] = item
3156
+ }
3157
+ return r
3158
+ }
3159
+
3160
+ $.ender({
3161
+ parents: function (selector, closest) {
3162
+ if (!this.length) return this
3163
+ if (!selector) selector = '*'
3164
+ var collection = $(selector), j, k, p, r = []
3165
+ for (j = 0, k = this.length; j < k; j++) {
3166
+ p = this[j]
3167
+ while (p = p.parentNode) {
3168
+ if (~indexOf(collection, p)) {
3169
+ r.push(p)
3170
+ if (closest) break;
3171
+ }
3172
+ }
3173
+ }
3174
+ return $(uniq(r))
3175
+ }
3176
+
3177
+ , parent: function() {
3178
+ return $(uniq(b(this).parent()))
3179
+ }
3180
+
3181
+ , closest: function (selector) {
3182
+ return this.parents(selector, true)
3183
+ }
3184
+
3185
+ , first: function () {
3186
+ return $(this.length ? this[0] : this)
3187
+ }
3188
+
3189
+ , last: function () {
3190
+ return $(this.length ? this[this.length - 1] : [])
3191
+ }
3192
+
3193
+ , next: function () {
3194
+ return $(b(this).next())
3195
+ }
3196
+
3197
+ , previous: function () {
3198
+ return $(b(this).previous())
3199
+ }
3200
+
3201
+ , appendTo: function (t) {
3202
+ return b(this.selector).appendTo(t, this)
3203
+ }
3204
+
3205
+ , prependTo: function (t) {
3206
+ return b(this.selector).prependTo(t, this)
3207
+ }
3208
+
3209
+ , insertAfter: function (t) {
3210
+ return b(this.selector).insertAfter(t, this)
3211
+ }
3212
+
3213
+ , insertBefore: function (t) {
3214
+ return b(this.selector).insertBefore(t, this)
3215
+ }
3216
+
3217
+ , siblings: function () {
3218
+ var i, l, p, r = []
3219
+ for (i = 0, l = this.length; i < l; i++) {
3220
+ p = this[i]
3221
+ while (p = p.previousSibling) p.nodeType == 1 && r.push(p)
3222
+ p = this[i]
3223
+ while (p = p.nextSibling) p.nodeType == 1 && r.push(p)
3224
+ }
3225
+ return $(r)
3226
+ }
3227
+
3228
+ , children: function () {
3229
+ var i, l, el, r = []
3230
+ for (i = 0, l = this.length; i < l; i++) {
3231
+ if (!(el = b.firstChild(this[i]))) continue;
3232
+ r.push(el)
3233
+ while (el = el.nextSibling) el.nodeType == 1 && r.push(el)
3234
+ }
3235
+ return $(uniq(r))
3236
+ }
3237
+
3238
+ , height: function (v) {
3239
+ return dimension.call(this, 'height', v)
3240
+ }
3241
+
3242
+ , width: function (v) {
3243
+ return dimension.call(this, 'width', v)
3244
+ }
3245
+ }, true)
3246
+
3247
+ /**
3248
+ * @param {string} type either width or height
3249
+ * @param {number=} opt_v becomes a setter instead of a getter
3250
+ * @return {number}
3251
+ */
3252
+ function dimension(type, opt_v) {
3253
+ return typeof opt_v == 'undefined'
3254
+ ? b(this).dim()[type]
3255
+ : this.css(type, opt_v)
3256
+ }
3257
+ }(ender));
3258
+
3259
+ }());
3260
+