UNPKG

este-library-oldschool

Version:

Library for github.com/steida/este.git

180 lines (162 loc) 5.11 kB
// 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); };