PageSourceSearch

https://blog.viszony.hu/assets/js/common/jquery.mobile_events.js?_=d6

js viszony.hu collected 2026-09-24 12:59:49 UTC 39,172 bytes, 875 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(function ($) {
28    $.attrFn = $.attrFn || {};
29
30    // navigator.userAgent.toLowerCase() isn't reliable for Chrome installs
31    // on mobile devices. As such, we will create a boolean isChromeDesktop
32    // The reason that we need to do this is because Chrome annoyingly
33    // purports support for touch events even if the underlying hardware
34    // does not!
35    var agent = navigator.userAgent.toLowerCase(),
36        isChromeDesktop = (agent.indexOf('chrome') > -1 && ((agent.indexOf('windows') > -1) || (agent.indexOf('macintosh') > -1) || (agent.indexOf('linux') > -1)) && agent.indexOf('mobile') < 0 && agent.indexOf('android') < 0),
37
38        settings = {
39            tap_pixel_range: 5,
40            swipe_h_threshold: 50,
41            swipe_v_threshold: 50,
42            taphold_threshold: 750,
43            doubletap_int: 500,
44
45            touch_capable: ('ontouchstart' in window && !isChromeDesktop),
46            orientation_support: ('orientation' in window && 'onorientationchange' in window),
47
48            startevent: ('ontouchstart' in window && !isChromeDesktop) ? 'touchstart' : 'mousedown',
49            endevent: ('ontouchstart' in window && !isChromeDesktop) ? 'touchend' : 'mouseup',
50            moveevent: ('ontouchstart' in window && !isChromeDesktop) ? 'touchmove' : 'mousemove',
51            tapevent: ('ontouchstart' in window && !isChromeDesktop) ? 'tap' : 'click',
52            scrollevent: ('ontouchstart' in window && !isChromeDesktop) ? 'touchmove' : 'scroll',
53
54            hold_timer: null,
55            tap_timer: null
56        };
57
58    // Convenience functions:
59    $.isTouchCapable = function() { return settings.touch_capable; };
60    $.getStartEvent = function() { return settings.startevent; };
61    $.getEndEvent = function() { return settings.endevent; };
62    $.getMoveEvent = function() { return settings.moveevent; };
63    $.getTapEvent = function() { return settings.tapevent; };
64    $.getScrollEvent = function() { return settings.scrollevent; };
65
66    // Add Event shortcuts:
67    $.each(['tapstart', 'tapend', 'tapmove', 'tap', 'tap2', 'tap3', 'tap4', 'singletap', 'doubletap', 'taphold', 'swipe', 'swipeup', 'swiperight', 'swipedown', 'swipeleft', 'swipeend', 'scrollstart', 'scrollend', 'orientationchange'], function (i, name) {
68        $.fn[name] = function (fn) {
69            return fn ? this.on(name, fn) : this.trigger(name);
70        };
71
72        $.attrFn[name] = true;
73    });
74
75    // tapstart Event:
76    $.event.special.tapstart = {
77        setup: function () {
78            var thisObject = this,
79                $this = $(thisObject);
80
81            $this.on(settings.startevent, function (e) {
82                $this.data('callee', arguments.callee);
83                if (e.which && e.which !== 1) {
84                    return false;
85                }
86
87                var origEvent = e.originalEvent,
88                    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': Date.now(),
98                        'target': e.target
99                    };
100
101                triggerCustomEvent(thisObject, 'tapstart', e, touchData);
102                return true;
103            });
104        },
105
106        remove: function () {
107            $(this).off(settings.startevent, $(this).data.callee);
108        }
109    };
110
111    // tapmove Event:
112    $.event.special.tapmove = {
113        setup: function() {
114            var thisObject = this,
115                $this = $(thisObject);
116
117            $this.on(settings.moveevent, function(e) {
118                $this.data('callee', arguments.callee);
119
120                var origEvent = e.originalEvent,
121                    touchData = {
122                        'position': {
123                            'x': ((settings.touch_capable) ? origEvent.touches[0].screenX : e.screenX),
124                            'y': (settings.touch_capable) ? origEvent.touches[0].screenY : e.screenY
125                        },
126                        'offset': {
127                            'x': (settings.touch_capable) ? origEvent.touches[0].pageX - origEvent.touches[0].target.offsetLeft : e.offsetX,
128                            'y': (settings.touch_capable) ? origEvent.touches[0].pageY - origEvent.touches[0].target.offsetTop : e.offsetY
129                        },
130                        'time': Date.now(),
131                        'target': e.target
132                    };
133
134                triggerCustomEvent(thisObject, 'tapmove', e, touchData);
135                return true;
136            });
137        },
138        remove: function() {
139            $(this).off(settings.moveevent, $(this).data.callee);
140        }
141    }
142
143    // tapend Event:
144    $.event.special.tapend = {
145        setup: function () {
146            var thisObject = this,
147                $this = $(thisObject);
148
149            $this.on(settings.endevent, function (e) {
150                // Touch event data:
151                $this.data('callee', arguments.callee);
152
153                var origEvent = e.originalEvent;
154                var touchData = {
155                    'position': {
156                        'x': (settings.touch_capable) ? origEvent.changedTouches[0].screenX : e.screenX,
157                        'y': (settings.touch_capable) ? origEvent.changedTouches[0].screenY : e.screenY
158                    },
159                    'offset': {
160                        'x': (settings.touch_capable) ? origEvent.changedTouches[0].pageX - origEvent.changedTouches[0].target.offsetLeft : e.offsetX,
161                        'y': (settings.touch_capable) ? origEvent.changedTouches[0].pageY - origEvent.changedTouches[0].target.offsetTop : e.offsetY
162                    },
163                    'time': Date.now(),
164                    'target': e.target
165                };
166                triggerCustomEvent(thisObject, 'tapend', e, touchData);
167                return true;
168            });
169        },
170        remove: function () {
171            $(this).off(settings.endevent, $(this).data.callee);
172        }
173    };
174
175    // taphold Event:
176    $.event.special.taphold = {
177        setup: function () {
178            var thisObject = this,
179                $this = $(thisObject),
180                origTarget,
181                timer,
182                start_pos = {
183                    x: 0,
184                    y: 0
185                },
186                end_x = 0,
187                end_y = 0;
188
189            $this.on(settings.startevent, function (e) {
190                if (e.which && e.which !== 1) {
191                    return false;
192                } else {
193                    $this.data('tapheld', false);
194                    origTarget = e.target;
195
196                    var origEvent = e.originalEvent;
197                    var start_time = Date.now(),
198                        startPosition = {
199                            'x': (settings.touch_capable) ? origEvent.touches[0].screenX : e.screenX,
200                            'y': (settings.touch_capable) ? origEvent.touches[0].screenY : e.screenY
201                        },
202                        startOffset = {
203                            'x': (settings.touch_capable) ? origEvent.touches[0].pageX - origEvent.touches[0].target.offsetLeft : e.offsetX,
204                            'y': (settings.touch_capable) ? origEvent.touches[0].pageY - origEvent.touches[0].target.offsetTop : e.offsetY
205                        };
206
207                    start_pos.x = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageX : e.pageX;
208                    start_pos.y = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageY : e.pageY;
209
210                    end_x = start_pos.x;
211                    end_y = start_pos.y;
212
213                    settings.hold_timer = window.setTimeout(function () {
214
215                        var diff_x = (start_pos.x - end_x),
216                            diff_y = (start_pos.y - end_y);
217
218                        if (e.target == origTarget && ((start_pos.x == end_x && start_pos.y == end_y) || (diff_x >= -(settings.tap_pixel_range) && diff_x <= settings.tap_pixel_range && diff_y >= -(settings.tap_pixel_range) && diff_y <= settings.tap_pixel_range))) {
219                            $this.data('tapheld', true);
220
221                            var end_time = Date.now(),
222                                endPosition = {
223                                    'x': (settings.touch_capable) ? origEvent.touches[0].screenX : e.screenX,
224                                    'y': (settings.touch_capable) ? origEvent.touches[0].screenY : e.screenY
225                                },
226                                endOffset = {
227                                    'x': (settings.touch_capable) ? origEvent.touches[0].pageX - origEvent.touches[0].target.offsetLeft : e.offsetX,
228                                    'y': (settings.touch_capable) ? origEvent.touches[0].pageY - origEvent.touches[0].target.offsetTop : e.offsetY
229                                };
230                            duration = end_time - start_time;
231
232                            // Build the touch data:
233                            var touchData = {
234                                'startTime': start_time,
235                                'endTime': end_time,
236                                'startPosition': startPosition,
237                                'startOffset': startOffset,
238                                'endPosition': endPosition,
239                                'endOffset': endOffset,
240                                'duration': duration,
241                                'target': e.target
242                            }
243                            $this.data('callee1', arguments.callee);
244                            triggerCustomEvent(thisObject, 'taphold', e, touchData);
245                        }
246                    }, settings.taphold_threshold);
247
248                    return true;
249                }
250            }).on(settings.endevent, function () {
251                $this.data('callee2', arguments.callee);
252                $this.data('tapheld', false);
253                window.clearTimeout(settings.hold_timer);
254            })
255                .on(settings.moveevent, function (e) {
256                    $this.data('callee3', arguments.callee);
257
258                    end_x = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageX : e.pageX;
259                    end_y = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageY : e.pageY;
260                });
261        },
262
263        remove: function () {
264            $(this).off(settings.startevent, $(this).data.callee1).off(settings.endevent, $(this).data.callee2).off(settings.moveevent, $(this).data.callee3);
265        }
266    };
267
268    // doubletap Event:
269    $.event.special.doubletap = {
270        setup: function () {
271            var thisObject = this,
272                $this = $(thisObject),
273                origTarget,
274                action,
275                firstTap,
276                origEvent,
277                cooloff,
278                cooling = false;
279
280            $this.on(settings.startevent, function (e) {
281                if (e.which && e.which !== 1) {
282                    return false;
283                }
284                $this.data('doubletapped', false);
285                origTarget = e.target;
286                $this.data('callee1', arguments.callee);
287
288                origEvent = e.originalEvent;
289                firstTap = {
290                    'position': {
291                        'x': (settings.touch_capable) ? origEvent.touches[0].screenX : e.screenX,
292                        'y': (settings.touch_capable) ? origEvent.touches[0].screenY : e.screenY
293                    },
294                    'offset': {
295                        'x': (settings.touch_capable) ? origEvent.touches[0].pageX - origEvent.touches[0].target.offsetLeft : e.offsetX,
296                        'y': (settings.touch_capable) ? origEvent.touches[0].pageY - origEvent.touches[0].target.offsetTop : e.offsetY
297                    },
298                    'time': Date.now(),
299                    'target': e.target
300                };
301
302                return true;
303            }).on(settings.endevent, function (e) {
304
305                var now = Date.now();
306                var lastTouch = $this.data('lastTouch') || now + 1;
307                var delta = now - lastTouch;
308                window.clearTimeout(action);
309                $this.data('callee2', arguments.callee);
310
311                if (delta < settings.doubletap_int && (e.target == origTarget) && delta > 100) {
312                    $this.data('doubletapped', true);
313                    window.clearTimeout(settings.tap_timer);
314
315                    // Now get the current event:
316                    var lastTap = {
317                        'position': {
318                            'x': (settings.touch_capable) ? e.originalEvent.changedTouches[0].screenX : e.screenX,
319                            'y': (settings.touch_capable) ? e.originalEvent.changedTouches[0].screenY : e.screenY
320                        },
321                        'offset': {
322                            'x': (settings.touch_capable) ? e.originalEvent.changedTouches[0].pageX - e.originalEvent.changedTouches[0].target.offsetLeft : e.offsetX,
323                            'y': (settings.touch_capable) ? e.originalEvent.changedTouches[0].pageY - e.originalEvent.changedTouches[0].target.offsetTop : e.offsetY
324                        },
325                        'time': Date.now(),
326                        'target': e.target
327                    }
328
329                    var touchData = {
330                        'firstTap': firstTap,
331                        'secondTap': lastTap,
332                        'interval': lastTap.time - firstTap.time
333                    };
334
335                    if (!cooling) {
336                        triggerCustomEvent(thisObject, 'doubletap', e, touchData);
337                    }
338
339                    cooling = true;
340
341                    cooloff = window.setTimeout(function (e) {
342                        cooling = false;
343                    }, settings.doubletap_int);
344
345                } else {
346                    $this.data('lastTouch', now);
347                    action = window.setTimeout(function (e) {
348                        window.clearTimeout(action);
349                    }, settings.doubletap_int, [e]);
350                }
351                $this.data
351('lastTouch', now);
352            });
353        },
354        remove: function () {
355            $(this).off(settings.startevent, $(this).data.callee1).off(settings.endevent, $(this).data.callee2);
356        }
357    };
358
359    // singletap Event:
360    // This is used in conjuction with doubletap when both events are needed on the same element
361    $.event.special.singletap = {
362        setup: function () {
363            var thisObject = this,
364                $this = $(thisObject),
365                origTarget = null,
366                startTime = null,
367                start_pos = {
368                    x: 0,
369                    y: 0
370                };
371
372            $this.on(settings.startevent, function (e) {
373                if (e.which && e.which !== 1) {
374                    return false;
375                } else {
376                    startTime = Date.now();
377                    origTarget = e.target;
378                    $this.data('callee1', arguments.callee);
379
380                    // Get the start x and y position:
381                    start_pos.x = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageX : e.pageX;
382                    start_pos.y = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageY : e.pageY;
383                    return true;
384                }
385            }).on(settings.endevent, function (e) {
386                $this.data('callee2', arguments.callee);
387                if (e.target == origTarget) {
388                    // Get the end point:
389                    end_pos_x = (e.originalEvent.changedTouches) ? e.originalEvent.changedTouches[0].pageX : e.pageX;
390                    end_pos_y = (e.originalEvent.changedTouches) ? e.originalEvent.changedTouches[0].pageY : e.pageY;
391
392                    // We need to check if it was a taphold:
393
394                    settings.tap_timer = window.setTimeout(function () {
395                        if (!$this.data('doubletapped') && !$this.data('tapheld') && (start_pos.x == end_pos_x) && (start_pos.y == end_pos_y)) {
396                            var origEvent = e.originalEvent;
397                            var touchData = {
398                                'position': {
399                                    'x': (settings.touch_capable) ? origEvent.changedTouches[0].screenX : e.screenX,
400                                    'y': (settings.touch_capable) ? origEvent.changedTouches[0].screenY : e.screenY
401                                },
402                                'offset': {
403                                    'x': (settings.touch_capable) ? origEvent.changedTouches[0].pageX - origEvent.changedTouches[0].target.offsetLeft : e.offsetX,
404                                    'y': (settings.touch_capable) ? origEvent.changedTouches[0].pageY - origEvent.changedTouches[0].target.offsetTop : e.offsetY
405                                },
406                                'time': Date.now(),
407                                'target': e.target
408                            };
409
410                            // Was it a taphold?
411                            if((touchData.time - startTime) < settings.taphold_threshold)
412                            {
413                                triggerCustomEvent(thisObject, 'singletap', e, touchData);
414                            }
415                        }
416                    }, settings.doubletap_int);
417                }
418            });
419        },
420
421        remove: function () {
422            $(this).off(settings.startevent, $(this).data.callee1).off(settings.endevent, $(this).data.callee2);
423        }
424    };
425
426    // tap Event:
427    $.event.special.tap = {
428        setup: function () {
429            var thisObject = this,
430                $this = $(thisObject),
431                started = false,
432                origTarget = null,
433                start_time,
434                start_pos = {
435                    x: 0,
436                    y: 0
437                },
438                touches;
439
440            $this.on(settings.startevent, function (e) {
441                $this.data('callee1', arguments.callee);
442
443                if (e.which && e.which !== 1) {
444                    return false;
445                } else {
446                    started = true;
447                    start_pos.x = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageX : e.pageX;
448                    start_pos.y = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageY : e.pageY;
449                    start_time = Date.now();
450                    origTarget = e.target;
451
452                    touches = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches : [ e ];
453                    return true;
454                }
455            }).on(settings.endevent, function (e) {
456                $this.data('callee2', arguments.callee);
457
458                // Only trigger if they've started, and the target matches:
459                var end_x = (e.originalEvent.targetTouches) ? e.originalEvent.changedTouches[0].pageX : e.pageX,
460                    end_y = (e.originalEvent.targetTouches) ? e.originalEvent.changedTouches[0].pageY : e.pageY,
461                    diff_x = (start_pos.x - end_x),
462                    diff_y = (start_pos.y - end_y),
463                    eventName;
464
465                if (origTarget == e.target && started && ((Date.now() - start_time) < settings.taphold_threshold) && ((start_pos.x == end_x && start_pos.y == end_y) || (diff_x >= -(settings.tap_pixel_range) && diff_x <= settings.tap_pixel_range && diff_y >= -(settings.tap_pixel_range) && diff_y <= settings.tap_pixel_range))) {
466                    var origEvent = e.originalEvent;
467                    var touchData = [ ];
468
469                    for( var i = 0; i < touches.length; i++)
470                    {
471                        var touch = {
472                            'position': {
473                                'x': (settings.touch_capable) ? origEvent.changedTouches[i].screenX : e.screenX,
474                                'y': (settings.touch_capable) ? origEvent.changedTouches[i].screenY : e.screenY
475                            },
476                            'offset': {
477                                'x': (settings.touch_capable) ? origEvent.changedTouches[i].pageX - origEvent.changedTouches[i].target.offsetLeft : e.offsetX,
478                                'y': (settings.touch_capable) ? origEvent.changedTouches[i].pageY - origEvent.changedTouches[i].target.offsetTop : e.offsetY
479                            },
480                            'time': Date.now(),
481                            'target': e.target
482                        };
483
484                        touchData.push( touch );
485                    }
486
487                    switch( touches.length )
488                    {
489                        case 1:
490                            eventName = 'tap';
491                            break;
492
493                        case 2:
494                            eventName = 'tap2';
495                            break;
496
497                        case 3:
498                            eventName = 'tap3';
499                            break;
500
501                        case 4:
502                            eventName = 'tap4';
503                            break;
504                    }
505
506                    triggerCustomEvent(thisObject, eventName, e, touchData);
507                }
508            });
509        },
510
511        remove: function () {
512            $(this).off(settings.startevent, $(this).data.callee1).off(settings.endevent, $(this).data.callee2);
513        }
514    };
515
516    // swipe Event (also handles swipeup, swiperight, swipedown and swipeleft):
517    $.event.special.swipe = {
518        setup: function () {
519            var thisObject = this,
520                $this = $(thisObject),
521                started = false,
522                hasSwiped = false,
523                originalCoord = {
524                    x: 0,
525                    y: 0
526                },
527                finalCoord = {
528                    x: 0,
529                    y: 0
530                },
531                startEvnt;
532
533            // Screen touched, store the original coordinate
534
535            function touchStart(e) {
536                $this = $(e.target);
537                $this.data('callee1', arguments.callee);
538                originalCoord.x = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageX : e.pageX;
539                originalCoord.y = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageY : e.pageY;
540                finalCoord.x = originalCoord.x;
541                finalCoord.y = originalCoord.y;
542                started = true;
543                var origEvent = e.originalEvent;
544                // Read event data into our startEvt:
545                startEvnt = {
546                    'position': {
547                        'x': (settings.touch_capable) ? origEvent.touches[0].screenX : e.screenX,
548                        'y': (settings.touch_capable) ? origEvent.touches[0].screenY : e.screenY
549                    },
550                    'offset': {
551                        'x': (settings.touch_capable) ? origEvent.touches[0].pageX - origEvent.touches[0].target.offsetLeft : e.offsetX,
552                        'y': (settings.touch_capable) ? origEvent.touches[0].pageY - origEvent.touches[0].target.offsetTop : e.offsetY
553                    },
554                    'time': Date.now(),
555                    'target': e.target
556                };
557            }
558
559            // Store coordinates as finger is swiping
560
561            function touchMove(e) {
562                $this = $(e.target);
563                $this.data('callee2', arguments.callee);
564                finalCoord.x = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageX : e.pageX;
565                finalCoord.y = (e.originalEvent.targetTouches) ? e.originalEvent.targetTouches[0].pageY : e.pageY;
566
567                var swipedir;
568
569                // We need to check if the element to which the event was bound contains a data-xthreshold | data-vthreshold:
570                var ele_x_threshold = $this.data('xthreshold'),
571                    ele_y_threshold = $this.data('ythreshold'),
572                    h_threshold = (typeof ele_x_threshold !== 'undefined' && ele_x_threshold !== false && parseInt(ele_x_threshold)) ? parseInt(ele_x_threshold) : settings.swipe_h_threshold,
573                    v_threshold = (typeof ele_y_threshold !== 'undefined' && ele_y_threshold !== false && parseInt(ele_y_threshold)) ? parseInt(ele_y_threshold) : settings.swipe_v_threshold;
574
575                if (originalCoord.y > finalCoord.y && (originalCoord.y - finalCoord.y > v_threshold)) {
576                    swipedir = 'swipeup';
577                }
578                if (originalCoord.x < finalCoord.x && (finalCoord.x - originalCoord.x > h_threshold)) {
579                    swipedir = 'swiperight';
580                }
581                if (originalCoord.y < finalCoord.y && (finalCoord.y - originalCoord.y > v_threshold)) {
582                    swipedir = 'swipedown';
583                }
584                if (originalCoord.x > finalCoord.x && (originalCoord.x - finalCoord.x > h_threshold)) {
585                    swipedir = 'swipeleft';
586                }
587                if (swipedir != undefined && started) {
588                    originalCoord.x = 0;
589                    originalCoord.y = 0;
590                    finalCoord.x = 0;
591                    finalCoord.y = 0;
592                    started = false;
593
594                    // Read event data into our endEvnt:
595                    var origEvent = e.originalEvent;
596                    endEvnt = {
597                        'position': {
598                            'x': (settings.touch_capable) ? origEvent.touches[0].screenX : e.screenX,
599                            'y': (settings.touch_capable) ? origEvent.touches[0].screenY : e.screenY
600                        },
601                        'offset': {
602                            'x': (settings.touch_capable) ? origEvent.touches[0].pageX - origEvent.touches[0].target.offsetLeft : e.offsetX,
603                            'y': (settings.touch_capable) ? origEvent.touches[0].pageY - origEvent.touches[0].target.offsetTop : e.offsetY
604                        },
605                        'time': Date.now(),
606                        'target': e.target
607                    };
608
609                    // Calculate the swipe amount (normalized):
610                    var xAmount = Math.abs(startEvnt.position.x - endEvnt.position.x),
611                        yAmount = Math.abs(startEvnt.position.y - endEvnt.position.y);
612
613                    var touchData = {
614                        'startEvnt': startEvnt,
615                        'endEvnt': endEvnt,
616                        'direction': swipedir.replace('swipe', ''),
617                        'xAmount': xAmount,
618                        'yAmount': yAmount,
619                        'duration': endEvnt.time - startEvnt.time
620                    }
621                    hasSwiped = true;
622                    $this.trigger('swipe', touchData).trigger(swipedir, touchData);
623                }
624            }
625
626            function touchEnd(e) {
627                $this = $(e.target);
628                var swipedir = "";
629                $this.data('callee3', arguments.callee);
630                if (hasSwiped) {
631                    // We need to check if the element to which the event was bound contains a data-xthreshold | data-vthreshold:
632                    var ele_x_threshold = $this.data('xthreshold'),
633                        ele_y_threshold = $this.data('ythreshold'),
634                        h_threshold = (typeof ele_x_threshold !== 'undefined' && ele_x_threshold !== false && parseInt(ele_x_threshold)) ? parseInt(ele_x_threshold) : settings.swipe_h_threshold,
635                        v_threshold = (typeof ele_y_threshold !== 'undefined' && ele_y_threshold !== false && parseInt(ele_y_threshold)) ? parseInt(ele_y_threshold) : settings.swipe_v_threshold;
636
637                    var origEvent = e.originalEvent;
638                    endEvnt = {
639                        'position': {
640                            'x': (settings.touch_capable) ? origEvent.changedTouches[0].screenX : e.screenX,
641                            'y': (settings.touch_capable) ? origEvent.changedTouches[0].screenY : e.screenY
642                        },
643                        'offset': {
644                            'x': (settings.touch_capable) ? origEvent.changedTouches[0].pageX - origEvent.changedTouches[0].target.offsetLeft : e.offsetX,
645                            'y': (settings.touch_capable) ? origEvent.changedTouches[0].pageY - origEvent.changedTouches[0].target.offsetTop : e.offsetY
646                        },
647                        'time': Date.now(),
648                        'target': e.target
649                    };
650
651                    // Read event data into our endEvnt:
652                    if (startEvnt.position.y > endEvnt.position.y && (startEvnt.position.y - endEvnt.position.y > v_threshold)) {
653                        swipedir = 'swipeup';
654                    }
655                    if (startEvnt.position.x < endEvnt.position.x && (endEvnt.position.x - startEvnt.position.x > h_threshold)) {
656                        swipedir = 'swiperight';
657                    }
658                    if (startEvnt.position.y < endEvnt.position.y && (endEvnt.position.y - startEvnt.position.y > v_threshold)) {
659                        swipedir = 'swipedown';
660                    }
661                    if (startEvnt.position.x > endEvnt.position.x && (startEvnt.position.x - endEvnt.position.x > h_threshold)) {
662                        swipedir = 'swipeleft';
663                    }
664
665                    // Calculate the swipe amount (normalized):
666                    var xAmount = Math.abs(startEvnt.position.x - endEvnt.position.x),
667                        yAmount = Math.abs(startEvnt.position.y - endEvnt.position.y);
668
669                    var touchData = {
670                        'startEvnt': startEvnt,
671                        'endEvnt': endEvnt,
672                        'direction': swipedir.replace('swipe', ''),
673                        'xAmount': xAmount,
674                        'yAmount': yAmount,
675                        'duration': endEvnt.time - startEvnt.time
676                    }
677                    $this.trigger('swipeend', touchData);
678                }
679
680                started = false;
681                hasSwiped = false;
682            }
683
684            $this.on(settings.startevent, touchStart);
685            $this.on(settings.moveevent, touchMove);
686            $this.on(settings.endevent, touchEnd);
687        },
688
689        remove: function () {
690            $(this).off(settings.startevent, $(this).data.callee1).off(settings.moveevent, $(this).data.callee2).off(settings.endevent, $(this).data.callee3);
691        }
692    };
693
694    // scrollstart Event (also handles scrollend):
695    $.event.special.scrollstart = {
696        setup: function () {
697            var thisObject = this,
698                $this = $(thisObject),
699                scrolling,
700                timer;
701
702            function trigger(event, state) {
703                scrolling = state;
704                triggerCustomEvent(thisObject, scrolling ? 'scrollstart' : 'scrollend', event);
705            }
706
707            // iPhone triggers scroll after a small delay; use touchmove instead
708            $this.on(settings.scrollevent, function (event) {
709                $this.data('callee', arguments.callee);
710
711                if (!scrolling) {
712                    trigger(event, true);
713                }
714
715                clearTimeout(timer);
716                timer = setTimeout(function () {
717                    trigger(event, false);
718                }, 50);
719            });
720        },
721
722        remove: function () {
723            $(this).off(settings.scrollevent, $(this).data.callee);
724        }
725    };
726
727    // This is the orientation change (largely borrowed from jQuery Mobile):
728    var win = $(window),
729        special_event,
730        get_orientation,
731        last_orientation,
732        initial_orientation_is_landscape,
733        initial_orientation_is_default,
734        portrait_map = {
735            '0': true,
736            '180': true
737        };
738
739    if (settings.orientation_support) {
740        var ww = window.innerWidth || win.width(),
741            wh = window.innerHeight || win.height(),
742            landscape_threshold = 50;
743
744        initial_orientation_is_landscape = ww > wh && (ww - wh) > landscape_threshold;
745        initial_orientation_is_default = portrait_map[window.orientation];
746
747        if ((initial_orientation_is_landscape && initial_orientation_is_default) || (!initial_orientation_is_landscape && !initial_orientation_is_default)) {
748            portrait_map = {
749                '-90': true,
750                '90': true
751            };
752        }
753    }
754
755    $.event.special.orientationchange = special_event = {
756        setup: function () {
757            // If the event is supported natively, return false so that jQuery
758            // will on to the event using DOM methods.
759            if (settings.orientation_support) {
760                return false;
761            }
762
763            // Get the current orientation to avoid initial double-triggering.
764            last_orientation = get_orientation();
765
766            win.on('throttledresize', handler);
767            return true;
768        },
769        teardown: function () {
770            if (settings.orientation_support) {
771                return false;
772            }
773
774            win.off('throttledresize', handler);
775            return true;
776        },
777        add: function (handleObj) {
778            // Save a reference to the bound event handler.
779            var old_handler = handleObj.handler;
780
781            handleObj.handler = function (event) {
782                event.orientation = get_orientation();
783                return old_handler.apply(this, arguments);
784            };
785        }
786    };
787
788    // If the event is not supported natively, this handler will be bound to
789    // the window resize event to simulate the orientationchange event.
790
791    function handler() {
792        // Get the current orientation.
793        var orientation = get_orientation();
794
795        if (orientation !== last_orientation) {
796            // The orientation has changed, so trigger the orientationchange event.
797            last_orientation = orientation;
798            win.trigger("orientationchange");
799        }
800    }
801
802    $.event.special.orientationchange.orientation = get_orientation = function () {
803        var isPortrait = true,
804            elem = document.documentElement;
805
806        if (settings.orientation_support) {
807            isPortrait = portrait_map[window.orientation];
808        } else {
809            isPortrait = elem && elem.clientWidth / elem.clientHeight < 1.1;
810        }
811
812        return isPortrait ? 'portrait' : 'landscape';
813    };
814
815    // throttle Handler:
816    $.event.special.throttledresize = {
817        setup: function () {
818            $(this).on('resize', throttle_handler);
819        },
820        teardown: function () {
821            $(this).off('resize', throttle_handler);
822        }
823    };
824
825    var throttle = 250,
826        throttle_handler = function () {
827            curr = Date.now();
828            diff = curr - lastCall;
829
830            if (diff >= throttle) {
831                lastCall = curr;
832                $(this).trigger('throttledresize');
833
834            } else {
835                if (heldCall) {
836                    window.clearTimeout(heldCall);
837                }
838
839                // Promise a held call will still execute
840                heldCall = window.setTimeout(handler, throttle - diff);
841            }
842        },
843        lastCall = 0,
844        heldCall,
845        curr,
846        diff;
847
848    // Trigger a custom event:
849
850    function triggerCustomEvent(obj, eventType, event, touchData) {
851        var originalType = event.type;
852        event.type = eventType;
853
854        $.event.dispatch.call(obj, event, touchData);
855        event.type = originalType;
856    }
857
858    // Correctly on anything we've overloaded:
859    $.each({
860        scrollend: 'scrollstart',
861        swipeup: 'swipe',
862        swiperight: 'swipe',
863        swipedown: 'swipe',
864        swipeleft: 'swipe',
865        swipeend: 'swipe',
866        tap2: 'tap'
867    }, function (e, srcE, touchData) {
868        $.event.special[e] = {
869            setup: function () {
870                $(this).on(srcE, $.noop);
871            }
872        };
873    });
874
875})(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.