h2ocube_rails_assets 0.0.11 → 0.0.12

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.
@@ -0,0 +1,22 @@
1
+ // Zepto.js
2
+ // (c) 2010-2012 Thomas Fuchs
3
+ // Zepto.js may be freely distributed under the MIT license.
4
+
5
+ ;(function($){
6
+ $.fn.end = function(){
7
+ return this.prevObject || $()
8
+ }
9
+
10
+ $.fn.andSelf = function(){
11
+ return this.add(this.prevObject || $())
12
+ }
13
+
14
+ 'filter,add,not,eq,first,last,find,closest,parents,parent,children,siblings'.split(',').forEach(function(property){
15
+ var fn = $.fn[property]
16
+ $.fn[property] = function(){
17
+ var ret = fn.apply(this, arguments)
18
+ ret.prevObject = this
19
+ return ret
20
+ }
21
+ })
22
+ })(Zepto)
@@ -0,0 +1,115 @@
1
+ // Zepto.js
2
+ // (c) 2010-2012 Thomas Fuchs
3
+ // Zepto.js may be freely distributed under the MIT license.
4
+
5
+ ;(function($){
6
+ var touch = {},
7
+ touchTimeout, tapTimeout, swipeTimeout,
8
+ longTapDelay = 750, longTapTimeout
9
+
10
+ function parentIfText(node) {
11
+ return 'tagName' in node ? node : node.parentNode
12
+ }
13
+
14
+ function swipeDirection(x1, x2, y1, y2) {
15
+ var xDelta = Math.abs(x1 - x2), yDelta = Math.abs(y1 - y2)
16
+ return xDelta >= yDelta ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')
17
+ }
18
+
19
+ function longTap() {
20
+ longTapTimeout = null
21
+ if (touch.last) {
22
+ touch.el.trigger('longTap')
23
+ touch = {}
24
+ }
25
+ }
26
+
27
+ function cancelLongTap() {
28
+ if (longTapTimeout) clearTimeout(longTapTimeout)
29
+ longTapTimeout = null
30
+ }
31
+
32
+ function cancelAll() {
33
+ if (touchTimeout) clearTimeout(touchTimeout)
34
+ if (tapTimeout) clearTimeout(tapTimeout)
35
+ if (swipeTimeout) clearTimeout(swipeTimeout)
36
+ if (longTapTimeout) clearTimeout(longTapTimeout)
37
+ touchTimeout = tapTimeout = swipeTimeout = longTapTimeout = null
38
+ touch = {}
39
+ }
40
+
41
+ $(document).ready(function(){
42
+ var now, delta
43
+
44
+ $(document.body)
45
+ .bind('touchstart', function(e){
46
+ now = Date.now()
47
+ delta = now - (touch.last || now)
48
+ touch.el = $(parentIfText(e.touches[0].target))
49
+ touchTimeout && clearTimeout(touchTimeout)
50
+ touch.x1 = e.touches[0].pageX
51
+ touch.y1 = e.touches[0].pageY
52
+ if (delta > 0 && delta <= 250) touch.isDoubleTap = true
53
+ touch.last = now
54
+ longTapTimeout = setTimeout(longTap, longTapDelay)
55
+ })
56
+ .bind('touchmove', function(e){
57
+ cancelLongTap()
58
+ touch.x2 = e.touches[0].pageX
59
+ touch.y2 = e.touches[0].pageY
60
+ if (Math.abs(touch.x1 - touch.x2) > 10)
61
+ e.preventDefault()
62
+ })
63
+ .bind('touchend', function(e){
64
+ cancelLongTap()
65
+
66
+ // swipe
67
+ if ((touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) ||
68
+ (touch.y2 && Math.abs(touch.y1 - touch.y2) > 30))
69
+
70
+ swipeTimeout = setTimeout(function() {
71
+ touch.el.trigger('swipe')
72
+ touch.el.trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2)))
73
+ touch = {}
74
+ }, 0)
75
+
76
+ // normal tap
77
+ else if ('last' in touch)
78
+
79
+ // delay by one tick so we can cancel the 'tap' event if 'scroll' fires
80
+ // ('tap' fires before 'scroll')
81
+ tapTimeout = setTimeout(function() {
82
+
83
+ // trigger universal 'tap' with the option to cancelTouch()
84
+ // (cancelTouch cancels processing of single vs double taps for faster 'tap' response)
85
+ var event = $.Event('tap')
86
+ event.cancelTouch = cancelAll
87
+ touch.el.trigger(event)
88
+
89
+ // trigger double tap immediately
90
+ if (touch.isDoubleTap) {
91
+ touch.el.trigger('doubleTap')
92
+ touch = {}
93
+ }
94
+
95
+ // trigger single tap after 250ms of inactivity
96
+ else {
97
+ touchTimeout = setTimeout(function(){
98
+ touchTimeout = null
99
+ touch.el.trigger('singleTap')
100
+ touch = {}
101
+ }, 250)
102
+ }
103
+
104
+ }, 0)
105
+
106
+ })
107
+ .bind('touchcancel', cancelAll)
108
+
109
+ $(window).bind('scroll', cancelAll)
110
+ })
111
+
112
+ ;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(m){
113
+ $.fn[m] = function(callback){ return this.bind(m, callback) }
114
+ })
115
+ })(Zepto)
@@ -0,0 +1,2 @@
1
+ //= require zepto
2
+ //= require_tree ./zepto
@@ -1,7 +1,9 @@
1
- /* Zepto v1.0rc1 - polyfill zepto event detect fx ajax form touch - zeptojs.com/license */
1
+ /* Zepto v1.0-1-ga3cab6c - polyfill zepto detect event ajax form fx - zeptojs.com/license */
2
+
3
+
2
4
  ;(function(undefined){
3
5
  if (String.prototype.trim === undefined) // fix for iOS 3.2
4
- String.prototype.trim = function(){ return this.replace(/^\s+/, '').replace(/\s+$/, '') }
6
+ String.prototype.trim = function(){ return this.replace(/^\s+|\s+$/g, '') }
5
7
 
6
8
  // For iOS 3.x
7
9
  // from https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
@@ -31,17 +33,19 @@
31
33
  }
32
34
 
33
35
  })()
