rails-i18nterface 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+