calatrava 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. data/.gitignore +9 -0
  2. data/.rvmrc +2 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +202 -0
  5. data/Plans.md +20 -0
  6. data/README.md +73 -0
  7. data/Rakefile +26 -0
  8. data/bin/calatrava +6 -0
  9. data/calatrava.gemspec +35 -0
  10. data/features/cli.feature +14 -0
  11. data/features/project.feature +48 -0
  12. data/features/step_definitions/template_steps.rb +8 -0
  13. data/features/support/env.rb +5 -0
  14. data/lib/calatrava/app.rb +30 -0
  15. data/lib/calatrava/manifest.rb +44 -0
  16. data/lib/calatrava/project.rb +218 -0
  17. data/lib/calatrava/resources_build_phase.rb +19 -0
  18. data/lib/calatrava/tasks/apache.rb +44 -0
  19. data/lib/calatrava/tasks/artifact.rb +24 -0
  20. data/lib/calatrava/tasks/assets.rb +6 -0
  21. data/lib/calatrava/tasks/automation.rb +38 -0
  22. data/lib/calatrava/tasks/bootstrap.rb +10 -0
  23. data/lib/calatrava/tasks/build.rb +1 -0
  24. data/lib/calatrava/tasks/configuration.rb +41 -0
  25. data/lib/calatrava/tasks/droid.rb +83 -0
  26. data/lib/calatrava/tasks/haml.rb +71 -0
  27. data/lib/calatrava/tasks/ios.rb +73 -0
  28. data/lib/calatrava/tasks/kernel.rb +52 -0
  29. data/lib/calatrava/tasks/precommit.rb +22 -0
  30. data/lib/calatrava/tasks/release.rb +17 -0
  31. data/lib/calatrava/tasks/shell.rb +17 -0
  32. data/lib/calatrava/tasks/web.rb +82 -0
  33. data/lib/calatrava/tasks.rb +93 -0
  34. data/lib/calatrava/template.rb +44 -0
  35. data/lib/calatrava/templates/.rvmrc.calatrava +2 -0
  36. data/lib/calatrava/templates/Gemfile.calatrava +4 -0
  37. data/lib/calatrava/templates/Rakefile +1 -0
  38. data/lib/calatrava/templates/assets/lib/ICanHaz.js +542 -0
  39. data/lib/calatrava/templates/assets/lib/underscore.js +1059 -0
  40. data/lib/calatrava/templates/assets/lib/zepto.js +1355 -0
  41. data/lib/calatrava/templates/build_env.sh +2 -0
  42. data/lib/calatrava/templates/config/environments.yml +17 -0
  43. data/lib/calatrava/templates/config/templates/env.coffee.erb +7 -0
  44. data/lib/calatrava/templates/config/templates/httpd.conf.erb +33 -0
  45. data/lib/calatrava/templates/droid/app/bridge.coffee +130 -0
  46. data/lib/calatrava/templates/droid/calatrava/ant/calatrava.xml +48 -0
  47. data/lib/calatrava/templates/droid/calatrava/calatrava-build.xml +91 -0
  48. data/lib/calatrava/templates/droid/calatrava/ivy.xml +8 -0
  49. data/lib/calatrava/templates/droid/calatrava/ivysettings.xml +12 -0
  50. data/lib/calatrava/templates/droid/calatrava/src/com/CALATRAVA_TMPL/AndroidManifest.xml.calatrava +20 -0
  51. data/lib/calatrava/templates/droid/calatrava/src/com/CALATRAVA_TMPL/ConversionForm.java.calatrava +27 -0
  52. data/lib/calatrava/templates/droid/calatrava/src/com/CALATRAVA_TMPL/Title.java.calatrava +23 -0
  53. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/CalatravaPage.java +13 -0
  54. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/AjaxRequestManager.java +166 -0
  55. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/AssetRepository.java +17 -0
  56. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/KernelBridge.java +25 -0
  57. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/Launcher.java +85 -0
  58. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/PageRegistry.java +225 -0
  59. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/RegisteredActivity.java +86 -0
  60. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/RequestLoader.java +31 -0
  61. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/RhinoService.java +212 -0
  62. data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/shell/WebViewActivity.java +247 -0
  63. data/lib/calatrava/templates/droid/manifest.yml +1 -0
  64. data/lib/calatrava/templates/ios/Podfile.calatrava +5 -0
  65. data/lib/calatrava/templates/ios/manifest.yml +1 -0
  66. data/lib/calatrava/templates/ios/res/js/bridge.js +249 -0
  67. data/lib/calatrava/templates/ios/res/xibs/ProgressViewController.xib +334 -0
  68. data/lib/calatrava/templates/ios/res/xibs/WebViewController.xib +173 -0
  69. data/lib/calatrava/templates/ios/src/AppDelegate.h +8 -0
  70. data/lib/calatrava/templates/ios/src/AppDelegate.m +56 -0
  71. data/lib/calatrava/templates/ios/src/CALATRAVA_TMPL-Info.plist +45 -0
  72. data/lib/calatrava/templates/ios/src/CALATRAVA_TMPL-Prefix.pch +14 -0
  73. data/lib/calatrava/templates/ios/src/ConversionFormViewController.h +16 -0
  74. data/lib/calatrava/templates/ios/src/ConversionFormViewController.m +179 -0
  75. data/lib/calatrava/templates/ios/src/ConversionFormViewController.xib +357 -0
  76. data/lib/calatrava/templates/ios/src/en.lproj/InfoPlist.strings +2 -0
  77. data/lib/calatrava/templates/ios/src/main.m +10 -0
  78. data/lib/calatrava/templates/ios/test/AJAXConnectionTest.m +21 -0
  79. data/lib/calatrava/templates/ios/test/AppTests-Prefix.pch +8 -0
  80. data/lib/calatrava/templates/ios/test/CalatravaiOSTests-Info.plist +22 -0
  81. data/lib/calatrava/templates/ios/test/TWBridgePageRegistryTest.m +15 -0
  82. data/lib/calatrava/templates/ios/test/en.lproj/InfoPlist.strings +2 -0
  83. data/lib/calatrava/templates/kernel/.gitignore +1 -0
  84. data/lib/calatrava/templates/kernel/app/calatrava.coffee +8 -0
  85. data/lib/calatrava/templates/kernel/app/converter/controller.converter.coffee +50 -0
  86. data/lib/calatrava/templates/kernel/app/converter/init.converter.coffee +11 -0
  87. data/lib/calatrava/templates/kernel/app/pageHelper.coffee +17 -0
  88. data/lib/calatrava/templates/kernel/features/support/bridge.coffee +124 -0
  89. data/lib/calatrava/templates/kernel/features/support/spec_helper.js +49 -0
  90. data/lib/calatrava/templates/kernel/spec/converter/controller.converter.spec.coffee +37 -0
  91. data/lib/calatrava/templates/kernel/spec/environment.spec_helper.coffee +25 -0
  92. data/lib/calatrava/templates/kernel/spec/spec_helper.js +49 -0
  93. data/lib/calatrava/templates/kernel/spec/stubView.coffee +18 -0
  94. data/lib/calatrava/templates/kernel/watchr.rb +17 -0
  95. data/lib/calatrava/templates/package.json +20 -0
  96. data/lib/calatrava/templates/shell/layouts/single_page.haml +23 -0
  97. data/lib/calatrava/templates/shell/pages/converter/conversionForm.haml +12 -0
  98. data/lib/calatrava/templates/shell/pages/converter/page.conversionForm.coffee +42 -0
  99. data/lib/calatrava/templates/shell/shell.scss +1 -0
  100. data/lib/calatrava/templates/shell/support/shell.coffee +21 -0
  101. data/lib/calatrava/templates/web/apache/conf/mime.types +1357 -0
  102. data/lib/calatrava/templates/web/app/source/bridge.coffee +158 -0
  103. data/lib/calatrava/templates/web/app/source/init.coffee +14 -0
  104. data/lib/calatrava/templates/web/app/views/index.haml +18 -0
  105. data/lib/calatrava/templates/web/deploy/instance.sh +10 -0
  106. data/lib/calatrava/templates/web/manifest.yml +1 -0
  107. data/lib/calatrava/version.rb +3 -0
  108. data/lib/calatrava.rb +5 -0
  109. metadata +302 -0
