Updates the finger data for a particular event object
@param {object} evt The event object containing the touch/finger data to upadte
@return a finger data object.
@inner
500926
function updateFingerData(evt) {
			
			var id = evt.identifier!==undefined ? evt.identifier : 0; 
			var f = getFingerData( id );
			
			f.end.x = evt.pageX||evt.clientX;
			f.end.y = evt.pageY||evt.clientY;
			
			return f;
		}
33154
function collectEventData(element, eventType, touches, ev) {

      // find out pointerType
      var pointerType = ionic.Gestures.POINTER_TOUCH;
      if(ev.type.match(/mouse/) || ionic.Gestures.PointerEvent.matchType(ionic.Gestures.POINTER_MOUSE, ev)) {
        pointerType = ionic.Gestures.POINTER_MOUSE;
      }

      return {
        center: ionic.Gestures.utils.getCenter(touches),
        timeStamp: new Date().getTime(),
        target: ev.target,
        touches: touches,
        eventType: eventType,
        pointerType: pointerType,
        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 ionic.Gestures.detection.stopDetect();
        }
      };
    }
29120
function getActiveTouches(mouseEv, eventName) {
        // empty list
        if (mouseEv.type == 'mouseup') {
            return new TouchList();
        }

        var touchList = createTouchList(mouseEv);
        if(isMultiTouch && mouseEv.type != 'mouseup' && eventName == 'touchend') {
            touchList.splice(1, 1);
        }
        return touchList;
    }
1002312
function getEventPoint(ev) {
  ev = ev.originalEvent || ev; // support jQuery events
  return (ev.touches && ev.touches[0]) ||
    (ev.changedTouches && ev.changedTouches[0]) ||
    ev;
}
845009
function(event) {
		
		if (this._touchIsTouchEvent(event)) {
			event.time = new Date().getTime();
			this.__touchEvents.push(event);
		}
		
		return this;
	}
