UNPKG

este-library-oldschool

Version:

Library for github.com/steida/este.git

288 lines (268 loc) 8.79 kB
// Generated by github.com/steida/coffee2closure 900.1.18 /** @fileoverview este.ui.Component provides easy event delegation and synthetic events registration. For example, if you want to use bubbling focus/blur, you have to instantiate goog.events.FocusHandler in enterDocument method, and dispose it in exitDocument. With este.ui.Component, you don't have to write this boilerplate code. For easy event delegation, replace event src with matching string selector. Note how bindModel method is used for automatic element-model wiring via 'e-model-cid' attribute. Supported synthetic (with bubbling) events: - tap, swipeleft, swiperight, swipeup, swipedown - focusin, focusout - input - submit - key or number from goog.events.KeyCodes enumeration Examples: ```coffee this.enterDocument -> super() this.on this.getElement(), 'click', this.onClick this.on '.box', 'tap', this.onBoxTap this.on 'input', 'focusin', this.onInputFocus this.on this.boxElement, 'tap', this.onTap this.on '.button', 'swipeleft', this.onButtonSwipeleft this.on '#new-todo-form', 'submit', this.onNewTodoFormSubmit this.on '.toggle', 'dblclick', this.onToggleDblclick this.on '.new-post', goog.events.KeyCodes.ENTER, this.onNewCommentKeyEnter return ``` ```coffee this.enterDocument -> super() * note how bindModel is used this.on '.box', 'tap', this.bindModel this.onBoxTap return ``` @see /demos/ui/component.html @see /demos/app/todomvc/js/todos/list/view.coffee */ 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.ui.Component'); goog.require('este.Collection'); goog.require('este.dom'); goog.require('este.events.EventHandler'); goog.require('este.Model'); goog.require('goog.asserts'); goog.require('goog.dom.classlist'); goog.require('goog.ui.Component'); /** @param {goog.dom.DomHelper=} domHelper Optional DOM helper. @constructor @extends {goog.ui.Component} */ este.ui.Component = function(domHelper) { este.ui.Component.superClass_.constructor.call(this, domHelper); } extend(este.ui.Component, superClass); /** @param {Function} fn @param {number} keyCode @param {*} handler @return {Function} @protected */ este.ui.Component.wrapListenerForKeyHandlerKeyFilter = function(fn, keyCode, handler) { return function(e) { if (e.keyCode !== keyCode) { return; } return fn.call(handler, e); }; }; /** @param {Function} fn @param {string} selector @return {Function} @protected */ este.ui.Component.wrapListenerForEventDelegation = function(fn, selector) { var matcher; matcher = function(node) { return goog.dom.isElement(node) && este.dom.match(node, selector); }; return function(e) { var target; target = goog.dom.getAncestor(e.target, matcher, true); if (!target || este.dom.isMouseHoverEventWithinElement(e, target)) { return; } e.originalTarget = e.target; e.target = target; return fn.call(this, e); }; }; /** @param {Element} el @return {Element} @protected */ este.ui.Component.getParentElementWithClientId = function(el) { var parent; parent = goog.dom.getAncestor(el, function(node) { return goog.dom.isElement(node) && (node.hasAttribute('e-model-cid') || node.hasAttribute('data-e-model-cid')); }, true); return /** @type {Element} */(parent); }; /** @type {este.events.EventHandler} @private */ este.ui.Component.prototype.esteHandler_ = null; /** @type {Object} @private */ este.ui.Component.prototype.componentListenables_ = null; /** @param {goog.events.ListenableType|string} src Event source. @param {string|number|Array.<string|number>} type Event type to listen for or array of event types. @param {Function} fn Optional callback function to be used as the listener. @param {boolean=} capture Optional whether to use capture phase. @param {boolean=} once @protected */ este.ui.Component.prototype.on = function(src, type, fn, capture, once) { var i, id, isKeyEventType, keyCode, len, ref, selector, t, useEventDelegation; if (goog.isArray(type)) { for (i = 0, len = type.length; i < len; i++) { t = type[i]; this.on(src, t, fn, capture); } return; } id = this.getComponentListenableId(src, type, fn, capture); if ((ref = this.componentListenables_) != null ? ref[id] : void 0) { return; } if (once) { fn = (function(src, type, fn, capture) { return function(e) { this.off(src, type, fn, capture); return fn.call(this, e); }; })(src, type, fn, capture); } useEventDelegation = goog.isString(src); if (useEventDelegation) { selector = src; src = this.getElement(); } isKeyEventType = goog.dom.isElement(src) && goog.isNumber(type); if (isKeyEventType) { keyCode = /** @type {number} */(type); fn = este.ui.Component.wrapListenerForKeyHandlerKeyFilter(fn, keyCode, this); type = 'key'; } if (useEventDelegation) { selector = /** @type {string} */(selector); fn = este.ui.Component.wrapListenerForEventDelegation(fn, selector); } if (this.componentListenables_ == null) { this.componentListenables_ = {}; } this.componentListenables_[id] = [src, type, fn, capture]; type = /** @type {string} */(type); src = /** @type {goog.events.ListenableType} */(src); this.getHandler().listen(src, type, fn, capture); }; /** @param {goog.events.ListenableType|string} src Event source. @param {string|number|Array.<string|number>} type Event type to listen for or array of event types. @param {Function} fn Optional callback function to be used as the listener. @param {boolean=} capture Optional whether to use capture phase. @protected */ este.ui.Component.prototype.once = function(src, type, fn, capture) { return this.on(src, type, fn, capture, true); }; /** @param {goog.events.ListenableType|string} src Event source. @param {string|number|Array.<string|number>} type Event type to listen for or array of event types. @param {Function} fn Optional callback function to be used as the listener. @param {boolean=} capture Optional whether to use capture phase. @protected */ este.ui.Component.prototype.off = function(src, type, fn, capture) { var i, id, len, listenable, ref, t; if (goog.isArray(type)) { for (i = 0, len = type.length; i < len; i++) { t = type[i]; this.off(src, t, fn, capture); } return; } id = this.getComponentListenableId(src, type, fn, capture); listenable = (ref = this.componentListenables_) != null ? ref[id] : void 0; if (!listenable) { return; } this.getHandler().unlisten.apply(this.getHandler(), listenable); delete this.componentListenables_[id]; }; /** @override */ este.ui.Component.prototype.getHandler = function() { return this.esteHandler_ != null ? this.esteHandler_ : this.esteHandler_ = new este.events.EventHandler(this); }; /** @protected */ este.ui.Component.prototype.getComponentListenableId = function(src, type, fn, capture) { return [goog.isString(src) ? src : goog.getUid(src), type, goog.getUid(fn), capture].join(); }; /** @override */ este.ui.Component.prototype.exitDocument = function() { var ref; if ((ref = this.esteHandler_) != null) { ref.removeAll(); } this.componentListenables_ = null; este.ui.Component.superClass_.exitDocument.call(this); }; /** Use this method when target has e-model-cid attribute. It will pass model instead of element if such model exists on any collection on this instance. @param {Function} fn @return {Function} */ este.ui.Component.prototype.bindModel = function(fn) { return function(e) { var cid, el, model; el = este.ui.Component.getParentElementWithClientId(e.target); if (el) { cid = el.getAttribute('e-model-cid') || el.getAttribute('data-e-model-cid'); model = this.findModelOnInstanceByClientId(cid); } return fn.call(this, model, el, e); }; }; /** @param {string} clientId @return {este.Model} @protected */ este.ui.Component.prototype.findModelOnInstanceByClientId = function(clientId) { var key, model, value; for (key in this) { value = this[key]; if (value instanceof este.Collection) { model = value.findByClientId(clientId); if (model) { return model; } } else if (value instanceof este.Model) { if (value.get('_cid') === clientId) { return value; } } } return null; };