rails-i18nterface 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +22 -0
- data/README.md +109 -0
- data/Rakefile +23 -0
- data/app/assets/javascripts/rails_i18nterface/application.js +8 -0
- data/app/assets/javascripts/rails_i18nterface/base.js +62 -0
- data/app/assets/javascripts/rails_i18nterface/ender.js +3260 -0
- data/app/assets/javascripts/rails_i18nterface/ender.min.js +45 -0
- data/app/assets/stylesheets/rails_i18nterface/application.css +450 -0
- data/app/controllers/rails_i18nterface/application_controller.rb +4 -0
- data/app/controllers/rails_i18nterface/translate_controller.rb +255 -0
- data/app/helpers/rails_i18nterface/application_helper.rb +4 -0
- data/app/helpers/rails_i18nterface/translate_helper.rb +74 -0
- data/app/models/translation.rb +4 -0
- data/app/views/layouts/rails_i18nterface/translate.html.erb +13 -0
- data/app/views/rails_i18nterface/translate/_namespaces.html.erb +1 -0
- data/app/views/rails_i18nterface/translate/_pagination.html.erb +18 -0
- data/app/views/rails_i18nterface/translate/index.html.erb +132 -0
- data/config/routes.rb +7 -0
- data/db/migrate/20110921112044_create_translations.rb +18 -0
- data/lib/rails-i18nterface.rb +8 -0
- data/lib/rails-i18nterface/engine.rb +7 -0
- data/lib/rails-i18nterface/file.rb +35 -0
- data/lib/rails-i18nterface/keys.rb +192 -0
- data/lib/rails-i18nterface/log.rb +35 -0
- data/lib/rails-i18nterface/storage.rb +29 -0
- data/lib/rails-i18nterface/version.rb +3 -0
- data/lib/tasks/rails-i18nterface.rake +4 -0
- data/spec/controllers/translate_controller_spec.rb +135 -0
- data/spec/internal/app/assets/javascripts/application.js +2 -0
- data/spec/internal/app/assets/stylesheets/application.css +3 -0
- data/spec/internal/app/controllers/application_controller.rb +4 -0
- data/spec/internal/app/models/article.rb +11 -0
- data/spec/internal/app/views/application/index.html.erb +5 -0
- data/spec/internal/app/views/categories/category.erb +1 -0
- data/spec/internal/app/views/categories/category.html +1 -0
- data/spec/internal/app/views/categories/category.html.erb +1 -0
- data/spec/internal/app/views/categories/category.rhtml +5 -0
- data/spec/internal/config/database.yml +3 -0
- data/spec/internal/config/routes.rb +4 -0
- data/spec/internal/db/combustion_test.sqlite +0 -0
- data/spec/internal/db/schema.rb +3 -0
- data/spec/internal/log/test.log +521 -0
- data/spec/internal/public/favicon.ico +0 -0
- data/spec/lib/file_spec.rb +53 -0
- data/spec/lib/keys_spec.rb +179 -0
- data/spec/lib/log_spec.rb +46 -0
- data/spec/lib/storage_spec.rb +33 -0
- data/spec/requests/search_spec.rb +62 -0
- data/spec/spec_helper.rb +37 -0
- 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
|
+
|