| OLD | NEW |
| 1 // Copyright (c) 2012 The Polymer Authors. All rights reserved. | 1 // Copyright (c) 2012 The Polymer Authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Redistribution and use in source and binary forms, with or without | 3 // Redistribution and use in source and binary forms, with or without |
| 4 // modification, are permitted provided that the following conditions are | 4 // modification, are permitted provided that the following conditions are |
| 5 // met: | 5 // met: |
| 6 // | 6 // |
| 7 // * Redistributions of source code must retain the above copyright | 7 // * Redistributions of source code must retain the above copyright |
| 8 // notice, this list of conditions and the following disclaimer. | 8 // notice, this list of conditions and the following disclaimer. |
| 9 // * Redistributions in binary form must reproduce the above | 9 // * Redistributions in binary form must reproduce the above |
| 10 // copyright notice, this list of conditions and the following disclaimer | 10 // copyright notice, this list of conditions and the following disclaimer |
| (...skipping 1027 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1038 scope.upgradeDocument = nop; | 1038 scope.upgradeDocument = nop; |
| 1039 scope.takeRecords = nop; | 1039 scope.takeRecords = nop; |
| 1040 | 1040 |
| 1041 } else { | 1041 } else { |
| 1042 | 1042 |
| 1043 /** | 1043 /** |
| 1044 * Registers a custom tag name with the document. | 1044 * Registers a custom tag name with the document. |
| 1045 * | 1045 * |
| 1046 * When a registered element is created, a `readyCallback` method is called | 1046 * When a registered element is created, a `readyCallback` method is called |
| 1047 * in the scope of the element. The `readyCallback` method can be specified on | 1047 * in the scope of the element. The `readyCallback` method can be specified on |
| 1048 * either `inOptions.prototype` or `inOptions.lifecycle` with the latter takin
g | 1048 * either `options.prototype` or `options.lifecycle` with the latter taking |
| 1049 * precedence. | 1049 * precedence. |
| 1050 * | 1050 * |
| 1051 * @method register | 1051 * @method register |
| 1052 * @param {String} inName The tag name to register. Must include a dash ('-'), | 1052 * @param {String} name The tag name to register. Must include a dash ('-'), |
| 1053 * for example 'x-component'. | 1053 * for example 'x-component'. |
| 1054 * @param {Object} inOptions | 1054 * @param {Object} options |
| 1055 * @param {String} [inOptions.extends] | 1055 * @param {String} [options.extends] |
| 1056 * (_off spec_) Tag name of an element to extend (or blank for a new | 1056 * (_off spec_) Tag name of an element to extend (or blank for a new |
| 1057 * element). This parameter is not part of the specification, but instead | 1057 * element). This parameter is not part of the specification, but instead |
| 1058 * is a hint for the polyfill because the extendee is difficult to infer. | 1058 * is a hint for the polyfill because the extendee is difficult to infer. |
| 1059 * Remember that the input prototype must chain to the extended element's | 1059 * Remember that the input prototype must chain to the extended element's |
| 1060 * prototype (or HTMLElement.prototype) regardless of the value of | 1060 * prototype (or HTMLElement.prototype) regardless of the value of |
| 1061 * `extends`. | 1061 * `extends`. |
| 1062 * @param {Object} inOptions.prototype The prototype to use for the new | 1062 * @param {Object} options.prototype The prototype to use for the new |
| 1063 * element. The prototype must inherit from HTMLElement. | 1063 * element. The prototype must inherit from HTMLElement. |
| 1064 * @param {Object} [inOptions.lifecycle] | 1064 * @param {Object} [options.lifecycle] |
| 1065 * Callbacks that fire at important phases in the life of the custom | 1065 * Callbacks that fire at important phases in the life of the custom |
| 1066 * element. | 1066 * element. |
| 1067 * | 1067 * |
| 1068 * @example | 1068 * @example |
| 1069 * FancyButton = document.register("fancy-button", { | 1069 * FancyButton = document.register("fancy-button", { |
| 1070 * extends: 'button', | 1070 * extends: 'button', |
| 1071 * prototype: Object.create(HTMLButtonElement.prototype, { | 1071 * prototype: Object.create(HTMLButtonElement.prototype, { |
| 1072 * readyCallback: { | 1072 * readyCallback: { |
| 1073 * value: function() { | 1073 * value: function() { |
| 1074 * console.log("a fancy-button was created", | 1074 * console.log("a fancy-button was created", |
| 1075 * } | 1075 * } |
| 1076 * } | 1076 * } |
| 1077 * }) | 1077 * }) |
| 1078 * }); | 1078 * }); |
| 1079 * @return {Function} Constructor for the newly registered type. | 1079 * @return {Function} Constructor for the newly registered type. |
| 1080 */ | 1080 */ |
| 1081 function register(inName, inOptions) { | 1081 function register(name, options) { |
| 1082 //console.warn('document.register("' + inName + '", ', inOptions, ')'); | 1082 //console.warn('document.register("' + name + '", ', options, ')'); |
| 1083 // construct a defintion out of options | 1083 // construct a defintion out of options |
| 1084 // TODO(sjmiles): probably should clone inOptions instead of mutating it | 1084 // TODO(sjmiles): probably should clone options instead of mutating it |
| 1085 var definition = inOptions || {}; | 1085 var definition = options || {}; |
| 1086 if (!inName) { | 1086 if (!name) { |
| 1087 // TODO(sjmiles): replace with more appropriate error (EricB can probably | 1087 // TODO(sjmiles): replace with more appropriate error (EricB can probably |
| 1088 // offer guidance) | 1088 // offer guidance) |
| 1089 throw new Error('Name argument must not be empty'); | 1089 throw new Error('document.register: first argument `name` must not be empt
y'); |
| 1090 } |
| 1091 if (name.indexOf('-') < 0) { |
| 1092 // TODO(sjmiles): replace with more appropriate error (EricB can probably |
| 1093 // offer guidance) |
| 1094 throw new Error('document.register: first argument `name` must contain a d
ash (\'-\'). Argument was \'' + String(name) + '\'.'); |
| 1090 } | 1095 } |
| 1091 // record name | 1096 // record name |
| 1092 definition.name = inName; | 1097 definition.name = name; |
| 1093 // must have a prototype, default to an extension of HTMLElement | 1098 // must have a prototype, default to an extension of HTMLElement |
| 1094 // TODO(sjmiles): probably should throw if no prototype, check spec | 1099 // TODO(sjmiles): probably should throw if no prototype, check spec |
| 1095 if (!definition.prototype) { | 1100 if (!definition.prototype) { |
| 1096 // TODO(sjmiles): replace with more appropriate error (EricB can probably | 1101 // TODO(sjmiles): replace with more appropriate error (EricB can probably |
| 1097 // offer guidance) | 1102 // offer guidance) |
| 1098 throw new Error('Options missing required prototype property'); | 1103 throw new Error('Options missing required prototype property'); |
| 1099 } | 1104 } |
| 1100 // ensure a lifecycle object so we don't have to null test it | 1105 // ensure a lifecycle object so we don't have to null test it |
| 1101 definition.lifecycle = definition.lifecycle || {}; | 1106 definition.lifecycle = definition.lifecycle || {}; |
| 1102 // build a list of ancestral custom elements (for native base detection) | 1107 // build a list of ancestral custom elements (for native base detection) |
| 1103 // TODO(sjmiles): we used to need to store this, but current code only | 1108 // TODO(sjmiles): we used to need to store this, but current code only |
| 1104 // uses it in 'resolveTagName': it should probably be inlined | 1109 // uses it in 'resolveTagName': it should probably be inlined |
| 1105 definition.ancestry = ancestry(definition.extends); | 1110 definition.ancestry = ancestry(definition.extends); |
| 1106 // extensions of native specializations of HTMLElement require localName | 1111 // extensions of native specializations of HTMLElement require localName |
| 1107 // to remain native, and use secondary 'is' specifier for extension type | 1112 // to remain native, and use secondary 'is' specifier for extension type |
| 1108 resolveTagName(definition); | 1113 resolveTagName(definition); |
| 1109 // some platforms require modifications to the user-supplied prototype | 1114 // some platforms require modifications to the user-supplied prototype |
| 1110 // chain | 1115 // chain |
| 1111 resolvePrototypeChain(definition); | 1116 resolvePrototypeChain(definition); |
| 1112 // overrides to implement attributeChanged callback | 1117 // overrides to implement attributeChanged callback |
| 1113 overrideAttributeApi(definition.prototype); | 1118 overrideAttributeApi(definition.prototype); |
| 1114 // 7.1.5: Register the DEFINITION with DOCUMENT | 1119 // 7.1.5: Register the DEFINITION with DOCUMENT |
| 1115 registerDefinition(inName, definition); | 1120 registerDefinition(name, definition); |
| 1116 // 7.1.7. Run custom element constructor generation algorithm with PROTOTYPE | 1121 // 7.1.7. Run custom element constructor generation algorithm with PROTOTYPE |
| 1117 // 7.1.8. Return the output of the previous step. | 1122 // 7.1.8. Return the output of the previous step. |
| 1118 definition.ctor = generateConstructor(definition); | 1123 definition.ctor = generateConstructor(definition); |
| 1119 definition.ctor.prototype = definition.prototype; | 1124 definition.ctor.prototype = definition.prototype; |
| 1120 // force our .constructor to be our actual constructor | 1125 // force our .constructor to be our actual constructor |
| 1121 definition.prototype.constructor = definition.ctor; | 1126 definition.prototype.constructor = definition.ctor; |
| 1122 // if initial parsing is complete | 1127 // if initial parsing is complete |
| 1123 if (scope.ready) { | 1128 if (scope.ready) { |
| 1124 // upgrade any pre-existing nodes of this type | 1129 // upgrade any pre-existing nodes of this type |
| 1125 scope.upgradeAll(document); | 1130 scope.upgradeAll(document); |
| 1126 } | 1131 } |
| 1127 return definition.ctor; | 1132 return definition.ctor; |
| 1128 } | 1133 } |
| 1129 | 1134 |
| 1130 function ancestry(inExtends) { | 1135 function ancestry(extnds) { |
| 1131 var extendee = registry[inExtends]; | 1136 var extendee = registry[extnds]; |
| 1132 if (extendee) { | 1137 if (extendee) { |
| 1133 return ancestry(extendee.extends).concat([extendee]); | 1138 return ancestry(extendee.extends).concat([extendee]); |
| 1134 } | 1139 } |
| 1135 return []; | 1140 return []; |
| 1136 } | 1141 } |
| 1137 | 1142 |
| 1138 function resolveTagName(inDefinition) { | 1143 function resolveTagName(definition) { |
| 1139 // if we are explicitly extending something, that thing is our | 1144 // if we are explicitly extending something, that thing is our |
| 1140 // baseTag, unless it represents a custom component | 1145 // baseTag, unless it represents a custom component |
| 1141 var baseTag = inDefinition.extends; | 1146 var baseTag = definition.extends; |
| 1142 // if our ancestry includes custom components, we only have a | 1147 // if our ancestry includes custom components, we only have a |
| 1143 // baseTag if one of them does | 1148 // baseTag if one of them does |
| 1144 for (var i=0, a; (a=inDefinition.ancestry[i]); i++) { | 1149 for (var i=0, a; (a=definition.ancestry[i]); i++) { |
| 1145 baseTag = a.is && a.tag; | 1150 baseTag = a.is && a.tag; |
| 1146 } | 1151 } |
| 1147 // our tag is our baseTag, if it exists, and otherwise just our name | 1152 // our tag is our baseTag, if it exists, and otherwise just our name |
| 1148 inDefinition.tag = baseTag || inDefinition.name; | 1153 definition.tag = baseTag || definition.name; |
| 1149 if (baseTag) { | 1154 if (baseTag) { |
| 1150 // if there is a base tag, use secondary 'is' specifier | 1155 // if there is a base tag, use secondary 'is' specifier |
| 1151 inDefinition.is = inDefinition.name; | 1156 definition.is = definition.name; |
| 1152 } | 1157 } |
| 1153 } | 1158 } |
| 1154 | 1159 |
| 1155 function resolvePrototypeChain(inDefinition) { | 1160 function resolvePrototypeChain(definition) { |
| 1156 // if we don't support __proto__ we need to locate the native level | 1161 // if we don't support __proto__ we need to locate the native level |
| 1157 // prototype for precise mixing in | 1162 // prototype for precise mixing in |
| 1158 if (!Object.__proto__) { | 1163 if (!Object.__proto__) { |
| 1159 // default prototype | 1164 // default prototype |
| 1160 var native = HTMLElement.prototype; | 1165 var native = HTMLElement.prototype; |
| 1161 // work out prototype when using type-extension | 1166 // work out prototype when using type-extension |
| 1162 if (inDefinition.is) { | 1167 if (definition.is) { |
| 1163 var inst = document.createElement(inDefinition.tag); | 1168 var inst = document.createElement(definition.tag); |
| 1164 native = Object.getPrototypeOf(inst); | 1169 native = Object.getPrototypeOf(inst); |
| 1165 } | 1170 } |
| 1166 // ensure __proto__ reference is installed at each point on the prototype | 1171 // ensure __proto__ reference is installed at each point on the prototype |
| 1167 // chain. | 1172 // chain. |
| 1168 // NOTE: On platforms without __proto__, a mixin strategy is used instead | 1173 // NOTE: On platforms without __proto__, a mixin strategy is used instead |
| 1169 // of prototype swizzling. In this case, this generated __proto__ provides | 1174 // of prototype swizzling. In this case, this generated __proto__ provides |
| 1170 // limited support for prototype traversal. | 1175 // limited support for prototype traversal. |
| 1171 var proto = inDefinition.prototype, ancestor; | 1176 var proto = definition.prototype, ancestor; |
| 1172 while (proto && (proto !== native)) { | 1177 while (proto && (proto !== native)) { |
| 1173 var ancestor = Object.getPrototypeOf(proto); | 1178 var ancestor = Object.getPrototypeOf(proto); |
| 1174 proto.__proto__ = ancestor; | 1179 proto.__proto__ = ancestor; |
| 1175 proto = ancestor; | 1180 proto = ancestor; |
| 1176 } | 1181 } |
| 1177 } | 1182 } |
| 1178 // cache this in case of mixin | 1183 // cache this in case of mixin |
| 1179 inDefinition.native = native; | 1184 definition.native = native; |
| 1180 } | 1185 } |
| 1181 | 1186 |
| 1182 // SECTION 4 | 1187 // SECTION 4 |
| 1183 | 1188 |
| 1184 function instantiate(inDefinition) { | 1189 function instantiate(definition) { |
| 1185 // 4.a.1. Create a new object that implements PROTOTYPE | 1190 // 4.a.1. Create a new object that implements PROTOTYPE |
| 1186 // 4.a.2. Let ELEMENT by this new object | 1191 // 4.a.2. Let ELEMENT by this new object |
| 1187 // | 1192 // |
| 1188 // the custom element instantiation algorithm must also ensure that the | 1193 // the custom element instantiation algorithm must also ensure that the |
| 1189 // output is a valid DOM element with the proper wrapper in place. | 1194 // output is a valid DOM element with the proper wrapper in place. |
| 1190 // | 1195 // |
| 1191 return upgrade(domCreateElement(inDefinition.tag), inDefinition); | 1196 return upgrade(domCreateElement(definition.tag), definition); |
| 1192 } | 1197 } |
| 1193 | 1198 |
| 1194 function upgrade(inElement, inDefinition) { | 1199 function upgrade(element, definition) { |
| 1195 // some definitions specify an 'is' attribute | 1200 // some definitions specify an 'is' attribute |
| 1196 if (inDefinition.is) { | 1201 if (definition.is) { |
| 1197 inElement.setAttribute('is', inDefinition.is); | 1202 element.setAttribute('is', definition.is); |
| 1198 } | 1203 } |
| 1199 // make 'element' implement inDefinition.prototype | 1204 // make 'element' implement definition.prototype |
| 1200 implement(inElement, inDefinition); | 1205 implement(element, definition); |
| 1201 // flag as upgraded | 1206 // flag as upgraded |
| 1202 inElement.__upgraded__ = true; | 1207 element.__upgraded__ = true; |
| 1203 // there should never be a shadow root on inElement at this point | 1208 // there should never be a shadow root on element at this point |
| 1204 // we require child nodes be upgraded before `created` | 1209 // we require child nodes be upgraded before `created` |
| 1205 scope.upgradeSubtree(inElement); | 1210 scope.upgradeSubtree(element); |
| 1206 // lifecycle management | 1211 // lifecycle management |
| 1207 created(inElement); | 1212 created(element); |
| 1208 // OUTPUT | 1213 // OUTPUT |
| 1209 return inElement; | 1214 return element; |
| 1210 } | 1215 } |
| 1211 | 1216 |
| 1212 function implement(inElement, inDefinition) { | 1217 function implement(element, definition) { |
| 1213 // prototype swizzling is best | 1218 // prototype swizzling is best |
| 1214 if (Object.__proto__) { | 1219 if (Object.__proto__) { |
| 1215 inElement.__proto__ = inDefinition.prototype; | 1220 element.__proto__ = definition.prototype; |
| 1216 } else { | 1221 } else { |
| 1217 // where above we can re-acquire inPrototype via | 1222 // where above we can re-acquire inPrototype via |
| 1218 // getPrototypeOf(Element), we cannot do so when | 1223 // getPrototypeOf(Element), we cannot do so when |
| 1219 // we use mixin, so we install a magic reference | 1224 // we use mixin, so we install a magic reference |
| 1220 customMixin(inElement, inDefinition.prototype, inDefinition.native); | 1225 customMixin(element, definition.prototype, definition.native); |
| 1221 inElement.__proto__ = inDefinition.prototype; | 1226 element.__proto__ = definition.prototype; |
| 1222 } | 1227 } |
| 1223 } | 1228 } |
| 1224 | 1229 |
| 1225 function customMixin(inTarget, inSrc, inNative) { | 1230 function customMixin(inTarget, inSrc, inNative) { |
| 1226 // TODO(sjmiles): 'used' allows us to only copy the 'youngest' version of | 1231 // TODO(sjmiles): 'used' allows us to only copy the 'youngest' version of |
| 1227 // any property. This set should be precalculated. We also need to | 1232 // any property. This set should be precalculated. We also need to |
| 1228 // consider this for supporting 'super'. | 1233 // consider this for supporting 'super'. |
| 1229 var used = {}; | 1234 var used = {}; |
| 1230 // start with inSrc | 1235 // start with inSrc |
| 1231 var p = inSrc; | 1236 var p = inSrc; |
| 1232 // sometimes the default is HTMLUnknownElement.prototype instead of | 1237 // sometimes the default is HTMLUnknownElement.prototype instead of |
| 1233 // HTMLElement.prototype, so we add a test | 1238 // HTMLElement.prototype, so we add a test |
| 1234 // the idea is to avoid mixing in native prototypes, so adding | 1239 // the idea is to avoid mixing in native prototypes, so adding |
| 1235 // the second test is WLOG | 1240 // the second test is WLOG |
| 1236 while (p !== inNative && p !== HTMLUnknownElement.prototype) { | 1241 while (p !== inNative && p !== HTMLUnknownElement.prototype) { |
| 1237 var keys = Object.getOwnPropertyNames(p); | 1242 var keys = Object.getOwnPropertyNames(p); |
| 1238 for (var i=0, k; k=keys[i]; i++) { | 1243 for (var i=0, k; k=keys[i]; i++) { |
| 1239 if (!used[k]) { | 1244 if (!used[k]) { |
| 1240 Object.defineProperty(inTarget, k, | 1245 Object.defineProperty(inTarget, k, |
| 1241 Object.getOwnPropertyDescriptor(p, k)); | 1246 Object.getOwnPropertyDescriptor(p, k)); |
| 1242 used[k] = 1; | 1247 used[k] = 1; |
| 1243 } | 1248 } |
| 1244 } | 1249 } |
| 1245 p = Object.getPrototypeOf(p); | 1250 p = Object.getPrototypeOf(p); |
| 1246 } | 1251 } |
| 1247 } | 1252 } |
| 1248 | 1253 |
| 1249 function created(inElement) { | 1254 function created(element) { |
| 1250 // invoke createdCallback | 1255 // invoke createdCallback |
| 1251 if (inElement.createdCallback) { | 1256 if (element.createdCallback) { |
| 1252 inElement.createdCallback(); | 1257 element.createdCallback(); |
| 1253 } | 1258 } |
| 1254 } | 1259 } |
| 1255 | 1260 |
| 1256 // attribute watching | 1261 // attribute watching |
| 1257 | 1262 |
| 1258 function overrideAttributeApi(prototype) { | 1263 function overrideAttributeApi(prototype) { |
| 1259 // overrides to implement callbacks | 1264 // overrides to implement callbacks |
| 1260 // TODO(sjmiles): should support access via .attributes NamedNodeMap | 1265 // TODO(sjmiles): should support access via .attributes NamedNodeMap |
| 1261 // TODO(sjmiles): preserves user defined overrides, if any | 1266 // TODO(sjmiles): preserves user defined overrides, if any |
| 1262 var setAttribute = prototype.setAttribute; | 1267 var setAttribute = prototype.setAttribute; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1275 if (this.attributeChangedCallback | 1280 if (this.attributeChangedCallback |
| 1276 && (this.getAttribute(name) !== oldValue)) { | 1281 && (this.getAttribute(name) !== oldValue)) { |
| 1277 this.attributeChangedCallback(name, oldValue); | 1282 this.attributeChangedCallback(name, oldValue); |
| 1278 } | 1283 } |
| 1279 } | 1284 } |
| 1280 | 1285 |
| 1281 // element registry (maps tag names to definitions) | 1286 // element registry (maps tag names to definitions) |
| 1282 | 1287 |
| 1283 var registry = {}; | 1288 var registry = {}; |
| 1284 | 1289 |
| 1285 function registerDefinition(inName, inDefinition) { | 1290 function registerDefinition(name, definition) { |
| 1286 if (registry[inName]) { | 1291 if (registry[name]) { |
| 1287 throw new Error('Cannot register a tag more than once'); | 1292 throw new Error('a type with that name is already registered.'); |
| 1288 } | 1293 } |
| 1289 registry[inName] = inDefinition; | 1294 registry[name] = definition; |
| 1290 } | 1295 } |
| 1291 | 1296 |
| 1292 function generateConstructor(inDefinition) { | 1297 function generateConstructor(definition) { |
| 1293 return function() { | 1298 return function() { |
| 1294 return instantiate(inDefinition); | 1299 return instantiate(definition); |
| 1295 }; | 1300 }; |
| 1296 } | 1301 } |
| 1297 | 1302 |
| 1298 function createElement(tag, typeExtension) { | 1303 function createElement(tag, typeExtension) { |
| 1299 // TODO(sjmiles): ignore 'tag' when using 'typeExtension', we could | |
| 1300 // error check it, or perhaps there should only ever be one argument | |
| 1301 var definition = registry[typeExtension || tag]; | 1304 var definition = registry[typeExtension || tag]; |
| 1302 if (definition) { | 1305 if (definition) { |
| 1303 return new definition.ctor(); | 1306 if (tag == definition.tag && typeExtension == definition.is) { |
| 1307 return new definition.ctor(); |
| 1308 } |
| 1309 // Handle empty string for type extension. |
| 1310 if (!typeExtension && !definition.is) { |
| 1311 return new definition.ctor(); |
| 1312 } |
| 1304 } | 1313 } |
| 1305 return domCreateElement(tag); | 1314 |
| 1315 if (typeExtension) { |
| 1316 var element = createElement(tag); |
| 1317 element.setAttribute('is', typeExtension); |
| 1318 return element; |
| 1319 } |
| 1320 var element = domCreateElement(tag); |
| 1321 // Custom tags should be HTMLElements even if not upgraded. |
| 1322 if (tag.indexOf('-') >= 0) { |
| 1323 implement(element, HTMLElement); |
| 1324 } |
| 1325 return element; |
| 1306 } | 1326 } |
| 1307 | 1327 |
| 1308 function upgradeElement(inElement) { | 1328 function upgradeElement(element) { |
| 1309 if (!inElement.__upgraded__ && (inElement.nodeType === Node.ELEMENT_NODE)) { | 1329 if (!element.__upgraded__ && (element.nodeType === Node.ELEMENT_NODE)) { |
| 1310 var type = inElement.getAttribute('is') || inElement.localName; | 1330 var is = element.getAttribute('is'); |
| 1311 var definition = registry[type]; | 1331 var definition = registry[is || element.localName]; |
| 1312 return definition && upgrade(inElement, definition); | 1332 if (definition) { |
| 1333 if (is && definition.tag == element.localName) { |
| 1334 return upgrade(element, definition); |
| 1335 } else if (!is && !definition.extends) { |
| 1336 return upgrade(element, definition); |
| 1337 } |
| 1338 } |
| 1313 } | 1339 } |
| 1314 } | 1340 } |
| 1315 | 1341 |
| 1316 function cloneNode(deep) { | 1342 function cloneNode(deep) { |
| 1317 // call original clone | 1343 // call original clone |
| 1318 var n = domCloneNode.call(this, deep); | 1344 var n = domCloneNode.call(this, deep); |
| 1319 // upgrade the element and subtree | 1345 // upgrade the element and subtree |
| 1320 scope.upgradeAll(n); | 1346 scope.upgradeAll(n); |
| 1321 // return the clone | 1347 // return the clone |
| 1322 return n; | 1348 return n; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1338 scope.registry = registry; | 1364 scope.registry = registry; |
| 1339 | 1365 |
| 1340 /** | 1366 /** |
| 1341 * Upgrade an element to a custom element. Upgrading an element | 1367 * Upgrade an element to a custom element. Upgrading an element |
| 1342 * causes the custom prototype to be applied, an `is` attribute | 1368 * causes the custom prototype to be applied, an `is` attribute |
| 1343 * to be attached (as needed), and invocation of the `readyCallback`. | 1369 * to be attached (as needed), and invocation of the `readyCallback`. |
| 1344 * `upgrade` does nothing if the element is already upgraded, or | 1370 * `upgrade` does nothing if the element is already upgraded, or |
| 1345 * if it matches no registered custom tag name. | 1371 * if it matches no registered custom tag name. |
| 1346 * | 1372 * |
| 1347 * @method ugprade | 1373 * @method ugprade |
| 1348 * @param {Element} inElement The element to upgrade. | 1374 * @param {Element} element The element to upgrade. |
| 1349 * @return {Element} The upgraded element. | 1375 * @return {Element} The upgraded element. |
| 1350 */ | 1376 */ |
| 1351 scope.upgrade = upgradeElement; | 1377 scope.upgrade = upgradeElement; |
| 1352 } | 1378 } |
| 1353 | 1379 |
| 1354 scope.hasNative = hasNative; | 1380 scope.hasNative = hasNative; |
| 1355 scope.useNative = useNative; | 1381 scope.useNative = useNative; |
| 1356 | 1382 |
| 1357 })(window.CustomElements); | 1383 })(window.CustomElements); |
| 1358 | 1384 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1449 } | 1475 } |
| 1450 | 1476 |
| 1451 if (document.readyState === 'complete') { | 1477 if (document.readyState === 'complete') { |
| 1452 bootstrap(); | 1478 bootstrap(); |
| 1453 } else { | 1479 } else { |
| 1454 var loadEvent = window.HTMLImports ? 'HTMLImportsLoaded' : 'DOMContentLoaded'; | 1480 var loadEvent = window.HTMLImports ? 'HTMLImportsLoaded' : 'DOMContentLoaded'; |
| 1455 window.addEventListener(loadEvent, bootstrap); | 1481 window.addEventListener(loadEvent, bootstrap); |
| 1456 } | 1482 } |
| 1457 | 1483 |
| 1458 })(); | 1484 })(); |
| OLD | NEW |