PageSourceSearch

https://beton.com.by/assets/templates/site/js/jquery.mobile-events.js

js beton.com.by collected 2026-10-04 23:26:06 UTC 25,292 bytes, 739 lines download raw bytes

1/*!
2 * jQuery Mobile Events
3 * by Ben Major (www.ben-major.co.uk)
4 *
5 * Copyright 2011, Ben Major
6 * Licensed under the MIT License:
7 * 
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 * 
26 */
27
28
29(function($) {
30	$.attrFn = $.attrFn || {};
31	
32	// navigator.userAgent.toLowerCase() isn't reliable for Chrome installs
33	// on mobile devices. As such, we will create a boolean isChromeDesktop
34	// The reason that we need to do this is because Chrome annoyingly
35	// purports support for touch events even if the underlying hardware
36	// does not!
37		
38	var isChromeDesktop = ((navigator.userAgent.toLowerCase().indexOf('chrome') > -1) && (
39						   (navigator.userAgent.toLowerCase().indexOf('windows') > -1) ||
40						   (navigator.userAgent.toLowerCase().indexOf('macintosh') > -1) ||
41						   (navigator.userAgent.toLowerCase().indexOf('linux') > -1)
42						  ));
43	
44	var settings = {
45		swipe_h_threshold 	: 50,
46		swipe_v_threshold 	: 50,
47		taphold_threshold 	: 750,
48		doubletap_int		: 500,
49		
50		touch_capable		: ('ontouchstart' in document.documentElement && !isChromeDesktop),
51		orientation_support	: ('orientation' in window && 'onorientationchange' in window),
52		
53		startevent		: ('ontouchstart' in document.documentElement && !isChromeDesktop) ? 'touchstart' : 'mousedown',
54		endevent		: ('ontouchstart' in document.documentElement && !isChromeDesktop) ? 'touchend' : 'mouseup',
55		moveevent		: ('ontouchstart' in document.documentElement && !isChromeDesktop) ? 'touchmove' : 'mousemove',
56		tapevent		: ('ontouchstart' in document.documentElement && !isChromeDesktop) ? 'tap' : 'click',
57		scrollevent		: ('ontouchstart' in document.documentElement && !isChromeDesktop) ? 'touchmove' : 'scroll',
58		
59		hold_timer		: null,
60		tap_timer		: null
61	};
62	
63	// Add Event shortcuts:
64	$.each(('tapstart tapend tap singletap doubletap taphold swipe swipeup swiperight swipedown swipeleft swipeend scrollstart scrollend orientationchange').split(' '), function(i, name) {
65		$.fn[name] = function(fn)
66		{
67			return fn ? this.bind(name, fn) : this.trigger(name);
68		};
69	
70		$.attrFn[name] = true;
71	});
72	
73	// tapstart Event:
74	$.event.special.tapstart = {
75		setup: function() {
76			var thisObject = this,
77			    $this = $(thisObject);
78			
79			$this.bind(settings.startevent, function(e) {
80				if(e.which && e.which !== 1)
81				{
82					return false;
83				}
84				else
85				{
86					// Touch event data:
87					var origEvent = e.originalEvent;
88					var touchData = {
89						'position': {
90							'x': (settings.touch_capable) ? origEvent.touches[0].screenX : e.screenX,
91							'y': (settings.touch_capable) ? origEvent.touches[0].screenY : e.screenY,
92						},
93						'offset': {
94							'x': (settings.touch_capable) ? origEvent.touches[0].pageX - origEvent.touches[0].target.offsetLeft : e.offsetX,
95							'y': (settings.touch_capable) ? origEvent.touches[0].pageY - origEvent.touches[0].target.offsetTop : e.offsetY,
96						},
97						'time': new Date().getTime(),
98						'target': e.target
99					};
100					
101					triggerCustomEvent(thisObject, 'tapstart', e, touchData);
102					return true;
103				}
104			});
105		}
106	};
107	
108	// tapend Event:
109	$.event.special.tapend = {
110		setup: function() {
111			var thisObject = this,
112			    $this = $(thisObject);
113			
114			$this.bind(settings.endevent, function(e) {
115				// Touch event data:
116				var origEvent = e.originalEvent;
117				var touchData = {
118					'position': {
119						'x': (settings.touch_capable) ? origEvent.changedTouches[0].screenX : e.screenX,
120						'y': (settings.touch_capable) ? origEvent.changedTouches[0].screenY : e.screenY
121					},
122					'offset': {
123						'x': (settings.touch_capable) ? origEvent.changedTouches[0].pageX - origEvent.changedTouches[0].target.offsetLeft : e.offsetX,
124						'y': (settings.touch_capable) ? origEvent.changedTouches[0].pageY - origEvent.changedTouches[0].target.offsetTop : e.offsetY
125					},
126					'time': new Date().getTime(),
127					'target': e.target
128				};
129				triggerCustomEvent(thisObject, 'tapend', e, touchData);
130				return true;
131			});
132		}
133	};
134	
135	// taphold Event:
136	$.event.special.taphold = {
137		setup: function() {
138			var thisObject = this,
139			    $this = $(thisObject),
140				origTarget,
141				timer,
142				start_pos = { x : 0, y : 0 };
143			
144			$this.bind(settings.startevent, function(e) {
145				if(e.which && e.which !== 1)
146				{
147					return false;
148				}
149				else
150				{
151					$this.data('tapheld', false);
152					origTarget = e.target;
153					
154					var origEvent = e.originalEvent;
155					var start_time = new Date().getTime(),
156					startPosition = {
157						'x': (settings.touch_capable) ? origEvent.touches[0].screenX : e.screenX,
158						'y': (settings.touch_capable) ? origEvent.touches[0].screenY : e.screenY
159					},
160					startOffset = {
161						'x': (settings.touch_capable) ? origEvent.touches[0].pageX - origEvent.touches[0].target.offsetLeft : e.offsetX,
162						'y': (settings.touch_capable) ? origEvent.touches[0].pageY - origEvent.touches[0].target.offsetTop : e.offsetY
163					};
164					
165					start_pos.x = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageX : e.pageX;
166					start_pos.y = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageY : e.pageY;
167					
168					settings.hold_timer = window.setTimeout(function() {
169						
170						var end_x = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageX : e.pageX,
171							end_y = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageY : e.pageY;
172							
173						if(e.target == origTarget && (start_pos.x == end_x && start_pos.y == end_y))
174						{
175							$this.data('tapheld', true);
176							
177							var end_time = new Date().getTime(),
178					         endPosition = {
179								'x': (settings.touch_capable) ? origEvent.touches[0].screenX : e.screenX,
180								'y': (settings.touch_capable) ? origEvent.touches[0].screenY : e.screenY
181							},
182					        endOffset = {
183								'x': (settings.touch_capable) ? origEvent.touches[0].pageX - origEvent.touches[0].target.offsetLeft : e.offsetX,
184								'y': (settings.touch_capable) ? origEvent.touches[0].pageY - origEvent.touches[0].target.offsetTop : e.offsetY
185							};
186							    duration = end_time - start_time;
187							
188							// Build the touch data:
189							var touchData = {
190								'startTime': start_time,
191								  'endTime': end_time,
192							'startPosition': startPosition,
193							  'startOffset': startOffset,
194							  'endPosition': endPosition,
195							    'endOffset': endOffset,
196							   'duration': duration,
197							       'target': e.target
198							}
199							
200							triggerCustomEvent(thisObject, 'taphold', e, touchData);
201						}
202					}, settings.taphold_threshold);
203					
204					return true;
205				}
206			}).bind(settings.endevent, function() {
207				$this.data('tapheld', false);
208				window.clearTimeout(settings.hold_timer);
209			});
210		}
211	};
212	
213	// doubletap Event:
214	$.event.special.doubletap = {
215		setup: function() {
216			var thisObject = this,
217			    $this = $(thisObject),
218				origTarget,
219				action,
220				firstTap;
221			
222			$this.bind(settings.startevent, function(e) {
223				if(e.which && e.which !== 1)
224				{
225					return false;
226				}
227				else
228				{
229					$this.data('doubletapped', false);
230					origTarget = e.target;
231					var origEvent = e.originalEvent;
232					firstTap = {
233						'position': {
234						    'x': (settings.touch_capable) ? origEvent.touches[0].screenX : e.screenX,
235							'y': (settings.touch_capable) ? origEvent.touches[0].screenY : e.screenY
236						},
237						'offset': {
238							'x': (settings.touch_capable) ? origEvent.touches[0].pageX - origEvent.touches[0].target.offsetLeft : e.offsetX,
239							'y': (settings.touch_capable) ? origEvent.touches[0].pageY - origEvent.touches[0].target.offsetTop : e.offsetY
240						},
241						'time': new Date().getTime(),
242						'target': e.target
243					};
244					
245					return true;
246				}
247			}).bind(settings.endevent, function(e) {
248				var now = new Date().getTime();
249				var lastTouch = $this.data('lastTouch') || now + 1;
250				var delta = now - lastTouch;
251				window.clearTimeout(action);
252				
253				if(delta < settings.doubletap_int && delta > 0 && (e.target == origTarget) && delta > 100)
254				{
255					$this.data('doubletapped', true);
256					window.clearTimeout(settings.tap_timer);
257					
258					// Now get the current event:
259					var lastTap = {
260						'position': {
261						    'x': (settings.touch_capable) ? origEvent.touches[0].screenX : e.screenX,
262							'y': (settings.touch_capable) ? origEvent.touches[0].screenY : e.screenY
263						},
264						'offset': {
265							'x': (settings.touch_capable) ? origEvent.touches[0].pageX - origEvent.touches[0].target.offsetLeft : e.offsetX,
266							'y': (settings.touch_capable) ? origEvent.touches[0].pageY - origEvent.touches[0].target.offsetTop : e.offsetY
267						},
268						'time': new Date().getTime(),
269						'target': e.target
270					}
271					
272					var touchData = {
273						 'firstTap': firstTap,
274						'secondTap': lastTap,
275						 'interval': lastTap.time - firstTap.time
276					};
277					
278					triggerCustomEvent(thisObject, 'doubletap', e, touchData);
279				}
280				else
281				{
282					$this.data('lastTouch', now);
283					action = window.setTimeout(function(e){ window.clearTimeout(action); }, settings.doubletap_int, [e]);
284				}
285				$this.data('lastTouch', now);
286			});
287		}
288	};
289	
290	// singletap Event:
291	// This is used in conjuction with doubletap when both events are needed on the same element
292	$.event.special.singletap = {
293		setup: function() {
294			var thisObject = this,
295			    $this = $(thisObject),
296				origTarget = null,
297				 startTime = null,
298				 start_pos = { x: 0, y: 0 };
299				
300			$this.bind(settings.startevent, function(e) {
301				if(e.which && e.which !== 1)
302				{
303					return false;
304				}
305				else
306				{
307					startTime = new Date().getTime();
308					origTarget = e.target;
309					
310					// Get the start x and y position:
311					start_pos.x = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageX : e.pageX;
312					start_pos.y = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageY : e.pageY;
313					return true;
314				}
315			}).bind(settings.endevent, function(e) {
316				
317				if(e.target == origTarget)
318				{
319					// Get the end point:
320					end_pos_x = (e.originalEvent.changedTouches) ? e.originalEvent.changedTouches[0].pageX : e.pageX;
321					end_pos_y = (e.originalEvent.changedTouches) ? e.originalEvent.changedTouches[0].pageY : e.pageY;
322					
323					settings.tap_timer = window.setTimeout(function() {	
324						if(!$this.data('doubletapped') && !$this.data('tapheld') && (start_pos.x == end_pos_x) && (start_pos.y == end_pos_y))
325						{
326							var origEvent = e.originalEvent;
327							var touchData = {
328								'position': {
329									'x': (settings.touch_capable) ? origEvent.changedTouches[0].screenX : e.screenX,
330									'y': (settings.touch_capable) ? origEvent.changedTouches[0].screenY : e.screenY,
331								},
332								'offset': {
333									'x': (settings.touch_capable) ? origEvent.changedTouches[0].pageX - origEvent.changedTouches[0].target.offsetLeft : e.offsetX,
334									'y': (settings.touch_capable) ? origEvent.changedTouches[0].pageY - origEvent.changedTouches[0].target.offsetTop : e.offsetY,
335								},
336								'time': new Date().getTime(),
337								'target': e.target
338							};
339							triggerCustomEvent(thisObject, 'singletap', e, touchData);
340						}
341					}, settings.doubletap_int);
342				}
343			});
344		}
345	};
346	
347	// tap Event:
348	$.event.special.tap = {
349		setup: function() {
350			var thisObject = this,
351				$this = $(thisObject),
352			    started = false,
353				origTarget = null,
354				start_time,
355				start_pos = { x : 0, y : 0 };
356			
357			$this.bind(settings.startevent, function(e) {
358				if(e.which && e.which !== 1)
359				{
360					return false;
361				}
362				else
363				{
364					started = true;
365					start_pos.x = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageX : e.pageX;
366					start_pos.y = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageY : e.pageY;
367					start_time = new Date().getTime();
368					origTarget = e.target;
369					return true;
370				}
371			}).bind(settings.endevent, function(e) {
372				// Only trigger if they've started, and the target matches:
373				var end_x = (e.originalEvent.targetTouches) ? e.originalEvent.changedTouches[0].pageX : e.pageX,
374					end_y = (e.originalEvent.targetTouches) ? e.originalEvent.changedTouches[0].pageY : e.pageY;
375				
376				if(origTarget == e.target && started && ((new Date().getTime() - start_time) < settings.taphold_threshold) && (start_pos.x == end_x && start_pos.y == end_y))
377				{
378					var origEvent = e.originalEvent;
379					var touchData = {
380						'position': {
381							'x': (settings.touch_capable) ? origEvent.changedTouches[0].screenX : e.screenX,
382							'y': (settings.touch_capable) ? origEvent.changedTouches[0].screenY : e.screenY,
383						},
384						'offset': {
385							'x': (settings.touch_capable) ? origEvent.changedTouches[0].pageX - origEvent.changedTouches[0].target.offsetLeft : e.offsetX,
386							'y': (settings.touch_capable) ? origEvent.changedTouches[0].pageY - origEvent.changedTouches[0].target.offsetTop : e.offsetY,
387						},
388						'time': new Date().getTime(),
389						'target': e.target
390					};
391					
392					triggerCustomEvent(thisObject, 'tap', e, touchData);
393				}
394			});
395		}
396	};
397	
398	// swipe Event (also handles swipeup, swiperight, swipedown and swipeleft):
399	$.event.special.swipe = {
400		setup: function() {
401			var thisObject = this,
402			    $this = $(thisObject),
403				started = false,
404			  hasSwiped =  false,
405				originalCoord = { x: 0, y: 0 },
406			    finalCoord    = { x: 0, y: 0 },
407				startEvnt;
408	
409			// Screen touched, store the original coordinate
410			function touchStart(e)
411			{
412				originalCoord.x = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageX : e.pageX;
413				originalCoord.y = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageY : e.pageY;
414				finalCoord.x = originalCoord.x;
415				finalCoord.y = originalCoord.y;
416				started = true;
417				var origEvent = e.originalEvent;
418				// Read event data into our startEvt:
419				startEvnt = {
420					'position': {
421						'x': (settings.touch_capable) ? origEvent.touches[0].screenX : e.screenX,
422						'y': (settings.touch_capable) ? origEvent.touches[0].screenY : e.screenY,
423					},
424					'offset': {
425						'x': (settings.touch_capable) ? origEvent.touches[0].pageX - origEvent.touches[0].target.offsetLeft : e.offsetX,
426						'y': (settings.touch_capable) ? origEvent.touches[0].pageY - origEvent.touches[0].target.offsetTop : e.offsetY,
427					},
428					'time': new Date().getTime(),
429					'target': e.target
430				};
431				
432				// For some reason, we need to add a 100ms pause in order to trigger swiping
433				// on Playbooks:
434				var dt = new Date();
435				while ((new Date()) - dt < 100) { }				
436			}
437			
438			// Store coordinates as finger is swiping
439			function touchMove(e)
440			{
441				finalCoord.x = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageX : e.pageX;
442				finalCoord.y = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageY : e.pageY;
443				window.clearTimeout(settings.hold_timer);
444				
445				var swipedir;
446				
447				// We need to check if the element to which the event was bound contains a data-xthreshold | data-vthreshold:
448				var ele_x_threshold = $this.attr('data-xthreshold'),
449				    ele_y_threshold = $this.attr('data-ythreshold'),
450					    h_threshold = (typeof ele_x_threshold !== 'undefined' && ele_x_threshold !== false && parseInt(ele_x_threshold)) ? parseInt(ele_x_threshold) : settings.swipe_h_threshold,
451						v_threshold = (typeof ele_y_threshold !== 'undefined' && ele_y_threshold !== false && parseInt(ele_y_threshold)) ? parseInt(ele_y_threshold) : settings.swipe_v_threshold;
452				
453				
454				if(originalCoord.y > finalCoord.y && (originalCoord.y - finalCoord.y > v_threshold)) { swipedir = 'swipeup'; }
455				if(originalCoord.x < finalCoord.x && (finalCoord.x - originalCoord.x > h_threshold)) { swipedir = 'swiperight'; }
456				if(originalCoord.y < finalCoord.y && (finalCoord.y - originalCoord.y > v_threshold)) { swipedir = 'swipedown'; }
457				if(originalCoord.x > finalCoord.x && (originalCoord.x - finalCoord.x > h_threshold)) { swipedir = 'swipeleft'; }
458				if(swipedir != undefined && started)
459				{
460					originalCoord.x = 0;
461					originalCoord.y = 0;
462					finalCoord.x = 0;
463					finalCoord.y = 0;
464					started = false;
465					
466					// Read event data into our endEvnt:
467					var origEvent = e.originalEvent;
468					endEvnt = {
469						'position': {
470							'x': (settings.touch_capable) ? origEvent.touches[0].screenX : e.screenX,
471							'y': (settings.touch_capable) ? origEvent.touches[0].screenY : e.screenY,
472						},
473						'offset': {
474							'x': (settings.touch_capable) ? origEvent.touches[0].pageX - origEvent.touches[0].target.offsetLeft : e.offsetX,
475							'y': (settings.touch_capable) ? origEvent.touches[0].pageY - origEvent.touches[0].target.offsetTop : e.offsetY,
476						},
477						'time': new Date().getTime(),
478						'target': e.target
479					};
480					
481					// Calculate the swipe amount (normalized):
482					var xAmount = Math.abs(startEvnt.position.x - endEvnt.position.x),
483					    yAmount = Math.abs(startEvnt.position.y - endEvnt.position.y);
484					
485					var touchData = {
486						'startEvnt': startEvnt,
487						  'endEvnt': endEvnt,
488						'direction': swipedir.replace('swipe', ''),
489						  'xAmount': xAmount,
490						  'yAmount': yAmount,
491						 'duration': endEvnt.time - startEvnt.time 
492					}
493					hasSwiped = true;
494					$this.trigger('swipe', touchData).trigger(swipedir, touchData);
495				}
496			}
497			
498			function touchEnd(e)
499			{
500				if(hasSwiped)
501				{
502					// We need to check if the element to which the event was bound contains a data-xthreshold | data-vthreshold:
503					var ele_x_threshold = $this.attr('data-xthreshold'),
504						ele_y_threshold = $this.attr('data-ythreshold'),
505							h_threshold = (typeof ele_x_threshold !== 'undefined' && ele_x_threshold !== false && parseInt(ele_x_threshold)) ? parseInt(ele_x_threshold) : settings.swipe_h_threshold,
506							v_threshold = (typeof ele_y_threshold !== 'undefined' && ele_y_threshold !== false && parseInt(ele_y_threshold)) ? parseInt(ele_y_threshold) : settings.swipe_v_threshold;
507					
508					var origEvent = e.originalEvent;
509					endEvnt = {
510						'position': {
511							'x': (settings.touch_capable) ? origEvent.changedTouches[0].screenX : e.screenX,
512							'y': (settings.touch_capable) ? origEvent.changedTouches[0].screenY : e.screenY,
513						},
514						'offset': {
515							'x': (settings.touch_capable) ? origEvent.changedTouches[0].pageX - origEvent.changedTouches[0].target.offsetLeft : e.offsetX,
516							'y': (settings.touch_capable) ? origEvent.changedTouches[0].pageY - origEvent.changedTouches[0].target.offsetTop : e.offsetY,
517						},
518						'time': new Date().getTime(),
519						'target': e.target
520					};
521					
522					// Read event data into our endEvnt:
523					if(startEvnt.position.y > endEvnt.position.y && (startEvnt.position.y - endEvnt.position.y > v_threshold)) { swipedir = 'swipeup'; }
524					if(startEvnt.position.x < endEvnt.position.x && (endEvnt.position.x - startEvnt.position.x > h_threshold)) { swipedir = 'swiperight'; }
525					if(startEvnt.position.y < endEvnt.position.y && (endEvnt.position.y - startEvnt.position.y > v_threshold)) { swipedir = 'swipedown'; }
526					if(startEvnt.position.x > endEvnt.position.x && (startEvnt.position.x - endEvnt.position.x > h_threshold)) { swipedir = 'swipeleft'; }
527						
528					// Calculate the swipe amount (normalized):
529					var xAmount = Math.abs(startEvnt.position.x - endEvnt.position.x),
530						yAmount = Math.abs(startEvnt.position.y - endEvnt.position.y);
531					
532					var touchData = {
533						'startEvnt': startEvnt,
534						  'endEvnt': endEvnt,
535						'direction': swipedir.replace('swipe', ''),
536						  'xAmount': xAmount,
537						  'yAmount': yAmount,
538						 'duration': endEvnt.time - startEvnt.time 
539					}
540					$this.trigger('swipeend', touchData);
541				}
542				
543				started = false;
544				hasSwiped = false;
545			}
546			
547			$this.bind(settings.startevent, touchStart);
548			$this.bind(settings.moveevent, touchMove);
549			$this.bind(settings.endevent, touchEnd);
550		}
551	};
552	
553	// scrollstart Event (also handles scrollend):
554	$.event.special.scrollstart = {
555		setup: function() {
556			var thisObject = this,
557				$this = $(thisObject),
558				scrolling,
559				timer;
560
561			function trigger(event, state)
562			{
563				scrolling = state;
564				triggerCustomEvent(thisObject, scrolling ? 'scrollstart' : 'scrollend', event);
565			}
566
567			// iPhone triggers scroll after a small delay; use touchmove instead
568			$this.bind(settings.scrollevent, function(event) {
569				if(!scrolling)
570				{
571					trigger(event, true);
572				}
573	
574				clearTimeout(timer);
575				timer = setTimeout(function() { trigger(event, false); }, 50);
576			});
577		}
578	};
579	
580	// This is the orientation change (largely borrowed from jQuery Mobile):
581	var win = $(window),
582		special_event,
583		get_orientation,
584		last_orientation,
585		initial_orientation_is_landscape,
586		initial_orientation_is_default,
587		portrait_map = { '0': true, '180': true };
588
589	if(settings.orientation_support)
590	{
591		var ww = window.innerWidth || $(window).width(),
592			wh = window.innerHeight || $(window).height(),
593			landscape_threshold = 50;
594
595		initial_orientation_is_landscape = ww > wh && (ww - wh) > landscape_threshold;
596		initial_orientation_is_default = portrait_map[window.orientation];
597
598		if((initial_orientation_is_landscape && initial_orientation_is_default) || (!initial_orientation_is_landscape && !initial_orientation_is_default))
599		{
600			portrait_map = { '-90': true, '90': true };
601		}
602	}
603
604	$.event.special.orientationchange = special_event = {
605		setup: function() {
606			// If the event is supported natively, return false so that jQuery
607			// will bind to the event using DOM methods.
608			if(settings.orientation_support)
609			{
610				return false;
611			}
612
613			// Get the current orientation to avoid initial double-triggering.
614			last_orientation = get_orientation();
615
616			win.bind('throttledresize', handler);
617			return true;
618		},
619		teardown: function()
620		{
621			if (settings.orientation_support)
622			{
623				return false;
624			}
625
626			win.unbind('throttledresize', handler);
627			return true;
628		},
629		add: function(handleObj)
630		{
631			// Save a reference to the bound event handler.
632			var old_handler = handleObj.handler;
633
634			handleObj.handler = function(event)
635			{
636				event.orientation = get_orientation();
637				return old_handler.apply(this, arguments);
638			};
639		}
640	};
641
642	// If the event is not supported natively, this handler will be bound to
643	// the window resize event to simulate the orientationchange event.
644	function handler()
645	{
646		// Get the current orientation.
647		var orientation = get_orientation();
648
649		if(orientation !== last_orientation)
650		{
651			// The orientation has changed, so trigger the orientationchange event.
652			last_orientation = orientation;
653			win.trigger( "orientationchange" );
654		}
655	}
656
657	$.event.special.orientationchange.orientation = get_orientation = function() {
658		var isPortrait = true,
659		    elem = document.documentElement;
660
661		if(settings.orientation_support)
662		{
663			isPortrait = portrait_map[window.orientation];
664		}
665		else
666		{
667			isPortrait = elem && elem.clientWidth / elem.clientHeight < 1.1;
668		}
669
670		return isPortrait ? 'portrait' : 'landscape';
671	};
672	
673	// throttle Handler:
674	$.event.special.throttledresize = {
675		setup: function()
676		{
677			$(this).bind('resize', throttle_handler);
678		},
679		teardown: function()
680		{
681			$(this).unbind('resize', throttle_handler);
682		}
683	};
684
685	var throttle = 250,
686		throttle_handler = function()
687		{
688			curr = (new Date()).getTime();
689			diff = curr - lastCall;
690
691			if(diff >= throttle)
692			{
693				lastCall = curr;
694				$(this).trigger('throttledresize');
695
696			}
697			else
698			{
699				if(heldCall)
700				{
701					window.clearTimeout(heldCall);
702				}
703
704				// Promise a held call will still execute
705				heldCall = window.setTimeout(handler, throttle - diff);
706			}
707		},
708		lastCall = 0,
709		heldCall,
710		curr,
711		diff;
712	
713	// Trigger a custom event:
714	function triggerCustomEvent( obj, eventType, event, touchData ) {
715		var originalType = event.type;
716		event.type = eventType;
717		
718		$.event.dispatch.call( obj, event, touchData );
719		event.type = originalType;
720	}
721	
722	// Correctly bind anything we've overloaded:
723	$.each({
724		scrollend: 'scrollstart',
725		swipeup: 'swipe',
726		swiperight: 'swipe',
727		swipedown: 'swipe',
728		swipeleft: 'swipe',
729		swipeend: 'swipe',
730	}, function(e, srcE, touchData) {
731		$.event.special[e] =
732		{
733			setup: function() {
734				$(this).bind(srcE, $.noop);
735			}
736		};
737	});
738	
739}) (jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.