780636
function(evt) {
		if (canvas.spaceKey || evt.button === 1) {return;}

		var right_click = evt.button === 2;
	
		if (evt.altKey) { // duplicate when dragging
			svgCanvas.cloneSelectedElements(0, 0);
		}
	
		root_sctm = $('#svgcontent g')[0].getScreenCTM().inverse();
		
		var pt = svgedit.math.transformPoint( evt.pageX, evt.pageY, root_sctm ),
			mouse_x = pt.x * current_zoom,
			mouse_y = pt.y * current_zoom;
			
		evt.preventDefault();

		if (right_click) {
			current_mode = "select";
			lastClickPoint = pt;
		}
		
		// This would seem to be unnecessary...
//		if (['select', 'resize'].indexOf(current_mode) == -1) {
//			setGradient();
//		}
		
		var x = mouse_x / current_zoom,
			y = mouse_y / current_zoom,
			mouse_target = getMouseTarget(evt);
		
		if (mouse_target.tagName === 'a' && mouse_target.childNodes.length === 1) {
			mouse_target = mouse_target.firstChild;
		}
		
		// real_x/y ignores grid-snap value
		var real_x = x;
		r_start_x = start_x = x;
		var real_y = y;
		r_start_y = start_y = y;

		if (curConfig.gridSnapping){
			x = svgedit.utilities.snapToGrid(x);
			y = svgedit.utilities.snapToGrid(y);
			start_x = svgedit.utilities.snapToGrid(start_x);
			start_y = svgedit.utilities.snapToGrid(start_y);
		}

		// if it is a selector grip, then it must be a single element selected, 
		// set the mouse_target to that and update the mode to rotate/resize
		
		if (mouse_target == selectorManager.selectorParentGroup && selectedElements[0] != null) {
			var grip = evt.target;
			var griptype = elData(grip, "type");
			// rotating
			if (griptype == "rotate") {
				current_mode = "rotate";
			}
			// resizing
			else if (griptype == "resize") {
				current_mode = "resize";
				current_resize_mode = elData(grip, "dir");
			}
			mouse_target = selectedElements[0];
		}
		
		startTransform = mouse_target.getAttribute("transform");
		var i, stroke_w,
			tlist = svgedit.transformlist.getTransformList(mouse_target);
		switch (current_mode) {
			case "select":
				started = true;
				current_resize_mode = "none";
				if (right_click) {started = false;}
				
				if (mouse_target != svgroot) {
					// if this element is not yet selected, clear selection and select it
					if (selectedElements.indexOf(mouse_target) == -1) {
						// only clear selection if shift is not pressed (otherwise, add 
						// element to selection)
						if (!evt.shiftKey) {
							// No need to do the call here as it will be done on addToSelection
							clearSelection(true);
						}
						addToSelection([mouse_target]);
						justSelected = mouse_target;
						pathActions.clear();
					}
					// else if it's a path, go into pathedit mode in mouseup
					
					if (!right_click) {
						// insert a dummy transform so if the element(s) are moved it will have
						// a transform to use for its translate
						for (i = 0; i < selectedElements.length; ++i) {
							if (selectedElements[i] == null) {continue;}
							var slist = svgedit.transformlist.getTransformList(selectedElements[i]);
							if (slist.numberOfItems) {
								slist.insertItemBefore(svgroot.createSVGTransform(), 0);
							} else {
								slist.appendItem(svgroot.createSVGTransform());
							}
						}
					}
				} else if (!right_click){
					clearSelection();
					current_mode = "multiselect";
					if (rubberBox == null) {
						rubberBox = selectorManager.getRubberBandBox();
					}
					r_start_x *= current_zoom;
					r_start_y *= current_zoom;
//					console.log('p',[evt.pageX, evt.pageY]);					
//					console.log('c',[evt.clientX, evt.clientY]);	
//					console.log('o',[evt.offsetX, evt.offsetY]);	
//					console.log('s',[start_x, start_y]);
					
					svgedit.utilities.assignAttributes(rubberBox, {
						'x': r_start_x,
						'y': r_start_y,
						'width': 0,
						'height': 0,
						'display': 'inline'
					}, 100);
				}
				break;
			case "zoom": 
				started = true;
				if (rubberBox == null) {
					rubberBox = selectorManager.getRubberBandBox();
				}
				svgedit.utilities.assignAttributes(rubberBox, {
						'x': real_x * current_zoom,
						'y': real_x * current_zoom,
						'width': 0,
						'height': 0,
						'display': 'inline'
				}, 100);
				break;
			case "resize":
				started = true;
				start_x = x;
				start_y = y;
				
				// Getting the BBox from the selection box, since we know we
				// want to orient around it
				init_bbox = svgedit.utilities.getBBox($('#selectedBox0')[0]);
				var bb = {};
				$.each(init_bbox, function(key, val) {
					bb[key] = val/current_zoom;
				});
				init_bbox = bb;
				
				// append three dummy transforms to the tlist so that
				// we can translate,scale,translate in mousemove
				var pos = svgedit.utilities.getRotationAngle(mouse_target) ? 1 : 0;
				
				if (svgedit.math.hasMatrixTransform(tlist)) {
					tlist.insertItemBefore(svgroot.createSVGTransform(), pos);
					tlist.insertItemBefore(svgroot.createSVGTransform(), pos);
					tlist.insertItemBefore(svgroot.createSVGTransform(), pos);
				} else {
					tlist.appendItem(svgroot.createSVGTransform());
					tlist.appendItem(svgroot.createSVGTransform());
					tlist.appendItem(svgroot.createSVGTransform());
					
					if (svgedit.browser.supportsNonScalingStroke()) {
						// Handle crash for newer Chrome and Safari 6 (Mobile and Desktop): 
						// https://code.google.com/p/svg-edit/issues/detail?id=904
						// Chromium issue: https://code.google.com/p/chromium/issues/detail?id=114625
						// TODO: Remove this workaround once vendor fixes the issue
						var isWebkit = svgedit.browser.isWebkit();

						if (isWebkit) {
							var delayedStroke = function(ele) {
								var _stroke = ele.getAttributeNS(null, 'stroke');
								ele.removeAttributeNS(null, 'stroke');
								//Re-apply stroke after delay. Anything higher than 1 seems to cause flicker
								setTimeout(function() { ele.setAttributeNS(null, 'stroke', _stroke); }, 0);
							};
						}
						mouse_target.style.vectorEffect = 'non-scaling-stroke';
						if (isWebkit) {delayedStroke(mouse_target);}

						var all = mouse_target.getElementsByTagName('*'),
							len = all.length;
						for (i = 0; i < len; i++) {
							all[i].style.vectorEffect = 'non-scaling-stroke';
							if (isWebkit) {delayedStroke(all[i]);}
						}
					}
				}
				break;
			case "fhellipse":
			case "fhrect":
			case "fhpath":
				start.x = real_x;
				start.y = real_y;
				started = true;
				d_attr = real_x + "," + real_y + " ";
				stroke_w = cur_shape.stroke_width == 0 ? 1 : cur_shape.stroke_width;
				addSvgElementFromJson({
					"element": "polyline",
					"curStyles": true,
					"attr": {
						"points": d_attr,
						"id": getNextId(),
						"fill": "none",
						"opacity": cur_shape.opacity / 2,
						"stroke-linecap": "round",
						"style": "pointer-events:none"
					}
				});
				freehand.minx = real_x;
				freehand.maxx = real_x;
				freehand.miny = real_y;
				freehand.maxy = real_y;
				break;
			case "image":
				started = true;
				var newImage = addSvgElementFromJson({
					"element": "image",
					"attr": {
						"x": x,
						"y": y,
						"width": 0,
						"height": 0,
						"id": getNextId(),
						"opacity": cur_shape.opacity / 2,
						"style": "pointer-events:inherit"
					}
				});
				setHref(newImage, last_good_img_url);
				preventClickDefault(newImage);
				break;
			case "square":
				// FIXME: once we create the rect, we lose information that this was a square
				// (for resizing purposes this could be important)
			case "rect":
				started = true;
				start_x = x;
				start_y = y;
				addSvgElementFromJson({
					"element": "rect",
					"curStyles": true,
					"attr": {
						"x": x,
						"y": y,
						"width": 0,
						"height": 0,
						"id": getNextId(),
						"opacity": cur_shape.opacity / 2
					}
				});
				break;
			case "line":
				started = true;
				stroke_w = cur_shape.stroke_width == 0 ? 1 : cur_shape.stroke_width;
				addSvgElementFromJson({
					"element": "line",
					"curStyles": true,
					"attr": {
						"x1": x,
						"y1": y,
						"x2": x,
						"y2": y,
						"id": getNextId(),
						"stroke": cur_shape.stroke,
						"stroke-width": stroke_w,
						"stroke-dasharray": cur_shape.stroke_dasharray,
						"stroke-linejoin": cur_shape.stroke_linejoin,
						"stroke-linecap": cur_shape.stroke_linecap,
						"stroke-opacity": cur_shape.stroke_opacity,
						"fill": "none",
						"opacity": cur_shape.opacity / 2,
						"style": "pointer-events:none"
					}
				});
				break;
			case "circle":
				started = true;
				addSvgElementFromJson({
					"element": "circle",
					"curStyles": true,
					"attr": {
						"cx": x,
						"cy": y,
						"r": 0,
						"id": getNextId(),
						"opacity": cur_shape.opacity / 2
					}
				});
				break;
			case "ellipse":
				started = true;
				addSvgElementFromJson({
					"element": "ellipse",
					"curStyles": true,
					"attr": {
						"cx": x,
						"cy": y,
						"rx": 0,
						"ry": 0,
						"id": getNextId(),
						"opacity": cur_shape.opacity / 2
					}
				});
				break;
			case "text":
				started = true;
				var newText = addSvgElementFromJson({
					"element": "text",
					"curStyles": true,
					"attr": {
						"x": x,
						"y": y,
						"id": getNextId(),
						"fill": cur_text.fill,
						"stroke-width": cur_text.stroke_width,
						"font-size": cur_text.font_size,
						"font-family": cur_text.font_family,
						"text-anchor": "middle",
						"xml:space": "preserve",
						"opacity": cur_shape.opacity
					}
				});
//					newText.textContent = "text";
				break;
			case "path":
				// Fall through
			case "pathedit":
				start_x *= current_zoom;
				start_y *= current_zoom;
				pathActions.mouseDown(evt, mouse_target, start_x, start_y);
				started = true;
				break;
			case "textedit":
				start_x *= current_zoom;
				start_y *= current_zoom;
				textActions.mouseDown(evt, mouse_target, start_x, start_y);
				started = true;
				break;
			case "rotate":
				started = true;
				// we are starting an undoable change (a drag-rotation)
				canvas.undoMgr.beginUndoableChange("transform", selectedElements);
				break;
			default:
				// This could occur in an extension
				break;
		}
		
		var ext_result = runExtensions("mouseDown", {
			event: evt,
			start_x: start_x,
			start_y: start_y,
			selectedElements: selectedElements
		}, true);
		
		$.each(ext_result, function(i, r) {
			if (r && r.started) {
				started = true;
			}
		});
	}
