/* * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ (function(scope) { // imports var log = window.WebComponents ? WebComponents.flags.log : {}; var api = scope.api.instance.events; var EVENT_PREFIX = api.EVENT_PREFIX; var mixedCaseEventTypes = {}; [ 'webkitAnimationStart', 'webkitAnimationEnd', 'webkitTransitionEnd', 'DOMFocusOut', 'DOMFocusIn', 'DOMMouseScroll' ].forEach(function(e) { mixedCaseEventTypes[e.toLowerCase()] = e; }); // polymer-element declarative api: events feature var events = { parseHostEvents: function() { // our delegates map var delegates = this.prototype.eventDelegates; // extract data from attributes into delegates this.addAttributeDelegates(delegates); }, addAttributeDelegates: function(delegates) { // for each attribute for (var i=0, a; a=this.attributes[i]; i++) { // does it have magic marker identifying it as an event delegate? if (this.hasEventPrefix(a.name)) { // if so, add the info to delegates delegates[this.removeEventPrefix(a.name)] = a.value.replace('{{', '') .replace('}}', '').trim(); } } }, // starts with 'on-' hasEventPrefix: function (n) { return n && (n[0] === 'o') && (n[1] === 'n') && (n[2] === '-'); }, removeEventPrefix: function(n) { return n.slice(prefixLength); }, findController: function(node) { while (node.parentNode) { if (node.eventController) { return node.eventController; } node = node.parentNode; } return node.host; }, getEventHandler: function(controller, target, method) { var events = this; return function(e) { if (!controller || !controller.PolymerBase) { controller = events.findController(target); } var args = [e, e.detail, e.currentTarget]; controller.dispatchMethod(controller, method, args); }; }, prepareEventBinding: function(pathString, name, node) { if (!this.hasEventPrefix(name)) return; var eventType = this.removeEventPrefix(name); eventType = mixedCaseEventTypes[eventType] || eventType; var events = this; return function(model, node, oneTime) { var handler = events.getEventHandler(undefined, node, pathString); PolymerGestures.addEventListener(node, eventType, handler); if (oneTime) return; // TODO(rafaelw): This is really pointless work. Aside from the cost // of these allocations, NodeBind is going to setAttribute back to its // current value. Fixing this would mean changing the TemplateBinding // binding delegate API. function bindingValue() { return '{{ ' + pathString + ' }}'; } return { open: bindingValue, discardChanges: bindingValue, close: function() { PolymerGestures.removeEventListener(node, eventType, handler); } }; }; } }; var prefixLength = EVENT_PREFIX.length; // exports scope.api.declaration.events = events; })(Polymer);