goog.module('nbsrc.utils.InteractionObserver');
const events = goog.require('goog.events');
const Event = goog.require('goog.events.Event');
const EventTarget = goog.require('goog.events.EventTarget');
const EventType = goog.require('goog.events.EventType');
const classlist = goog.require('goog.dom.classlist');
/**
* Checks permanently if a user interacts with a mouse or touch and toggles a class to the html tag.
* @extends {EventTarget}
*/
class InteractionObserver extends EventTarget
{
constructor()
{
super();
/**
* Defines if a mouse interaction was detected.
* @type {boolean}
* @private
*/
this.isMouseDetected_ = false;
/**
* Defines if a touch interaction was detected.
* @type {boolean}
* @private
*/
this.isTouchDetected_ = false;
/**
* Defines if a keyboard tab interaction was detected.
* @type {boolean}
* @private
*/
this.isTabDetected_ = false;
/**
* Defines the current interaction mode: `MOUSE`, `TAB` or `TOUCH`
* @type {string}
* @private
*/
this.currentMode_ = 'TOUCH';
/**
* Specifies whether one of the classes `is-mouse-mode`, `is-tab-mode` or `is-touch-mode`
* should be added to the main document element as a representation of the current interaction mode.
* @type {boolean}
* @private
*/
this.setCssClasses_ = true;
events.listen(window, EventType.MOUSEMOVE, this.handleMouseMove_, false, this);
events.listen(window, EventType.TOUCHSTART, this.handleTouchStart_, false, this);
events.listen(window, EventType.KEYUP, this.handleKeyUp_, false, this);
if(this.setCssClasses_)
classlist.enable(document.documentElement, 'is-touch-mode', true);
}
/**
* Monitors the interaction with the mouse
* @private
* @param {Event} event
*/
handleMouseMove_(event)
{
if(this.isTabDetected_)
{
this.isTabDetected_ = false;
if(this.setCssClasses_)
classlist.enable(document.documentElement, 'is-tab-mode', false);
}
if(!this.isMouseDetected_)
{
if(!this.isTouchDetected_)
{
this.isMouseDetected_ = true;
this.handleModeChange_();
}
this.isTouchDetected_ = false;
}
else
{
events.unlisten(window, EventType.MOUSEMOVE, this.handleMouseMove_, false, this);
}
}
/**
* Monitors the interaction by touch
* @private
* @param {Event} event
*/
handleTouchStart_(event)
{
if(this.isTabDetected_)
{
this.isTabDetected_ = false;
if(this.setCssClasses_)
classlist.enable(document.documentElement, 'is-tab-mode', false);
}
this.isTouchDetected_ = true;
this.isMouseDetected_ = false;
this.handleModeChange_();
}
/**
* Monitors the interaction by key
* @private
* @param {Event} event
*/
handleKeyUp_(event)
{
if (event.keyCode === 9)
{
this.isTabDetected_ = true;
this.handleModeChange_();
}
}
/**
* Changes the current interaction mode and fires a EventType.CHANGE event when the mode changes.
* @private
*/
handleModeChange_()
{
if(this.currentMode_ !== 'TAB' && this.isTabDetected_)
{
if(this.setCssClasses_)
classlist.enable(document.documentElement, 'is-tab-mode', true);
events.listen(window, EventType.MOUSEMOVE, this.handleMouseMove_, false, this);
this.currentMode_ = 'TAB';
this.isMouseDetected_ = false;
this.isTouchDetected_ = false;
this.dispatchEvent(new Event(EventType.CHANGE));
}
else if(this.currentMode_ !== 'MOUSE' && this.isMouseDetected_)
{
if(this.setCssClasses_)
{
classlist.enable(document.documentElement, 'is-mouse-mode', true);
classlist.enable(document.documentElement, 'is-touch-mode', false);
}
events.unlisten(window, EventType.MOUSEMOVE, this.handleMouseMove_, false, this);
this.currentMode_ = 'MOUSE';
this.dispatchEvent(new Event(EventType.CHANGE));
}
else if(this.currentMode_ !== 'TOUCH' && this.isTouchDetected_)
{
if(this.setCssClasses_)
{
classlist.enable(document.documentElement, 'is-mouse-mode', false);
classlist.enable(document.documentElement, 'is-touch-mode', true);
}
events.listen(window, EventType.MOUSEMOVE, this.handleMouseMove_, false, this);
this.currentMode_ = 'TOUCH';
this.dispatchEvent(new Event(EventType.CHANGE));
}
}
/**
* Returns the current interaction mode
* @public
*/
getMode()
{
return this.currentMode_;
}
}
goog.addSingletonGetter(InteractionObserver);
exports = InteractionObserver;