1227393
function () {
        return $(this).bind ('touchstart', function preventZoom (e) {
            var t2 = e.timeStamp
            var t1 = $(this).data ('lastTouch') || t2
            var dt = t2 - t1
            var fingers = e.originalEvent.touches.length
            $(this).data ('lastTouch', t2)
            if (!dt || dt > 500 || fingers > 1) {
                return } // not double-tap
            e.preventDefault ()                     // double tap - prevent the zoom
            $(e.target).trigger ('click') }) }
1303227
function(evt) {
        evt.preventDefault();
        evt.stopPropagation();
        if (debug) { timedLog("endSecondFinger"); }
        if (evt.touches.length > 1) {
          if (debug) { timedLog("endSecondFinger - capped"); }
          return true;
        }
        if (debug) { timedLog("endSecondFinger - continued"); }
        handlers.startmark(evt);
        // If there are no fingers left on the screen,
        // we have not finished the handling
        return evt.touches.length !== 0;
      }
1346631
function (evt) {
    var direction;
    var canvas = this.el.sceneEl.canvas;
    var deltaY;
    var yawObject = this.yawObject;

    if (!this.touchStarted || !this.data.touchEnabled) { return; }

    deltaY = 2 * Math.PI * (evt.touches[0].pageX - this.touchStart.x) / canvas.clientWidth;

    direction = this.data.reverseTouchDrag ? 1 : -1;
    // Limit touch orientaion to to yaw (y axis).
    yawObject.rotation.y -= deltaY * 0.5 * direction;
    this.touchStart = {
      x: evt.touches[0].pageX,
      y: evt.touches[0].pageY
    };
  }
