Index: pkg/web_components/lib/platform.concat.js |
diff --git a/pkg/web_components/lib/platform.concat.js b/pkg/web_components/lib/platform.concat.js |
index 9fa19b5c3d0c77a98d5e5a12c59c39c79628b508..6fa2b7b4f1830554045bbb76fead092f966584bc 100644 |
--- a/pkg/web_components/lib/platform.concat.js |
+++ b/pkg/web_components/lib/platform.concat.js |
@@ -52,6 +52,12 @@ if (typeof WeakMap === 'undefined') { |
(function(global) { |
'use strict'; |
+ var PROP_ADD_TYPE = 'add'; |
+ var PROP_UPDATE_TYPE = 'update'; |
+ var PROP_RECONFIGURE_TYPE = 'reconfigure'; |
+ var PROP_DELETE_TYPE = 'delete'; |
+ var ARRAY_SPLICE_TYPE = 'splice'; |
+ |
// Detect and do basic sanity checking on Object/Array.observe. |
function detectObjectObserve() { |
if (typeof Object.observe !== 'function' || |
@@ -66,29 +72,44 @@ if (typeof WeakMap === 'undefined') { |
} |
var test = {}; |
- var arr = []; |
Object.observe(test, callback); |
- Array.observe(arr, callback); |
test.id = 1; |
test.id = 2; |
delete test.id; |
- arr.push(1, 2); |
- arr.length = 0; |
- |
Object.deliverChangeRecords(callback); |
- if (records.length !== 5) |
+ if (records.length !== 3) |
return false; |
- if (records[0].type != 'add' || |
- records[1].type != 'update' || |
- records[2].type != 'delete' || |
- records[3].type != 'splice' || |
- records[4].type != 'splice') { |
+ // TODO(rafaelw): Remove this when new change record type names make it to |
+ // chrome release. |
+ if (records[0].type == 'new' && |
+ records[1].type == 'updated' && |
+ records[2].type == 'deleted') { |
+ PROP_ADD_TYPE = 'new'; |
+ PROP_UPDATE_TYPE = 'updated'; |
+ PROP_RECONFIGURE_TYPE = 'reconfigured'; |
+ PROP_DELETE_TYPE = 'deleted'; |
+ } else if (records[0].type != 'add' || |
+ records[1].type != 'update' || |
+ records[2].type != 'delete') { |
+ console.error('Unexpected change record names for Object.observe. ' + |
+ 'Using dirty-checking instead'); |
return false; |
} |
- |
Object.unobserve(test, callback); |
- Array.unobserve(arr, callback); |
+ |
+ test = [0]; |
+ Array.observe(test, callback); |
+ test[1] = 1; |
+ test.length = 0; |
+ Object.deliverChangeRecords(callback); |
+ if (records.length != 2) |
+ return false; |
+ if (records[0].type != ARRAY_SPLICE_TYPE || |
+ records[1].type != ARRAY_SPLICE_TYPE) { |
+ return false; |
+ } |
+ Array.unobserve(test, callback); |
return true; |
} |
@@ -247,7 +268,7 @@ if (typeof WeakMap === 'undefined') { |
for (var i = 0; i < this.length; i++) { |
if (i) |
obj = obj[this[i - 1]]; |
- if (!isObject(obj)) |
+ if (!obj) |
return; |
observe(obj); |
} |
@@ -457,7 +478,7 @@ if (typeof WeakMap === 'undefined') { |
var resetScheduled = false; |
function observe(obj) { |
- if (!obj) |
+ if (!isObject(obj)) |
return; |
var index = toRemove.indexOf(obj); |
@@ -658,14 +679,7 @@ if (typeof WeakMap === 'undefined') { |
var runningMicrotaskCheckpoint = false; |
- var hasDebugForceFullDelivery = hasObserve && (function() { |
- try { |
- eval('%RunMicrotasks()'); |
- return true; |
- } catch (ex) { |
- return false; |
- } |
- })(); |
+ var hasDebugForceFullDelivery = typeof Object.deliverAllChangeRecords == 'function'; |
global.Platform = global.Platform || {}; |
@@ -674,7 +688,7 @@ if (typeof WeakMap === 'undefined') { |
return; |
if (hasDebugForceFullDelivery) { |
- eval('%RunMicrotasks()'); |
+ Object.deliverAllChangeRecords(); |
return; |
} |
@@ -1104,11 +1118,10 @@ if (typeof WeakMap === 'undefined') { |
} |
} |
- var expectedRecordTypes = { |
- add: true, |
- update: true, |
- delete: true |
- }; |
+ var expectedRecordTypes = {}; |
+ expectedRecordTypes[PROP_ADD_TYPE] = true; |
+ expectedRecordTypes[PROP_UPDATE_TYPE] = true; |
+ expectedRecordTypes[PROP_DELETE_TYPE] = true; |
function notifyFunction(object, name) { |
if (typeof Object.observe !== 'function') |
@@ -1132,7 +1145,7 @@ if (typeof WeakMap === 'undefined') { |
var value = observable.open(function(newValue, oldValue) { |
value = newValue; |
if (notify) |
- notify('update', oldValue); |
+ notify(PROP_UPDATE_TYPE, oldValue); |
}); |
Object.defineProperty(target, name, { |
@@ -1174,10 +1187,10 @@ if (typeof WeakMap === 'undefined') { |
if (!(record.name in oldValues)) |
oldValues[record.name] = record.oldValue; |
- if (record.type == 'update') |
+ if (record.type == PROP_UPDATE_TYPE) |
continue; |
- if (record.type == 'add') { |
+ if (record.type == PROP_ADD_TYPE) { |
if (record.name in removed) |
delete removed[record.name]; |
else |
@@ -1574,12 +1587,12 @@ if (typeof WeakMap === 'undefined') { |
for (var i = 0; i < changeRecords.length; i++) { |
var record = changeRecords[i]; |
switch(record.type) { |
- case 'splice': |
+ case ARRAY_SPLICE_TYPE: |
mergeSplice(splices, record.index, record.removed.slice(), record.addedCount); |
break; |
- case 'add': |
- case 'update': |
- case 'delete': |
+ case PROP_ADD_TYPE: |
+ case PROP_UPDATE_TYPE: |
+ case PROP_DELETE_TYPE: |
if (!isIndex(record.name)) |
continue; |
var index = toNumber(record.name); |
@@ -1628,6 +1641,16 @@ if (typeof WeakMap === 'undefined') { |
global.CompoundObserver = CompoundObserver; |
global.Path = Path; |
global.ObserverTransform = ObserverTransform; |
+ |
+ // TODO(rafaelw): Only needed for testing until new change record names |
+ // make it to release. |
+ global.Observer.changeRecordTypes = { |
+ add: PROP_ADD_TYPE, |
+ update: PROP_UPDATE_TYPE, |
+ reconfigure: PROP_RECONFIGURE_TYPE, |
+ 'delete': PROP_DELETE_TYPE, |
+ splice: ARRAY_SPLICE_TYPE |
+ }; |
})(typeof global !== 'undefined' && global && typeof module !== 'undefined' && module ? global : this || window); |
// prepoulate window.Platform.flags for default controls |
@@ -1643,8 +1666,7 @@ window.logFlags = window.logFlags || {}; |
o = o.split('='); |
o[0] && (flags[o[0]] = o[1] || true); |
}); |
- var entryPoint = document.currentScript || |
- document.querySelector('script[src*="platform.js"]'); |
+ var entryPoint = document.currentScript || document.querySelector('script[src*="platform.js"]'); |
if (entryPoint) { |
var a = entryPoint.attributes; |
for (var i = 0, n; i < a.length; i++) { |
@@ -1662,19 +1684,13 @@ window.logFlags = window.logFlags || {}; |
// If any of these flags match 'native', then force native ShadowDOM; any |
// other truthy value, or failure to detect native |
// ShadowDOM, results in polyfill |
- flags.shadow = flags.shadow || flags.shadowdom || flags.polyfill; |
+ flags.shadow = (flags.shadow || flags.shadowdom || flags.polyfill); |
if (flags.shadow === 'native') { |
flags.shadow = false; |
} else { |
flags.shadow = flags.shadow || !HTMLElement.prototype.createShadowRoot; |
} |
- if (flags.shadow && document.querySelectorAll('script').length > 1) { |
- console.warn('platform.js is not the first script on the page. ' + |
- 'See http://www.polymer-project.org/docs/start/platform.html#setup ' + |
- 'for details.'); |
- } |
- |
// CustomElements polyfill flag |
if (flags.register) { |
window.CustomElements = window.CustomElements || {flags: {}}; |
@@ -2554,9 +2570,6 @@ window.ShadowDOMPolyfill = {}; |
function setTreeScope(node, treeScope) { |
if (node.treeScope_ !== treeScope) { |
node.treeScope_ = treeScope; |
- for (var sr = node.shadowRoot; sr; sr = sr.olderShadowRoot) { |
- sr.treeScope_.parent = treeScope; |
- } |
for (var child = node.firstChild; child; child = child.nextSibling) { |
setTreeScope(child, treeScope); |
} |
@@ -2753,17 +2766,8 @@ window.ShadowDOMPolyfill = {}; |
if (handledEventsTable.get(originalEvent)) |
return; |
handledEventsTable.set(originalEvent, true); |
- dispatchEvent(wrap(originalEvent), wrap(originalEvent.target)); |
- } |
- function isLoadLikeEvent(event) { |
- switch (event.type) { |
- case 'beforeunload': |
- case 'load': |
- case 'unload': |
- return true; |
- } |
- return false; |
+ return dispatchEvent(wrap(originalEvent), wrap(originalEvent.target)); |
} |
function dispatchEvent(event, originalWrapperTarget) { |
@@ -2775,15 +2779,15 @@ window.ShadowDOMPolyfill = {}; |
scope.renderAllPending(); |
var eventPath = retarget(originalWrapperTarget); |
- // For window "load" events the "load" event is dispatched at the window but |
+ // For window load events the load event is dispatched at the window but |
// the target is set to the document. |
// |
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the-end |
// |
// TODO(arv): Find a less hacky way to do this. |
- if (eventPath.length === 2 && |
- eventPath[0].target instanceof wrappers.Document && |
- isLoadLikeEvent(event)) { |
+ if (event.type === 'load' && |
+ eventPath.length === 2 && |
+ eventPath[0].target instanceof wrappers.Document) { |
eventPath.shift(); |
} |
@@ -2853,26 +2857,17 @@ window.ShadowDOMPolyfill = {}; |
if ('relatedTarget' in event) { |
var originalEvent = unwrap(event); |
- var unwrappedRelatedTarget = originalEvent.relatedTarget; |
- |
// X-Tag sets relatedTarget on a CustomEvent. If they do that there is no |
// way to have relatedTarget return the adjusted target but worse is that |
// the originalEvent might not have a relatedTarget so we hit an assert |
// when we try to wrap it. |
- if (unwrappedRelatedTarget) { |
- // In IE we can get objects that are not EventTargets at this point. |
- // Safari does not have an EventTarget interface so revert to checking |
- // for addEventListener as an approximation. |
- if (unwrappedRelatedTarget instanceof Object && |
- unwrappedRelatedTarget.addEventListener) { |
- var relatedTarget = wrap(unwrappedRelatedTarget); |
- |
- var adjusted = adjustRelatedTarget(currentTarget, relatedTarget); |
- if (adjusted === target) |
- return true; |
- } else { |
- adjusted = null; |
- } |
+ if (originalEvent.relatedTarget) { |
+ var relatedTarget = wrap(originalEvent.relatedTarget); |
+ |
+ var adjusted = adjustRelatedTarget(currentTarget, relatedTarget); |
+ if (adjusted === target) |
+ return true; |
+ |
relatedTargetTable.set(event, adjusted); |
} |
} |
@@ -2959,14 +2954,10 @@ window.ShadowDOMPolyfill = {}; |
* @constructor |
*/ |
function Event(type, options) { |
- if (type instanceof OriginalEvent) { |
- var impl = type; |
- if (!OriginalBeforeUnloadEvent && impl.type === 'beforeunload') |
- return new BeforeUnloadEvent(impl); |
- this.impl = impl; |
- } else { |
+ if (type instanceof OriginalEvent) |
+ this.impl = type; |
+ else |
return wrap(constructEvent(OriginalEvent, 'Event', type, options)); |
- } |
} |
Event.prototype = { |
get target() { |
@@ -3049,11 +3040,7 @@ window.ShadowDOMPolyfill = {}; |
var relatedTargetProto = { |
get relatedTarget() { |
- var relatedTarget = relatedTargetTable.get(this); |
- // relatedTarget can be null. |
- if (relatedTarget !== undefined) |
- return relatedTarget; |
- return wrap(unwrap(this).relatedTarget); |
+ return relatedTargetTable.get(this) || wrap(unwrap(this).relatedTarget); |
} |
}; |
@@ -3142,12 +3129,8 @@ window.ShadowDOMPolyfill = {}; |
configureEventConstructor('FocusEvent', {relatedTarget: null}, 'UIEvent'); |
} |
- // Safari 7 does not yet have BeforeUnloadEvent. |
- // https://bugs.webkit.org/show_bug.cgi?id=120849 |
- var OriginalBeforeUnloadEvent = window.BeforeUnloadEvent; |
- |
function BeforeUnloadEvent(impl) { |
- Event.call(this, impl); |
+ Event.call(this); |
} |
BeforeUnloadEvent.prototype = Object.create(Event.prototype); |
mixin(BeforeUnloadEvent.prototype, { |
@@ -3159,9 +3142,6 @@ window.ShadowDOMPolyfill = {}; |
} |
}); |
- if (OriginalBeforeUnloadEvent) |
- registerWrapper(OriginalBeforeUnloadEvent, BeforeUnloadEvent); |
- |
function isValidListener(fun) { |
if (typeof fun === 'function') |
return true; |
@@ -3490,7 +3470,6 @@ window.ShadowDOMPolyfill = {}; |
var registerWrapper = scope.registerWrapper; |
var setTreeScope = scope.setTreeScope; |
var unwrap = scope.unwrap; |
- var unwrapIfNeeded = scope.unwrapIfNeeded; |
var wrap = scope.wrap; |
var wrapIfNeeded = scope.wrapIfNeeded; |
var wrappers = scope.wrappers; |
@@ -4139,8 +4118,7 @@ window.ShadowDOMPolyfill = {}; |
compareDocumentPosition: function(otherNode) { |
// This only wraps, it therefore only operates on the composed DOM and not |
// the logical DOM. |
- return originalCompareDocumentPosition.call(this.impl, |
- unwrapIfNeeded(otherNode)); |
+ return originalCompareDocumentPosition.call(this.impl, unwrap(otherNode)); |
}, |
normalize: function() { |
@@ -4327,12 +4305,6 @@ window.ShadowDOMPolyfill = {}; |
} |
wrapperList.length = i; |
return wrapperList; |
- }, |
- |
- remove: function() { |
- var p = this.parentNode; |
- if (p) |
- p.removeChild(this); |
} |
}; |
@@ -5275,14 +5247,8 @@ window.ShadowDOMPolyfill = {}; |
remove: function(indexOrNode) { |
// Spec only allows index but implementations allow index or node. |
// remove() is also allowed which is same as remove(undefined) |
- if (indexOrNode === undefined) { |
- HTMLElement.prototype.remove.call(this); |
- return; |
- } |
- |
if (typeof indexOrNode === 'object') |
indexOrNode = unwrap(indexOrNode); |
- |
unwrap(this).remove(indexOrNode); |
}, |
@@ -6802,15 +6768,7 @@ window.ShadowDOMPolyfill = {}; |
if (document.registerElement) { |
var originalRegisterElement = document.registerElement; |
Document.prototype.registerElement = function(tagName, object) { |
- var prototype, extendsOption; |
- if (object !== undefined) { |
- prototype = object.prototype; |
- extendsOption = object.extends; |
- } |
- |
- if (!prototype) |
- prototype = Object.create(HTMLElement.prototype); |
- |
+ var prototype = object.prototype; |
// If we already used the object as a prototype for another custom |
// element. |
@@ -6871,13 +6829,13 @@ window.ShadowDOMPolyfill = {}; |
}); |
var p = {prototype: newPrototype}; |
- if (extendsOption) |
- p.extends = extendsOption; |
+ if (object.extends) |
+ p.extends = object.extends; |
function CustomElementConstructor(node) { |
if (!node) { |
- if (extendsOption) { |
- return document.createElement(extendsOption, tagName); |
+ if (object.extends) { |
+ return document.createElement(object.extends, tagName); |
} else { |
return document.createElement(tagName); |
} |
@@ -7079,31 +7037,6 @@ window.ShadowDOMPolyfill = {}; |
})(window.ShadowDOMPolyfill); |
-/** |
- * Copyright 2014 The Polymer Authors. All rights reserved. |
- * Use of this source code is goverened by a BSD-style |
- * license that can be found in the LICENSE file. |
- */ |
- |
-(function(scope) { |
- 'use strict'; |
- |
- var unwrap = scope.unwrap; |
- |
- // DataTransfer (Clipboard in old Blink/WebKit) has a single method that |
- // requires wrapping. Since it is only a method we do not need a real wrapper, |
- // we can just override the method. |
- |
- var OriginalDataTransfer = window.DataTransfer || window.Clipboard; |
- var OriginalDataTransferSetDragImage = |
- OriginalDataTransfer.prototype.setDragImage; |
- |
- OriginalDataTransfer.prototype.setDragImage = function(image, x, y) { |
- OriginalDataTransferSetDragImage.call(this, unwrap(image), x, y); |
- }; |
- |
-})(window.ShadowDOMPolyfill); |
- |
// Copyright 2013 The Polymer Authors. All rights reserved. |
// Use of this source code is goverened by a BSD-style |
// license that can be found in the LICENSE file. |
@@ -7274,7 +7207,7 @@ window.ShadowDOMPolyfill = {}; |
Shimmed features: |
- * :host, :host-context: ShadowDOM allows styling of the shadowRoot's host |
+ * :host, :ancestor: ShadowDOM allows styling of the shadowRoot's host |
element using the :host rule. To shim this feature, the :host styles are |
reformatted and prefixed with a given scope name and promoted to a |
document level stylesheet. |
@@ -7448,7 +7381,7 @@ var ShadowCSS = { |
def.rootStyles = styles; |
def.scopeStyles = def.rootStyles; |
var extendee = this.registry[def.extendsName]; |
- if (extendee) { |
+ if (extendee && (!root || root.querySelector('shadow'))) { |
def.scopeStyles = extendee.scopeStyles.concat(def.scopeStyles); |
} |
return def; |
@@ -7543,7 +7476,7 @@ var ShadowCSS = { |
var unscoped = this.extractUnscopedRulesFromCssText(cssText); |
cssText = this.insertPolyfillHostInCssText(cssText); |
cssText = this.convertColonHost(cssText); |
- cssText = this.convertColonHostContext(cssText); |
+ cssText = this.convertColonAncestor(cssText); |
cssText = this.convertCombinators(cssText); |
if (scopeSelector) { |
var self = this, cssText; |
@@ -7592,7 +7525,7 @@ var ShadowCSS = { |
this.colonHostPartReplacer); |
}, |
/* |
- * convert a rule like :host-context(.foo) > .bar { } |
+ * convert a rule like :ancestor(.foo) > .bar { } |
* |
* to |
* |
@@ -7600,15 +7533,15 @@ var ShadowCSS = { |
* |
* and |
* |
- * :host-context(.foo:host) .bar { ... } |
+ * :ancestor(.foo:host) .bar { ... } |
* |
* to |
* |
* scopeName.foo .bar { ... } |
*/ |
- convertColonHostContext: function(cssText) { |
- return this.convertColonRule(cssText, cssColonHostContextRe, |
- this.colonHostContextPartReplacer); |
+ convertColonAncestor: function(cssText) { |
+ return this.convertColonRule(cssText, cssColonAncestorRe, |
+ this.colonAncestorPartReplacer); |
}, |
convertColonRule: function(cssText, regExp, partReplacer) { |
// p1 = :host, p2 = contents of (), p3 rest of rule |
@@ -7626,7 +7559,7 @@ var ShadowCSS = { |
} |
}); |
}, |
- colonHostContextPartReplacer: function(host, part, suffix) { |
+ colonAncestorPartReplacer: function(host, part, suffix) { |
if (part.match(polyfillHost)) { |
return this.colonHostPartReplacer(host, part, suffix); |
} else { |
@@ -7640,10 +7573,7 @@ var ShadowCSS = { |
* Convert ^ and ^^ combinators by replacing with space. |
*/ |
convertCombinators: function(cssText) { |
- for (var i=0; i < combinatorsRe.length; i++) { |
- cssText = cssText.replace(combinatorsRe[i], ' '); |
- } |
- return cssText; |
+ return cssText.replace(/\^\^/g, ' ').replace(/\^/g, ' '); |
}, |
// change a selector like 'div' to 'name div' |
scopeRules: function(cssRules, scopeSelector) { |
@@ -7716,31 +7646,17 @@ var ShadowCSS = { |
return scoped; |
}, |
insertPolyfillHostInCssText: function(selector) { |
- return selector.replace(colonHostContextRe, polyfillHostContext).replace( |
- colonHostRe, polyfillHost); |
+ return selector.replace(hostRe, polyfillHost).replace(colonHostRe, |
+ polyfillHost).replace(colonAncestorRe, polyfillAncestor); |
}, |
propertiesFromRule: function(rule) { |
- var cssText = rule.style.cssText; |
// TODO(sorvell): Safari cssom incorrectly removes quotes from the content |
// property. (https://bugs.webkit.org/show_bug.cgi?id=118045) |
- // don't replace attr rules |
- if (rule.style.content && !rule.style.content.match(/['"]+|attr/)) { |
- cssText = cssText.replace(/content:[^;]*;/g, 'content: \'' + |
+ if (rule.style.content && !rule.style.content.match(/['"]+/)) { |
+ return rule.style.cssText.replace(/content:[^;]*;/g, 'content: \'' + |
rule.style.content + '\';'); |
} |
- // TODO(sorvell): we can workaround this issue here, but we need a list |
- // of troublesome properties to fix https://github.com/Polymer/platform/issues/53 |
- // |
- // inherit rules can be omitted from cssText |
- // TODO(sorvell): remove when Blink bug is fixed: |
- // https://code.google.com/p/chromium/issues/detail?id=358273 |
- var style = rule.style; |
- for (var i in style) { |
- if (style[i] === 'initial') { |
- cssText += i + ': initial; '; |
- } |
- } |
- return cssText; |
+ return rule.style.cssText; |
}, |
replaceTextInStyles: function(styles, action) { |
if (styles && action) { |
@@ -7776,28 +7692,21 @@ var selectorRe = /([^{]*)({[\s\S]*?})/gim, |
cssPartRe = /::part\(([^)]*)\)/gim, |
// note: :host pre-processed to -shadowcsshost. |
polyfillHost = '-shadowcsshost', |
- // note: :host-context pre-processed to -shadowcsshostcontext. |
- polyfillHostContext = '-shadowcsscontext', |
+ // note: :ancestor pre-processed to -shadowcssancestor. |
+ polyfillAncestor = '-shadowcssancestor', |
parenSuffix = ')(?:\\((' + |
'(?:\\([^)(]*\\)|[^)(]*)+?' + |
')\\))?([^,{]*)'; |
cssColonHostRe = new RegExp('(' + polyfillHost + parenSuffix, 'gim'), |
- cssColonHostContextRe = new RegExp('(' + polyfillHostContext + parenSuffix, 'gim'), |
+ cssColonAncestorRe = new RegExp('(' + polyfillAncestor + parenSuffix, 'gim'), |
selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$', |
+ hostRe = /@host/gim, |
colonHostRe = /\:host/gim, |
- colonHostContextRe = /\:host-context/gim, |
+ colonAncestorRe = /\:ancestor/gim, |
/* host name without combinator */ |
polyfillHostNoCombinator = polyfillHost + '-no-combinator', |
polyfillHostRe = new RegExp(polyfillHost, 'gim'), |
- polyfillHostContextRe = new RegExp(polyfillHostContext, 'gim'), |
- combinatorsRe = [ |
- /\^\^/g, |
- /\^/g, |
- /\/shadow\//g, |
- /\/shadow-deep\//g, |
- /::shadow/g, |
- /\/deep\//g |
- ]; |
+ polyfillAncestorRe = new RegExp(polyfillAncestor, 'gim'); |
function stylesToCssText(styles, preserveComments) { |
var cssText = ''; |
@@ -8009,18 +7918,30 @@ scope.ShadowCSS = ShadowCSS; |
window.wrap = window.unwrap = function(n){ |
return n; |
} |
- |
- addEventListener('DOMContentLoaded', function() { |
- if (CustomElements.useNative === false) { |
- var originalCreateShadowRoot = Element.prototype.createShadowRoot; |
- Element.prototype.createShadowRoot = function() { |
- var root = originalCreateShadowRoot.call(this); |
- CustomElements.watchShadow(this); |
- return root; |
- }; |
+ |
+ var originalCreateShadowRoot = Element.prototype.webkitCreateShadowRoot; |
+ Element.prototype.webkitCreateShadowRoot = function() { |
+ var elderRoot = this.webkitShadowRoot; |
+ var root = originalCreateShadowRoot.call(this); |
+ root.olderShadowRoot = elderRoot; |
+ root.host = this; |
+ CustomElements.watchShadow(this); |
+ return root; |
+ } |
+ |
+ Object.defineProperties(Element.prototype, { |
+ shadowRoot: { |
+ get: function() { |
+ return this.webkitShadowRoot; |
+ } |
+ }, |
+ createShadowRoot: { |
+ value: function() { |
+ return this.webkitCreateShadowRoot(); |
+ } |
} |
}); |
- |
+ |
window.templateContent = function(inTemplate) { |
// if MDV exists, it may need to boostrap this template to reveal content |
if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) { |
@@ -9868,38 +9789,23 @@ window.HTMLImports = window.HTMLImports || {flags:{}}; |
}, |
fetch: function(url, elt) { |
flags.load && console.log('fetch', url, elt); |
- if (url.match(/^data:/)) { |
- // Handle Data URI Scheme |
- var pieces = url.split(','); |
- var header = pieces[0]; |
- var body = pieces[1]; |
- if(header.indexOf(';base64') > -1) { |
- body = atob(body); |
- } else { |
- body = decodeURIComponent(body); |
- } |
- setTimeout(function() { |
- this.receive(url, elt, null, body); |
- }.bind(this), 0); |
+ var receiveXhr = function(err, resource) { |
+ this.receive(url, elt, err, resource); |
+ }.bind(this); |
+ xhr.load(url, receiveXhr); |
+ // TODO(sorvell): blocked on |
+ // https://code.google.com/p/chromium/issues/detail?id=257221 |
+ // xhr'ing for a document makes scripts in imports runnable; otherwise |
+ // they are not; however, it requires that we have doctype=html in |
+ // the import which is unacceptable. This is only needed on Chrome |
+ // to avoid the bug above. |
+ /* |
+ if (isDocumentLink(elt)) { |
+ xhr.loadDocument(url, receiveXhr); |
} else { |
- var receiveXhr = function(err, resource) { |
- this.receive(url, elt, err, resource); |
- }.bind(this); |
xhr.load(url, receiveXhr); |
- // TODO(sorvell): blocked on) |
- // https://code.google.com/p/chromium/issues/detail?id=257221 |
- // xhr'ing for a document makes scripts in imports runnable; otherwise |
- // they are not; however, it requires that we have doctype=html in |
- // the import which is unacceptable. This is only needed on Chrome |
- // to avoid the bug above. |
- /* |
- if (isDocumentLink(elt)) { |
- xhr.loadDocument(url, receiveXhr); |
- } else { |
- xhr.load(url, receiveXhr); |
- } |
- */ |
} |
+ */ |
}, |
receive: function(url, elt, err, resource) { |
this.cache[url] = resource; |
@@ -11024,7 +10930,6 @@ if (useNative) { |
scope.upgradeDocument = nop; |
scope.upgradeDocumentTree = nop; |
scope.takeRecords = nop; |
- scope.reservedTagList = []; |
} else { |
@@ -11081,10 +10986,6 @@ if (useNative) { |
// offer guidance) |
throw new Error('document.registerElement: first argument (\'name\') must contain a dash (\'-\'). Argument provided was \'' + String(name) + '\'.'); |
} |
- // prevent registering reserved names |
- if (isReservedTag(name)) { |
- throw new Error('Failed to execute \'registerElement\' on \'Document\': Registration failed for type \'' + String(name) + '\'. The type name is invalid.'); |
- } |
// elements may only be registered once |
if (getRegisteredDefinition(name)) { |
throw new Error('DuplicateDefinitionError: a type with name \'' + String(name) + '\' is already registered'); |
@@ -11128,19 +11029,6 @@ if (useNative) { |
return definition.ctor; |
} |
- function isReservedTag(name) { |
- for (var i = 0; i < reservedTagList.length; i++) { |
- if (name === reservedTagList[i]) { |
- return true; |
- } |
- } |
- } |
- |
- var reservedTagList = [ |
- 'annotation-xml', 'color-profile', 'font-face', 'font-face-src', |
- 'font-face-uri', 'font-face-format', 'font-face-name', 'missing-glyph' |
- ]; |
- |
function ancestry(extnds) { |
var extendee = getRegisteredDefinition(extnds); |
if (extendee) { |
@@ -11437,7 +11325,6 @@ if (!Object.__proto__ && !useNative) { |
// exports |
scope.instanceof = isInstance; |
-scope.reservedTagList = reservedTagList; |
// bc |
document.register = document.registerElement; |
@@ -11871,7 +11758,7 @@ scope.styleResolver = styleResolver; |
*/ |
(function() { |
function shadowSelector(v) { |
- return 'body /shadow-deep/ ' + selector(v); |
+ return 'body ^^ ' + selector(v); |
} |
function selector(v) { |
return '[touch-action="' + v + '"]'; |
@@ -11893,31 +11780,18 @@ scope.styleResolver = styleResolver; |
} |
]; |
var styles = ''; |
- // only install stylesheet if the browser has touch action support |
- var head = document.head; |
- var hasNativePE = window.PointerEvent || window.MSPointerEvent; |
- // only add shadow selectors if shadowdom is supported |
- var hasShadowRoot = !window.ShadowDOMPolyfill && document.head.createShadowRoot; |
- |
- if (hasNativePE) { |
- attrib2css.forEach(function(r) { |
- if (String(r) === r) { |
- styles += selector(r) + rule(r) + '\n'; |
- if (hasShadowRoot) { |
- styles += shadowSelector(r) + rule(r) + '\n'; |
- } |
- } else { |
- styles += r.selectors.map(selector) + rule(r.rule) + '\n'; |
- if (hasShadowRoot) { |
- styles += r.selectors.map(shadowSelector) + rule(r.rule) + '\n'; |
- } |
- } |
- }); |
- |
- var el = document.createElement('style'); |
- el.textContent = styles; |
- document.head.appendChild(el); |
- } |
+ attrib2css.forEach(function(r) { |
+ if (String(r) === r) { |
+ styles += selector(r) + rule(r) + '\n'; |
+ styles += shadowSelector(r) + rule(r) + '\n'; |
+ } else { |
+ styles += r.selectors.map(selector) + rule(r.rule) + '\n'; |
+ styles += r.selectors.map(shadowSelector) + rule(r.rule) + '\n'; |
+ } |
+ }); |
+ var el = document.createElement('style'); |
+ el.textContent = styles; |
+ document.head.appendChild(el); |
})(); |
/* |
@@ -11941,6 +11815,16 @@ scope.styleResolver = styleResolver; |
* @return {Event} A new PointerEvent of type `inType` and initialized with properties from `inDict`. |
*/ |
(function(scope) { |
+ // test for DOM Level 4 Events |
+ var NEW_MOUSE_EVENT = false; |
+ var HAS_BUTTONS = false; |
+ try { |
+ var ev = new MouseEvent('click', {buttons: 1}); |
+ NEW_MOUSE_EVENT = true; |
+ HAS_BUTTONS = ev.buttons === 1; |
+ ev = null; |
+ } catch(e) { |
+ } |
var MOUSE_PROPS = [ |
'bubbles', |
@@ -11957,8 +11841,6 @@ scope.styleResolver = styleResolver; |
'metaKey', |
'button', |
'relatedTarget', |
- 'pageX', |
- 'pageY' |
]; |
var MOUSE_DEFAULTS = [ |
@@ -11975,23 +11857,73 @@ scope.styleResolver = styleResolver; |
false, |
false, |
0, |
- null, |
- 0, |
- 0 |
+ null |
]; |
function PointerEvent(inType, inDict) { |
- inDict = inDict || Object.create(null); |
+ inDict = inDict || {}; |
+ // According to the w3c spec, |
+ // http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-button |
+ // MouseEvent.button == 0 can mean either no mouse button depressed, or the |
+ // left mouse button depressed. |
+ // |
+ // As of now, the only way to distinguish between the two states of |
+ // MouseEvent.button is by using the deprecated MouseEvent.which property, as |
+ // this maps mouse buttons to positive integers > 0, and uses 0 to mean that |
+ // no mouse button is held. |
+ // |
+ // MouseEvent.which is derived from MouseEvent.button at MouseEvent creation, |
+ // but initMouseEvent does not expose an argument with which to set |
+ // MouseEvent.which. Calling initMouseEvent with a buttonArg of 0 will set |
+ // MouseEvent.button == 0 and MouseEvent.which == 1, breaking the expectations |
+ // of app developers. |
+ // |
+ // The only way to propagate the correct state of MouseEvent.which and |
+ // MouseEvent.button to a new MouseEvent.button == 0 and MouseEvent.which == 0 |
+ // is to call initMouseEvent with a buttonArg value of -1. |
+ // |
+ // This is fixed with DOM Level 4's use of buttons |
+ var buttons = inDict.buttons; |
+ // touch has two possible buttons state: 0 and 1, rely on being told the right one |
+ if (!HAS_BUTTONS && !buttons && inType !== 'touch') { |
+ switch (inDict.which) { |
+ case 1: buttons = 1; break; |
+ case 2: buttons = 4; break; |
+ case 3: buttons = 2; break; |
+ default: buttons = 0; |
+ } |
+ } |
- var e = document.createEvent('Event'); |
- e.initEvent(inType, inDict.bubbles || false, inDict.cancelable || false); |
+ var e; |
+ if (NEW_MOUSE_EVENT) { |
+ e = new MouseEvent(inType, inDict); |
+ } else { |
+ e = document.createEvent('MouseEvent'); |
+ |
+ // import values from the given dictionary |
+ var props = {}, p; |
+ for(var i = 0; i < MOUSE_PROPS.length; i++) { |
+ p = MOUSE_PROPS[i]; |
+ props[p] = inDict[p] || MOUSE_DEFAULTS[i]; |
+ } |
- // define inherited MouseEvent properties |
- for(var i = 0, p; i < MOUSE_PROPS.length; i++) { |
- p = MOUSE_PROPS[i]; |
- e[p] = inDict[p] || MOUSE_DEFAULTS[i]; |
+ // define the properties inherited from MouseEvent |
+ e.initMouseEvent( |
+ inType, props.bubbles, props.cancelable, props.view, props.detail, |
+ props.screenX, props.screenY, props.clientX, props.clientY, props.ctrlKey, |
+ props.altKey, props.shiftKey, props.metaKey, props.button, props.relatedTarget |
+ ); |
+ } |
+ |
+ // make the event pass instanceof checks |
+ e.__proto__ = PointerEvent.prototype; |
+ |
+ // define the buttons property according to DOM Level 3 spec |
+ if (!HAS_BUTTONS) { |
+ // IE 10 has buttons on MouseEvent.prototype as a getter w/o any setting |
+ // mechanism |
+ Object.defineProperty(e, 'buttons', {get: function(){ return buttons; }, enumerable: true}); |
} |
- e.buttons = inDict.buttons || 0; |
// Spec requires that pointers without pressure specified use 0.5 for down |
// state and 0 for up state. |
@@ -11999,26 +11931,27 @@ scope.styleResolver = styleResolver; |
if (inDict.pressure) { |
pressure = inDict.pressure; |
} else { |
- pressure = e.buttons ? 0.5 : 0; |
+ pressure = buttons ? 0.5 : 0; |
} |
- // add x/y properties aliased to clientX/Y |
- e.x = e.clientX; |
- e.y = e.clientY; |
- |
// define the properties of the PointerEvent interface |
- e.pointerId = inDict.pointerId || 0; |
- e.width = inDict.width || 0; |
- e.height = inDict.height || 0; |
- e.pressure = pressure; |
- e.tiltX = inDict.tiltX || 0; |
- e.tiltY = inDict.tiltY || 0; |
- e.pointerType = inDict.pointerType || ''; |
- e.hwTimestamp = inDict.hwTimestamp || 0; |
- e.isPrimary = inDict.isPrimary || false; |
+ Object.defineProperties(e, { |
+ pointerId: { value: inDict.pointerId || 0, enumerable: true }, |
+ width: { value: inDict.width || 0, enumerable: true }, |
+ height: { value: inDict.height || 0, enumerable: true }, |
+ pressure: { value: pressure, enumerable: true }, |
+ tiltX: { value: inDict.tiltX || 0, enumerable: true }, |
+ tiltY: { value: inDict.tiltY || 0, enumerable: true }, |
+ pointerType: { value: inDict.pointerType || '', enumerable: true }, |
+ hwTimestamp: { value: inDict.hwTimestamp || 0, enumerable: true }, |
+ isPrimary: { value: inDict.isPrimary || false, enumerable: true } |
+ }); |
return e; |
} |
+ // PointerEvent extends MouseEvent |
+ PointerEvent.prototype = Object.create(MouseEvent.prototype); |
+ |
// attach to window |
if (!scope.PointerEvent) { |
scope.PointerEvent = PointerEvent; |
@@ -12129,9 +12062,7 @@ scope.styleResolver = styleResolver; |
'type', |
'target', |
'currentTarget', |
- 'which', |
- 'pageX', |
- 'pageY' |
+ 'which' |
]; |
var CLONE_DEFAULTS = [ |
@@ -12166,8 +12097,6 @@ scope.styleResolver = styleResolver; |
'', |
null, |
null, |
- 0, |
- 0, |
0 |
]; |
@@ -12186,12 +12115,13 @@ scope.styleResolver = styleResolver; |
* - pointercancel: a pointer will no longer generate events |
*/ |
var dispatcher = { |
+ targets: new WeakMap(), |
+ handledEvents: new WeakMap(), |
pointermap: new scope.PointerMap(), |
- eventMap: Object.create(null), |
- captureInfo: Object.create(null), |
+ eventMap: {}, |
// Scope objects for native events. |
// This exists for ease of testing. |
- eventSources: Object.create(null), |
+ eventSources: {}, |
eventSourceList: [], |
/** |
* Add a new event source that will generate pointer events. |
@@ -12281,7 +12211,7 @@ scope.styleResolver = styleResolver; |
// This is used to prevent multiple dispatch of pointerevents from |
// platform events. This can happen when two elements in different scopes |
// are set up to create pointer events, which is relevant to Shadow DOM. |
- if (inEvent._handledByPE) { |
+ if (this.handledEvents.get(inEvent)) { |
return; |
} |
var type = inEvent.type; |
@@ -12289,7 +12219,7 @@ scope.styleResolver = styleResolver; |
if (fn) { |
fn(inEvent); |
} |
- inEvent._handledByPE = true; |
+ this.handledEvents.set(inEvent, true); |
}, |
// set up event listeners |
listen: function(target, events) { |
@@ -12320,14 +12250,14 @@ scope.styleResolver = styleResolver; |
*/ |
makeEvent: function(inType, inEvent) { |
// relatedTarget must be null if pointer is captured |
- if (this.captureInfo[inEvent.pointerId]) { |
+ if (this.captureInfo) { |
inEvent.relatedTarget = null; |
} |
var e = new PointerEvent(inType, inEvent); |
if (inEvent.preventDefault) { |
e.preventDefault = inEvent.preventDefault; |
} |
- e._target = e._target || inEvent.target; |
+ this.targets.set(e, this.targets.get(inEvent) || inEvent.target); |
return e; |
}, |
// make and dispatch an event in one call |
@@ -12343,7 +12273,7 @@ scope.styleResolver = styleResolver; |
* properties. |
*/ |
cloneEvent: function(inEvent) { |
- var eventCopy = Object.create(null), p; |
+ var eventCopy = {}, p; |
for (var i = 0; i < CLONE_PROPS.length; i++) { |
p = CLONE_PROPS[i]; |
eventCopy[p] = inEvent[p] || CLONE_DEFAULTS[i]; |
@@ -12367,32 +12297,33 @@ scope.styleResolver = styleResolver; |
getTarget: function(inEvent) { |
// if pointer capture is set, route all events for the specified pointerId |
// to the capture target |
- return this.captureInfo[inEvent.pointerId] || inEvent._target; |
+ if (this.captureInfo) { |
+ if (this.captureInfo.id === inEvent.pointerId) { |
+ return this.captureInfo.target; |
+ } |
+ } |
+ return this.targets.get(inEvent); |
}, |
setCapture: function(inPointerId, inTarget) { |
- if (this.captureInfo[inPointerId]) { |
- this.releaseCapture(inPointerId); |
+ if (this.captureInfo) { |
+ this.releaseCapture(this.captureInfo.id); |
} |
- this.captureInfo[inPointerId] = inTarget; |
- var e = document.createEvent('Event'); |
- e.initEvent('gotpointercapture', true, false); |
- e.pointerId = inPointerId; |
+ this.captureInfo = {id: inPointerId, target: inTarget}; |
+ var e = new PointerEvent('gotpointercapture', { bubbles: true }); |
this.implicitRelease = this.releaseCapture.bind(this, inPointerId); |
document.addEventListener('pointerup', this.implicitRelease); |
document.addEventListener('pointercancel', this.implicitRelease); |
- e._target = inTarget; |
+ this.targets.set(e, inTarget); |
this.asyncDispatchEvent(e); |
}, |
releaseCapture: function(inPointerId) { |
- var t = this.captureInfo[inPointerId]; |
- if (t) { |
- var e = document.createEvent('Event'); |
- e.initEvent('lostpointercapture', true, false); |
- e.pointerId = inPointerId; |
- this.captureInfo[inPointerId] = undefined; |
+ if (this.captureInfo && this.captureInfo.id === inPointerId) { |
+ var e = new PointerEvent('lostpointercapture', { bubbles: true }); |
+ var t = this.captureInfo.target; |
+ this.captureInfo = null; |
document.removeEventListener('pointerup', this.implicitRelease); |
document.removeEventListener('pointercancel', this.implicitRelease); |
- e._target = t; |
+ this.targets.set(e, t); |
this.asyncDispatchEvent(e); |
} |
}, |
@@ -12409,7 +12340,7 @@ scope.styleResolver = styleResolver; |
} |
}, |
asyncDispatchEvent: function(inEvent) { |
- requestAnimationFrame(this.dispatchEvent.bind(this, inEvent)); |
+ setTimeout(this.dispatchEvent.bind(this, inEvent), 0); |
} |
}; |
dispatcher.boundHandler = dispatcher.eventHandler.bind(dispatcher); |
@@ -12552,13 +12483,6 @@ scope.styleResolver = styleResolver; |
// radius around touchend that swallows mouse events |
var DEDUP_DIST = 25; |
- var WHICH_TO_BUTTONS = [0, 1, 4, 2]; |
- |
- var HAS_BUTTONS = false; |
- try { |
- HAS_BUTTONS = new MouseEvent('test', {buttons: 1}).buttons === 1; |
- } catch (e) {} |
- |
// handler block for native mouse events |
var mouseEvents = { |
POINTER_ID: 1, |
@@ -12600,9 +12524,6 @@ scope.styleResolver = styleResolver; |
e.pointerId = this.POINTER_ID; |
e.isPrimary = true; |
e.pointerType = this.POINTER_TYPE; |
- if (!HAS_BUTTONS) { |
- e.buttons = WHICH_TO_BUTTONS[e.which] || 0; |
- } |
return e; |
}, |
mousedown: function(inEvent) { |
@@ -12667,7 +12588,6 @@ scope.styleResolver = styleResolver; |
(function(scope) { |
var dispatcher = scope.dispatcher; |
- var captureInfo = dispatcher.captureInfo; |
var findTarget = scope.findTarget; |
var allShadows = scope.targetFinding.allShadows.bind(scope.targetFinding); |
var pointermap = dispatcher.pointermap; |
@@ -12686,6 +12606,7 @@ scope.styleResolver = styleResolver; |
// handler block for native touch events |
var touchEvents = { |
+ scrollType: new WeakMap(), |
events: [ |
'touchstart', |
'touchmove', |
@@ -12710,21 +12631,21 @@ scope.styleResolver = styleResolver; |
var a = el.getAttribute(ATTRIB); |
var st = this.touchActionToScrollType(a); |
if (st) { |
- el._scrollType = st; |
+ this.scrollType.set(el, st); |
dispatcher.listen(el, this.events); |
// set touch-action on shadows as well |
allShadows(el).forEach(function(s) { |
- s._scrollType = st; |
+ this.scrollType.set(s, st); |
dispatcher.listen(s, this.events); |
}, this); |
} |
}, |
elementRemoved: function(el) { |
- el._scrollType = undefined; |
+ this.scrollType['delete'](el); |
dispatcher.unlisten(el, this.events); |
// remove touch-action from shadow |
allShadows(el).forEach(function(s) { |
- s._scrollType = undefined; |
+ this.scrollType['delete'](s); |
dispatcher.unlisten(s, this.events); |
}, this); |
}, |
@@ -12734,9 +12655,9 @@ scope.styleResolver = styleResolver; |
var oldSt = this.touchActionToScrollType(oldValue); |
// simply update scrollType if listeners are already established |
if (st && oldSt) { |
- el._scrollType = st; |
+ this.scrollType.set(el, st); |
allShadows(el).forEach(function(s) { |
- s._scrollType = st; |
+ this.scrollType.set(s, st); |
}, this); |
} else if (oldSt) { |
this.elementRemoved(el); |
@@ -12806,46 +12727,44 @@ scope.styleResolver = styleResolver; |
return ret; |
}, |
touchToPointer: function(inTouch) { |
- var cte = this.currentTouchEvent; |
var e = dispatcher.cloneEvent(inTouch); |
// Spec specifies that pointerId 1 is reserved for Mouse. |
// Touch identifiers can start at 0. |
// Add 2 to the touch identifier for compatibility. |
- var id = e.pointerId = inTouch.identifier + 2; |
- e.target = captureInfo[id] || findTarget(e); |
+ e.pointerId = inTouch.identifier + 2; |
+ e.target = findTarget(e); |
e.bubbles = true; |
e.cancelable = true; |
e.detail = this.clickCount; |
e.button = 0; |
- e.buttons = this.typeToButtons(cte.type); |
+ e.buttons = this.typeToButtons(this.currentTouchEvent); |
e.width = inTouch.webkitRadiusX || inTouch.radiusX || 0; |
e.height = inTouch.webkitRadiusY || inTouch.radiusY || 0; |
e.pressure = inTouch.webkitForce || inTouch.force || 0.5; |
e.isPrimary = this.isPrimaryTouch(inTouch); |
e.pointerType = this.POINTER_TYPE; |
- // forward touch preventDefaults |
- var self = this; |
- e.preventDefault = function() { |
- self.scrolling = false; |
- self.firstXY = null; |
- cte.preventDefault(); |
- }; |
return e; |
}, |
processTouches: function(inEvent, inFunction) { |
var tl = inEvent.changedTouches; |
- this.currentTouchEvent = inEvent; |
- for (var i = 0, t; i < tl.length; i++) { |
- t = tl[i]; |
- inFunction.call(this, this.touchToPointer(t)); |
- } |
+ this.currentTouchEvent = inEvent.type; |
+ var pointers = touchMap(tl, this.touchToPointer, this); |
+ // forward touch preventDefaults |
+ pointers.forEach(function(p) { |
+ p.preventDefault = function() { |
+ this.scrolling = false; |
+ this.firstXY = null; |
+ inEvent.preventDefault(); |
+ }; |
+ }, this); |
+ pointers.forEach(inFunction, this); |
}, |
// For single axis scrollers, determines whether the element should emit |
// pointer events or behave as a scroller |
shouldScroll: function(inEvent) { |
if (this.firstXY) { |
var ret; |
- var scrollAxis = inEvent.currentTarget._scrollType; |
+ var scrollAxis = this.scrollType.get(inEvent.currentTarget); |
if (scrollAxis === 'none') { |
// this element is a touch-action: none, should never scroll |
ret = false; |
@@ -12892,7 +12811,7 @@ scope.styleResolver = styleResolver; |
// index in pointermap. |
if (key !== 1 && !this.findTouch(tl, key - 2)) { |
var p = value.out; |
- d.push(p); |
+ d.push(this.touchToPointer(p)); |
} |
}, this); |
d.forEach(this.cancelOut, this); |
@@ -13108,7 +13027,8 @@ scope.styleResolver = styleResolver; |
var dispatcher = scope.dispatcher; |
// only activate if this platform does not have pointer events |
- if (window.PointerEvent !== scope.PointerEvent) { |
+ if (window.navigator.pointerEnabled === undefined) { |
+ Object.defineProperty(window.navigator, 'pointerEnabled', {value: true, enumerable: true}); |
if (window.navigator.msPointerEnabled) { |
var tp = window.navigator.msMaxTouchPoints; |
@@ -13488,7 +13408,7 @@ PointerGestureEvent.prototype.preventTap = function() { |
// must clone events to keep the (possibly shadowed) target correct for |
// async dispatching |
var e = this.cloneEvent(inEvent); |
- requestAnimationFrame(this.runQueue.bind(this, inHandlerFns, e)); |
+ setTimeout(this.runQueue.bind(this, inHandlerFns, e), 0); |
}, |
// Dispatch the queued events |
runQueue: function(inHandlers, inEvent) { |
@@ -13549,7 +13469,10 @@ PointerGestureEvent.prototype.preventTap = function() { |
} |
}, |
asyncDispatchEvent: function(inEvent, inTarget) { |
- requestAnimationFrame(this.dispatchEvent.bind(this, inEvent, inTarget)); |
+ var fn = function() { |
+ this.dispatchEvent(inEvent, inTarget); |
+ }.bind(this); |
+ setTimeout(fn, 0); |
}, |
preventTap: function(inPointerId) { |
var t = this.recognizers.tap; |
@@ -14168,8 +14091,7 @@ PointerGestureEvent.prototype.preventTap = function() { |
pointers.push(p); |
}); |
var dist = 0; |
- // start with at least two pointers |
- var points = {a: pointers[0], b: pointers[1]}; |
+ var points = {}; |
var x, y, d; |
for (var i = 0; i < pointers.length; i++) { |
var a = pointers[i]; |
@@ -14347,12 +14269,19 @@ PointerGestureEvent.prototype.preventTap = function() { |
} |
})(window.PointerGestures); |
-// Copyright (c) 2014 The Polymer Project Authors. All rights reserved. |
-// This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt |
-// The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
-// The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt |
-// Code distributed by Google as part of the polymer project is also |
-// subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt |
+// Copyright 2011 Google Inc. |
+// |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
+// you may not use this file except in compliance with the License. |
+// You may obtain a copy of the License at |
+// |
+// http://www.apache.org/licenses/LICENSE-2.0 |
+// |
+// Unless required by applicable law or agreed to in writing, software |
+// distributed under the License is distributed on an "AS IS" BASIS, |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+// See the License for the specific language governing permissions and |
+// limitations under the License. |
(function(global) { |
'use strict'; |
@@ -14367,24 +14296,42 @@ PointerGestureEvent.prototype.preventTap = function() { |
return typeof node.getElementById === 'function' ? node : null; |
} |
+ |
Node.prototype.bind = function(name, observable) { |
console.error('Unhandled binding to Node: ', this, name, observable); |
}; |
- function updateBindings(node, name, binding) { |
- var bindings = node.bindings_; |
- if (!bindings) |
- bindings = node.bindings_ = {}; |
+ function unbind(node, name) { |
+ var bindings = node.bindings; |
+ if (!bindings) { |
+ node.bindings = {}; |
+ return; |
+ } |
- if (bindings[name]) |
- binding[name].close(); |
+ var binding = bindings[name]; |
+ if (!binding) |
+ return; |
- return bindings[name] = binding; |
+ binding.close(); |
+ bindings[name] = undefined; |
} |
- function returnBinding(node, name, binding) { |
- return binding; |
- } |
+ Node.prototype.unbind = function(name) { |
+ unbind(this, name); |
+ }; |
+ |
+ Node.prototype.unbindAll = function() { |
+ if (!this.bindings) |
+ return; |
+ var names = Object.keys(this.bindings); |
+ for (var i = 0; i < names.length; i++) { |
+ var binding = this.bindings[names[i]]; |
+ if (binding) |
+ binding.close(); |
+ } |
+ |
+ this.bindings = {}; |
+ }; |
function sanitizeValue(value) { |
return value == null ? '' : value; |
@@ -14400,19 +14347,6 @@ PointerGestureEvent.prototype.preventTap = function() { |
}; |
} |
- var maybeUpdateBindings = returnBinding; |
- |
- Object.defineProperty(Platform, 'enableBindingsReflection', { |
- get: function() { |
- return maybeUpdateBindings === updateBindings; |
- }, |
- set: function(enable) { |
- maybeUpdateBindings = enable ? updateBindings : returnBinding; |
- return enable; |
- }, |
- configurable: true |
- }); |
- |
Text.prototype.bind = function(name, value, oneTime) { |
if (name !== 'textContent') |
return Node.prototype.bind.call(this, name, value, oneTime); |
@@ -14420,9 +14354,9 @@ PointerGestureEvent.prototype.preventTap = function() { |
if (oneTime) |
return updateText(this, value); |
- var observable = value; |
- updateText(this, observable.open(textBinding(this))); |
- return maybeUpdateBindings(this, name, observable); |
+ unbind(this, 'textContent'); |
+ updateText(this, value.open(textBinding(this))); |
+ return this.bindings.textContent = value; |
} |
function updateAttribute(el, name, conditional, value) { |
@@ -14453,12 +14387,11 @@ PointerGestureEvent.prototype.preventTap = function() { |
if (oneTime) |
return updateAttribute(this, name, conditional, value); |
- |
- var observable = value; |
+ unbind(this, name); |
updateAttribute(this, name, conditional, |
- observable.open(attributeBinding(this, name, conditional))); |
+ value.open(attributeBinding(this, name, conditional))); |
- return maybeUpdateBindings(this, name, observable); |
+ return this.bindings[name] = value; |
}; |
var checkboxEventType; |
@@ -14527,13 +14460,15 @@ PointerGestureEvent.prototype.preventTap = function() { |
} |
input.addEventListener(eventType, eventHandler); |
- return { |
- close: function() { |
- input.removeEventListener(eventType, eventHandler); |
- observable.close(); |
- }, |
+ var capturedClose = observable.close; |
+ observable.close = function() { |
+ if (!capturedClose) |
+ return; |
+ input.removeEventListener(eventType, eventHandler); |
- observable_: observable |
+ observable.close = capturedClose; |
+ observable.close(); |
+ capturedClose = undefined; |
} |
} |
@@ -14577,10 +14512,10 @@ PointerGestureEvent.prototype.preventTap = function() { |
if (input.tagName === 'INPUT' && |
input.type === 'radio') { |
getAssociatedRadioButtons(input).forEach(function(radio) { |
- var checkedBinding = radio.bindings_.checked; |
+ var checkedBinding = radio.bindings.checked; |
if (checkedBinding) { |
// Set the value directly to avoid an infinite call stack. |
- checkedBinding.observable_.setValue(false); |
+ checkedBinding.setValue(false); |
} |
}); |
} |
@@ -14590,6 +14525,7 @@ PointerGestureEvent.prototype.preventTap = function() { |
if (name !== 'value' && name !== 'checked') |
return HTMLElement.prototype.bind.call(this, name, value, oneTime); |
+ |
this.removeAttribute(name); |
var sanitizeFn = name == 'checked' ? booleanSanitize : sanitizeValue; |
var postEventFn = name == 'checked' ? checkedPostEvent : noop; |
@@ -14597,15 +14533,13 @@ PointerGestureEvent.prototype.preventTap = function() { |
if (oneTime) |
return updateInput(this, name, value, sanitizeFn); |
- |
- var observable = value; |
- var binding = bindInputEvent(this, name, observable, postEventFn); |
+ unbind(this, name); |
+ bindInputEvent(this, name, value, postEventFn); |
updateInput(this, name, |
- observable.open(inputBinding(this, name, sanitizeFn)), |
+ value.open(inputBinding(this, name, sanitizeFn)), |
sanitizeFn); |
- // Checkboxes may need to update bindings of other checkboxes. |
- return updateBindings(this, name, binding); |
+ return this.bindings[name] = value; |
} |
HTMLTextAreaElement.prototype.bind = function(name, value, oneTime) { |
@@ -14617,11 +14551,12 @@ PointerGestureEvent.prototype.preventTap = function() { |
if (oneTime) |
return updateInput(this, 'value', value); |
- var observable = value; |
- var binding = bindInputEvent(this, 'value', observable); |
+ unbind(this, 'value'); |
+ bindInputEvent(this, 'value', value); |
updateInput(this, 'value', |
- observable.open(inputBinding(this, 'value', sanitizeValue))); |
- return maybeUpdateBindings(this, name, binding); |
+ value.open(inputBinding(this, 'value', sanitizeValue))); |
+ |
+ return this.bindings.value = value; |
} |
function updateOption(option, value) { |
@@ -14630,18 +14565,18 @@ PointerGestureEvent.prototype.preventTap = function() { |
var selectBinding; |
var oldValue; |
if (parentNode instanceof HTMLSelectElement && |
- parentNode.bindings_ && |
- parentNode.bindings_.value) { |
+ parentNode.bindings && |
+ parentNode.bindings.value) { |
select = parentNode; |
- selectBinding = select.bindings_.value; |
+ selectBinding = select.bindings.value; |
oldValue = select.value; |
} |
option.value = sanitizeValue(value); |
if (select && select.value != oldValue) { |
- selectBinding.observable_.setValue(select.value); |
- selectBinding.observable_.discardChanges(); |
+ selectBinding.setValue(select.value); |
+ selectBinding.discardChanges(); |
Platform.performMicrotaskCheckpoint(); |
} |
} |
@@ -14661,10 +14596,10 @@ PointerGestureEvent.prototype.preventTap = function() { |
if (oneTime) |
return updateOption(this, value); |
- var observable = value; |
- var binding = bindInputEvent(this, 'value', observable); |
- updateOption(this, observable.open(optionBinding(this))); |
- return maybeUpdateBindings(this, name, binding); |
+ unbind(this, 'value'); |
+ bindInputEvent(this, 'value', value); |
+ updateOption(this, value.open(optionBinding(this))); |
+ return this.bindings.value = value; |
} |
HTMLSelectElement.prototype.bind = function(name, value, oneTime) { |
@@ -14679,22 +14614,27 @@ PointerGestureEvent.prototype.preventTap = function() { |
if (oneTime) |
return updateInput(this, name, value); |
- var observable = value; |
- var binding = bindInputEvent(this, name, observable); |
+ unbind(this, name); |
+ bindInputEvent(this, name, value); |
updateInput(this, name, |
- observable.open(inputBinding(this, name))); |
- |
- // Option update events may need to access select bindings. |
- return updateBindings(this, name, binding); |
+ value.open(inputBinding(this, name))); |
+ return this.bindings[name] = value; |
} |
})(this); |
-// Copyright (c) 2014 The Polymer Project Authors. All rights reserved. |
-// This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt |
-// The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
-// The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt |
-// Code distributed by Google as part of the polymer project is also |
-// subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt |
+// Copyright 2011 Google Inc. |
+// |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
+// you may not use this file except in compliance with the License. |
+// You may obtain a copy of the License at |
+// |
+// http://www.apache.org/licenses/LICENSE-2.0 |
+// |
+// Unless required by applicable law or agreed to in writing, software |
+// distributed under the License is distributed on an "AS IS" BASIS, |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+// See the License for the specific language governing permissions and |
+// limitations under the License. |
(function(global) { |
'use strict'; |
@@ -15159,13 +15099,8 @@ PointerGestureEvent.prototype.preventTap = function() { |
if (oneTime) |
return; |
- if (!this.bindings_) { |
- this.bindings_ = { ref: value }; |
- } else { |
- this.bindings_.ref = value; |
- } |
- |
- return value; |
+ this.unbind('ref'); |
+ return this.bindings.ref = value; |
}, |
processBindingDirectives_: function(directives) { |
@@ -15176,6 +15111,7 @@ PointerGestureEvent.prototype.preventTap = function() { |
if (this.iterator_) { |
this.iterator_.close(); |
this.iterator_ = undefined; |
+ this.bindings.iterator = undefined; |
} |
return; |
@@ -15183,6 +15119,8 @@ PointerGestureEvent.prototype.preventTap = function() { |
if (!this.iterator_) { |
this.iterator_ = new TemplateIterator(this); |
+ this.bindings = this.bindings || {}; |
+ this.bindings.iterator = this.iterator_; |
} |
this.iterator_.updateDependencies(directives, this.model_); |
@@ -15195,16 +15133,14 @@ PointerGestureEvent.prototype.preventTap = function() { |
return this.iterator_; |
}, |
- createInstance: function(model, bindingDelegate, delegate_) { |
+ createInstance: function(model, bindingDelegate, delegate_, |
+ instanceBindings_) { |
if (bindingDelegate) |
delegate_ = this.newDelegate_(bindingDelegate); |
if (!this.refContent_) |
this.refContent_ = this.ref_.content; |
var content = this.refContent_; |
- if (content.firstChild === null) |
- return emptyInstance; |
- |
var map = this.bindingMap_; |
if (!map || map.content !== content) { |
// TODO(rafaelw): Setup a MutationObserver on content to detect |
@@ -15219,32 +15155,21 @@ PointerGestureEvent.prototype.preventTap = function() { |
var instance = stagingDocument.createDocumentFragment(); |
instance.templateCreator_ = this; |
instance.protoContent_ = content; |
- instance.bindings_ = []; |
- instance.terminator_ = null; |
- var instanceRecord = instance.templateInstance_ = { |
+ |
+ var instanceRecord = { |
firstNode: null, |
lastNode: null, |
model: model |
}; |
var i = 0; |
- var collectTerminator = false; |
for (var child = content.firstChild; child; child = child.nextSibling) { |
- // The terminator of the instance is the clone of the last child of the |
- // content. If the last child is an active template, it may produce |
- // instances as a result of production, so simply collecting the last |
- // child of the instance after it has finished producing may be wrong. |
- if (child.nextSibling === null) |
- collectTerminator = true; |
- |
var clone = cloneAndBindInstance(child, instance, stagingDocument, |
map.children[i++], |
model, |
delegate_, |
- instance.bindings_); |
+ instanceBindings_); |
clone.templateInstance_ = instanceRecord; |
- if (collectTerminator) |
- instance.terminator_ = clone; |
} |
instanceRecord.firstNode = instance.firstChild; |
@@ -15279,8 +15204,7 @@ PointerGestureEvent.prototype.preventTap = function() { |
clear: function() { |
this.model_ = undefined; |
this.delegate_ = undefined; |
- if (this.bindings_ && this.bindings_.ref) |
- this.bindings_.ref.close() |
+ this.bindings_ = undefined; |
this.refContent_ = undefined; |
if (!this.iterator_) |
return; |
@@ -15385,14 +15309,9 @@ PointerGestureEvent.prototype.preventTap = function() { |
var pathString = s.slice(startIndex + 2, endIndex).trim(); |
tokens.push(oneTime); // ONE_TIME? |
onlyOneTime = onlyOneTime && oneTime; |
+ tokens.push(Path.get(pathString)); // PATH |
var delegateFn = prepareBindingFn && |
prepareBindingFn(pathString, name, node); |
- // Don't try to parse the expression if there's a prepareBinding function |
- if (delegateFn == null) { |
- tokens.push(Path.get(pathString)); // PATH |
- } else { |
- tokens.push(null); |
- } |
tokens.push(delegateFn); // DELEGATE_FN |
lastIndex = endIndex + 2; |
} |
@@ -15610,14 +15529,14 @@ PointerGestureEvent.prototype.preventTap = function() { |
} |
}); |
- var emptyInstance = document.createDocumentFragment(); |
- emptyInstance.bindings_ = []; |
- emptyInstance.terminator_ = null; |
- |
function TemplateIterator(templateElement) { |
this.closed = false; |
this.templateElement_ = templateElement; |
- this.instances = []; |
+ |
+ // Flattened array of tuples: |
+ // <instanceTerminatorNode, [bindingsSetupByInstance]> |
+ this.terminators = []; |
+ |
this.deps = undefined; |
this.iteratedValue = []; |
this.presentValue = undefined; |
@@ -15712,53 +15631,63 @@ PointerGestureEvent.prototype.preventTap = function() { |
this.iteratedValue)); |
}, |
- getLastInstanceNode: function(index) { |
+ getTerminatorAt: function(index) { |
if (index == -1) |
return this.templateElement_; |
- var instance = this.instances[index]; |
- var terminator = instance.terminator_; |
- if (!terminator) |
- return this.getLastInstanceNode(index - 1); |
- |
+ var terminator = this.terminators[index*2]; |
if (terminator.nodeType !== Node.ELEMENT_NODE || |
this.templateElement_ === terminator) { |
return terminator; |
} |
- var subtemplateIterator = terminator.iterator_; |
- if (!subtemplateIterator) |
+ var subIterator = terminator.iterator_; |
+ if (!subIterator) |
return terminator; |
- return subtemplateIterator.getLastTemplateNode(); |
+ return subIterator.getTerminatorAt(subIterator.terminators.length/2 - 1); |
}, |
- getLastTemplateNode: function() { |
- return this.getLastInstanceNode(this.instances.length - 1); |
- }, |
+ // TODO(rafaelw): If we inserting sequences of instances we can probably |
+ // avoid lots of calls to getTerminatorAt(), or cache its result. |
+ insertInstanceAt: function(index, fragment, instanceNodes, |
+ instanceBindings) { |
+ var previousTerminator = this.getTerminatorAt(index - 1); |
+ var terminator = previousTerminator; |
+ if (fragment) |
+ terminator = fragment.lastChild || terminator; |
+ else if (instanceNodes) |
+ terminator = instanceNodes[instanceNodes.length - 1] || terminator; |
- insertInstanceAt: function(index, fragment) { |
- var previousInstanceLast = this.getLastInstanceNode(index - 1); |
+ this.terminators.splice(index*2, 0, terminator, instanceBindings); |
var parent = this.templateElement_.parentNode; |
- this.instances.splice(index, 0, fragment); |
+ var insertBeforeNode = previousTerminator.nextSibling; |
- parent.insertBefore(fragment, previousInstanceLast.nextSibling); |
+ if (fragment) { |
+ parent.insertBefore(fragment, insertBeforeNode); |
+ } else if (instanceNodes) { |
+ for (var i = 0; i < instanceNodes.length; i++) |
+ parent.insertBefore(instanceNodes[i], insertBeforeNode); |
+ } |
}, |
extractInstanceAt: function(index) { |
- var previousInstanceLast = this.getLastInstanceNode(index - 1); |
- var lastNode = this.getLastInstanceNode(index); |
- var parent = this.templateElement_.parentNode; |
- var instance = this.instances.splice(index, 1)[0]; |
+ var instanceNodes = []; |
+ var previousTerminator = this.getTerminatorAt(index - 1); |
+ var terminator = this.getTerminatorAt(index); |
+ instanceNodes.instanceBindings = this.terminators[index*2 + 1]; |
+ this.terminators.splice(index*2, 2); |
- while (lastNode !== previousInstanceLast) { |
- var node = previousInstanceLast.nextSibling; |
- if (node == lastNode) |
- lastNode = previousInstanceLast; |
+ var parent = this.templateElement_.parentNode; |
+ while (terminator !== previousTerminator) { |
+ var node = previousTerminator.nextSibling; |
+ if (node == terminator) |
+ terminator = previousTerminator; |
- instance.appendChild(parent.removeChild(node)); |
+ parent.removeChild(node); |
+ instanceNodes.push(node); |
} |
- return instance; |
+ return instanceNodes; |
}, |
getDelegateFn: function(fn) { |
@@ -15792,50 +15721,46 @@ PointerGestureEvent.prototype.preventTap = function() { |
delegate.prepareInstancePositionChanged); |
} |
- // Instance Removals |
var instanceCache = new Map; |
var removeDelta = 0; |
- for (var i = 0; i < splices.length; i++) { |
- var splice = splices[i]; |
- var removed = splice.removed; |
- for (var j = 0; j < removed.length; j++) { |
- var model = removed[j]; |
- var instance = this.extractInstanceAt(splice.index + removeDelta); |
- if (instance !== emptyInstance) { |
- instanceCache.set(model, instance); |
- } |
- } |
+ splices.forEach(function(splice) { |
+ splice.removed.forEach(function(model) { |
+ var instanceNodes = |
+ this.extractInstanceAt(splice.index + removeDelta); |
+ instanceCache.set(model, instanceNodes); |
+ }, this); |
removeDelta -= splice.addedCount; |
- } |
+ }, this); |
- // Instance Insertions |
- for (var i = 0; i < splices.length; i++) { |
- var splice = splices[i]; |
+ splices.forEach(function(splice) { |
var addIndex = splice.index; |
for (; addIndex < splice.index + splice.addedCount; addIndex++) { |
var model = this.iteratedValue[addIndex]; |
- var instance = instanceCache.get(model); |
- if (instance) { |
+ var fragment = undefined; |
+ var instanceNodes = instanceCache.get(model); |
+ var instanceBindings; |
+ if (instanceNodes) { |
instanceCache.delete(model); |
+ instanceBindings = instanceNodes.instanceBindings; |
} else { |
- if (this.instanceModelFn_) { |
+ instanceBindings = []; |
+ if (this.instanceModelFn_) |
model = this.instanceModelFn_(model); |
- } |
- if (model === undefined) { |
- instance = emptyInstance; |
- } else { |
- instance = template.createInstance(model, undefined, delegate); |
+ if (model !== undefined) { |
+ fragment = template.createInstance(model, undefined, delegate, |
+ instanceBindings); |
} |
} |
- this.insertInstanceAt(addIndex, instance); |
+ this.insertInstanceAt(addIndex, fragment, instanceNodes, |
+ instanceBindings); |
} |
- } |
+ }, this); |
- instanceCache.forEach(function(instance) { |
- this.closeInstanceBindings(instance); |
+ instanceCache.forEach(function(instanceNodes) { |
+ this.closeInstanceBindings(instanceNodes.instanceBindings); |
}, this); |
if (this.instancePositionChangedFn_) |
@@ -15843,11 +15768,17 @@ PointerGestureEvent.prototype.preventTap = function() { |
}, |
reportInstanceMoved: function(index) { |
- var instance = this.instances[index]; |
- if (instance === emptyInstance) |
- return; |
+ var previousTerminator = this.getTerminatorAt(index - 1); |
+ var terminator = this.getTerminatorAt(index); |
+ if (previousTerminator === terminator) |
+ return; // instance has zero nodes. |
- this.instancePositionChangedFn_(instance.templateInstance_, index); |
+ // We must use the first node of the instance, because any subsequent |
+ // nodes may have been generated by sub-templates. |
+ // TODO(rafaelw): This is brittle WRT instance mutation -- e.g. if the |
+ // first node was removed by script. |
+ var templateInstance = previousTerminator.nextSibling.templateInstance; |
+ this.instancePositionChangedFn_(templateInstance, index); |
}, |
reportInstancesMoved: function(splices) { |
@@ -15875,17 +15806,16 @@ PointerGestureEvent.prototype.preventTap = function() { |
if (offset == 0) |
return; |
- var length = this.instances.length; |
+ var length = this.terminators.length / 2; |
while (index < length) { |
this.reportInstanceMoved(index); |
index++; |
} |
}, |
- closeInstanceBindings: function(instance) { |
- var bindings = instance.bindings_; |
- for (var i = 0; i < bindings.length; i++) { |
- bindings[i].close(); |
+ closeInstanceBindings: function(instanceBindings) { |
+ for (var i = 0; i < instanceBindings.length; i++) { |
+ instanceBindings[i].close(); |
} |
}, |
@@ -15901,11 +15831,11 @@ PointerGestureEvent.prototype.preventTap = function() { |
if (this.closed) |
return; |
this.unobserve(); |
- for (var i = 0; i < this.instances.length; i++) { |
- this.closeInstanceBindings(this.instances[i]); |
+ for (var i = 1; i < this.terminators.length; i += 2) { |
+ this.closeInstanceBindings(this.terminators[i]); |
} |
- this.instances.length = 0; |
+ this.terminators.length = 0; |
this.closeDeps(); |
this.templateElement_.iterator_ = undefined; |
this.closed = true; |
@@ -16954,12 +16884,19 @@ PointerGestureEvent.prototype.preventTap = function() { |
}; |
})(this); |
-// Copyright (c) 2014 The Polymer Project Authors. All rights reserved. |
-// This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt |
-// The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
-// The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt |
-// Code distributed by Google as part of the polymer project is also |
-// subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt |
+// Copyright 2013 Google Inc. |
+// |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
+// you may not use this file except in compliance with the License. |
+// You may obtain a copy of the License at |
+// |
+// http://www.apache.org/licenses/LICENSE-2.0 |
+// |
+// Unless required by applicable law or agreed to in writing, software |
+// distributed under the License is distributed on an "AS IS" BASIS, |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+// See the License for the specific language governing permissions and |
+// limitations under the License. |
(function (global) { |
'use strict'; |
@@ -17386,18 +17323,10 @@ PointerGestureEvent.prototype.preventTap = function() { |
return this.getValue(model, undefined, filterRegistry); |
var observer = new CompoundObserver(); |
- // captures deps. |
- var firstValue = this.getValue(model, observer, filterRegistry); |
- var firstTime = true; |
+ this.getValue(model, observer, filterRegistry); // captures deps. |
var self = this; |
function valueFn() { |
- // deps cannot have changed on first value retrieval. |
- if (firstTime) { |
- firstTime = false; |
- return firstValue; |
- } |
- |
if (self.dynamicDeps) |
observer.startReset(); |
@@ -17541,23 +17470,6 @@ PointerGestureEvent.prototype.preventTap = function() { |
} |
} |
- function isLiteralExpression(pathString) { |
- switch (pathString) { |
- case '': |
- return false; |
- |
- case 'false': |
- case 'null': |
- case 'true': |
- return true; |
- } |
- |
- if (!isNaN(Number(pathString))) |
- return true; |
- |
- return false; |
- }; |
- |
function PolymerExpressions() {} |
PolymerExpressions.prototype = { |
@@ -17601,7 +17513,7 @@ PointerGestureEvent.prototype.preventTap = function() { |
return prepareEventBinding(path, name, this); |
} |
- if (!isLiteralExpression(pathString) && path.valid) { |
+ if (path.valid) { |
if (path.length == 1) { |
return function(model, node, oneTime) { |
if (oneTime) |
@@ -17609,8 +17521,9 @@ PointerGestureEvent.prototype.preventTap = function() { |
var scope = findScope(model, path[0]); |
return new PathObserver(scope, path); |
- }; |
+ } |
} |
+ |
return; // bail out early if pathString is simple path. |
} |
@@ -17673,17 +17586,14 @@ function flush() { |
}; |
// polling dirty checker |
-// flush periodically if platform does not have object observe. |
-if (!Observer.hasObjectObserve) { |
- var FLUSH_POLL_INTERVAL = 125; |
- window.addEventListener('WebComponentsReady', function() { |
- flush(); |
+var FLUSH_POLL_INTERVAL = 125; |
+window.addEventListener('WebComponentsReady', function() { |
+ flush(); |
+ // flush periodically if platform does not have object observe. |
+ if (!Observer.hasObjectObserve) { |
scope.flushPoll = setInterval(flush, FLUSH_POLL_INTERVAL); |
- }); |
-} else { |
- // make flush a no-op when we have Object.observe |
- flush = function() {}; |
-} |
+ } |
+}); |
if (window.CustomElements && !CustomElements.useNative) { |
var originalImportNode = Document.prototype.importNode; |