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