1170090
function(evt) {
        if (this.passesTolerance(evt)) {
            if (this.timerId != null) {
                // already received a click
                if (this.last.touches && this.last.touches.length === 1) {
                    // touch device, no dblclick event - this may be a double
                    if (this["double"]) {
                        // on Android don't let the browser zoom on the page
                        OpenLayers.Event.preventDefault(evt);
                    }
                    this.handleDouble(evt);
                }
                // if we're not in a touch environment we clear the click timer
                // if we've got a second touch, we'll get two touchend events
                if (!this.last.touches || this.last.touches.length !== 2) {
                    this.clearTimer();
                }
            } else {
                // remember the first click info so we can compare to the second
                this.first = this.getEventInfo(evt);
                // set the timer, send evt only if single is true
                //use a clone of the event object because it will no longer 
                //be a valid event object in IE in the timer callback
                var clickEvent = this.single ?
                    OpenLayers.Util.extend({}, evt) : null;
                this.queuePotentialClick(clickEvent);
            }
        }
    }
427753
function(evt) {
        this.mouseDown = true;
        this.lastDown = evt.xy;
        if(!this.touch) { // no point displayed until up on touch devices
            this.modifyFeature(evt.xy);
        }
        this.stoppedDown = this.stopDown;
        return !this.stopDown;
    }
1249615
function (evt) {
            if (evt.type === "tap") {
                var cfg = this._cfg;
                if (!cfg) {
                    // Widget already disposed
                    return true;
                }

                if ((cfg.tapToToggle || cfg.tapToMove) && this._isSwitch) {
                    // With this configuration, on tap we want to toggle the value
                    this._value = this._value >= this._switchThreshold ? 0 : 1;
                } else if (cfg.tapToMove) {
                    this._savedX = evt.detail.currentX - this._sliderDimension.x - this._sliderWidth / 2;
                    this._savedX = (this._savedX > this._railWidth) ? this._railWidth : this._savedX;
                    this._value = Math.max(this._savedX / this._railWidth, 0);
                }
                this._storeValue();
                this._setLeftPosition();
                this._updateDisplay();
            }
        }
