PageSourceSearch

https://pains.mg.gov.br/modules/mod_bt_contentslider/tmpl/js/hammer.js

js pains.mg.gov.br collected 2026-10-04 08:18:35 UTC 25,335 bytes, 907 lines download raw bytes

1/*
2* Hammer.JS
3* version 0.6.4
4* author: Eight Media
5* https://github.com/EightMedia/hammer.js
6* Licensed under the MIT license.
7*/
8function Hammer(element, options, undefined)
9{
10    var self = this;
11
12    var defaults = {
13        // prevent the default event or not... might be buggy when false
14        prevent_default : false,
15        not_prevent_tags : {id: [], className: [], tagName: []},
16        css_hacks : true,
17
18        swipe : true,
19        swipe_time : 200, // ms
20        swipe_min_distance : 20, // pixels
21
22        drag : true,
23        drag_vertical : true,
24        drag_horizontal : true,
25        // minimum distance before the drag event starts
26        drag_min_distance : 20, // pixels
27
28        // pinch zoom and rotation
29        transform : true,
30        scale_treshold : 0.1,
31        rotation_treshold : 15, // degrees
32
33        tap : true,
34        tap_double : true,
35        tap_max_interval : 300,
36        tap_max_distance : 10,
37        tap_double_distance: 20,
38
39        hold : true,
40        hold_timeout : 500
41    };
42    options = mergeObject(defaults, options);
43
44    // some css hacks
45    (function() {
46        if(!options.css_hacks) {
47            return false;
48        }
49
50        var vendors = ['webkit','moz','ms','o',''];
51        var css_props = {
52            "userSelect": "none",
53            "touchCallout": "none",
54            "userDrag": "none",
55            "tapHighlightColor": "rgba(0,0,0,0)"
56        };
57
58        var prop = '';
59        for(var i = 0; i < vendors.length; i++) {
60            for(var p in css_props) {
61                prop = p;
62                if(vendors[i]) {
63                    prop = vendors[i] + prop.substring(0, 1).toUpperCase() + prop.substring(1);
64                }
65                element.style[ prop ] = css_props[p];
66            }
67        }
68    })();
69
70    // holds the distance that has been moved
71    var _distance = 0;
72
73    // holds the exact angle that has been moved
74    var _angle = 0;
75
76    // holds the direction that has been moved
77    var _direction = 0;
78
79    // holds position movement for sliding
80    var _pos = { };
81
82    // how many fingers are on the screen
83    var _fingers = 0;
84
85    var _first = false;
86
87    var _gesture = null;
88    var _prev_gesture = null;
89
90    var _touch_start_time = null;
91    var _prev_tap_pos = {x: 0, y: 0};
92    var _prev_tap_end_time = null;
93
94    var _hold_timer = null;
95
96    var _offset = {};
97
98    // keep track of the mouse status
99    var _mousedown = false;
100
101    var _event_start;
102    var _event_move;
103    var _event_end;
104
105    var _has_touch = ('ontouchstart' in window);
106
107    var _can_tap = false;
108
109
110    /**
111* option setter/getter
112* @param string key
113* @param mixed value
114* @return mixed value
115*/
116    this.option = function(key, val) {
117        if(val !== undefined) {
118            options[key] = val;
119        }
120
121        return options[key];
122    };
123
124
125    /**
126* angle to direction define
127* @param float angle
128* @return string direction
129*/
130    this.getDirectionFromAngle = function( angle ) {
131        var directions = {
132            down: angle >= 45 && angle < 135, //90
133            left: angle >= 135 || angle <= -135, //180
134            up: angle < -45 && angle > -135, //270
135            right: angle >= -45 && angle <= 45 //0
136        };
137
138        var direction, key;
139        for(key in directions){
140            if(directions[key]){
141                direction = key;
142                break;
143            }
144        }
145        return direction;
146    };
147
148
149    /**
150* destroy events
151* @return void
152*/
153    this.destroy = function() {
154        if(_has_touch) {
155            removeEvent(element, "touchstart touchmove touchend touchcancel", handleEvents);
156        }
157        // for non-touch
158        else {
159            removeEvent(element, "mouseup mousedown mousemove", handleEvents);
160            removeEvent(element, "mouseout", handleMouseOut);
161        }
162    };
163
164
165    /**
166* count the number of fingers in the event
167* when no fingers are detected, one finger is returned (mouse pointer)
168* @param event
169* @return int fingers
170*/
171    function countFingers( event )
172    {
173        // there is a bug on android (until v4?) that touches is always 1,
174        // so no multitouch is supported, e.g. no, zoom and rotation...
175        return event.touches ? event.touches.length : 1;
176    }
177
178
179    /**
180* get the x and y positions from the event object
181* @param event
182* @return array [{ x: int, y: int }]
183*/
184    function getXYfromEvent( event )
185    {
186        event = event || window.event;
187
188        // no touches, use the event pageX and pageY
189        if(!_has_touch) {
190            var doc = document,
191                body = doc.body;
192
193            return [{
194                x: event.pageX || event.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && doc.clientLeft || 0 ),
195                y: event.pageY || event.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && doc.clientTop || 0 )
196            }];
197        }
198        // multitouch, return array with positions
199        else {
200            var pos = [], src;
201            for(var t=0, len=event.touches.length; t<len; t++) {
202                src = event.touches[t];
203                pos.push({ x: src.pageX, y: src.pageY });
204            }
205            return pos;
206        }
207    }
208
209
210    /**
211* calculate the angle between two points
212* @param object pos1 { x: int, y: int }
213* @param object pos2 { x: int, y: int }
214*/
215    function getAngle( pos1, pos2 )
216    {
217        return Math.atan2(pos2.y - pos1.y, pos2.x - pos1.x) * 180 / Math.PI;
218    }
219
220    /**
221* calculate the distance between two points
222* @param object pos1 { x: int, y: int }
223* @param object pos2 { x: int, y: int }
224*/
225    function getDistance( pos1, pos2 )
226    {
227        var x = pos2.x - pos1.x, y = pos2.y - pos1.y;
228        return Math.sqrt((x * x) + (y * y));
229    }
230
231
232    /**
233* calculate the scale size between two fingers
234* @param object pos_start
235* @param object pos_move
236* @return float scale
237*/
238    function calculateScale(pos_start, pos_move)
239    {
240        if(pos_start.length == 2 && pos_move.length == 2) {
241            var start_distance = getDistance(pos_start[0], pos_start[1]);
242            var end_distance = getDistance(pos_move[0], pos_move[1]);
243
244
245
246
247
248
249
250
251
252
253            return end_distance / start_distance;
254        }
255
256        return 0;
257    }
258
259
260    /**
261* calculate the rotation degrees between two fingers
262* @param object pos_start
263* @param object pos_move
264* @return float rotation
265*/
266    function calculateRotation(pos_start, pos_move)
267    {
268        if(pos_start.length == 2 && pos_move.length == 2) {
269            var start_rotation = getAngle(pos_start[1], pos_start[0]);
270            var end_rotation = getAngle(pos_move[1], pos_move[0]);
271
272
273
274
275
276
277
278
279
280
281            return end_rotation - start_rotation;
282        }
283
284        return 0;
285    }
286
287
288    /**
289* trigger an event/callback by name with params
290* @param string name
291* @param array params
292*/
293    function triggerEvent( eventName, params )
294    {
295        // return touches object
296        params.touches = getXYfromEvent(params.originalEvent);
297        params.type = eventName;
298
299        // trigger callback
300        if(isFunction(self["on"+ eventName])) {
301            self["on"+ eventName].call(self, params);
302        }
303    }
304
305
306    /**
307* cancel event
308* @param object event
309* @return void
310*/
311
312    function cancelEvent(event)
313    {
314
315        event = event || window.event;
316        if(event.preventDefault){
317        	for(i = 0; i < options.not_prevent_tags.className.length -1 ; i++)
318        		if(event.target.className == options.not_prevent_tags.className[i]){
319        			return;
320        		}
321        	for(i = 0; i < options.not_prevent_tags.tagName.length -1 ; i++)
322        		if(event.target.tagName == options.not_prevent_tags.tagName[i] ){
323        			return;
324        		}
325        	for(i = 0; i < options.not_prevent_tags.id.length -1 ; i++)
326        		if(event.target.id == options.not_prevent_tags.id[i]){
327        			return;
328        		}
329        	if(countFingers(event)== 2){return;}
330	            event.preventDefault();
331	            event.stopPropagation();
332        }else{
333            event.returnValue = false;
334            event.cancelBubble = true;
335        }
336    }
337
338
339
340    /**
341* reset the internal vars to the start values
342*/
343    function reset()
344    {
345        _pos = {};
346        _first = false;
347        _fingers = 0;
348        _distance = 0;
349        _angle = 0;
350        _gesture = null;
351    }
352
353
354    var gestures = {
355        // hold gesture
356        // fired on touchstart
357        hold : function(event)
358        {
359            // only when one finger is on the screen
360            if(options.hold) {
361                _gesture = 'hold';
362                clearTimeout(_hold_timer);
363
364                _hold_timer = setTimeout(function() {
365                    if(_gesture == 'hold') {
366                        triggerEvent("hold", {
367                            originalEvent : event,
368                            position : _pos.start
369                        });
370                    }
371                }, options.hold_timeout);
372            }
373        },
374
375        // swipe gesture
376        // fired on touchend
377        swipe : function(event)
378        {
379            if (!_pos.move || _gesture === "transform") {
380
381                return;
382            }
383
384            // get the distance we moved
385            var _distance_x = _pos.move[0].x - _pos.start[0].x;
386            var _distance_y = _pos.move[0].y - _pos.start[0].y;
387            _distance = Math.sqrt(_distance_x*_distance_x + _distance_y*_distance_y);
388
389            // compare the kind of gesture by time
390            var now = new Date().getTime();
391            var touch_time = now - _touch_start_time;
392
393            if(options.swipe && (options.swipe_time > touch_time) && (_distance > options.swipe_min_distance)) {
394                // calculate the angle
395                _angle = getAngle(_pos.start[0], _pos.move[0]);
396                _direction = self.getDirectionFromAngle(_angle);
397
398                _gesture = 'swipe';
399
400                var position = { x: _pos.move[0].x - _offset.left,
401                    y: _pos.move[0].y - _offset.top };
402
403                var event_obj = {
404                    originalEvent : event,
405                    position : position,
406                    direction : _direction,
407                    distance : _distance,
408                    distanceX : _distance_x,
409                    distanceY : _distance_y,
410                    angle : _angle
411                };
412
413                // normal slide event
414                triggerEvent("swipe", event_obj);
415            }
416        },
417
418
419        // drag gesture
420        // fired on mousemove
421        drag : function(event)
422        {
423            // get the distance we moved
424            var _distance_x = _pos.move[0].x - _pos.start[0].x;
425            var _distance_y = _pos.move[0].y - _pos.start[0].y;
426            _distance = Math.sqrt(_distance_x * _distance_x + _distance_y * _distance_y);
427
428            // drag
429            // minimal movement required
430            if(options.drag && (_distance > options.drag_min_distance) || _gesture == 'drag') {
431                // calculate the angle
432                _angle = getAngle(_pos.start[0], _pos.move[0]);
433                _direction = self.getDirectionFromAngle(_angle);
434
435                // check the movement and stop if we go in the wrong direction
436                var is_vertical = (_direction == 'up' || _direction == 'down');
437
438                if(((is_vertical && !options.drag_vertical) || (!is_vertical && !options.drag_horizontal)) && (_distance > options.drag_min_distance)) {
439
440                    return;
441                }
442
443                _gesture = 'drag';
444
445                var position = { x: _pos.move[0].x - _offset.left,
446                    y: _pos.move[0].y - _offset.top };
447
448                var event_obj = {
449                    originalEvent : event,
450                    position : position,
451                    direction : _direction,
452                    distance : _distance,
453                    distanceX : _distance_x,
454                    distanceY : _distance_y,
455                    angle : _angle
456                };
457
458                // on the first time trigger the start event
459                if(_first) {
460                    triggerEvent("dragstart", event_obj);
461
462                    _first = false;
463                }
464
465                // normal slide event
466                triggerEvent("drag", event_obj);
467
468                cancelEvent(event);
469            }
470        },
471
472
473        // transform gesture
474        // fired on touchmove
475        transform : function(event)
476        {
477            if(options.transform) {
478                var count = countFingers(event);
479                if (count !== 2) {
480                    return false;
481                }
482
483                var rotation = calculateRotation(_pos.start, _pos.move);
484                var scale = calculateScale(_pos.start, _pos.move);
485
486
487                if (_gesture === 'transform' ||
488                    Math.abs(1 - scale) > options.scale_treshold ||
489                    Math.abs(rotation) > options.rotation_treshold) {
490
491                    _gesture = 'transform';
492                    _pos.center = {
493                        x: ((_pos.move[0].x + _pos.move[1].x) / 2) - _offset.left,
494                        y: ((_pos.move[0].y + _pos.move[1].y) / 2) - _offset.top
495                    };
496
497                    if(_first)
498                        _pos.startCenter = _pos.center;
499
500                    var _distance_x = _pos.center.x - _pos.startCenter.x;
501                    var _distance_y = _pos.center.y - _pos.startCenter.y;
502                    _distance = Math.sqrt(_distance_x*_distance_x + _distance_y*_distance_y);
503
504
505
506                    var event_obj = {
507                        originalEvent : event,
508                        position : _pos.center,
509                        scale : scale,
510
511                        rotation : rotation,
512                        distance : _distance,
513                        distanceX : _distance_x,
514                        distanceY : _distance_y
515                    };
516
517                    // on the first time trigger the start event
518                    if (_first) {
519
520                        triggerEvent("transformstart", event_obj);
521                        _first = false;
522                    }
523
524                    triggerEvent("transform", event_obj);
525
526                    cancelEvent(event);
527
528                    return true;
529                }
530            }
531
532            return false;
533        },
534
535
536        // tap and double tap gesture
537        // fired on touchend
538        tap : function(event)
539        {
540            // compare the kind of gesture by time
541            var now = new Date().getTime();
542            var touch_time = now - _touch_start_time;
543
544            // dont fire when hold is fired
545            if(options.hold && !(options.hold && options.hold_timeout > touch_time)) {
546                return;
547            }
548
549            // when previous event was tap and the tap was max_interval ms ago
550            var is_double_tap = (function(){
551                if (_prev_tap_pos &&
552                    options.tap_double &&
553                    _prev_gesture == 'tap' &&
554                    _pos.start &&
555                    (_touch_start_time - _prev_tap_end_time) < options.tap_max_interval)
556                {
557                    var x_distance = Math.abs(_prev_tap_pos[0].x - _pos.start[0].x);
558                    var y_distance = Math.abs(_prev_tap_pos[0].y - _pos.start[0].y);
559                    return (_prev_tap_pos && _pos.start && Math.max(x_distance, y_distance) < options.tap_double_distance);
560                }
561                return false;
562            })();
563
564            if(is_double_tap) {
565                _gesture = 'double_tap';
566                _prev_tap_end_time = null;
567
568                triggerEvent("doubletap", {
569                    originalEvent : event,
570                    position : _pos.start
571                });
572                cancelEvent(event);
573            }
574
575            // single tap is single touch
576            else {
577                var x_distance = (_pos.move) ? Math.abs(_pos.move[0].x - _pos.start[0].x) : 0;
578                var y_distance = (_pos.move) ? Math.abs(_pos.move[0].y - _pos.start[0].y) : 0;
579                _distance = Math.max(x_distance, y_distance);
580
581                if(_distance < options.tap_max_distance) {
582                    _gesture = 'tap';
583                    _prev_tap_end_time = now;
584                    _prev_tap_pos = _pos.start;
585
586                    if(options.tap) {
587                        triggerEvent("tap", {
588                            originalEvent : event,
589                            position : _pos.start
590                        });
591                        cancelEvent(event);
592                    }
593                }
594            }
595
596        }
597
598    };
599
600
601    function handleEvents(event)
602    {
603        var count;
604        switch(event.type)
605        {
606            case 'mousedown':
607            case 'touchstart':
608                count = countFingers(event);
609                _can_tap = count === 1;
610
611
612
613
614
615
616                //We were dragging and now we are zooming.
617                if (count === 2 && _gesture === "drag") {
618
619
620
621
622
623
624
625                    //The user needs to have the dragend to be fired to ensure that
626                    //there is proper cleanup from the drag and move onto transforming.
627                    triggerEvent("dragend", {
628                        originalEvent : event,
629                        direction : _direction,
630                        distance : _distance,
631                        angle : _angle
632                    });
633                }
634                _setup();
635
636
637
638
639
640
641
642
643
644
645                if(options.prevent_default) {
646                    cancelEvent(event);
647                }
648                break;
649
650            case 'mousemove':
651            case 'touchmove':
652                count = countFingers(event);
653
654                //The user has gone from transforming to dragging. The
655                //user needs to have the proper cleanup of the state and
656                //setup with the new "start" points.
657                if (!_mousedown && count === 1) {
658
659                    return false;
660                } else if (!_mousedown && count === 2) {
661                    _can_tap = false;
662
663                    reset();
664                    _setup();
665                }
666
667                _event_move = event;
668                _pos.move = getXYfromEvent(event);
669
670                if(!gestures.transform(event)) {
671                    gestures.drag(event);
672                }
673                break;
674
675            case 'mouseup':
676            case 'mouseout':
677            case 'touchcancel':
678            case 'touchend':
679                var callReset = true;
680
681
682
683
684                _mousedown = false;
685                _event_end = event;
686
687
688                // swipe gesture
689                gestures.swipe(event);
690
691
692                // drag gesture
693                // dragstart is triggered, so dragend is possible
694                if(_gesture == 'drag') {
695                    triggerEvent("dragend", {
696                        originalEvent : event,
697                        direction : _direction,
698                        distance : _distance,
699                        angle : _angle
700
701                    });
702                }
703
704                // transform
705                // transformstart is triggered, so transformed is possible
706                else if(_gesture == 'transform') {
707                    // define the transform distance
708                    var _distance_x = _pos.center.x - _pos.startCenter.x;
709                    var _distance_y = _pos.center.y - _pos.startCenter.y;
710                    
711                    triggerEvent("transformend", {
712                        originalEvent : event,
713                        position : _pos.center,
714                        scale : calculateScale(_pos.start, _pos.move),
715                        rotation : calculateRotation(_pos.start, _pos.move),
716                        distance : _distance,
717                        distanceX : _distance_x,
718                        distanceY : _distance_y
719                    });
720
721                    //If the user goes from transformation to drag there needs to be a
722                    //state reset so that way a dragstart/drag/dragend will be properly
723                    //fired.
724                    if (countFingers(event) === 1) {
725                        reset();
726                        _setup();
727                        callReset = false;
728                    }
729                } else if (_can_tap) {
730
731
732                    gestures.tap(_event_start);
733                }
734
735                _prev_gesture = _gesture;
736
737                // trigger release event
738                // "release" by default doesn't return the co-ords where your
739                // finger was released. "position" will return "the last touched co-ords"
740
741                triggerEvent("release", {
742                    originalEvent : event,
743                    gesture : _gesture,
744                    position : _pos.move || _pos.start
745                });
746
747                // reset vars if this was not a transform->drag touch end operation.
748                if (callReset) {
749                    reset();
750                }
751
752
753                break;
754        } // end switch
755
756        /**
757* Performs a blank setup.
758* @private
759*/
760        function _setup() {
761            _pos.start = getXYfromEvent(event);
762            _touch_start_time = new Date().getTime();
763            _fingers = countFingers(event);
764            _first = true;
765            _event_start = event;
766
767            // borrowed from jquery offset https://github.com/jquery/jquery/blob/master/src/offset.js
768            var box = element.getBoundingClientRect();
769            var clientTop = element.clientTop || document.body.clientTop || 0;
770            var clientLeft = element.clientLeft || document.body.clientLeft || 0;
771            var scrollTop = window.pageYOffset || element.scrollTop || document.body.scrollTop;
772            var scrollLeft = window.pageXOffset || element.scrollLeft || document.body.scrollLeft;
773
774            _offset = {
775                top: box.top + scrollTop - clientTop,
776                left: box.left + scrollLeft - clientLeft
777            };
778
779            _mousedown = true;
780
781            // hold gesture
782            gestures.hold(event);
783        }
784    }
785
786
787    function handleMouseOut(event) {
788        if(!isInsideHammer(element, event.relatedTarget)) {
789            handleEvents(event);
790        }
791    }
792
793
794    // bind events for touch devices
795    // except for windows phone 7.5, it doesnt support touch events..!
796    if(_has_touch) {
797        addEvent(element, "touchstart touchmove touchend touchcancel", handleEvents);
798    }
799    // for non-touch
800    else {
801        addEvent(element, "mouseup mousedown mousemove", handleEvents);
802        addEvent(element, "mouseout", handleMouseOut);
803    }
804
805
806    /**
807* find if element is (inside) given parent element
808* @param object element
809* @param object parent
810* @return bool inside
811*/
812    function isInsideHammer(parent, child) {
813        // get related target for IE
814        if(!child && window.event && window.event.toElement){
815            child = window.event.toElement;
816        }
817
818        if(parent === child){
819            return true;
820        }
821
822        // loop over parentNodes of child until we find hammer element
823        if(child){
824            var node = child.parentNode;
825            while(node !== null){
826                if(node === parent){
827                    return true;
828                }
829
830                node = node.parentNode;
831            }
832        }
833        return false;
834    }
835
836
837    /**
838* merge 2 objects into a new object
839* @param object obj1
840* @param object obj2
841* @return object merged object
842*/
843    function mergeObject(obj1, obj2) {
844        var output = {};
845
846        if(!obj2) {
847            return obj1;
848        }
849
850        for (var prop in obj1) {
851            if (prop in obj2) {
852                output[prop] = obj2[prop];
853            } else {
854                output[prop] = obj1[prop];
855            }
856        }
857        return output;
858    }
859
860
861    /**
862* check if object is a function
863* @param object obj
864* @return bool is function
865*/
866    function isFunction( obj ){
867        return Object.prototype.toString.call( obj ) == "[object Function]";
868    }
869
870
871    /**
872* attach event
873* @param node element
874* @param string types
875* @param object callback
876*/
877    function addEvent(element, types, callback) {
878        types = types.split(" ");
879        for(var t= 0,len=types.length; t<len; t++) {
880            if(element.addEventListener){
881                element.addEventListener(types[t], callback, false);
882            }
883            else if(document.attachEvent){
884                element.attachEvent("on"+ types[t], callback);
885            }
886        }
887    }
888
889
890    /**
891* detach event
892* @param node element
893* @param string types
894* @param object callback
895*/
896    function removeEvent(element, types, callback) {
897        types = types.split(" ");
898        for(var t= 0,len=types.length; t<len; t++) {
899            if(element.removeEventListener){
900                element.removeEventListener(types[t], callback, false);
901            }
902            else if(document.detachEvent){
903                element.detachEvent("on"+ types[t], callback);
904            }
905        }
906    }
907}

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.