| OLD | NEW |
| (Empty) | |
| 1 <!-- |
| 2 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 3 // Use of this source code is governed by a BSD-style license that can be |
| 4 // found in the LICENSE file. |
| 5 --> |
| 6 <import src="sky-binder.sky" as="binder" /> |
| 7 <script> |
| 8 // TODO(esprehn): It would be nice if these were exposed by the platform so |
| 9 // the framework didn't need to hard code a list. |
| 10 var defaultAttributesNames = new Set([ |
| 11 'accesskey', |
| 12 'alt', |
| 13 'as', |
| 14 'async', |
| 15 'class', |
| 16 'contenteditable', |
| 17 'crossorigin', |
| 18 'dir', |
| 19 'height', |
| 20 'href', |
| 21 'id', |
| 22 'is', |
| 23 'lang', |
| 24 'media', |
| 25 'name', |
| 26 'rel', |
| 27 'select', |
| 28 'sizes', |
| 29 'spellcheck', |
| 30 'src', |
| 31 'srcset', |
| 32 'style', |
| 33 'tabindex', |
| 34 'title', |
| 35 'type', |
| 36 'width', |
| 37 ]); |
| 38 |
| 39 var attributeConverters = { |
| 40 boolean: function(value) { |
| 41 if (typeof value == 'string') |
| 42 return value == 'true'; |
| 43 return !!value; |
| 44 }, |
| 45 number: function(value) { |
| 46 return Number(value); |
| 47 }, |
| 48 string: function(value) { |
| 49 if (value === null) |
| 50 return ''; |
| 51 return String(value); |
| 52 }, |
| 53 }; |
| 54 |
| 55 function eventHandlerCallback(event) { |
| 56 var element = event.currentTarget; |
| 57 var registration = getRegistration(element.localName); |
| 58 var method = registration.eventHandlers.get(event.type); |
| 59 var handler = element[method]; |
| 60 if (!(typeof handler == 'function')) { |
| 61 throw new Error('Element ' + element.localName + |
| 62 ' specifies invalid event handler "' + method + '"'); |
| 63 } |
| 64 handler.call(element, event); |
| 65 } |
| 66 |
| 67 class ElementRegistration { |
| 68 constructor(tagName) { |
| 69 this.tagName = tagName; |
| 70 this.attributes = new Map(); |
| 71 this.eventHandlers = new Map(); |
| 72 this.template = null; |
| 73 Object.preventExtensions(this); |
| 74 } |
| 75 |
| 76 allowsAttribute(name) { |
| 77 if (name.startsWith('data-')) |
| 78 return true; |
| 79 if (defaultAttributesNames.has(name)) |
| 80 return true; |
| 81 if (this.attributes.has(name)) |
| 82 return true; |
| 83 return false; |
| 84 } |
| 85 |
| 86 defineAttribute(name, type) { |
| 87 var converter = attributeConverters[type]; |
| 88 |
| 89 if (!converter) { |
| 90 console.error('Invalid attribute type "' + type + '", type must be one' |
| 91 + ' of boolean, number or string.'); |
| 92 return; |
| 93 } |
| 94 |
| 95 this.attributes.set(name, converter); |
| 96 } |
| 97 |
| 98 synthesizeAttributes(prototype) { |
| 99 this.attributes.forEach(function(converter, name) { |
| 100 Object.defineProperty(prototype, name, { |
| 101 get: function() { |
| 102 return converter(this.getAttribute(name)); |
| 103 }, |
| 104 set: function(newValue) { |
| 105 this.setAttribute(name, converter(newValue)); |
| 106 }, |
| 107 enumerable: true, |
| 108 configurable: true, |
| 109 }); |
| 110 }); |
| 111 } |
| 112 |
| 113 addInstanceEventListeners(instance) { |
| 114 for (var eventName of this.eventHandlers.keys()) { |
| 115 instance.addEventListener(eventName, eventHandlerCallback); |
| 116 } |
| 117 } |
| 118 } |
| 119 |
| 120 var registrations = new Map(); |
| 121 |
| 122 function registerElement(tagName) { |
| 123 if (registrations.has(tagName)) |
| 124 throw new Error('tagName "' + tagName + '" registered twice.'); |
| 125 var registration = new ElementRegistration(tagName); |
| 126 registrations.set(tagName, registration); |
| 127 return registration; |
| 128 } |
| 129 |
| 130 function getRegistration(tagName) { |
| 131 return registrations.get(tagName); |
| 132 } |
| 133 |
| 134 function checkAttribute(tagName, attrName) { |
| 135 var registration = getRegistration(tagName); |
| 136 |
| 137 if (!registration) |
| 138 return defaultAttributesNames.has(attrName); |
| 139 |
| 140 return registration.allowsAttribute(attrName); |
| 141 } |
| 142 |
| 143 module.exports = { |
| 144 registerElement: registerElement, |
| 145 getRegistration: getRegistration, |
| 146 checkAttribute: checkAttribute, |
| 147 }; |
| 148 </script> |
| OLD | NEW |