600845
function touchMove(jqEvent) {
			
			//As we use Jquery bind for events, we need to target the original event object
			//If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
			var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
			
			//If we are ending, cancelling, or within the threshold of 2 fingers being released, don't track anything..
			if (phase === PHASE_END || phase === PHASE_CANCEL || inMultiFingerRelease())
				return;

			var ret,
				touches = event.touches,
				evt = touches ? touches[0] : event;
			

			//Update the  finger data 
			var currentFinger = updateFingerData(evt);
			endTime = getTimeStamp();
			
			if (touches) {
				fingerCount = touches.length;
			}

			if (options.hold)
				clearTimeout(holdTimeout);

			phase = PHASE_MOVE;

			//If we have 2 fingers get Touches distance as well
			if(fingerCount==2) {
				
				//Keep track of the initial pinch distance, so we can calculate the diff later
				//We do this here as well as the start event, in case they start with 1 finger, and the press 2 fingers
				if(startTouchesDistance==0) {
					//Create second finger if this is the first time...
					createFingerData( 1, touches[1] );
					
					startTouchesDistance = endTouchesDistance = calculateTouchesDistance(fingerData[0].start, fingerData[1].start);
				} else {
					//Else just update the second finger
					updateFingerData(touches[1]);
				
					endTouchesDistance = calculateTouchesDistance(fingerData[0].end, fingerData[1].end);
					pinchDirection = calculatePinchDirection(fingerData[0].end, fingerData[1].end);
				}
				
				
				pinchZoom = calculatePinchZoom(startTouchesDistance, endTouchesDistance);
				pinchDistance = Math.abs(startTouchesDistance - endTouchesDistance);
			}
			
			
			

			if ( (fingerCount === options.fingers || options.fingers === ALL_FINGERS) || !touches || hasPinches() ) {
				
				direction = calculateDirection(currentFinger.start, currentFinger.end);
				
				//Check if we need to prevent default event (page scroll / pinch zoom) or not
				validateDefaultEvent(jqEvent, direction);

				//Distance and duration are all off the main finger
				distance = calculateDistance(currentFinger.start, currentFinger.end);
				duration = calculateDuration();

                //Cache the maximum distance we made in this direction
                setMaxDistance(direction, distance);


				if (options.swipeStatus || options.pinchStatus) {
					ret = triggerHandler(event, phase);
				}
				
				
				//If we trigger end events when threshold are met, or trigger events when touch leaves element
				if(!options.triggerOnTouchEnd || options.triggerOnTouchLeave) {
					
					var inBounds = true;
					
					//If checking if we leave the element, run the bounds check (we can use touchleave as its not supported on webkit)
					if(options.triggerOnTouchLeave) {
						var bounds = getbounds( this );
						inBounds = isInBounds( currentFinger.end, bounds );
					}
					
					//Trigger end handles as we swipe if thresholds met or if we have left the element if the user has asked to check these..
					if(!options.triggerOnTouchEnd && inBounds) {
						phase = getNextPhase( PHASE_MOVE );
					} 
					//We end if out of bounds here, so set current phase to END, and check if its modified 
					else if(options.triggerOnTouchLeave && !inBounds ) {
						phase = getNextPhase( PHASE_END );
					}
						
					if(phase==PHASE_CANCEL || phase==PHASE_END)	{
						triggerHandler(event, phase);
					}				
				}
			}
			else {
				phase = PHASE_CANCEL;
				triggerHandler(event, phase);
			}

			if (ret === false) {
				phase = PHASE_CANCEL;
				triggerHandler(event, phase);
			}
		}
1223464
function (evt) {
                var event = new ariaDomEvent(evt);

                connectMouseEvents(this);

                if (evt.type === "touchstart") {
                    // The position of touch events is not determined correctly by clientX/Y
                    var elementPosition = ariaTouchEvent.getPositions(event);
                    event.clientX = elementPosition[0].x;
                    event.clientY = elementPosition[0].y;
                }

                if (this._detectDrag(event)) {
                    event.preventDefault(true);
                }

                event.$dispose();
                return false;
            }
788188
function (evt) {
    var threshold = 30;
    if (!this.pressed) {
      this.pressed = true;
      this.emit('touchdown');
      var self = this;
      this.interval = setInterval(function() {
        var delta = performance.now() - self.lastTime;
        if (delta > threshold) {
          self.pressed = false;
          self.lastTime = 0;
          self.emit('touchup');
          clearInterval(self.interval);
        }
      }, threshold);
    }
    this.lastTime = performance.now();
  }
1217793
function (evt) {
    if (evt.touches.length !== 1 || !this.data.touchEnabled) { return; }
    this.touchStart = {
      x: evt.touches[0].pageX,
      y: evt.touches[0].pageY
    };
    this.touchStarted = true;
  }
337879
function FakeTouches(element) {
        this.element = element;

        this.touches = [];
        this.touch_type = FakeTouches.TOUCH_EVENTS;
        this.has_multitouch = true;
    }