este-library-oldschool
Version:
Library for github.com/steida/este.git
180 lines (162 loc) • 5.11 kB
JavaScript
// Generated by github.com/steida/coffee2closure 900.1.18
/**
@fileoverview Hover simulation for touch devices, :hover does not work well
on mobile devices. It flickers, hover state isn't removed etc. So this class
provides alternative approach via este.events.GestureHandler. It adds e-hover
className for matched elements.
EXPERIMENTAL STUFF!
Behaviour:
- 'e-mobile-hover' class is applied immediately
- 'e-mobile-hover-scroll' class is applied after 250ms, which is usefull for
scrollable content, where we don't want to see 'hover' immediately.
It mimics native iOS behaviour on scrollable lists.
- Hover state is removed after 750ms, because on anchors native context menu
is shown and that prevents touchend event to be dispatched. Previous
hover is removed too for sure.
*/
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.superClass_ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
goog.provide('este.labs.mobile.Hover');
goog.require('este.Base');
goog.require('este.events.GestureHandler');
goog.require('goog.dom');
goog.require('goog.dom.classlist');
/**
@param {Element} element
@constructor
@extends {este.Base}
*/
este.labs.mobile.Hover = function(element) {
este.labs.mobile.Hover.superClass_.constructor.call(this);
this.gestureHandler = new este.events.GestureHandler(element);
}
extend(este.labs.mobile.Hover, superClass);
/**
Defines on which elements hover state is simulated.
@type {function(Node) : boolean}
*/
este.labs.mobile.Hover.prototype.matcher = function(node) {
if (!node.tagName) {
return false;
}
node = /** @type {Element} */(node);
return node.tagName === 'A' || goog.dom.classlist.contains(node, 'button');
};
/**
@type {este.events.GestureHandler}
@protected
*/
este.labs.mobile.Hover.prototype.gestureHandler = null;
/**
@type {Node}
@protected
*/
este.labs.mobile.Hover.prototype.previous = null;
/**
@type {?number}
@protected
*/
este.labs.mobile.Hover.prototype.hoverScrollTimeout = null;
/**
@param {boolean} enabled
*/
este.labs.mobile.Hover.prototype.setEnabled = function(enabled) {
if (enabled) {
this.on(this.gestureHandler, 'start', this.onGestureHandlerStart);
return this.on(this.gestureHandler, 'end', this.onGestureHandlerEnd);
} else {
this.off(this.gestureHandler, 'start', this.onGestureHandlerStart);
return this.off(this.gestureHandler, 'end', this.onGestureHandlerEnd);
}
};
/**
@param {goog.events.BrowserEvent} e
@protected
*/
este.labs.mobile.Hover.prototype.onGestureHandlerStart = function(e) {
var target;
target = this.getFilteredTarget(e.target);
if (!target) {
return;
}
this.handlePrevious(target);
this.addHoverNow(target);
this.addHoverScrollAfterWhile(target);
return this.removeHoverStateAfterWhile(target);
};
/**
@param {Node} target
@protected
*/
este.labs.mobile.Hover.prototype.handlePrevious = function(target) {
this.removeHoverState(this.previous);
return this.previous = target;
};
/**
@param {Node} target
@protected
*/
este.labs.mobile.Hover.prototype.addHoverNow = function(target) {
target = /** @type {Element} */(target);
return goog.dom.classlist.add(target, 'e-mobile-hover');
};
/**
@param {Node} target
@protected
*/
este.labs.mobile.Hover.prototype.addHoverScrollAfterWhile = function(target) {
return this.hoverScrollTimeout = setTimeout((function(_this) {
return function() {
target = /** @type {Element} */(target);
return goog.dom.classlist.add(target, 'e-mobile-hover-scroll');
};
})(this), 250);
};
/**
Remove hover state after 750ms, because native anchor context menu prevents
touchend, which is supposed to remove hover classNames.
@param {Node} target
@protected
*/
este.labs.mobile.Hover.prototype.removeHoverStateAfterWhile = function(target) {
return setTimeout((function(_this) {
return function() {
return _this.removeHoverState(target);
};
})(this), 750);
};
/**
@param {goog.events.BrowserEvent} e
@protected
*/
este.labs.mobile.Hover.prototype.onGestureHandlerEnd = function(e) {
return this.removeHoverState(this.previous);
};
/**
@param {Node} target
@protected
*/
este.labs.mobile.Hover.prototype.removeHoverState = function(target) {
clearTimeout(this.hoverScrollTimeout);
if (!target) {
return;
}
target = /** @type {Element} */(target);
goog.dom.classlist.remove(target, 'e-mobile-hover');
return goog.dom.classlist.remove(target, 'e-mobile-hover-scroll');
};
/**
@param {Node} node
@return {Node}
@protected
*/
este.labs.mobile.Hover.prototype.getFilteredTarget = function(node) {
return goog.dom.getAncestor(node, this.matcher, true);
};
/**
@override
*/
este.labs.mobile.Hover.prototype.disposeInternal = function() {
this.gestureHandler.dispose();
este.labs.mobile.Hover.superClass_.disposeInternal.call(this);
};