@@ -0,0 +1,1355 @@
1
+ /* Zepto v1.0rc1 - polyfill zepto event detect fx ajax form touch - zeptojs.com/license */
2
+ ;(function(undefined){
3
+ if (String.prototype.trim === undefined) // fix for iOS 3.2
4
+ String.prototype.trim = function(){ return this.replace(/^\s+/, '').replace(/\s+$/, '') }
5
+
6
+ // For iOS 3.x
7
+ // from https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
8
+ if (Array.prototype.reduce === undefined)
9
+ Array.prototype.reduce = function(fun){
10
+ if(this === void 0 || this === null) throw new TypeError()
11
+ var t = Object(this), len = t.length >>> 0, k = 0, accumulator
12
+ if(typeof fun != 'function') throw new TypeError()
13
+ if(len == 0 && arguments.length == 1) throw new TypeError()
14
+
15
+ if(arguments.length >= 2)
16
+ accumulator = arguments[1]
17
+ else
18
+ do{
19
+ if(k in t){
20
+ accumulator = t[k++]
21
+ break
22
+ }
23
+ if(++k >= len) throw new TypeError()
24
+ } while (true)
25
+
26
+ while (k < len){
27
+ if(k in t) accumulator = fun.call(undefined, accumulator, t[k], k, t)
28
+ k++
29
+ }
30
+ return accumulator
31
+ }
32
+
33
+ })()
34
+ var Zepto = (function() {
35
+ var undefined, key, $, classList, emptyArray = [], slice = emptyArray.slice,
36
+ document = window.document,
37
+ elementDisplay = {}, classCache = {},
38
+ getComputedStyle = document.defaultView.getComputedStyle,
39
+ cssNumber = { 'column-count': 1, 'columns': 1, 'font-weight': 1, 'line-height': 1,'opacity': 1, 'z-index': 1, 'zoom': 1 },
40
+ fragmentRE = /^\s*<(\w+|!)[^>]*>/,
41
+
42
+ // Used by `$.zepto.init` to wrap elements, text/comment nodes, document,
43
+ // and document fragment node types.
44
+ elementTypes = [1, 3, 8, 9, 11],
45
+
46
+ adjacencyOperators = [ 'after', 'prepend', 'before', 'append' ],
47
+ table = document.createElement('table'),
48
+ tableRow = document.createElement('tr'),
49
+ containers = {
50
+ 'tr': document.createElement('tbody'),
51
+ 'tbody': table, 'thead': table, 'tfoot': table,
52
+ 'td': tableRow, 'th': tableRow,
53
+ '*': document.createElement('div')
54
+ },
55
+ readyRE = /complete|loaded|interactive/,
56
+ classSelectorRE = /^\.([\w-]+)$/,
57
+ idSelectorRE = /^#([\w-]+)$/,
58
+ tagSelectorRE = /^[\w-]+$/,
59
+ toString = ({}).toString,
60
+ zepto = {},
61
+ camelize, uniq,
62
+ tempParent = document.createElement('div')
63
+
64
+ zepto.matches = function(element, selector) {
65
+ if (!element || element.nodeType !== 1) return false
66
+ var matchesSelector = element.webkitMatchesSelector || element.mozMatchesSelector ||
67
+ element.oMatchesSelector || element.matchesSelector
68
+ if (matchesSelector) return matchesSelector.call(element, selector)
69
+ // fall back to performing a selector:
70
+ var match, parent = element.parentNode, temp = !parent
71
+ if (temp) (parent = tempParent).appendChild(element)
72
+ match = ~zepto.qsa(parent, selector).indexOf(element)
73
+ temp && tempParent.removeChild(element)
74
+ return match
75
+ }
76
+
77
+ function isFunction(value) { return toString.call(value) == "[object Function]" }
78
+ function isObject(value) { return value instanceof Object }
79
+ function isPlainObject(value) {
80
+ var key, ctor
81
+ if (toString.call(value) !== "[object Object]") return false
82
+ ctor = (isFunction(value.constructor) && value.constructor.prototype)
83
+ if (!ctor || !hasOwnProperty.call(ctor, 'isPrototypeOf')) return false
84
+ for (key in value);
85
+ return key === undefined || hasOwnProperty.call(value, key)
86
+ }
87
+ function isArray(value) { return value instanceof Array }
88
+ function likeArray(obj) { return typeof obj.length == 'number' }
89
+
90
+ function compact(array) { return array.filter(function(item){ return item !== undefined && item !== null }) }
91
+ function flatten(array) { return array.length > 0 ? [].concat.apply([], array) : array }
92
+ camelize = function(str){ return str.replace(/-+(.)?/g, function(match, chr){ return chr ? chr.toUpperCase() : '' }) }
93
+ function dasherize(str) {
94
+ return str.replace(/::/g, '/')
95
+ .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
96
+ .replace(/([a-z\d])([A-Z])/g, '$1_$2')
97
+ .replace(/_/g, '-')
98
+ .toLowerCase()
99
+ }
100
+ uniq = function(array){ return array.filter(function(item, idx){ return array.indexOf(item) == idx }) }
101
+
102
+ function classRE(name) {
103
+ return name in classCache ?
104
+ classCache[name] : (classCache[name] = new RegExp('(^|\\s)' + name + '(\\s|$)'))
105
+ }
106
+
107
+ function maybeAddPx(name, value) {
108
+ return (typeof value == "number" && !cssNumber[dasherize(name)]) ? value + "px" : value
109
+ }
110
+
111
+ function defaultDisplay(nodeName) {
112
+ var element, display
113
+ if (!elementDisplay[nodeName]) {
114
+ element = document.createElement(nodeName)
115
+ document.body.appendChild(element)
116
+ display = getComputedStyle(element, '').getPropertyValue("display")
117
+ element.parentNode.removeChild(element)
118
+ display == "none" && (display = "block")
119
+ elementDisplay[nodeName] = display
120
+ }
121
+ return elementDisplay[nodeName]
122
+ }
123
+
124
+ // `$.zepto.fragment` takes a html string and an optional tag name
125
+ // to generate DOM nodes nodes from the given html string.
126
+ // The generated DOM nodes are returned as an array.
127
+ // This function can be overriden in plugins for example to make
128
+ // it compatible with browsers that don't support the DOM fully.
129
+ zepto.fragment = function(html, name) {
130
+ if (name === undefined) name = fragmentRE.test(html) && RegExp.$1
131
+ if (!(name in containers)) name = '*'
132
+ var container = containers[name]
133
+ container.innerHTML = '' + html
134
+ return $.each(slice.call(container.childNodes), function(){
135
+ container.removeChild(this)
136
+ })
137
+ }
138
+
139
+ // `$.zepto.Z` swaps out the prototype of the given `dom` array
140
+ // of nodes with `$.fn` and thus supplying all the Zepto functions
141
+ // to the array. Note that `__proto__` is not supported on Internet
142
+ // Explorer. This method can be overriden in plugins.
143
+ zepto.Z = function(dom, selector) {
144
+ dom = dom || []
145
+ dom.__proto__ = arguments.callee.prototype
146
+ dom.selector = selector || ''
147
+ return dom
148
+ }
149
+
150
+ // `$.zepto.isZ` should return `true` if the given object is a Zepto
151
+ // collection. This method can be overriden in plugins.
152
+ zepto.isZ = function(object) {
153
+ return object instanceof zepto.Z
154
+ }
155
+
156
+ // `$.zepto.init` is Zepto's counterpart to jQuery's `$.fn.init` and
157
+ // takes a CSS selector and an optional context (and handles various
158
+ // special cases).
159
+ // This method can be overriden in plugins.
160
+ zepto.init = function(selector, context) {
161
+ // If nothing given, return an empty Zepto collection
162
+ if (!selector) return zepto.Z()
163
+ // If a function is given, call it when the DOM is ready
164
+ else if (isFunction(selector)) return $(document).ready(selector)
165
+ // If a Zepto collection is given, juts return it
166
+ else if (zepto.isZ(selector)) return selector
167
+ else {
168
+ var dom
169
+ // normalize array if an array of nodes is given
170
+ if (isArray(selector)) dom = compact(selector)
171
+ // if a JavaScript object is given, return a copy of it
172
+ // this is a somewhat peculiar option, but supported by
173
+ // jQuery so we'll do it, too
174
+ else if (isPlainObject(selector))
175
+ dom = [$.extend({}, selector)], selector = null
176
+ // wrap stuff like `document` or `window`
177
+ else if (elementTypes.indexOf(selector.nodeType) >= 0 || selector === window)
178
+ dom = [selector], selector = null
179
+ // If it's a html fragment, create nodes from it
180
+ else if (fragmentRE.test(selector))
181
+ dom = zepto.fragment(selector.trim(), RegExp.$1), selector = null
182
+ // If there's a context, create a collection on that context first, and select
183
+ // nodes from there
184
+ else if (context !== undefined) return $(context).find(selector)
185
+ // And last but no least, if it's a CSS selector, use it to select nodes.
186
+ else dom = zepto.qsa(document, selector)
187
+ // create a new Zepto collection from the nodes found
188
+ return zepto.Z(dom, selector)
189
+ }
190
+ }
191
+
192
+ // `$` will be the base `Zepto` object. When calling this
193
+ // function just call `$.zepto.init, whichs makes the implementation
194
+ // details of selecting nodes and creating Zepto collections
195
+ // patchable in plugins.
196
+ $ = function(selector, context){
197
+ return zepto.init(selector, context)
198
+ }
199
+
200
+ // Copy all but undefined properties from one or more
201
+ // objects to the `target` object.
202
+ $.extend = function(target){
203
+ slice.call(arguments, 1).forEach(function(source) {
204
+ for (key in source)
205
+ if (source[key] !== undefined)
206
+ target[key] = source[key]
207
+ })
208
+ return target
209
+ }
210
+
211
+ // `$.zepto.qsa` is Zepto's CSS selector implementation which
212
+ // uses `document.querySelectorAll` and optimizes for some special cases, like `#id`.
213
+ // This method can be overriden in plugins.
214
+ zepto.qsa = function(element, selector){
215
+ var found
216
+ return (element === document && idSelectorRE.test(selector)) ?
217
+ ( (found = element.getElementById(RegExp.$1)) ? [found] : emptyArray ) :
218
+ (element.nodeType !== 1 && element.nodeType !== 9) ? emptyArray :
219
+ slice.call(
220
+ classSelectorRE.test(selector) ? element.getElementsByClassName(RegExp.$1) :
221
+ tagSelectorRE.test(selector) ? element.getElementsByTagName(selector) :
222
+ element.querySelectorAll(selector)
223
+ )
224
+ }
225
+
226
+ function filtered(nodes, selector) {
227
+ return selector === undefined ? $(nodes) : $(nodes).filter(selector)
228
+ }
229
+
230
+ function funcArg(context, arg, idx, payload) {
231
+ return isFunction(arg) ? arg.call(context, idx, payload) : arg
232
+ }
233
+
234
+ $.isFunction = isFunction
235
+ $.isObject = isObject
236
+ $.isArray = isArray
237
+ $.isPlainObject = isPlainObject
238
+
239
+ $.inArray = function(elem, array, i){
240
+ return emptyArray.indexOf.call(array, elem, i)
241
+ }
242
+
243
+ $.trim = function(str) { return str.trim() }
244
+
245
+ // plugin compatibility
246
+ $.uuid = 0
247
+
248
+ $.map = function(elements, callback){
249
+ var value, values = [], i, key
250
+ if (likeArray(elements))
251
+ for (i = 0; i < elements.length; i++) {
252
+ value = callback(elements[i], i)
253
+ if (value != null) values.push(value)
254
+ }
255
+ else
256
+ for (key in elements) {
257
+ value = callback(elements[key], key)
258
+ if (value != null) values.push(value)
259
+ }
260
+ return flatten(values)
261
+ }
262
+
263
+ $.each = function(elements, callback){
264
+ var i, key
265
+ if (likeArray(elements)) {
266
+ for (i = 0; i < elements.length; i++)
267
+ if (callback.call(elements[i], i, elements[i]) === false) return elements
268
+ } else {
269
+ for (key in elements)
270
+ if (callback.call(elements[key], key, elements[key]) === false) return elements
271
+ }
272
+
273
+ return elements
274
+ }
275
+
276
+ // Define methods that will be available on all
277
+ // Zepto collections
278
+ $.fn = {
279
+ // Because a collection acts like an array
280
+ // copy over these useful array functions.
281
+ forEach: emptyArray.forEach,
282
+ reduce: emptyArray.reduce,
283
+ push: emptyArray.push,
284
+ indexOf: emptyArray.indexOf,
285
+ concat: emptyArray.concat,
286
+
287
+ // `map` and `slice` in the jQuery API work differently
288
+ // from their array counterparts
289
+ map: function(fn){
290
+ return $.map(this, function(el, i){ return fn.call(el, i, el) })
291
+ },
292
+ slice: function(){
293
+ return $(slice.apply(this, arguments))
294
+ },
295
+
296
+ ready: function(callback){
297
+ if (readyRE.test(document.readyState)) callback($)
298
+ else document.addEventListener('DOMContentLoaded', function(){ callback($) }, false)
299
+ return this
300
+ },
301
+ get: function(idx){
302
+ return idx === undefined ? slice.call(this) : this[idx]
303
+ },
304
+ toArray: function(){ return this.get() },
305
+ size: function(){
306
+ return this.length
307
+ },
308
+ remove: function(){
309
+ return this.each(function(){
310
+ if (this.parentNode != null)
311
+ this.parentNode.removeChild(this)
312
+ })
313
+ },
314
+ each: function(callback){
315
+ this.forEach(function(el, idx){ callback.call(el, idx, el) })
316
+ return this
317
+ },
318
+ filter: function(selector){
319
+ return $([].filter.call(this, function(element){
320
+ return zepto.matches(element, selector)
321
+ }))
322
+ },
323
+ add: function(selector,context){
324
+ return $(uniq(this.concat($(selector,context))))
325
+ },
326
+ is: function(selector){
327
+ return this.length > 0 && zepto.matches(this[0], selector)
328
+ },
329
+ not: function(selector){
330
+ var nodes=[]
331
+ if (isFunction(selector) && selector.call !== undefined)
332
+ this.each(function(idx){
333
+ if (!selector.call(this,idx)) nodes.push(this)
334
+ })
335
+ else {
336
+ var excludes = typeof selector == 'string' ? this.filter(selector) :
337
+ (likeArray(selector) && isFunction(selector.item)) ? slice.call(selector) : $(selector)
338
+ this.forEach(function(el){
339
+ if (excludes.indexOf(el) < 0) nodes.push(el)
340
+ })
341
+ }
342
+ return $(nodes)
343
+ },
344
+ eq: function(idx){
345
+ return idx === -1 ? this.slice(idx) : this.slice(idx, + idx + 1)
346
+ },
347
+ first: function(){
348
+ var el = this[0]
349
+ return el && !isObject(el) ? el : $(el)
350
+ },
351
+ last: function(){
352
+ var el = this[this.length - 1]
353
+ return el && !isObject(el) ? el : $(el)
354
+ },
355
+ find: function(selector){
356
+ var result
357
+ if (this.length == 1) result = zepto.qsa(this[0], selector)
358
+ else result = this.map(function(){ return zepto.qsa(this, selector) })
359
+ return $(result)
360
+ },
361
+ closest: function(selector, context){
362
+ var node = this[0]
363
+ while (node && !zepto.matches(node, selector))
364
+ node = node !== context && node !== document && node.parentNode
365
+ return $(node)
366
+ },
367
+ parents: function(selector){
368
+ var ancestors = [], nodes = this
369
+ while (nodes.length > 0)
370
+ nodes = $.map(nodes, function(node){
371
+ if ((node = node.parentNode) && node !== document && ancestors.indexOf(node) < 0) {
372
+ ancestors.push(node)
373
+ return node
374
+ }
375
+ })
376
+ return filtered(ancestors, selector)
377
+ },
378
+ parent: function(selector){
379
+ return filtered(uniq(this.pluck('parentNode')), selector)
380
+ },
381
+ children: function(selector){
382
+ return filtered(this.map(function(){ return slice.call(this.children) }), selector)
383
+ },
384
+ siblings: function(selector){
385
+ return filtered(this.map(function(i, el){
386
+ return slice.call(el.parentNode.children).filter(function(child){ return child!==el })
387
+ }), selector)
388
+ },
389
+ empty: function(){
390
+ return this.each(function(){ this.innerHTML = '' })
391
+ },
392
+ // `pluck` is borrowed from Prototype.js
393
+ pluck: function(property){
394
+ return this.map(function(){ return this[property] })
395
+ },
396
+ show: function(){
397
+ return this.each(function(){
398
+ this.style.display == "none" && (this.style.display = null)
399
+ if (getComputedStyle(this, '').getPropertyValue("display") == "none")
400
+ this.style.display = defaultDisplay(this.nodeName)
401
+ })
402
+ },
403
+ replaceWith: function(newContent){
404
+ return this.before(newContent).remove()
405
+ },
406
+ wrap: function(newContent){
407
+ return this.each(function(){
408
+ $(this).wrapAll($(newContent)[0].cloneNode(false))
409
+ })
410
+ },
411
+ wrapAll: function(newContent){
412
+ if (this[0]) {
413
+ $(this[0]).before(newContent = $(newContent))
414
+ newContent.append(this)
415
+ }
416
+ return this
417
+ },
418
+ unwrap: function(){
419
+ this.parent().each(function(){
420
+ $(this).replaceWith($(this).children())
421
+ })
422
+ return this
423
+ },
424
+ clone: function(){
425
+ return $(this.map(function(){ return this.cloneNode(true) }))
426
+ },
427
+ hide: function(){
428
+ return this.css("display", "none")
429
+ },
430
+ toggle: function(setting){
431
+ return (setting === undefined ? this.css("display") == "none" : setting) ? this.show() : this.hide()
432
+ },
433
+ prev: function(){ return $(this.pluck('previousElementSibling')) },
434
+ next: function(){ return $(this.pluck('nextElementSibling')) },
435
+ html: function(html){
436
+ return html === undefined ?
437
+ (this.length > 0 ? this[0].innerHTML : null) :
438
+ this.each(function(idx){
439
+ var originHtml = this.innerHTML
440
+ $(this).empty().append( funcArg(this, html, idx, originHtml) )
441
+ })
442
+ },
443
+ text: function(text){
444
+ return text === undefined ?
445
+ (this.length > 0 ? this[0].textContent : null) :
446
+ this.each(function(){ this.textContent = text })
447
+ },
448
+ attr: function(name, value){
449
+ var result
450
+ return (typeof name == 'string' && value === undefined) ?
451
+ (this.length == 0 || this[0].nodeType !== 1 ? undefined :
452
+ (name == 'value' && this[0].nodeName == 'INPUT') ? this.val() :
453
+ (!(result = this[0].getAttribute(name)) && name in this[0]) ? this[0][name] : result
454
+ ) :
455
+ this.each(function(idx){
456
+ if (this.nodeType !== 1) return
457
+ if (isObject(name)) for (key in name) this.setAttribute(key, name[key])
458
+ else this.setAttribute(name, funcArg(this, value, idx, this.getAttribute(name)))
459
+ })
460
+ },
461
+ removeAttr: function(name){
462
+ return this.each(function(){ if (this.nodeType === 1) this.removeAttribute(name) })
463
+ },
464
+ prop: function(name, value){
465
+ return (value === undefined) ?
466
+ (this[0] ? this[0][name] : undefined) :
467
+ this.each(function(idx){
468
+ this[name] = funcArg(this, value, idx, this[name])
469
+ })
470
+ },
471
+ data: function(name, value){
472
+ var data = this.attr('data-' + dasherize(name), value)
473
+ return data !== null ? data : undefined
474
+ },
475
+ val: function(value){
476
+ return (value === undefined) ?
477
+ (this.length > 0 ? this[0].value : undefined) :
478
+ this.each(function(idx){
479
+ this.value = funcArg(this, value, idx, this.value)
480
+ })
481
+ },
482
+ offset: function(){
483
+ if (this.length==0) return null
484
+ var obj = this[0].getBoundingClientRect()
485
+ return {
486
+ left: obj.left + window.pageXOffset,
487
+ top: obj.top + window.pageYOffset,
488
+ width: obj.width,
489
+ height: obj.height
490
+ }
491
+ },
492
+ css: function(property, value){
493
+ if (value === undefined && typeof property == 'string')
494
+ return (
495
+ this.length == 0
496
+ ? undefined
497
+ : this[0].style[camelize(property)] || getComputedStyle(this[0], '').getPropertyValue(property))
498
+
499
+ var css = ''
500
+ for (key in property)
501
+ if(typeof property[key] == 'string' && property[key] == '')
502
+ this.each(function(){ this.style.removeProperty(dasherize(key)) })
503
+ else
504
+ css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ';'
505
+
506
+ if (typeof property == 'string')
507
+ if (value == '')
508
+ this.each(function(){ this.style.removeProperty(dasherize(property)) })
509
+ else
510
+ css = dasherize(property) + ":" + maybeAddPx(property, value)
511
+
512
+ return this.each(function(){ this.style.cssText += ';' + css })
513
+ },
514
+ index: function(element){
515
+ return element ? this.indexOf($(element)[0]) : this.parent().children().indexOf(this[0])
516
+ },
517
+ hasClass: function(name){
518
+ if (this.length < 1) return false
519
+ else return classRE(name).test(this[0].className)
520
+ },
521
+ addClass: function(name){
522
+ return this.each(function(idx){
523
+ classList = []
524
+ var cls = this.className, newName = funcArg(this, name, idx, cls)
525
+ newName.split(/\s+/g).forEach(function(klass){
526
+ if (!$(this).hasClass(klass)) classList.push(klass)
527
+ }, this)
528
+ classList.length && (this.className += (cls ? " " : "") + classList.join(" "))
529
+ })
530
+ },
531
+ removeClass: function(name){
532
+ return this.each(function(idx){
533
+ if (name === undefined)
534
+ return this.className = ''
535
+ classList = this.className
536
+ funcArg(this, name, idx, classList).split(/\s+/g).forEach(function(klass){
537
+ classList = classList.replace(classRE(klass), " ")
538
+ })
539
+ this.className = classList.trim()
540
+ })
541
+ },
542
+ toggleClass: function(name, when){
543
+ return this.each(function(idx){
544
+ var newName = funcArg(this, name, idx, this.className)
545
+ ;(when === undefined ? !$(this).hasClass(newName) : when) ?
546
+ $(this).addClass(newName) : $(this).removeClass(newName)
547
+ })
548
+ }
549
+ }
550
+
551
+ // Generate the `width` and `height` functions
552
+ ;['width', 'height'].forEach(function(dimension){
553
+ $.fn[dimension] = function(value){
554
+ var offset, Dimension = dimension.replace(/./, function(m){ return m[0].toUpperCase() })
555
+ if (value === undefined) return this[0] == window ? window['inner' + Dimension] :
556
+ this[0] == document ? document.documentElement['offset' + Dimension] :
557
+ (offset = this.offset()) && offset[dimension]
558
+ else return this.each(function(idx){
559
+ var el = $(this)
560
+ el.css(dimension, funcArg(this, value, idx, el[dimension]()))
561
+ })
562
+ }
563
+ })
564
+
565
+ function insert(operator, target, node) {
566
+ var parent = (operator % 2) ? target : target.parentNode
567
+ parent ? parent.insertBefore(node,
568
+ !operator ? target.nextSibling : // after
569
+ operator == 1 ? parent.firstChild : // prepend
570
+ operator == 2 ? target : // before
571
+ null) : // append
572
+ $(node).remove()
573
+ }
574
+
575
+ function traverseNode(node, fun) {
576
+ fun(node)
577
+ for (var key in node.childNodes) traverseNode(node.childNodes[key], fun)
578
+ }
579
+
580
+ // Generate the `after`, `prepend`, `before`, `append`,
581
+ // `insertAfter`, `insertBefore`, `appendTo`, and `prependTo` methods.
582
+ adjacencyOperators.forEach(function(key, operator) {
583
+ $.fn[key] = function(){
584
+ // arguments can be nodes, arrays of nodes, Zepto objects and HTML strings
585
+ var nodes = $.map(arguments, function(n){ return isObject(n) ? n : zepto.fragment(n) })
586
+ if (nodes.length < 1) return this
587
+ var size = this.length, copyByClone = size > 1, inReverse = operator < 2
588
+
589
+ return this.each(function(index, target){
590
+ for (var i = 0; i < nodes.length; i++) {
591
+ var node = nodes[inReverse ? nodes.length-i-1 : i]
592
+ traverseNode(node, function(node){
593
+ if (node.nodeName != null && node.nodeName.toUpperCase() === 'SCRIPT' && (!node.type || node.type === 'text/javascript'))
594
+ window['eval'].call(window, node.innerHTML)
595
+ })
596
+ if (copyByClone && index < size - 1) node = node.cloneNode(true)
597
+ insert(operator, target, node)
598
+ }
599
+ })
600
+ }
601
+
602
+ $.fn[(operator % 2) ? key+'To' : 'insert'+(operator ? 'Before' : 'After')] = function(html){
603
+ $(html)[key](this)
604
+ return this
605
+ }
606
+ })
607
+
608
+ zepto.Z.prototype = $.fn
609
+
610
+ // Export internal API functions in the `$.zepto` namespace
611
+ zepto.camelize = camelize
612
+ zepto.uniq = uniq
613
+ $.zepto = zepto
614
+
615
+ return $
616
+ })()
617
+
618
+ // If `$` is not yet defined, point it to `Zepto`
619
+ window.Zepto = Zepto
620
+ '$' in window || (window.$ = Zepto)
621
+ ;(function($){
622
+ var $$ = $.zepto.qsa, handlers = {}, _zid = 1, specialEvents={}
623
+
624
+ specialEvents.click = specialEvents.mousedown = specialEvents.mouseup = specialEvents.mousemove = 'MouseEvents'
625
+
626
+ function zid(element) {
627
+ return element._zid || (element._zid = _zid++)
628
+ }
629
+ function findHandlers(element, event, fn, selector) {
630
+ event = parse(event)
631
+ if (event.ns) var matcher = matcherFor(event.ns)
632
+ return (handlers[zid(element)] || []).filter(function(handler) {
633
+ return handler
634
+ && (!event.e || handler.e == event.e)
635
+ && (!event.ns || matcher.test(handler.ns))
636
+ && (!fn || zid(handler.fn) === zid(fn))
637
+ && (!selector || handler.sel == selector)
638
+ })
639
+ }
640
+ function parse(event) {
641
+ var parts = ('' + event).split('.')
642
+ return {e: parts[0], ns: parts.slice(1).sort().join(' ')}
643
+ }
644
+ function matcherFor(ns) {
645
+ return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)')
646
+ }
647
+
648
+ function eachEvent(events, fn, iterator){
649
+ if ($.isObject(events)) $.each(events, iterator)
650
+ else events.split(/\s/).forEach(function(type){ iterator(type, fn) })
651
+ }
652
+
653
+ function add(element, events, fn, selector, getDelegate, capture){
654
+ capture = !!capture
655
+ var id = zid(element), set = (handlers[id] || (handlers[id] = []))
656
+ eachEvent(events, fn, function(event, fn){
657
+ var delegate = getDelegate && getDelegate(fn, event),
658
+ callback = delegate || fn
659
+ var proxyfn = function (event) {
660
+ var result = callback.apply(element, [event].concat(event.data))
661
+ if (result === false) event.preventDefault()
662
+ return result
663
+ }
664
+ var handler = $.extend(parse(event), {fn: fn, proxy: proxyfn, sel: selector, del: delegate, i: set.length})
665
+ set.push(handler)
666
+ element.addEventListener(handler.e, proxyfn, capture)
667
+ })
668
+ }
669
+ function remove(element, events, fn, selector){
670
+ var id = zid(element)
671
+ eachEvent(events || '', fn, function(event, fn){
672
+ findHandlers(element, event, fn, selector).forEach(function(handler){
673
+ delete handlers[id][handler.i]
674
+ element.removeEventListener(handler.e, handler.proxy, false)
675
+ })
676
+ })
677
+ }
678
+
679
+ $.event = { add: add, remove: remove }
680
+
681
+ $.proxy = function(fn, context) {
682
+ if ($.isFunction(fn)) {
683
+ var proxyFn = function(){ return fn.apply(context, arguments) }
684
+ proxyFn._zid = zid(fn)
685
+ return proxyFn
686
+ } else if (typeof context == 'string') {
687
+ return $.proxy(fn[context], fn)
688
+ } else {
689
+ throw new TypeError("expected function")
690
+ }
691
+ }
692
+
693
+ $.fn.bind = function(event, callback){
694
+ return this.each(function(){
695
+ add(this, event, callback)
696
+ })
697
+ }
698
+ $.fn.unbind = function(event, callback){
699
+ return this.each(function(){
700
+ remove(this, event, callback)
701
+ })
702
+ }
703
+ $.fn.one = function(event, callback){
704
+ return this.each(function(i, element){
705
+ add(this, event, callback, null, function(fn, type){
706
+ return function(){
707
+ var result = fn.apply(element, arguments)
708
+ remove(element, type, fn)
709
+ return result
710
+ }
711
+ })
712
+ })
713
+ }
714
+
715
+ var returnTrue = function(){return true},
716
+ returnFalse = function(){return false},
717
+ eventMethods = {
718
+ preventDefault: 'isDefaultPrevented',
719
+ stopImmediatePropagation: 'isImmediatePropagationStopped',
720
+ stopPropagation: 'isPropagationStopped'
721
+ }
722
+ function createProxy(event) {
723
+ var proxy = $.extend({originalEvent: event}, event)
724
+ $.each(eventMethods, function(name, predicate) {
725
+ proxy[name] = function(){
726
+ this[predicate] = returnTrue
727
+ return event[name].apply(event, arguments)
728
+ }
729
+ proxy[predicate] = returnFalse
730
+ })
731
+ return proxy
732
+ }
733
+
734
+ // emulates the 'defaultPrevented' property for browsers that have none
735
+ function fix(event) {
736
+ if (!('defaultPrevented' in event)) {
737
+ event.defaultPrevented = false
738
+ var prevent = event.preventDefault
739
+ event.preventDefault = function() {
740
+ this.defaultPrevented = true
741
+ prevent.call(this)
742
+ }
743
+ }
744
+ }
745
+
746
+ $.fn.delegate = function(selector, event, callback){
747
+ var capture = false
748
+ if(event == 'blur' || event == 'focus'){
749
+ if($.iswebkit)
750
+ event = event == 'blur' ? 'focusout' : event == 'focus' ? 'focusin' : event
751
+ else
752
+ capture = true
753
+ }
754
+
755
+ return this.each(function(i, element){
756
+ add(element, event, callback, selector, function(fn){
757
+ return function(e){
758
+ var evt, match = $(e.target).closest(selector, element).get(0)
759
+ if (match) {
760
+ evt = $.extend(createProxy(e), {currentTarget: match, liveFired: element})
761
+ return fn.apply(match, [evt].concat([].slice.call(arguments, 1)))
762
+ }
763
+ }
764
+ }, capture)
765
+ })
766
+ }
767
+ $.fn.undelegate = function(selector, event, callback){
768
+ return this.each(function(){
769
+ remove(this, event, callback, selector)
770
+ })
771
+ }
772
+
773
+ $.fn.live = function(event, callback){
774
+ $(document.body).delegate(this.selector, event, callback)
775
+ return this
776
+ }
777
+ $.fn.die = function(event, callback){
778
+ $(document.body).undelegate(this.selector, event, callback)
779
+ return this
780
+ }
781
+
782
+ $.fn.on = function(event, selector, callback){
783
+ return selector == undefined || $.isFunction(selector) ?
784
+ this.bind(event, selector) : this.delegate(selector, event, callback)
785
+ }
786
+ $.fn.off = function(event, selector, callback){
787
+ return selector == undefined || $.isFunction(selector) ?
788
+ this.unbind(event, selector) : this.undelegate(selector, event, callback)
789
+ }
790
+
791
+ $.fn.trigger = function(event, data){
792
+ if (typeof event == 'string') event = $.Event(event)
793
+ fix(event)
794
+ event.data = data
795
+ return this.each(function(){
796
+ // items in the collection might not be DOM elements
797
+ // (todo: possibly support events on plain old objects)
798
+ if('dispatchEvent' in this) this.dispatchEvent(event)
799
+ })
800
+ }
801
+
802
+ // triggers event handlers on current element just as if an event occurred,
803
+ // doesn't trigger an actual event, doesn't bubble
804
+ $.fn.triggerHandler = function(event, data){
805
+ var e, result
806
+ this.each(function(i, element){
807
+ e = createProxy(typeof event == 'string' ? $.Event(event) : event)
808
+ e.data = data
809
+ e.target = element
810
+ $.each(findHandlers(element, event.type || event), function(i, handler){
811
+ result = handler.proxy(e)
812
+ if (e.isImmediatePropagationStopped()) return false
813
+ })
814
+ })
815
+ return result
816
+ }
817
+
818
+ // shortcut methods for `.bind(event, fn)` for each event type
819
+ ;('focusin focusout load resize scroll unload click dblclick '+
820
+ 'mousedown mouseup mousemove mouseover mouseout '+
821
+ 'change select keydown keypress keyup error').split(' ').forEach(function(event) {
822
+ $.fn[event] = function(callback){ return this.bind(event, callback) }
823
+ })
824
+
825
+ ;['focus', 'blur'].forEach(function(name) {
826
+ $.fn[name] = function(callback) {
827
+ if (callback) this.bind(name, callback)
828
+ else if (this.length) try { this.get(0)[name]() } catch(e){}
829
+ return this
830
+ }
831
+ })
832
+
833
+ $.Event = function(type, props) {
834
+ var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true
835
+ if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name])
836
+ event.initEvent(type, bubbles, true, null, null, null, null, null, null, null, null, null, null, null, null)
837
+ return event
838
+ }
839
+
840
+ })(Zepto)
841
+ ;(function($){
842
+ function detect(ua){
843
+ var os = this.os = {}, browser = this.browser = {},
844
+ webkit = ua.match(/WebKit\/([\d.]+)/),
845
+ android = ua.match(/(Android)\s+([\d.]+)/),
846
+ ipad = ua.match(/(iPad).*OS\s([\d_]+)/),
847
+ iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/),
848
+ webos = ua.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),
849
+ touchpad = webos && ua.match(/TouchPad/),
850
+ kindle = ua.match(/Kindle\/([\d.]+)/),
851
+ silk = ua.match(/Silk\/([\d._]+)/),
852
+ blackberry = ua.match(/(BlackBerry).*Version\/([\d.]+)/)
853
+
854
+ // todo clean this up with a better OS/browser
855
+ // separation. we need to discern between multiple
856
+ // browsers on android, and decide if kindle fire in
857
+ // silk mode is android or not
858
+
859
+ if (browser.webkit = !!webkit) browser.version = webkit[1]
860
+
861
+ if (android) os.android = true, os.version = android[2]
862
+ if (iphone) os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.')
863
+ if (ipad) os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.')
864
+ if (webos) os.webos = true, os.version = webos[2]
865
+ if (touchpad) os.touchpad = true
866
+ if (blackberry) os.blackberry = true, os.version = blackberry[2]
867
+ if (kindle) os.kindle = true, os.version = kindle[1]
868
+ if (silk) browser.silk = true, browser.version = silk[1]
869
+ if (!silk && os.android && ua.match(/Kindle Fire/)) browser.silk = true
870
+ }
871
+
872
+ detect.call($, navigator.userAgent)
873
+ // make available to unit tests
874
+ $.__detect = detect
875
+
876
+ })(Zepto)
877
+ ;(function($, undefined){
878
+ var prefix = '', eventPrefix, endEventName, endAnimationName,
879
+ vendors = { Webkit: 'webkit', Moz: '', O: 'o', ms: 'MS' },
880
+ document = window.document, testEl = document.createElement('div'),
881
+ supportedTransforms = /^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,
882
+ clearProperties = {}
883
+
884
+ function downcase(str) { return str.toLowerCase() }
885
+ function normalizeEvent(name) { return eventPrefix ? eventPrefix + name : downcase(name) }
886
+
887
+ $.each(vendors, function(vendor, event){
888
+ if (testEl.style[vendor + 'TransitionProperty'] !== undefined) {
889
+ prefix = '-' + downcase(vendor) + '-'
890
+ eventPrefix = event
891
+ return false
892
+ }
893
+ })
894
+
895
+ clearProperties[prefix + 'transition-property'] =
896
+ clearProperties[prefix + 'transition-duration'] =
897
+ clearProperties[prefix + 'transition-timing-function'] =
898
+ clearProperties[prefix + 'animation-name'] =
899
+ clearProperties[prefix + 'animation-duration'] = ''
900
+
901
+ $.fx = {
902
+ off: (eventPrefix === undefined && testEl.style.transitionProperty === undefined),
903
+ cssPrefix: prefix,
904
+ transitionEnd: normalizeEvent('TransitionEnd'),
905
+ animationEnd: normalizeEvent('AnimationEnd')
906
+ }
907
+
908
+ $.fn.animate = function(properties, duration, ease, callback){
909
+ if ($.isObject(duration))
910
+ ease = duration.easing, callback = duration.complete, duration = duration.duration
911
+ if (duration) duration = duration / 1000
912
+ return this.anim(properties, duration, ease, callback)
913
+ }
914
+
915
+ $.fn.anim = function(properties, duration, ease, callback){
916
+ var transforms, cssProperties = {}, key, that = this, wrappedCallback, endEvent = $.fx.transitionEnd
917
+ if (duration === undefined) duration = 0.4
918
+ if ($.fx.off) duration = 0
919
+
920
+ if (typeof properties == 'string') {
921
+ // keyframe animation
922
+ cssProperties[prefix + 'animation-name'] = properties
923
+ cssProperties[prefix + 'animation-duration'] = duration + 's'
924
+ endEvent = $.fx.animationEnd
925
+ } else {
926
+ // CSS transitions
927
+ for (key in properties)
928
+ if (supportedTransforms.test(key)) {
929
+ transforms || (transforms = [])
930
+ transforms.push(key + '(' + properties[key] + ')')
931
+ }
932
+ else cssProperties[key] = properties[key]
933
+
934
+ if (transforms) cssProperties[prefix + 'transform'] = transforms.join(' ')
935
+ if (!$.fx.off && typeof properties === 'object') {
936
+ cssProperties[prefix + 'transition-property'] = Object.keys(properties).join(', ')
937
+ cssProperties[prefix + 'transition-duration'] = duration + 's'
938
+ cssProperties[prefix + 'transition-timing-function'] = (ease || 'linear')
939
+ }
940
+ }
941
+
942
+ wrappedCallback = function(event){
943
+ if (typeof event !== 'undefined') {
944
+ if (event.target !== event.currentTarget) return // makes sure the event didn't bubble from "below"
945
+ $(event.target).unbind(endEvent, arguments.callee)
946
+ }
947
+ $(this).css(clearProperties)
948
+ callback && callback.call(this)
949
+ }
950
+ if (duration > 0) this.bind(endEvent, wrappedCallback)
951
+
952
+ setTimeout(function() {
953
+ that.css(cssProperties)
954
+ if (duration <= 0) setTimeout(function() {
955
+ that.each(function(){ wrappedCallback.call(this) })
956
+ }, 0)
957
+ }, 0)
958
+
959
+ return this
960
+ }
961
+
962
+ testEl = null
963
+ })(Zepto)
964
+ ;(function($){
965
+ var jsonpID = 0,
966
+ isObject = $.isObject,
967
+ document = window.document,
968
+ key,
969
+ name,
970
+ rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
971
+ scriptTypeRE = /^(?:text|application)\/javascript/i,
972
+ xmlTypeRE = /^(?:text|application)\/xml/i,
973
+ jsonType = 'application/json',
974
+ htmlType = 'text/html',
975
+ blankRE = /^\s*$/
976
+
977
+ // trigger a custom event and return false if it was cancelled
978
+ function triggerAndReturn(context, eventName, data) {
979
+ var event = $.Event(eventName)
980
+ $(context).trigger(event, data)
981
+ return !event.defaultPrevented
982
+ }
983
+
984
+ // trigger an Ajax "global" event
985
+ function triggerGlobal(settings, context, eventName, data) {
986
+ if (settings.global) return triggerAndReturn(context || document, eventName, data)
987
+ }
988
+
989
+ // Number of active Ajax requests
990
+ $.active = 0
991
+
992
+ function ajaxStart(settings) {
993
+ if (settings.global && $.active++ === 0) triggerGlobal(settings, null, 'ajaxStart')
994
+ }
995
+ function ajaxStop(settings) {
996
+ if (settings.global && !(--$.active)) triggerGlobal(settings, null, 'ajaxStop')
997
+ }
998
+
999
+ // triggers an extra global event "ajaxBeforeSend" that's like "ajaxSend" but cancelable
1000
+ function ajaxBeforeSend(xhr, settings) {
1001
+ var context = settings.context
1002
+ if (settings.beforeSend.call(context, xhr, settings) === false ||
1003
+ triggerGlobal(settings, context, 'ajaxBeforeSend', [xhr, settings]) === false)
1004
+ return false
1005
+
1006
+ triggerGlobal(settings, context, 'ajaxSend', [xhr, settings])
1007
+ }
1008
+ function ajaxSuccess(data, xhr, settings) {
1009
+ var context = settings.context, status = 'success'
1010
+ settings.success.call(context, data, status, xhr)
1011
+ triggerGlobal(settings, context, 'ajaxSuccess', [xhr, settings, data])
1012
+ ajaxComplete(status, xhr, settings)
1013
+ }
1014
+ // type: "timeout", "error", "abort", "parsererror"
1015
+ function ajaxError(error, type, xhr, settings) {
1016
+ var context = settings.context
1017
+ settings.error.call(context, xhr, type, error)
1018
+ triggerGlobal(settings, context, 'ajaxError', [xhr, settings, error])
1019
+ ajaxComplete(type, xhr, settings)
1020
+ }
1021
+ // status: "success", "notmodified", "error", "timeout", "abort", "parsererror"
1022
+ function ajaxComplete(status, xhr, settings) {
1023
+ var context = settings.context
1024
+ settings.complete.call(context, xhr, status)
1025
+ triggerGlobal(settings, context, 'ajaxComplete', [xhr, settings])
1026
+ ajaxStop(settings)
1027
+ }
1028
+
1029
+ // Empty function, used as default callback
1030
+ function empty() {}
1031
+
1032
+ $.ajaxJSONP = function(options){
1033
+ var callbackName = 'jsonp' + (++jsonpID),
1034
+ script = document.createElement('script'),
1035
+ abort = function(){
1036
+ $(script).remove()
1037
+ if (callbackName in window) window[callbackName] = empty
1038
+ ajaxComplete('abort', xhr, options)
1039
+ },
1040
+ xhr = { abort: abort }, abortTimeout
1041
+
1042
+ if (options.error) script.onerror = function() {
1043
+ xhr.abort()
1044
+ options.error()
1045
+ }
1046
+
1047
+ window[callbackName] = function(data){
1048
+ clearTimeout(abortTimeout)
1049
+ $(script).remove()
1050
+ delete window[callbackName]
1051
+ ajaxSuccess(data, xhr, options)
1052
+ }
1053
+
1054
+ serializeData(options)
1055
+ script.src = options.url.replace(/=\?/, '=' + callbackName)
1056
+ $('head').append(script)
1057
+
1058
+ if (options.timeout > 0) abortTimeout = setTimeout(function(){
1059
+ xhr.abort()
1060
+ ajaxComplete('timeout', xhr, options)
1061
+ }, options.timeout)
1062
+
1063
+ return xhr
1064
+ }
1065
+
1066
+ $.ajaxSettings = {
1067
+ // Default type of request
1068
+ type: 'GET',
1069
+ // Callback that is executed before request
1070
+ beforeSend: empty,
1071
+ // Callback that is executed if the request succeeds
1072
+ success: empty,
1073
+ // Callback that is executed the the server drops error
1074
+ error: empty,
1075
+ // Callback that is executed on request complete (both: error and success)
1076
+ complete: empty,
1077
+ // The context for the callbacks
1078
+ context: null,
1079
+ // Whether to trigger "global" Ajax events
1080
+ global: true,
1081
+ // Transport
1082
+ xhr: function () {
1083
+ return new window.XMLHttpRequest()
1084
+ },
1085
+ // MIME types mapping
1086
+ accepts: {
1087
+ script: 'text/javascript, application/javascript',
1088
+ json: jsonType,
1089
+ xml: 'application/xml, text/xml',
1090
+ html: htmlType,
1091
+ text: 'text/plain'
1092
+ },
1093
+ // Whether the request is to another domain
1094
+ crossDomain: false,
1095
+ // Default timeout
1096
+ timeout: 0
1097
+ }
1098
+
1099
+ function mimeToDataType(mime) {
1100
+ return mime && ( mime == htmlType ? 'html' :
1101
+ mime == jsonType ? 'json' :
1102
+ scriptTypeRE.test(mime) ? 'script' :
1103
+ xmlTypeRE.test(mime) && 'xml' ) || 'text'
1104
+ }
1105
+
1106
+ function appendQuery(url, query) {
1107
+ return (url + '&' + query).replace(/[&?]{1,2}/, '?')
1108
+ }
1109
+
1110
+ // serialize payload and append it to the URL for GET requests
1111
+ function serializeData(options) {
1112
+ if (isObject(options.data)) options.data = $.param(options.data)
1113
+ if (options.data && (!options.type || options.type.toUpperCase() == 'GET'))
1114
+ options.url = appendQuery(options.url, options.data)
1115
+ }
1116
+
1117
+ $.ajax = function(options){
1118
+ var settings = $.extend({}, options || {})
1119
+ for (key in $.ajaxSettings) if (settings[key] === undefined) settings[key] = $.ajaxSettings[key]
1120
+
1121
+ ajaxStart(settings)
1122
+
1123
+ if (!settings.crossDomain) settings.crossDomain = /^([\w-]+:)?\/\/([^\/]+)/.test(settings.url) &&
1124
+ RegExp.$2 != window.location.host
1125
+
1126
+ var dataType = settings.dataType, hasPlaceholder = /=\?/.test(settings.url)
1127
+ if (dataType == 'jsonp' || hasPlaceholder) {
1128
+ if (!hasPlaceholder) settings.url = appendQuery(settings.url, 'callback=?')
1129
+ return $.ajaxJSONP(settings)
1130
+ }
1131
+
1132
+ if (!settings.url) settings.url = window.location.toString()
1133
+ serializeData(settings)
1134
+
1135
+ var mime = settings.accepts[dataType],
1136
+ baseHeaders = { },
1137
+ protocol = /^([\w-]+:)\/\//.test(settings.url) ? RegExp.$1 : window.location.protocol,
1138
+ xhr = $.ajaxSettings.xhr(), abortTimeout
1139
+
1140
+ if (!settings.crossDomain) baseHeaders['X-Requested-With'] = 'XMLHttpRequest'
1141
+ if (mime) {
1142
+ baseHeaders['Accept'] = mime
1143
+ if (mime.indexOf(',') > -1) mime = mime.split(',', 2)[0]
1144
+ xhr.overrideMimeType && xhr.overrideMimeType(mime)
1145
+ }
1146
+ if (settings.contentType || (settings.data && settings.type.toUpperCase() != 'GET'))
1147
+ baseHeaders['Content-Type'] = (settings.contentType || 'application/x-www-form-urlencoded')
1148
+ settings.headers = $.extend(baseHeaders, settings.headers || {})
1149
+
1150
+ xhr.onreadystatechange = function(){
1151
+ if (xhr.readyState == 4) {
1152
+ clearTimeout(abortTimeout)
1153
+ var result, error = false
1154
+ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304 || (xhr.status == 0 && protocol == 'file:')) {
1155
+ dataType = dataType || mimeToDataType(xhr.getResponseHeader('content-type'))
1156
+ result = xhr.responseText
1157
+
1158
+ try {
1159
+ if (dataType == 'script') (1,eval)(result)
1160
+ else if (dataType == 'xml') result = xhr.responseXML
1161
+ else if (dataType == 'json') result = blankRE.test(result) ? null : JSON.parse(result)
1162
+ } catch (e) { error = e }
1163
+
1164
+ if (error) ajaxError(error, 'parsererror', xhr, settings)
1165
+ else ajaxSuccess(result, xhr, settings)
1166
+ } else {
1167
+ ajaxError(null, 'error', xhr, settings)
1168
+ }
1169
+ }
1170
+ }
1171
+
1172
+ var async = 'async' in settings ? settings.async : true
1173
+ xhr.open(settings.type, settings.url, async)
1174
+
1175
+ for (name in settings.headers) xhr.setRequestHeader(name, settings.headers[name])
1176
+
1177
+ if (ajaxBeforeSend(xhr, settings) === false) {
1178
+ xhr.abort()
1179
+ return false
1180
+ }
1181
+
1182
+ if (settings.timeout > 0) abortTimeout = setTimeout(function(){
1183
+ xhr.onreadystatechange = empty
1184
+ xhr.abort()
1185
+ ajaxError(null, 'timeout', xhr, settings)
1186
+ }, settings.timeout)
1187
+
1188
+ // avoid sending empty string (#319)
1189
+ xhr.send(settings.data ? settings.data : null)
1190
+ return xhr
1191
+ }
1192
+
1193
+ $.get = function(url, success){ return $.ajax({ url: url, success: success }) }
1194
+
1195
+ $.post = function(url, data, success, dataType){
1196
+ if ($.isFunction(data)) dataType = dataType || success, success = data, data = null
1197
+ return $.ajax({ type: 'POST', url: url, data: data, success: success, dataType: dataType })
1198
+ }
1199
+
1200
+ $.getJSON = function(url, success){
1201
+ return $.ajax({ url: url, success: success, dataType: 'json' })
1202
+ }
1203
+
1204
+ $.fn.load = function(url, success){
1205
+ if (!this.length) return this
1206
+ var self = this, parts = url.split(/\s/), selector
1207
+ if (parts.length > 1) url = parts[0], selector = parts[1]
1208
+ $.get(url, function(response){
1209
+ self.html(selector ?
1210
+ $(document.createElement('div')).html(response.replace(rscript, "")).find(selector).html()
1211
+ : response)
1212
+ success && success.call(self)
1213
+ })
1214
+ return this
1215
+ }
1216
+
1217
+ var escape = encodeURIComponent
1218
+
1219
+ function serialize(params, obj, traditional, scope){
1220
+ var array = $.isArray(obj)
1221
+ $.each(obj, function(key, value) {
1222
+ if (scope) key = traditional ? scope : scope + '[' + (array ? '' : key) + ']'
1223
+ // handle data in serializeArray() format
1224
+ if (!scope && array) params.add(value.name, value.value)
1225
+ // recurse into nested objects
1226
+ else if (traditional ? $.isArray(value) : isObject(value))
1227
+ serialize(params, value, traditional, key)
1228
+ else params.add(key, value)
1229
+ })
1230
+ }
1231
+
1232
+ $.param = function(obj, traditional){
1233
+ var params = []
1234
+ params.add = function(k, v){ this.push(escape(k) + '=' + escape(v)) }
1235
+ serialize(params, obj, traditional)
1236
+ return params.join('&').replace('%20', '+')
1237
+ }
1238
+ })(Zepto)
1239
+ ;(function ($) {
1240
+ $.fn.serializeArray = function () {
1241
+ var result = [], el
1242
+ $( Array.prototype.slice.call(this.get(0).elements) ).each(function () {
1243
+ el = $(this)
1244
+ var type = el.attr('type')
1245
+ if (this.nodeName.toLowerCase() != 'fieldset' &&
1246
+ !this.disabled && type != 'submit' && type != 'reset' && type != 'button' &&
1247
+ ((type != 'radio' && type != 'checkbox') || this.checked))
1248
+ result.push({
1249
+ name: el.attr('name'),
1250
+ value: el.val()
1251
+ })
1252
+ })
1253
+ return result
1254
+ }
1255
+
1256
+ $.fn.serialize = function () {
1257
+ var result = []
1258
+ this.serializeArray().forEach(function (elm) {
1259
+ result.push( encodeURIComponent(elm.name) + '=' + encodeURIComponent(elm.value) )
1260
+ })
1261
+ return result.join('&')
1262
+ }
1263
+
1264
+ $.fn.submit = function (callback) {
1265
+ if (callback) this.bind('submit', callback)
1266
+ else if (this.length) {
1267
+ var event = $.Event('submit')
1268
+ this.eq(0).trigger(event)
1269
+ if (!event.defaultPrevented) this.get(0).submit()
1270
+ }
1271
+ return this
1272
+ }
1273
+
1274
+ })(Zepto)
1275
+ ;(function($){
1276
+ var touch = {}, touchTimeout
1277
+
1278
+ function parentIfText(node){
1279
+ return 'tagName' in node ? node : node.parentNode
1280
+ }
1281
+
1282
+ function swipeDirection(x1, x2, y1, y2){
1283
+ var xDelta = Math.abs(x1 - x2), yDelta = Math.abs(y1 - y2)
1284
+ return xDelta >= yDelta ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')
1285
+ }
1286
+
1287
+ var longTapDelay = 750, longTapTimeout
1288
+
1289
+ function longTap(){
1290
+ longTapTimeout = null
1291
+ if (touch.last) {
1292
+ touch.el.trigger('longTap')
1293
+ touch = {}
1294
+ }
1295
+ }
1296
+
1297
+ function cancelLongTap(){
1298
+ if (longTapTimeout) clearTimeout(longTapTimeout)
1299
+ longTapTimeout = null
1300
+ }
1301
+
1302
+ $(document).ready(function(){
1303
+ var now, delta
1304
+
1305
+ $(document.body).bind('touchstart', function(e){
1306
+ now = Date.now()
1307
+ delta = now - (touch.last || now)
1308
+ touch.el = $(parentIfText(e.touches[0].target))
1309
+ touchTimeout && clearTimeout(touchTimeout)
1310
+ touch.x1 = e.touches[0].pageX
1311
+ touch.y1 = e.touches[0].pageY
1312
+ if (delta > 0 && delta <= 250) touch.isDoubleTap = true
1313
+ touch.last = now
1314
+ longTapTimeout = setTimeout(longTap, longTapDelay)
1315
+ }).bind('touchmove', function(e){
1316
+ cancelLongTap()
1317
+ touch.x2 = e.touches[0].pageX
1318
+ touch.y2 = e.touches[0].pageY
1319
+ }).bind('touchend', function(e){
1320
+ cancelLongTap()
1321
+
1322
+ // double tap (tapped twice within 250ms)
1323
+ if (touch.isDoubleTap) {
1324
+ touch.el.trigger('doubleTap')
1325
+ touch = {}
1326
+
1327
+ // swipe
1328
+ } else if ((touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) ||
1329
+ (touch.y2 && Math.abs(touch.y1 - touch.y2) > 30)) {
1330
+ touch.el.trigger('swipe') &&
1331
+ touch.el.trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2)))
1332
+ touch = {}
1333
+
1334
+ // normal tap
1335
+ } else if ('last' in touch) {
1336
+ touch.el.trigger('tap')
1337
+
1338
+ touchTimeout = setTimeout(function(){
1339
+ touchTimeout = null
1340
+ touch.el.trigger('singleTap')
1341
+ touch = {}
1342
+ }, 250)
1343
+ }
1344
+ }).bind('touchcancel', function(){
1345
+ if (touchTimeout) clearTimeout(touchTimeout)
1346
+ if (longTapTimeout) clearTimeout(longTapTimeout)
1347
+ longTapTimeout = touchTimeout = null
1348
+ touch = {}
1349
+ })
1350
+ })
1351
+
1352
+ ;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(m){
1353
+ $.fn[m] = function(callback){ return this.bind(m, callback) }
1354
+ })
1355
+ })(Zepto);