OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 The Polymer Authors. All rights reserved. | 2 * Copyright 2012 The Polymer Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style | 3 * Use of this source code is governed by a BSD-style |
4 * license that can be found in the LICENSE file. | 4 * license that can be found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 if (typeof WeakMap === 'undefined') { | 7 if (typeof WeakMap === 'undefined') { |
8 (function() { | 8 (function() { |
9 var defineProperty = Object.defineProperty; | 9 var defineProperty = Object.defineProperty; |
10 var counter = Date.now() % 1e9; | 10 var counter = Date.now() % 1e9; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 // | 45 // |
46 // Unless required by applicable law or agreed to in writing, software | 46 // Unless required by applicable law or agreed to in writing, software |
47 // distributed under the License is distributed on an "AS IS" BASIS, | 47 // distributed under the License is distributed on an "AS IS" BASIS, |
48 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 48 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
49 // See the License for the specific language governing permissions and | 49 // See the License for the specific language governing permissions and |
50 // limitations under the License. | 50 // limitations under the License. |
51 | 51 |
52 (function(global) { | 52 (function(global) { |
53 'use strict'; | 53 'use strict'; |
54 | 54 |
55 var PROP_ADD_TYPE = 'add'; | |
56 var PROP_UPDATE_TYPE = 'update'; | |
57 var PROP_RECONFIGURE_TYPE = 'reconfigure'; | |
58 var PROP_DELETE_TYPE = 'delete'; | |
59 var ARRAY_SPLICE_TYPE = 'splice'; | |
60 | |
61 // Detect and do basic sanity checking on Object/Array.observe. | 55 // Detect and do basic sanity checking on Object/Array.observe. |
62 function detectObjectObserve() { | 56 function detectObjectObserve() { |
63 if (typeof Object.observe !== 'function' || | 57 if (typeof Object.observe !== 'function' || |
64 typeof Array.observe !== 'function') { | 58 typeof Array.observe !== 'function') { |
65 return false; | 59 return false; |
66 } | 60 } |
67 | 61 |
68 var records = []; | 62 var records = []; |
69 | 63 |
70 function callback(recs) { | 64 function callback(recs) { |
71 records = recs; | 65 records = recs; |
72 } | 66 } |
73 | 67 |
74 var test = {}; | 68 var test = {}; |
| 69 var arr = []; |
75 Object.observe(test, callback); | 70 Object.observe(test, callback); |
| 71 Array.observe(arr, callback); |
76 test.id = 1; | 72 test.id = 1; |
77 test.id = 2; | 73 test.id = 2; |
78 delete test.id; | 74 delete test.id; |
| 75 arr.push(1, 2); |
| 76 arr.length = 0; |
| 77 |
79 Object.deliverChangeRecords(callback); | 78 Object.deliverChangeRecords(callback); |
80 if (records.length !== 3) | 79 if (records.length !== 5) |
81 return false; | 80 return false; |
82 | 81 |
83 // TODO(rafaelw): Remove this when new change record type names make it to | 82 if (records[0].type != 'add' || |
84 // chrome release. | 83 records[1].type != 'update' || |
85 if (records[0].type == 'new' && | 84 records[2].type != 'delete' || |
86 records[1].type == 'updated' && | 85 records[3].type != 'splice' || |
87 records[2].type == 'deleted') { | 86 records[4].type != 'splice') { |
88 PROP_ADD_TYPE = 'new'; | |
89 PROP_UPDATE_TYPE = 'updated'; | |
90 PROP_RECONFIGURE_TYPE = 'reconfigured'; | |
91 PROP_DELETE_TYPE = 'deleted'; | |
92 } else if (records[0].type != 'add' || | |
93 records[1].type != 'update' || | |
94 records[2].type != 'delete') { | |
95 console.error('Unexpected change record names for Object.observe. ' + | |
96 'Using dirty-checking instead'); | |
97 return false; | 87 return false; |
98 } | 88 } |
| 89 |
99 Object.unobserve(test, callback); | 90 Object.unobserve(test, callback); |
100 | 91 Array.unobserve(arr, callback); |
101 test = [0]; | |
102 Array.observe(test, callback); | |
103 test[1] = 1; | |
104 test.length = 0; | |
105 Object.deliverChangeRecords(callback); | |
106 if (records.length != 2) | |
107 return false; | |
108 if (records[0].type != ARRAY_SPLICE_TYPE || | |
109 records[1].type != ARRAY_SPLICE_TYPE) { | |
110 return false; | |
111 } | |
112 Array.unobserve(test, callback); | |
113 | 92 |
114 return true; | 93 return true; |
115 } | 94 } |
116 | 95 |
117 var hasObserve = detectObjectObserve(); | 96 var hasObserve = detectObjectObserve(); |
118 | 97 |
119 function detectEval() { | 98 function detectEval() { |
120 // don't test for eval if document has CSP securityPolicy object and we can
see that | 99 // don't test for eval if document has CSP securityPolicy object and we can
see that |
121 // eval is not supported. This avoids an error message in console even when
the exception | 100 // eval is not supported. This avoids an error message in console even when
the exception |
122 // is caught | 101 // is caught |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 return; | 240 return; |
262 obj = obj[this[i]]; | 241 obj = obj[this[i]]; |
263 } | 242 } |
264 return obj; | 243 return obj; |
265 }, | 244 }, |
266 | 245 |
267 iterateObjects: function(obj, observe) { | 246 iterateObjects: function(obj, observe) { |
268 for (var i = 0; i < this.length; i++) { | 247 for (var i = 0; i < this.length; i++) { |
269 if (i) | 248 if (i) |
270 obj = obj[this[i - 1]]; | 249 obj = obj[this[i - 1]]; |
271 if (!obj) | 250 if (!isObject(obj)) |
272 return; | 251 return; |
273 observe(obj); | 252 observe(obj); |
274 } | 253 } |
275 }, | 254 }, |
276 | 255 |
277 compiledGetValueFromFn: function() { | 256 compiledGetValueFromFn: function() { |
278 var accessors = this.map(function(ident) { | 257 var accessors = this.map(function(ident) { |
279 return isIndex(ident) ? '["' + ident + '"]' : '.' + ident; | 258 return isIndex(ident) ? '["' + ident + '"]' : '.' + ident; |
280 }); | 259 }); |
281 | 260 |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 | 450 |
472 function newObservedSet() { | 451 function newObservedSet() { |
473 var observers = []; | 452 var observers = []; |
474 var observerCount = 0; | 453 var observerCount = 0; |
475 var objects = []; | 454 var objects = []; |
476 var toRemove = emptyArray; | 455 var toRemove = emptyArray; |
477 var resetNeeded = false; | 456 var resetNeeded = false; |
478 var resetScheduled = false; | 457 var resetScheduled = false; |
479 | 458 |
480 function observe(obj) { | 459 function observe(obj) { |
481 if (!isObject(obj)) | 460 if (!obj) |
482 return; | 461 return; |
483 | 462 |
484 var index = toRemove.indexOf(obj); | 463 var index = toRemove.indexOf(obj); |
485 if (index >= 0) { | 464 if (index >= 0) { |
486 toRemove[index] = undefined; | 465 toRemove[index] = undefined; |
487 objects.push(obj); | 466 objects.push(obj); |
488 } else if (objects.indexOf(obj) < 0) { | 467 } else if (objects.indexOf(obj) < 0) { |
489 objects.push(obj); | 468 objects.push(obj); |
490 Object.observe(obj, callback); | 469 Object.observe(obj, callback); |
491 } | 470 } |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
672 | 651 |
673 allObservers.push(observer); | 652 allObservers.push(observer); |
674 } | 653 } |
675 | 654 |
676 function removeFromAll(observer) { | 655 function removeFromAll(observer) { |
677 Observer._allObserversCount--; | 656 Observer._allObserversCount--; |
678 } | 657 } |
679 | 658 |
680 var runningMicrotaskCheckpoint = false; | 659 var runningMicrotaskCheckpoint = false; |
681 | 660 |
682 var hasDebugForceFullDelivery = typeof Object.deliverAllChangeRecords == 'func
tion'; | 661 var hasDebugForceFullDelivery = hasObserve && (function() { |
| 662 try { |
| 663 eval('%RunMicrotasks()'); |
| 664 return true; |
| 665 } catch (ex) { |
| 666 return false; |
| 667 } |
| 668 })(); |
683 | 669 |
684 global.Platform = global.Platform || {}; | 670 global.Platform = global.Platform || {}; |
685 | 671 |
686 global.Platform.performMicrotaskCheckpoint = function() { | 672 global.Platform.performMicrotaskCheckpoint = function() { |
687 if (runningMicrotaskCheckpoint) | 673 if (runningMicrotaskCheckpoint) |
688 return; | 674 return; |
689 | 675 |
690 if (hasDebugForceFullDelivery) { | 676 if (hasDebugForceFullDelivery) { |
691 Object.deliverAllChangeRecords(); | 677 eval('%RunMicrotasks()'); |
692 return; | 678 return; |
693 } | 679 } |
694 | 680 |
695 if (!collectObservers) | 681 if (!collectObservers) |
696 return; | 682 return; |
697 | 683 |
698 runningMicrotaskCheckpoint = true; | 684 runningMicrotaskCheckpoint = true; |
699 | 685 |
700 var cycles = 0; | 686 var cycles = 0; |
701 var anyChanged, toCheck; | 687 var anyChanged, toCheck; |
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1111 this.observable_.close(); | 1097 this.observable_.close(); |
1112 this.callback_ = undefined; | 1098 this.callback_ = undefined; |
1113 this.target_ = undefined; | 1099 this.target_ = undefined; |
1114 this.observable_ = undefined; | 1100 this.observable_ = undefined; |
1115 this.value_ = undefined; | 1101 this.value_ = undefined; |
1116 this.getValueFn_ = undefined; | 1102 this.getValueFn_ = undefined; |
1117 this.setValueFn_ = undefined; | 1103 this.setValueFn_ = undefined; |
1118 } | 1104 } |
1119 } | 1105 } |
1120 | 1106 |
1121 var expectedRecordTypes = {}; | 1107 var expectedRecordTypes = { |
1122 expectedRecordTypes[PROP_ADD_TYPE] = true; | 1108 add: true, |
1123 expectedRecordTypes[PROP_UPDATE_TYPE] = true; | 1109 update: true, |
1124 expectedRecordTypes[PROP_DELETE_TYPE] = true; | 1110 delete: true |
| 1111 }; |
1125 | 1112 |
1126 function notifyFunction(object, name) { | 1113 function notifyFunction(object, name) { |
1127 if (typeof Object.observe !== 'function') | 1114 if (typeof Object.observe !== 'function') |
1128 return; | 1115 return; |
1129 | 1116 |
1130 var notifier = Object.getNotifier(object); | 1117 var notifier = Object.getNotifier(object); |
1131 return function(type, oldValue) { | 1118 return function(type, oldValue) { |
1132 var changeRecord = { | 1119 var changeRecord = { |
1133 object: object, | 1120 object: object, |
1134 type: type, | 1121 type: type, |
1135 name: name | 1122 name: name |
1136 }; | 1123 }; |
1137 if (arguments.length === 2) | 1124 if (arguments.length === 2) |
1138 changeRecord.oldValue = oldValue; | 1125 changeRecord.oldValue = oldValue; |
1139 notifier.notify(changeRecord); | 1126 notifier.notify(changeRecord); |
1140 } | 1127 } |
1141 } | 1128 } |
1142 | 1129 |
1143 Observer.defineComputedProperty = function(target, name, observable) { | 1130 Observer.defineComputedProperty = function(target, name, observable) { |
1144 var notify = notifyFunction(target, name); | 1131 var notify = notifyFunction(target, name); |
1145 var value = observable.open(function(newValue, oldValue) { | 1132 var value = observable.open(function(newValue, oldValue) { |
1146 value = newValue; | 1133 value = newValue; |
1147 if (notify) | 1134 if (notify) |
1148 notify(PROP_UPDATE_TYPE, oldValue); | 1135 notify('update', oldValue); |
1149 }); | 1136 }); |
1150 | 1137 |
1151 Object.defineProperty(target, name, { | 1138 Object.defineProperty(target, name, { |
1152 get: function() { | 1139 get: function() { |
1153 observable.deliver(); | 1140 observable.deliver(); |
1154 return value; | 1141 return value; |
1155 }, | 1142 }, |
1156 set: function(newValue) { | 1143 set: function(newValue) { |
1157 observable.setValue(newValue); | 1144 observable.setValue(newValue); |
1158 return newValue; | 1145 return newValue; |
(...skipping 21 matching lines...) Expand all Loading... |
1180 var record = changeRecords[i]; | 1167 var record = changeRecords[i]; |
1181 if (!expectedRecordTypes[record.type]) { | 1168 if (!expectedRecordTypes[record.type]) { |
1182 console.error('Unknown changeRecord type: ' + record.type); | 1169 console.error('Unknown changeRecord type: ' + record.type); |
1183 console.error(record); | 1170 console.error(record); |
1184 continue; | 1171 continue; |
1185 } | 1172 } |
1186 | 1173 |
1187 if (!(record.name in oldValues)) | 1174 if (!(record.name in oldValues)) |
1188 oldValues[record.name] = record.oldValue; | 1175 oldValues[record.name] = record.oldValue; |
1189 | 1176 |
1190 if (record.type == PROP_UPDATE_TYPE) | 1177 if (record.type == 'update') |
1191 continue; | 1178 continue; |
1192 | 1179 |
1193 if (record.type == PROP_ADD_TYPE) { | 1180 if (record.type == 'add') { |
1194 if (record.name in removed) | 1181 if (record.name in removed) |
1195 delete removed[record.name]; | 1182 delete removed[record.name]; |
1196 else | 1183 else |
1197 added[record.name] = true; | 1184 added[record.name] = true; |
1198 | 1185 |
1199 continue; | 1186 continue; |
1200 } | 1187 } |
1201 | 1188 |
1202 // type = 'delete' | 1189 // type = 'delete' |
1203 if (record.name in added) { | 1190 if (record.name in added) { |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1580 if (!inserted) | 1567 if (!inserted) |
1581 splices.push(splice); | 1568 splices.push(splice); |
1582 } | 1569 } |
1583 | 1570 |
1584 function createInitialSplices(array, changeRecords) { | 1571 function createInitialSplices(array, changeRecords) { |
1585 var splices = []; | 1572 var splices = []; |
1586 | 1573 |
1587 for (var i = 0; i < changeRecords.length; i++) { | 1574 for (var i = 0; i < changeRecords.length; i++) { |
1588 var record = changeRecords[i]; | 1575 var record = changeRecords[i]; |
1589 switch(record.type) { | 1576 switch(record.type) { |
1590 case ARRAY_SPLICE_TYPE: | 1577 case 'splice': |
1591 mergeSplice(splices, record.index, record.removed.slice(), record.adde
dCount); | 1578 mergeSplice(splices, record.index, record.removed.slice(), record.adde
dCount); |
1592 break; | 1579 break; |
1593 case PROP_ADD_TYPE: | 1580 case 'add': |
1594 case PROP_UPDATE_TYPE: | 1581 case 'update': |
1595 case PROP_DELETE_TYPE: | 1582 case 'delete': |
1596 if (!isIndex(record.name)) | 1583 if (!isIndex(record.name)) |
1597 continue; | 1584 continue; |
1598 var index = toNumber(record.name); | 1585 var index = toNumber(record.name); |
1599 if (index < 0) | 1586 if (index < 0) |
1600 continue; | 1587 continue; |
1601 mergeSplice(splices, index, [record.oldValue], 1); | 1588 mergeSplice(splices, index, [record.oldValue], 1); |
1602 break; | 1589 break; |
1603 default: | 1590 default: |
1604 console.error('Unexpected record type: ' + JSON.stringify(record)); | 1591 console.error('Unexpected record type: ' + JSON.stringify(record)); |
1605 break; | 1592 break; |
(...skipping 28 matching lines...) Expand all Loading... |
1634 global.ArrayObserver.calculateSplices = function(current, previous) { | 1621 global.ArrayObserver.calculateSplices = function(current, previous) { |
1635 return arraySplice.calculateSplices(current, previous); | 1622 return arraySplice.calculateSplices(current, previous); |
1636 }; | 1623 }; |
1637 | 1624 |
1638 global.ArraySplice = ArraySplice; | 1625 global.ArraySplice = ArraySplice; |
1639 global.ObjectObserver = ObjectObserver; | 1626 global.ObjectObserver = ObjectObserver; |
1640 global.PathObserver = PathObserver; | 1627 global.PathObserver = PathObserver; |
1641 global.CompoundObserver = CompoundObserver; | 1628 global.CompoundObserver = CompoundObserver; |
1642 global.Path = Path; | 1629 global.Path = Path; |
1643 global.ObserverTransform = ObserverTransform; | 1630 global.ObserverTransform = ObserverTransform; |
1644 | |
1645 // TODO(rafaelw): Only needed for testing until new change record names | |
1646 // make it to release. | |
1647 global.Observer.changeRecordTypes = { | |
1648 add: PROP_ADD_TYPE, | |
1649 update: PROP_UPDATE_TYPE, | |
1650 reconfigure: PROP_RECONFIGURE_TYPE, | |
1651 'delete': PROP_DELETE_TYPE, | |
1652 splice: ARRAY_SPLICE_TYPE | |
1653 }; | |
1654 })(typeof global !== 'undefined' && global && typeof module !== 'undefined' && m
odule ? global : this || window); | 1631 })(typeof global !== 'undefined' && global && typeof module !== 'undefined' && m
odule ? global : this || window); |
1655 | 1632 |
1656 // prepoulate window.Platform.flags for default controls | 1633 // prepoulate window.Platform.flags for default controls |
1657 window.Platform = window.Platform || {}; | 1634 window.Platform = window.Platform || {}; |
1658 // prepopulate window.logFlags if necessary | 1635 // prepopulate window.logFlags if necessary |
1659 window.logFlags = window.logFlags || {}; | 1636 window.logFlags = window.logFlags || {}; |
1660 // process flags | 1637 // process flags |
1661 (function(scope){ | 1638 (function(scope){ |
1662 // import | 1639 // import |
1663 var flags = scope.flags || {}; | 1640 var flags = scope.flags || {}; |
1664 // populate flags from location | 1641 // populate flags from location |
1665 location.search.slice(1).split('&').forEach(function(o) { | 1642 location.search.slice(1).split('&').forEach(function(o) { |
1666 o = o.split('='); | 1643 o = o.split('='); |
1667 o[0] && (flags[o[0]] = o[1] || true); | 1644 o[0] && (flags[o[0]] = o[1] || true); |
1668 }); | 1645 }); |
1669 var entryPoint = document.currentScript || document.querySelector('script[src*
="platform.js"]'); | 1646 var entryPoint = document.currentScript || |
| 1647 document.querySelector('script[src*="platform.js"]'); |
1670 if (entryPoint) { | 1648 if (entryPoint) { |
1671 var a = entryPoint.attributes; | 1649 var a = entryPoint.attributes; |
1672 for (var i = 0, n; i < a.length; i++) { | 1650 for (var i = 0, n; i < a.length; i++) { |
1673 n = a[i]; | 1651 n = a[i]; |
1674 if (n.name !== 'src') { | 1652 if (n.name !== 'src') { |
1675 flags[n.name] = n.value || true; | 1653 flags[n.name] = n.value || true; |
1676 } | 1654 } |
1677 } | 1655 } |
1678 } | 1656 } |
1679 if (flags.log) { | 1657 if (flags.log) { |
1680 flags.log.split(',').forEach(function(f) { | 1658 flags.log.split(',').forEach(function(f) { |
1681 window.logFlags[f] = true; | 1659 window.logFlags[f] = true; |
1682 }); | 1660 }); |
1683 } | 1661 } |
1684 // If any of these flags match 'native', then force native ShadowDOM; any | 1662 // If any of these flags match 'native', then force native ShadowDOM; any |
1685 // other truthy value, or failure to detect native | 1663 // other truthy value, or failure to detect native |
1686 // ShadowDOM, results in polyfill | 1664 // ShadowDOM, results in polyfill |
1687 flags.shadow = (flags.shadow || flags.shadowdom || flags.polyfill); | 1665 flags.shadow = flags.shadow || flags.shadowdom || flags.polyfill; |
1688 if (flags.shadow === 'native') { | 1666 if (flags.shadow === 'native') { |
1689 flags.shadow = false; | 1667 flags.shadow = false; |
1690 } else { | 1668 } else { |
1691 flags.shadow = flags.shadow || !HTMLElement.prototype.createShadowRoot; | 1669 flags.shadow = flags.shadow || !HTMLElement.prototype.createShadowRoot; |
1692 } | 1670 } |
1693 | 1671 |
| 1672 if (flags.shadow && document.querySelectorAll('script').length > 1) { |
| 1673 console.warn('platform.js is not the first script on the page. ' + |
| 1674 'See http://www.polymer-project.org/docs/start/platform.html#setup ' + |
| 1675 'for details.'); |
| 1676 } |
| 1677 |
1694 // CustomElements polyfill flag | 1678 // CustomElements polyfill flag |
1695 if (flags.register) { | 1679 if (flags.register) { |
1696 window.CustomElements = window.CustomElements || {flags: {}}; | 1680 window.CustomElements = window.CustomElements || {flags: {}}; |
1697 window.CustomElements.flags.register = flags.register; | 1681 window.CustomElements.flags.register = flags.register; |
1698 } | 1682 } |
1699 | 1683 |
1700 if (flags.imports) { | 1684 if (flags.imports) { |
1701 window.HTMLImports = window.HTMLImports || {flags: {}}; | 1685 window.HTMLImports = window.HTMLImports || {flags: {}}; |
1702 window.HTMLImports.flags.imports = flags.imports; | 1686 window.HTMLImports.flags.imports = flags.imports; |
1703 } | 1687 } |
(...skipping 859 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2563 if (treeScope === this) | 2547 if (treeScope === this) |
2564 return true; | 2548 return true; |
2565 } | 2549 } |
2566 return false; | 2550 return false; |
2567 } | 2551 } |
2568 }; | 2552 }; |
2569 | 2553 |
2570 function setTreeScope(node, treeScope) { | 2554 function setTreeScope(node, treeScope) { |
2571 if (node.treeScope_ !== treeScope) { | 2555 if (node.treeScope_ !== treeScope) { |
2572 node.treeScope_ = treeScope; | 2556 node.treeScope_ = treeScope; |
| 2557 for (var sr = node.shadowRoot; sr; sr = sr.olderShadowRoot) { |
| 2558 sr.treeScope_.parent = treeScope; |
| 2559 } |
2573 for (var child = node.firstChild; child; child = child.nextSibling) { | 2560 for (var child = node.firstChild; child; child = child.nextSibling) { |
2574 setTreeScope(child, treeScope); | 2561 setTreeScope(child, treeScope); |
2575 } | 2562 } |
2576 } | 2563 } |
2577 } | 2564 } |
2578 | 2565 |
2579 function getTreeScope(node) { | 2566 function getTreeScope(node) { |
2580 if (node.treeScope_) | 2567 if (node.treeScope_) |
2581 return node.treeScope_; | 2568 return node.treeScope_; |
2582 var parent = node.parentNode; | 2569 var parent = node.parentNode; |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2759 | 2746 |
2760 function inSameTree(a, b) { | 2747 function inSameTree(a, b) { |
2761 return getTreeScope(a) === getTreeScope(b); | 2748 return getTreeScope(a) === getTreeScope(b); |
2762 } | 2749 } |
2763 | 2750 |
2764 function dispatchOriginalEvent(originalEvent) { | 2751 function dispatchOriginalEvent(originalEvent) { |
2765 // Make sure this event is only dispatched once. | 2752 // Make sure this event is only dispatched once. |
2766 if (handledEventsTable.get(originalEvent)) | 2753 if (handledEventsTable.get(originalEvent)) |
2767 return; | 2754 return; |
2768 handledEventsTable.set(originalEvent, true); | 2755 handledEventsTable.set(originalEvent, true); |
| 2756 dispatchEvent(wrap(originalEvent), wrap(originalEvent.target)); |
| 2757 } |
2769 | 2758 |
2770 return dispatchEvent(wrap(originalEvent), wrap(originalEvent.target)); | 2759 function isLoadLikeEvent(event) { |
| 2760 switch (event.type) { |
| 2761 case 'beforeunload': |
| 2762 case 'load': |
| 2763 case 'unload': |
| 2764 return true; |
| 2765 } |
| 2766 return false; |
2771 } | 2767 } |
2772 | 2768 |
2773 function dispatchEvent(event, originalWrapperTarget) { | 2769 function dispatchEvent(event, originalWrapperTarget) { |
2774 if (currentlyDispatchingEvents.get(event)) | 2770 if (currentlyDispatchingEvents.get(event)) |
2775 throw new Error('InvalidStateError') | 2771 throw new Error('InvalidStateError') |
2776 currentlyDispatchingEvents.set(event, true); | 2772 currentlyDispatchingEvents.set(event, true); |
2777 | 2773 |
2778 // Render to ensure that the event path is correct. | 2774 // Render to ensure that the event path is correct. |
2779 scope.renderAllPending(); | 2775 scope.renderAllPending(); |
2780 var eventPath = retarget(originalWrapperTarget); | 2776 var eventPath = retarget(originalWrapperTarget); |
2781 | 2777 |
2782 // For window load events the load event is dispatched at the window but | 2778 // For window "load" events the "load" event is dispatched at the window but |
2783 // the target is set to the document. | 2779 // the target is set to the document. |
2784 // | 2780 // |
2785 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#
the-end | 2781 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#
the-end |
2786 // | 2782 // |
2787 // TODO(arv): Find a less hacky way to do this. | 2783 // TODO(arv): Find a less hacky way to do this. |
2788 if (event.type === 'load' && | 2784 if (eventPath.length === 2 && |
2789 eventPath.length === 2 && | 2785 eventPath[0].target instanceof wrappers.Document && |
2790 eventPath[0].target instanceof wrappers.Document) { | 2786 isLoadLikeEvent(event)) { |
2791 eventPath.shift(); | 2787 eventPath.shift(); |
2792 } | 2788 } |
2793 | 2789 |
2794 eventPathTable.set(event, eventPath); | 2790 eventPathTable.set(event, eventPath); |
2795 | 2791 |
2796 if (dispatchCapturing(event, eventPath)) { | 2792 if (dispatchCapturing(event, eventPath)) { |
2797 if (dispatchAtTarget(event, eventPath)) { | 2793 if (dispatchAtTarget(event, eventPath)) { |
2798 dispatchBubbling(event, eventPath); | 2794 dispatchBubbling(event, eventPath); |
2799 } | 2795 } |
2800 } | 2796 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2850 function invoke(tuple, event, phase) { | 2846 function invoke(tuple, event, phase) { |
2851 var target = tuple.target; | 2847 var target = tuple.target; |
2852 var currentTarget = tuple.currentTarget; | 2848 var currentTarget = tuple.currentTarget; |
2853 | 2849 |
2854 var listeners = listenersTable.get(currentTarget); | 2850 var listeners = listenersTable.get(currentTarget); |
2855 if (!listeners) | 2851 if (!listeners) |
2856 return true; | 2852 return true; |
2857 | 2853 |
2858 if ('relatedTarget' in event) { | 2854 if ('relatedTarget' in event) { |
2859 var originalEvent = unwrap(event); | 2855 var originalEvent = unwrap(event); |
| 2856 var unwrappedRelatedTarget = originalEvent.relatedTarget; |
| 2857 |
2860 // X-Tag sets relatedTarget on a CustomEvent. If they do that there is no | 2858 // X-Tag sets relatedTarget on a CustomEvent. If they do that there is no |
2861 // way to have relatedTarget return the adjusted target but worse is that | 2859 // way to have relatedTarget return the adjusted target but worse is that |
2862 // the originalEvent might not have a relatedTarget so we hit an assert | 2860 // the originalEvent might not have a relatedTarget so we hit an assert |
2863 // when we try to wrap it. | 2861 // when we try to wrap it. |
2864 if (originalEvent.relatedTarget) { | 2862 if (unwrappedRelatedTarget) { |
2865 var relatedTarget = wrap(originalEvent.relatedTarget); | 2863 // In IE we can get objects that are not EventTargets at this point. |
| 2864 // Safari does not have an EventTarget interface so revert to checking |
| 2865 // for addEventListener as an approximation. |
| 2866 if (unwrappedRelatedTarget instanceof Object && |
| 2867 unwrappedRelatedTarget.addEventListener) { |
| 2868 var relatedTarget = wrap(unwrappedRelatedTarget); |
2866 | 2869 |
2867 var adjusted = adjustRelatedTarget(currentTarget, relatedTarget); | 2870 var adjusted = adjustRelatedTarget(currentTarget, relatedTarget); |
2868 if (adjusted === target) | 2871 if (adjusted === target) |
2869 return true; | 2872 return true; |
2870 | 2873 } else { |
| 2874 adjusted = null; |
| 2875 } |
2871 relatedTargetTable.set(event, adjusted); | 2876 relatedTargetTable.set(event, adjusted); |
2872 } | 2877 } |
2873 } | 2878 } |
2874 | 2879 |
2875 eventPhaseTable.set(event, phase); | 2880 eventPhaseTable.set(event, phase); |
2876 var type = event.type; | 2881 var type = event.type; |
2877 | 2882 |
2878 var anyRemoved = false; | 2883 var anyRemoved = false; |
2879 targetTable.set(event, target); | 2884 targetTable.set(event, target); |
2880 currentTargetTable.set(event, currentTarget); | 2885 currentTargetTable.set(event, currentTarget); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2947 keyLocation: true | 2952 keyLocation: true |
2948 }; | 2953 }; |
2949 | 2954 |
2950 /** | 2955 /** |
2951 * Creates a new Event wrapper or wraps an existin native Event object. | 2956 * Creates a new Event wrapper or wraps an existin native Event object. |
2952 * @param {string|Event} type | 2957 * @param {string|Event} type |
2953 * @param {Object=} options | 2958 * @param {Object=} options |
2954 * @constructor | 2959 * @constructor |
2955 */ | 2960 */ |
2956 function Event(type, options) { | 2961 function Event(type, options) { |
2957 if (type instanceof OriginalEvent) | 2962 if (type instanceof OriginalEvent) { |
2958 this.impl = type; | 2963 var impl = type; |
2959 else | 2964 if (!OriginalBeforeUnloadEvent && impl.type === 'beforeunload') |
| 2965 return new BeforeUnloadEvent(impl); |
| 2966 this.impl = impl; |
| 2967 } else { |
2960 return wrap(constructEvent(OriginalEvent, 'Event', type, options)); | 2968 return wrap(constructEvent(OriginalEvent, 'Event', type, options)); |
| 2969 } |
2961 } | 2970 } |
2962 Event.prototype = { | 2971 Event.prototype = { |
2963 get target() { | 2972 get target() { |
2964 return targetTable.get(this); | 2973 return targetTable.get(this); |
2965 }, | 2974 }, |
2966 get currentTarget() { | 2975 get currentTarget() { |
2967 return currentTargetTable.get(this); | 2976 return currentTargetTable.get(this); |
2968 }, | 2977 }, |
2969 get eventPhase() { | 2978 get eventPhase() { |
2970 return eventPhaseTable.get(this); | 2979 return eventPhaseTable.get(this); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3033 } | 3042 } |
3034 } | 3043 } |
3035 return GenericEvent; | 3044 return GenericEvent; |
3036 } | 3045 } |
3037 | 3046 |
3038 var UIEvent = registerGenericEvent('UIEvent', Event); | 3047 var UIEvent = registerGenericEvent('UIEvent', Event); |
3039 var CustomEvent = registerGenericEvent('CustomEvent', Event); | 3048 var CustomEvent = registerGenericEvent('CustomEvent', Event); |
3040 | 3049 |
3041 var relatedTargetProto = { | 3050 var relatedTargetProto = { |
3042 get relatedTarget() { | 3051 get relatedTarget() { |
3043 return relatedTargetTable.get(this) || wrap(unwrap(this).relatedTarget); | 3052 var relatedTarget = relatedTargetTable.get(this); |
| 3053 // relatedTarget can be null. |
| 3054 if (relatedTarget !== undefined) |
| 3055 return relatedTarget; |
| 3056 return wrap(unwrap(this).relatedTarget); |
3044 } | 3057 } |
3045 }; | 3058 }; |
3046 | 3059 |
3047 function getInitFunction(name, relatedTargetIndex) { | 3060 function getInitFunction(name, relatedTargetIndex) { |
3048 return function() { | 3061 return function() { |
3049 arguments[relatedTargetIndex] = unwrap(arguments[relatedTargetIndex]); | 3062 arguments[relatedTargetIndex] = unwrap(arguments[relatedTargetIndex]); |
3050 var impl = unwrap(this); | 3063 var impl = unwrap(this); |
3051 impl[name].apply(impl, arguments); | 3064 impl[name].apply(impl, arguments); |
3052 }; | 3065 }; |
3053 } | 3066 } |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3122 ctrlKey: false, | 3135 ctrlKey: false, |
3123 altKey: false, | 3136 altKey: false, |
3124 shiftKey: false, | 3137 shiftKey: false, |
3125 metaKey: false, | 3138 metaKey: false, |
3126 button: 0, | 3139 button: 0, |
3127 relatedTarget: null | 3140 relatedTarget: null |
3128 }, 'UIEvent'); | 3141 }, 'UIEvent'); |
3129 configureEventConstructor('FocusEvent', {relatedTarget: null}, 'UIEvent'); | 3142 configureEventConstructor('FocusEvent', {relatedTarget: null}, 'UIEvent'); |
3130 } | 3143 } |
3131 | 3144 |
| 3145 // Safari 7 does not yet have BeforeUnloadEvent. |
| 3146 // https://bugs.webkit.org/show_bug.cgi?id=120849 |
| 3147 var OriginalBeforeUnloadEvent = window.BeforeUnloadEvent; |
| 3148 |
3132 function BeforeUnloadEvent(impl) { | 3149 function BeforeUnloadEvent(impl) { |
3133 Event.call(this); | 3150 Event.call(this, impl); |
3134 } | 3151 } |
3135 BeforeUnloadEvent.prototype = Object.create(Event.prototype); | 3152 BeforeUnloadEvent.prototype = Object.create(Event.prototype); |
3136 mixin(BeforeUnloadEvent.prototype, { | 3153 mixin(BeforeUnloadEvent.prototype, { |
3137 get returnValue() { | 3154 get returnValue() { |
3138 return this.impl.returnValue; | 3155 return this.impl.returnValue; |
3139 }, | 3156 }, |
3140 set returnValue(v) { | 3157 set returnValue(v) { |
3141 this.impl.returnValue = v; | 3158 this.impl.returnValue = v; |
3142 } | 3159 } |
3143 }); | 3160 }); |
3144 | 3161 |
| 3162 if (OriginalBeforeUnloadEvent) |
| 3163 registerWrapper(OriginalBeforeUnloadEvent, BeforeUnloadEvent); |
| 3164 |
3145 function isValidListener(fun) { | 3165 function isValidListener(fun) { |
3146 if (typeof fun === 'function') | 3166 if (typeof fun === 'function') |
3147 return true; | 3167 return true; |
3148 return fun && fun.handleEvent; | 3168 return fun && fun.handleEvent; |
3149 } | 3169 } |
3150 | 3170 |
3151 function isMutationEvent(type) { | 3171 function isMutationEvent(type) { |
3152 switch (type) { | 3172 switch (type) { |
3153 case 'DOMAttrModified': | 3173 case 'DOMAttrModified': |
3154 case 'DOMAttributeNameChanged': | 3174 case 'DOMAttributeNameChanged': |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3463 var assert = scope.assert; | 3483 var assert = scope.assert; |
3464 var defineWrapGetter = scope.defineWrapGetter; | 3484 var defineWrapGetter = scope.defineWrapGetter; |
3465 var enqueueMutation = scope.enqueueMutation; | 3485 var enqueueMutation = scope.enqueueMutation; |
3466 var getTreeScope = scope.getTreeScope; | 3486 var getTreeScope = scope.getTreeScope; |
3467 var isWrapper = scope.isWrapper; | 3487 var isWrapper = scope.isWrapper; |
3468 var mixin = scope.mixin; | 3488 var mixin = scope.mixin; |
3469 var registerTransientObservers = scope.registerTransientObservers; | 3489 var registerTransientObservers = scope.registerTransientObservers; |
3470 var registerWrapper = scope.registerWrapper; | 3490 var registerWrapper = scope.registerWrapper; |
3471 var setTreeScope = scope.setTreeScope; | 3491 var setTreeScope = scope.setTreeScope; |
3472 var unwrap = scope.unwrap; | 3492 var unwrap = scope.unwrap; |
| 3493 var unwrapIfNeeded = scope.unwrapIfNeeded; |
3473 var wrap = scope.wrap; | 3494 var wrap = scope.wrap; |
3474 var wrapIfNeeded = scope.wrapIfNeeded; | 3495 var wrapIfNeeded = scope.wrapIfNeeded; |
3475 var wrappers = scope.wrappers; | 3496 var wrappers = scope.wrappers; |
3476 | 3497 |
3477 function assertIsNodeWrapper(node) { | 3498 function assertIsNodeWrapper(node) { |
3478 assert(node instanceof Node); | 3499 assert(node instanceof Node); |
3479 } | 3500 } |
3480 | 3501 |
3481 function createOneElementNodeList(node) { | 3502 function createOneElementNodeList(node) { |
3482 var nodes = new NodeList(); | 3503 var nodes = new NodeList(); |
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4111 return cloneNode(this, deep); | 4132 return cloneNode(this, deep); |
4112 }, | 4133 }, |
4113 | 4134 |
4114 contains: function(child) { | 4135 contains: function(child) { |
4115 return contains(this, wrapIfNeeded(child)); | 4136 return contains(this, wrapIfNeeded(child)); |
4116 }, | 4137 }, |
4117 | 4138 |
4118 compareDocumentPosition: function(otherNode) { | 4139 compareDocumentPosition: function(otherNode) { |
4119 // This only wraps, it therefore only operates on the composed DOM and not | 4140 // This only wraps, it therefore only operates on the composed DOM and not |
4120 // the logical DOM. | 4141 // the logical DOM. |
4121 return originalCompareDocumentPosition.call(this.impl, unwrap(otherNode)); | 4142 return originalCompareDocumentPosition.call(this.impl, |
| 4143 unwrapIfNeeded(otherNode)); |
4122 }, | 4144 }, |
4123 | 4145 |
4124 normalize: function() { | 4146 normalize: function() { |
4125 var nodes = snapshotNodeList(this.childNodes); | 4147 var nodes = snapshotNodeList(this.childNodes); |
4126 var remNodes = []; | 4148 var remNodes = []; |
4127 var s = ''; | 4149 var s = ''; |
4128 var modNode; | 4150 var modNode; |
4129 | 4151 |
4130 for (var i = 0, n; i < nodes.length; i++) { | 4152 for (var i = 0, n; i < nodes.length; i++) { |
4131 n = nodes[i]; | 4153 n = nodes[i]; |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4298 get children() { | 4320 get children() { |
4299 var wrapperList = new NodeList(); | 4321 var wrapperList = new NodeList(); |
4300 var i = 0; | 4322 var i = 0; |
4301 for (var child = this.firstElementChild; | 4323 for (var child = this.firstElementChild; |
4302 child; | 4324 child; |
4303 child = child.nextElementSibling) { | 4325 child = child.nextElementSibling) { |
4304 wrapperList[i++] = child; | 4326 wrapperList[i++] = child; |
4305 } | 4327 } |
4306 wrapperList.length = i; | 4328 wrapperList.length = i; |
4307 return wrapperList; | 4329 return wrapperList; |
| 4330 }, |
| 4331 |
| 4332 remove: function() { |
| 4333 var p = this.parentNode; |
| 4334 if (p) |
| 4335 p.removeChild(this); |
4308 } | 4336 } |
4309 }; | 4337 }; |
4310 | 4338 |
4311 var ChildNodeInterface = { | 4339 var ChildNodeInterface = { |
4312 get nextElementSibling() { | 4340 get nextElementSibling() { |
4313 return forwardElement(this.nextSibling); | 4341 return forwardElement(this.nextSibling); |
4314 }, | 4342 }, |
4315 | 4343 |
4316 get previousElementSibling() { | 4344 get previousElementSibling() { |
4317 return backwardsElement(this.previousSibling); | 4345 return backwardsElement(this.previousSibling); |
(...skipping 922 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5240 mixin(HTMLSelectElement.prototype, { | 5268 mixin(HTMLSelectElement.prototype, { |
5241 add: function(element, before) { | 5269 add: function(element, before) { |
5242 if (typeof before === 'object') // also includes null | 5270 if (typeof before === 'object') // also includes null |
5243 before = unwrap(before); | 5271 before = unwrap(before); |
5244 unwrap(this).add(unwrap(element), before); | 5272 unwrap(this).add(unwrap(element), before); |
5245 }, | 5273 }, |
5246 | 5274 |
5247 remove: function(indexOrNode) { | 5275 remove: function(indexOrNode) { |
5248 // Spec only allows index but implementations allow index or node. | 5276 // Spec only allows index but implementations allow index or node. |
5249 // remove() is also allowed which is same as remove(undefined) | 5277 // remove() is also allowed which is same as remove(undefined) |
| 5278 if (indexOrNode === undefined) { |
| 5279 HTMLElement.prototype.remove.call(this); |
| 5280 return; |
| 5281 } |
| 5282 |
5250 if (typeof indexOrNode === 'object') | 5283 if (typeof indexOrNode === 'object') |
5251 indexOrNode = unwrap(indexOrNode); | 5284 indexOrNode = unwrap(indexOrNode); |
| 5285 |
5252 unwrap(this).remove(indexOrNode); | 5286 unwrap(this).remove(indexOrNode); |
5253 }, | 5287 }, |
5254 | 5288 |
5255 get form() { | 5289 get form() { |
5256 return wrap(unwrap(this).form); | 5290 return wrap(unwrap(this).form); |
5257 } | 5291 } |
5258 }); | 5292 }); |
5259 | 5293 |
5260 registerWrapper(OriginalHTMLSelectElement, HTMLSelectElement, | 5294 registerWrapper(OriginalHTMLSelectElement, HTMLSelectElement, |
5261 document.createElement('select')); | 5295 document.createElement('select')); |
(...skipping 1499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6761 }, | 6795 }, |
6762 getSelection: function() { | 6796 getSelection: function() { |
6763 renderAllPending(); | 6797 renderAllPending(); |
6764 return new Selection(originalGetSelection.call(unwrap(this))); | 6798 return new Selection(originalGetSelection.call(unwrap(this))); |
6765 } | 6799 } |
6766 }); | 6800 }); |
6767 | 6801 |
6768 if (document.registerElement) { | 6802 if (document.registerElement) { |
6769 var originalRegisterElement = document.registerElement; | 6803 var originalRegisterElement = document.registerElement; |
6770 Document.prototype.registerElement = function(tagName, object) { | 6804 Document.prototype.registerElement = function(tagName, object) { |
6771 var prototype = object.prototype; | 6805 var prototype, extendsOption; |
| 6806 if (object !== undefined) { |
| 6807 prototype = object.prototype; |
| 6808 extendsOption = object.extends; |
| 6809 } |
| 6810 |
| 6811 if (!prototype) |
| 6812 prototype = Object.create(HTMLElement.prototype); |
| 6813 |
6772 | 6814 |
6773 // If we already used the object as a prototype for another custom | 6815 // If we already used the object as a prototype for another custom |
6774 // element. | 6816 // element. |
6775 if (scope.nativePrototypeTable.get(prototype)) { | 6817 if (scope.nativePrototypeTable.get(prototype)) { |
6776 // TODO(arv): DOMException | 6818 // TODO(arv): DOMException |
6777 throw new Error('NotSupportedError'); | 6819 throw new Error('NotSupportedError'); |
6778 } | 6820 } |
6779 | 6821 |
6780 // Find first object on the prototype chain that already have a native | 6822 // Find first object on the prototype chain that already have a native |
6781 // prototype. Keep track of all the objects before that so we can create | 6823 // prototype. Keep track of all the objects before that so we can create |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6822 // if this element has been wrapped prior to registration, | 6864 // if this element has been wrapped prior to registration, |
6823 // the wrapper is stale; in this case rewrap | 6865 // the wrapper is stale; in this case rewrap |
6824 if (!(wrap(this) instanceof CustomElementConstructor)) { | 6866 if (!(wrap(this) instanceof CustomElementConstructor)) { |
6825 rewrap(this); | 6867 rewrap(this); |
6826 } | 6868 } |
6827 f.apply(wrap(this), arguments); | 6869 f.apply(wrap(this), arguments); |
6828 }; | 6870 }; |
6829 }); | 6871 }); |
6830 | 6872 |
6831 var p = {prototype: newPrototype}; | 6873 var p = {prototype: newPrototype}; |
6832 if (object.extends) | 6874 if (extendsOption) |
6833 p.extends = object.extends; | 6875 p.extends = extendsOption; |
6834 | 6876 |
6835 function CustomElementConstructor(node) { | 6877 function CustomElementConstructor(node) { |
6836 if (!node) { | 6878 if (!node) { |
6837 if (object.extends) { | 6879 if (extendsOption) { |
6838 return document.createElement(object.extends, tagName); | 6880 return document.createElement(extendsOption, tagName); |
6839 } else { | 6881 } else { |
6840 return document.createElement(tagName); | 6882 return document.createElement(tagName); |
6841 } | 6883 } |
6842 } | 6884 } |
6843 this.impl = node; | 6885 this.impl = node; |
6844 } | 6886 } |
6845 CustomElementConstructor.prototype = prototype; | 6887 CustomElementConstructor.prototype = prototype; |
6846 CustomElementConstructor.prototype.constructor = CustomElementConstructor; | 6888 CustomElementConstructor.prototype.constructor = CustomElementConstructor; |
6847 | 6889 |
6848 scope.constructorTable.set(newPrototype, CustomElementConstructor); | 6890 scope.constructorTable.set(newPrototype, CustomElementConstructor); |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7030 return new Selection(originalGetSelection.call(unwrap(this))); | 7072 return new Selection(originalGetSelection.call(unwrap(this))); |
7031 }, | 7073 }, |
7032 }); | 7074 }); |
7033 | 7075 |
7034 registerWrapper(OriginalWindow, Window); | 7076 registerWrapper(OriginalWindow, Window); |
7035 | 7077 |
7036 scope.wrappers.Window = Window; | 7078 scope.wrappers.Window = Window; |
7037 | 7079 |
7038 })(window.ShadowDOMPolyfill); | 7080 })(window.ShadowDOMPolyfill); |
7039 | 7081 |
| 7082 /** |
| 7083 * Copyright 2014 The Polymer Authors. All rights reserved. |
| 7084 * Use of this source code is goverened by a BSD-style |
| 7085 * license that can be found in the LICENSE file. |
| 7086 */ |
| 7087 |
| 7088 (function(scope) { |
| 7089 'use strict'; |
| 7090 |
| 7091 var unwrap = scope.unwrap; |
| 7092 |
| 7093 // DataTransfer (Clipboard in old Blink/WebKit) has a single method that |
| 7094 // requires wrapping. Since it is only a method we do not need a real wrapper, |
| 7095 // we can just override the method. |
| 7096 |
| 7097 var OriginalDataTransfer = window.DataTransfer || window.Clipboard; |
| 7098 var OriginalDataTransferSetDragImage = |
| 7099 OriginalDataTransfer.prototype.setDragImage; |
| 7100 |
| 7101 OriginalDataTransfer.prototype.setDragImage = function(image, x, y) { |
| 7102 OriginalDataTransferSetDragImage.call(this, unwrap(image), x, y); |
| 7103 }; |
| 7104 |
| 7105 })(window.ShadowDOMPolyfill); |
| 7106 |
7040 // Copyright 2013 The Polymer Authors. All rights reserved. | 7107 // Copyright 2013 The Polymer Authors. All rights reserved. |
7041 // Use of this source code is goverened by a BSD-style | 7108 // Use of this source code is goverened by a BSD-style |
7042 // license that can be found in the LICENSE file. | 7109 // license that can be found in the LICENSE file. |
7043 | 7110 |
7044 (function(scope) { | 7111 (function(scope) { |
7045 'use strict'; | 7112 'use strict'; |
7046 | 7113 |
7047 var isWrapperFor = scope.isWrapperFor; | 7114 var isWrapperFor = scope.isWrapperFor; |
7048 | 7115 |
7049 // This is a list of the elements we currently override the global constructor | 7116 // This is a list of the elements we currently override the global constructor |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7200 relatively simply implemented. The goal is to allow users to avoid the | 7267 relatively simply implemented. The goal is to allow users to avoid the |
7201 most obvious pitfalls and do so without compromising performance significantly
. | 7268 most obvious pitfalls and do so without compromising performance significantly
. |
7202 For ShadowDOM styling that's not covered here, a set of best practices | 7269 For ShadowDOM styling that's not covered here, a set of best practices |
7203 can be provided that should allow users to accomplish more complex styling. | 7270 can be provided that should allow users to accomplish more complex styling. |
7204 | 7271 |
7205 The following is a list of specific ShadowDOM styling features and a brief | 7272 The following is a list of specific ShadowDOM styling features and a brief |
7206 discussion of the approach used to shim. | 7273 discussion of the approach used to shim. |
7207 | 7274 |
7208 Shimmed features: | 7275 Shimmed features: |
7209 | 7276 |
7210 * :host, :ancestor: ShadowDOM allows styling of the shadowRoot's host | 7277 * :host, :host-context: ShadowDOM allows styling of the shadowRoot's host |
7211 element using the :host rule. To shim this feature, the :host styles are | 7278 element using the :host rule. To shim this feature, the :host styles are |
7212 reformatted and prefixed with a given scope name and promoted to a | 7279 reformatted and prefixed with a given scope name and promoted to a |
7213 document level stylesheet. | 7280 document level stylesheet. |
7214 For example, given a scope name of .foo, a rule like this: | 7281 For example, given a scope name of .foo, a rule like this: |
7215 | 7282 |
7216 :host { | 7283 :host { |
7217 background: red; | 7284 background: red; |
7218 } | 7285 } |
7219 } | 7286 } |
7220 | 7287 |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7374 registerRoot: function(root, name, extendsName) { | 7441 registerRoot: function(root, name, extendsName) { |
7375 var def = this.registry[name] = { | 7442 var def = this.registry[name] = { |
7376 root: root, | 7443 root: root, |
7377 name: name, | 7444 name: name, |
7378 extendsName: extendsName | 7445 extendsName: extendsName |
7379 } | 7446 } |
7380 var styles = this.findStyles(root); | 7447 var styles = this.findStyles(root); |
7381 def.rootStyles = styles; | 7448 def.rootStyles = styles; |
7382 def.scopeStyles = def.rootStyles; | 7449 def.scopeStyles = def.rootStyles; |
7383 var extendee = this.registry[def.extendsName]; | 7450 var extendee = this.registry[def.extendsName]; |
7384 if (extendee && (!root || root.querySelector('shadow'))) { | 7451 if (extendee) { |
7385 def.scopeStyles = extendee.scopeStyles.concat(def.scopeStyles); | 7452 def.scopeStyles = extendee.scopeStyles.concat(def.scopeStyles); |
7386 } | 7453 } |
7387 return def; | 7454 return def; |
7388 }, | 7455 }, |
7389 findStyles: function(root) { | 7456 findStyles: function(root) { |
7390 if (!root) { | 7457 if (!root) { |
7391 return []; | 7458 return []; |
7392 } | 7459 } |
7393 var styles = root.querySelectorAll('style'); | 7460 var styles = root.querySelectorAll('style'); |
7394 return Array.prototype.filter.call(styles, function(s) { | 7461 return Array.prototype.filter.call(styles, function(s) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7469 * .foo {... } | 7536 * .foo {... } |
7470 * | 7537 * |
7471 * and converts this to | 7538 * and converts this to |
7472 * | 7539 * |
7473 * scopeName .foo { ... } | 7540 * scopeName .foo { ... } |
7474 */ | 7541 */ |
7475 scopeCssText: function(cssText, scopeSelector) { | 7542 scopeCssText: function(cssText, scopeSelector) { |
7476 var unscoped = this.extractUnscopedRulesFromCssText(cssText); | 7543 var unscoped = this.extractUnscopedRulesFromCssText(cssText); |
7477 cssText = this.insertPolyfillHostInCssText(cssText); | 7544 cssText = this.insertPolyfillHostInCssText(cssText); |
7478 cssText = this.convertColonHost(cssText); | 7545 cssText = this.convertColonHost(cssText); |
7479 cssText = this.convertColonAncestor(cssText); | 7546 cssText = this.convertColonHostContext(cssText); |
7480 cssText = this.convertCombinators(cssText); | 7547 cssText = this.convertCombinators(cssText); |
7481 if (scopeSelector) { | 7548 if (scopeSelector) { |
7482 var self = this, cssText; | 7549 var self = this, cssText; |
7483 withCssRules(cssText, function(rules) { | 7550 withCssRules(cssText, function(rules) { |
7484 cssText = self.scopeRules(rules, scopeSelector); | 7551 cssText = self.scopeRules(rules, scopeSelector); |
7485 }); | 7552 }); |
7486 | 7553 |
7487 } | 7554 } |
7488 cssText = cssText + '\n' + unscoped; | 7555 cssText = cssText + '\n' + unscoped; |
7489 return cssText.trim(); | 7556 return cssText.trim(); |
(...skipping 28 matching lines...) Expand all Loading... |
7518 * | 7585 * |
7519 * to | 7586 * to |
7520 * | 7587 * |
7521 * scopeName.foo > .bar | 7588 * scopeName.foo > .bar |
7522 */ | 7589 */ |
7523 convertColonHost: function(cssText) { | 7590 convertColonHost: function(cssText) { |
7524 return this.convertColonRule(cssText, cssColonHostRe, | 7591 return this.convertColonRule(cssText, cssColonHostRe, |
7525 this.colonHostPartReplacer); | 7592 this.colonHostPartReplacer); |
7526 }, | 7593 }, |
7527 /* | 7594 /* |
7528 * convert a rule like :ancestor(.foo) > .bar { } | 7595 * convert a rule like :host-context(.foo) > .bar { } |
7529 * | 7596 * |
7530 * to | 7597 * to |
7531 * | 7598 * |
7532 * scopeName.foo > .bar, .foo scopeName > .bar { } | 7599 * scopeName.foo > .bar, .foo scopeName > .bar { } |
7533 * | 7600 * |
7534 * and | 7601 * and |
7535 * | 7602 * |
7536 * :ancestor(.foo:host) .bar { ... } | 7603 * :host-context(.foo:host) .bar { ... } |
7537 * | 7604 * |
7538 * to | 7605 * to |
7539 * | 7606 * |
7540 * scopeName.foo .bar { ... } | 7607 * scopeName.foo .bar { ... } |
7541 */ | 7608 */ |
7542 convertColonAncestor: function(cssText) { | 7609 convertColonHostContext: function(cssText) { |
7543 return this.convertColonRule(cssText, cssColonAncestorRe, | 7610 return this.convertColonRule(cssText, cssColonHostContextRe, |
7544 this.colonAncestorPartReplacer); | 7611 this.colonHostContextPartReplacer); |
7545 }, | 7612 }, |
7546 convertColonRule: function(cssText, regExp, partReplacer) { | 7613 convertColonRule: function(cssText, regExp, partReplacer) { |
7547 // p1 = :host, p2 = contents of (), p3 rest of rule | 7614 // p1 = :host, p2 = contents of (), p3 rest of rule |
7548 return cssText.replace(regExp, function(m, p1, p2, p3) { | 7615 return cssText.replace(regExp, function(m, p1, p2, p3) { |
7549 p1 = polyfillHostNoCombinator; | 7616 p1 = polyfillHostNoCombinator; |
7550 if (p2) { | 7617 if (p2) { |
7551 var parts = p2.split(','), r = []; | 7618 var parts = p2.split(','), r = []; |
7552 for (var i=0, l=parts.length, p; (i<l) && (p=parts[i]); i++) { | 7619 for (var i=0, l=parts.length, p; (i<l) && (p=parts[i]); i++) { |
7553 p = p.trim(); | 7620 p = p.trim(); |
7554 r.push(partReplacer(p1, p, p3)); | 7621 r.push(partReplacer(p1, p, p3)); |
7555 } | 7622 } |
7556 return r.join(','); | 7623 return r.join(','); |
7557 } else { | 7624 } else { |
7558 return p1 + p3; | 7625 return p1 + p3; |
7559 } | 7626 } |
7560 }); | 7627 }); |
7561 }, | 7628 }, |
7562 colonAncestorPartReplacer: function(host, part, suffix) { | 7629 colonHostContextPartReplacer: function(host, part, suffix) { |
7563 if (part.match(polyfillHost)) { | 7630 if (part.match(polyfillHost)) { |
7564 return this.colonHostPartReplacer(host, part, suffix); | 7631 return this.colonHostPartReplacer(host, part, suffix); |
7565 } else { | 7632 } else { |
7566 return host + part + suffix + ', ' + part + ' ' + host + suffix; | 7633 return host + part + suffix + ', ' + part + ' ' + host + suffix; |
7567 } | 7634 } |
7568 }, | 7635 }, |
7569 colonHostPartReplacer: function(host, part, suffix) { | 7636 colonHostPartReplacer: function(host, part, suffix) { |
7570 return host + part.replace(polyfillHost, '') + suffix; | 7637 return host + part.replace(polyfillHost, '') + suffix; |
7571 }, | 7638 }, |
7572 /* | 7639 /* |
7573 * Convert ^ and ^^ combinators by replacing with space. | 7640 * Convert ^ and ^^ combinators by replacing with space. |
7574 */ | 7641 */ |
7575 convertCombinators: function(cssText) { | 7642 convertCombinators: function(cssText) { |
7576 return cssText.replace(/\^\^/g, ' ').replace(/\^/g, ' '); | 7643 for (var i=0; i < combinatorsRe.length; i++) { |
| 7644 cssText = cssText.replace(combinatorsRe[i], ' '); |
| 7645 } |
| 7646 return cssText; |
7577 }, | 7647 }, |
7578 // change a selector like 'div' to 'name div' | 7648 // change a selector like 'div' to 'name div' |
7579 scopeRules: function(cssRules, scopeSelector) { | 7649 scopeRules: function(cssRules, scopeSelector) { |
7580 var cssText = ''; | 7650 var cssText = ''; |
7581 if (cssRules) { | 7651 if (cssRules) { |
7582 Array.prototype.forEach.call(cssRules, function(rule) { | 7652 Array.prototype.forEach.call(cssRules, function(rule) { |
7583 if (rule.selectorText && (rule.style && rule.style.cssText)) { | 7653 if (rule.selectorText && (rule.style && rule.style.cssText)) { |
7584 cssText += this.scopeSelector(rule.selectorText, scopeSelector, | 7654 cssText += this.scopeSelector(rule.selectorText, scopeSelector, |
7585 this.strictStyling) + ' {\n\t'; | 7655 this.strictStyling) + ' {\n\t'; |
7586 cssText += this.propertiesFromRule(rule) + '\n}\n\n'; | 7656 cssText += this.propertiesFromRule(rule) + '\n}\n\n'; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7639 var t = p.trim().replace(polyfillHostRe, ''); | 7709 var t = p.trim().replace(polyfillHostRe, ''); |
7640 if (t && (splits.indexOf(t) < 0) && (t.indexOf(attrName) < 0)) { | 7710 if (t && (splits.indexOf(t) < 0) && (t.indexOf(attrName) < 0)) { |
7641 p = t.replace(/([^:]*)(:*)(.*)/, '$1' + attrName + '$2$3') | 7711 p = t.replace(/([^:]*)(:*)(.*)/, '$1' + attrName + '$2$3') |
7642 } | 7712 } |
7643 return p; | 7713 return p; |
7644 }).join(sep); | 7714 }).join(sep); |
7645 }); | 7715 }); |
7646 return scoped; | 7716 return scoped; |
7647 }, | 7717 }, |
7648 insertPolyfillHostInCssText: function(selector) { | 7718 insertPolyfillHostInCssText: function(selector) { |
7649 return selector.replace(hostRe, polyfillHost).replace(colonHostRe, | 7719 return selector.replace(colonHostContextRe, polyfillHostContext).replace( |
7650 polyfillHost).replace(colonAncestorRe, polyfillAncestor); | 7720 colonHostRe, polyfillHost); |
7651 }, | 7721 }, |
7652 propertiesFromRule: function(rule) { | 7722 propertiesFromRule: function(rule) { |
| 7723 var cssText = rule.style.cssText; |
7653 // TODO(sorvell): Safari cssom incorrectly removes quotes from the content | 7724 // TODO(sorvell): Safari cssom incorrectly removes quotes from the content |
7654 // property. (https://bugs.webkit.org/show_bug.cgi?id=118045) | 7725 // property. (https://bugs.webkit.org/show_bug.cgi?id=118045) |
7655 if (rule.style.content && !rule.style.content.match(/['"]+/)) { | 7726 // don't replace attr rules |
7656 return rule.style.cssText.replace(/content:[^;]*;/g, 'content: \'' + | 7727 if (rule.style.content && !rule.style.content.match(/['"]+|attr/)) { |
| 7728 cssText = cssText.replace(/content:[^;]*;/g, 'content: \'' + |
7657 rule.style.content + '\';'); | 7729 rule.style.content + '\';'); |
7658 } | 7730 } |
7659 return rule.style.cssText; | 7731 // TODO(sorvell): we can workaround this issue here, but we need a list |
| 7732 // of troublesome properties to fix https://github.com/Polymer/platform/issu
es/53 |
| 7733 // |
| 7734 // inherit rules can be omitted from cssText |
| 7735 // TODO(sorvell): remove when Blink bug is fixed: |
| 7736 // https://code.google.com/p/chromium/issues/detail?id=358273 |
| 7737 var style = rule.style; |
| 7738 for (var i in style) { |
| 7739 if (style[i] === 'initial') { |
| 7740 cssText += i + ': initial; '; |
| 7741 } |
| 7742 } |
| 7743 return cssText; |
7660 }, | 7744 }, |
7661 replaceTextInStyles: function(styles, action) { | 7745 replaceTextInStyles: function(styles, action) { |
7662 if (styles && action) { | 7746 if (styles && action) { |
7663 if (!(styles instanceof Array)) { | 7747 if (!(styles instanceof Array)) { |
7664 styles = [styles]; | 7748 styles = [styles]; |
7665 } | 7749 } |
7666 Array.prototype.forEach.call(styles, function(s) { | 7750 Array.prototype.forEach.call(styles, function(s) { |
7667 s.textContent = action.call(this, s.textContent); | 7751 s.textContent = action.call(this, s.textContent); |
7668 }, this); | 7752 }, this); |
7669 } | 7753 } |
(...skipping 15 matching lines...) Expand all Loading... |
7685 // TODO(sorvell): remove either content or comment | 7769 // TODO(sorvell): remove either content or comment |
7686 cssCommentRuleRe = /\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim, | 7770 cssCommentRuleRe = /\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim, |
7687 cssContentRuleRe = /(polyfill-rule)[^}]*(content\:[\s]*'([^']*)'[^;]*;)[^}]*
}/gim, | 7771 cssContentRuleRe = /(polyfill-rule)[^}]*(content\:[\s]*'([^']*)'[^;]*;)[^}]*
}/gim, |
7688 // TODO(sorvell): remove either content or comment | 7772 // TODO(sorvell): remove either content or comment |
7689 cssCommentUnscopedRuleRe = /\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]
*\*+)*)\//gim, | 7773 cssCommentUnscopedRuleRe = /\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]
*\*+)*)\//gim, |
7690 cssContentUnscopedRuleRe = /(polyfill-unscoped-rule)[^}]*(content\:[\s]*'([^
']*)'[^;]*;)[^}]*}/gim, | 7774 cssContentUnscopedRuleRe = /(polyfill-unscoped-rule)[^}]*(content\:[\s]*'([^
']*)'[^;]*;)[^}]*}/gim, |
7691 cssPseudoRe = /::(x-[^\s{,(]*)/gim, | 7775 cssPseudoRe = /::(x-[^\s{,(]*)/gim, |
7692 cssPartRe = /::part\(([^)]*)\)/gim, | 7776 cssPartRe = /::part\(([^)]*)\)/gim, |
7693 // note: :host pre-processed to -shadowcsshost. | 7777 // note: :host pre-processed to -shadowcsshost. |
7694 polyfillHost = '-shadowcsshost', | 7778 polyfillHost = '-shadowcsshost', |
7695 // note: :ancestor pre-processed to -shadowcssancestor. | 7779 // note: :host-context pre-processed to -shadowcsshostcontext. |
7696 polyfillAncestor = '-shadowcssancestor', | 7780 polyfillHostContext = '-shadowcsscontext', |
7697 parenSuffix = ')(?:\\((' + | 7781 parenSuffix = ')(?:\\((' + |
7698 '(?:\\([^)(]*\\)|[^)(]*)+?' + | 7782 '(?:\\([^)(]*\\)|[^)(]*)+?' + |
7699 ')\\))?([^,{]*)'; | 7783 ')\\))?([^,{]*)'; |
7700 cssColonHostRe = new RegExp('(' + polyfillHost + parenSuffix, 'gim'), | 7784 cssColonHostRe = new RegExp('(' + polyfillHost + parenSuffix, 'gim'), |
7701 cssColonAncestorRe = new RegExp('(' + polyfillAncestor + parenSuffix, 'gim')
, | 7785 cssColonHostContextRe = new RegExp('(' + polyfillHostContext + parenSuffix,
'gim'), |
7702 selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$', | 7786 selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$', |
7703 hostRe = /@host/gim, | |
7704 colonHostRe = /\:host/gim, | 7787 colonHostRe = /\:host/gim, |
7705 colonAncestorRe = /\:ancestor/gim, | 7788 colonHostContextRe = /\:host-context/gim, |
7706 /* host name without combinator */ | 7789 /* host name without combinator */ |
7707 polyfillHostNoCombinator = polyfillHost + '-no-combinator', | 7790 polyfillHostNoCombinator = polyfillHost + '-no-combinator', |
7708 polyfillHostRe = new RegExp(polyfillHost, 'gim'), | 7791 polyfillHostRe = new RegExp(polyfillHost, 'gim'), |
7709 polyfillAncestorRe = new RegExp(polyfillAncestor, 'gim'); | 7792 polyfillHostContextRe = new RegExp(polyfillHostContext, 'gim'), |
| 7793 combinatorsRe = [ |
| 7794 /\^\^/g, |
| 7795 /\^/g, |
| 7796 /\/shadow\//g, |
| 7797 /\/shadow-deep\//g, |
| 7798 /::shadow/g, |
| 7799 /\/deep\//g |
| 7800 ]; |
7710 | 7801 |
7711 function stylesToCssText(styles, preserveComments) { | 7802 function stylesToCssText(styles, preserveComments) { |
7712 var cssText = ''; | 7803 var cssText = ''; |
7713 Array.prototype.forEach.call(styles, function(s) { | 7804 Array.prototype.forEach.call(styles, function(s) { |
7714 cssText += s.textContent + '\n\n'; | 7805 cssText += s.textContent + '\n\n'; |
7715 }); | 7806 }); |
7716 // strip comments for easier processing | 7807 // strip comments for easier processing |
7717 if (!preserveComments) { | 7808 if (!preserveComments) { |
7718 cssText = cssText.replace(cssCommentRe, ''); | 7809 cssText = cssText.replace(cssCommentRe, ''); |
7719 } | 7810 } |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7911 // poor man's adapter for template.content on various platform scenarios | 8002 // poor man's adapter for template.content on various platform scenarios |
7912 window.templateContent = window.templateContent || function(inTemplate) { | 8003 window.templateContent = window.templateContent || function(inTemplate) { |
7913 return inTemplate.content; | 8004 return inTemplate.content; |
7914 }; | 8005 }; |
7915 | 8006 |
7916 // so we can call wrap/unwrap without testing for ShadowDOMPolyfill | 8007 // so we can call wrap/unwrap without testing for ShadowDOMPolyfill |
7917 | 8008 |
7918 window.wrap = window.unwrap = function(n){ | 8009 window.wrap = window.unwrap = function(n){ |
7919 return n; | 8010 return n; |
7920 } | 8011 } |
7921 | 8012 |
7922 var originalCreateShadowRoot = Element.prototype.webkitCreateShadowRoot; | 8013 addEventListener('DOMContentLoaded', function() { |
7923 Element.prototype.webkitCreateShadowRoot = function() { | 8014 if (CustomElements.useNative === false) { |
7924 var elderRoot = this.webkitShadowRoot; | 8015 var originalCreateShadowRoot = Element.prototype.createShadowRoot; |
7925 var root = originalCreateShadowRoot.call(this); | 8016 Element.prototype.createShadowRoot = function() { |
7926 root.olderShadowRoot = elderRoot; | 8017 var root = originalCreateShadowRoot.call(this); |
7927 root.host = this; | 8018 CustomElements.watchShadow(this); |
7928 CustomElements.watchShadow(this); | 8019 return root; |
7929 return root; | 8020 }; |
7930 } | |
7931 | |
7932 Object.defineProperties(Element.prototype, { | |
7933 shadowRoot: { | |
7934 get: function() { | |
7935 return this.webkitShadowRoot; | |
7936 } | |
7937 }, | |
7938 createShadowRoot: { | |
7939 value: function() { | |
7940 return this.webkitCreateShadowRoot(); | |
7941 } | |
7942 } | 8021 } |
7943 }); | 8022 }); |
7944 | 8023 |
7945 window.templateContent = function(inTemplate) { | 8024 window.templateContent = function(inTemplate) { |
7946 // if MDV exists, it may need to boostrap this template to reveal content | 8025 // if MDV exists, it may need to boostrap this template to reveal content |
7947 if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) { | 8026 if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) { |
7948 HTMLTemplateElement.bootstrap(inTemplate); | 8027 HTMLTemplateElement.bootstrap(inTemplate); |
7949 } | 8028 } |
7950 // fallback when there is no Shadow DOM polyfill, no MDV polyfill, and no | 8029 // fallback when there is no Shadow DOM polyfill, no MDV polyfill, and no |
7951 // native template support | 8030 // native template support |
7952 if (!inTemplate.content && !inTemplate._content) { | 8031 if (!inTemplate.content && !inTemplate._content) { |
7953 var frag = document.createDocumentFragment(); | 8032 var frag = document.createDocumentFragment(); |
7954 while (inTemplate.firstChild) { | 8033 while (inTemplate.firstChild) { |
(...skipping 1827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9782 // don't need fetch | 9861 // don't need fetch |
9783 return true; | 9862 return true; |
9784 } | 9863 } |
9785 // first node waiting for inUrl | 9864 // first node waiting for inUrl |
9786 this.pending[url] = [elt]; | 9865 this.pending[url] = [elt]; |
9787 // need fetch (not a dupe) | 9866 // need fetch (not a dupe) |
9788 return false; | 9867 return false; |
9789 }, | 9868 }, |
9790 fetch: function(url, elt) { | 9869 fetch: function(url, elt) { |
9791 flags.load && console.log('fetch', url, elt); | 9870 flags.load && console.log('fetch', url, elt); |
9792 var receiveXhr = function(err, resource) { | 9871 if (url.match(/^data:/)) { |
9793 this.receive(url, elt, err, resource); | 9872 // Handle Data URI Scheme |
9794 }.bind(this); | 9873 var pieces = url.split(','); |
9795 xhr.load(url, receiveXhr); | 9874 var header = pieces[0]; |
9796 // TODO(sorvell): blocked on | 9875 var body = pieces[1]; |
9797 // https://code.google.com/p/chromium/issues/detail?id=257221 | 9876 if(header.indexOf(';base64') > -1) { |
9798 // xhr'ing for a document makes scripts in imports runnable; otherwise | 9877 body = atob(body); |
9799 // they are not; however, it requires that we have doctype=html in | 9878 } else { |
9800 // the import which is unacceptable. This is only needed on Chrome | 9879 body = decodeURIComponent(body); |
9801 // to avoid the bug above. | 9880 } |
9802 /* | 9881 setTimeout(function() { |
9803 if (isDocumentLink(elt)) { | 9882 this.receive(url, elt, null, body); |
9804 xhr.loadDocument(url, receiveXhr); | 9883 }.bind(this), 0); |
9805 } else { | 9884 } else { |
| 9885 var receiveXhr = function(err, resource) { |
| 9886 this.receive(url, elt, err, resource); |
| 9887 }.bind(this); |
9806 xhr.load(url, receiveXhr); | 9888 xhr.load(url, receiveXhr); |
| 9889 // TODO(sorvell): blocked on) |
| 9890 // https://code.google.com/p/chromium/issues/detail?id=257221 |
| 9891 // xhr'ing for a document makes scripts in imports runnable; otherwise |
| 9892 // they are not; however, it requires that we have doctype=html in |
| 9893 // the import which is unacceptable. This is only needed on Chrome |
| 9894 // to avoid the bug above. |
| 9895 /* |
| 9896 if (isDocumentLink(elt)) { |
| 9897 xhr.loadDocument(url, receiveXhr); |
| 9898 } else { |
| 9899 xhr.load(url, receiveXhr); |
| 9900 } |
| 9901 */ |
9807 } | 9902 } |
9808 */ | |
9809 }, | 9903 }, |
9810 receive: function(url, elt, err, resource) { | 9904 receive: function(url, elt, err, resource) { |
9811 this.cache[url] = resource; | 9905 this.cache[url] = resource; |
9812 var $p = this.pending[url]; | 9906 var $p = this.pending[url]; |
9813 for (var i=0, l=$p.length, p; (i<l) && (p=$p[i]); i++) { | 9907 for (var i=0, l=$p.length, p; (i<l) && (p=$p[i]); i++) { |
9814 //if (!err) { | 9908 //if (!err) { |
9815 this.onload(url, p, resource); | 9909 this.onload(url, p, resource); |
9816 //} | 9910 //} |
9817 this.tail(); | 9911 this.tail(); |
9818 } | 9912 } |
(...skipping 1104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10923 scope.upgradeElement = nop; | 11017 scope.upgradeElement = nop; |
10924 | 11018 |
10925 scope.watchShadow = nop; | 11019 scope.watchShadow = nop; |
10926 scope.upgrade = nop; | 11020 scope.upgrade = nop; |
10927 scope.upgradeAll = nop; | 11021 scope.upgradeAll = nop; |
10928 scope.upgradeSubtree = nop; | 11022 scope.upgradeSubtree = nop; |
10929 scope.observeDocument = nop; | 11023 scope.observeDocument = nop; |
10930 scope.upgradeDocument = nop; | 11024 scope.upgradeDocument = nop; |
10931 scope.upgradeDocumentTree = nop; | 11025 scope.upgradeDocumentTree = nop; |
10932 scope.takeRecords = nop; | 11026 scope.takeRecords = nop; |
| 11027 scope.reservedTagList = []; |
10933 | 11028 |
10934 } else { | 11029 } else { |
10935 | 11030 |
10936 /** | 11031 /** |
10937 * Registers a custom tag name with the document. | 11032 * Registers a custom tag name with the document. |
10938 * | 11033 * |
10939 * When a registered element is created, a `readyCallback` method is called | 11034 * When a registered element is created, a `readyCallback` method is called |
10940 * in the scope of the element. The `readyCallback` method can be specified on | 11035 * in the scope of the element. The `readyCallback` method can be specified on |
10941 * either `options.prototype` or `options.lifecycle` with the latter taking | 11036 * either `options.prototype` or `options.lifecycle` with the latter taking |
10942 * precedence. | 11037 * precedence. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10979 if (!name) { | 11074 if (!name) { |
10980 // TODO(sjmiles): replace with more appropriate error (EricB can probably | 11075 // TODO(sjmiles): replace with more appropriate error (EricB can probably |
10981 // offer guidance) | 11076 // offer guidance) |
10982 throw new Error('document.registerElement: first argument `name` must not
be empty'); | 11077 throw new Error('document.registerElement: first argument `name` must not
be empty'); |
10983 } | 11078 } |
10984 if (name.indexOf('-') < 0) { | 11079 if (name.indexOf('-') < 0) { |
10985 // TODO(sjmiles): replace with more appropriate error (EricB can probably | 11080 // TODO(sjmiles): replace with more appropriate error (EricB can probably |
10986 // offer guidance) | 11081 // offer guidance) |
10987 throw new Error('document.registerElement: first argument (\'name\') must
contain a dash (\'-\'). Argument provided was \'' + String(name) + '\'.'); | 11082 throw new Error('document.registerElement: first argument (\'name\') must
contain a dash (\'-\'). Argument provided was \'' + String(name) + '\'.'); |
10988 } | 11083 } |
| 11084 // prevent registering reserved names |
| 11085 if (isReservedTag(name)) { |
| 11086 throw new Error('Failed to execute \'registerElement\' on \'Document\': Re
gistration failed for type \'' + String(name) + '\'. The type name is invalid.')
; |
| 11087 } |
10989 // elements may only be registered once | 11088 // elements may only be registered once |
10990 if (getRegisteredDefinition(name)) { | 11089 if (getRegisteredDefinition(name)) { |
10991 throw new Error('DuplicateDefinitionError: a type with name \'' + String(n
ame) + '\' is already registered'); | 11090 throw new Error('DuplicateDefinitionError: a type with name \'' + String(n
ame) + '\' is already registered'); |
10992 } | 11091 } |
10993 // must have a prototype, default to an extension of HTMLElement | 11092 // must have a prototype, default to an extension of HTMLElement |
10994 // TODO(sjmiles): probably should throw if no prototype, check spec | 11093 // TODO(sjmiles): probably should throw if no prototype, check spec |
10995 if (!definition.prototype) { | 11094 if (!definition.prototype) { |
10996 // TODO(sjmiles): replace with more appropriate error (EricB can probably | 11095 // TODO(sjmiles): replace with more appropriate error (EricB can probably |
10997 // offer guidance) | 11096 // offer guidance) |
10998 throw new Error('Options missing required prototype property'); | 11097 throw new Error('Options missing required prototype property'); |
(...skipping 23 matching lines...) Expand all Loading... |
11022 // force our .constructor to be our actual constructor | 11121 // force our .constructor to be our actual constructor |
11023 definition.prototype.constructor = definition.ctor; | 11122 definition.prototype.constructor = definition.ctor; |
11024 // if initial parsing is complete | 11123 // if initial parsing is complete |
11025 if (scope.ready) { | 11124 if (scope.ready) { |
11026 // upgrade any pre-existing nodes of this type | 11125 // upgrade any pre-existing nodes of this type |
11027 scope.upgradeDocumentTree(document); | 11126 scope.upgradeDocumentTree(document); |
11028 } | 11127 } |
11029 return definition.ctor; | 11128 return definition.ctor; |
11030 } | 11129 } |
11031 | 11130 |
| 11131 function isReservedTag(name) { |
| 11132 for (var i = 0; i < reservedTagList.length; i++) { |
| 11133 if (name === reservedTagList[i]) { |
| 11134 return true; |
| 11135 } |
| 11136 } |
| 11137 } |
| 11138 |
| 11139 var reservedTagList = [ |
| 11140 'annotation-xml', 'color-profile', 'font-face', 'font-face-src', |
| 11141 'font-face-uri', 'font-face-format', 'font-face-name', 'missing-glyph' |
| 11142 ]; |
| 11143 |
11032 function ancestry(extnds) { | 11144 function ancestry(extnds) { |
11033 var extendee = getRegisteredDefinition(extnds); | 11145 var extendee = getRegisteredDefinition(extnds); |
11034 if (extendee) { | 11146 if (extendee) { |
11035 return ancestry(extendee.extends).concat([extendee]); | 11147 return ancestry(extendee.extends).concat([extendee]); |
11036 } | 11148 } |
11037 return []; | 11149 return []; |
11038 } | 11150 } |
11039 | 11151 |
11040 function resolveTagName(definition) { | 11152 function resolveTagName(definition) { |
11041 // if we are explicitly extending something, that thing is our | 11153 // if we are explicitly extending something, that thing is our |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11318 return false; | 11430 return false; |
11319 } | 11431 } |
11320 } else { | 11432 } else { |
11321 isInstance = function(obj, base) { | 11433 isInstance = function(obj, base) { |
11322 return obj instanceof base; | 11434 return obj instanceof base; |
11323 } | 11435 } |
11324 } | 11436 } |
11325 | 11437 |
11326 // exports | 11438 // exports |
11327 scope.instanceof = isInstance; | 11439 scope.instanceof = isInstance; |
| 11440 scope.reservedTagList = reservedTagList; |
11328 | 11441 |
11329 // bc | 11442 // bc |
11330 document.register = document.registerElement; | 11443 document.register = document.registerElement; |
11331 | 11444 |
11332 scope.hasNative = hasNative; | 11445 scope.hasNative = hasNative; |
11333 scope.useNative = useNative; | 11446 scope.useNative = useNative; |
11334 | 11447 |
11335 })(window.CustomElements); | 11448 })(window.CustomElements); |
11336 | 11449 |
11337 /* | 11450 /* |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11751 window.PointerEventsPolyfill = scope; | 11864 window.PointerEventsPolyfill = scope; |
11752 })(window.PointerEventsPolyfill); | 11865 })(window.PointerEventsPolyfill); |
11753 | 11866 |
11754 /* | 11867 /* |
11755 * Copyright 2013 The Polymer Authors. All rights reserved. | 11868 * Copyright 2013 The Polymer Authors. All rights reserved. |
11756 * Use of this source code is governed by a BSD-style | 11869 * Use of this source code is governed by a BSD-style |
11757 * license that can be found in the LICENSE file. | 11870 * license that can be found in the LICENSE file. |
11758 */ | 11871 */ |
11759 (function() { | 11872 (function() { |
11760 function shadowSelector(v) { | 11873 function shadowSelector(v) { |
11761 return 'body ^^ ' + selector(v); | 11874 return 'body /shadow-deep/ ' + selector(v); |
11762 } | 11875 } |
11763 function selector(v) { | 11876 function selector(v) { |
11764 return '[touch-action="' + v + '"]'; | 11877 return '[touch-action="' + v + '"]'; |
11765 } | 11878 } |
11766 function rule(v) { | 11879 function rule(v) { |
11767 return '{ -ms-touch-action: ' + v + '; touch-action: ' + v + '; touch-action
-delay: none; }'; | 11880 return '{ -ms-touch-action: ' + v + '; touch-action: ' + v + '; touch-action
-delay: none; }'; |
11768 } | 11881 } |
11769 var attrib2css = [ | 11882 var attrib2css = [ |
11770 'none', | 11883 'none', |
11771 'auto', | 11884 'auto', |
11772 'pan-x', | 11885 'pan-x', |
11773 'pan-y', | 11886 'pan-y', |
11774 { | 11887 { |
11775 rule: 'pan-x pan-y', | 11888 rule: 'pan-x pan-y', |
11776 selectors: [ | 11889 selectors: [ |
11777 'pan-x pan-y', | 11890 'pan-x pan-y', |
11778 'pan-y pan-x' | 11891 'pan-y pan-x' |
11779 ] | 11892 ] |
11780 } | 11893 } |
11781 ]; | 11894 ]; |
11782 var styles = ''; | 11895 var styles = ''; |
11783 attrib2css.forEach(function(r) { | 11896 // only install stylesheet if the browser has touch action support |
11784 if (String(r) === r) { | 11897 var head = document.head; |
11785 styles += selector(r) + rule(r) + '\n'; | 11898 var hasNativePE = window.PointerEvent || window.MSPointerEvent; |
11786 styles += shadowSelector(r) + rule(r) + '\n'; | 11899 // only add shadow selectors if shadowdom is supported |
11787 } else { | 11900 var hasShadowRoot = !window.ShadowDOMPolyfill && document.head.createShadowRoo
t; |
11788 styles += r.selectors.map(selector) + rule(r.rule) + '\n'; | 11901 |
11789 styles += r.selectors.map(shadowSelector) + rule(r.rule) + '\n'; | 11902 if (hasNativePE) { |
11790 } | 11903 attrib2css.forEach(function(r) { |
11791 }); | 11904 if (String(r) === r) { |
11792 var el = document.createElement('style'); | 11905 styles += selector(r) + rule(r) + '\n'; |
11793 el.textContent = styles; | 11906 if (hasShadowRoot) { |
11794 document.head.appendChild(el); | 11907 styles += shadowSelector(r) + rule(r) + '\n'; |
| 11908 } |
| 11909 } else { |
| 11910 styles += r.selectors.map(selector) + rule(r.rule) + '\n'; |
| 11911 if (hasShadowRoot) { |
| 11912 styles += r.selectors.map(shadowSelector) + rule(r.rule) + '\n'; |
| 11913 } |
| 11914 } |
| 11915 }); |
| 11916 |
| 11917 var el = document.createElement('style'); |
| 11918 el.textContent = styles; |
| 11919 document.head.appendChild(el); |
| 11920 } |
11795 })(); | 11921 })(); |
11796 | 11922 |
11797 /* | 11923 /* |
11798 * Copyright 2013 The Polymer Authors. All rights reserved. | 11924 * Copyright 2013 The Polymer Authors. All rights reserved. |
11799 * Use of this source code is governed by a BSD-style | 11925 * Use of this source code is governed by a BSD-style |
11800 * license that can be found in the LICENSE file. | 11926 * license that can be found in the LICENSE file. |
11801 */ | 11927 */ |
11802 | 11928 |
11803 /** | 11929 /** |
11804 * This is the constructor for new PointerEvents. | 11930 * This is the constructor for new PointerEvents. |
11805 * | 11931 * |
11806 * New Pointer Events must be given a type, and an optional dictionary of | 11932 * New Pointer Events must be given a type, and an optional dictionary of |
11807 * initialization properties. | 11933 * initialization properties. |
11808 * | 11934 * |
11809 * Due to certain platform requirements, events returned from the constructor | 11935 * Due to certain platform requirements, events returned from the constructor |
11810 * identify as MouseEvents. | 11936 * identify as MouseEvents. |
11811 * | 11937 * |
11812 * @constructor | 11938 * @constructor |
11813 * @param {String} inType The type of the event to create. | 11939 * @param {String} inType The type of the event to create. |
11814 * @param {Object} [inDict] An optional dictionary of initial event properties. | 11940 * @param {Object} [inDict] An optional dictionary of initial event properties. |
11815 * @return {Event} A new PointerEvent of type `inType` and initialized with prop
erties from `inDict`. | 11941 * @return {Event} A new PointerEvent of type `inType` and initialized with prop
erties from `inDict`. |
11816 */ | 11942 */ |
11817 (function(scope) { | 11943 (function(scope) { |
11818 // test for DOM Level 4 Events | |
11819 var NEW_MOUSE_EVENT = false; | |
11820 var HAS_BUTTONS = false; | |
11821 try { | |
11822 var ev = new MouseEvent('click', {buttons: 1}); | |
11823 NEW_MOUSE_EVENT = true; | |
11824 HAS_BUTTONS = ev.buttons === 1; | |
11825 ev = null; | |
11826 } catch(e) { | |
11827 } | |
11828 | 11944 |
11829 var MOUSE_PROPS = [ | 11945 var MOUSE_PROPS = [ |
11830 'bubbles', | 11946 'bubbles', |
11831 'cancelable', | 11947 'cancelable', |
11832 'view', | 11948 'view', |
11833 'detail', | 11949 'detail', |
11834 'screenX', | 11950 'screenX', |
11835 'screenY', | 11951 'screenY', |
11836 'clientX', | 11952 'clientX', |
11837 'clientY', | 11953 'clientY', |
11838 'ctrlKey', | 11954 'ctrlKey', |
11839 'altKey', | 11955 'altKey', |
11840 'shiftKey', | 11956 'shiftKey', |
11841 'metaKey', | 11957 'metaKey', |
11842 'button', | 11958 'button', |
11843 'relatedTarget', | 11959 'relatedTarget', |
| 11960 'pageX', |
| 11961 'pageY' |
11844 ]; | 11962 ]; |
11845 | 11963 |
11846 var MOUSE_DEFAULTS = [ | 11964 var MOUSE_DEFAULTS = [ |
11847 false, | 11965 false, |
11848 false, | 11966 false, |
11849 null, | 11967 null, |
11850 null, | 11968 null, |
11851 0, | 11969 0, |
11852 0, | 11970 0, |
11853 0, | 11971 0, |
11854 0, | 11972 0, |
11855 false, | 11973 false, |
11856 false, | 11974 false, |
11857 false, | 11975 false, |
11858 false, | 11976 false, |
11859 0, | 11977 0, |
11860 null | 11978 null, |
| 11979 0, |
| 11980 0 |
11861 ]; | 11981 ]; |
11862 | 11982 |
11863 function PointerEvent(inType, inDict) { | 11983 function PointerEvent(inType, inDict) { |
11864 inDict = inDict || {}; | 11984 inDict = inDict || Object.create(null); |
11865 // According to the w3c spec, | 11985 |
11866 // http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-button | 11986 var e = document.createEvent('Event'); |
11867 // MouseEvent.button == 0 can mean either no mouse button depressed, or the | 11987 e.initEvent(inType, inDict.bubbles || false, inDict.cancelable || false); |
11868 // left mouse button depressed. | 11988 |
11869 // | 11989 // define inherited MouseEvent properties |
11870 // As of now, the only way to distinguish between the two states of | 11990 for(var i = 0, p; i < MOUSE_PROPS.length; i++) { |
11871 // MouseEvent.button is by using the deprecated MouseEvent.which property, a
s | 11991 p = MOUSE_PROPS[i]; |
11872 // this maps mouse buttons to positive integers > 0, and uses 0 to mean that | 11992 e[p] = inDict[p] || MOUSE_DEFAULTS[i]; |
11873 // no mouse button is held. | |
11874 // | |
11875 // MouseEvent.which is derived from MouseEvent.button at MouseEvent creation
, | |
11876 // but initMouseEvent does not expose an argument with which to set | |
11877 // MouseEvent.which. Calling initMouseEvent with a buttonArg of 0 will set | |
11878 // MouseEvent.button == 0 and MouseEvent.which == 1, breaking the expectatio
ns | |
11879 // of app developers. | |
11880 // | |
11881 // The only way to propagate the correct state of MouseEvent.which and | |
11882 // MouseEvent.button to a new MouseEvent.button == 0 and MouseEvent.which ==
0 | |
11883 // is to call initMouseEvent with a buttonArg value of -1. | |
11884 // | |
11885 // This is fixed with DOM Level 4's use of buttons | |
11886 var buttons = inDict.buttons; | |
11887 // touch has two possible buttons state: 0 and 1, rely on being told the rig
ht one | |
11888 if (!HAS_BUTTONS && !buttons && inType !== 'touch') { | |
11889 switch (inDict.which) { | |
11890 case 1: buttons = 1; break; | |
11891 case 2: buttons = 4; break; | |
11892 case 3: buttons = 2; break; | |
11893 default: buttons = 0; | |
11894 } | |
11895 } | 11993 } |
11896 | 11994 e.buttons = inDict.buttons || 0; |
11897 var e; | |
11898 if (NEW_MOUSE_EVENT) { | |
11899 e = new MouseEvent(inType, inDict); | |
11900 } else { | |
11901 e = document.createEvent('MouseEvent'); | |
11902 | |
11903 // import values from the given dictionary | |
11904 var props = {}, p; | |
11905 for(var i = 0; i < MOUSE_PROPS.length; i++) { | |
11906 p = MOUSE_PROPS[i]; | |
11907 props[p] = inDict[p] || MOUSE_DEFAULTS[i]; | |
11908 } | |
11909 | |
11910 // define the properties inherited from MouseEvent | |
11911 e.initMouseEvent( | |
11912 inType, props.bubbles, props.cancelable, props.view, props.detail, | |
11913 props.screenX, props.screenY, props.clientX, props.clientY, props.ctrlKe
y, | |
11914 props.altKey, props.shiftKey, props.metaKey, props.button, props.related
Target | |
11915 ); | |
11916 } | |
11917 | |
11918 // make the event pass instanceof checks | |
11919 e.__proto__ = PointerEvent.prototype; | |
11920 | |
11921 // define the buttons property according to DOM Level 3 spec | |
11922 if (!HAS_BUTTONS) { | |
11923 // IE 10 has buttons on MouseEvent.prototype as a getter w/o any setting | |
11924 // mechanism | |
11925 Object.defineProperty(e, 'buttons', {get: function(){ return buttons; }, e
numerable: true}); | |
11926 } | |
11927 | 11995 |
11928 // Spec requires that pointers without pressure specified use 0.5 for down | 11996 // Spec requires that pointers without pressure specified use 0.5 for down |
11929 // state and 0 for up state. | 11997 // state and 0 for up state. |
11930 var pressure = 0; | 11998 var pressure = 0; |
11931 if (inDict.pressure) { | 11999 if (inDict.pressure) { |
11932 pressure = inDict.pressure; | 12000 pressure = inDict.pressure; |
11933 } else { | 12001 } else { |
11934 pressure = buttons ? 0.5 : 0; | 12002 pressure = e.buttons ? 0.5 : 0; |
11935 } | 12003 } |
11936 | 12004 |
| 12005 // add x/y properties aliased to clientX/Y |
| 12006 e.x = e.clientX; |
| 12007 e.y = e.clientY; |
| 12008 |
11937 // define the properties of the PointerEvent interface | 12009 // define the properties of the PointerEvent interface |
11938 Object.defineProperties(e, { | 12010 e.pointerId = inDict.pointerId || 0; |
11939 pointerId: { value: inDict.pointerId || 0, enumerable: true }, | 12011 e.width = inDict.width || 0; |
11940 width: { value: inDict.width || 0, enumerable: true }, | 12012 e.height = inDict.height || 0; |
11941 height: { value: inDict.height || 0, enumerable: true }, | 12013 e.pressure = pressure; |
11942 pressure: { value: pressure, enumerable: true }, | 12014 e.tiltX = inDict.tiltX || 0; |
11943 tiltX: { value: inDict.tiltX || 0, enumerable: true }, | 12015 e.tiltY = inDict.tiltY || 0; |
11944 tiltY: { value: inDict.tiltY || 0, enumerable: true }, | 12016 e.pointerType = inDict.pointerType || ''; |
11945 pointerType: { value: inDict.pointerType || '', enumerable: true }, | 12017 e.hwTimestamp = inDict.hwTimestamp || 0; |
11946 hwTimestamp: { value: inDict.hwTimestamp || 0, enumerable: true }, | 12018 e.isPrimary = inDict.isPrimary || false; |
11947 isPrimary: { value: inDict.isPrimary || false, enumerable: true } | |
11948 }); | |
11949 return e; | 12019 return e; |
11950 } | 12020 } |
11951 | 12021 |
11952 // PointerEvent extends MouseEvent | |
11953 PointerEvent.prototype = Object.create(MouseEvent.prototype); | |
11954 | |
11955 // attach to window | 12022 // attach to window |
11956 if (!scope.PointerEvent) { | 12023 if (!scope.PointerEvent) { |
11957 scope.PointerEvent = PointerEvent; | 12024 scope.PointerEvent = PointerEvent; |
11958 } | 12025 } |
11959 })(window); | 12026 })(window); |
11960 | 12027 |
11961 /* | 12028 /* |
11962 * Copyright 2013 The Polymer Authors. All rights reserved. | 12029 * Copyright 2013 The Polymer Authors. All rights reserved. |
11963 * Use of this source code is governed by a BSD-style | 12030 * Use of this source code is governed by a BSD-style |
11964 * license that can be found in the LICENSE file. | 12031 * license that can be found in the LICENSE file. |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12055 'pressure', | 12122 'pressure', |
12056 'tiltX', | 12123 'tiltX', |
12057 'tiltY', | 12124 'tiltY', |
12058 'pointerType', | 12125 'pointerType', |
12059 'hwTimestamp', | 12126 'hwTimestamp', |
12060 'isPrimary', | 12127 'isPrimary', |
12061 // event instance | 12128 // event instance |
12062 'type', | 12129 'type', |
12063 'target', | 12130 'target', |
12064 'currentTarget', | 12131 'currentTarget', |
12065 'which' | 12132 'which', |
| 12133 'pageX', |
| 12134 'pageY' |
12066 ]; | 12135 ]; |
12067 | 12136 |
12068 var CLONE_DEFAULTS = [ | 12137 var CLONE_DEFAULTS = [ |
12069 // MouseEvent | 12138 // MouseEvent |
12070 false, | 12139 false, |
12071 false, | 12140 false, |
12072 null, | 12141 null, |
12073 null, | 12142 null, |
12074 0, | 12143 0, |
12075 0, | 12144 0, |
(...skipping 14 matching lines...) Expand all Loading... |
12090 0, | 12159 0, |
12091 0, | 12160 0, |
12092 0, | 12161 0, |
12093 '', | 12162 '', |
12094 0, | 12163 0, |
12095 false, | 12164 false, |
12096 // event instance | 12165 // event instance |
12097 '', | 12166 '', |
12098 null, | 12167 null, |
12099 null, | 12168 null, |
| 12169 0, |
| 12170 0, |
12100 0 | 12171 0 |
12101 ]; | 12172 ]; |
12102 | 12173 |
12103 var HAS_SVG_INSTANCE = (typeof SVGElementInstance !== 'undefined'); | 12174 var HAS_SVG_INSTANCE = (typeof SVGElementInstance !== 'undefined'); |
12104 | 12175 |
12105 /** | 12176 /** |
12106 * This module is for normalizing events. Mouse and Touch events will be | 12177 * This module is for normalizing events. Mouse and Touch events will be |
12107 * collected here, and fire PointerEvents that have the same semantics, no | 12178 * collected here, and fire PointerEvents that have the same semantics, no |
12108 * matter the source. | 12179 * matter the source. |
12109 * Events fired: | 12180 * Events fired: |
12110 * - pointerdown: a pointing is added | 12181 * - pointerdown: a pointing is added |
12111 * - pointerup: a pointer is removed | 12182 * - pointerup: a pointer is removed |
12112 * - pointermove: a pointer is moved | 12183 * - pointermove: a pointer is moved |
12113 * - pointerover: a pointer crosses into an element | 12184 * - pointerover: a pointer crosses into an element |
12114 * - pointerout: a pointer leaves an element | 12185 * - pointerout: a pointer leaves an element |
12115 * - pointercancel: a pointer will no longer generate events | 12186 * - pointercancel: a pointer will no longer generate events |
12116 */ | 12187 */ |
12117 var dispatcher = { | 12188 var dispatcher = { |
12118 targets: new WeakMap(), | |
12119 handledEvents: new WeakMap(), | |
12120 pointermap: new scope.PointerMap(), | 12189 pointermap: new scope.PointerMap(), |
12121 eventMap: {}, | 12190 eventMap: Object.create(null), |
| 12191 captureInfo: Object.create(null), |
12122 // Scope objects for native events. | 12192 // Scope objects for native events. |
12123 // This exists for ease of testing. | 12193 // This exists for ease of testing. |
12124 eventSources: {}, | 12194 eventSources: Object.create(null), |
12125 eventSourceList: [], | 12195 eventSourceList: [], |
12126 /** | 12196 /** |
12127 * Add a new event source that will generate pointer events. | 12197 * Add a new event source that will generate pointer events. |
12128 * | 12198 * |
12129 * `inSource` must contain an array of event names named `events`, and | 12199 * `inSource` must contain an array of event names named `events`, and |
12130 * functions with the names specified in the `events` array. | 12200 * functions with the names specified in the `events` array. |
12131 * @param {string} name A name for the event source | 12201 * @param {string} name A name for the event source |
12132 * @param {Object} source A new source of platform events. | 12202 * @param {Object} source A new source of platform events. |
12133 */ | 12203 */ |
12134 registerSource: function(name, source) { | 12204 registerSource: function(name, source) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12204 this.over(event); | 12274 this.over(event); |
12205 if (!this.contains(event.target, event.relatedTarget)) { | 12275 if (!this.contains(event.target, event.relatedTarget)) { |
12206 this.enter(event); | 12276 this.enter(event); |
12207 } | 12277 } |
12208 }, | 12278 }, |
12209 // LISTENER LOGIC | 12279 // LISTENER LOGIC |
12210 eventHandler: function(inEvent) { | 12280 eventHandler: function(inEvent) { |
12211 // This is used to prevent multiple dispatch of pointerevents from | 12281 // This is used to prevent multiple dispatch of pointerevents from |
12212 // platform events. This can happen when two elements in different scopes | 12282 // platform events. This can happen when two elements in different scopes |
12213 // are set up to create pointer events, which is relevant to Shadow DOM. | 12283 // are set up to create pointer events, which is relevant to Shadow DOM. |
12214 if (this.handledEvents.get(inEvent)) { | 12284 if (inEvent._handledByPE) { |
12215 return; | 12285 return; |
12216 } | 12286 } |
12217 var type = inEvent.type; | 12287 var type = inEvent.type; |
12218 var fn = this.eventMap && this.eventMap[type]; | 12288 var fn = this.eventMap && this.eventMap[type]; |
12219 if (fn) { | 12289 if (fn) { |
12220 fn(inEvent); | 12290 fn(inEvent); |
12221 } | 12291 } |
12222 this.handledEvents.set(inEvent, true); | 12292 inEvent._handledByPE = true; |
12223 }, | 12293 }, |
12224 // set up event listeners | 12294 // set up event listeners |
12225 listen: function(target, events) { | 12295 listen: function(target, events) { |
12226 events.forEach(function(e) { | 12296 events.forEach(function(e) { |
12227 this.addEvent(target, e); | 12297 this.addEvent(target, e); |
12228 }, this); | 12298 }, this); |
12229 }, | 12299 }, |
12230 // remove event listeners | 12300 // remove event listeners |
12231 unlisten: function(target, events) { | 12301 unlisten: function(target, events) { |
12232 events.forEach(function(e) { | 12302 events.forEach(function(e) { |
(...skipping 10 matching lines...) Expand all Loading... |
12243 /** | 12313 /** |
12244 * Creates a new Event of type `inType`, based on the information in | 12314 * Creates a new Event of type `inType`, based on the information in |
12245 * `inEvent`. | 12315 * `inEvent`. |
12246 * | 12316 * |
12247 * @param {string} inType A string representing the type of event to create | 12317 * @param {string} inType A string representing the type of event to create |
12248 * @param {Event} inEvent A platform event with a target | 12318 * @param {Event} inEvent A platform event with a target |
12249 * @return {Event} A PointerEvent of type `inType` | 12319 * @return {Event} A PointerEvent of type `inType` |
12250 */ | 12320 */ |
12251 makeEvent: function(inType, inEvent) { | 12321 makeEvent: function(inType, inEvent) { |
12252 // relatedTarget must be null if pointer is captured | 12322 // relatedTarget must be null if pointer is captured |
12253 if (this.captureInfo) { | 12323 if (this.captureInfo[inEvent.pointerId]) { |
12254 inEvent.relatedTarget = null; | 12324 inEvent.relatedTarget = null; |
12255 } | 12325 } |
12256 var e = new PointerEvent(inType, inEvent); | 12326 var e = new PointerEvent(inType, inEvent); |
12257 if (inEvent.preventDefault) { | 12327 if (inEvent.preventDefault) { |
12258 e.preventDefault = inEvent.preventDefault; | 12328 e.preventDefault = inEvent.preventDefault; |
12259 } | 12329 } |
12260 this.targets.set(e, this.targets.get(inEvent) || inEvent.target); | 12330 e._target = e._target || inEvent.target; |
12261 return e; | 12331 return e; |
12262 }, | 12332 }, |
12263 // make and dispatch an event in one call | 12333 // make and dispatch an event in one call |
12264 fireEvent: function(inType, inEvent) { | 12334 fireEvent: function(inType, inEvent) { |
12265 var e = this.makeEvent(inType, inEvent); | 12335 var e = this.makeEvent(inType, inEvent); |
12266 return this.dispatchEvent(e); | 12336 return this.dispatchEvent(e); |
12267 }, | 12337 }, |
12268 /** | 12338 /** |
12269 * Returns a snapshot of inEvent, with writable properties. | 12339 * Returns a snapshot of inEvent, with writable properties. |
12270 * | 12340 * |
12271 * @param {Event} inEvent An event that contains properties to copy. | 12341 * @param {Event} inEvent An event that contains properties to copy. |
12272 * @return {Object} An object containing shallow copies of `inEvent`'s | 12342 * @return {Object} An object containing shallow copies of `inEvent`'s |
12273 * properties. | 12343 * properties. |
12274 */ | 12344 */ |
12275 cloneEvent: function(inEvent) { | 12345 cloneEvent: function(inEvent) { |
12276 var eventCopy = {}, p; | 12346 var eventCopy = Object.create(null), p; |
12277 for (var i = 0; i < CLONE_PROPS.length; i++) { | 12347 for (var i = 0; i < CLONE_PROPS.length; i++) { |
12278 p = CLONE_PROPS[i]; | 12348 p = CLONE_PROPS[i]; |
12279 eventCopy[p] = inEvent[p] || CLONE_DEFAULTS[i]; | 12349 eventCopy[p] = inEvent[p] || CLONE_DEFAULTS[i]; |
12280 // Work around SVGInstanceElement shadow tree | 12350 // Work around SVGInstanceElement shadow tree |
12281 // Return the <use> element that is represented by the instance for Safa
ri, Chrome, IE. | 12351 // Return the <use> element that is represented by the instance for Safa
ri, Chrome, IE. |
12282 // This is the behavior implemented by Firefox. | 12352 // This is the behavior implemented by Firefox. |
12283 if (HAS_SVG_INSTANCE && (p === 'target' || p === 'relatedTarget')) { | 12353 if (HAS_SVG_INSTANCE && (p === 'target' || p === 'relatedTarget')) { |
12284 if (eventCopy[p] instanceof SVGElementInstance) { | 12354 if (eventCopy[p] instanceof SVGElementInstance) { |
12285 eventCopy[p] = eventCopy[p].correspondingUseElement; | 12355 eventCopy[p] = eventCopy[p].correspondingUseElement; |
12286 } | 12356 } |
12287 } | 12357 } |
12288 } | 12358 } |
12289 // keep the semantics of preventDefault | 12359 // keep the semantics of preventDefault |
12290 if (inEvent.preventDefault) { | 12360 if (inEvent.preventDefault) { |
12291 eventCopy.preventDefault = function() { | 12361 eventCopy.preventDefault = function() { |
12292 inEvent.preventDefault(); | 12362 inEvent.preventDefault(); |
12293 }; | 12363 }; |
12294 } | 12364 } |
12295 return eventCopy; | 12365 return eventCopy; |
12296 }, | 12366 }, |
12297 getTarget: function(inEvent) { | 12367 getTarget: function(inEvent) { |
12298 // if pointer capture is set, route all events for the specified pointerId | 12368 // if pointer capture is set, route all events for the specified pointerId |
12299 // to the capture target | 12369 // to the capture target |
12300 if (this.captureInfo) { | 12370 return this.captureInfo[inEvent.pointerId] || inEvent._target; |
12301 if (this.captureInfo.id === inEvent.pointerId) { | |
12302 return this.captureInfo.target; | |
12303 } | |
12304 } | |
12305 return this.targets.get(inEvent); | |
12306 }, | 12371 }, |
12307 setCapture: function(inPointerId, inTarget) { | 12372 setCapture: function(inPointerId, inTarget) { |
12308 if (this.captureInfo) { | 12373 if (this.captureInfo[inPointerId]) { |
12309 this.releaseCapture(this.captureInfo.id); | 12374 this.releaseCapture(inPointerId); |
12310 } | 12375 } |
12311 this.captureInfo = {id: inPointerId, target: inTarget}; | 12376 this.captureInfo[inPointerId] = inTarget; |
12312 var e = new PointerEvent('gotpointercapture', { bubbles: true }); | 12377 var e = document.createEvent('Event'); |
| 12378 e.initEvent('gotpointercapture', true, false); |
| 12379 e.pointerId = inPointerId; |
12313 this.implicitRelease = this.releaseCapture.bind(this, inPointerId); | 12380 this.implicitRelease = this.releaseCapture.bind(this, inPointerId); |
12314 document.addEventListener('pointerup', this.implicitRelease); | 12381 document.addEventListener('pointerup', this.implicitRelease); |
12315 document.addEventListener('pointercancel', this.implicitRelease); | 12382 document.addEventListener('pointercancel', this.implicitRelease); |
12316 this.targets.set(e, inTarget); | 12383 e._target = inTarget; |
12317 this.asyncDispatchEvent(e); | 12384 this.asyncDispatchEvent(e); |
12318 }, | 12385 }, |
12319 releaseCapture: function(inPointerId) { | 12386 releaseCapture: function(inPointerId) { |
12320 if (this.captureInfo && this.captureInfo.id === inPointerId) { | 12387 var t = this.captureInfo[inPointerId]; |
12321 var e = new PointerEvent('lostpointercapture', { bubbles: true }); | 12388 if (t) { |
12322 var t = this.captureInfo.target; | 12389 var e = document.createEvent('Event'); |
12323 this.captureInfo = null; | 12390 e.initEvent('lostpointercapture', true, false); |
| 12391 e.pointerId = inPointerId; |
| 12392 this.captureInfo[inPointerId] = undefined; |
12324 document.removeEventListener('pointerup', this.implicitRelease); | 12393 document.removeEventListener('pointerup', this.implicitRelease); |
12325 document.removeEventListener('pointercancel', this.implicitRelease); | 12394 document.removeEventListener('pointercancel', this.implicitRelease); |
12326 this.targets.set(e, t); | 12395 e._target = t; |
12327 this.asyncDispatchEvent(e); | 12396 this.asyncDispatchEvent(e); |
12328 } | 12397 } |
12329 }, | 12398 }, |
12330 /** | 12399 /** |
12331 * Dispatches the event to its target. | 12400 * Dispatches the event to its target. |
12332 * | 12401 * |
12333 * @param {Event} inEvent The event to be dispatched. | 12402 * @param {Event} inEvent The event to be dispatched. |
12334 * @return {Boolean} True if an event handler returns true, false otherwise. | 12403 * @return {Boolean} True if an event handler returns true, false otherwise. |
12335 */ | 12404 */ |
12336 dispatchEvent: scope.external.dispatchEvent || function(inEvent) { | 12405 dispatchEvent: scope.external.dispatchEvent || function(inEvent) { |
12337 var t = this.getTarget(inEvent); | 12406 var t = this.getTarget(inEvent); |
12338 if (t) { | 12407 if (t) { |
12339 return t.dispatchEvent(inEvent); | 12408 return t.dispatchEvent(inEvent); |
12340 } | 12409 } |
12341 }, | 12410 }, |
12342 asyncDispatchEvent: function(inEvent) { | 12411 asyncDispatchEvent: function(inEvent) { |
12343 setTimeout(this.dispatchEvent.bind(this, inEvent), 0); | 12412 requestAnimationFrame(this.dispatchEvent.bind(this, inEvent)); |
12344 } | 12413 } |
12345 }; | 12414 }; |
12346 dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher); | 12415 dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher); |
12347 scope.dispatcher = dispatcher; | 12416 scope.dispatcher = dispatcher; |
12348 scope.register = dispatcher.register.bind(dispatcher); | 12417 scope.register = dispatcher.register.bind(dispatcher); |
12349 scope.unregister = dispatcher.unregister.bind(dispatcher); | 12418 scope.unregister = dispatcher.unregister.bind(dispatcher); |
12350 })(window.PointerEventsPolyfill); | 12419 })(window.PointerEventsPolyfill); |
12351 | 12420 |
12352 /* | 12421 /* |
12353 * Copyright 2013 The Polymer Authors. All rights reserved. | 12422 * Copyright 2013 The Polymer Authors. All rights reserved. |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12476 * Use of this source code is governed by a BSD-style | 12545 * Use of this source code is governed by a BSD-style |
12477 * license that can be found in the LICENSE file. | 12546 * license that can be found in the LICENSE file. |
12478 */ | 12547 */ |
12479 | 12548 |
12480 (function (scope) { | 12549 (function (scope) { |
12481 var dispatcher = scope.dispatcher; | 12550 var dispatcher = scope.dispatcher; |
12482 var pointermap = dispatcher.pointermap; | 12551 var pointermap = dispatcher.pointermap; |
12483 // radius around touchend that swallows mouse events | 12552 // radius around touchend that swallows mouse events |
12484 var DEDUP_DIST = 25; | 12553 var DEDUP_DIST = 25; |
12485 | 12554 |
| 12555 var WHICH_TO_BUTTONS = [0, 1, 4, 2]; |
| 12556 |
| 12557 var HAS_BUTTONS = false; |
| 12558 try { |
| 12559 HAS_BUTTONS = new MouseEvent('test', {buttons: 1}).buttons === 1; |
| 12560 } catch (e) {} |
| 12561 |
12486 // handler block for native mouse events | 12562 // handler block for native mouse events |
12487 var mouseEvents = { | 12563 var mouseEvents = { |
12488 POINTER_ID: 1, | 12564 POINTER_ID: 1, |
12489 POINTER_TYPE: 'mouse', | 12565 POINTER_TYPE: 'mouse', |
12490 events: [ | 12566 events: [ |
12491 'mousedown', | 12567 'mousedown', |
12492 'mousemove', | 12568 'mousemove', |
12493 'mouseup', | 12569 'mouseup', |
12494 'mouseover', | 12570 'mouseover', |
12495 'mouseout' | 12571 'mouseout' |
(...skipping 21 matching lines...) Expand all Loading... |
12517 var e = dispatcher.cloneEvent(inEvent); | 12593 var e = dispatcher.cloneEvent(inEvent); |
12518 // forward mouse preventDefault | 12594 // forward mouse preventDefault |
12519 var pd = e.preventDefault; | 12595 var pd = e.preventDefault; |
12520 e.preventDefault = function() { | 12596 e.preventDefault = function() { |
12521 inEvent.preventDefault(); | 12597 inEvent.preventDefault(); |
12522 pd(); | 12598 pd(); |
12523 }; | 12599 }; |
12524 e.pointerId = this.POINTER_ID; | 12600 e.pointerId = this.POINTER_ID; |
12525 e.isPrimary = true; | 12601 e.isPrimary = true; |
12526 e.pointerType = this.POINTER_TYPE; | 12602 e.pointerType = this.POINTER_TYPE; |
| 12603 if (!HAS_BUTTONS) { |
| 12604 e.buttons = WHICH_TO_BUTTONS[e.which] || 0; |
| 12605 } |
12527 return e; | 12606 return e; |
12528 }, | 12607 }, |
12529 mousedown: function(inEvent) { | 12608 mousedown: function(inEvent) { |
12530 if (!this.isEventSimulatedFromTouch(inEvent)) { | 12609 if (!this.isEventSimulatedFromTouch(inEvent)) { |
12531 var p = pointermap.has(this.POINTER_ID); | 12610 var p = pointermap.has(this.POINTER_ID); |
12532 // TODO(dfreedman) workaround for some elements not sending mouseup | 12611 // TODO(dfreedman) workaround for some elements not sending mouseup |
12533 // http://crbug/149091 | 12612 // http://crbug/149091 |
12534 if (p) { | 12613 if (p) { |
12535 this.cancel(inEvent); | 12614 this.cancel(inEvent); |
12536 } | 12615 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12581 })(window.PointerEventsPolyfill); | 12660 })(window.PointerEventsPolyfill); |
12582 | 12661 |
12583 /* | 12662 /* |
12584 * Copyright 2013 The Polymer Authors. All rights reserved. | 12663 * Copyright 2013 The Polymer Authors. All rights reserved. |
12585 * Use of this source code is governed by a BSD-style | 12664 * Use of this source code is governed by a BSD-style |
12586 * license that can be found in the LICENSE file. | 12665 * license that can be found in the LICENSE file. |
12587 */ | 12666 */ |
12588 | 12667 |
12589 (function(scope) { | 12668 (function(scope) { |
12590 var dispatcher = scope.dispatcher; | 12669 var dispatcher = scope.dispatcher; |
| 12670 var captureInfo = dispatcher.captureInfo; |
12591 var findTarget = scope.findTarget; | 12671 var findTarget = scope.findTarget; |
12592 var allShadows = scope.targetFinding.allShadows.bind(scope.targetFinding); | 12672 var allShadows = scope.targetFinding.allShadows.bind(scope.targetFinding); |
12593 var pointermap = dispatcher.pointermap; | 12673 var pointermap = dispatcher.pointermap; |
12594 var touchMap = Array.prototype.map.call.bind(Array.prototype.map); | 12674 var touchMap = Array.prototype.map.call.bind(Array.prototype.map); |
12595 // This should be long enough to ignore compat mouse events made by touch | 12675 // This should be long enough to ignore compat mouse events made by touch |
12596 var DEDUP_TIMEOUT = 2500; | 12676 var DEDUP_TIMEOUT = 2500; |
12597 var CLICK_COUNT_TIMEOUT = 200; | 12677 var CLICK_COUNT_TIMEOUT = 200; |
12598 var ATTRIB = 'touch-action'; | 12678 var ATTRIB = 'touch-action'; |
12599 var INSTALLER; | 12679 var INSTALLER; |
12600 // The presence of touch event handlers blocks scrolling, and so we must be ca
reful to | 12680 // The presence of touch event handlers blocks scrolling, and so we must be ca
reful to |
12601 // avoid adding handlers unnecessarily. Chrome plans to add a touch-action-de
lay property | 12681 // avoid adding handlers unnecessarily. Chrome plans to add a touch-action-de
lay property |
12602 // (crbug.com/329559) to address this, and once we have that we can opt-in to
a simpler | 12682 // (crbug.com/329559) to address this, and once we have that we can opt-in to
a simpler |
12603 // handler registration mechanism. Rather than try to predict how exactly to
opt-in to | 12683 // handler registration mechanism. Rather than try to predict how exactly to
opt-in to |
12604 // that we'll just leave this disabled until there is a build of Chrome to tes
t. | 12684 // that we'll just leave this disabled until there is a build of Chrome to tes
t. |
12605 var HAS_TOUCH_ACTION_DELAY = false; | 12685 var HAS_TOUCH_ACTION_DELAY = false; |
12606 | 12686 |
12607 // handler block for native touch events | 12687 // handler block for native touch events |
12608 var touchEvents = { | 12688 var touchEvents = { |
12609 scrollType: new WeakMap(), | |
12610 events: [ | 12689 events: [ |
12611 'touchstart', | 12690 'touchstart', |
12612 'touchmove', | 12691 'touchmove', |
12613 'touchend', | 12692 'touchend', |
12614 'touchcancel' | 12693 'touchcancel' |
12615 ], | 12694 ], |
12616 register: function(target) { | 12695 register: function(target) { |
12617 if (HAS_TOUCH_ACTION_DELAY) { | 12696 if (HAS_TOUCH_ACTION_DELAY) { |
12618 dispatcher.listen(target, this.events); | 12697 dispatcher.listen(target, this.events); |
12619 } else { | 12698 } else { |
12620 INSTALLER.enableOnSubtree(target); | 12699 INSTALLER.enableOnSubtree(target); |
12621 } | 12700 } |
12622 }, | 12701 }, |
12623 unregister: function(target) { | 12702 unregister: function(target) { |
12624 if (HAS_TOUCH_ACTION_DELAY) { | 12703 if (HAS_TOUCH_ACTION_DELAY) { |
12625 dispatcher.unlisten(target, this.events); | 12704 dispatcher.unlisten(target, this.events); |
12626 } else { | 12705 } else { |
12627 // TODO(dfreedman): is it worth it to disconnect the MO? | 12706 // TODO(dfreedman): is it worth it to disconnect the MO? |
12628 } | 12707 } |
12629 }, | 12708 }, |
12630 elementAdded: function(el) { | 12709 elementAdded: function(el) { |
12631 var a = el.getAttribute(ATTRIB); | 12710 var a = el.getAttribute(ATTRIB); |
12632 var st = this.touchActionToScrollType(a); | 12711 var st = this.touchActionToScrollType(a); |
12633 if (st) { | 12712 if (st) { |
12634 this.scrollType.set(el, st); | 12713 el._scrollType = st; |
12635 dispatcher.listen(el, this.events); | 12714 dispatcher.listen(el, this.events); |
12636 // set touch-action on shadows as well | 12715 // set touch-action on shadows as well |
12637 allShadows(el).forEach(function(s) { | 12716 allShadows(el).forEach(function(s) { |
12638 this.scrollType.set(s, st); | 12717 s._scrollType = st; |
12639 dispatcher.listen(s, this.events); | 12718 dispatcher.listen(s, this.events); |
12640 }, this); | 12719 }, this); |
12641 } | 12720 } |
12642 }, | 12721 }, |
12643 elementRemoved: function(el) { | 12722 elementRemoved: function(el) { |
12644 this.scrollType['delete'](el); | 12723 el._scrollType = undefined; |
12645 dispatcher.unlisten(el, this.events); | 12724 dispatcher.unlisten(el, this.events); |
12646 // remove touch-action from shadow | 12725 // remove touch-action from shadow |
12647 allShadows(el).forEach(function(s) { | 12726 allShadows(el).forEach(function(s) { |
12648 this.scrollType['delete'](s); | 12727 s._scrollType = undefined; |
12649 dispatcher.unlisten(s, this.events); | 12728 dispatcher.unlisten(s, this.events); |
12650 }, this); | 12729 }, this); |
12651 }, | 12730 }, |
12652 elementChanged: function(el, oldValue) { | 12731 elementChanged: function(el, oldValue) { |
12653 var a = el.getAttribute(ATTRIB); | 12732 var a = el.getAttribute(ATTRIB); |
12654 var st = this.touchActionToScrollType(a); | 12733 var st = this.touchActionToScrollType(a); |
12655 var oldSt = this.touchActionToScrollType(oldValue); | 12734 var oldSt = this.touchActionToScrollType(oldValue); |
12656 // simply update scrollType if listeners are already established | 12735 // simply update scrollType if listeners are already established |
12657 if (st && oldSt) { | 12736 if (st && oldSt) { |
12658 this.scrollType.set(el, st); | 12737 el._scrollType = st; |
12659 allShadows(el).forEach(function(s) { | 12738 allShadows(el).forEach(function(s) { |
12660 this.scrollType.set(s, st); | 12739 s._scrollType = st; |
12661 }, this); | 12740 }, this); |
12662 } else if (oldSt) { | 12741 } else if (oldSt) { |
12663 this.elementRemoved(el); | 12742 this.elementRemoved(el); |
12664 } else if (st) { | 12743 } else if (st) { |
12665 this.elementAdded(el); | 12744 this.elementAdded(el); |
12666 } | 12745 } |
12667 }, | 12746 }, |
12668 scrollTypes: { | 12747 scrollTypes: { |
12669 EMITTER: 'none', | 12748 EMITTER: 'none', |
12670 XSCROLLER: 'pan-x', | 12749 XSCROLLER: 'pan-x', |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12720 } | 12799 } |
12721 }, | 12800 }, |
12722 typeToButtons: function(type) { | 12801 typeToButtons: function(type) { |
12723 var ret = 0; | 12802 var ret = 0; |
12724 if (type === 'touchstart' || type === 'touchmove') { | 12803 if (type === 'touchstart' || type === 'touchmove') { |
12725 ret = 1; | 12804 ret = 1; |
12726 } | 12805 } |
12727 return ret; | 12806 return ret; |
12728 }, | 12807 }, |
12729 touchToPointer: function(inTouch) { | 12808 touchToPointer: function(inTouch) { |
| 12809 var cte = this.currentTouchEvent; |
12730 var e = dispatcher.cloneEvent(inTouch); | 12810 var e = dispatcher.cloneEvent(inTouch); |
12731 // Spec specifies that pointerId 1 is reserved for Mouse. | 12811 // Spec specifies that pointerId 1 is reserved for Mouse. |
12732 // Touch identifiers can start at 0. | 12812 // Touch identifiers can start at 0. |
12733 // Add 2 to the touch identifier for compatibility. | 12813 // Add 2 to the touch identifier for compatibility. |
12734 e.pointerId = inTouch.identifier + 2; | 12814 var id = e.pointerId = inTouch.identifier + 2; |
12735 e.target = findTarget(e); | 12815 e.target = captureInfo[id] || findTarget(e); |
12736 e.bubbles = true; | 12816 e.bubbles = true; |
12737 e.cancelable = true; | 12817 e.cancelable = true; |
12738 e.detail = this.clickCount; | 12818 e.detail = this.clickCount; |
12739 e.button = 0; | 12819 e.button = 0; |
12740 e.buttons = this.typeToButtons(this.currentTouchEvent); | 12820 e.buttons = this.typeToButtons(cte.type); |
12741 e.width = inTouch.webkitRadiusX || inTouch.radiusX || 0; | 12821 e.width = inTouch.webkitRadiusX || inTouch.radiusX || 0; |
12742 e.height = inTouch.webkitRadiusY || inTouch.radiusY || 0; | 12822 e.height = inTouch.webkitRadiusY || inTouch.radiusY || 0; |
12743 e.pressure = inTouch.webkitForce || inTouch.force || 0.5; | 12823 e.pressure = inTouch.webkitForce || inTouch.force || 0.5; |
12744 e.isPrimary = this.isPrimaryTouch(inTouch); | 12824 e.isPrimary = this.isPrimaryTouch(inTouch); |
12745 e.pointerType = this.POINTER_TYPE; | 12825 e.pointerType = this.POINTER_TYPE; |
| 12826 // forward touch preventDefaults |
| 12827 var self = this; |
| 12828 e.preventDefault = function() { |
| 12829 self.scrolling = false; |
| 12830 self.firstXY = null; |
| 12831 cte.preventDefault(); |
| 12832 }; |
12746 return e; | 12833 return e; |
12747 }, | 12834 }, |
12748 processTouches: function(inEvent, inFunction) { | 12835 processTouches: function(inEvent, inFunction) { |
12749 var tl = inEvent.changedTouches; | 12836 var tl = inEvent.changedTouches; |
12750 this.currentTouchEvent = inEvent.type; | 12837 this.currentTouchEvent = inEvent; |
12751 var pointers = touchMap(tl, this.touchToPointer, this); | 12838 for (var i = 0, t; i < tl.length; i++) { |
12752 // forward touch preventDefaults | 12839 t = tl[i]; |
12753 pointers.forEach(function(p) { | 12840 inFunction.call(this, this.touchToPointer(t)); |
12754 p.preventDefault = function() { | 12841 } |
12755 this.scrolling = false; | |
12756 this.firstXY = null; | |
12757 inEvent.preventDefault(); | |
12758 }; | |
12759 }, this); | |
12760 pointers.forEach(inFunction, this); | |
12761 }, | 12842 }, |
12762 // For single axis scrollers, determines whether the element should emit | 12843 // For single axis scrollers, determines whether the element should emit |
12763 // pointer events or behave as a scroller | 12844 // pointer events or behave as a scroller |
12764 shouldScroll: function(inEvent) { | 12845 shouldScroll: function(inEvent) { |
12765 if (this.firstXY) { | 12846 if (this.firstXY) { |
12766 var ret; | 12847 var ret; |
12767 var scrollAxis = this.scrollType.get(inEvent.currentTarget); | 12848 var scrollAxis = inEvent.currentTarget._scrollType; |
12768 if (scrollAxis === 'none') { | 12849 if (scrollAxis === 'none') { |
12769 // this element is a touch-action: none, should never scroll | 12850 // this element is a touch-action: none, should never scroll |
12770 ret = false; | 12851 ret = false; |
12771 } else if (scrollAxis === 'XY') { | 12852 } else if (scrollAxis === 'XY') { |
12772 // this element should always scroll | 12853 // this element should always scroll |
12773 ret = true; | 12854 ret = true; |
12774 } else { | 12855 } else { |
12775 var t = inEvent.changedTouches[0]; | 12856 var t = inEvent.changedTouches[0]; |
12776 // check the intended scroll axis, and other axis | 12857 // check the intended scroll axis, and other axis |
12777 var a = scrollAxis; | 12858 var a = scrollAxis; |
(...skipping 26 matching lines...) Expand all Loading... |
12804 // pointermap.pointers() should be < tl.length here, as the touchstart has
not | 12885 // pointermap.pointers() should be < tl.length here, as the touchstart has
not |
12805 // been processed yet. | 12886 // been processed yet. |
12806 if (pointermap.pointers() >= tl.length) { | 12887 if (pointermap.pointers() >= tl.length) { |
12807 var d = []; | 12888 var d = []; |
12808 pointermap.forEach(function(value, key) { | 12889 pointermap.forEach(function(value, key) { |
12809 // Never remove pointerId == 1, which is mouse. | 12890 // Never remove pointerId == 1, which is mouse. |
12810 // Touch identifiers are 2 smaller than their pointerId, which is the | 12891 // Touch identifiers are 2 smaller than their pointerId, which is the |
12811 // index in pointermap. | 12892 // index in pointermap. |
12812 if (key !== 1 && !this.findTouch(tl, key - 2)) { | 12893 if (key !== 1 && !this.findTouch(tl, key - 2)) { |
12813 var p = value.out; | 12894 var p = value.out; |
12814 d.push(this.touchToPointer(p)); | 12895 d.push(p); |
12815 } | 12896 } |
12816 }, this); | 12897 }, this); |
12817 d.forEach(this.cancelOut, this); | 12898 d.forEach(this.cancelOut, this); |
12818 } | 12899 } |
12819 }, | 12900 }, |
12820 touchstart: function(inEvent) { | 12901 touchstart: function(inEvent) { |
12821 this.vacuumTouches(inEvent); | 12902 this.vacuumTouches(inEvent); |
12822 this.setPrimaryTouch(inEvent.changedTouches[0]); | 12903 this.setPrimaryTouch(inEvent.changedTouches[0]); |
12823 this.dedupSynthMouse(inEvent); | 12904 this.dedupSynthMouse(inEvent); |
12824 if (!this.scrolling) { | 12905 if (!this.scrolling) { |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13020 | 13101 |
13021 /** | 13102 /** |
13022 * This module contains the handlers for native platform events. | 13103 * This module contains the handlers for native platform events. |
13023 * From here, the dispatcher is called to create unified pointer events. | 13104 * From here, the dispatcher is called to create unified pointer events. |
13024 * Included are touch events (v1), mouse events, and MSPointerEvents. | 13105 * Included are touch events (v1), mouse events, and MSPointerEvents. |
13025 */ | 13106 */ |
13026 (function(scope) { | 13107 (function(scope) { |
13027 var dispatcher = scope.dispatcher; | 13108 var dispatcher = scope.dispatcher; |
13028 | 13109 |
13029 // only activate if this platform does not have pointer events | 13110 // only activate if this platform does not have pointer events |
13030 if (window.navigator.pointerEnabled === undefined) { | 13111 if (window.PointerEvent !== scope.PointerEvent) { |
13031 Object.defineProperty(window.navigator, 'pointerEnabled', {value: true, enum
erable: true}); | |
13032 | 13112 |
13033 if (window.navigator.msPointerEnabled) { | 13113 if (window.navigator.msPointerEnabled) { |
13034 var tp = window.navigator.msMaxTouchPoints; | 13114 var tp = window.navigator.msMaxTouchPoints; |
13035 Object.defineProperty(window.navigator, 'maxTouchPoints', { | 13115 Object.defineProperty(window.navigator, 'maxTouchPoints', { |
13036 value: tp, | 13116 value: tp, |
13037 enumerable: true | 13117 enumerable: true |
13038 }); | 13118 }); |
13039 dispatcher.registerSource('ms', scope.msEvents); | 13119 dispatcher.registerSource('ms', scope.msEvents); |
13040 } else { | 13120 } else { |
13041 dispatcher.registerSource('mouse', scope.mouseEvents); | 13121 dispatcher.registerSource('mouse', scope.mouseEvents); |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13401 if (fns) { | 13481 if (fns) { |
13402 this.makeQueue(fns, inEvent); | 13482 this.makeQueue(fns, inEvent); |
13403 } | 13483 } |
13404 this.handledEvents.set(inEvent, true); | 13484 this.handledEvents.set(inEvent, true); |
13405 }, | 13485 }, |
13406 // queue event for async dispatch | 13486 // queue event for async dispatch |
13407 makeQueue: function(inHandlerFns, inEvent) { | 13487 makeQueue: function(inHandlerFns, inEvent) { |
13408 // must clone events to keep the (possibly shadowed) target correct for | 13488 // must clone events to keep the (possibly shadowed) target correct for |
13409 // async dispatching | 13489 // async dispatching |
13410 var e = this.cloneEvent(inEvent); | 13490 var e = this.cloneEvent(inEvent); |
13411 setTimeout(this.runQueue.bind(this, inHandlerFns, e), 0); | 13491 requestAnimationFrame(this.runQueue.bind(this, inHandlerFns, e)); |
13412 }, | 13492 }, |
13413 // Dispatch the queued events | 13493 // Dispatch the queued events |
13414 runQueue: function(inHandlers, inEvent) { | 13494 runQueue: function(inHandlers, inEvent) { |
13415 this.currentPointerId = inEvent.pointerId; | 13495 this.currentPointerId = inEvent.pointerId; |
13416 for (var i = 0, f, l = inHandlers.length; (i < l) && (f = inHandlers[i]);
i++) { | 13496 for (var i = 0, f, l = inHandlers.length; (i < l) && (f = inHandlers[i]);
i++) { |
13417 f(inEvent); | 13497 f(inEvent); |
13418 } | 13498 } |
13419 this.currentPointerId = 0; | 13499 this.currentPointerId = 0; |
13420 }, | 13500 }, |
13421 // set up event listeners | 13501 // set up event listeners |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13462 dispatchEvent: function(inEvent, inTarget) { | 13542 dispatchEvent: function(inEvent, inTarget) { |
13463 var t = inTarget || this.targets.get(inEvent); | 13543 var t = inTarget || this.targets.get(inEvent); |
13464 if (t) { | 13544 if (t) { |
13465 t.dispatchEvent(inEvent); | 13545 t.dispatchEvent(inEvent); |
13466 if (inEvent.tapPrevented) { | 13546 if (inEvent.tapPrevented) { |
13467 this.preventTap(this.currentPointerId); | 13547 this.preventTap(this.currentPointerId); |
13468 } | 13548 } |
13469 } | 13549 } |
13470 }, | 13550 }, |
13471 asyncDispatchEvent: function(inEvent, inTarget) { | 13551 asyncDispatchEvent: function(inEvent, inTarget) { |
13472 var fn = function() { | 13552 requestAnimationFrame(this.dispatchEvent.bind(this, inEvent, inTarget)); |
13473 this.dispatchEvent(inEvent, inTarget); | |
13474 }.bind(this); | |
13475 setTimeout(fn, 0); | |
13476 }, | 13553 }, |
13477 preventTap: function(inPointerId) { | 13554 preventTap: function(inPointerId) { |
13478 var t = this.recognizers.tap; | 13555 var t = this.recognizers.tap; |
13479 if (t){ | 13556 if (t){ |
13480 t.preventTap(inPointerId); | 13557 t.preventTap(inPointerId); |
13481 } | 13558 } |
13482 } | 13559 } |
13483 }; | 13560 }; |
13484 dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher); | 13561 dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher); |
13485 // recognizers call into the dispatcher and load later | 13562 // recognizers call into the dispatcher and load later |
(...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14084 if (angle != this.reference.angle) { | 14161 if (angle != this.reference.angle) { |
14085 this.dispatchRotate(angle, points); | 14162 this.dispatchRotate(angle, points); |
14086 } | 14163 } |
14087 }, | 14164 }, |
14088 calcChord: function() { | 14165 calcChord: function() { |
14089 var pointers = []; | 14166 var pointers = []; |
14090 pointermap.forEach(function(p) { | 14167 pointermap.forEach(function(p) { |
14091 pointers.push(p); | 14168 pointers.push(p); |
14092 }); | 14169 }); |
14093 var dist = 0; | 14170 var dist = 0; |
14094 var points = {}; | 14171 // start with at least two pointers |
| 14172 var points = {a: pointers[0], b: pointers[1]}; |
14095 var x, y, d; | 14173 var x, y, d; |
14096 for (var i = 0; i < pointers.length; i++) { | 14174 for (var i = 0; i < pointers.length; i++) { |
14097 var a = pointers[i]; | 14175 var a = pointers[i]; |
14098 for (var j = i + 1; j < pointers.length; j++) { | 14176 for (var j = i + 1; j < pointers.length; j++) { |
14099 var b = pointers[j]; | 14177 var b = pointers[j]; |
14100 x = Math.abs(a.clientX - b.clientX); | 14178 x = Math.abs(a.clientX - b.clientX); |
14101 y = Math.abs(a.clientY - b.clientY); | 14179 y = Math.abs(a.clientY - b.clientY); |
14102 d = x + y; | 14180 d = x + y; |
14103 if (d > dist) { | 14181 if (d > dist) { |
14104 dist = d; | 14182 dist = d; |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14262 // register scopes after a steadystate is reached | 14340 // register scopes after a steadystate is reached |
14263 // less MutationObserver churn | 14341 // less MutationObserver churn |
14264 document.addEventListener('readystatechange', function() { | 14342 document.addEventListener('readystatechange', function() { |
14265 if (document.readyState === 'complete') { | 14343 if (document.readyState === 'complete') { |
14266 registerScopes(); | 14344 registerScopes(); |
14267 } | 14345 } |
14268 }); | 14346 }); |
14269 } | 14347 } |
14270 })(window.PointerGestures); | 14348 })(window.PointerGestures); |
14271 | 14349 |
14272 // Copyright 2011 Google Inc. | 14350 // Copyright (c) 2014 The Polymer Project Authors. All rights reserved. |
14273 // | 14351 // This code may only be used under the BSD style license found at http://polyme
r.github.io/LICENSE.txt |
14274 // Licensed under the Apache License, Version 2.0 (the "License"); | 14352 // The complete set of authors may be found at http://polymer.github.io/AUTHORS.
txt |
14275 // you may not use this file except in compliance with the License. | 14353 // The complete set of contributors may be found at http://polymer.github.io/CON
TRIBUTORS.txt |
14276 // You may obtain a copy of the License at | 14354 // Code distributed by Google as part of the polymer project is also |
14277 // | 14355 // subject to an additional IP rights grant found at http://polymer.github.io/PA
TENTS.txt |
14278 // http://www.apache.org/licenses/LICENSE-2.0 | |
14279 // | |
14280 // Unless required by applicable law or agreed to in writing, software | |
14281 // distributed under the License is distributed on an "AS IS" BASIS, | |
14282 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14283 // See the License for the specific language governing permissions and | |
14284 // limitations under the License. | |
14285 | 14356 |
14286 (function(global) { | 14357 (function(global) { |
14287 'use strict'; | 14358 'use strict'; |
14288 | 14359 |
14289 var filter = Array.prototype.filter.call.bind(Array.prototype.filter); | 14360 var filter = Array.prototype.filter.call.bind(Array.prototype.filter); |
14290 | 14361 |
14291 function getTreeScope(node) { | 14362 function getTreeScope(node) { |
14292 while (node.parentNode) { | 14363 while (node.parentNode) { |
14293 node = node.parentNode; | 14364 node = node.parentNode; |
14294 } | 14365 } |
14295 | 14366 |
14296 return typeof node.getElementById === 'function' ? node : null; | 14367 return typeof node.getElementById === 'function' ? node : null; |
14297 } | 14368 } |
14298 | 14369 |
14299 | |
14300 Node.prototype.bind = function(name, observable) { | 14370 Node.prototype.bind = function(name, observable) { |
14301 console.error('Unhandled binding to Node: ', this, name, observable); | 14371 console.error('Unhandled binding to Node: ', this, name, observable); |
14302 }; | 14372 }; |
14303 | 14373 |
14304 function unbind(node, name) { | 14374 function updateBindings(node, name, binding) { |
14305 var bindings = node.bindings; | 14375 var bindings = node.bindings_; |
14306 if (!bindings) { | 14376 if (!bindings) |
14307 node.bindings = {}; | 14377 bindings = node.bindings_ = {}; |
14308 return; | |
14309 } | |
14310 | 14378 |
14311 var binding = bindings[name]; | 14379 if (bindings[name]) |
14312 if (!binding) | 14380 binding[name].close(); |
14313 return; | |
14314 | 14381 |
14315 binding.close(); | 14382 return bindings[name] = binding; |
14316 bindings[name] = undefined; | |
14317 } | 14383 } |
14318 | 14384 |
14319 Node.prototype.unbind = function(name) { | 14385 function returnBinding(node, name, binding) { |
14320 unbind(this, name); | 14386 return binding; |
14321 }; | 14387 } |
14322 | |
14323 Node.prototype.unbindAll = function() { | |
14324 if (!this.bindings) | |
14325 return; | |
14326 var names = Object.keys(this.bindings); | |
14327 for (var i = 0; i < names.length; i++) { | |
14328 var binding = this.bindings[names[i]]; | |
14329 if (binding) | |
14330 binding.close(); | |
14331 } | |
14332 | |
14333 this.bindings = {}; | |
14334 }; | |
14335 | 14388 |
14336 function sanitizeValue(value) { | 14389 function sanitizeValue(value) { |
14337 return value == null ? '' : value; | 14390 return value == null ? '' : value; |
14338 } | 14391 } |
14339 | 14392 |
14340 function updateText(node, value) { | 14393 function updateText(node, value) { |
14341 node.data = sanitizeValue(value); | 14394 node.data = sanitizeValue(value); |
14342 } | 14395 } |
14343 | 14396 |
14344 function textBinding(node) { | 14397 function textBinding(node) { |
14345 return function(value) { | 14398 return function(value) { |
14346 return updateText(node, value); | 14399 return updateText(node, value); |
14347 }; | 14400 }; |
14348 } | 14401 } |
14349 | 14402 |
| 14403 var maybeUpdateBindings = returnBinding; |
| 14404 |
| 14405 Object.defineProperty(Platform, 'enableBindingsReflection', { |
| 14406 get: function() { |
| 14407 return maybeUpdateBindings === updateBindings; |
| 14408 }, |
| 14409 set: function(enable) { |
| 14410 maybeUpdateBindings = enable ? updateBindings : returnBinding; |
| 14411 return enable; |
| 14412 }, |
| 14413 configurable: true |
| 14414 }); |
| 14415 |
14350 Text.prototype.bind = function(name, value, oneTime) { | 14416 Text.prototype.bind = function(name, value, oneTime) { |
14351 if (name !== 'textContent') | 14417 if (name !== 'textContent') |
14352 return Node.prototype.bind.call(this, name, value, oneTime); | 14418 return Node.prototype.bind.call(this, name, value, oneTime); |
14353 | 14419 |
14354 if (oneTime) | 14420 if (oneTime) |
14355 return updateText(this, value); | 14421 return updateText(this, value); |
14356 | 14422 |
14357 unbind(this, 'textContent'); | 14423 var observable = value; |
14358 updateText(this, value.open(textBinding(this))); | 14424 updateText(this, observable.open(textBinding(this))); |
14359 return this.bindings.textContent = value; | 14425 return maybeUpdateBindings(this, name, observable); |
14360 } | 14426 } |
14361 | 14427 |
14362 function updateAttribute(el, name, conditional, value) { | 14428 function updateAttribute(el, name, conditional, value) { |
14363 if (conditional) { | 14429 if (conditional) { |
14364 if (value) | 14430 if (value) |
14365 el.setAttribute(name, ''); | 14431 el.setAttribute(name, ''); |
14366 else | 14432 else |
14367 el.removeAttribute(name); | 14433 el.removeAttribute(name); |
14368 return; | 14434 return; |
14369 } | 14435 } |
(...skipping 10 matching lines...) Expand all Loading... |
14380 Element.prototype.bind = function(name, value, oneTime) { | 14446 Element.prototype.bind = function(name, value, oneTime) { |
14381 var conditional = name[name.length - 1] == '?'; | 14447 var conditional = name[name.length - 1] == '?'; |
14382 if (conditional) { | 14448 if (conditional) { |
14383 this.removeAttribute(name); | 14449 this.removeAttribute(name); |
14384 name = name.slice(0, -1); | 14450 name = name.slice(0, -1); |
14385 } | 14451 } |
14386 | 14452 |
14387 if (oneTime) | 14453 if (oneTime) |
14388 return updateAttribute(this, name, conditional, value); | 14454 return updateAttribute(this, name, conditional, value); |
14389 | 14455 |
14390 unbind(this, name); | 14456 |
| 14457 var observable = value; |
14391 updateAttribute(this, name, conditional, | 14458 updateAttribute(this, name, conditional, |
14392 value.open(attributeBinding(this, name, conditional))); | 14459 observable.open(attributeBinding(this, name, conditional))); |
14393 | 14460 |
14394 return this.bindings[name] = value; | 14461 return maybeUpdateBindings(this, name, observable); |
14395 }; | 14462 }; |
14396 | 14463 |
14397 var checkboxEventType; | 14464 var checkboxEventType; |
14398 (function() { | 14465 (function() { |
14399 // Attempt to feature-detect which event (change or click) is fired first | 14466 // Attempt to feature-detect which event (change or click) is fired first |
14400 // for checkboxes. | 14467 // for checkboxes. |
14401 var div = document.createElement('div'); | 14468 var div = document.createElement('div'); |
14402 var checkbox = div.appendChild(document.createElement('input')); | 14469 var checkbox = div.appendChild(document.createElement('input')); |
14403 checkbox.setAttribute('type', 'checkbox'); | 14470 checkbox.setAttribute('type', 'checkbox'); |
14404 var first; | 14471 var first; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14453 var eventType = getEventForInputType(input); | 14520 var eventType = getEventForInputType(input); |
14454 | 14521 |
14455 function eventHandler() { | 14522 function eventHandler() { |
14456 observable.setValue(input[property]); | 14523 observable.setValue(input[property]); |
14457 observable.discardChanges(); | 14524 observable.discardChanges(); |
14458 (postEventFn || noop)(input); | 14525 (postEventFn || noop)(input); |
14459 Platform.performMicrotaskCheckpoint(); | 14526 Platform.performMicrotaskCheckpoint(); |
14460 } | 14527 } |
14461 input.addEventListener(eventType, eventHandler); | 14528 input.addEventListener(eventType, eventHandler); |
14462 | 14529 |
14463 var capturedClose = observable.close; | 14530 return { |
14464 observable.close = function() { | 14531 close: function() { |
14465 if (!capturedClose) | 14532 input.removeEventListener(eventType, eventHandler); |
14466 return; | 14533 observable.close(); |
14467 input.removeEventListener(eventType, eventHandler); | 14534 }, |
14468 | 14535 |
14469 observable.close = capturedClose; | 14536 observable_: observable |
14470 observable.close(); | |
14471 capturedClose = undefined; | |
14472 } | 14537 } |
14473 } | 14538 } |
14474 | 14539 |
14475 function booleanSanitize(value) { | 14540 function booleanSanitize(value) { |
14476 return Boolean(value); | 14541 return Boolean(value); |
14477 } | 14542 } |
14478 | 14543 |
14479 // |element| is assumed to be an HTMLInputElement with |type| == 'radio'. | 14544 // |element| is assumed to be an HTMLInputElement with |type| == 'radio'. |
14480 // Returns an array containing all radio buttons other than |element| that | 14545 // Returns an array containing all radio buttons other than |element| that |
14481 // have the same |name|, either in the form that |element| belongs to or, | 14546 // have the same |name|, either in the form that |element| belongs to or, |
(...skipping 23 matching lines...) Expand all Loading... |
14505 } | 14570 } |
14506 } | 14571 } |
14507 | 14572 |
14508 function checkedPostEvent(input) { | 14573 function checkedPostEvent(input) { |
14509 // Only the radio button that is getting checked gets an event. We | 14574 // Only the radio button that is getting checked gets an event. We |
14510 // therefore find all the associated radio buttons and update their | 14575 // therefore find all the associated radio buttons and update their |
14511 // check binding manually. | 14576 // check binding manually. |
14512 if (input.tagName === 'INPUT' && | 14577 if (input.tagName === 'INPUT' && |
14513 input.type === 'radio') { | 14578 input.type === 'radio') { |
14514 getAssociatedRadioButtons(input).forEach(function(radio) { | 14579 getAssociatedRadioButtons(input).forEach(function(radio) { |
14515 var checkedBinding = radio.bindings.checked; | 14580 var checkedBinding = radio.bindings_.checked; |
14516 if (checkedBinding) { | 14581 if (checkedBinding) { |
14517 // Set the value directly to avoid an infinite call stack. | 14582 // Set the value directly to avoid an infinite call stack. |
14518 checkedBinding.setValue(false); | 14583 checkedBinding.observable_.setValue(false); |
14519 } | 14584 } |
14520 }); | 14585 }); |
14521 } | 14586 } |
14522 } | 14587 } |
14523 | 14588 |
14524 HTMLInputElement.prototype.bind = function(name, value, oneTime) { | 14589 HTMLInputElement.prototype.bind = function(name, value, oneTime) { |
14525 if (name !== 'value' && name !== 'checked') | 14590 if (name !== 'value' && name !== 'checked') |
14526 return HTMLElement.prototype.bind.call(this, name, value, oneTime); | 14591 return HTMLElement.prototype.bind.call(this, name, value, oneTime); |
14527 | 14592 |
14528 | |
14529 this.removeAttribute(name); | 14593 this.removeAttribute(name); |
14530 var sanitizeFn = name == 'checked' ? booleanSanitize : sanitizeValue; | 14594 var sanitizeFn = name == 'checked' ? booleanSanitize : sanitizeValue; |
14531 var postEventFn = name == 'checked' ? checkedPostEvent : noop; | 14595 var postEventFn = name == 'checked' ? checkedPostEvent : noop; |
14532 | 14596 |
14533 if (oneTime) | 14597 if (oneTime) |
14534 return updateInput(this, name, value, sanitizeFn); | 14598 return updateInput(this, name, value, sanitizeFn); |
14535 | 14599 |
14536 unbind(this, name); | 14600 |
14537 bindInputEvent(this, name, value, postEventFn); | 14601 var observable = value; |
| 14602 var binding = bindInputEvent(this, name, observable, postEventFn); |
14538 updateInput(this, name, | 14603 updateInput(this, name, |
14539 value.open(inputBinding(this, name, sanitizeFn)), | 14604 observable.open(inputBinding(this, name, sanitizeFn)), |
14540 sanitizeFn); | 14605 sanitizeFn); |
14541 | 14606 |
14542 return this.bindings[name] = value; | 14607 // Checkboxes may need to update bindings of other checkboxes. |
| 14608 return updateBindings(this, name, binding); |
14543 } | 14609 } |
14544 | 14610 |
14545 HTMLTextAreaElement.prototype.bind = function(name, value, oneTime) { | 14611 HTMLTextAreaElement.prototype.bind = function(name, value, oneTime) { |
14546 if (name !== 'value') | 14612 if (name !== 'value') |
14547 return HTMLElement.prototype.bind.call(this, name, value, oneTime); | 14613 return HTMLElement.prototype.bind.call(this, name, value, oneTime); |
14548 | 14614 |
14549 this.removeAttribute('value'); | 14615 this.removeAttribute('value'); |
14550 | 14616 |
14551 if (oneTime) | 14617 if (oneTime) |
14552 return updateInput(this, 'value', value); | 14618 return updateInput(this, 'value', value); |
14553 | 14619 |
14554 unbind(this, 'value'); | 14620 var observable = value; |
14555 bindInputEvent(this, 'value', value); | 14621 var binding = bindInputEvent(this, 'value', observable); |
14556 updateInput(this, 'value', | 14622 updateInput(this, 'value', |
14557 value.open(inputBinding(this, 'value', sanitizeValue))); | 14623 observable.open(inputBinding(this, 'value', sanitizeValue))); |
14558 | 14624 return maybeUpdateBindings(this, name, binding); |
14559 return this.bindings.value = value; | |
14560 } | 14625 } |
14561 | 14626 |
14562 function updateOption(option, value) { | 14627 function updateOption(option, value) { |
14563 var parentNode = option.parentNode;; | 14628 var parentNode = option.parentNode;; |
14564 var select; | 14629 var select; |
14565 var selectBinding; | 14630 var selectBinding; |
14566 var oldValue; | 14631 var oldValue; |
14567 if (parentNode instanceof HTMLSelectElement && | 14632 if (parentNode instanceof HTMLSelectElement && |
14568 parentNode.bindings && | 14633 parentNode.bindings_ && |
14569 parentNode.bindings.value) { | 14634 parentNode.bindings_.value) { |
14570 select = parentNode; | 14635 select = parentNode; |
14571 selectBinding = select.bindings.value; | 14636 selectBinding = select.bindings_.value; |
14572 oldValue = select.value; | 14637 oldValue = select.value; |
14573 } | 14638 } |
14574 | 14639 |
14575 option.value = sanitizeValue(value); | 14640 option.value = sanitizeValue(value); |
14576 | 14641 |
14577 if (select && select.value != oldValue) { | 14642 if (select && select.value != oldValue) { |
14578 selectBinding.setValue(select.value); | 14643 selectBinding.observable_.setValue(select.value); |
14579 selectBinding.discardChanges(); | 14644 selectBinding.observable_.discardChanges(); |
14580 Platform.performMicrotaskCheckpoint(); | 14645 Platform.performMicrotaskCheckpoint(); |
14581 } | 14646 } |
14582 } | 14647 } |
14583 | 14648 |
14584 function optionBinding(option) { | 14649 function optionBinding(option) { |
14585 return function(value) { | 14650 return function(value) { |
14586 updateOption(option, value); | 14651 updateOption(option, value); |
14587 } | 14652 } |
14588 } | 14653 } |
14589 | 14654 |
14590 HTMLOptionElement.prototype.bind = function(name, value, oneTime) { | 14655 HTMLOptionElement.prototype.bind = function(name, value, oneTime) { |
14591 if (name !== 'value') | 14656 if (name !== 'value') |
14592 return HTMLElement.prototype.bind.call(this, name, value, oneTime); | 14657 return HTMLElement.prototype.bind.call(this, name, value, oneTime); |
14593 | 14658 |
14594 this.removeAttribute('value'); | 14659 this.removeAttribute('value'); |
14595 | 14660 |
14596 if (oneTime) | 14661 if (oneTime) |
14597 return updateOption(this, value); | 14662 return updateOption(this, value); |
14598 | 14663 |
14599 unbind(this, 'value'); | 14664 var observable = value; |
14600 bindInputEvent(this, 'value', value); | 14665 var binding = bindInputEvent(this, 'value', observable); |
14601 updateOption(this, value.open(optionBinding(this))); | 14666 updateOption(this, observable.open(optionBinding(this))); |
14602 return this.bindings.value = value; | 14667 return maybeUpdateBindings(this, name, binding); |
14603 } | 14668 } |
14604 | 14669 |
14605 HTMLSelectElement.prototype.bind = function(name, value, oneTime) { | 14670 HTMLSelectElement.prototype.bind = function(name, value, oneTime) { |
14606 if (name === 'selectedindex') | 14671 if (name === 'selectedindex') |
14607 name = 'selectedIndex'; | 14672 name = 'selectedIndex'; |
14608 | 14673 |
14609 if (name !== 'selectedIndex' && name !== 'value') | 14674 if (name !== 'selectedIndex' && name !== 'value') |
14610 return HTMLElement.prototype.bind.call(this, name, value, oneTime); | 14675 return HTMLElement.prototype.bind.call(this, name, value, oneTime); |
14611 | 14676 |
14612 this.removeAttribute(name); | 14677 this.removeAttribute(name); |
14613 | 14678 |
14614 if (oneTime) | 14679 if (oneTime) |
14615 return updateInput(this, name, value); | 14680 return updateInput(this, name, value); |
14616 | 14681 |
14617 unbind(this, name); | 14682 var observable = value; |
14618 bindInputEvent(this, name, value); | 14683 var binding = bindInputEvent(this, name, observable); |
14619 updateInput(this, name, | 14684 updateInput(this, name, |
14620 value.open(inputBinding(this, name))); | 14685 observable.open(inputBinding(this, name))); |
14621 return this.bindings[name] = value; | 14686 |
| 14687 // Option update events may need to access select bindings. |
| 14688 return updateBindings(this, name, binding); |
14622 } | 14689 } |
14623 })(this); | 14690 })(this); |
14624 | 14691 |
14625 // Copyright 2011 Google Inc. | 14692 // Copyright (c) 2014 The Polymer Project Authors. All rights reserved. |
14626 // | 14693 // This code may only be used under the BSD style license found at http://polyme
r.github.io/LICENSE.txt |
14627 // Licensed under the Apache License, Version 2.0 (the "License"); | 14694 // The complete set of authors may be found at http://polymer.github.io/AUTHORS.
txt |
14628 // you may not use this file except in compliance with the License. | 14695 // The complete set of contributors may be found at http://polymer.github.io/CON
TRIBUTORS.txt |
14629 // You may obtain a copy of the License at | 14696 // Code distributed by Google as part of the polymer project is also |
14630 // | 14697 // subject to an additional IP rights grant found at http://polymer.github.io/PA
TENTS.txt |
14631 // http://www.apache.org/licenses/LICENSE-2.0 | |
14632 // | |
14633 // Unless required by applicable law or agreed to in writing, software | |
14634 // distributed under the License is distributed on an "AS IS" BASIS, | |
14635 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14636 // See the License for the specific language governing permissions and | |
14637 // limitations under the License. | |
14638 | 14698 |
14639 (function(global) { | 14699 (function(global) { |
14640 'use strict'; | 14700 'use strict'; |
14641 | 14701 |
14642 function assert(v) { | 14702 function assert(v) { |
14643 if (!v) | 14703 if (!v) |
14644 throw new Error('Assertion failed'); | 14704 throw new Error('Assertion failed'); |
14645 } | 14705 } |
14646 | 14706 |
14647 var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); | 14707 var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); |
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15092 var ref = oneTime ? value : value.open(function(ref) { | 15152 var ref = oneTime ? value : value.open(function(ref) { |
15093 self.setAttribute('ref', ref); | 15153 self.setAttribute('ref', ref); |
15094 self.refChanged_(); | 15154 self.refChanged_(); |
15095 }); | 15155 }); |
15096 | 15156 |
15097 this.setAttribute('ref', ref); | 15157 this.setAttribute('ref', ref); |
15098 this.refChanged_(); | 15158 this.refChanged_(); |
15099 if (oneTime) | 15159 if (oneTime) |
15100 return; | 15160 return; |
15101 | 15161 |
15102 this.unbind('ref'); | 15162 if (!this.bindings_) { |
15103 return this.bindings.ref = value; | 15163 this.bindings_ = { ref: value }; |
| 15164 } else { |
| 15165 this.bindings_.ref = value; |
| 15166 } |
| 15167 |
| 15168 return value; |
15104 }, | 15169 }, |
15105 | 15170 |
15106 processBindingDirectives_: function(directives) { | 15171 processBindingDirectives_: function(directives) { |
15107 if (this.iterator_) | 15172 if (this.iterator_) |
15108 this.iterator_.closeDeps(); | 15173 this.iterator_.closeDeps(); |
15109 | 15174 |
15110 if (!directives.if && !directives.bind && !directives.repeat) { | 15175 if (!directives.if && !directives.bind && !directives.repeat) { |
15111 if (this.iterator_) { | 15176 if (this.iterator_) { |
15112 this.iterator_.close(); | 15177 this.iterator_.close(); |
15113 this.iterator_ = undefined; | 15178 this.iterator_ = undefined; |
15114 this.bindings.iterator = undefined; | |
15115 } | 15179 } |
15116 | 15180 |
15117 return; | 15181 return; |
15118 } | 15182 } |
15119 | 15183 |
15120 if (!this.iterator_) { | 15184 if (!this.iterator_) { |
15121 this.iterator_ = new TemplateIterator(this); | 15185 this.iterator_ = new TemplateIterator(this); |
15122 this.bindings = this.bindings || {}; | |
15123 this.bindings.iterator = this.iterator_; | |
15124 } | 15186 } |
15125 | 15187 |
15126 this.iterator_.updateDependencies(directives, this.model_); | 15188 this.iterator_.updateDependencies(directives, this.model_); |
15127 | 15189 |
15128 if (templateObserver) { | 15190 if (templateObserver) { |
15129 templateObserver.observe(this, { attributes: true, | 15191 templateObserver.observe(this, { attributes: true, |
15130 attributeFilter: ['ref'] }); | 15192 attributeFilter: ['ref'] }); |
15131 } | 15193 } |
15132 | 15194 |
15133 return this.iterator_; | 15195 return this.iterator_; |
15134 }, | 15196 }, |
15135 | 15197 |
15136 createInstance: function(model, bindingDelegate, delegate_, | 15198 createInstance: function(model, bindingDelegate, delegate_) { |
15137 instanceBindings_) { | |
15138 if (bindingDelegate) | 15199 if (bindingDelegate) |
15139 delegate_ = this.newDelegate_(bindingDelegate); | 15200 delegate_ = this.newDelegate_(bindingDelegate); |
15140 | 15201 |
15141 if (!this.refContent_) | 15202 if (!this.refContent_) |
15142 this.refContent_ = this.ref_.content; | 15203 this.refContent_ = this.ref_.content; |
15143 var content = this.refContent_; | 15204 var content = this.refContent_; |
| 15205 if (content.firstChild === null) |
| 15206 return emptyInstance; |
| 15207 |
15144 var map = this.bindingMap_; | 15208 var map = this.bindingMap_; |
15145 if (!map || map.content !== content) { | 15209 if (!map || map.content !== content) { |
15146 // TODO(rafaelw): Setup a MutationObserver on content to detect | 15210 // TODO(rafaelw): Setup a MutationObserver on content to detect |
15147 // when the instanceMap is invalid. | 15211 // when the instanceMap is invalid. |
15148 map = createInstanceBindingMap(content, | 15212 map = createInstanceBindingMap(content, |
15149 delegate_ && delegate_.prepareBinding) || []; | 15213 delegate_ && delegate_.prepareBinding) || []; |
15150 map.content = content; | 15214 map.content = content; |
15151 this.bindingMap_ = map; | 15215 this.bindingMap_ = map; |
15152 } | 15216 } |
15153 | 15217 |
15154 var stagingDocument = getTemplateStagingDocument(this); | 15218 var stagingDocument = getTemplateStagingDocument(this); |
15155 var instance = stagingDocument.createDocumentFragment(); | 15219 var instance = stagingDocument.createDocumentFragment(); |
15156 instance.templateCreator_ = this; | 15220 instance.templateCreator_ = this; |
15157 instance.protoContent_ = content; | 15221 instance.protoContent_ = content; |
15158 | 15222 instance.bindings_ = []; |
15159 var instanceRecord = { | 15223 instance.terminator_ = null; |
| 15224 var instanceRecord = instance.templateInstance_ = { |
15160 firstNode: null, | 15225 firstNode: null, |
15161 lastNode: null, | 15226 lastNode: null, |
15162 model: model | 15227 model: model |
15163 }; | 15228 }; |
15164 | 15229 |
15165 var i = 0; | 15230 var i = 0; |
| 15231 var collectTerminator = false; |
15166 for (var child = content.firstChild; child; child = child.nextSibling) { | 15232 for (var child = content.firstChild; child; child = child.nextSibling) { |
| 15233 // The terminator of the instance is the clone of the last child of the |
| 15234 // content. If the last child is an active template, it may produce |
| 15235 // instances as a result of production, so simply collecting the last |
| 15236 // child of the instance after it has finished producing may be wrong. |
| 15237 if (child.nextSibling === null) |
| 15238 collectTerminator = true; |
| 15239 |
15167 var clone = cloneAndBindInstance(child, instance, stagingDocument, | 15240 var clone = cloneAndBindInstance(child, instance, stagingDocument, |
15168 map.children[i++], | 15241 map.children[i++], |
15169 model, | 15242 model, |
15170 delegate_, | 15243 delegate_, |
15171 instanceBindings_); | 15244 instance.bindings_); |
15172 clone.templateInstance_ = instanceRecord; | 15245 clone.templateInstance_ = instanceRecord; |
| 15246 if (collectTerminator) |
| 15247 instance.terminator_ = clone; |
15173 } | 15248 } |
15174 | 15249 |
15175 instanceRecord.firstNode = instance.firstChild; | 15250 instanceRecord.firstNode = instance.firstChild; |
15176 instanceRecord.lastNode = instance.lastChild; | 15251 instanceRecord.lastNode = instance.lastChild; |
15177 instance.templateCreator_ = undefined; | 15252 instance.templateCreator_ = undefined; |
15178 instance.protoContent_ = undefined; | 15253 instance.protoContent_ = undefined; |
15179 return instance; | 15254 return instance; |
15180 }, | 15255 }, |
15181 | 15256 |
15182 get model() { | 15257 get model() { |
(...skipping 14 matching lines...) Expand all Loading... |
15197 return; | 15272 return; |
15198 | 15273 |
15199 this.refContent_ = undefined; | 15274 this.refContent_ = undefined; |
15200 this.iterator_.valueChanged(); | 15275 this.iterator_.valueChanged(); |
15201 this.iterator_.updateIteratedValue(); | 15276 this.iterator_.updateIteratedValue(); |
15202 }, | 15277 }, |
15203 | 15278 |
15204 clear: function() { | 15279 clear: function() { |
15205 this.model_ = undefined; | 15280 this.model_ = undefined; |
15206 this.delegate_ = undefined; | 15281 this.delegate_ = undefined; |
15207 this.bindings_ = undefined; | 15282 if (this.bindings_ && this.bindings_.ref) |
| 15283 this.bindings_.ref.close() |
15208 this.refContent_ = undefined; | 15284 this.refContent_ = undefined; |
15209 if (!this.iterator_) | 15285 if (!this.iterator_) |
15210 return; | 15286 return; |
15211 this.iterator_.valueChanged(); | 15287 this.iterator_.valueChanged(); |
15212 this.iterator_.close() | 15288 this.iterator_.close() |
15213 this.iterator_ = undefined; | 15289 this.iterator_ = undefined; |
15214 }, | 15290 }, |
15215 | 15291 |
15216 setDelegate_: function(delegate) { | 15292 setDelegate_: function(delegate) { |
15217 this.delegate_ = delegate; | 15293 this.delegate_ = delegate; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15302 | 15378 |
15303 tokens.push(s.slice(lastIndex)); // TEXT | 15379 tokens.push(s.slice(lastIndex)); // TEXT |
15304 break; | 15380 break; |
15305 } | 15381 } |
15306 | 15382 |
15307 tokens = tokens || []; | 15383 tokens = tokens || []; |
15308 tokens.push(s.slice(lastIndex, startIndex)); // TEXT | 15384 tokens.push(s.slice(lastIndex, startIndex)); // TEXT |
15309 var pathString = s.slice(startIndex + 2, endIndex).trim(); | 15385 var pathString = s.slice(startIndex + 2, endIndex).trim(); |
15310 tokens.push(oneTime); // ONE_TIME? | 15386 tokens.push(oneTime); // ONE_TIME? |
15311 onlyOneTime = onlyOneTime && oneTime; | 15387 onlyOneTime = onlyOneTime && oneTime; |
15312 tokens.push(Path.get(pathString)); // PATH | |
15313 var delegateFn = prepareBindingFn && | 15388 var delegateFn = prepareBindingFn && |
15314 prepareBindingFn(pathString, name, node); | 15389 prepareBindingFn(pathString, name, node); |
| 15390 // Don't try to parse the expression if there's a prepareBinding function |
| 15391 if (delegateFn == null) { |
| 15392 tokens.push(Path.get(pathString)); // PATH |
| 15393 } else { |
| 15394 tokens.push(null); |
| 15395 } |
15315 tokens.push(delegateFn); // DELEGATE_FN | 15396 tokens.push(delegateFn); // DELEGATE_FN |
15316 lastIndex = endIndex + 2; | 15397 lastIndex = endIndex + 2; |
15317 } | 15398 } |
15318 | 15399 |
15319 if (lastIndex === length) | 15400 if (lastIndex === length) |
15320 tokens.push(''); // TEXT | 15401 tokens.push(''); // TEXT |
15321 | 15402 |
15322 tokens.hasOnePath = tokens.length === 5; | 15403 tokens.hasOnePath = tokens.length === 5; |
15323 tokens.isSimplePath = tokens.hasOnePath && | 15404 tokens.isSimplePath = tokens.hasOnePath && |
15324 tokens[0] == '' && | 15405 tokens[0] == '' && |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15522 } | 15603 } |
15523 | 15604 |
15524 Object.defineProperty(Node.prototype, 'templateInstance', { | 15605 Object.defineProperty(Node.prototype, 'templateInstance', { |
15525 get: function() { | 15606 get: function() { |
15526 var instance = this.templateInstance_; | 15607 var instance = this.templateInstance_; |
15527 return instance ? instance : | 15608 return instance ? instance : |
15528 (this.parentNode ? this.parentNode.templateInstance : undefined); | 15609 (this.parentNode ? this.parentNode.templateInstance : undefined); |
15529 } | 15610 } |
15530 }); | 15611 }); |
15531 | 15612 |
| 15613 var emptyInstance = document.createDocumentFragment(); |
| 15614 emptyInstance.bindings_ = []; |
| 15615 emptyInstance.terminator_ = null; |
| 15616 |
15532 function TemplateIterator(templateElement) { | 15617 function TemplateIterator(templateElement) { |
15533 this.closed = false; | 15618 this.closed = false; |
15534 this.templateElement_ = templateElement; | 15619 this.templateElement_ = templateElement; |
15535 | 15620 this.instances = []; |
15536 // Flattened array of tuples: | |
15537 // <instanceTerminatorNode, [bindingsSetupByInstance]> | |
15538 this.terminators = []; | |
15539 | |
15540 this.deps = undefined; | 15621 this.deps = undefined; |
15541 this.iteratedValue = []; | 15622 this.iteratedValue = []; |
15542 this.presentValue = undefined; | 15623 this.presentValue = undefined; |
15543 this.arrayObserver = undefined; | 15624 this.arrayObserver = undefined; |
15544 } | 15625 } |
15545 | 15626 |
15546 TemplateIterator.prototype = { | 15627 TemplateIterator.prototype = { |
15547 closeDeps: function() { | 15628 closeDeps: function() { |
15548 var deps = this.deps; | 15629 var deps = this.deps; |
15549 if (deps) { | 15630 if (deps) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15624 this.presentValue = value; | 15705 this.presentValue = value; |
15625 if (observeValue) { | 15706 if (observeValue) { |
15626 this.arrayObserver = new ArrayObserver(this.presentValue); | 15707 this.arrayObserver = new ArrayObserver(this.presentValue); |
15627 this.arrayObserver.open(this.handleSplices, this); | 15708 this.arrayObserver.open(this.handleSplices, this); |
15628 } | 15709 } |
15629 | 15710 |
15630 this.handleSplices(ArrayObserver.calculateSplices(this.presentValue, | 15711 this.handleSplices(ArrayObserver.calculateSplices(this.presentValue, |
15631 this.iteratedValue)); | 15712 this.iteratedValue)); |
15632 }, | 15713 }, |
15633 | 15714 |
15634 getTerminatorAt: function(index) { | 15715 getLastInstanceNode: function(index) { |
15635 if (index == -1) | 15716 if (index == -1) |
15636 return this.templateElement_; | 15717 return this.templateElement_; |
15637 var terminator = this.terminators[index*2]; | 15718 var instance = this.instances[index]; |
| 15719 var terminator = instance.terminator_; |
| 15720 if (!terminator) |
| 15721 return this.getLastInstanceNode(index - 1); |
| 15722 |
15638 if (terminator.nodeType !== Node.ELEMENT_NODE || | 15723 if (terminator.nodeType !== Node.ELEMENT_NODE || |
15639 this.templateElement_ === terminator) { | 15724 this.templateElement_ === terminator) { |
15640 return terminator; | 15725 return terminator; |
15641 } | 15726 } |
15642 | 15727 |
15643 var subIterator = terminator.iterator_; | 15728 var subtemplateIterator = terminator.iterator_; |
15644 if (!subIterator) | 15729 if (!subtemplateIterator) |
15645 return terminator; | 15730 return terminator; |
15646 | 15731 |
15647 return subIterator.getTerminatorAt(subIterator.terminators.length/2 - 1); | 15732 return subtemplateIterator.getLastTemplateNode(); |
15648 }, | 15733 }, |
15649 | 15734 |
15650 // TODO(rafaelw): If we inserting sequences of instances we can probably | 15735 getLastTemplateNode: function() { |
15651 // avoid lots of calls to getTerminatorAt(), or cache its result. | 15736 return this.getLastInstanceNode(this.instances.length - 1); |
15652 insertInstanceAt: function(index, fragment, instanceNodes, | 15737 }, |
15653 instanceBindings) { | |
15654 var previousTerminator = this.getTerminatorAt(index - 1); | |
15655 var terminator = previousTerminator; | |
15656 if (fragment) | |
15657 terminator = fragment.lastChild || terminator; | |
15658 else if (instanceNodes) | |
15659 terminator = instanceNodes[instanceNodes.length - 1] || terminator; | |
15660 | 15738 |
15661 this.terminators.splice(index*2, 0, terminator, instanceBindings); | 15739 insertInstanceAt: function(index, fragment) { |
| 15740 var previousInstanceLast = this.getLastInstanceNode(index - 1); |
15662 var parent = this.templateElement_.parentNode; | 15741 var parent = this.templateElement_.parentNode; |
15663 var insertBeforeNode = previousTerminator.nextSibling; | 15742 this.instances.splice(index, 0, fragment); |
15664 | 15743 |
15665 if (fragment) { | 15744 parent.insertBefore(fragment, previousInstanceLast.nextSibling); |
15666 parent.insertBefore(fragment, insertBeforeNode); | |
15667 } else if (instanceNodes) { | |
15668 for (var i = 0; i < instanceNodes.length; i++) | |
15669 parent.insertBefore(instanceNodes[i], insertBeforeNode); | |
15670 } | |
15671 }, | 15745 }, |
15672 | 15746 |
15673 extractInstanceAt: function(index) { | 15747 extractInstanceAt: function(index) { |
15674 var instanceNodes = []; | 15748 var previousInstanceLast = this.getLastInstanceNode(index - 1); |
15675 var previousTerminator = this.getTerminatorAt(index - 1); | 15749 var lastNode = this.getLastInstanceNode(index); |
15676 var terminator = this.getTerminatorAt(index); | 15750 var parent = this.templateElement_.parentNode; |
15677 instanceNodes.instanceBindings = this.terminators[index*2 + 1]; | 15751 var instance = this.instances.splice(index, 1)[0]; |
15678 this.terminators.splice(index*2, 2); | |
15679 | 15752 |
15680 var parent = this.templateElement_.parentNode; | 15753 while (lastNode !== previousInstanceLast) { |
15681 while (terminator !== previousTerminator) { | 15754 var node = previousInstanceLast.nextSibling; |
15682 var node = previousTerminator.nextSibling; | 15755 if (node == lastNode) |
15683 if (node == terminator) | 15756 lastNode = previousInstanceLast; |
15684 terminator = previousTerminator; | |
15685 | 15757 |
15686 parent.removeChild(node); | 15758 instance.appendChild(parent.removeChild(node)); |
15687 instanceNodes.push(node); | |
15688 } | 15759 } |
15689 | 15760 |
15690 return instanceNodes; | 15761 return instance; |
15691 }, | 15762 }, |
15692 | 15763 |
15693 getDelegateFn: function(fn) { | 15764 getDelegateFn: function(fn) { |
15694 fn = fn && fn(this.templateElement_); | 15765 fn = fn && fn(this.templateElement_); |
15695 return typeof fn === 'function' ? fn : null; | 15766 return typeof fn === 'function' ? fn : null; |
15696 }, | 15767 }, |
15697 | 15768 |
15698 handleSplices: function(splices) { | 15769 handleSplices: function(splices) { |
15699 if (this.closed || !splices.length) | 15770 if (this.closed || !splices.length) |
15700 return; | 15771 return; |
(...skipping 13 matching lines...) Expand all Loading... |
15714 this.instanceModelFn_ = | 15785 this.instanceModelFn_ = |
15715 this.getDelegateFn(delegate && delegate.prepareInstanceModel); | 15786 this.getDelegateFn(delegate && delegate.prepareInstanceModel); |
15716 } | 15787 } |
15717 | 15788 |
15718 if (this.instancePositionChangedFn_ === undefined) { | 15789 if (this.instancePositionChangedFn_ === undefined) { |
15719 this.instancePositionChangedFn_ = | 15790 this.instancePositionChangedFn_ = |
15720 this.getDelegateFn(delegate && | 15791 this.getDelegateFn(delegate && |
15721 delegate.prepareInstancePositionChanged); | 15792 delegate.prepareInstancePositionChanged); |
15722 } | 15793 } |
15723 | 15794 |
| 15795 // Instance Removals |
15724 var instanceCache = new Map; | 15796 var instanceCache = new Map; |
15725 var removeDelta = 0; | 15797 var removeDelta = 0; |
15726 splices.forEach(function(splice) { | 15798 for (var i = 0; i < splices.length; i++) { |
15727 splice.removed.forEach(function(model) { | 15799 var splice = splices[i]; |
15728 var instanceNodes = | 15800 var removed = splice.removed; |
15729 this.extractInstanceAt(splice.index + removeDelta); | 15801 for (var j = 0; j < removed.length; j++) { |
15730 instanceCache.set(model, instanceNodes); | 15802 var model = removed[j]; |
15731 }, this); | 15803 var instance = this.extractInstanceAt(splice.index + removeDelta); |
| 15804 if (instance !== emptyInstance) { |
| 15805 instanceCache.set(model, instance); |
| 15806 } |
| 15807 } |
15732 | 15808 |
15733 removeDelta -= splice.addedCount; | 15809 removeDelta -= splice.addedCount; |
15734 }, this); | 15810 } |
15735 | 15811 |
15736 splices.forEach(function(splice) { | 15812 // Instance Insertions |
| 15813 for (var i = 0; i < splices.length; i++) { |
| 15814 var splice = splices[i]; |
15737 var addIndex = splice.index; | 15815 var addIndex = splice.index; |
15738 for (; addIndex < splice.index + splice.addedCount; addIndex++) { | 15816 for (; addIndex < splice.index + splice.addedCount; addIndex++) { |
15739 var model = this.iteratedValue[addIndex]; | 15817 var model = this.iteratedValue[addIndex]; |
15740 var fragment = undefined; | 15818 var instance = instanceCache.get(model); |
15741 var instanceNodes = instanceCache.get(model); | 15819 if (instance) { |
15742 var instanceBindings; | |
15743 if (instanceNodes) { | |
15744 instanceCache.delete(model); | 15820 instanceCache.delete(model); |
15745 instanceBindings = instanceNodes.instanceBindings; | |
15746 } else { | 15821 } else { |
15747 instanceBindings = []; | 15822 if (this.instanceModelFn_) { |
15748 if (this.instanceModelFn_) | |
15749 model = this.instanceModelFn_(model); | 15823 model = this.instanceModelFn_(model); |
| 15824 } |
15750 | 15825 |
15751 if (model !== undefined) { | 15826 if (model === undefined) { |
15752 fragment = template.createInstance(model, undefined, delegate, | 15827 instance = emptyInstance; |
15753 instanceBindings); | 15828 } else { |
| 15829 instance = template.createInstance(model, undefined, delegate); |
15754 } | 15830 } |
15755 } | 15831 } |
15756 | 15832 |
15757 this.insertInstanceAt(addIndex, fragment, instanceNodes, | 15833 this.insertInstanceAt(addIndex, instance); |
15758 instanceBindings); | |
15759 } | 15834 } |
15760 }, this); | 15835 } |
15761 | 15836 |
15762 instanceCache.forEach(function(instanceNodes) { | 15837 instanceCache.forEach(function(instance) { |
15763 this.closeInstanceBindings(instanceNodes.instanceBindings); | 15838 this.closeInstanceBindings(instance); |
15764 }, this); | 15839 }, this); |
15765 | 15840 |
15766 if (this.instancePositionChangedFn_) | 15841 if (this.instancePositionChangedFn_) |
15767 this.reportInstancesMoved(splices); | 15842 this.reportInstancesMoved(splices); |
15768 }, | 15843 }, |
15769 | 15844 |
15770 reportInstanceMoved: function(index) { | 15845 reportInstanceMoved: function(index) { |
15771 var previousTerminator = this.getTerminatorAt(index - 1); | 15846 var instance = this.instances[index]; |
15772 var terminator = this.getTerminatorAt(index); | 15847 if (instance === emptyInstance) |
15773 if (previousTerminator === terminator) | 15848 return; |
15774 return; // instance has zero nodes. | |
15775 | 15849 |
15776 // We must use the first node of the instance, because any subsequent | 15850 this.instancePositionChangedFn_(instance.templateInstance_, index); |
15777 // nodes may have been generated by sub-templates. | |
15778 // TODO(rafaelw): This is brittle WRT instance mutation -- e.g. if the | |
15779 // first node was removed by script. | |
15780 var templateInstance = previousTerminator.nextSibling.templateInstance; | |
15781 this.instancePositionChangedFn_(templateInstance, index); | |
15782 }, | 15851 }, |
15783 | 15852 |
15784 reportInstancesMoved: function(splices) { | 15853 reportInstancesMoved: function(splices) { |
15785 var index = 0; | 15854 var index = 0; |
15786 var offset = 0; | 15855 var offset = 0; |
15787 for (var i = 0; i < splices.length; i++) { | 15856 for (var i = 0; i < splices.length; i++) { |
15788 var splice = splices[i]; | 15857 var splice = splices[i]; |
15789 if (offset != 0) { | 15858 if (offset != 0) { |
15790 while (index < splice.index) { | 15859 while (index < splice.index) { |
15791 this.reportInstanceMoved(index); | 15860 this.reportInstanceMoved(index); |
15792 index++; | 15861 index++; |
15793 } | 15862 } |
15794 } else { | 15863 } else { |
15795 index = splice.index; | 15864 index = splice.index; |
15796 } | 15865 } |
15797 | 15866 |
15798 while (index < splice.index + splice.addedCount) { | 15867 while (index < splice.index + splice.addedCount) { |
15799 this.reportInstanceMoved(index); | 15868 this.reportInstanceMoved(index); |
15800 index++; | 15869 index++; |
15801 } | 15870 } |
15802 | 15871 |
15803 offset += splice.addedCount - splice.removed.length; | 15872 offset += splice.addedCount - splice.removed.length; |
15804 } | 15873 } |
15805 | 15874 |
15806 if (offset == 0) | 15875 if (offset == 0) |
15807 return; | 15876 return; |
15808 | 15877 |
15809 var length = this.terminators.length / 2; | 15878 var length = this.instances.length; |
15810 while (index < length) { | 15879 while (index < length) { |
15811 this.reportInstanceMoved(index); | 15880 this.reportInstanceMoved(index); |
15812 index++; | 15881 index++; |
15813 } | 15882 } |
15814 }, | 15883 }, |
15815 | 15884 |
15816 closeInstanceBindings: function(instanceBindings) { | 15885 closeInstanceBindings: function(instance) { |
15817 for (var i = 0; i < instanceBindings.length; i++) { | 15886 var bindings = instance.bindings_; |
15818 instanceBindings[i].close(); | 15887 for (var i = 0; i < bindings.length; i++) { |
| 15888 bindings[i].close(); |
15819 } | 15889 } |
15820 }, | 15890 }, |
15821 | 15891 |
15822 unobserve: function() { | 15892 unobserve: function() { |
15823 if (!this.arrayObserver) | 15893 if (!this.arrayObserver) |
15824 return; | 15894 return; |
15825 | 15895 |
15826 this.arrayObserver.close(); | 15896 this.arrayObserver.close(); |
15827 this.arrayObserver = undefined; | 15897 this.arrayObserver = undefined; |
15828 }, | 15898 }, |
15829 | 15899 |
15830 close: function() { | 15900 close: function() { |
15831 if (this.closed) | 15901 if (this.closed) |
15832 return; | 15902 return; |
15833 this.unobserve(); | 15903 this.unobserve(); |
15834 for (var i = 1; i < this.terminators.length; i += 2) { | 15904 for (var i = 0; i < this.instances.length; i++) { |
15835 this.closeInstanceBindings(this.terminators[i]); | 15905 this.closeInstanceBindings(this.instances[i]); |
15836 } | 15906 } |
15837 | 15907 |
15838 this.terminators.length = 0; | 15908 this.instances.length = 0; |
15839 this.closeDeps(); | 15909 this.closeDeps(); |
15840 this.templateElement_.iterator_ = undefined; | 15910 this.templateElement_.iterator_ = undefined; |
15841 this.closed = true; | 15911 this.closed = true; |
15842 } | 15912 } |
15843 }; | 15913 }; |
15844 | 15914 |
15845 // Polyfill-specific API. | 15915 // Polyfill-specific API. |
15846 HTMLTemplateElement.forAllTemplatesFrom_ = forAllTemplatesFrom; | 15916 HTMLTemplateElement.forAllTemplatesFrom_ = forAllTemplatesFrom; |
15847 })(this); | 15917 })(this); |
15848 | 15918 |
(...skipping 1028 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16877 }; | 16947 }; |
16878 | 16948 |
16879 return parseTopLevel(); | 16949 return parseTopLevel(); |
16880 } | 16950 } |
16881 | 16951 |
16882 global.esprima = { | 16952 global.esprima = { |
16883 parse: parse | 16953 parse: parse |
16884 }; | 16954 }; |
16885 })(this); | 16955 })(this); |
16886 | 16956 |
16887 // Copyright 2013 Google Inc. | 16957 // Copyright (c) 2014 The Polymer Project Authors. All rights reserved. |
16888 // | 16958 // This code may only be used under the BSD style license found at http://polyme
r.github.io/LICENSE.txt |
16889 // Licensed under the Apache License, Version 2.0 (the "License"); | 16959 // The complete set of authors may be found at http://polymer.github.io/AUTHORS.
txt |
16890 // you may not use this file except in compliance with the License. | 16960 // The complete set of contributors may be found at http://polymer.github.io/CON
TRIBUTORS.txt |
16891 // You may obtain a copy of the License at | 16961 // Code distributed by Google as part of the polymer project is also |
16892 // | 16962 // subject to an additional IP rights grant found at http://polymer.github.io/PA
TENTS.txt |
16893 // http://www.apache.org/licenses/LICENSE-2.0 | |
16894 // | |
16895 // Unless required by applicable law or agreed to in writing, software | |
16896 // distributed under the License is distributed on an "AS IS" BASIS, | |
16897 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
16898 // See the License for the specific language governing permissions and | |
16899 // limitations under the License. | |
16900 | 16963 |
16901 (function (global) { | 16964 (function (global) { |
16902 'use strict'; | 16965 'use strict'; |
16903 | 16966 |
16904 // JScript does not have __proto__. We wrap all object literals with | 16967 // JScript does not have __proto__. We wrap all object literals with |
16905 // createObject which uses Object.create, Object.defineProperty and | 16968 // createObject which uses Object.create, Object.defineProperty and |
16906 // Object.getOwnPropertyDescriptor to create a new object that does the exact | 16969 // Object.getOwnPropertyDescriptor to create a new object that does the exact |
16907 // same thing. The main downside to this solution is that we have to extract | 16970 // same thing. The main downside to this solution is that we have to extract |
16908 // all those property descriptors for IE. | 16971 // all those property descriptors for IE. |
16909 var createObject = ('__proto__' in {}) ? | 16972 var createObject = ('__proto__' in {}) ? |
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17316 this.filters = delegate.filters; | 17379 this.filters = delegate.filters; |
17317 this.dynamicDeps = delegate.dynamicDeps; | 17380 this.dynamicDeps = delegate.dynamicDeps; |
17318 } | 17381 } |
17319 | 17382 |
17320 Expression.prototype = { | 17383 Expression.prototype = { |
17321 getBinding: function(model, filterRegistry, oneTime) { | 17384 getBinding: function(model, filterRegistry, oneTime) { |
17322 if (oneTime) | 17385 if (oneTime) |
17323 return this.getValue(model, undefined, filterRegistry); | 17386 return this.getValue(model, undefined, filterRegistry); |
17324 | 17387 |
17325 var observer = new CompoundObserver(); | 17388 var observer = new CompoundObserver(); |
17326 this.getValue(model, observer, filterRegistry); // captures deps. | 17389 // captures deps. |
| 17390 var firstValue = this.getValue(model, observer, filterRegistry); |
| 17391 var firstTime = true; |
17327 var self = this; | 17392 var self = this; |
17328 | 17393 |
17329 function valueFn() { | 17394 function valueFn() { |
| 17395 // deps cannot have changed on first value retrieval. |
| 17396 if (firstTime) { |
| 17397 firstTime = false; |
| 17398 return firstValue; |
| 17399 } |
| 17400 |
17330 if (self.dynamicDeps) | 17401 if (self.dynamicDeps) |
17331 observer.startReset(); | 17402 observer.startReset(); |
17332 | 17403 |
17333 var value = self.getValue(model, | 17404 var value = self.getValue(model, |
17334 self.dynamicDeps ? observer : undefined, | 17405 self.dynamicDeps ? observer : undefined, |
17335 filterRegistry); | 17406 filterRegistry); |
17336 if (self.dynamicDeps) | 17407 if (self.dynamicDeps) |
17337 observer.finishReset(); | 17408 observer.finishReset(); |
17338 | 17409 |
17339 return value; | 17410 return value; |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17463 return { | 17534 return { |
17464 open: bindingValue, | 17535 open: bindingValue, |
17465 discardChanges: bindingValue, | 17536 discardChanges: bindingValue, |
17466 close: function() { | 17537 close: function() { |
17467 node.removeEventListener(eventType, handler); | 17538 node.removeEventListener(eventType, handler); |
17468 } | 17539 } |
17469 }; | 17540 }; |
17470 } | 17541 } |
17471 } | 17542 } |
17472 | 17543 |
| 17544 function isLiteralExpression(pathString) { |
| 17545 switch (pathString) { |
| 17546 case '': |
| 17547 return false; |
| 17548 |
| 17549 case 'false': |
| 17550 case 'null': |
| 17551 case 'true': |
| 17552 return true; |
| 17553 } |
| 17554 |
| 17555 if (!isNaN(Number(pathString))) |
| 17556 return true; |
| 17557 |
| 17558 return false; |
| 17559 }; |
| 17560 |
17473 function PolymerExpressions() {} | 17561 function PolymerExpressions() {} |
17474 | 17562 |
17475 PolymerExpressions.prototype = { | 17563 PolymerExpressions.prototype = { |
17476 // "built-in" filters | 17564 // "built-in" filters |
17477 styleObject: function(value) { | 17565 styleObject: function(value) { |
17478 var parts = []; | 17566 var parts = []; |
17479 for (var key in value) { | 17567 for (var key in value) { |
17480 parts.push(convertStylePropertyName(key) + ': ' + value[key]); | 17568 parts.push(convertStylePropertyName(key) + ': ' + value[key]); |
17481 } | 17569 } |
17482 return parts.join('; '); | 17570 return parts.join('; '); |
(...skipping 23 matching lines...) Expand all Loading... |
17506 var path = Path.get(pathString); | 17594 var path = Path.get(pathString); |
17507 if (isEventHandler(name)) { | 17595 if (isEventHandler(name)) { |
17508 if (!path.valid) { | 17596 if (!path.valid) { |
17509 console.error('on-* bindings must be simple path expressions'); | 17597 console.error('on-* bindings must be simple path expressions'); |
17510 return; | 17598 return; |
17511 } | 17599 } |
17512 | 17600 |
17513 return prepareEventBinding(path, name, this); | 17601 return prepareEventBinding(path, name, this); |
17514 } | 17602 } |
17515 | 17603 |
17516 if (path.valid) { | 17604 if (!isLiteralExpression(pathString) && path.valid) { |
17517 if (path.length == 1) { | 17605 if (path.length == 1) { |
17518 return function(model, node, oneTime) { | 17606 return function(model, node, oneTime) { |
17519 if (oneTime) | 17607 if (oneTime) |
17520 return path.getValueFrom(model); | 17608 return path.getValueFrom(model); |
17521 | 17609 |
17522 var scope = findScope(model, path[0]); | 17610 var scope = findScope(model, path[0]); |
17523 return new PathObserver(scope, path); | 17611 return new PathObserver(scope, path); |
17524 } | 17612 }; |
17525 } | 17613 } |
17526 | |
17527 return; // bail out early if pathString is simple path. | 17614 return; // bail out early if pathString is simple path. |
17528 } | 17615 } |
17529 | 17616 |
17530 return prepareBinding(pathString, name, node, this); | 17617 return prepareBinding(pathString, name, node, this); |
17531 }, | 17618 }, |
17532 | 17619 |
17533 prepareInstanceModel: function(template) { | 17620 prepareInstanceModel: function(template) { |
17534 var scopeName = template.polymerExpressionScopeIdent_; | 17621 var scopeName = template.polymerExpressionScopeIdent_; |
17535 if (!scopeName) | 17622 if (!scopeName) |
17536 return; | 17623 return; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17579 scope.endOfMicrotask(function() { | 17666 scope.endOfMicrotask(function() { |
17580 flushing = false; | 17667 flushing = false; |
17581 logFlags.data && console.group('Platform.flush()'); | 17668 logFlags.data && console.group('Platform.flush()'); |
17582 scope.performMicrotaskCheckpoint(); | 17669 scope.performMicrotaskCheckpoint(); |
17583 logFlags.data && console.groupEnd(); | 17670 logFlags.data && console.groupEnd(); |
17584 }); | 17671 }); |
17585 } | 17672 } |
17586 }; | 17673 }; |
17587 | 17674 |
17588 // polling dirty checker | 17675 // polling dirty checker |
17589 var FLUSH_POLL_INTERVAL = 125; | 17676 // flush periodically if platform does not have object observe. |
17590 window.addEventListener('WebComponentsReady', function() { | 17677 if (!Observer.hasObjectObserve) { |
17591 flush(); | 17678 var FLUSH_POLL_INTERVAL = 125; |
17592 // flush periodically if platform does not have object observe. | 17679 window.addEventListener('WebComponentsReady', function() { |
17593 if (!Observer.hasObjectObserve) { | 17680 flush(); |
17594 scope.flushPoll = setInterval(flush, FLUSH_POLL_INTERVAL); | 17681 scope.flushPoll = setInterval(flush, FLUSH_POLL_INTERVAL); |
17595 } | 17682 }); |
17596 }); | 17683 } else { |
| 17684 // make flush a no-op when we have Object.observe |
| 17685 flush = function() {}; |
| 17686 } |
17597 | 17687 |
17598 if (window.CustomElements && !CustomElements.useNative) { | 17688 if (window.CustomElements && !CustomElements.useNative) { |
17599 var originalImportNode = Document.prototype.importNode; | 17689 var originalImportNode = Document.prototype.importNode; |
17600 Document.prototype.importNode = function(node, deep) { | 17690 Document.prototype.importNode = function(node, deep) { |
17601 var imported = originalImportNode.call(this, node, deep); | 17691 var imported = originalImportNode.call(this, node, deep); |
17602 CustomElements.upgradeAll(imported); | 17692 CustomElements.upgradeAll(imported); |
17603 return imported; | 17693 return imported; |
17604 } | 17694 } |
17605 } | 17695 } |
17606 | 17696 |
17607 // exports | 17697 // exports |
17608 scope.flush = flush; | 17698 scope.flush = flush; |
17609 | 17699 |
17610 })(window.Platform); | 17700 })(window.Platform); |
17611 | 17701 |
17612 | 17702 |
17613 //# sourceMappingURL=platform.concat.js.map | 17703 //# sourceMappingURL=platform.concat.js.map |
OLD | NEW |