Вход Регистрация
Файл: templates/backend/default/assets/plugins/Mapplic/js/hammer.js
Строк: 1819
<?php
/*! Hammer.JS - v1.0.9 - 2014-03-18
 * http://eightmedia.github.com/hammer.js
 *
 * Copyright (c) 2014 Jorik Tangelder <j.tangelder@gmail.com>;
 * Licensed under the MIT license */

(function(windowundefined) {
  
'use strict';

/**
 * Hammer
 * use this to create instances
 * @param   {HTMLElement}   element
 * @param   {Object}        options
 * @returns {Hammer.Instance}
 * @constructor
 */
var Hammer = function(elementoptions) {
  return new 
Hammer.Instance(elementoptions || {});
};

// default settings
Hammer.defaults = {
  
// add styles and attributes to the element to prevent the browser from doing
  // its native behavior. this doesnt prevent the scrolling, but cancels
  // the contextmenu, tap highlighting etc
  // set to false to disable this
  
stop_browser_behavior: {
    
// this also triggers onselectstart=false for IE
    
userSelect       'none',
    
// this makes the element blocking in IE10 >, you could experiment with the value
    // see for more options this issue; https://github.com/EightMedia/hammer.js/issues/241
    
touchAction      'none',
    
touchCallout     'none',
    
contentZooming   'none',
    
userDrag         'none',
    
tapHighlightColor'rgba(0,0,0,0)'
  
}

  
//
  // more settings are defined per gesture at gestures.js
  //
};


// detect touchevents
Hammer.HAS_POINTEREVENTS window.navigator.pointerEnabled || window.navigator.msPointerEnabled;
Hammer.HAS_TOUCHEVENTS = ('ontouchstart' in window);

// dont use mouseevents on mobile devices
Hammer.MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android|silk/i;
Hammer.NO_MOUSEEVENTS Hammer.HAS_TOUCHEVENTS && window.navigator.userAgent.match(Hammer.MOBILE_REGEX);

// eventtypes per touchevent (start, move, end)
// are filled by Event.determineEventTypes on setup
Hammer.EVENT_TYPES = {};

// interval in which Hammer recalculates current velocity in ms
Hammer.UPDATE_VELOCITY_INTERVAL 16;

// hammer document where the base events are added at
Hammer.DOCUMENT window.document;

// define these also as vars, for internal usage.
// direction defines
var DIRECTION_DOWN Hammer.DIRECTION_DOWN 'down';
var 
DIRECTION_LEFT Hammer.DIRECTION_LEFT 'left';
var 
DIRECTION_UP Hammer.DIRECTION_UP 'up';
var 
DIRECTION_RIGHT Hammer.DIRECTION_RIGHT 'right';

// pointer type
var POINTER_MOUSE Hammer.POINTER_MOUSE 'mouse';
var 
POINTER_TOUCH Hammer.POINTER_TOUCH 'touch';
var 
POINTER_PEN Hammer.POINTER_PEN 'pen';

// touch event defines
var EVENT_START Hammer.EVENT_START 'start';
var 
EVENT_MOVE Hammer.EVENT_MOVE 'move';
var 
EVENT_END Hammer.EVENT_END 'end';


// plugins and gestures namespaces
Hammer.plugins Hammer.plugins || {};
Hammer.gestures Hammer.gestures || {};


// if the window events are set...
Hammer.READY false;

/**
 * setup events to detect gestures on the document
 */
function setup() {
  if(
Hammer.READY) {
    return;
  }

  
// find what eventtypes we add listeners to
  
Event.determineEventTypes();

  
// Register all gestures inside Hammer.gestures
  
Utils.each(Hammer.gestures, function(gesture){
    
Detection.register(gesture);
  });

  
// Add touch events on the document
  
Event.onTouch(Hammer.DOCUMENTEVENT_MOVEDetection.detect);
  
Event.onTouch(Hammer.DOCUMENTEVENT_ENDDetection.detect);

  
// Hammer is ready...!
  
Hammer.READY true;
}

var 
Utils Hammer.utils = {
  
/**
   * extend method,
   * also used for cloning when dest is an empty object
   * @param   {Object}    dest
   * @param   {Object}    src
   * @parm  {Boolean}  merge    do a merge
   * @returns {Object}    dest
   */
  
extend: function extend(destsrcmerge) {
    for(var 
key in src) {
      if(
dest[key] !== undefined && merge) {
        continue;
      }
      
dest[key] = src[key];
    }
    return 
dest;
  },


  
/**
   * for each
   * @param obj
   * @param iterator
   */
  
each: function(objiteratorcontext) {
    var 
io;
    
// native forEach on arrays
    
if ('forEach' in obj) {
      
obj.forEach(iteratorcontext);
    }
    
// arrays
    
else if(obj.length !== undefined) {
      for(
i=-1; (o=obj[++i]);) {
        if (
iterator.call(contextoiobj) === false) {
          return;
        }
      }
    }
    
// objects
    
else {
      for(
i in obj) {
        if(
obj.hasOwnProperty(i) &&
            
iterator.call(contextobj[i], iobj) === false) {
          return;
        }
      }
    }
  },

  
/**
   * find if a node is in the given parent
   * used for event delegation tricks
   * @param   {HTMLElement}   node
   * @param   {HTMLElement}   parent
   * @returns {boolean}       has_parent
   */
  
hasParent: function(nodeparent) {
    while(
node) {
      if(
node == parent) {
        return 
true;
      }
      
node node.parentNode;
    }
    return 
false;
  },


  
/**
   * get the center of all the touches
   * @param   {Array}     touches
   * @returns {Object}    center
   */
  
getCenter: function getCenter(touches) {
    var 
valuesX = [], valuesY = [];

    
Utils.each(touches, function(touch) {
      
// I prefer clientX because it ignore the scrolling position
      
valuesX.push(typeof touch.clientX !== 'undefined' touch.clientX touch.pageX);
      
valuesY.push(typeof touch.clientY !== 'undefined' touch.clientY touch.pageY);
    });

    return {
      
pageX: (Math.min.apply(MathvaluesX) + Math.max.apply(MathvaluesX)) / 2,
      
pageY: (Math.min.apply(MathvaluesY) + Math.max.apply(MathvaluesY)) / 2
    
};
  },


  
/**
   * calculate the velocity between two points
   * @param   {Number}    delta_time
   * @param   {Number}    delta_x
   * @param   {Number}    delta_y
   * @returns {Object}    velocity
   */
  
getVelocity: function getVelocity(delta_timedelta_xdelta_y) {
    return {
      
xMath.abs(delta_x delta_time) || 0,
      
yMath.abs(delta_y delta_time) || 0
    
};
  },


  
/**
   * calculate the angle between two coordinates
   * @param   {Touch}     touch1
   * @param   {Touch}     touch2
   * @returns {Number}    angle
   */
  
getAngle: function getAngle(touch1touch2) {
    var 
touch2.pageY touch1.pageY
      
touch2.pageX touch1.pageX;
    return 
Math.atan2(yx) * 180 Math.PI;
  },


  
/**
   * angle to direction define
   * @param   {Touch}     touch1
   * @param   {Touch}     touch2
   * @returns {String}    direction constant, like DIRECTION_LEFT
   */
  
getDirection: function getDirection(touch1touch2) {
    var 
Math.abs(touch1.pageX touch2.pageX)
      , 
Math.abs(touch1.pageY touch2.pageY);
    if(
>= y) {
      return 
touch1.pageX touch2.pageX DIRECTION_LEFT DIRECTION_RIGHT;
    }
    return 
touch1.pageY touch2.pageY DIRECTION_UP DIRECTION_DOWN;
  },


  
/**
   * calculate the distance between two touches
   * @param   {Touch}     touch1
   * @param   {Touch}     touch2
   * @returns {Number}    distance
   */
  
getDistance: function getDistance(touch1touch2) {
    var 
touch2.pageX touch1.pageX
      
touch2.pageY touch1.pageY;
    return 
Math.sqrt((x) + (y));
  },


  
/**
   * calculate the scale factor between two touchLists (fingers)
   * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
   * @param   {Array}     start
   * @param   {Array}     end
   * @returns {Number}    scale
   */
  
getScale: function getScale(startend) {
    
// need two fingers...
    
if(start.length >= && end.length >= 2) {
      return 
this.getDistance(end[0], end[1]) / this.getDistance(start[0], start[1]);
    }
    return 
1;
  },


  
/**
   * calculate the rotation degrees between two touchLists (fingers)
   * @param   {Array}     start
   * @param   {Array}     end
   * @returns {Number}    rotation
   */
  
getRotation: function getRotation(startend) {
    
// need two fingers
    
if(start.length >= && end.length >= 2) {
      return 
this.getAngle(end[1], end[0]) - this.getAngle(start[1], start[0]);
    }
    return 
0;
  },


  
/**
   * boolean if the direction is vertical
   * @param    {String}    direction
   * @returns  {Boolean}   is_vertical
   */
  
isVertical: function isVertical(direction) {
    return 
direction == DIRECTION_UP || direction == DIRECTION_DOWN;
  },


  
/**
   * toggle browser default behavior with css props
   * @param   {HtmlElement}   element
   * @param   {Object}        css_props
   * @param   {Boolean}       toggle
   */
  
toggleDefaultBehavior: function toggleDefaultBehavior(elementcss_propstoggle) {
    if(!
css_props || !element || !element.style) {
      return;
    }

    
// with css properties for modern browsers
    
Utils.each(['webkit''moz''Moz''ms''o'''], function(vendor) {
      
Utils.each(css_props, function(valueprop) {
          
// vender prefix at the property
          
if(vendor) {
            
prop vendor prop.substring(01).toUpperCase() + prop.substring(1);
          }
          
// set the style
          
if(prop in element.style) {
            
element.style[prop] = !toggle && value;
          }
      });
    });

    var 
false_fn = function(){ return false; };

    
// also the disable onselectstart
    
if(css_props.userSelect == 'none') {
      
element.onselectstart = !toggle && false_fn;
    }
    
// and disable ondragstart
    
if(css_props.userDrag == 'none') {
      
element.ondragstart = !toggle && false_fn;
    }
  }
};


/**
 * create new hammer instance
 * all methods should return the instance itself, so it is chainable.
 * @param   {HTMLElement}       element
 * @param   {Object}            [options={}]
 * @returns {Hammer.Instance}
 * @constructor
 */
Hammer.Instance = function(elementoptions) {
  var 
self this;

  
// setup HammerJS window events and register all gestures
  // this also sets up the default options
  
setup();

  
this.element element;

  
// start/stop detection option
  
this.enabled true;

  
// merge options
  
this.options Utils.extend(
    
Utils.extend({}, Hammer.defaults),
    
options || {});

  
// add some css to the element to prevent the browser from doing its native behavoir
  
if(this.options.stop_browser_behavior) {
    
Utils.toggleDefaultBehavior(this.elementthis.options.stop_browser_behaviorfalse);
  }

  
// start detection on touchstart
  
this.eventStartHandler Event.onTouch(elementEVENT_START, function(ev) {
    if(
self.enabled) {
      
Detection.startDetect(selfev);
    }
  });

  
// keep a list of user event handlers which needs to be removed when calling 'dispose'
  
this.eventHandlers = [];

  
// return instance
  
return this;
};


Hammer.Instance.prototype = {
  
/**
   * bind events to the instance
   * @param   {String}      gesture
   * @param   {Function}    handler
   * @returns {Hammer.Instance}
   */
  
on: function onEvent(gesturehandler) {
    var 
gestures gesture.split(' ');
    
Utils.each(gestures, function(gesture) {
      
this.element.addEventListener(gesturehandlerfalse);
      
this.eventHandlers.push({ gesturegesturehandlerhandler });
    }, 
this);
    return 
this;
  },


  
/**
   * unbind events to the instance
   * @param   {String}      gesture
   * @param   {Function}    handler
   * @returns {Hammer.Instance}
   */
  
off: function offEvent(gesturehandler) {
    var 
gestures gesture.split(' ')
      , 
ieh;
    
Utils.each(gestures, function(gesture) {
      
this.element.removeEventListener(gesturehandlerfalse);

      
// remove the event handler from the internal list
      
for(i=-1; (eh=this.eventHandlers[++i]);) {
        if(
eh.gesture === gesture && eh.handler === handler) {
          
this.eventHandlers.splice(i1);
        }
      }
    }, 
this);
    return 
this;
  },


  
/**
   * trigger gesture event
   * @param   {String}      gesture
   * @param   {Object}      [eventData]
   * @returns {Hammer.Instance}
   */
  
trigger: function triggerEvent(gestureeventData) {
    
// optional
    
if(!eventData) {
      
eventData = {};
    }

    
// create DOM event
    
var event Hammer.DOCUMENT.createEvent('Event');
    
event.initEvent(gesturetruetrue);
    
event.gesture eventData;

    
// trigger on the target if it is in the instance element,
    // this is for event delegation tricks
    
var element this.element;
    if(
Utils.hasParent(eventData.targetelement)) {
      
element eventData.target;
    }

    
element.dispatchEvent(event);
    return 
this;
  },


  
/**
   * enable of disable hammer.js detection
   * @param   {Boolean}   state
   * @returns {Hammer.Instance}
   */
  
enable: function enable(state) {
    
this.enabled state;
    return 
this;
  },


  
/**
   * dispose this hammer instance
   * @returns {Hammer.Instance}
   */
  
dispose: function dispose() {
    var 
ieh;

    
// undo all changes made by stop_browser_behavior
    
if(this.options.stop_browser_behavior) {
      
Utils.toggleDefaultBehavior(this.elementthis.options.stop_browser_behaviortrue);
    }

    
// unbind all custom event handlers
    
for(i=-1; (eh=this.eventHandlers[++i]);) {
      
this.element.removeEventListener(eh.gestureeh.handlerfalse);
    }
    
this.eventHandlers = [];

    
// unbind the start event listener
    
Event.unbindDom(this.elementHammer.EVENT_TYPES[EVENT_START], this.eventStartHandler);

    return 
null;
  }
};


/**
 * this holds the last move event,
 * used to fix empty touchend issue
 * see the onTouch event for an explanation
 * @type {Object}
 */
var last_move_event null;

/**
 * when the mouse is hold down, this is true
 * @type {Boolean}
 */
var enable_detect false;

/**
 * when touch events have been fired, this is true
 * @type {Boolean}
 */
var touch_triggered false;

var 
Event Hammer.event = {
  
/**
   * simple addEventListener
   * @param   {HTMLElement}   element
   * @param   {String}        type
   * @param   {Function}      handler
   */
  
bindDom: function(elementtypehandler) {
    var 
types type.split(' ');
    
Utils.each(types, function(type){
      
element.addEventListener(typehandlerfalse);
    });
  },


  
/**
   * simple removeEventListener
   * @param   {HTMLElement}   element
   * @param   {String}        type
   * @param   {Function}      handler
   */
  
unbindDom: function(elementtypehandler) {
    var 
types type.split(' ');
    
Utils.each(types, function(type){
      
element.removeEventListener(typehandlerfalse);
    });
  },


  
/**
   * touch events with mouse fallback
   * @param   {HTMLElement}   element
   * @param   {String}        eventType        like EVENT_MOVE
   * @param   {Function}      handler
   */
  
onTouch: function onTouch(elementeventTypehandler) {
    var 
self this;

    var 
bindDomOnTouch = function(ev) {
      var 
srcEventType ev.type.toLowerCase();

      
// onmouseup, but when touchend has been fired we do nothing.
      // this is for touchdevices which also fire a mouseup on touchend
      
if(srcEventType.match(/mouse/) && touch_triggered) {
        return;
      }

      
// mousebutton must be down or a touch event
      
else if(srcEventType.match(/touch/) ||   // touch events are always on screen
        
srcEventType.match(/pointerdown/) || // pointerevents touch
        
(srcEventType.match(/mouse/) && ev.which === 1)   // mouse is pressed
        
) {
        
enable_detect true;
      }

      
// mouse isn't pressed
      
else if(srcEventType.match(/mouse/) && !ev.which) {
        
enable_detect false;
      }


      
// we are in a touch event, set the touch triggered bool to true,
      // this for the conflicts that may occur on ios and android
      
if(srcEventType.match(/touch|pointer/)) {
        
touch_triggered true;
      }

      
// count the total touches on the screen
      
var count_touches 0;

      
// when touch has been triggered in this detection session
      // and we are now handling a mouse event, we stop that to prevent conflicts
      
if(enable_detect) {
        
// update pointerevent
        
if(Hammer.HAS_POINTEREVENTS && eventType != EVENT_END) {
          
count_touches PointerEvent.updatePointer(eventTypeev);
        }
        
// touch
        
else if(srcEventType.match(/touch/)) {
          
count_touches ev.touches.length;
        }
        
// mouse
        
else if(!touch_triggered) {
          
count_touches srcEventType.match(/up/) ? 1;
        }

        
// if we are in a end event, but when we remove one touch and
        // we still have enough, set eventType to move
        
if(count_touches && eventType == EVENT_END) {
          
eventType EVENT_MOVE;
        }
        
// no touches, force the end event
        
else if(!count_touches) {
          
eventType EVENT_END;
        }

        
// store the last move event
        
if(count_touches || last_move_event === null) {
          
last_move_event ev;
        }

        
// trigger the handler
        
handler.call(Detectionself.collectEventData(elementeventType,
                                         
self.getTouchList(last_move_eventeventType),
                                         
ev));

        
// remove pointerevent from list
        
if(Hammer.HAS_POINTEREVENTS && eventType == EVENT_END) {
          
count_touches PointerEvent.updatePointer(eventTypeev);
        }
      }

      
// on the end we reset everything
      
if(!count_touches) {
        
last_move_event null;
        
enable_detect false;
        
touch_triggered false;
        
PointerEvent.reset();
      }
    };

    
this.bindDom(elementHammer.EVENT_TYPES[eventType], bindDomOnTouch);

    
// return the bound function to be able to unbind it later
    
return bindDomOnTouch;
  },


  
/**
   * we have different events for each device/browser
   * determine what we need and set them in the Hammer.EVENT_TYPES constant
   */
  
determineEventTypes: function determineEventTypes() {
    
// determine the eventtype we want to set
    
var types;

    
// pointerEvents magic
    
if(Hammer.HAS_POINTEREVENTS) {
      
types PointerEvent.getEvents();
    }
    
// on Android, iOS, blackberry, windows mobile we dont want any mouseevents
    
else if(Hammer.NO_MOUSEEVENTS) {
      
types = [
        
'touchstart',
        
'touchmove',
        
'touchend touchcancel'];
    }
    
// for non pointer events browsers and mixed browsers,
    // like chrome on windows8 touch laptop
    
else {
      
types = [
        
'touchstart mousedown',
        
'touchmove mousemove',
        
'touchend touchcancel mouseup'];
    }

    
Hammer.EVENT_TYPES[EVENT_START] = types[0];
    
Hammer.EVENT_TYPES[EVENT_MOVE] = types[1];
    
Hammer.EVENT_TYPES[EVENT_END] = types[2];
  },


  
/**
   * create touchlist depending on the event
   * @param   {Object}    ev
   * @param   {String}    eventType   used by the fakemultitouch plugin
   */
  
getTouchList: function getTouchList(ev/*, eventType*/) {
    
// get the fake pointerEvent touchlist
    
if(Hammer.HAS_POINTEREVENTS) {
      return 
PointerEvent.getTouchList();
    }

    
// get the touchlist
    
if(ev.touches) {
      return 
ev.touches;
    }

    
// make fake touchlist from mouse position
    
ev.identifier 1;
    return [
ev];
  },


  
/**
   * collect event data for Hammer js
   * @param   {HTMLElement}   element
   * @param   {String}        eventType        like EVENT_MOVE
   * @param   {Object}        eventData
   */
  
collectEventData: function collectEventData(elementeventTypetouchesev) {
    
// find out pointerType
    
var pointerType POINTER_TOUCH;
    if(
ev.type.match(/mouse/) || PointerEvent.matchType(POINTER_MOUSEev)) {
      
pointerType POINTER_MOUSE;
    }

    return {
      
center     Utils.getCenter(touches),
      
timeStamp  : new Date().getTime(),
      
target     ev.target,
      
touches    touches,
      
eventType  eventType,
      
pointerTypepointerType,
      
srcEvent   ev,

      
/**
       * prevent the browser default actions
       * mostly used to disable scrolling of the browser
       */
      
preventDefault: function() {
        if(
this.srcEvent.preventManipulation) {
          
this.srcEvent.preventManipulation();
        }

        if(
this.srcEvent.preventDefault) {
          
this.srcEvent.preventDefault();
        }
      },

      
/**
       * stop bubbling the event up to its parents
       */
      
stopPropagation: function() {
        
this.srcEvent.stopPropagation();
      },

      
/**
       * immediately stop gesture detection
       * might be useful after a swipe was detected
       * @return {*}
       */
      
stopDetect: function() {
        return 
Detection.stopDetect();
      }
    };
  }
};

var 
PointerEvent Hammer.PointerEvent = {
  
/**
   * holds all pointers
   * @type {Object}
   */
  
pointers: {},

  
/**
   * get a list of pointers
   * @returns {Array}     touchlist
   */
  
getTouchList: function() {
    var 
touchlist = [];
    
// we can use forEach since pointerEvents only is in IE10
    
Utils.each(this.pointers, function(pointer){
      
touchlist.push(pointer);
    });

    return 
touchlist;
  },

  
/**
   * update the position of a pointer
   * @param   {String}   type             EVENT_END
   * @param   {Object}   pointerEvent
   */
  
updatePointer: function(typepointerEvent) {
    if(
type == EVENT_END) {
      
delete this.pointers[pointerEvent.pointerId];
    }
    else {
      
pointerEvent.identifier pointerEvent.pointerId;
      
this.pointers[pointerEvent.pointerId] = pointerEvent;
    }

    
// it's save to use Object.keys, since pointerEvents are only in newer browsers
    
return Object.keys(this.pointers).length;
  },

  
/**
   * check if ev matches pointertype
   * @param   {String}        pointerType     POINTER_MOUSE
   * @param   {PointerEvent}  ev
   */
  
matchType: function(pointerTypeev) {
    if(!
ev.pointerType) {
      return 
false;
    }

    var 
pt ev.pointerType
      
types = {};

    
types[POINTER_MOUSE] = (pt === POINTER_MOUSE);
    
types[POINTER_TOUCH] = (pt === POINTER_TOUCH);
    
types[POINTER_PEN] = (pt === POINTER_PEN);
    return 
types[pointerType];
  },


  
/**
   * get events
   */
  
getEvents: function() {
    return [
      
'pointerdown MSPointerDown',
      
'pointermove MSPointerMove',
      
'pointerup pointercancel MSPointerUp MSPointerCancel'
    
];
  },

  
/**
   * reset the list
   */
  
reset: function() {
    
this.pointers = {};
  }
};


var 
Detection Hammer.detection = {
  
// contains all registred Hammer.gestures in the correct order
  
gestures: [],

  
// data of the current Hammer.gesture detection session
  
current null,

  
// the previous Hammer.gesture session data
  // is a full clone of the previous gesture.current object
  
previousnull,

  
// when this becomes true, no gestures are fired
  
stopped false,


  
/**
   * start Hammer.gesture detection
   * @param   {Hammer.Instance}   inst
   * @param   {Object}            eventData
   */
  
startDetect: function startDetect(insteventData) {
    
// already busy with a Hammer.gesture detection on an element
    
if(this.current) {
      return;
    }

    
this.stopped false;

    
this.current = {
      
inst              inst// reference to HammerInstance we're working for
      
startEvent        Utils.extend({}, eventData), // start eventData for distances, timing etc
      
lastEvent         false// last eventData
      
lastVelocityEvent false// last eventData for velocity.
      
velocity          false// current velocity
      
name              '' // current gesture we're in/detected, can be 'tap', 'hold' etc
    
};

    
this.detect(eventData);
  },


  
/**
   * Hammer.gesture detection
   * @param   {Object}    eventData
   */
  
detect: function detect(eventData) {
    if(!
this.current || this.stopped) {
      return;
    }

    
// extend event data with calculations about scale, distance etc
    
eventData this.extendEventData(eventData);

    
// instance options
    
var inst_options this.current.inst.options;

    
// call Hammer.gesture handlers
    
Utils.each(this.gestures, function(gesture) {
      
// only when the instance options have enabled this gesture
      
if(!this.stopped && inst_options[gesture.name] !== false) {
        
// if a handler returns false, we stop with the detection
        
if(gesture.handler.call(gestureeventDatathis.current.inst) === false) {
          
this.stopDetect();
          return 
false;
        }
      }
    }, 
this);

    
// store as previous event event
    
if(this.current) {
      
this.current.lastEvent eventData;
    }

    
// endevent, but not the last touch, so dont stop
    
if(eventData.eventType == EVENT_END && !eventData.touches.length 1) {
      
this.stopDetect();
    }

    return 
eventData;
  },


  
/**
   * clear the Hammer.gesture vars
   * this is called on endDetect, but can also be used when a final Hammer.gesture has been detected
   * to stop other Hammer.gestures from being fired
   */
  
stopDetect: function stopDetect() {
    
// clone current data to the store as the previous gesture
    // used for the double tap gesture, since this is an other gesture detect session
    
this.previous Utils.extend({}, this.current);

    
// reset the current
    
this.current null;

    
// stopped!
    
this.stopped true;
  },


  
/**
   * extend eventData for Hammer.gestures
   * @param   {Object}   ev
   * @returns {Object}   ev
   */
  
extendEventData: function extendEventData(ev) {
    var 
cur this.current
      
startEv cur.startEvent;

    
// if the touches change, set the new touches over the startEvent touches
    // this because touchevents don't have all the touches on touchstart, or the
    // user must place his fingers at the EXACT same time on the screen, which is not realistic
    // but, sometimes it happens that both fingers are touching at the EXACT same time
    
if(ev.touches.length != startEv.touches.length || ev.touches === startEv.touches) {
      
// extend 1 level deep to get the touchlist with the touch objects
      
startEv.touches = [];
      
Utils.each(ev.touches, function(touch) {
        
startEv.touches.push(Utils.extend({}, touch));
      });
    }

    var 
delta_time ev.timeStamp startEv.timeStamp
      
delta_x ev.center.pageX startEv.center.pageX
      
delta_y ev.center.pageY startEv.center.pageY
      
interimAngle
      
interimDirection
      
velocityEv cur.lastVelocityEvent
      
velocity cur.velocity;

    
// calculate velocity every x ms
    
if (velocityEv && ev.timeStamp velocityEv.timeStamp Hammer.UPDATE_VELOCITY_INTERVAL) {
        
velocity Utils.getVelocity(ev.timeStamp velocityEv.timeStamp,
                                            
ev.center.pageX velocityEv.center.pageX,
                                            
ev.center.pageY velocityEv.center.pageY);

        
cur.lastVelocityEvent ev;
        
cur.velocity velocity;
    }
    else if(!
cur.velocity) {
        
velocity Utils.getVelocity(delta_timedelta_xdelta_y);

        
cur.lastVelocityEvent ev;
        
cur.velocity velocity;
    }

    
// end events (e.g. dragend) don't have useful values for interimDirection & interimAngle
    // because the previous event has exactly the same coordinates
    // so for end events, take the previous values of interimDirection & interimAngle
    // instead of recalculating them and getting a spurious '0'
    
if(ev.eventType == EVENT_END) {
      
interimAngle cur.lastEvent && cur.lastEvent.interimAngle;
      
interimDirection cur.lastEvent && cur.lastEvent.interimDirection;
    }
    else {
      
interimAngle cur.lastEvent &&
        
Utils.getAngle(cur.lastEvent.centerev.center);
      
interimDirection cur.lastEvent &&
        
Utils.getDirection(cur.lastEvent.centerev.center);
    }

    
Utils.extend(ev, {
      
deltaTimedelta_time,

      
deltaXdelta_x,
      
deltaYdelta_y,

      
velocityXvelocity.x,
      
velocityYvelocity.y,

      
distanceUtils.getDistance(startEv.centerev.center),

      
angleUtils.getAngle(startEv.centerev.center),
      
interimAngleinterimAngle,

      
directionUtils.getDirection(startEv.centerev.center),
      
interimDirectioninterimDirection,

      
scaleUtils.getScale(startEv.touchesev.touches),
      
rotationUtils.getRotation(startEv.touchesev.touches),

      
startEventstartEv
    
});

    return 
ev;
  },


  
/**
   * register new gesture
   * @param   {Object}    gesture object, see gestures.js for documentation
   * @returns {Array}     gestures
   */
  
register: function register(gesture) {
    
// add an enable gesture options if there is no given
    
var options gesture.defaults || {};
    if(
options[gesture.name] === undefined) {
      
options[gesture.name] = true;
    }

    
// extend Hammer default options with the Hammer.gesture options
    
Utils.extend(Hammer.defaultsoptionstrue);

    
// set its index
    
gesture.index gesture.index || 1000;

    
// add Hammer.gesture to the list
    
this.gestures.push(gesture);

    
// sort the list by index
    
this.gestures.sort(function(ab) {
      if(
a.index b.index) { return -1; }
      if(
a.index b.index) { return 1; }
      return 
0;
    });

    return 
this.gestures;
  }
};


/**
 * Drag
 * Move with x fingers (default 1) around on the page. Blocking the scrolling when
 * moving left and right is a good practice. When all the drag events are blocking
 * you disable scrolling on that area.
 * @events  drag, drapleft, dragright, dragup, dragdown
 */
Hammer.gestures.Drag = {
  
name     'drag',
  
index    50,
  
defaults : {
    
drag_min_distance            10,

    
// Set correct_for_drag_min_distance to true to make the starting point of the drag
    // be calculated from where the drag was triggered, not from where the touch started.
    // Useful to avoid a jerk-starting drag, which can make fine-adjustments
    // through dragging difficult, and be visually unappealing.
    
correct_for_drag_min_distancetrue,

    
// set 0 for unlimited, but this can conflict with transform
    
drag_max_touches             1,

    
// prevent default browser behavior when dragging occurs
    // be careful with it, it makes the element a blocking element
    // when you are using the drag gesture, it is a good practice to set this true
    
drag_block_horizontal        false,
    
drag_block_vertical          false,

    
// drag_lock_to_axis keeps the drag gesture on the axis that it started on,
    // It disallows vertical directions if the initial direction was horizontal, and vice versa.
    
drag_lock_to_axis            false,

    
// drag lock only kicks in when distance > drag_lock_min_distance
    // This way, locking occurs only when the distance has become large enough to reliably determine the direction
    
drag_lock_min_distance       25
  
},

  
triggeredfalse,
  
handler  : function dragGesture(evinst) {
    
// current gesture isnt drag, but dragged is true
    // this means an other gesture is busy. now call dragend
    
if(Detection.current.name != this.name && this.triggered) {
      
inst.trigger(this.name 'end'ev);
      
this.triggered false;
      return;
    }

    
// max touches
    
if(inst.options.drag_max_touches &&
      
ev.touches.length inst.options.drag_max_touches) {
      return;
    }

    switch(
ev.eventType) {
      case 
EVENT_START:
        
this.triggered false;
        break;

      case 
EVENT_MOVE:
        
// when the distance we moved is too small we skip this gesture
        // or we can be already in dragging
        
if(ev.distance inst.options.drag_min_distance &&
          
Detection.current.name != this.name) {
          return;
        }

        
// we are dragging!
        
if(Detection.current.name != this.name) {
          
Detection.current.name this.name;
          if(
inst.options.correct_for_drag_min_distance && ev.distance 0) {
            
// When a drag is triggered, set the event center to drag_min_distance pixels from the original event center.
            // Without this correction, the dragged distance would jumpstart at drag_min_distance pixels instead of at 0.
            // It might be useful to save the original start point somewhere
            
var factor Math.abs(inst.options.drag_min_distance ev.distance);
            
Detection.current.startEvent.center.pageX += ev.deltaX factor;
            
Detection.current.startEvent.center.pageY += ev.deltaY factor;

            
// recalculate event data using new start point
            
ev Detection.extendEventData(ev);
          }
        }

        
// lock drag to axis?
        
if(Detection.current.lastEvent.drag_locked_to_axis ||
            ( 
inst.options.drag_lock_to_axis &&
              
inst.options.drag_lock_min_distance <= ev.distance
            
)) {
          
ev.drag_locked_to_axis true;
        }
        var 
last_direction Detection.current.lastEvent.direction;
        if(
ev.drag_locked_to_axis && last_direction !== ev.direction) {
          
// keep direction on the axis that the drag gesture started on
          
if(Utils.isVertical(last_direction)) {
            
ev.direction = (ev.deltaY 0) ? DIRECTION_UP DIRECTION_DOWN;
          }
          else {
            
ev.direction = (ev.deltaX 0) ? DIRECTION_LEFT DIRECTION_RIGHT;
          }
        }

        
// first time, trigger dragstart event
        
if(!this.triggered) {
          
inst.trigger(this.name 'start'ev);
          
this.triggered true;
        }

        
// trigger events
        
inst.trigger(this.nameev);
        
inst.trigger(this.name ev.directionev);

        var 
is_vertical Utils.isVertical(ev.direction);

        
// block the browser events
        
if((inst.options.drag_block_vertical && is_vertical) ||
          (
inst.options.drag_block_horizontal && !is_vertical)) {
          
ev.preventDefault();
        }
        break;

      case 
EVENT_END:
        
// trigger dragend
        
if(this.triggered) {
          
inst.trigger(this.name 'end'ev);
        }

        
this.triggered false;
        break;
    }
  }
};

/**
 * Hold
 * Touch stays at the same place for x time
 * @events  hold
 */
Hammer.gestures.Hold = {
  
name    'hold',
  
index   10,
  
defaults: {
    
hold_timeout  500,
    
hold_threshold1
  
},
  
timer   null,

  
handler : function holdGesture(evinst) {
    switch(
ev.eventType) {
      case 
EVENT_START:
        
// clear any running timers
        
clearTimeout(this.timer);

        
// set the gesture so we can check in the timeout if it still is
        
Detection.current.name this.name;

        
// set timer and if after the timeout it still is hold,
        // we trigger the hold event
        
this.timer setTimeout(function() {
          if(
Detection.current.name == 'hold') {
            
inst.trigger('hold'ev);
          }
        }, 
inst.options.hold_timeout);
        break;

      
// when you move or end we clear the timer
      
case EVENT_MOVE:
        if(
ev.distance inst.options.hold_threshold) {
          
clearTimeout(this.timer);
        }
        break;

      case 
EVENT_END:
        
clearTimeout(this.timer);
        break;
    }
  }
};

/**
 * Release
 * Called as last, tells the user has released the screen
 * @events  release
 */
Hammer.gestures.Release = {
  
name   'release',
  
index  Infinity,
  
handler: function releaseGesture(evinst) {
    if(
ev.eventType == EVENT_END) {
      
inst.trigger(this.nameev);
    }
  }
};

/**
 * Swipe
 * triggers swipe events when the end velocity is above the threshold
 * for best usage, set prevent_default (on the drag gesture) to true
 * @events  swipe, swipeleft, swiperight, swipeup, swipedown
 */
Hammer.gestures.Swipe = {
  
name    'swipe',
  
index   40,
  
defaults: {
    
swipe_min_touches1,
    
swipe_max_touches1,
    
swipe_velocity   0.7
  
},
  
handler : function swipeGesture(evinst) {
    if(
ev.eventType == EVENT_END) {
      
// max touches
      
if(ev.touches.length inst.options.swipe_min_touches ||
        
ev.touches.length inst.options.swipe_max_touches) {
        return;
      }

      
// when the distance we moved is too small we skip this gesture
      // or we can be already in dragging
      
if(ev.velocityX inst.options.swipe_velocity ||
        
ev.velocityY inst.options.swipe_velocity) {
        
// trigger swipe events
        
inst.trigger(this.nameev);
        
inst.trigger(this.name ev.directionev);
      }
    }
  }
};

/**
 * Tap/DoubleTap
 * Quick touch at a place or double at the same place
 * @events  tap, doubletap
 */
Hammer.gestures.Tap = {
  
name    'tap',
  
index   100,
  
defaults: {
    
tap_max_touchtime 250,
    
tap_max_distance  10,
    
tap_always        true,
    
doubletap_distance20,
    
doubletap_interval300
  
},

  
has_movedfalse,

  
handler : function tapGesture(evinst) {
    var 
prevsince_prevdid_doubletap;

    
// reset moved state
    
if(ev.eventType == EVENT_START) {
      
this.has_moved false;
    }

    
// Track the distance we've moved. If it's above the max ONCE, remember that (fixes #406).
    
else if(ev.eventType == EVENT_MOVE && !this.moved) {
      
this.has_moved = (ev.distance inst.options.tap_max_distance);
    }

    else if(
ev.eventType == EVENT_END &&
        
ev.srcEvent.type != 'touchcancel' &&
        
ev.deltaTime inst.options.tap_max_touchtime && !this.has_moved) {

      
// previous gesture, for the double tap since these are two different gesture detections
      
prev Detection.previous;
      
since_prev prev && prev.lastEvent && ev.timeStamp prev.lastEvent.timeStamp;
      
did_doubletap false;

      
// check if double tap
      
if(prev && prev.name == 'tap' &&
          (
since_prev && since_prev inst.options.doubletap_interval) &&
          
ev.distance inst.options.doubletap_distance) {
        
inst.trigger('doubletap'ev);
        
did_doubletap true;
      }

      
// do a single tap
      
if(!did_doubletap || inst.options.tap_always) {
        
Detection.current.name 'tap';
        
inst.trigger(Detection.current.nameev);
      }
    }
  }
};

/**
 * Touch
 * Called as first, tells the user has touched the screen
 * @events  touch
 */
Hammer.gestures.Touch = {
  
name    'touch',
  
index   : -Infinity,
  
defaults: {
    
// call preventDefault at touchstart, and makes the element blocking by
    // disabling the scrolling of the page, but it improves gestures like
    // transforming and dragging.
    // be careful with using this, it can be very annoying for users to be stuck
    // on the page
    
prevent_default    false,

    
// disable mouse events, so only touch (or pen!) input triggers events
    
prevent_mouseeventsfalse
  
},
  
handler : function touchGesture(evinst) {
    if(
inst.options.prevent_mouseevents &&
        
ev.pointerType == POINTER_MOUSE) {
      
ev.stopDetect();
      return;
    }

    if(
inst.options.prevent_default) {
      
ev.preventDefault();
    }

    if(
ev.eventType == EVENT_START) {
      
inst.trigger(this.nameev);
    }
  }
};


/**
 * Transform
 * User want to scale or rotate with 2 fingers
 * @events  transform, pinch, pinchin, pinchout, rotate
 */
Hammer.gestures.Transform = {
  
name     'transform',
  
index    45,
  
defaults : {
    
// factor, no scale is 1, zoomin is to 0 and zoomout until higher then 1
    
transform_min_scale      0.01,
    
// rotation in degrees
    
transform_min_rotation   1,
    
// prevent default browser behavior when two touches are on the screen
    // but it makes the element a blocking element
    // when you are using the transform gesture, it is a good practice to set this true
    
transform_always_block   false,
    
// ensures that all touches occurred within the instance element
    
transform_within_instancefalse
  
},

  
triggeredfalse,

  
handler  : function transformGesture(evinst) {
    
// current gesture isnt drag, but dragged is true
    // this means an other gesture is busy. now call dragend
    
if(Detection.current.name != this.name && this.triggered) {
      
inst.trigger(this.name 'end'ev);
      
this.triggered false;
      return;
    }

    
// at least multitouch
    
if(ev.touches.length 2) {
      return;
    }

    
// prevent default when two fingers are on the screen
    
if(inst.options.transform_always_block) {
      
ev.preventDefault();
    }

    
// check if all touches occurred within the instance element
    
if(inst.options.transform_within_instance) {
      for(var 
i=-1ev.touches[++i];) {
        if(!
Utils.hasParent(ev.touches[i].targetinst.element)) {
          return;
        }
      }
    }

    switch(
ev.eventType) {
      case 
EVENT_START:
        
this.triggered false;
        break;

      case 
EVENT_MOVE:
        var 
scale_threshold Math.abs(ev.scale);
        var 
rotation_threshold Math.abs(ev.rotation);

        
// when the distance we moved is too small we skip this gesture
        // or we can be already in dragging
        
if(scale_threshold inst.options.transform_min_scale &&
          
rotation_threshold inst.options.transform_min_rotation) {
          return;
        }

        
// we are transforming!
        
Detection.current.name this.name;

        
// first time, trigger dragstart event
        
if(!this.triggered) {
          
inst.trigger(this.name 'start'ev);
          
this.triggered true;
        }

        
inst.trigger(this.nameev); // basic transform event

        // trigger rotate event
        
if(rotation_threshold inst.options.transform_min_rotation) {
          
inst.trigger('rotate'ev);
        }

        
// trigger pinch event
        
if(scale_threshold inst.options.transform_min_scale) {
          
inst.trigger('pinch'ev);
          
inst.trigger('pinch' + (ev.scale<'in' 'out'), ev);
        }
        break;

      case 
EVENT_END:
        
// trigger dragend
        
if(this.triggered) {
          
inst.trigger(this.name 'end'ev);
        }

        
this.triggered false;
        break;
    }
  }
};

// AMD export
if(typeof define == 'function' && define.amd) {
  
define(function(){
    return 
Hammer;
  });
}
// commonjs export
else if(typeof module == 'object' && module.exports) {
  
module.exports Hammer;
}
// browser export
else {
  
window.Hammer Hammer;
}

})(
window);
?>
Онлайн: 2
Реклама