API Docs for:
Show:

File: touch.js

/*******************************************************************************
 * Copyright (c) 2017 Genialist Software Ltd.
 * All rights reserved.
 ******************************************************************************/

// TOUCH-EVENTS SINGLE-FINGER SWIPE-SENSING JAVASCRIPT
// Courtesy of PADILICIOUS.COM and MACOSXAUTOMATION.COM

// this script can be used with one or more page elements to perform actions based on them being swiped with a single finger

function pTouchInstance(id) {
	var that = this;
	
	this.id = id;
	
	this.triggerElementID = null; // this variable is used to identity the triggering element
	this.fingerCount = 0;
	this.startX = 0;
	this.startY = 0;
	this.curX = 0;
	this.curY = 0;
	this.deltaX = 0;
	this.deltaY = 0;
	this.horzDiff = 0;
	this.vertDiff = 0;
	this.minLength = 72; // the shortest distance the user may swipe
	this.swipeLength = 0;
	this.swipeAngle = null;
	this.swipeDirection = null;

// The 4 Touch Event Handlers

// NOTE: the touchStart handler should also receive the ID of the triggering element
// make sure its ID is passed in the event call placed in the element declaration, like:
// <div id="	picture-frame" ontouchstart="touchStart(event,'picture-frame');"  ontouchend="touchEnd(event);" ontouchmove="touchMove(event);" ontouchcancel="touchCancel(event);">

	this.touchStart = function(event,passedName) {
		// disable the standard ability to select the touched object
		//event.preventDefault();
		
		// get the total number of fingers touching the screen
		that.fingerCount = event.touches.length;
		// since we're looking for a swipe (single finger) and not a gesture (multiple fingers),
		// check that only one finger was used
		if ( that.fingerCount == 1 ) {
			// get the coordinates of the touch
			that.startX = event.touches[0].pageX;
			that.startY = event.touches[0].pageY;
			// store the triggering element ID
			that.triggerElementID = passedName;
		} else {
			// more than one finger touched so cancel
			that.touchCancel(event);
		}
	};

	this.touchMove = function(event) {
		//event.preventDefault();
		
		if ( event.touches.length == 1 ) {
			that.curX = event.touches[0].pageX;
			that.curY = event.touches[0].pageY;
		} else {
			that.touchCancel(event);
		}
	};

	this.touchEnd = function(event) {
		//event.preventDefault();
		// check to see if more than one finger was used and that there is an ending coordinate
		if ( that.fingerCount == 1 && that.curX != 0 ) {
			// use the Distance Formula to determine the length of the swipe
			that.swipeLength = Math.round(Math.sqrt(Math.pow(that.curX - that.startX,2) + Math.pow(that.curY - that.startY,2)));
			// if the user swiped more than the minimum length, perform the appropriate action
			
			//alert("length: " + swipeLength);
			
			if ( that.swipeLength >= that.minLength ) {
				event.preventDefault();
				
				that.caluculateAngle();
				that.determineSwipeDirection();
				that.processingRoutine(event);
				that.touchCancel(event); // reset the variables
			} else {
				that.touchCancel(event);
			}
		} else {
			that.touchCancel(event);
		}
	};

	this.touchCancel = function(event) {
		// reset the variables back to default values
		that.fingerCount = 0;
		that.startX = 0;
		that.startY = 0;
		that.curX = 0;
		that.curY = 0;
		that.deltaX = 0;
		that.deltaY = 0;
		that.horzDiff = 0;
		that.vertDiff = 0;
		that.swipeLength = 0;
		that.swipeAngle = null;
		that.swipeDirection = null;
		that.triggerElementID = null;
	};

	this.caluculateAngle = function() {
		var X = that.startX-that.curX;
		var Y = that.curY-that.startY;
		var Z = Math.round(Math.sqrt(Math.pow(X,2)+Math.pow(Y,2))); //the distance - rounded - in pixels
		var r = Math.atan2(Y,X); //angle in radians (Cartesian system)
		that.swipeAngle = Math.round(r*180/Math.PI); //angle in degrees
		if ( that.swipeAngle < 0 ) { that.swipeAngle =  360 - Math.abs(that.swipeAngle); }
	};

	this.determineSwipeDirection = function() {
		if ( (that.swipeAngle <= 45) && (that.swipeAngle >= 0) ) {
			that.swipeDirection = 'left';
		} else if ( (that.swipeAngle <= 360) && (that.swipeAngle >= 315) ) {
			that.swipeDirection = 'left';
		} else if ( (that.swipeAngle >= 135) && (that.swipeAngle <= 225) ) {
			that.swipeDirection = 'right';
		} else if ( (that.swipeAngle > 45) && (that.swipeAngle < 135) ) {
			that.swipeDirection = 'down';
		} else {
			that.swipeDirection = 'up';
		}
	};

	this.processingRoutine = function(e) {
		//var swipedElement = document.getElementById(triggerElementID);
		if ( that.swipeDirection == 'left' ) {
			//pConsole.info(that, e.id);
			//pConsole.info(that, id+": Left touch gesture...")
			if (that.onleft) 
				that.onleft();
			// REPLACE WITH YOUR ROUTINES
			//swipedElement.style.backgroundColor = 'orange';
			//pPictureGallery.next();
	
		} else if ( that.swipeDirection == 'right' ) {
			//pConsole.info(that, id+": Right touch gesture...")
			if (that.onright) 
				that.onright(); 
			// REPLACE WITH YOUR ROUTINES
			//swipedElement.style.backgroundColor = 'green';
			//pPictureGallery.previous();
	
		}/* else if ( that.swipeDirection == 'up' ) {
			// REPLACE WITH YOUR ROUTINES
			//swipedElement.style.backgroundColor = 'maroon';
			if (thumbs_mode == true)
				pSlideShow.showImage();
			else
				history.back();
	
		} else if ( that.swipeDirection == 'down' ) {
			// REPLACE WITH YOUR ROUTINES
			//swipedElement.style.backgroundColor = 'purple';
	
			if (thumbs_mode == false)
				pSlideShow.showThumbs();
				//showImage();
			//else
			//	showThumbs();//First();
		}*/
	};
};