36
+
34
37
  var Zepto = (function() {
35
- var undefined, key, $, classList, emptyArray = [], slice = emptyArray.slice,
38
+ var undefined, key, $, classList, emptyArray = [], slice = emptyArray.slice, filter = emptyArray.filter,
36
39
  document = window.document,
37
40
  elementDisplay = {}, classCache = {},
38
41
  getComputedStyle = document.defaultView.getComputedStyle,
39
42
  cssNumber = { 'column-count': 1, 'columns': 1, 'font-weight': 1, 'line-height': 1,'opacity': 1, 'z-index': 1, 'zoom': 1 },
40
43
  fragmentRE = /^\s*<(\w+|!)[^>]*>/,
44
+ tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
45
+ rootNodeRE = /^(?:body|html)$/i,
41
46
 
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],
47
+ // special attributes that should be get/set via method calls
48
+ methodAttributes = ['val', 'css', 'html', 'text', 'data', 'width', 'height', 'offset'],
45
49
 
46
50
  adjacencyOperators = [ 'after', 'prepend', 'before', 'append' ],
47
51
  table = document.createElement('table'),
@@ -54,9 +58,10 @@ var Zepto = (function() {
54
58
  },
55
59
  readyRE = /complete|loaded|interactive/,
56
60
  classSelectorRE = /^\.([\w-]+)$/,
57
- idSelectorRE = /^#([\w-]+)$/,
61
+ idSelectorRE = /^#([\w-]*)$/,
58
62
  tagSelectorRE = /^[\w-]+$/,
59
- toString = ({}).toString,
63
+ class2type = {},
64
+ toString = class2type.toString,
60
65
  zepto = {},
61
66
  camelize, uniq,
62
67
  tempParent = document.createElement('div')
@@ -74,21 +79,23 @@ var Zepto = (function() {
74
79
  return match
75
80
  }
76
81
 
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)
82
+ function type(obj) {
83
+ return obj == null ? String(obj) :
84
+ class2type[toString.call(obj)] || "object"
85
+ }
86
+
87
+ function isFunction(value) { return type(value) == "function" }
88
+ function isWindow(obj) { return obj != null && obj == obj.window }
89
+ function isDocument(obj) { return obj != null && obj.nodeType == obj.DOCUMENT_NODE }
90
+ function isObject(obj) { return type(obj) == "object" }
91
+ function isPlainObject(obj) {
92
+ return isObject(obj) && !isWindow(obj) && obj.__proto__ == Object.prototype
86
93
  }
87
94
  function isArray(value) { return value instanceof Array }
88
95
  function likeArray(obj) { return typeof obj.length == 'number' }
89
96
 
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 }
97
+ function compact(array) { return filter.call(array, function(item){ return item != null }) }
98
+ function flatten(array) { return array.length > 0 ? $.fn.concat.apply([], array) : array }
92
99
  camelize = function(str){ return str.replace(/-+(.)?/g, function(match, chr){ return chr ? chr.toUpperCase() : '' }) }
93
100
  function dasherize(str) {
94
101
  return str.replace(/::/g, '/')
@@ -97,7 +104,7 @@ var Zepto = (function() {
97
104
  .replace(/_/g, '-')
98
105
  .toLowerCase()
99
106
  }
100
- uniq = function(array){ return array.filter(function(item, idx){ return array.indexOf(item) == idx }) }
107
+ uniq = function(array){ return filter.call(array, function(item, idx){ return array.indexOf(item) == idx }) }
101
108
 
102
109
  function classRE(name) {
103
110
  return name in classCache ?
@@ -121,19 +128,35 @@ var Zepto = (function() {
121
128
  return elementDisplay[nodeName]
122
129
  }
123
130
 
131
+ function children(element) {
132
+ return 'children' in element ?
133
+ slice.call(element.children) :
134
+ $.map(element.childNodes, function(node){ if (node.nodeType == 1) return node })
135
+ }
136
+
124
137
  // `$.zepto.fragment` takes a html string and an optional tag name
125
138
  // to generate DOM nodes nodes from the given html string.
126
139
  // The generated DOM nodes are returned as an array.
127
140
  // This function can be overriden in plugins for example to make
128
141
  // it compatible with browsers that don't support the DOM fully.
129
- zepto.fragment = function(html, name) {
142
+ zepto.fragment = function(html, name, properties) {
143
+ if (html.replace) html = html.replace(tagExpanderRE, "<$1></$2>")
130
144
  if (name === undefined) name = fragmentRE.test(html) && RegExp.$1
131
145
  if (!(name in containers)) name = '*'
132
- var container = containers[name]
146
+
147
+ var nodes, dom, container = containers[name]
133
148
  container.innerHTML = '' + html
134
- return $.each(slice.call(container.childNodes), function(){
149
+ dom = $.each(slice.call(container.childNodes), function(){
135
150
  container.removeChild(this)
136
151
  })
152
+ if (isPlainObject(properties)) {
153
+ nodes = $(dom)
154
+ $.each(properties, function(key, value) {
155
+ if (methodAttributes.indexOf(key) > -1) nodes[key](value)
156
+ else nodes.attr(key, value)
157
+ })
158
+ }
159
+ return dom
137
160
  }
138
161
 
139
162
  // `$.zepto.Z` swaps out the prototype of the given `dom` array
@@ -142,7 +165,7 @@ var Zepto = (function() {
142
165
  // Explorer. This method can be overriden in plugins.
143
166
  zepto.Z = function(dom, selector) {
144
167
  dom = dom || []
145
- dom.__proto__ = arguments.callee.prototype
168
+ dom.__proto__ = $.fn
146
169
  dom.selector = selector || ''
147
170
  return dom
148
171
  }
@@ -168,17 +191,12 @@ var Zepto = (function() {
168
191
  var dom
169
192
  // normalize array if an array of nodes is given
170
193
  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
194
+ // Wrap DOM nodes. If a plain object is given, duplicate it.
195
+ else if (isObject(selector))
196
+ dom = [isPlainObject(selector) ? $.extend({}, selector) : selector], selector = null
179
197
  // If it's a html fragment, create nodes from it
180
198
  else if (fragmentRE.test(selector))
181
- dom = zepto.fragment(selector.trim(), RegExp.$1), selector = null
199
+ dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
182
200
  // If there's a context, create a collection on that context first, and select
183
201
  // nodes from there
184
202
  else if (context !== undefined) return $(context).find(selector)
@@ -190,21 +208,34 @@ var Zepto = (function() {
190
208
  }
191
209
 
192
210
  // `$` will be the base `Zepto` object. When calling this
193
- // function just call `$.zepto.init, whichs makes the implementation
211
+ // function just call `$.zepto.init, which makes the implementation
194
212
  // details of selecting nodes and creating Zepto collections
195
213
  // patchable in plugins.
196
214
  $ = function(selector, context){
197
215
  return zepto.init(selector, context)
198
216
  }
199
217
 
218
+ function extend(target, source, deep) {
219
+ for (key in source)
220
+ if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
221
+ if (isPlainObject(source[key]) && !isPlainObject(target[key]))
222
+ target[key] = {}
223
+ if (isArray(source[key]) && !isArray(target[key]))
224
+ target[key] = []
225
+ extend(target[key], source[key], deep)
226
+ }
227
+ else if (source[key] !== undefined) target[key] = source[key]
228
+ }
229
+
200
230
  // Copy all but undefined properties from one or more
201
231
  // objects to the `target` object.
202
232
  $.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
- })
233
+ var deep, args = slice.call(arguments, 1)
234
+ if (typeof target == 'boolean') {
235
+ deep = target
236
+ target = args.shift()
237
+ }
238
+ args.forEach(function(arg){ extend(target, arg, deep) })
208
239
  return target
209
240
  }
210
241
 
@@ -213,9 +244,9 @@ var Zepto = (function() {
213
244
  // This method can be overriden in plugins.
214
245
  zepto.qsa = function(element, selector){
215
246
  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 :
247
+ return (isDocument(element) && idSelectorRE.test(selector)) ?
248
+ ( (found = element.getElementById(RegExp.$1)) ? [found] : [] ) :
249
+ (element.nodeType !== 1 && element.nodeType !== 9) ? [] :
219
250
  slice.call(
220
251
  classSelectorRE.test(selector) ? element.getElementsByClassName(RegExp.$1) :
221
252
  tagSelectorRE.test(selector) ? element.getElementsByTagName(selector) :
@@ -227,23 +258,73 @@ var Zepto = (function() {
227
258
  return selector === undefined ? $(nodes) : $(nodes).filter(selector)
228
259
  }
229
260
 
261
+ $.contains = function(parent, node) {
262
+ return parent !== node && parent.contains(node)
263
+ }
264
+
230
265
  function funcArg(context, arg, idx, payload) {
231
- return isFunction(arg) ? arg.call(context, idx, payload) : arg
266
+ return isFunction(arg) ? arg.call(context, idx, payload) : arg
267
+ }
268
+
269
+ function setAttribute(node, name, value) {
270
+ value == null ? node.removeAttribute(name) : node.setAttribute(name, value)
271
+ }
272
+
273
+ // access className property while respecting SVGAnimatedString
274
+ function className(node, value){
275
+ var klass = node.className,
276
+ svg = klass && klass.baseVal !== undefined
277
+
278
+ if (value === undefined) return svg ? klass.baseVal : klass
279
+ svg ? (klass.baseVal = value) : (node.className = value)
280
+ }
281
+
282
+ // "true" => true
283
+ // "false" => false
284
+ // "null" => null
285
+ // "42" => 42
286
+ // "42.5" => 42.5
287
+ // JSON => parse if valid
288
+ // String => self
289
+ function deserializeValue(value) {
290
+ var num
291
+ try {
292
+ return value ?
293
+ value == "true" ||
294
+ ( value == "false" ? false :
295
+ value == "null" ? null :
296
+ !isNaN(num = Number(value)) ? num :
297
+ /^[\[\{]/.test(value) ? $.parseJSON(value) :
298
+ value )
299
+ : value
300
+ } catch(e) {
301
+ return value
302
+ }
232
303
  }
233
304
 
305
+ $.type = type
234
306
  $.isFunction = isFunction
235
- $.isObject = isObject
307
+ $.isWindow = isWindow
236
308
  $.isArray = isArray
237
309
  $.isPlainObject = isPlainObject
238
310
 
311
+ $.isEmptyObject = function(obj) {
312
+ var name
313
+ for (name in obj) return false
314
+ return true
315
+ }
316
+
239
317
  $.inArray = function(elem, array, i){
240
318
  return emptyArray.indexOf.call(array, elem, i)
241
319
  }
242
320
 
321
+ $.camelCase = camelize
243
322
  $.trim = function(str) { return str.trim() }
244
323
 
245
324
  // plugin compatibility
246
325
  $.uuid = 0
326
+ $.support = { }
327
+ $.expr = { }
247
328
 
248
329
  $.map = function(elements, callback){
249
330
  var value, values = [], i, key
@@ -273,6 +354,17 @@ var Zepto = (function() {
273
354
  return elements
274
355
  }
275
356
 
357
+ $.grep = function(elements, callback){
358
+ return filter.call(elements, callback)
359
+ }
360
+
361
+ if (window.JSON) $.parseJSON = JSON.parse
362
+
363
+ // Populate the class2type map
364
+ $.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
365
+ class2type[ "[object " + name + "]" ] = name.toLowerCase()
366
+ })
367
+
276
368
  // Define methods that will be available on all
277
369
  // Zepto collections
278
370
  $.fn = {
@@ -281,13 +373,14 @@ var Zepto = (function() {
281
373
  forEach: emptyArray.forEach,
282
374
  reduce: emptyArray.reduce,
283
375
  push: emptyArray.push,
376
+ sort: emptyArray.sort,
284
377
  indexOf: emptyArray.indexOf,
285
378
  concat: emptyArray.concat,
286
379
 
287
380
  // `map` and `slice` in the jQuery API work differently
288
381
  // from their array counterparts
289
382
  map: function(fn){
290
- return $.map(this, function(el, i){ return fn.call(el, i, el) })
383
+ return $($.map(this, function(el, i){ return fn.call(el, i, el) }))
291
384
  },
292
385
  slice: function(){
293
386
  return $(slice.apply(this, arguments))
@@ -299,7 +392,7 @@ var Zepto = (function() {
299
392
  return this
300
393
  },
301
394
  get: function(idx){
302
- return idx === undefined ? slice.call(this) : this[idx]
395
+ return idx === undefined ? slice.call(this) : this[idx >= 0 ? idx : idx + this.length]
303
396
  },
304
397
  toArray: function(){ return this.get() },
305
398
  size: function(){
@@ -312,11 +405,14 @@ var Zepto = (function() {
312
405
  })
313
406
  },
314
407
  each: function(callback){
315
- this.forEach(function(el, idx){ callback.call(el, idx, el) })
408
+ emptyArray.every.call(this, function(el, idx){
409
+ return callback.call(el, idx, el) !== false
410
+ })
316
411
  return this
317
412
  },
318
413
  filter: function(selector){
319
- return $([].filter.call(this, function(element){
414
+ if (isFunction(selector)) return this.not(this.not(selector))
415
+ return $(filter.call(this, function(element){
320
416
  return zepto.matches(element, selector)
321
417
  }))
322
418
  },
@@ -341,6 +437,13 @@ var Zepto = (function() {
341
437
  }
342
438
  return $(nodes)
343
439
  },
440
+ has: function(selector){
441
+ return this.filter(function(){
442
+ return isObject(selector) ?
443
+ $.contains(this, selector) :
444
+ $(this).find(selector).size()
445
+ })
446
+ },
344
447
  eq: function(idx){
345
448
  return idx === -1 ? this.slice(idx) : this.slice(idx, + idx + 1)
346
449
  },
@@ -353,22 +456,30 @@ var Zepto = (function() {
353
456
  return el && !isObject(el) ? el : $(el)
354
457
  },
355
458
  find: function(selector){
356
- var result
357
- if (this.length == 1) result = zepto.qsa(this[0], selector)
459
+ var result, $this = this
460
+ if (typeof selector == 'object')
461
+ result = $(selector).filter(function(){
462
+ var node = this
463
+ return emptyArray.some.call($this, function(parent){
464
+ return $.contains(parent, node)
465
+ })
466
+ })
467
+ else if (this.length == 1) result = $(zepto.qsa(this[0], selector))
358
468
  else result = this.map(function(){ return zepto.qsa(this, selector) })
359
- return $(result)
469
+ return result
360
470
  },
361
471
  closest: function(selector, context){
362
- var node = this[0]
363
- while (node && !zepto.matches(node, selector))
364
- node = node !== context && node !== document && node.parentNode
472
+ var node = this[0], collection = false
473
+ if (typeof selector == 'object') collection = $(selector)
474
+ while (node && !(collection ? collection.indexOf(node) >= 0 : zepto.matches(node, selector)))
475
+ node = node !== context && !isDocument(node) && node.parentNode
365
476
  return $(node)
366
477
  },
367
478
  parents: function(selector){
368
479
  var ancestors = [], nodes = this
369
480
  while (nodes.length > 0)
370
481
  nodes = $.map(nodes, function(node){
371
- if ((node = node.parentNode) && node !== document && ancestors.indexOf(node) < 0) {
482
+ if ((node = node.parentNode) && !isDocument(node) && ancestors.indexOf(node) < 0) {
372
483
  ancestors.push(node)
373
484
  return node
374
485
  }
@@ -379,11 +490,14 @@ var Zepto = (function() {
379
490
  return filtered(uniq(this.pluck('parentNode')), selector)
380
491
  },
381
492
  children: function(selector){
382
- return filtered(this.map(function(){ return slice.call(this.children) }), selector)
493
+ return filtered(this.map(function(){ return children(this) }), selector)
494
+ },
495
+ contents: function() {
496
+ return this.map(function() { return slice.call(this.childNodes) })
383
497
  },
384
498
  siblings: function(selector){
385
499
  return filtered(this.map(function(i, el){
386
- return slice.call(el.parentNode.children).filter(function(child){ return child!==el })
500
+ return filter.call(children(el.parentNode), function(child){ return child!==el })
387
501
  }), selector)
388
502
  },
389
503
  empty: function(){
@@ -391,7 +505,7 @@ var Zepto = (function() {
391
505
  },
392
506
  // `pluck` is borrowed from Prototype.js
393
507
  pluck: function(property){
394
- return this.map(function(){ return this[property] })
508
+ return $.map(this, function(el){ return el[property] })
395
509
  },
396
510
  show: function(){
397
511
  return this.each(function(){
@@ -403,18 +517,37 @@ var Zepto = (function() {
403
517
  replaceWith: function(newContent){
404
518
  return this.before(newContent).remove()
405
519
  },
406
- wrap: function(newContent){
407
- return this.each(function(){
408
- $(this).wrapAll($(newContent)[0].cloneNode(false))
520
+ wrap: function(structure){
521
+ var func = isFunction(structure)
522
+ if (this[0] && !func)
523
+ var dom = $(structure).get(0),
524
+ clone = dom.parentNode || this.length > 1
525
+
526
+ return this.each(function(index){
527
+ $(this).wrapAll(
528
+ func ? structure.call(this, index) :
529
+ clone ? dom.cloneNode(true) : dom
530
+ )
409
531
  })
410
532
  },
411
- wrapAll: function(newContent){
533
+ wrapAll: function(structure){
412
534
  if (this[0]) {
413
- $(this[0]).before(newContent = $(newContent))
414
- newContent.append(this)
535
+ $(this[0]).before(structure = $(structure))
536
+ var children
537
+ // drill down to the inmost element
538
+ while ((children = structure.children()).length) structure = children.first()
539
+ $(structure).append(this)
415
540
  }
416
541
  return this
417
542
  },
543
+ wrapInner: function(structure){
544
+ var func = isFunction(structure)
545
+ return this.each(function(index){
546
+ var self = $(this), contents = self.contents(),
547
+ dom = func ? structure.call(this, index) : structure
548
+ contents.length ? contents.wrapAll(dom) : self.append(dom)
549
+ })
550
+ },
418
551
  unwrap: function(){
419
552
  this.parent().each(function(){
420
553
  $(this).replaceWith($(this).children())
@@ -422,16 +555,19 @@ var Zepto = (function() {
422
555
  return this
423
556
  },
424
557
  clone: function(){
425
- return $(this.map(function(){ return this.cloneNode(true) }))
558
+ return this.map(function(){ return this.cloneNode(true) })
426
559
  },
427
560
  hide: function(){
428
561
  return this.css("display", "none")
429
562
  },
430
563
  toggle: function(setting){
431
- return (setting === undefined ? this.css("display") == "none" : setting) ? this.show() : this.hide()
564
+ return this.each(function(){
565
+ var el = $(this)
566
+ ;(setting === undefined ? el.css("display") == "none" : setting) ? el.show() : el.hide()
567
+ })
432
568
  },
433
- prev: function(){ return $(this.pluck('previousElementSibling')) },
434
- next: function(){ return $(this.pluck('nextElementSibling')) },
569
+ prev: function(selector){ return $(this.pluck('previousElementSibling')).filter(selector || '*') },
570
+ next: function(selector){ return $(this.pluck('nextElementSibling')).filter(selector || '*') },
435
571
  html: function(html){
436
572
  return html === undefined ?
437
573
  (this.length > 0 ? this[0].innerHTML : null) :
@@ -454,60 +590,73 @@ var Zepto = (function() {
454
590
  ) :
455
591
  this.each(function(idx){
456
592
  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)))
593
+ if (isObject(name)) for (key in name) setAttribute(this, key, name[key])
594
+ else setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name)))
459
595
  })
460
596
  },
461
597
  removeAttr: function(name){
462
- return this.each(function(){ if (this.nodeType === 1) this.removeAttribute(name) })
598
+ return this.each(function(){ this.nodeType === 1 && setAttribute(this, name) })
463
599
  },
464
600
  prop: function(name, value){
465
601
  return (value === undefined) ?
466
- (this[0] ? this[0][name] : undefined) :
602
+ (this[0] && this[0][name]) :
467
603
  this.each(function(idx){
468
604
  this[name] = funcArg(this, value, idx, this[name])
469
605
  })
470
606
  },
471
607
  data: function(name, value){
472
608
  var data = this.attr('data-' + dasherize(name), value)
473
- return data !== null ? data : undefined
609
+ return data !== null ? deserializeValue(data) : undefined
474
610
  },
475
611
  val: function(value){
476
612
  return (value === undefined) ?
477
- (this.length > 0 ? this[0].value : undefined) :
613
+ (this[0] && (this[0].multiple ?
614
+ $(this[0]).find('option').filter(function(o){ return this.selected }).pluck('value') :
615
+ this[0].value)
616
+ ) :
478
617
  this.each(function(idx){
479
618
  this.value = funcArg(this, value, idx, this.value)
480
619
  })
481
620
  },
482
- offset: function(){
621
+ offset: function(coordinates){
622
+ if (coordinates) return this.each(function(index){
623
+ var $this = $(this),
624
+ coords = funcArg(this, coordinates, index, $this.offset()),
625
+ parentOffset = $this.offsetParent().offset(),
626
+ props = {
627
+ top: coords.top - parentOffset.top,
628
+ left: coords.left - parentOffset.left
629
+ }
630
+
631
+ if ($this.css('position') == 'static') props['position'] = 'relative'
632
+ $this.css(props)
633
+ })
483
634
  if (this.length==0) return null
484
635
  var obj = this[0].getBoundingClientRect()
485
636
  return {
486
637
  left: obj.left + window.pageXOffset,
487
638
  top: obj.top + window.pageYOffset,
488
- width: obj.width,
489
- height: obj.height
639
+ width: Math.round(obj.width),
640
+ height: Math.round(obj.height)
490
641
  }
491
642
  },
492
643
  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))
644
+ if (arguments.length < 2 && typeof property == 'string')
645
+ return this[0] && (this[0].style[camelize(property)] || getComputedStyle(this[0], '').getPropertyValue(property))
498
646
 
499
647
  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 == '')
648
+ if (type(property) == 'string') {
649
+ if (!value && value !== 0)
508
650
  this.each(function(){ this.style.removeProperty(dasherize(property)) })
509
651
  else
510
652
  css = dasherize(property) + ":" + maybeAddPx(property, value)
653
+ } else {
654
+ for (key in property)
655
+ if (!property[key] && property[key] !== 0)
656
+ this.each(function(){ this.style.removeProperty(dasherize(key)) })
657
+ else
658
+ css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ';'
659
+ }
511
660
 
512
661
  return this.each(function(){ this.style.cssText += ';' + css })
513
662
  },
@@ -515,63 +664,97 @@ var Zepto = (function() {
515
664
  return element ? this.indexOf($(element)[0]) : this.parent().children().indexOf(this[0])
516
665
  },
517
666
  hasClass: function(name){
518
- if (this.length < 1) return false
519
- else return classRE(name).test(this[0].className)
667
+ return emptyArray.some.call(this, function(el){
668
+ return this.test(className(el))
669
+ }, classRE(name))
520
670
  },
521
671
  addClass: function(name){
522
672
  return this.each(function(idx){
523
673
  classList = []
524
- var cls = this.className, newName = funcArg(this, name, idx, cls)
674
+ var cls = className(this), newName = funcArg(this, name, idx, cls)
525
675
  newName.split(/\s+/g).forEach(function(klass){
526
676
  if (!$(this).hasClass(klass)) classList.push(klass)
527
677
  }, this)
528
- classList.length && (this.className += (cls ? " " : "") + classList.join(" "))
678
+ classList.length && className(this, cls + (cls ? " " : "") + classList.join(" "))
529
679
  })
530
680
  },
531
681
  removeClass: function(name){
532
682
  return this.each(function(idx){
533
- if (name === undefined)
534
- return this.className = ''
535
- classList = this.className
683
+ if (name === undefined) return className(this, '')
684
+ classList = className(this)
536
685
  funcArg(this, name, idx, classList).split(/\s+/g).forEach(function(klass){
537
686
  classList = classList.replace(classRE(klass), " ")
538
687
  })
539
- this.className = classList.trim()
688
+ className(this, classList.trim())
540
689
  })
541
690
  },
542
691
  toggleClass: function(name, when){
543
692
  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)
693
+ var $this = $(this), names = funcArg(this, name, idx, className(this))
694
+ names.split(/\s+/g).forEach(function(klass){
695
+ (when === undefined ? !$this.hasClass(klass) : when) ?
696
+ $this.addClass(klass) : $this.removeClass(klass)
697
+ })
698
+ })
699
+ },
700
+ scrollTop: function(){
701
+ if (!this.length) return
702
+ return ('scrollTop' in this[0]) ? this[0].scrollTop : this[0].scrollY
703
+ },
704
+ position: function() {
705
+ if (!this.length) return
706
+
707
+ var elem = this[0],
708
+ // Get *real* offsetParent
709
+ offsetParent = this.offsetParent(),
710
+ // Get correct offsets
711
+ offset = this.offset(),
712
+ parentOffset = rootNodeRE.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset()
713
+
714
+ // Subtract element margins
715
+ // note: when an element has margin: auto the offsetLeft and marginLeft
716
+ // are the same in Safari causing offset.left to incorrectly be 0
717
+ offset.top -= parseFloat( $(elem).css('margin-top') ) || 0
718
+ offset.left -= parseFloat( $(elem).css('margin-left') ) || 0
719
+
720
+ // Add offsetParent borders
721
+ parentOffset.top += parseFloat( $(offsetParent[0]).css('border-top-width') ) || 0
722
+ parentOffset.left += parseFloat( $(offsetParent[0]).css('border-left-width') ) || 0
723
+
724
+ // Subtract the two offsets
725
+ return {
726
+ top: offset.top - parentOffset.top,
727
+ left: offset.left - parentOffset.left
728
+ }
729
+ },
730
+ offsetParent: function() {
731
+ return this.map(function(){
732
+ var parent = this.offsetParent || document.body
733
+ while (parent && !rootNodeRE.test(parent.nodeName) && $(parent).css("position") == "static")
734
+ parent = parent.offsetParent
735
+ return parent
547
736
  })
548
737
  }
549
738
  }
550
739
 
740
+ // for now
741
+ $.fn.detach = $.fn.remove
742
+
551
743
  // Generate the `width` and `height` functions
552
744
  ;['width', 'height'].forEach(function(dimension){
553
745
  $.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] :
746
+ var offset, el = this[0],
747
+ Dimension = dimension.replace(/./, function(m){ return m[0].toUpperCase() })
748
+ if (value === undefined) return isWindow(el) ? el['inner' + Dimension] :
749
+ isDocument(el) ? el.documentElement['offset' + Dimension] :
557
750
  (offset = this.offset()) && offset[dimension]
558
751
  else return this.each(function(idx){
559
- var el = $(this)
752
+ el = $(this)
560
753
  el.css(dimension, funcArg(this, value, idx, el[dimension]()))
561
754
  })
562
755
  }
563
756
  })
564
757
 
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
758
  function traverseNode(node, fun) {
576
759
  fun(node)
577
760
  for (var key in node.childNodes) traverseNode(node.childNodes[key], fun)
@@ -579,28 +762,47 @@ var Zepto = (function() {
579
762
 
580
763
  // Generate the `after`, `prepend`, `before`, `append`,
581
764
  // `insertAfter`, `insertBefore`, `appendTo`, and `prependTo` methods.
582
- adjacencyOperators.forEach(function(key, operator) {
583
- $.fn[key] = function(){
765
+ adjacencyOperators.forEach(function(operator, operatorIndex) {
766
+ var inside = operatorIndex % 2 //=> prepend, append
767
+
768
+ $.fn[operator] = function(){
584
769
  // 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) })
770
+ var argType, nodes = $.map(arguments, function(arg) {
771
+ argType = type(arg)
772
+ return argType == "object" || argType == "array" || arg == null ?
773
+ arg : zepto.fragment(arg)
774
+ }),
775
+ parent, copyByClone = this.length > 1
586
776
  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)
777
+
778
+ return this.each(function(_, target){
779
+ parent = inside ? target : target.parentNode
780
+
781
+ // convert all methods to a "before" operation
782
+ target = operatorIndex == 0 ? target.nextSibling :
783
+ operatorIndex == 1 ? target.firstChild :
784
+ operatorIndex == 2 ? target :
785
+ null
786
+
787
+ nodes.forEach(function(node){
788
+ if (copyByClone) node = node.cloneNode(true)
789
+ else if (!parent) return $(node).remove()
790
+
791
+ traverseNode(parent.insertBefore(node, target), function(el){
792
+ if (el.nodeName != null && el.nodeName.toUpperCase() === 'SCRIPT' &&
793
+ (!el.type || el.type === 'text/javascript') && !el.src)
794
+ window['eval'].call(window, el.innerHTML)
595
795
  })
596
- if (copyByClone && index < size - 1) node = node.cloneNode(true)
597
- insert(operator, target, node)
598
- }
796
+ })
599
797
  })
600
798
  }
601
799
 
602
- $.fn[(operator % 2) ? key+'To' : 'insert'+(operator ? 'Before' : 'After')] = function(html){
603
- $(html)[key](this)
800
+ // after => insertAfter
801
+ // prepend => prependTo
802
+ // before => insertBefore
803
+ // append => appendTo
804
+ $.fn[inside ? operator+'To' : 'insert'+(operatorIndex ? 'Before' : 'After')] = function(html){
805
+ $(html)[operator](this)
604
806
  return this
605
807
  }
606
808
  })
@@ -608,18 +810,71 @@ var Zepto = (function() {
608
810
  zepto.Z.prototype = $.fn
609
811
 
610
812
  // Export internal API functions in the `$.zepto` namespace
611
- zepto.camelize = camelize
612
813
  zepto.uniq = uniq
814
+ zepto.deserializeValue = deserializeValue
613
815
  $.zepto = zepto
614
816
 
615
817
  return $
616
818
  })()
617
819
 
618
- // If `$` is not yet defined, point it to `Zepto`
619
820
  window.Zepto = Zepto
620
821
  '$' in window || (window.$ = Zepto)
822
+
621
823
  ;(function($){
622
- var $$ = $.zepto.qsa, handlers = {}, _zid = 1, specialEvents={}
824
+ function detect(ua){
825
+ var os = this.os = {}, browser = this.browser = {},
826
+ webkit = ua.match(/WebKit\/([\d.]+)/),
827
+ android = ua.match(/(Android)\s+([\d.]+)/),
828
+ ipad = ua.match(/(iPad).*OS\s([\d_]+)/),
829
+ iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/),
830
+ webos = ua.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),
831
+ touchpad = webos && ua.match(/TouchPad/),
832
+ kindle = ua.match(/Kindle\/([\d.]+)/),
833
+ silk = ua.match(/Silk\/([\d._]+)/),
834
+ blackberry = ua.match(/(BlackBerry).*Version\/([\d.]+)/),
835
+ bb10 = ua.match(/(BB10).*Version\/([\d.]+)/),
836
+ rimtabletos = ua.match(/(RIM\sTablet\sOS)\s([\d.]+)/),
837
+ playbook = ua.match(/PlayBook/),
838
+ chrome = ua.match(/Chrome\/([\d.]+)/) || ua.match(/CriOS\/([\d.]+)/),
839
+ firefox = ua.match(/Firefox\/([\d.]+)/)
840
+
841
+ // Todo: clean this up with a better OS/browser seperation:
842
+ // - discern (more) between multiple browsers on android
843
+ // - decide if kindle fire in silk mode is android or not
844
+ // - Firefox on Android doesn't specify the Android version
845
+ // - possibly devide in os, device and browser hashes
846
+
847
+ if (browser.webkit = !!webkit) browser.version = webkit[1]
848
+
849
+ if (android) os.android = true, os.version = android[2]
850
+ if (iphone) os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.')
851
+ if (ipad) os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.')
852
+ if (webos) os.webos = true, os.version = webos[2]
853
+ if (touchpad) os.touchpad = true
854
+ if (blackberry) os.blackberry = true, os.version = blackberry[2]
855
+ if (bb10) os.bb10 = true, os.version = bb10[2]
856
+ if (rimtabletos) os.rimtabletos = true, os.version = rimtabletos[2]
857
+ if (playbook) browser.playbook = true
858
+ if (kindle) os.kindle = true, os.version = kindle[1]
859
+ if (silk) browser.silk = true, browser.version = silk[1]
860
+ if (!silk && os.android && ua.match(/Kindle Fire/)) browser.silk = true
861
+ if (chrome) browser.chrome = true, browser.version = chrome[1]
862
+ if (firefox) browser.firefox = true, browser.version = firefox[1]
863
+
864
+ os.tablet = !!(ipad || playbook || (android && !ua.match(/Mobile/)) || (firefox && ua.match(/Tablet/)))
865
+ os.phone = !!(!os.tablet && (android || iphone || webos || blackberry || bb10 ||
866
+ (chrome && ua.match(/Android/)) || (chrome && ua.match(/CriOS\/([\d.]+)/)) || (firefox && ua.match(/Mobile/))))
867
+ }
868
+
869
+ detect.call($, navigator.userAgent)
870
+ // make available to unit tests
871
+ $.__detect = detect
872
+
873
+ })(Zepto)
874
+
875
+ ;(function($){
876
+ var $$ = $.zepto.qsa, handlers = {}, _zid = 1, specialEvents={},
877
+ hover = { mouseenter: 'mouseover', mouseleave: 'mouseout' }
623
878
 
624
879
  specialEvents.click = specialEvents.mousedown = specialEvents.mouseup = specialEvents.mousemove = 'MouseEvents'
625
880
 
@@ -646,32 +901,50 @@ window.Zepto = Zepto
646
901
  }
647
902
 
648
903
  function eachEvent(events, fn, iterator){
649
- if ($.isObject(events)) $.each(events, iterator)
904
+ if ($.type(events) != "string") $.each(events, iterator)
650
905
  else events.split(/\s/).forEach(function(type){ iterator(type, fn) })
651
906
  }
652
907
 
908
+ function eventCapture(handler, captureSetting) {
909
+ return handler.del &&
910
+ (handler.e == 'focus' || handler.e == 'blur') ||
911
+ !!captureSetting
912
+ }
913
+
914
+ function realEvent(type) {
915
+ return hover[type] || type
916
+ }
917
+
653
918
  function add(element, events, fn, selector, getDelegate, capture){
654
- capture = !!capture
655
919
  var id = zid(element), set = (handlers[id] || (handlers[id] = []))
656
920
  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()
921
+ var handler = parse(event)
922
+ handler.fn = fn
923
+ handler.sel = selector
924
+ // emulate mouseenter, mouseleave
925
+ if (handler.e in hover) fn = function(e){
926
+ var related = e.relatedTarget
927
+ if (!related || (related !== this && !$.contains(this, related)))
928
+ return handler.fn.apply(this, arguments)
929
+ }
930
+ handler.del = getDelegate && getDelegate(fn, event)
931
+ var callback = handler.del || fn
932
+ handler.proxy = function (e) {
933
+ var result = callback.apply(element, [e].concat(e.data))
934
+ if (result === false) e.preventDefault(), e.stopPropagation()
662
935
  return result
663
936
  }
664
- var handler = $.extend(parse(event), {fn: fn, proxy: proxyfn, sel: selector, del: delegate, i: set.length})
937
+ handler.i = set.length
665
938
  set.push(handler)
666
- element.addEventListener(handler.e, proxyfn, capture)
939
+ element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
667
940
  })
668
941
  }
669
- function remove(element, events, fn, selector){
942
+ function remove(element, events, fn, selector, capture){
670
943
  var id = zid(element)
671
944
  eachEvent(events || '', fn, function(event, fn){
672
945
  findHandlers(element, event, fn, selector).forEach(function(handler){
673
946
  delete handlers[id][handler.i]
674
- element.removeEventListener(handler.e, handler.proxy, false)
947
+ element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
675
948
  })
676
949
  })
677
950
  }
@@ -714,13 +987,17 @@ window.Zepto = Zepto
714
987
 
715
988
  var returnTrue = function(){return true},
716
989
  returnFalse = function(){return false},
990
+ ignoreProperties = /^([A-Z]|layer[XY]$)/,
717
991
  eventMethods = {
718
992
  preventDefault: 'isDefaultPrevented',
719
993
  stopImmediatePropagation: 'isImmediatePropagationStopped',
720
994
  stopPropagation: 'isPropagationStopped'
721
995
  }
722
996
  function createProxy(event) {
723
- var proxy = $.extend({originalEvent: event}, event)
997
+ var key, proxy = { originalEvent: event }
998
+ for (key in event)
999
+ if (!ignoreProperties.test(key) && event[key] !== undefined) proxy[key] = event[key]
1000
+
724
1001
  $.each(eventMethods, function(name, predicate) {
725
1002
  proxy[name] = function(){
726
1003
  this[predicate] = returnTrue
@@ -744,14 +1021,6 @@ window.Zepto = Zepto
744
1021
  }
745
1022
 
746
1023
  $.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
1024
  return this.each(function(i, element){
756
1025
  add(element, event, callback, selector, function(fn){
757
1026
  return function(e){
@@ -761,7 +1030,7 @@ window.Zepto = Zepto
761
1030
  return fn.apply(match, [evt].concat([].slice.call(arguments, 1)))
762
1031
  }
763
1032
  }
764
- }, capture)
1033
+ })
765
1034
  })
766
1035
  }
767
1036
  $.fn.undelegate = function(selector, event, callback){
@@ -780,16 +1049,16 @@ window.Zepto = Zepto
780
1049
  }
781
1050
 
782
1051
  $.fn.on = function(event, selector, callback){
783
- return selector == undefined || $.isFunction(selector) ?
784
- this.bind(event, selector) : this.delegate(selector, event, callback)
1052
+ return !selector || $.isFunction(selector) ?
1053
+ this.bind(event, selector || callback) : this.delegate(selector, event, callback)
785
1054
  }
786
1055
  $.fn.off = function(event, selector, callback){
787
- return selector == undefined || $.isFunction(selector) ?
788
- this.unbind(event, selector) : this.undelegate(selector, event, callback)
1056
+ return !selector || $.isFunction(selector) ?
1057
+ this.unbind(event, selector || callback) : this.undelegate(selector, event, callback)
789
1058
  }
790
1059
 
791
1060
  $.fn.trigger = function(event, data){
792
- if (typeof event == 'string') event = $.Event(event)
1061
+ if (typeof event == 'string' || $.isPlainObject(event)) event = $.Event(event)
793
1062
  fix(event)
794
1063
  event.data = data
795
1064
  return this.each(function(){
@@ -817,153 +1086,39 @@ window.Zepto = Zepto
817
1086
 
818
1087
  // shortcut methods for `.bind(event, fn)` for each event type
819
1088
  ;('focusin focusout load resize scroll unload click dblclick '+
820
- 'mousedown mouseup mousemove mouseover mouseout '+
1089
+ 'mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave '+
821
1090
  'change select keydown keypress keyup error').split(' ').forEach(function(event) {
822
- $.fn[event] = function(callback){ return this.bind(event, callback) }
1091
+ $.fn[event] = function(callback) {
1092
+ return callback ?
1093
+ this.bind(event, callback) :
1094
+ this.trigger(event)
1095
+ }
823
1096
  })
824
1097
 
825
1098
  ;['focus', 'blur'].forEach(function(name) {
826
1099
  $.fn[name] = function(callback) {
827
1100
  if (callback) this.bind(name, callback)
828
- else if (this.length) try { this.get(0)[name]() } catch(e){}
1101
+ else this.each(function(){
1102
+ try { this[name]() }
1103
+ catch(e) {}
1104
+ })
829
1105
  return this
830
1106
  }
831
1107
  })
832
1108
 
833
1109
  $.Event = function(type, props) {
1110
+ if (typeof type != 'string') props = type, type = props.type
834
1111
  var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true
835
1112
  if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name])
836
1113
  event.initEvent(type, bubbles, true, null, null, null, null, null, null, null, null, null, null, null, null)
1114
+ event.isDefaultPrevented = function(){ return this.defaultPrevented }
837
1115
  return event
838
1116
  }
839
1117
 
840
1118
  })(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
1119
 
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
1120
  ;(function($){
965
1121
  var jsonpID = 0,
966
- isObject = $.isObject,
967
1122
  document = window.document,
968
1123
  key,
969
1124
  name,
@@ -1030,35 +1185,42 @@ window.Zepto = Zepto
1030
1185
  function empty() {}
1031
1186
 
1032
1187
  $.ajaxJSONP = function(options){
1188
+ if (!('type' in options)) return $.ajax(options)
1189
+
1033
1190
  var callbackName = 'jsonp' + (++jsonpID),
1034
1191
  script = document.createElement('script'),
1035
- abort = function(){
1192
+ cleanup = function() {
1193
+ clearTimeout(abortTimeout)
1036
1194
  $(script).remove()
1037
- if (callbackName in window) window[callbackName] = empty
1038
- ajaxComplete('abort', xhr, options)
1195
+ delete window[callbackName]
1196
+ },
1197
+ abort = function(type){
1198
+ cleanup()
1199
+ // In case of manual abort or timeout, keep an empty function as callback
1200
+ // so that the SCRIPT tag that eventually loads won't result in an error.
1201
+ if (!type || type == 'timeout') window[callbackName] = empty
1202
+ ajaxError(null, type || 'abort', xhr, options)
1039
1203
  },
1040
1204
  xhr = { abort: abort }, abortTimeout
1041
1205
 
1042
- if (options.error) script.onerror = function() {
1043
- xhr.abort()
1044
- options.error()
1206
+ if (ajaxBeforeSend(xhr, options) === false) {
1207
+ abort('abort')
1208
+ return false
1045
1209
  }
1046
1210
 
1047
1211
  window[callbackName] = function(data){
1048
- clearTimeout(abortTimeout)
1049
- $(script).remove()
1050
- delete window[callbackName]
1212
+ cleanup()
1051
1213
  ajaxSuccess(data, xhr, options)
1052
1214
  }
1053
1215
 
1054
- serializeData(options)
1216
+ script.onerror = function() { abort('error') }
1217
+
1055
1218
  script.src = options.url.replace(/=\?/, '=' + callbackName)
1056
1219
  $('head').append(script)
1057
1220
 
1058
1221
  if (options.timeout > 0) abortTimeout = setTimeout(function(){
1059
- xhr.abort()
1060
- ajaxComplete('timeout', xhr, options)
1061
- }, options.timeout)
1222
+ abort('timeout')
1223
+ }, options.timeout)
1062
1224
 
1063
1225
  return xhr
1064
1226
  }
@@ -1093,10 +1255,15 @@ window.Zepto = Zepto
1093
1255
  // Whether the request is to another domain
1094
1256
  crossDomain: false,
1095
1257
  // Default timeout
1096
- timeout: 0
1258
+ timeout: 0,
1259
+ // Whether data should be serialized to string
1260
+ processData: true,
1261
+ // Whether the browser should be allowed to cache GET responses
1262
+ cache: true,
1097
1263
  }
1098
1264
 
1099
1265
  function mimeToDataType(mime) {
1266
+ if (mime) mime = mime.split(';', 2)[0]
1100
1267
  return mime && ( mime == htmlType ? 'html' :
1101
1268
  mime == jsonType ? 'json' :
1102
1269
  scriptTypeRE.test(mime) ? 'script' :
@@ -1109,7 +1276,8 @@ window.Zepto = Zepto
1109
1276
 
1110
1277
  // serialize payload and append it to the URL for GET requests
1111
1278
  function serializeData(options) {
1112
- if (isObject(options.data)) options.data = $.param(options.data)
1279
+ if (options.processData && options.data && $.type(options.data) != "string")
1280
+ options.data = $.param(options.data, options.traditional)
1113
1281
  if (options.data && (!options.type || options.type.toUpperCase() == 'GET'))
1114
1282
  options.url = appendQuery(options.url, options.data)
1115
1283
  }
@@ -1123,19 +1291,20 @@ window.Zepto = Zepto
1123
1291
  if (!settings.crossDomain) settings.crossDomain = /^([\w-]+:)?\/\/([^\/]+)/.test(settings.url) &&
1124
1292
  RegExp.$2 != window.location.host
1125
1293
 
1294
+ if (!settings.url) settings.url = window.location.toString()
1295
+ serializeData(settings)
1296
+ if (settings.cache === false) settings.url = appendQuery(settings.url, '_=' + Date.now())
1297
+
1126
1298
  var dataType = settings.dataType, hasPlaceholder = /=\?/.test(settings.url)
1127
1299
  if (dataType == 'jsonp' || hasPlaceholder) {
1128
1300
  if (!hasPlaceholder) settings.url = appendQuery(settings.url, 'callback=?')
1129
1301
  return $.ajaxJSONP(settings)
1130
1302
  }
1131
1303
 
1132
- if (!settings.url) settings.url = window.location.toString()
1133
- serializeData(settings)
1134
-
1135
1304
  var mime = settings.accepts[dataType],
1136
1305
  baseHeaders = { },
1137
1306
  protocol = /^([\w-]+:)\/\//.test(settings.url) ? RegExp.$1 : window.location.protocol,
1138
- xhr = $.ajaxSettings.xhr(), abortTimeout
1307
+ xhr = settings.xhr(), abortTimeout
1139
1308
 
1140
1309
  if (!settings.crossDomain) baseHeaders['X-Requested-With'] = 'XMLHttpRequest'
1141
1310
  if (mime) {
@@ -1143,12 +1312,13 @@ window.Zepto = Zepto
1143
1312
  if (mime.indexOf(',') > -1) mime = mime.split(',', 2)[0]
1144
1313
  xhr.overrideMimeType && xhr.overrideMimeType(mime)
1145
1314
  }
1146
- if (settings.contentType || (settings.data && settings.type.toUpperCase() != 'GET'))
1315
+ if (settings.contentType || (settings.contentType !== false && settings.data && settings.type.toUpperCase() != 'GET'))
1147
1316
  baseHeaders['Content-Type'] = (settings.contentType || 'application/x-www-form-urlencoded')
1148
1317
  settings.headers = $.extend(baseHeaders, settings.headers || {})
1149
1318
 
1150
1319
  xhr.onreadystatechange = function(){
1151
1320
  if (xhr.readyState == 4) {
1321
+ xhr.onreadystatechange = empty;
1152
1322
  clearTimeout(abortTimeout)
1153
1323
  var result, error = false
1154
1324
  if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304 || (xhr.status == 0 && protocol == 'file:')) {
@@ -1156,15 +1326,16 @@ window.Zepto = Zepto
1156
1326
  result = xhr.responseText
1157
1327
 
1158
1328
  try {
1329
+ // http://perfectionkills.com/global-eval-what-are-the-options/
1159
1330
  if (dataType == 'script') (1,eval)(result)
1160
1331
  else if (dataType == 'xml') result = xhr.responseXML
1161
- else if (dataType == 'json') result = blankRE.test(result) ? null : JSON.parse(result)
1332
+ else if (dataType == 'json') result = blankRE.test(result) ? null : $.parseJSON(result)
1162
1333
  } catch (e) { error = e }
1163
1334
 
1164
1335
  if (error) ajaxError(error, 'parsererror', xhr, settings)
1165
1336
  else ajaxSuccess(result, xhr, settings)
1166
1337
  } else {
1167
- ajaxError(null, 'error', xhr, settings)
1338
+ ajaxError(null, xhr.status ? 'error' : 'abort', xhr, settings)
1168
1339
  }
1169
1340
  }
1170
1341
  }
@@ -1190,40 +1361,60 @@ window.Zepto = Zepto
1190
1361
  return xhr
1191
1362
  }
1192
1363
 
1193
- $.get = function(url, success){ return $.ajax({ url: url, success: success }) }
1364
+ // handle optional data/success arguments
1365
+ function parseArguments(url, data, success, dataType) {
1366
+ var hasData = !$.isFunction(data)
1367
+ return {
1368
+ url: url,
1369
+ data: hasData ? data : undefined,
1370
+ success: !hasData ? data : $.isFunction(success) ? success : undefined,
1371
+ dataType: hasData ? dataType || success : success
1372
+ }
1373
+ }
1374
+
1375
+ $.get = function(url, data, success, dataType){
1376
+ return $.ajax(parseArguments.apply(null, arguments))
1377
+ }
1194
1378
 
1195
1379
  $.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 })
1380
+ var options = parseArguments.apply(null, arguments)
1381
+ options.type = 'POST'
1382
+ return $.ajax(options)
1198
1383
  }
1199
1384
 
1200
- $.getJSON = function(url, success){
1201
- return $.ajax({ url: url, success: success, dataType: 'json' })
1385
+ $.getJSON = function(url, data, success){
1386
+ var options = parseArguments.apply(null, arguments)
1387
+ options.dataType = 'json'
1388
+ return $.ajax(options)
1202
1389
  }
1203
1390
 
1204
- $.fn.load = function(url, success){
1391
+ $.fn.load = function(url, data, success){
1205
1392
  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){
1393
+ var self = this, parts = url.split(/\s/), selector,
1394
+ options = parseArguments(url, data, success),
1395
+ callback = options.success
1396
+ if (parts.length > 1) options.url = parts[0], selector = parts[1]
1397
+ options.success = function(response){
1209
1398
  self.html(selector ?
1210
- $(document.createElement('div')).html(response.replace(rscript, "")).find(selector).html()
1399
+ $('<div>').html(response.replace(rscript, "")).find(selector)
1211
1400
  : response)
1212
- success && success.call(self)
1213
- })
1401
+ callback && callback.apply(self, arguments)
1402
+ }
1403
+ $.ajax(options)
1214
1404
  return this
1215
1405
  }
1216
1406
 
1217
1407
  var escape = encodeURIComponent
1218
1408
 
1219
1409
  function serialize(params, obj, traditional, scope){
1220
- var array = $.isArray(obj)
1410
+ var type, array = $.isArray(obj)
1221
1411
  $.each(obj, function(key, value) {
1412
+ type = $.type(value)
1222
1413
  if (scope) key = traditional ? scope : scope + '[' + (array ? '' : key) + ']'
1223
1414
  // handle data in serializeArray() format
1224
1415
  if (!scope && array) params.add(value.name, value.value)
1225
1416
  // recurse into nested objects
1226
- else if (traditional ? $.isArray(value) : isObject(value))
1417
+ else if (type == "array" || (!traditional && type == "object"))
1227
1418
  serialize(params, value, traditional, key)
1228
1419
  else params.add(key, value)
1229
1420
  })
@@ -1233,9 +1424,10 @@ window.Zepto = Zepto
1233
1424
  var params = []
1234
1425
  params.add = function(k, v){ this.push(escape(k) + '=' + escape(v)) }
1235
1426
  serialize(params, obj, traditional)
1236
- return params.join('&').replace('%20', '+')
1427
+ return params.join('&').replace(/%20/g, '+')
1237
1428
  }
1238
1429
  })(Zepto)
1430
+
1239
1431
  ;(function ($) {
1240
1432
  $.fn.serializeArray = function () {
1241
1433
  var result = [], el
@@ -1272,84 +1464,102 @@ window.Zepto = Zepto
1272
1464
  }
1273
1465
 
1274
1466
  })(Zepto)
1275
- ;(function($){
1276
- var touch = {}, touchTimeout
1277
1467
 
1278
- function parentIfText(node){
1279
- return 'tagName' in node ? node : node.parentNode
1468
+ ;(function($, undefined){
1469
+ var prefix = '', eventPrefix, endEventName, endAnimationName,
1470
+ vendors = { Webkit: 'webkit', Moz: '', O: 'o', ms: 'MS' },
1471
+ document = window.document, testEl = document.createElement('div'),
1472
+ supportedTransforms = /^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,
1473
+ transform,
1474
+ transitionProperty, transitionDuration, transitionTiming,
1475
+ animationName, animationDuration, animationTiming,
1476
+ cssReset = {}
1477
+
1478
+ function dasherize(str) { return downcase(str.replace(/([a-z])([A-Z])/, '$1-$2')) }
1479
+ function downcase(str) { return str.toLowerCase() }
1480
+ function normalizeEvent(name) { return eventPrefix ? eventPrefix + name : downcase(name) }
1481
+
1482
+ $.each(vendors, function(vendor, event){
1483
+ if (testEl.style[vendor + 'TransitionProperty'] !== undefined) {
1484
+ prefix = '-' + downcase(vendor) + '-'
1485
+ eventPrefix = event
1486
+ return false
1487
+ }
1488
+ })
1489
+
1490
+ transform = prefix + 'transform'
1491
+ cssReset[transitionProperty = prefix + 'transition-property'] =
1492
+ cssReset[transitionDuration = prefix + 'transition-duration'] =
1493
+ cssReset[transitionTiming = prefix + 'transition-timing-function'] =
1494
+ cssReset[animationName = prefix + 'animation-name'] =
1495
+ cssReset[animationDuration = prefix + 'animation-duration'] =
1496
+ cssReset[animationTiming = prefix + 'animation-timing-function'] = ''
1497
+
1498
+ $.fx = {
1499
+ off: (eventPrefix === undefined && testEl.style.transitionProperty === undefined),
1500
+ speeds: { _default: 400, fast: 200, slow: 600 },
1501
+ cssPrefix: prefix,
1502
+ transitionEnd: normalizeEvent('TransitionEnd'),
1503
+ animationEnd: normalizeEvent('AnimationEnd')
1280
1504
  }
1281
1505
 
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')
1506
+ $.fn.animate = function(properties, duration, ease, callback){
1507
+ if ($.isPlainObject(duration))
1508
+ ease = duration.easing, callback = duration.complete, duration = duration.duration
1509
+ if (duration) duration = (typeof duration == 'number' ? duration :
1510
+ ($.fx.speeds[duration] || $.fx.speeds._default)) / 1000
1511
+ return this.anim(properties, duration, ease, callback)
1285
1512
  }
1286
1513
 
1287
- var longTapDelay = 750, longTapTimeout
1514
+ $.fn.anim = function(properties, duration, ease, callback){
1515
+ var key, cssValues = {}, cssProperties, transforms = '',
1516
+ that = this, wrappedCallback, endEvent = $.fx.transitionEnd
1517
+
1518
+ if (duration === undefined) duration = 0.4
1519
+ if ($.fx.off) duration = 0
1288
1520
 
1289
- function longTap(){
1290
- longTapTimeout = null
1291
- if (touch.last) {
1292
- touch.el.trigger('longTap')
1293
- touch = {}
1521
+ if (typeof properties == 'string') {
1522
+ // keyframe animation
1523
+ cssValues[animationName] = properties
1524
+ cssValues[animationDuration] = duration + 's'
1525
+ cssValues[animationTiming] = (ease || 'linear')
1526
+ endEvent = $.fx.animationEnd
1527
+ } else {
1528
+ cssProperties = []
1529
+ // CSS transitions
1530
+ for (key in properties)
1531
+ if (supportedTransforms.test(key)) transforms += key + '(' + properties[key] + ') '
1532
+ else cssValues[key] = properties[key], cssProperties.push(dasherize(key))
1533
+
1534
+ if (transforms) cssValues[transform] = transforms, cssProperties.push(transform)
1535
+ if (duration > 0 && typeof properties === 'object') {
1536
+ cssValues[transitionProperty] = cssProperties.join(', ')
1537
+ cssValues[transitionDuration] = duration + 's'
1538
+ cssValues[transitionTiming] = (ease || 'linear')
1539
+ }
1294
1540
  }
1295
- }
1296
1541
 
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)
1542
+ wrappedCallback = function(event){
1543
+ if (typeof event !== 'undefined') {
1544
+ if (event.target !== event.currentTarget) return // makes sure the event didn't bubble from "below"
1545
+ $(event.target).unbind(endEvent, wrappedCallback)
1343
1546
  }
1344
- }).bind('touchcancel', function(){
1345
- if (touchTimeout) clearTimeout(touchTimeout)
1346
- if (longTapTimeout) clearTimeout(longTapTimeout)
1347
- longTapTimeout = touchTimeout = null
1348
- touch = {}
1349
- })
1350
- })
1547
+ $(this).css(cssReset)
1548
+ callback && callback.call(this)
1549
+ }
1550
+ if (duration > 0) this.bind(endEvent, wrappedCallback)
1351
1551
 
1352
- ;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(m){
1353
- $.fn[m] = function(callback){ return this.bind(m, callback) }
1354
- })
1552
+ // trigger page reflow so new elements can animate
1553
+ this.size() && this.get(0).clientLeft
1554
+
1555
+ this.css(cssValues)
1556
+
1557
+ if (duration <= 0) setTimeout(function() {
1558
+ that.each(function(){ wrappedCallback.call(this) })
1559
+ }, 0)
1560
+
1561
+ return this
1562
+ }
1563
+
1564
+ testEl = null
1355
1565
  })(Zepto)