/**
* KEY AND MOUSE EVENT LISTENER
* @class
*/
/* global MenubarActions */
/* global debug */
/* global getId */
/* global getTranslation */
/* global grouptree */
/* global waitForFinalEvent */
/* jshint -W098 */
var keylistener = function () {
/* jshint +W098 */
var self = this;
this.altModifierPressed = false;
this.menubaractions = new MenubarActions();
this.overscroll = 0;
this.overscrollTimeout = null;
this.overscrollThreshhold = 4000;
this.registeredListener = [];
/**
* Scrolllistener for the mouse
* @param {object} event the scroll event
*/
this.mouseScroll = function (event) {
// positive or negative value for one turn
var delta = event.wheelDelta || -event.detail || false;
if (delta === false) {
return;
}
if (event.ctrlKey || event.altKey) {
self.stopEvent(event);
if (delta > 0) {
self.menubaractions.zoomIn(event);
} else {
self.menubaractions.zoomOut(event);
}
return;
} else {
// normal scrolling
if (!getId('single-page').isCurrent()) {
return;
}
// now check on the new ScrollPosition
var wrapper = getId('__contentwrapper');
var page = self.menubaractions.getCurrentTab();
if (wrapper.scrollTop + wrapper.offsetHeight >= page.offsetHeight ||
wrapper.scrollTop <= 0) {
self.overscroll += -delta;
var direction = self.overscroll >= self.overscrollThreshhold ? self.menubaractions.nextPage :
(self.overscroll <= -self.overscrollThreshhold ? self.menubaractions.previousPage : null);
if (direction != null) {
debug(self.overscroll);
if (self.overscrollTimeout) {
clearTimeout(self.overscrollTimeout);
}
self.overscroll = 0;
direction(function (didSetPage) {
if (didSetPage === false) {
return;
}
wrapper.scrollTop = 0;
});
}
clearTimeout(self.overscrollTimeout);
self.overscrollTimeout = setTimeout(function () {
debug("reset overscroll at:" + self.overscroll);
self.overscroll = 0;
}, 500);
}
}
};
// Value to remember last touch distance. Reset when touch movement ends
this.touchDistanceStart = 0;
// DoubleTap to reset zoom in touch environment
this.touchDetected = null;
/*
* Distance function for the two points
*/
this.distance = function( x1, x2, y1, y2 ) {
var a = x1-x2, b = y1-y2;
return Math.sqrt( a*a + b*b );
};
/**
* Start detecting touch movement for scaling events
* @param {object} event the event
*/
this.touchesStart = function (event) {
if (!event.touches || event.touches.length != 2) {
// Try to detect dpuble touch and reset zoom
if ( self.touchDetected ) {
clearTimeout( self.touchDetected );
self.touchDetected = null;
self.menubaractions.updateZoom(getTranslation("menuBar.zoom.pageFit"));
} else {
self.touchDetected = setTimeout(function(){
self.touchDetected = null;
}, 300);
}
return;
}
var touch1 = event.touches[0],
touch2 = event.touches[1];
self.touchDistanceStart = self.distance( touch1.clientX, touch2.clientX, touch1.clientY, touch2.clientY );
document.documentElement.addEvent('touchmove', self.touchesMove);
document.documentElement.addEvent('touchend', self.touchesStop);
};
/**
* Detect the motion of two touches fort pinching to zoom
* @param {object} event the event
*/
this.touchesMove = function (event) {
if (!event.touches || event.touches.length != 2) {
return;
}
self.stopEvent( event );
var touch1 = event.touches[0],
touch2 = event.touches[1],
touchDistanceStart = self.distance( touch1.clientX, touch2.clientX, touch1.clientY, touch2.clientY ),
touchDistanceDelta = Math.ceil(touchDistanceStart - self.touchDistanceStart);
if (touchDistanceDelta > 0) {
self.menubaractions.zoomIn(event, true);
} else {
self.menubaractions.zoomOut(event, true);
}
self.touchDistanceStart = touchDistanceStart;
};
/**
* End the touches events for scaling the content
* @param {Object} event the event
*/
this.touchesStop = function (event) {
self.stopEvent( event );
document.documentElement.removeEvent('touchmove', self.touchesMove);
document.documentElement.removeEvent('touchend', self.touchesStop);
self.touchDistanceStart = 0;
};
/**
* Keybindings for the whole viewer. Checks only for the press down.
* @param {object} event the keyboard event
*/
this.checkDownKey = function (event) {
let keycode;
if (event.which) {
keycode = event.which;
} else {
keycode = event.keyCode;
}
var catchedEvent = true;
switch (keycode) {
case 13:
if (this.nodeName == 'INPUT') {
this.fireEvent('blur');
}
break;
case 107: // +
self.menubaractions.zoomIn(event);
break;
case 109: // -
self.menubaractions.zoomOut(event);
break;
case 33: // page up
self.menubaractions.previousPage();
break;
case 34: // page down
self.menubaractions.nextPage();
break;
case 35: // end
self.menubaractions.lastPage();
break;
case 36: // home
self.menubaractions.firstPage();
break;
case 37: // left
case 38: // up
case 39: // right
case 40: // down
(new grouptree()).keyboardNavigation(keycode);
break;
default:
catchedEvent = false;
}
if (catchedEvent) {
self.stopEvent(event);
}
};
/**
* Check for a released key event
* @param {object} event the keyboard event
*/
this.checkUpKey = function (event) {
};
/**
* Event cancellation
* @param {object} [event=window.event] cancel event.
*/
this.stopEvent = function (event) {
event = event || window.event;
if (event) {
event.cancelBubble = true;
event.returnValue = false;
if (event.stopPropagation) {
event.stopPropagation();
}
if (event.preventDefault) {
event.preventDefault();
}
}
return false;
};
/**
* Add a keylistener to the list of know listeners for external access
* @param {string} keyCode The keycode combination as string
* @param {string} description The description
*
* */
this.addKeyListener = function(keyCode, description) {
// Check if the list already contains such object.
var exists = this.registeredListener.filter(function(elem){
return elem.keyCode == keyCode;
});
if ( exists.length > 0 ) { return false; }
this.registeredListener.push({
keyCode: keyCode,
description: description
});
// To ensure that we did add this entry to our list
return true;
};
/**
* initialise the keyboard events
*/
this.init = function () {
if (!getId('__contentwrapper')) { return; }
window.addEvent('keydown', self.checkDownKey);
window.addEvent('keyup', self.checkUpKey);
getId('__contentwrapper').addEvent('mouseover', function () {
debug("register event");
window.addEvent('mousewheel', self.mouseScroll);
document.documentElement.addEvent('mousewheel', self.mouseScroll); // This is for IE
/* Mozialla Handling */
if (window.addEventListener) {
window.addEventListener('MozMousePixelScroll', self.mouseScroll, false);
}
});
getId('__contentwrapper').addEvent('mouseout', function () {
debug("remove event");
window.removeEvent('mousewheel', self.mouseScroll);
document.documentElement.removeEvent('mousewheel', self.mouseScroll); // This is for IE
/* Mozialla Handling */
if (window.removeEventListener) {
window.removeEventListener('MozMousePixelScroll', self.mouseScroll, false);
}
});
this.addKeyListener("+", getTranslation("menuBar.zoomIn") );
this.addKeyListener("-", getTranslation("menuBar.zoomOut") );
this.addKeyListener("Home", getTranslation("menuBar.first") );
this.addKeyListener("Page Up", getTranslation("menuBar.previous") );
this.addKeyListener("Page Down", getTranslation("menuBar.next") );
this.addKeyListener("End", getTranslation("menuBar.last") );
this.addKeyListener("Left", getTranslation("keyBinding.grouptree.close") );
this.addKeyListener("Up", getTranslation("keyBinding.grouptree.previous") );
this.addKeyListener("Right", getTranslation("keyBinding.grouptree.open") );
this.addKeyListener("Down", getTranslation("keyBinding.grouptree.next") );
this.addKeyListener("ESC", getTranslation("keyBinding.closeDialog") );
// Touches Start for mobile Devices
document.documentElement.addEvent('touchstart', self.touchesStart);
// Resize Events
window.addEvent('resize', waitForFinalEvent( function(){
self.menubaractions.setZoom($.jStorage.get("menu.zoom"), {});
}, 250, "resizeWindow")); // Update zoom with resizing
};
};