/******************************************************************************/

const pTouch = (new function() {
	var that = this, data = new pMap();
	
	function f_get(x) {
		var d = data.getValue(x);
		if (!d)
			data.put(x, d = new pTouchInstance(x));
		return d;
	}
		
	function xel_touchstart(e) { return that.touchStart(this, e); }
	function xel_touchend(e) { return that.touchEnd(this, e); }
	function xel_touchmove(e) { return that.touchMove(this, e); }
	function xel_touchcancel(e) { return that.touchCancel(this, e); }
		
	this.getData = function(id) {
		return f_get(id);
	};

	this.touchStart = function(x, e) {
		f_get(x.id).touchStart(e, x.id);
	};

	this.touchMove = function(x, e) {
		f_get(x.id).touchMove(e);
	};

	this.touchEnd = function(x, e) {
		f_get(x.id).touchEnd(e);
	};

	this.touchCancel = function(x, e) {
		f_get(x.id).touchCancel(e);
	};
	
	this.enable = function(x) {
		if (x = pElement.x(x)) {
			x.addEventListener('touchstart', xel_touchstart);
			x.addEventListener('touchend', xel_touchend);
			x.addEventListener('touchmove', xel_touchmove);
			x.addEventListener('touchcancel', xel_touchcancel);
		}
	};
	
	function f_overscroll(el) {
	  el.addEventListener('touchstart', function() {
	    var top = el.scrollTop
	      , totalScroll = el.scrollHeight
	      , currentScroll = top + el.offsetHeight

	    //If we're at the top or the bottom of the containers
	    //scroll, push up or down one pixel.
	    //
	    //this prevents the scroll from "passing through" to
	    //the body.
	    if(top === 0) {
	      el.scrollTop = 1
	    } else if(currentScroll === totalScroll) {
	      el.scrollTop = top - 1
	    }
	  })

	  el.addEventListener('touchmove', function(evt) {
	    //if the content is actually scrollable, i.e. the content is long enough
	    //that scrolling can occur
	    if(el.offsetHeight < el.scrollHeight)
	      evt._isScroller = true
	  })
	}

	f_overscroll(document.body);
	
	function f_noscroll(e) {
		//In this case, the default behavior is scrolling the body, which
		//would result in an overflow.  Since we don't want that, we preventDefault.
		if (!e._isScroller)
		    e.preventDefault()
	}
	
	var scroll_disabled;
	function f_disableScroll() {
		if (!scroll_disabled) {
			document.body.addEventListener('touchmove', f_noscroll, { capture: true, passive: false});
			scroll_disabled = true;
			return true;
		}
	};
	
	function eh_dialog_open(e) { if (e.first) f_enableScroll(); };
	function eh_dialog_close(e) { if (e.first) f_disableScroll(); };
	this.disableScroll = function() {
		if (f_disableScroll()) {
			pDialog.addEventListener('open', eh_dialog_open);
			pDialog.addEventListener('close', eh_dialog_close);
		}
	};
	
	function f_enableScroll() {
		if (scroll_disabled) {
			document.body.removeEventListener('touchmove', f_noscroll, { capture: true, passive: false});
			scroll_disabled = false;
			return true;
		}
	};
	this.enableScroll = function() {
		if (f_enableScroll()) {
			pDialog.removeEventListener('open', eh_dialog_open);
			pDialog.removeEventListener('close', eh_dialog_close);
		}
	};
});

/******************************************************************************/
/***  END OF FILE  ************************************************************/
/******************************************************************************/