Index: third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js |
diff --git a/third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js b/third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js |
index efa86c507b5db26e50bd18dae8cfde6a9577a1c8..ad5ce0a9ac00037d97bf8ed06ff6abfb6bbcb5b7 100644 |
--- a/third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js |
+++ b/third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js |
@@ -36,6 +36,9 @@ var annote = { |
bindings: [], |
events: [] |
}; |
+if (element.localName === 'content') { |
+list._hasContent = true; |
+} |
this._parseChildNodesAnnotations(element, annote, list); |
if (element.attributes) { |
this._parseNodeAttributeAnnotations(element, annote, list); |
@@ -54,6 +57,14 @@ for (var i = 0, node = root.firstChild; node; node = node.nextSibling, i++) { |
if (node.localName === 'template' && !node.hasAttribute('preserve-content')) { |
this._parseTemplate(node, i, list, annote); |
} |
+if (node.nodeType === Node.TEXT_NODE) { |
+var n = node.nextSibling; |
+while (n && n.nodeType === Node.TEXT_NODE) { |
+node.textContent += n.textContent; |
+root.removeChild(n); |
+n = n.nextSibling; |
+} |
+} |
var childAnnotation = this._parseNodeAnnotations(node, list, callback); |
if (childAnnotation) { |
childAnnotation.parent = annote; |
@@ -163,6 +174,9 @@ at.value = a === 'style' ? resolveCss(v, ownerDocument) : resolve(v, ownerDocume |
} |
} |
function resolve(url, ownerDocument) { |
+if (url && url[0] === '#') { |
+return url; |
+} |
var resolver = getUrlResolver(ownerDocument); |
resolver.href = url; |
return resolver.href || url; |
@@ -323,18 +337,57 @@ this.listen(node, name, listeners[key]); |
listen: function (node, eventName, methodName) { |
this._listen(node, eventName, this._createEventHandler(node, eventName, methodName)); |
}, |
+_boundListenerKey: function (eventName, methodName) { |
+return eventName + ':' + methodName; |
+}, |
+_recordEventHandler: function (host, eventName, target, methodName, handler) { |
+var hbl = host.__boundListeners; |
+if (!hbl) { |
+hbl = host.__boundListeners = new WeakMap(); |
+} |
+var bl = hbl.get(target); |
+if (!bl) { |
+bl = {}; |
+hbl.set(target, bl); |
+} |
+var key = this._boundListenerKey(eventName, methodName); |
+bl[key] = handler; |
+}, |
+_recallEventHandler: function (host, eventName, target, methodName) { |
+var hbl = host.__boundListeners; |
+if (!hbl) { |
+return; |
+} |
+var bl = hbl.get(target); |
+if (!bl) { |
+return; |
+} |
+var key = this._boundListenerKey(eventName, methodName); |
+return bl[key]; |
+}, |
_createEventHandler: function (node, eventName, methodName) { |
var host = this; |
-return function (e) { |
+var handler = function (e) { |
if (host[methodName]) { |
host[methodName](e, e.detail); |
} else { |
host._warn(host._logf('_createEventHandler', 'listener method `' + methodName + '` not defined')); |
} |
}; |
+this._recordEventHandler(host, eventName, node, methodName, handler); |
+return handler; |
+}, |
+unlisten: function (node, eventName, methodName) { |
+var handler = this._recallEventHandler(this, eventName, node, methodName); |
+if (handler) { |
+this._unlisten(node, eventName, handler); |
+} |
}, |
_listen: function (node, eventName, handler) { |
node.addEventListener(eventName, handler); |
+}, |
+_unlisten: function (node, eventName, handler) { |
+node.removeEventListener(eventName, handler); |
} |
}); |
(function () { |
@@ -353,6 +406,7 @@ var MOUSE_EVENTS = [ |
'mouseup', |
'click' |
]; |
+var IS_TOUCH_ONLY = navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/); |
var mouseCanceller = function (mouseEvent) { |
mouseEvent[HANDLED_OBJ] = { skip: true }; |
if (mouseEvent.type === 'click') { |
@@ -377,6 +431,9 @@ document.removeEventListener(en, mouseCanceller, true); |
} |
} |
function ignoreMouse() { |
+if (IS_TOUCH_ONLY) { |
+return; |
+} |
if (!POINTERSTATE.mouse.mouseIgnoreJob) { |
setupTeardownMouseCanceller(true); |
} |
@@ -388,7 +445,6 @@ POINTERSTATE.mouse.mouseIgnoreJob = null; |
POINTERSTATE.mouse.mouseIgnoreJob = Polymer.Debounce(POINTERSTATE.mouse.mouseIgnoreJob, unset, MOUSE_TIMEOUT); |
} |
var POINTERSTATE = { |
-tapPrevented: false, |
mouse: { |
target: null, |
mouseIgnoreJob: null |
@@ -426,6 +482,12 @@ node = next; |
} |
return node; |
}, |
+findOriginalTarget: function (ev) { |
+if (ev.path) { |
+return ev.path[0]; |
+} |
+return ev.target; |
+}, |
handleNative: function (ev) { |
var handled; |
var type = ev.type; |
@@ -510,24 +572,62 @@ node[GESTURE_KEY] = gobj = {}; |
} |
for (var i = 0, dep, gd; i < deps.length; i++) { |
dep = deps[i]; |
+if (IS_TOUCH_ONLY && MOUSE_EVENTS.indexOf(dep) > -1) { |
+continue; |
+} |
gd = gobj[dep]; |
if (!gd) { |
-gobj[dep] = gd = {}; |
+gobj[dep] = gd = { _count: 0 }; |
+} |
+if (gd._count === 0) { |
node.addEventListener(dep, this.handleNative); |
} |
gd[name] = (gd[name] || 0) + 1; |
+gd._count = (gd._count || 0) + 1; |
} |
node.addEventListener(evType, handler); |
if (recognizer.touchAction) { |
this.setTouchAction(node, recognizer.touchAction); |
} |
}, |
+remove: function (node, evType, handler) { |
+var recognizer = this.gestures[evType]; |
+var deps = recognizer.deps; |
+var name = recognizer.name; |
+var gobj = node[GESTURE_KEY]; |
+if (gobj) { |
+for (var i = 0, dep, gd; i < deps.length; i++) { |
+dep = deps[i]; |
+gd = gobj[dep]; |
+if (gd && gd[name]) { |
+gd[name] = (gd[name] || 1) - 1; |
+gd._count = (gd._count || 1) - 1; |
+} |
+if (gd._count === 0) { |
+node.removeEventListener(dep, this.handleNative); |
+} |
+} |
+} |
+node.removeEventListener(evType, handler); |
+}, |
register: function (recog) { |
this.recognizers.push(recog); |
for (var i = 0; i < recog.emits.length; i++) { |
this.gestures[recog.emits[i]] = recog; |
} |
}, |
+findRecognizerByEvent: function (evName) { |
+for (var i = 0, r; i < this.recognizers.length; i++) { |
+r = this.recognizers[i]; |
+for (var j = 0, n; j < r.emits.length; j++) { |
+n = r.emits[j]; |
+if (n === evName) { |
+return r; |
+} |
+} |
+} |
+return null; |
+}, |
setTouchAction: function (node, value) { |
if (HAS_NATIVE_TA) { |
node.style.touchAction = value; |
@@ -535,12 +635,23 @@ node.style.touchAction = value; |
node[TOUCH_ACTION] = value; |
}, |
fire: function (target, type, detail) { |
-var ev = new CustomEvent(type, { |
-detail: detail, |
+var ev = Polymer.Base.fire(type, detail, { |
+node: target, |
bubbles: true, |
cancelable: true |
}); |
-target.dispatchEvent(ev); |
+if (ev.defaultPrevented) { |
+var se = detail.sourceEvent; |
+if (se && se.preventDefault) { |
+se.preventDefault(); |
+} |
+} |
+}, |
+prevent: function (evName) { |
+var recognizer = this.findRecognizerByEvent(evName); |
+if (recognizer.info) { |
+recognizer.info.prevent = true; |
+} |
} |
}; |
Gestures.register({ |
@@ -555,7 +666,7 @@ emits: [ |
'up' |
], |
mousedown: function (e) { |
-var t = e.currentTarget; |
+var t = Gestures.findOriginalTarget(e); |
var self = this; |
var upfn = function upfn(e) { |
self.fire('up', t, e); |
@@ -565,16 +676,18 @@ document.addEventListener('mouseup', upfn); |
this.fire('down', t, e); |
}, |
touchstart: function (e) { |
-this.fire('down', e.currentTarget, e.changedTouches[0]); |
+this.fire('down', Gestures.findOriginalTarget(e), e.changedTouches[0]); |
}, |
touchend: function (e) { |
-this.fire('up', e.currentTarget, e.changedTouches[0]); |
+this.fire('up', Gestures.findOriginalTarget(e), e.changedTouches[0]); |
}, |
fire: function (type, target, event) { |
+var self = this; |
Gestures.fire(target, type, { |
x: event.clientX, |
y: event.clientY, |
-sourceEvent: event |
+sourceEvent: event, |
+prevent: Gestures.prevent.bind(Gestures) |
}); |
} |
}); |
@@ -599,7 +712,8 @@ if (this.moves.length > TRACK_LENGTH) { |
this.moves.shift(); |
} |
this.moves.push(move); |
-} |
+}, |
+prevent: false |
}, |
clearInfo: function () { |
this.info.state = 'start'; |
@@ -607,8 +721,12 @@ this.info.started = false; |
this.info.moves = []; |
this.info.x = 0; |
this.info.y = 0; |
+this.info.prevent = false; |
}, |
hasMovedEnough: function (x, y) { |
+if (this.info.prevent) { |
+return false; |
+} |
if (this.info.started) { |
return true; |
} |
@@ -617,7 +735,7 @@ var dy = Math.abs(this.info.y - y); |
return dx >= TRACK_DISTANCE || dy >= TRACK_DISTANCE; |
}, |
mousedown: function (e) { |
-var t = e.currentTarget; |
+var t = Gestures.findOriginalTarget(e); |
var self = this; |
var movefn = function movefn(e) { |
var x = e.clientX, y = e.clientY; |
@@ -628,13 +746,12 @@ x: x, |
y: y |
}); |
self.fire(t, e); |
-e.preventDefault(); |
self.info.started = true; |
} |
}; |
var upfn = function upfn(e) { |
if (self.info.started) { |
-POINTERSTATE.tapPrevented = true; |
+Gestures.prevent('tap'); |
movefn(e); |
} |
self.clearInfo(); |
@@ -652,7 +769,7 @@ this.info.x = ct.clientX; |
this.info.y = ct.clientY; |
}, |
touchmove: function (e) { |
-var t = e.currentTarget; |
+var t = Gestures.findOriginalTarget(e); |
var ct = e.changedTouches[0]; |
var x = ct.clientX, y = ct.clientY; |
if (this.hasMovedEnough(x, y)) { |
@@ -666,10 +783,10 @@ this.info.started = true; |
} |
}, |
touchend: function (e) { |
-var t = e.currentTarget; |
+var t = Gestures.findOriginalTarget(e); |
var ct = e.changedTouches[0]; |
if (this.info.started) { |
-POINTERSTATE.tapPrevented = true; |
+Gestures.prevent('tap'); |
this.info.state = 'end'; |
this.info.addMove({ |
x: ct.clientX, |
@@ -713,38 +830,39 @@ deps: [ |
'touchend' |
], |
emits: ['tap'], |
-start: { |
+info: { |
x: NaN, |
-y: NaN |
+y: NaN, |
+prevent: false |
}, |
reset: function () { |
-this.start.x = NaN; |
-this.start.y = NaN; |
+this.info.x = NaN; |
+this.info.y = NaN; |
+this.info.prevent = false; |
}, |
save: function (e) { |
-this.start.x = e.clientX; |
-this.start.y = e.clientY; |
+this.info.x = e.clientX; |
+this.info.y = e.clientY; |
}, |
mousedown: function (e) { |
-POINTERSTATE.tapPrevented = false; |
this.save(e); |
}, |
click: function (e) { |
this.forward(e); |
}, |
touchstart: function (e) { |
-POINTERSTATE.tapPrevented = false; |
this.save(e.changedTouches[0]); |
}, |
touchend: function (e) { |
this.forward(e.changedTouches[0]); |
}, |
forward: function (e) { |
-var dx = Math.abs(e.clientX - this.start.x); |
-var dy = Math.abs(e.clientY - this.start.y); |
+var dx = Math.abs(e.clientX - this.info.x); |
+var dy = Math.abs(e.clientY - this.info.y); |
+var t = Gestures.findOriginalTarget(e); |
if (isNaN(dx) || isNaN(dy) || dx <= TAP_DISTANCE && dy <= TAP_DISTANCE) { |
-if (!POINTERSTATE.tapPrevented) { |
-Gestures.fire(e.target, 'tap', { |
+if (!this.info.prevent) { |
+Gestures.fire(t, 'tap', { |
x: e.clientX, |
y: e.clientY, |
sourceEvent: e |
@@ -768,6 +886,13 @@ Gestures.add(node, eventName, handler); |
node.addEventListener(eventName, handler); |
} |
}, |
+_unlisten: function (node, eventName, handler) { |
+if (Gestures.gestures[eventName]) { |
+Gestures.remove(node, eventName, handler); |
+} else { |
+node.removeEventListener(eventName, handler); |
+} |
+}, |
setScrollDirection: function (direction, node) { |
node = node || this; |
Gestures.setTouchAction(node, DIRECTION_MAP[direction] || 'auto'); |
@@ -775,50 +900,55 @@ Gestures.setTouchAction(node, DIRECTION_MAP[direction] || 'auto'); |
}); |
Polymer.Gestures = Gestures; |
}()); |
-Polymer.Async = function () { |
-var currVal = 0; |
-var lastVal = 0; |
-var callbacks = []; |
-var twiddle = document.createTextNode(''); |
-function runAsync(callback, waitTime) { |
+Polymer.Async = { |
+_currVal: 0, |
+_lastVal: 0, |
+_callbacks: [], |
+_twiddleContent: 0, |
+_twiddle: document.createTextNode(''), |
+run: function (callback, waitTime) { |
if (waitTime > 0) { |
return ~setTimeout(callback, waitTime); |
} else { |
-twiddle.textContent = currVal++; |
-callbacks.push(callback); |
-return currVal - 1; |
-} |
+this._twiddle.textContent = this._twiddleContent++; |
+this._callbacks.push(callback); |
+return this._currVal++; |
} |
-function cancelAsync(handle) { |
+}, |
+cancel: function (handle) { |
if (handle < 0) { |
clearTimeout(~handle); |
} else { |
-var idx = handle - lastVal; |
+var idx = handle - this._lastVal; |
if (idx >= 0) { |
-if (!callbacks[idx]) { |
+if (!this._callbacks[idx]) { |
throw 'invalid async handle: ' + handle; |
} |
-callbacks[idx] = null; |
+this._callbacks[idx] = null; |
} |
} |
-} |
-function atEndOfMicrotask() { |
-var len = callbacks.length; |
+}, |
+_atEndOfMicrotask: function () { |
+var len = this._callbacks.length; |
for (var i = 0; i < len; i++) { |
-var cb = callbacks[i]; |
+var cb = this._callbacks[i]; |
if (cb) { |
+try { |
cb(); |
+} catch (e) { |
+i++; |
+this._callbacks.splice(0, i); |
+this._lastVal += i; |
+this._twiddle.textContent = this._twiddleContent++; |
+throw e; |
} |
} |
-callbacks.splice(0, len); |
-lastVal += len; |
} |
-new (window.MutationObserver || JsMutationObserver)(atEndOfMicrotask).observe(twiddle, { characterData: true }); |
-return { |
-run: runAsync, |
-cancel: cancelAsync |
+this._callbacks.splice(0, len); |
+this._lastVal += len; |
+} |
}; |
-}(); |
+new (window.MutationObserver || JsMutationObserver)(Polymer.Async._atEndOfMicrotask.bind(Polymer.Async)).observe(Polymer.Async._twiddle, { characterData: true }); |
Polymer.Debounce = function () { |
var Async = Polymer.Async; |
var Debouncer = function (context) { |
@@ -901,7 +1031,8 @@ Polymer.dom(toElement).setAttribute(name, ''); |
} |
}, |
getContentChildNodes: function (slctr) { |
-return Polymer.dom(Polymer.dom(this.root).querySelector(slctr || 'content')).getDistributedNodes(); |
+var content = Polymer.dom(this.root).querySelector(slctr || 'content'); |
+return content ? Polymer.dom(content).getDistributedNodes() : []; |
}, |
getContentChildren: function (slctr) { |
return this.getContentChildNodes(slctr).filter(function (n) { |
@@ -913,9 +1044,10 @@ options = options || Polymer.nob; |
var node = options.node || this; |
var detail = detail === null || detail === undefined ? Polymer.nob : detail; |
var bubbles = options.bubbles === undefined ? true : options.bubbles; |
+var cancelable = Boolean(options.cancelable); |
var event = new CustomEvent(type, { |
bubbles: Boolean(bubbles), |
-cancelable: Boolean(options.cancelable), |
+cancelable: cancelable, |
detail: detail |
}); |
node.dispatchEvent(event); |
@@ -972,30 +1104,25 @@ elt[n] = props[n]; |
} |
} |
return elt; |
-}, |
-mixin: function (target, source) { |
-for (var i in source) { |
-target[i] = source[i]; |
-} |
} |
}); |
Polymer.Bind = { |
prepareModel: function (model) { |
model._propertyEffects = {}; |
model._bindListeners = []; |
-var api = this._modelApi; |
-for (var n in api) { |
-model[n] = api[n]; |
-} |
+Polymer.Base.mixin(model, this._modelApi); |
}, |
_modelApi: { |
_notifyChange: function (property) { |
var eventName = Polymer.CaseMap.camelToDashCase(property) + '-changed'; |
-this.fire(eventName, { value: this[property] }, { bubbles: false }); |
+Polymer.Base.fire(eventName, { value: this[property] }, { |
+bubbles: false, |
+node: this |
+}); |
}, |
-_propertySet: function (property, value, effects) { |
+_propertySetter: function (property, value, effects, fromAbove) { |
var old = this.__data__[property]; |
-if (old !== value) { |
+if (old !== value && (old === old || value === value)) { |
this.__data__[property] = value; |
if (typeof value == 'object') { |
this._clearPath(property); |
@@ -1004,16 +1131,25 @@ if (this._propertyChanged) { |
this._propertyChanged(property, value, old); |
} |
if (effects) { |
-this._effectEffects(property, value, effects, old); |
+this._effectEffects(property, value, effects, old, fromAbove); |
} |
} |
return old; |
}, |
-_effectEffects: function (property, value, effects, old) { |
+__setProperty: function (property, value, quiet, node) { |
+node = node || this; |
+var effects = node._propertyEffects && node._propertyEffects[property]; |
+if (effects) { |
+node._propertySetter(property, value, effects, quiet); |
+} else { |
+node[property] = value; |
+} |
+}, |
+_effectEffects: function (property, value, effects, old, fromAbove) { |
effects.forEach(function (fx) { |
var fn = Polymer.Bind['_' + fx.kind + 'Effect']; |
if (fn) { |
-fn.call(this, property, value, fx.effect, old); |
+fn.call(this, property, value, fx.effect, old, fromAbove); |
} |
}, this); |
}, |
@@ -1071,10 +1207,13 @@ return this.__data__[property]; |
} |
}; |
var setter = function (value) { |
-this._propertySet(property, value, effects); |
+this._propertySetter(property, value, effects); |
}; |
-if (model.getPropertyInfo && model.getPropertyInfo(property).readOnly) { |
+var info = model.getPropertyInfo && model.getPropertyInfo(property); |
+if (info && info.readOnly) { |
+if (!info.computed) { |
model['_set' + this.upper(property)] = setter; |
+} |
} else { |
defun.set = setter; |
} |
@@ -1145,11 +1284,13 @@ return this._applyEffectValue(calc, effect); |
_reflectEffect: function (source) { |
this.reflectPropertyToAttribute(source); |
}, |
-_notifyEffect: function (source) { |
+_notifyEffect: function (source, value, effect, old, fromAbove) { |
+if (!fromAbove) { |
this._notifyChange(source); |
+} |
}, |
-_functionEffect: function (source, value, fn, old) { |
-fn.call(this, source, value, old); |
+_functionEffect: function (source, value, fn, old, fromAbove) { |
+fn.call(this, source, value, old, fromAbove); |
}, |
_observerEffect: function (source, value, effect, old) { |
var fn = this[effect.method]; |
@@ -1175,7 +1316,7 @@ var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value); |
if (args) { |
var fn = this[effect.method]; |
if (fn) { |
-this[effect.property] = fn.apply(this, args); |
+this.__setProperty(effect.property, fn.apply(this, args)); |
} else { |
this._warn(this._logf('_computeEffect', 'compute method `' + effect.method + '` not defined')); |
} |
@@ -1248,6 +1389,7 @@ if (prop.observer) { |
this._addObserverEffect(p, prop.observer); |
} |
if (prop.computed) { |
+prop.readOnly = true; |
this._addComputedEffect(p, prop.computed); |
} |
if (prop.notify) { |
@@ -1438,12 +1580,13 @@ this._configure(); |
}, |
_configure: function () { |
this._configureAnnotationReferences(); |
+this._aboveConfig = this.mixin({}, this._config); |
var config = {}; |
this.behaviors.forEach(function (b) { |
this._configureProperties(b.properties, config); |
}, this); |
this._configureProperties(this.properties, config); |
-this._mixinConfigure(config, this._config); |
+this._mixinConfigure(config, this._aboveConfig); |
this._config = config; |
this._distributeConfig(this._config); |
}, |
@@ -1487,18 +1630,13 @@ node._configValue(x.effect.name, value); |
}, |
_afterClientsReady: function () { |
this._executeStaticEffects(); |
-this._applyConfig(this._config); |
+this._applyConfig(this._config, this._aboveConfig); |
this._flushHandlers(); |
}, |
-_applyConfig: function (config) { |
+_applyConfig: function (config, aboveConfig) { |
for (var n in config) { |
if (this[n] === undefined) { |
-var effects = this._propertyEffects[n]; |
-if (effects) { |
-this._propertySet(n, config[n], effects); |
-} else { |
-this[n] = config[n]; |
-} |
+this.__setProperty(n, config[n], n in aboveConfig); |
} |
} |
}, |
@@ -1527,12 +1665,13 @@ h[0].call(this, h[1], h[2]); |
'use strict'; |
Polymer.Base._addFeature({ |
notifyPath: function (path, value, fromAbove) { |
-var old = this._propertySet(path, value); |
-if (old !== value) { |
+var old = this._propertySetter(path, value); |
+if (old !== value && (old === old || value === value)) { |
this._pathEffector(path, value); |
if (!fromAbove) { |
this._notifyPath(path, value); |
} |
+return true; |
} |
}, |
_getPathParts: function (path) { |
@@ -1565,6 +1704,15 @@ return; |
} |
array = Array.isArray(prop) ? prop : null; |
} |
+if (array) { |
+var coll = Polymer.Collection.get(array); |
+var old = prop[last]; |
+var key = coll.getKey(old); |
+if (key) { |
+parts[i] = key; |
+coll.setItem(key, value); |
+} |
+} |
prop[last] = value; |
if (!root) { |
this.notifyPath(parts.join('.'), value); |
@@ -1689,7 +1837,7 @@ object: array, |
type: 'splice' |
}]; |
var change = { |
-keySplices: Polymer.Collection.get(array).applySplices(splices), |
+keySplices: Polymer.Collection.applySplices(array, splices), |
indexSplices: splices |
}; |
this.set(path + '.splices', change); |
@@ -1718,9 +1866,8 @@ return ret; |
splice: function (path, start, deleteCount) { |
var array = this.get(path); |
var args = Array.prototype.slice.call(arguments, 1); |
-var rem = array.slice(start, start + deleteCount); |
var ret = array.splice.apply(array, args); |
-this._notifySplice(array, path, start, args.length - 2, rem); |
+this._notifySplice(array, path, start, args.length - 2, ret); |
return ret; |
}, |
shift: function (path) { |
@@ -1868,10 +2015,10 @@ var AT_START = '@'; |
var rx = { |
comments: /\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim, |
port: /@import[^;]*;/gim, |
-customProp: /(?:^|[\s;])--[^;{]*?:[^{};]*?;/gim, |
-mixinProp: /(?:^|[\s;])--[^;{]*?:[^{;]*?{[^}]*?};?/gim, |
-mixinApply: /@apply[\s]*\([^)]*?\)[\s]*;/gim, |
-varApply: /[^;:]*?:[^;]*var[^;]*;/gim, |
+customProp: /(?:^|[\s;])--[^;{]*?:[^{};]*?(?:[;\n]|$)/gim, |
+mixinProp: /(?:^|[\s;])--[^;{]*?:[^{;]*?{[^}]*?}(?:[;\n]|$)?/gim, |
+mixinApply: /@apply[\s]*\([^)]*?\)[\s]*(?:[;\n]|$)?/gim, |
+varApply: /[^;:]*?:[^;]*var[^;]*(?:[;\n]|$)?/gim, |
keyframesRule: /^@[^\s]*keyframes/ |
}; |
return api; |
@@ -1889,12 +2036,14 @@ this.forEachStyleRule(rules, callback); |
return this.parser.stringify(rules, preserveProperties); |
}, |
forRulesInStyles: function (styles, callback) { |
+if (styles) { |
for (var i = 0, l = styles.length, s; i < l && (s = styles[i]); i++) { |
this.forEachStyleRule(this.rulesForStyle(s), callback); |
} |
+} |
}, |
rulesForStyle: function (style) { |
-if (!style.__cssRules) { |
+if (!style.__cssRules && style.textContent) { |
style.__cssRules = this.parser.parse(style.textContent); |
} |
return style.__cssRules; |
@@ -2047,23 +2196,33 @@ rule.selector = p$.join(COMPLEX_SELECTOR_SEP); |
}, |
_transformComplexSelector: function (selector, scope, hostScope) { |
var stop = false; |
+var hostContext = false; |
var self = this; |
selector = selector.replace(SIMPLE_SELECTOR_SEP, function (m, c, s) { |
if (!stop) { |
-var o = self._transformCompoundSelector(s, c, scope, hostScope); |
-if (o.stop) { |
-stop = true; |
-} |
-c = o.combinator; |
-s = o.value; |
+var info = self._transformCompoundSelector(s, c, scope, hostScope); |
+stop = stop || info.stop; |
+hostContext = hostContext || info.hostContext; |
+c = info.combinator; |
+s = info.value; |
+} else { |
+s = s.replace(SCOPE_JUMP, ' '); |
} |
return c + s; |
}); |
+if (hostContext) { |
+selector = selector.replace(HOST_CONTEXT_PAREN, function (m, pre, paren, post) { |
+return pre + paren + ' ' + hostScope + post + COMPLEX_SELECTOR_SEP + ' ' + pre + hostScope + paren + post; |
+}); |
+} |
return selector; |
}, |
_transformCompoundSelector: function (selector, combinator, scope, hostScope) { |
var jumpIndex = selector.search(SCOPE_JUMP); |
-if (selector.indexOf(HOST) >= 0) { |
+var hostContext = false; |
+if (selector.indexOf(HOST_CONTEXT) >= 0) { |
+hostContext = true; |
+} else if (selector.indexOf(HOST) >= 0) { |
selector = selector.replace(HOST_PAREN, function (m, host, paren) { |
return hostScope + paren; |
}); |
@@ -2082,7 +2241,8 @@ stop = true; |
return { |
value: selector, |
combinator: combinator, |
-stop: stop |
+stop: stop, |
+hostContext: hostContext |
}; |
}, |
_transformSimpleSelector: function (selector, scope) { |
@@ -2090,20 +2250,32 @@ var p$ = selector.split(PSEUDO_PREFIX); |
p$[0] += scope; |
return p$.join(PSEUDO_PREFIX); |
}, |
-rootRule: function (rule) { |
-this._transformRule(rule, this._transformRootSelector); |
+documentRule: function (rule) { |
+rule.selector = rule.parsedSelector; |
+this.normalizeRootSelector(rule); |
+if (!nativeShadow) { |
+this._transformRule(rule, this._transformDocumentSelector); |
+} |
+}, |
+normalizeRootSelector: function (rule) { |
+if (rule.selector === ROOT) { |
+rule.selector = 'body'; |
+} |
}, |
-_transformRootSelector: function (selector) { |
-return selector.match(SCOPE_JUMP) ? this._transformComplexSelector(selector) : selector.trim() + SCOPE_ROOT_SELECTOR; |
+_transformDocumentSelector: function (selector) { |
+return selector.match(SCOPE_JUMP) ? this._transformComplexSelector(selector, SCOPE_DOC_SELECTOR) : this._transformSimpleSelector(selector.trim(), SCOPE_DOC_SELECTOR); |
}, |
SCOPE_NAME: 'style-scope' |
}; |
var SCOPE_NAME = api.SCOPE_NAME; |
-var SCOPE_ROOT_SELECTOR = ':not([' + SCOPE_NAME + '])' + ':not(.' + SCOPE_NAME + ')'; |
+var SCOPE_DOC_SELECTOR = ':not([' + SCOPE_NAME + '])' + ':not(.' + SCOPE_NAME + ')'; |
var COMPLEX_SELECTOR_SEP = ','; |
var SIMPLE_SELECTOR_SEP = /(^|[\s>+~]+)([^\s>+~]+)/g; |
var HOST = ':host'; |
+var ROOT = ':root'; |
var HOST_PAREN = /(\:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g; |
+var HOST_CONTEXT = ':host-context'; |
+var HOST_CONTEXT_PAREN = /(.*)(?:\:host-context)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))(.*)/; |
var CONTENT = '::content'; |
var SCOPE_JUMP = /\:\:content|\:\:shadow|\/deep\//; |
var CSS_CLASS_PREFIX = '.'; |
@@ -2278,6 +2450,7 @@ return mo; |
}); |
}()); |
Polymer.StyleProperties = function () { |
+'use strict'; |
var nativeShadow = Polymer.Settings.useNativeShadow; |
var matchesSelector = Polymer.DomApi.matchesSelector; |
var styleUtil = Polymer.StyleUtil; |
@@ -2344,6 +2517,10 @@ collectPropertiesInCssText: function (cssText, props) { |
var m; |
while (m = this.rx.VAR_CAPTURE.exec(cssText)) { |
props[m[1]] = true; |
+var def = m[2]; |
+if (def && def.match(this.rx.IS_VAR)) { |
+props[def] = true; |
+} |
} |
}, |
reify: function (props) { |
@@ -2443,27 +2620,29 @@ return props; |
}, |
transformStyles: function (element, properties, scopeSelector) { |
var self = this; |
-var hostRx = new RegExp(this.rx.HOST_PREFIX + element.is + this.rx.HOST_SUFFIX); |
+var hostSelector = styleTransformer._calcHostScope(element.is, element.extends); |
+var rxHostSelector = element.extends ? '\\' + hostSelector.slice(0, -1) + '\\]' : hostSelector; |
+var hostRx = new RegExp(this.rx.HOST_PREFIX + rxHostSelector + this.rx.HOST_SUFFIX); |
return styleTransformer.elementStyles(element, function (rule) { |
self.applyProperties(rule, properties); |
if (rule.cssText && !nativeShadow) { |
-self._scopeSelector(rule, hostRx, element.is, element._scopeCssViaAttr, scopeSelector); |
+self._scopeSelector(rule, hostRx, hostSelector, element._scopeCssViaAttr, scopeSelector); |
} |
}); |
}, |
-_scopeSelector: function (rule, hostRx, is, viaAttr, scopeId) { |
+_scopeSelector: function (rule, hostRx, hostSelector, viaAttr, scopeId) { |
rule.transformedSelector = rule.transformedSelector || rule.selector; |
var selector = rule.transformedSelector; |
var scope = viaAttr ? '[' + styleTransformer.SCOPE_NAME + '~=' + scopeId + ']' : '.' + scopeId; |
var parts = selector.split(','); |
for (var i = 0, l = parts.length, p; i < l && (p = parts[i]); i++) { |
-parts[i] = p.match(hostRx) ? p.replace(is, is + scope) : scope + ' ' + p; |
+parts[i] = p.match(hostRx) ? p.replace(hostSelector, hostSelector + scope) : scope + ' ' + p; |
} |
rule.selector = parts.join(','); |
}, |
applyElementScopeSelector: function (element, selector, old, viaAttr) { |
var c = viaAttr ? element.getAttribute(styleTransformer.SCOPE_NAME) : element.className; |
-v = old ? c.replace(old, selector) : (c ? c + ' ' : '') + this.XSCOPE_NAME + ' ' + selector; |
+var v = old ? c.replace(old, selector) : (c ? c + ' ' : '') + this.XSCOPE_NAME + ' ' + selector; |
if (c !== v) { |
if (viaAttr) { |
element.setAttribute(styleTransformer.SCOPE_NAME, v); |
@@ -2477,7 +2656,7 @@ var cssText = style ? style.textContent || '' : this.transformStyles(element, pr |
var s = element._customStyle; |
if (s && !nativeShadow && s !== style) { |
s._useCount--; |
-if (s._useCount <= 0) { |
+if (s._useCount <= 0 && s.parentNode) { |
s.parentNode.removeChild(s); |
} |
} |
@@ -2498,13 +2677,23 @@ element._customStyle = style; |
} |
return style; |
}, |
+mixinCustomStyle: function (props, customStyle) { |
+var v; |
+for (var i in customStyle) { |
+v = customStyle[i]; |
+if (v || v === 0) { |
+props[i] = v; |
+} |
+} |
+}, |
rx: { |
-VAR_ASSIGN: /(?:^|;\s*)(--[^\:;]*?):\s*?(?:([^;{]*?)|{([^}]*)})(?=;)/gim, |
-MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(([^)]*)\);?/im, |
-VAR_MATCH: /(^|\W+)var\([\s]*([^,)]*)[\s]*,?[\s]*((?:[^,)]*)|(?:[^;]*\([^;)]*\)))[\s]*?\)/gim, |
-VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(--[^,\s)]*))?(?:\)|,)/gim, |
+VAR_ASSIGN: /(?:^|[;\n]\s*)(--[\w-]*?):\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\n])|$)/gi, |
+MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(([^)]*)\)/i, |
+VAR_MATCH: /(^|\W+)var\([\s]*([^,)]*)[\s]*,?[\s]*((?:[^,)]*)|(?:[^;]*\([^;)]*\)))[\s]*?\)/gi, |
+VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(--[^,\s)]*))?(?:\)|,)/gi, |
+IS_VAR: /^--/, |
BRACKETED: /\{[^}]*\}/g, |
-HOST_PREFIX: '(?:^|[^.])', |
+HOST_PREFIX: '(?:^|[^.#[:])', |
HOST_SUFFIX: '($|[.:[\\s>+~])' |
}, |
HOST_SELECTORS: [':host'], |
@@ -2517,35 +2706,6 @@ var v = 1 << n % 32; |
bits[o] = (bits[o] || 0) | v; |
} |
}(); |
-Polymer.StyleDefaults = function () { |
-var styleProperties = Polymer.StyleProperties; |
-var styleUtil = Polymer.StyleUtil; |
-var style = document.createElement('style'); |
-var api = { |
-style: style, |
-_styles: [style], |
-_properties: null, |
-applyCss: function (cssText) { |
-this.style.textContent += cssText; |
-styleUtil.clearStyleRules(this.style); |
-this._properties = null; |
-}, |
-get _styleProperties() { |
-if (!this._properties) { |
-styleProperties.decorateStyles(this._styles); |
-this._styles._scopeStyleProperties = null; |
-this._properties = styleProperties.scopePropertiesFromStyles(this._styles); |
-} |
-return this._properties; |
-}, |
-_needsStyleProperties: function () { |
-}, |
-_computeStyleProperties: function () { |
-return this._styleProperties; |
-} |
-}; |
-return api; |
-}(); |
(function () { |
Polymer.StyleCache = function () { |
this.cache = {}; |
@@ -2576,8 +2736,10 @@ clear: function () { |
this.cache = {}; |
}, |
_objectsEqual: function (target, source) { |
+var t, s; |
for (var i in target) { |
-if (target[i] !== source[i]) { |
+t = target[i], s = source[i]; |
+if (!(typeof t === 'object' && t ? this._objectsStrictlyEqual(t, s) : t === s)) { |
return false; |
} |
} |
@@ -2585,10 +2747,57 @@ if (Array.isArray(target)) { |
return target.length === source.length; |
} |
return true; |
+}, |
+_objectsStrictlyEqual: function (target, source) { |
+return this._objectsEqual(target, source) && this._objectsEqual(source, target); |
} |
}; |
}()); |
+Polymer.StyleDefaults = function () { |
+var styleProperties = Polymer.StyleProperties; |
+var styleUtil = Polymer.StyleUtil; |
+var StyleCache = Polymer.StyleCache; |
+var api = { |
+_styles: [], |
+_properties: null, |
+customStyle: {}, |
+_styleCache: new StyleCache(), |
+addStyle: function (style) { |
+this._styles.push(style); |
+this._properties = null; |
+}, |
+get _styleProperties() { |
+if (!this._properties) { |
+styleProperties.decorateStyles(this._styles); |
+this._styles._scopeStyleProperties = null; |
+this._properties = styleProperties.scopePropertiesFromStyles(this._styles); |
+styleProperties.mixinCustomStyle(this._properties, this.customStyle); |
+styleProperties.reify(this._properties); |
+} |
+return this._properties; |
+}, |
+_needsStyleProperties: function () { |
+}, |
+_computeStyleProperties: function () { |
+return this._styleProperties; |
+}, |
+updateStyles: function (properties) { |
+this._properties = null; |
+if (properties) { |
+Polymer.Base.mixin(this.customStyle, properties); |
+} |
+this._styleCache.clear(); |
+for (var i = 0, s; i < this._styles.length; i++) { |
+s = this._styles[i]; |
+s = s.__importElement || s; |
+s._apply(); |
+} |
+} |
+}; |
+return api; |
+}(); |
(function () { |
+'use strict'; |
var serializeValueToAttribute = Polymer.Base.serializeValueToAttribute; |
var propertyUtils = Polymer.StyleProperties; |
var styleTransformer = Polymer.StyleTransformer; |
@@ -2610,12 +2819,23 @@ if (!this._scopeSelector && this._needsStyleProperties()) { |
this._updateStyleProperties(); |
} |
}, |
+_findStyleHost: function () { |
+var e = this, root; |
+while (root = Polymer.dom(e).getOwnerRoot()) { |
+if (Polymer.isInstance(root.host)) { |
+return root.host; |
+} |
+e = root.host; |
+} |
+return styleDefaults; |
+}, |
_updateStyleProperties: function () { |
-var info, scope = this.domHost || styleDefaults; |
+var info, scope = this._findStyleHost(); |
if (!scope._styleCache) { |
scope._styleCache = new Polymer.StyleCache(); |
} |
var scopeData = propertyUtils.propertyDataFromStyles(scope._styles, this); |
+scopeData.key.customStyle = this.customStyle; |
info = scope._styleCache.retrieve(this.is, scopeData.key, this._styles); |
var scopeCached = Boolean(info); |
if (scopeCached) { |
@@ -2628,17 +2848,16 @@ if (!scopeCached) { |
info = styleCache.retrieve(this.is, this._ownStyleProperties, this._styles); |
} |
var globalCached = Boolean(info) && !scopeCached; |
-style = this._applyStyleProperties(info); |
+var style = this._applyStyleProperties(info); |
if (!scopeCached) { |
-var cacheableStyle = style; |
-if (nativeShadow) { |
-cacheableStyle = style.cloneNode ? style.cloneNode(true) : Object.create(style || null); |
-} |
+style = style && nativeShadow ? style.cloneNode(true) : style; |
info = { |
-style: cacheableStyle, |
+style: style, |
_scopeSelector: this._scopeSelector, |
_styleProperties: this._styleProperties |
}; |
+scopeData.key.customStyle = {}; |
+this.mixin(scopeData.key.customStyle, this.customStyle); |
scope._styleCache.store(this.is, info, scopeData.key, this._styles); |
if (!globalCached) { |
styleCache.store(this.is, Object.create(info), this._ownStyleProperties, this._styles); |
@@ -2646,7 +2865,7 @@ styleCache.store(this.is, Object.create(info), this._ownStyleProperties, this._s |
} |
}, |
_computeStyleProperties: function (scopeProps) { |
-var scope = this.domHost || styleDefaults; |
+var scope = this._findStyleHost(); |
if (!scope._styleProperties) { |
scope._computeStyleProperties(); |
} |
@@ -2655,7 +2874,7 @@ this.mixin(props, propertyUtils.hostPropertiesFromStyles(this._styles)); |
scopeProps = scopeProps || propertyUtils.propertyDataFromStyles(scope._styles, this).properties; |
this.mixin(props, scopeProps); |
this.mixin(props, propertyUtils.scopePropertiesFromStyles(this._styles)); |
-this.mixin(props, this.customStyle); |
+propertyUtils.mixinCustomStyle(props, this.customStyle); |
propertyUtils.reify(props); |
this._styleProperties = props; |
}, |
@@ -2671,15 +2890,15 @@ _scopeCount: 0, |
_applyStyleProperties: function (info) { |
var oldScopeSelector = this._scopeSelector; |
this._scopeSelector = info ? info._scopeSelector : this.is + '-' + this.__proto__._scopeCount++; |
-style = propertyUtils.applyElementStyle(this, this._styleProperties, this._scopeSelector, info && info.style); |
-if ((style || oldScopeSelector) && !nativeShadow) { |
+var style = propertyUtils.applyElementStyle(this, this._styleProperties, this._scopeSelector, info && info.style); |
+if (!nativeShadow) { |
propertyUtils.applyElementScopeSelector(this, this._scopeSelector, oldScopeSelector, this._scopeCssViaAttr); |
} |
-return style || {}; |
+return style; |
}, |
serializeValueToAttribute: function (value, attribute, node) { |
node = node || this; |
-if (attribute === 'class') { |
+if (attribute === 'class' && !nativeShadow) { |
var host = node === this ? this.domHost || this.dataHost : this; |
if (host) { |
value = host._scopeElementClass(node, value); |
@@ -2694,8 +2913,11 @@ selector += (selector ? ' ' : '') + SCOPE_NAME + ' ' + this.is + (element._scope |
} |
return selector; |
}, |
-updateStyles: function () { |
+updateStyles: function (properties) { |
if (this.isAttached) { |
+if (properties) { |
+this.mixin(this.customStyle, properties); |
+} |
if (this._needsStyleProperties()) { |
this._updateStyleProperties(); |
} else { |
@@ -2719,8 +2941,8 @@ c.updateStyles(); |
} |
} |
}); |
-Polymer.updateStyles = function () { |
-styleDefaults._styleCache.clear(); |
+Polymer.updateStyles = function (properties) { |
+styleDefaults.updateStyles(properties); |
Polymer.Base._updateRootStyles(document); |
}; |
var styleCache = new Polymer.StyleCache(); |
@@ -2732,7 +2954,6 @@ Polymer.Base._addFeature({ |
_registerFeatures: function () { |
this._prepIs(); |
this._prepAttributes(); |
-this._prepExtends(); |
this._prepConstructor(); |
this._prepTemplate(); |
this._prepStyles(); |
@@ -2772,53 +2993,52 @@ var nativeShadow = Polymer.Settings.useNativeShadow; |
var propertyUtils = Polymer.StyleProperties; |
var styleUtil = Polymer.StyleUtil; |
var styleDefaults = Polymer.StyleDefaults; |
+var styleTransformer = Polymer.StyleTransformer; |
Polymer({ |
is: 'custom-style', |
extends: 'style', |
created: function () { |
-this._appliesToDocument = this.parentNode.localName !== 'dom-module'; |
-if (this._appliesToDocument) { |
+this._tryApply(); |
+}, |
+attached: function () { |
+this._tryApply(); |
+}, |
+_tryApply: function () { |
+if (!this._appliesToDocument) { |
+if (this.parentNode && this.parentNode.localName !== 'dom-module') { |
+this._appliesToDocument = true; |
var e = this.__appliedElement || this; |
-var rules = styleUtil.rulesForStyle(e); |
-propertyUtils.decorateStyles([e]); |
-this._rulesToDefaultProperties(rules); |
-this.async(this._applyStyle); |
+styleDefaults.addStyle(e); |
+if (e.textContent) { |
+this._apply(); |
+} else { |
+var observer = new MutationObserver(function () { |
+observer.disconnect(); |
+this._apply(); |
+}.bind(this)); |
+observer.observe(e, { childList: true }); |
+} |
+} |
} |
}, |
-_applyStyle: function () { |
+_apply: function () { |
var e = this.__appliedElement || this; |
this._computeStyleProperties(); |
var props = this._styleProperties; |
var self = this; |
e.textContent = styleUtil.toCssText(styleUtil.rulesForStyle(e), function (rule) { |
-if (rule.selector === ':root') { |
-rule.selector = 'body'; |
-} |
var css = rule.cssText = rule.parsedCssText; |
if (rule.propertyInfo && rule.propertyInfo.cssText) { |
css = css.replace(propertyUtils.rx.VAR_ASSIGN, ''); |
rule.cssText = propertyUtils.valueForProperties(css, props); |
} |
-if (!nativeShadow) { |
-Polymer.StyleTransformer.rootRule(rule); |
-} |
+styleTransformer.documentRule(rule); |
}); |
-}, |
-_rulesToDefaultProperties: function (rules) { |
-styleUtil.forEachStyleRule(rules, function (rule) { |
-if (!rule.propertyInfo.properties) { |
-rule.cssText = ''; |
-} |
-}); |
-var cssText = styleUtil.parser.stringify(rules, true); |
-if (cssText) { |
-styleDefaults.applyCss(cssText); |
-} |
} |
}); |
}()); |
Polymer.Templatizer = { |
-properties: { _hideTemplateChildren: { observer: '_showHideChildren' } }, |
+properties: { __hideTemplateChildren__: { observer: '_showHideChildren' } }, |
_templatizerStatic: { |
count: 0, |
callbacks: {}, |
@@ -2847,6 +3067,7 @@ this._prepParentProperties(archetype, template); |
archetype._notifyPath = this._notifyPathImpl; |
archetype._scopeElementClass = this._scopeElementClassImpl; |
archetype.listen = this._listenImpl; |
+archetype._showHideChildren = this._showHideChildrenImpl; |
var _constructor = this._constructorImpl; |
var ctor = function TemplateInstance(model, host) { |
_constructor.call(this, model, host); |
@@ -2859,7 +3080,15 @@ this.ctor = ctor; |
_getRootDataHost: function () { |
return this.dataHost && this.dataHost._rootDataHost || this.dataHost; |
}, |
-_showHideChildren: function (hidden) { |
+_showHideChildrenImpl: function (hide) { |
+var c = this._children; |
+for (var i = 0; i < c.length; i++) { |
+var n = c[i]; |
+if (n.style) { |
+n.style.display = hide ? 'none' : ''; |
+n.__hideTemplateChildren__ = hide; |
+} |
+} |
}, |
_debounceTemplate: function (fn) { |
this._templatizerStatic.callbacks[this._templatizerId] = fn.bind(this); |
@@ -2882,6 +3111,9 @@ var parentProps = archetype._parentProps; |
for (var prop in parentProps) { |
archetype._addPropertyEffect(prop, 'function', this._createHostPropEffector(prop)); |
} |
+for (var prop in this._instanceProps) { |
+archetype._addPropertyEffect(prop, 'function', this._createInstancePropEffector(prop)); |
+} |
}, |
_customPrepAnnotations: function (archetype, template) { |
archetype._template = template; |
@@ -2940,18 +3172,29 @@ return function (source, value) { |
this.dataHost['_parent_' + prop] = value; |
}; |
}, |
+_createInstancePropEffector: function (prop) { |
+return function (source, value, old, fromAbove) { |
+if (!fromAbove) { |
+this.dataHost._forwardInstanceProp(this, prop, value); |
+} |
+}; |
+}, |
_extendTemplate: function (template, proto) { |
Object.getOwnPropertyNames(proto).forEach(function (n) { |
var val = template[n]; |
var pd = Object.getOwnPropertyDescriptor(proto, n); |
Object.defineProperty(template, n, pd); |
if (val !== undefined) { |
-template._propertySet(n, val); |
+template._propertySetter(n, val); |
} |
}); |
}, |
+_showHideChildren: function (hidden) { |
+}, |
_forwardInstancePath: function (inst, path, value) { |
}, |
+_forwardInstanceProp: function (inst, prop, value) { |
+}, |
_notifyPathImpl: function (path, value) { |
var dataHost = this.dataHost; |
var dot = path.indexOf('.'); |
@@ -2974,6 +3217,7 @@ this._rootDataHost = host._getRootDataHost(); |
this._setupConfigure(model); |
this._pushHost(host); |
this.root = this.instanceTemplate(this._template); |
+this.root.__noContent = !this._notes._hasContent; |
this.root.__styleScoped = true; |
this._popHost(); |
this._marshalAnnotatedNodes(); |
@@ -2985,6 +3229,9 @@ children.push(n); |
n._templateInstance = this; |
} |
this._children = children; |
+if (host.__hideTemplateChildren__) { |
+this._showHideChildren(true); |
+} |
this._tryReady(); |
}, |
_listenImpl: function (node, eventName, methodName) { |
@@ -3011,6 +3258,20 @@ model[prop] = this['_parent_' + prop]; |
} |
} |
return new this.ctor(model, this); |
+}, |
+modelForElement: function (el) { |
+var model; |
+while (el) { |
+if (model = el._templateInstance) { |
+if (model.dataHost != this) { |
+el = model.dataHost; |
+} else { |
+return model; |
+} |
+} else { |
+el = el.parentNode; |
+} |
+} |
} |
}; |
Polymer({ |
@@ -3057,7 +3318,7 @@ this._removeFromMap(this.store[key]); |
delete this.store[key]; |
}, |
_removeFromMap: function (item) { |
-if (typeof item == 'object') { |
+if (item && typeof item == 'object') { |
this.omap.delete(item); |
} else { |
delete this.pmap[item]; |
@@ -3069,7 +3330,7 @@ this.removeKey(key); |
return key; |
}, |
getKey: function (item) { |
-if (typeof item == 'object') { |
+if (item && typeof item == 'object') { |
return this.omap.get(item); |
} else { |
return this.pmap[item]; |
@@ -3078,8 +3339,17 @@ return this.pmap[item]; |
getKeys: function () { |
return Object.keys(this.store); |
}, |
-setItem: function (key, value) { |
-this.store[key] = value; |
+setItem: function (key, item) { |
+var old = this.store[key]; |
+if (old) { |
+this._removeFromMap(old); |
+} |
+if (item && typeof item == 'object') { |
+this.omap.set(item, key); |
+} else { |
+this.pmap[item] = key; |
+} |
+this.store[key] = item; |
}, |
getItem: function (key) { |
return this.store[key]; |
@@ -3091,7 +3361,7 @@ items.push(store[key]); |
} |
return items; |
}, |
-applySplices: function (splices) { |
+_applySplices: function (splices) { |
var keySplices = []; |
for (var i = 0; i < splices.length; i++) { |
var j, o, key, s = splices[i]; |
@@ -3120,6 +3390,10 @@ return keySplices; |
Polymer.Collection.get = function (userArray) { |
return Polymer._collections.get(userArray) || new Polymer.Collection(userArray); |
}; |
+Polymer.Collection.applySplices = function (userArray, splices) { |
+var coll = Polymer._collections.get(userArray); |
+return coll ? coll._applySplices(splices) : null; |
+}; |
Polymer({ |
is: 'dom-repeat', |
extends: 'template', |
@@ -3149,19 +3423,18 @@ delay: Number |
}, |
behaviors: [Polymer.Templatizer], |
observers: ['_itemsChanged(items.*)'], |
+created: function () { |
+this._instances = []; |
+}, |
detached: function () { |
-if (this.rows) { |
-for (var i = 0; i < this.rows.length; i++) { |
+for (var i = 0; i < this._instances.length; i++) { |
this._detachRow(i); |
} |
-} |
}, |
attached: function () { |
-if (this.rows) { |
var parentNode = Polymer.dom(this).parentNode; |
-for (var i = 0; i < this.rows.length; i++) { |
-Polymer.dom(parentNode).insertBefore(this.rows[i].root, this); |
-} |
+for (var i = 0; i < this._instances.length; i++) { |
+Polymer.dom(parentNode).insertBefore(this._instances[i].root, this); |
} |
}, |
ready: function () { |
@@ -3178,7 +3451,7 @@ var sort = this.sort; |
this._sortFn = sort && (typeof sort == 'function' ? sort : function () { |
return dataHost[sort].apply(dataHost, arguments); |
}); |
-this._fullRefresh = true; |
+this._needFullRefresh = true; |
if (this.items) { |
this._debounceTemplate(this._render); |
} |
@@ -3189,7 +3462,7 @@ var filter = this.filter; |
this._filterFn = filter && (typeof filter == 'function' ? filter : function () { |
return dataHost[filter].apply(dataHost, arguments); |
}); |
-this._fullRefresh = true; |
+this._needFullRefresh = true; |
if (this.items) { |
this._debounceTemplate(this._render); |
} |
@@ -3207,7 +3480,7 @@ this.collection = null; |
this._error(this._logf('dom-repeat', 'expected array for `items`,' + ' found', this.items)); |
} |
this._splices = []; |
-this._fullRefresh = true; |
+this._needFullRefresh = true; |
this._debounceTemplate(this._render); |
} else if (change.path == 'items.splices') { |
this._splices = this._splices.concat(change.value.keySplices); |
@@ -3224,7 +3497,7 @@ path = path.substring(path.indexOf('.') + 1); |
var paths = this._observePaths; |
for (var i = 0; i < paths.length; i++) { |
if (path.indexOf(paths[i]) === 0) { |
-this._fullRefresh = true; |
+this._needFullRefresh = true; |
if (this.delay) { |
this.debounce('render', this._render, this.delay); |
} else { |
@@ -3236,102 +3509,111 @@ return; |
} |
}, |
render: function () { |
-this._fullRefresh = true; |
-this.debounce('render', this._render); |
+this._needFullRefresh = true; |
+this._debounceTemplate(this._render); |
this._flushTemplates(); |
}, |
_render: function () { |
var c = this.collection; |
-if (!this._fullRefresh) { |
+if (this._needFullRefresh) { |
+this._applyFullRefresh(); |
+this._needFullRefresh = false; |
+} else { |
if (this._sortFn) { |
-this._applySplicesViewSort(this._splices); |
+this._applySplicesUserSort(this._splices); |
} else { |
if (this._filterFn) { |
-this._fullRefresh = true; |
+this._applyFullRefresh(); |
} else { |
-this._applySplicesArraySort(this._splices); |
-} |
+this._applySplicesArrayOrder(this._splices); |
} |
} |
-if (this._fullRefresh) { |
-this._sortAndFilter(); |
-this._fullRefresh = false; |
} |
this._splices = []; |
-var rowForKey = this._rowForKey = {}; |
-var keys = this._orderedKeys; |
-this.rows = this.rows || []; |
-for (var i = 0; i < keys.length; i++) { |
-var key = keys[i]; |
-var item = c.getItem(key); |
-var row = this.rows[i]; |
-rowForKey[key] = i; |
-if (!row) { |
-this.rows.push(row = this._insertRow(i, null, item)); |
-} |
-row[this.as] = item; |
-row.__key__ = key; |
-row[this.indexAs] = i; |
-} |
-for (; i < this.rows.length; i++) { |
-this._detachRow(i); |
+var keyToIdx = this._keyToInstIdx = {}; |
+for (var i = 0; i < this._instances.length; i++) { |
+var inst = this._instances[i]; |
+keyToIdx[inst.__key__] = i; |
+inst.__setProperty(this.indexAs, i, true); |
} |
-this.rows.splice(keys.length, this.rows.length - keys.length); |
this.fire('dom-change'); |
}, |
-_sortAndFilter: function () { |
+_applyFullRefresh: function () { |
var c = this.collection; |
-if (!this._sortFn) { |
-this._orderedKeys = []; |
+var keys; |
+if (this._sortFn) { |
+keys = c ? c.getKeys() : []; |
+} else { |
+keys = []; |
var items = this.items; |
if (items) { |
for (var i = 0; i < items.length; i++) { |
-this._orderedKeys.push(c.getKey(items[i])); |
+keys.push(c.getKey(items[i])); |
} |
} |
-} else { |
-this._orderedKeys = c ? c.getKeys() : []; |
} |
if (this._filterFn) { |
-this._orderedKeys = this._orderedKeys.filter(function (a) { |
+keys = keys.filter(function (a) { |
return this._filterFn(c.getItem(a)); |
}, this); |
} |
if (this._sortFn) { |
-this._orderedKeys.sort(function (a, b) { |
+keys.sort(function (a, b) { |
return this._sortFn(c.getItem(a), c.getItem(b)); |
}.bind(this)); |
} |
+for (var i = 0; i < keys.length; i++) { |
+var key = keys[i]; |
+var inst = this._instances[i]; |
+if (inst) { |
+inst.__setProperty('__key__', key, true); |
+inst.__setProperty(this.as, c.getItem(key), true); |
+} else { |
+this._instances.push(this._insertRow(i, key)); |
+} |
+} |
+for (; i < this._instances.length; i++) { |
+this._detachRow(i); |
+} |
+this._instances.splice(keys.length, this._instances.length - keys.length); |
}, |
_keySort: function (a, b) { |
return this.collection.getKey(a) - this.collection.getKey(b); |
}, |
-_applySplicesViewSort: function (splices) { |
+_applySplicesUserSort: function (splices) { |
var c = this.collection; |
-var keys = this._orderedKeys; |
-var rows = this.rows; |
-var removedRows = []; |
-var addedKeys = []; |
+var instances = this._instances; |
+var keyMap = {}; |
var pool = []; |
var sortFn = this._sortFn || this._keySort.bind(this); |
splices.forEach(function (s) { |
for (var i = 0; i < s.removed.length; i++) { |
-var idx = this._rowForKey[s.removed[i]]; |
-if (idx != null) { |
-removedRows.push(idx); |
-} |
+var key = s.removed[i]; |
+keyMap[key] = keyMap[key] ? null : -1; |
} |
for (var i = 0; i < s.added.length; i++) { |
-addedKeys.push(s.added[i]); |
+var key = s.added[i]; |
+keyMap[key] = keyMap[key] ? null : 1; |
} |
}, this); |
-if (removedRows.length) { |
-removedRows.sort(); |
-for (var i = removedRows.length - 1; i >= 0; i--) { |
-var idx = removedRows[i]; |
+var removedIdxs = []; |
+var addedKeys = []; |
+for (var key in keyMap) { |
+if (keyMap[key] === -1) { |
+removedIdxs.push(this._keyToInstIdx[key]); |
+} |
+if (keyMap[key] === 1) { |
+addedKeys.push(key); |
+} |
+} |
+if (removedIdxs.length) { |
+removedIdxs.sort(); |
+for (var i = removedIdxs.length - 1; i >= 0; i--) { |
+var idx = removedIdxs[i]; |
+if (idx !== undefined) { |
pool.push(this._detachRow(idx)); |
-rows.splice(idx, 1); |
-keys.splice(idx, 1); |
+instances.splice(idx, 1); |
+} |
} |
} |
if (addedKeys.length) { |
@@ -3345,19 +3627,19 @@ return this._sortFn(c.getItem(a), c.getItem(b)); |
}.bind(this)); |
var start = 0; |
for (var i = 0; i < addedKeys.length; i++) { |
-start = this._insertRowIntoViewSort(start, addedKeys[i], pool); |
+start = this._insertRowUserSort(start, addedKeys[i], pool); |
} |
} |
}, |
-_insertRowIntoViewSort: function (start, key, pool) { |
+_insertRowUserSort: function (start, key, pool) { |
var c = this.collection; |
var item = c.getItem(key); |
-var end = this.rows.length - 1; |
+var end = this._instances.length - 1; |
var idx = -1; |
var sortFn = this._sortFn || this._keySort.bind(this); |
while (start <= end) { |
var mid = start + end >> 1; |
-var midKey = this._orderedKeys[mid]; |
+var midKey = this._instances[mid].__key__; |
var cmp = sortFn(c.getItem(midKey), item); |
if (cmp < 0) { |
start = mid + 1; |
@@ -3371,121 +3653,114 @@ break; |
if (idx < 0) { |
idx = end + 1; |
} |
-this._orderedKeys.splice(idx, 0, key); |
-this.rows.splice(idx, 0, this._insertRow(idx, pool, c.getItem(key))); |
+this._instances.splice(idx, 0, this._insertRow(idx, key, pool)); |
return idx; |
}, |
-_applySplicesArraySort: function (splices) { |
-var keys = this._orderedKeys; |
+_applySplicesArrayOrder: function (splices) { |
var pool = []; |
+var c = this.collection; |
splices.forEach(function (s) { |
for (var i = 0; i < s.removed.length; i++) { |
-pool.push(this._detachRow(s.index + i)); |
+var inst = this._detachRow(s.index + i); |
+if (!inst.isPlaceholder) { |
+pool.push(inst); |
} |
-this.rows.splice(s.index, s.removed.length); |
-}, this); |
-var c = this.collection; |
-splices.forEach(function (s) { |
-var args = [ |
-s.index, |
-s.removed.length |
-].concat(s.added); |
-keys.splice.apply(keys, args); |
+} |
+this._instances.splice(s.index, s.removed.length); |
for (var i = 0; i < s.added.length; i++) { |
-var item = c.getItem(s.added[i]); |
-var row = this._insertRow(s.index + i, pool, item); |
-this.rows.splice(s.index + i, 0, row); |
+var inst = { |
+isPlaceholder: true, |
+key: s.added[i] |
+}; |
+this._instances.splice(s.index + i, 0, inst); |
} |
}, this); |
+for (var i = this._instances.length - 1; i >= 0; i--) { |
+var inst = this._instances[i]; |
+if (inst.isPlaceholder) { |
+this._instances[i] = this._insertRow(i, inst.key, pool, true); |
+} |
+} |
}, |
_detachRow: function (idx) { |
-var row = this.rows[idx]; |
+var inst = this._instances[idx]; |
+if (!inst.isPlaceholder) { |
var parentNode = Polymer.dom(this).parentNode; |
-for (var i = 0; i < row._children.length; i++) { |
-var el = row._children[i]; |
-Polymer.dom(row.root).appendChild(el); |
+for (var i = 0; i < inst._children.length; i++) { |
+var el = inst._children[i]; |
+Polymer.dom(inst.root).appendChild(el); |
} |
-return row; |
+} |
+return inst; |
}, |
-_insertRow: function (idx, pool, item) { |
-var row = pool && pool.pop() || this._generateRow(idx, item); |
-var beforeRow = this.rows[idx]; |
+_insertRow: function (idx, key, pool, replace) { |
+var inst; |
+if (inst = pool && pool.pop()) { |
+inst.__setProperty(this.as, this.collection.getItem(key), true); |
+inst.__setProperty('__key__', key, true); |
+} else { |
+inst = this._generateRow(idx, key); |
+} |
+var beforeRow = this._instances[replace ? idx + 1 : idx]; |
var beforeNode = beforeRow ? beforeRow._children[0] : this; |
var parentNode = Polymer.dom(this).parentNode; |
-Polymer.dom(parentNode).insertBefore(row.root, beforeNode); |
-return row; |
+Polymer.dom(parentNode).insertBefore(inst.root, beforeNode); |
+return inst; |
}, |
-_generateRow: function (idx, item) { |
-var model = { __key__: this.collection.getKey(item) }; |
-model[this.as] = item; |
+_generateRow: function (idx, key) { |
+var model = { __key__: key }; |
+model[this.as] = this.collection.getItem(key); |
model[this.indexAs] = idx; |
-var row = this.stamp(model); |
-return row; |
+var inst = this.stamp(model); |
+return inst; |
}, |
_showHideChildren: function (hidden) { |
-if (this.rows) { |
-for (var i = 0; i < this.rows.length; i++) { |
-var c$ = this.rows[i]._children; |
-for (var j = 0; j < c$.length; j++) { |
-var c = c$[j]; |
-if (c.style) { |
-c.style.display = hidden ? 'none' : ''; |
-} |
-c._hideTemplateChildren = hidden; |
+for (var i = 0; i < this._instances.length; i++) { |
+this._instances[i]._showHideChildren(hidden); |
} |
+}, |
+_forwardInstanceProp: function (inst, prop, value) { |
+if (prop == this.as) { |
+var idx; |
+if (this._sortFn || this._filterFn) { |
+idx = this.items.indexOf(this.collection.getItem(inst.__key__)); |
+} else { |
+idx = inst[this.indexAs]; |
} |
+this.set('items.' + idx, value); |
} |
}, |
-_forwardInstancePath: function (row, path, value) { |
+_forwardInstancePath: function (inst, path, value) { |
if (path.indexOf(this.as + '.') === 0) { |
-this.notifyPath('items.' + row.__key__ + '.' + path.slice(this.as.length + 1), value); |
-return true; |
+this.notifyPath('items.' + inst.__key__ + '.' + path.slice(this.as.length + 1), value); |
} |
}, |
_forwardParentProp: function (prop, value) { |
-if (this.rows) { |
-this.rows.forEach(function (row) { |
-row[prop] = value; |
+this._instances.forEach(function (inst) { |
+inst.__setProperty(prop, value, true); |
}, this); |
-} |
}, |
_forwardParentPath: function (path, value) { |
-if (this.rows) { |
-this.rows.forEach(function (row) { |
-row.notifyPath(path, value, true); |
+this._instances.forEach(function (inst) { |
+inst.notifyPath(path, value, true); |
}, this); |
-} |
}, |
_forwardItemPath: function (path, value) { |
-if (this._rowForKey) { |
+if (this._keyToInstIdx) { |
var dot = path.indexOf('.'); |
var key = path.substring(0, dot < 0 ? path.length : dot); |
-var idx = this._rowForKey[key]; |
-var row = this.rows[idx]; |
-if (row) { |
+var idx = this._keyToInstIdx[key]; |
+var inst = this._instances[idx]; |
+if (inst) { |
if (dot >= 0) { |
path = this.as + '.' + path.substring(dot + 1); |
-row.notifyPath(path, value, true); |
+inst.notifyPath(path, value, true); |
} else { |
-row[this.as] = value; |
+inst.__setProperty(this.as, value, true); |
} |
} |
} |
}, |
-modelForElement: function (el) { |
-var model; |
-while (el) { |
-if (model = el._templateInstance) { |
-if (model.dataHost != this) { |
-el = model.dataHost; |
-} else { |
-return model; |
-} |
-} else { |
-el = el.parentNode; |
-} |
-} |
-}, |
itemForElement: function (el) { |
var instance = this.modelForElement(el); |
return instance && instance[this.as]; |
@@ -3549,8 +3824,10 @@ if (this.multi) { |
var scol = Polymer.Collection.get(this.selected); |
var skey = scol.getKey(item); |
if (skey >= 0) { |
+if (this.toggle) { |
this.deselect(item); |
-} else if (this.toggle) { |
+} |
+} else { |
this.push('selected', item); |
this.async(function () { |
skey = scol.getKey(item); |
@@ -3573,15 +3850,16 @@ extends: 'template', |
properties: { |
'if': { |
type: Boolean, |
-value: false |
+value: false, |
+observer: '_queueRender' |
}, |
restamp: { |
type: Boolean, |
-value: false |
+value: false, |
+observer: '_queueRender' |
} |
}, |
behaviors: [Polymer.Templatizer], |
-observers: ['_queueRender(if, restamp)'], |
_queueRender: function () { |
this._debounceTemplate(this._render); |
}, |
@@ -3637,7 +3915,7 @@ this._instance = null; |
}, |
_wrapTextNodes: function (root) { |
for (var n = root.firstChild; n; n = n.nextSibling) { |
-if (n.nodeType === Node.TEXT_NODE) { |
+if (n.nodeType === Node.TEXT_NODE && n.textContent.trim()) { |
var s = document.createElement('span'); |
root.insertBefore(s, n); |
s.appendChild(n); |
@@ -3646,14 +3924,9 @@ n = s; |
} |
}, |
_showHideChildren: function () { |
-var hidden = this._hideTemplateChildren || !this.if; |
+var hidden = this.__hideTemplateChildren__ || !this.if; |
if (this._instance) { |
-var c$ = this._instance._children; |
-for (var i = 0; i < c$.length; i++) { |
-var c = c$[i]; |
-c.style.display = hidden ? 'none' : ''; |
-c._hideTemplateChildren = hidden; |
-} |
+this._instance._showHideChildren(hidden); |
} |
}, |
_forwardParentProp: function (prop, value) { |
@@ -3700,7 +3973,6 @@ created: function () { |
Polymer.ImportStatus.whenLoaded(this._readySelf.bind(this)); |
}, |
_registerFeatures: function () { |
-this._prepExtends(); |
this._prepConstructor(); |
}, |
_insertChildren: function () { |