/*******************************************************************************
* 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 ************************************************************/
/******************************************************************************/