From 5787196ae2e99e544a7cfcca6ad5a0a86cf53125 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 11 Jul 2015 02:01:02 -0700 Subject: [PATCH 01/68] Release July 11 notes --- _deploy | 2 +- source/_includes/custom/navigation.html | 2 +- ...meras-arduino-kodi-efergy-support.markdown | 129 ++++++++++++++++++ source/components/camera.generic.markdown | 24 ++++ source/components/index.markdown | 12 ++ source/components/sensor.efergy.markdown | 27 ++++ source/demo/manifest.json | 2 +- source/getting-started/index.markdown | 8 +- source/help/{help.markdown => index.markdown} | 0 source/images/supported_brands/efergy.png | Bin 0 -> 13067 bytes 10 files changed, 196 insertions(+), 10 deletions(-) create mode 100644 source/_posts/2015-07-11-ip-cameras-arduino-kodi-efergy-support.markdown create mode 100644 source/components/camera.generic.markdown create mode 100644 source/components/sensor.efergy.markdown rename source/help/{help.markdown => index.markdown} (100%) create mode 100644 source/images/supported_brands/efergy.png diff --git a/_deploy b/_deploy index 853a81fe69b..aaa26e2e2bd 160000 --- a/_deploy +++ b/_deploy @@ -1 +1 @@ -Subproject commit 853a81fe69bcc1acff5492e200a6ab9944b86af2 +Subproject commit aaa26e2e2bd352fcb015330314ea9176292f5c80 diff --git a/source/_includes/custom/navigation.html b/source/_includes/custom/navigation.html index 5e0ca259357..06d049a284e 100644 --- a/source/_includes/custom/navigation.html +++ b/source/_includes/custom/navigation.html @@ -24,5 +24,5 @@
  • Blog
  • -
  • Need help?
  • +
  • Need help?
  • diff --git a/source/_posts/2015-07-11-ip-cameras-arduino-kodi-efergy-support.markdown b/source/_posts/2015-07-11-ip-cameras-arduino-kodi-efergy-support.markdown new file mode 100644 index 00000000000..d01fd2816d9 --- /dev/null +++ b/source/_posts/2015-07-11-ip-cameras-arduino-kodi-efergy-support.markdown @@ -0,0 +1,129 @@ +--- +layout: post +title: "IP Cameras, Arduinos, Kodi and Efergy Energy Monitors now supported" +description: "New support for IP Cameras, Arduinos, Kodi and Efergy monitors" +date: 2015-07-11 01:37 -0700 +date_formatted: "July 11, 2015" +comments: true +categories: release-notes +--- + +Another month has passed and some great new features have landed in Home Assistant. This month release has been made possible by [balloob](https://github.com/balloob), [ettisan](https://github.com/ettisan), [fabaff](https://github.com/fabaff), [gyran](https://github.com/gyran), [jamespcole](https://github.com/jamespcole), [michaelarnauts](https://github.com/michaelarnauts), [miniconfig](https://github.com/miniconfig) and [rmkraus](https://github.com/rmkraus). + +This release includes some architectural changes by me. The first is that the frontend is now based on a [NuclearJS](http://optimizely.github.io/nuclear-js/) JavaScript backend. This has greatly helped to organize and optimize the frontend code. Another change is that Home Assistant will now install dependencies on-demand instead of installing dependencies for all supported devices. + +__IP Camera Support__
    +James has worked very hard to add support for IP cameras to Home Assistant which is included in this release. The initial release focusses on providing generic IP camera support. This means that any webcam that can exposes a JPEG image via a url can be integrated. + +Home Assistant will route the requests to your camera via the server allowing you to expose IP camera's inside your network via the Home Assistant app. + +```yaml +# Example configuration.yaml entry +camera: + platform: generic + name: my sample camera + username: MY_USERNAME + password: MY_PASSWORD + still_image_url: http://194.218.96.92/jpg/image.jpg +``` + +

    +To update to the latest version, run scripts/update. Please report any issues on GitHub. +

    + + + +__Arduino__
    + +Fabian has contributed support for interfacing with Arduinos. This makes it possible to connect your Arduino via USB and expose pins as sensor data and write to pins via switches. Have a look at [the docs](/components/arduino.markdown) for an extensive guide to get started. + +```yaml +# Example configuration.yaml entry +switch: + platform: arduino + pins: + 11: + name: Fan Office + type: digital + 12: + name: Light Desk + type: digital + +sensor: + platform: arduino + pins: + 1: + name: Door switch + type: analog + 0: + name: Brightness + type: analog +``` + +__Kodi (XBMC)__
    + +Ettisan has contributed a Kodi (XBMC) platform for the media player component. This allows you to track all the media that you are playing and allow you to control it. + +``` +# Example configuration.yaml entry +media_player: + platform: kodi + name: Kodi + url: http://192.168.0.123/jsonrpc + user: kodi + password: my_secure_password +``` + +__TP-Link__
    + +Michael has added TP-Link support to the device tracker. This allows you to now detect presence if you have a TP-Link router. + +```yaml +# Example configuration.yaml entry +device_tracker: + platform: tplink + host: YOUR_ROUTER_IP + username: YOUR_ADMIN_USERNAME + password: YOUR_ADMIN_PASSWORD +``` + +__Efergy energy monitor__
    + +Miniconfig has contributed support for the [Efergy energy meters](https://efergy.com). To get an app token, log in to your efergy account, go to the Settings page, click on App tokens, and click "Add token". + +```yaml +# Example configuration.yaml entry +sensor: + platform: efergy + app_token: APP_TOKEN + utc_offset: UTC_OFFSET + monitored_variables: + - type: instant_readings + - type: budget + - type: cost + period: day + currency: $ +``` + +__Forecast.io__
    +Fabiann has added support for [Forecast.io](https://forecast.io/) to get weather forecasts for Home Assistant. You need an API key which is free but requires a [registration](https://developer.forecast.io/register). To add Forecast.io to your installation, add the following to your `configuration.yaml` file: + +```yaml +# Example configuration.yaml entry +sensor: + platform: forecast + api_key: YOUR_APP_KEY + monitored_conditions: + - summary + - precip_type + - precip_intensity + - temperature + - dew_point + - wind_speed + - wind_bearing + - cloud_cover + - humidity + - pressure + - visibility + - ozone +``` diff --git a/source/components/camera.generic.markdown b/source/components/camera.generic.markdown new file mode 100644 index 00000000000..0ee83747637 --- /dev/null +++ b/source/components/camera.generic.markdown @@ -0,0 +1,24 @@ +--- +layout: page +title: "Generic IP Camera" +description: "Instructions how to integrate IP cameras within Home Assistant." +date: 2015-07-11 0:36 +sidebar: false +comments: false +sharing: true +footer: true +--- + +This component allows you to integrate any IP camera into Home Assistant. It supports fetching images from a url with optional HTTP authentication. + +Home Assistant will serve the images via its server, making it possible to view your IP camera's while outside of your network. + +```yaml +# Example configuration.yaml entry +camera: + platform: generic + name: my sample camera + username: MY_USERNAME + password: MY_PASSWORD + still_image_url: http://194.218.96.92/jpg/image.jpg +``` diff --git a/source/components/index.markdown b/source/components/index.markdown index 198109b3696..044f764466f 100644 --- a/source/components/index.markdown +++ b/source/components/index.markdown @@ -163,6 +163,18 @@ Entities are things that you want to observe within Home Assistant. Support for Controls your Arduino's digital pins and read from the analog pins. + + + Efergy Engage hubs + Monitors home energy use as measured by an Efergy engage hub. + + + + + Generic IP cameras + Integrate any IP camera or image url into a camera feed. + +

    diff --git a/source/components/sensor.efergy.markdown b/source/components/sensor.efergy.markdown new file mode 100644 index 00000000000..7886ef0e459 --- /dev/null +++ b/source/components/sensor.efergy.markdown @@ -0,0 +1,27 @@ +--- +layout: page +title: "Efergy support" +description: "Instructions how to integrate Efergy devices within Home Assistant." +date: 2015-07-11 0:15 +sidebar: false +comments: false +sharing: true +footer: true +--- + + +Integrate your [Efergy](https://efergy.com) meter information into Home Assistant. To get an app token, log in to your efergy account, go to the Settings page, click on App tokens, and click "Add token". + +```yaml +# Example configuration.yaml entry +sensor: + platform: efergy + app_token: APP_TOKEN + utc_offset: UTC_OFFSET + monitored_variables: + - type: instant_readings + - type: budget + - type: cost + period: day + currency: $ +``` diff --git a/source/demo/manifest.json b/source/demo/manifest.json index 69143ce5179..4454a923df9 100644 --- a/source/demo/manifest.json +++ b/source/demo/manifest.json @@ -1,7 +1,7 @@ { "name": "Home Assistant", "short_name": "Assistant", - "start_url": "/", + "start_url": "/demo/", "display": "standalone", "icons": [ { diff --git a/source/getting-started/index.markdown b/source/getting-started/index.markdown index d230dd379cb..73494570e26 100644 --- a/source/getting-started/index.markdown +++ b/source/getting-started/index.markdown @@ -25,7 +25,6 @@ Installing and running Home Assistant on your local machine is easy. Make sure y git clone --recursive https://github.com/balloob/home-assistant.git python3 -m venv home-assistant cd home-assistant -python3 -m pip install -r requirements.txt python3 -m homeassistant --open-ui ```

    @@ -79,7 +78,7 @@ curl -L https://raw.githubusercontent.com/yyuu/pyenv-installer/master/bin/pyenv- ```bash nano ~/.bashrc ``` - +

    Then add these lines to the end of the file and save:

    ``` export PATH="$HOME/.pyenv/bin:$PATH" @@ -122,11 +121,6 @@ cd home-assistant pyenv local homeassistant ``` -

    Step 6. Finish the install

    -```bash -python3 -m pip install -r requirements.txt -``` -

    Step 7. Start it up

    ```bash python3 -m homeassistant diff --git a/source/help/help.markdown b/source/help/index.markdown similarity index 100% rename from source/help/help.markdown rename to source/help/index.markdown diff --git a/source/images/supported_brands/efergy.png b/source/images/supported_brands/efergy.png new file mode 100644 index 0000000000000000000000000000000000000000..4d1c1673cdeac6ff9684429b9c80f2151eb5fc0c GIT binary patch literal 13067 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≪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 Zwl}olO1e@n@d_f**EZ3r)o_maKLAe7WDWoT literal 0 HcmV?d00001 From 1a30efa2df95001e8eb6ee93a3d703474108596f Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 11 Jul 2015 12:30:28 -0700 Subject: [PATCH 02/68] Update demo --- _deploy | 2 +- source/demo/frontend.html | 1800 +++++++++++++++---------- source/demo/webcomponents-lite.min.js | 6 +- 3 files changed, 1118 insertions(+), 690 deletions(-) diff --git a/_deploy b/_deploy index aaa26e2e2bd..51e2a43dfbc 160000 --- a/_deploy +++ b/_deploy @@ -1 +1 @@ -Subproject commit aaa26e2e2bd352fcb015330314ea9176292f5c80 +Subproject commit 51e2a43dfbc4f40bafffab86bc0309030666c490 diff --git a/source/demo/frontend.html b/source/demo/frontend.html index b1c6d302076..593499cbfd2 100644 --- a/source/demo/frontend.html +++ b/source/demo/frontend.html @@ -141,6 +141,12 @@ this.copyOwnProperty(n, api, prototype); } return prototype || api; }, +mixin: function (target, source) { +for (var i in source) { +target[i] = source[i]; +} +return target; +}, copyOwnProperty: function (name, source, target) { var pd = Object.getOwnPropertyDescriptor(source, name); if (pd) { @@ -516,7 +522,7 @@ debouncer.stop(); } } }); -Polymer.version = '1.0.4'; +Polymer.version = '1.0.6'; Polymer.Base._addFeature({ _registerFeatures: function () { this._prepIs(); @@ -955,6 +961,8 @@ var getInnerHTML = Polymer.domInnerHTML.getInnerHTML; var nativeInsertBefore = Element.prototype.insertBefore; var nativeRemoveChild = Element.prototype.removeChild; var nativeAppendChild = Element.prototype.appendChild; +var nativeCloneNode = Element.prototype.cloneNode; +var nativeImportNode = Document.prototype.importNode; var dirtyRoots = []; var DomApi = function (node) { this.node = node; @@ -1064,8 +1072,8 @@ node._ownerShadyRoot = root; return node._ownerShadyRoot; }, _maybeDistribute: function (node, parent) { -var fragContent = node.nodeType === Node.DOCUMENT_FRAGMENT_NODE && node.querySelector(CONTENT); -var wrappedContent = fragContent && fragContent.parentNode.nodeType !== Node.DOCUMENT_FRAGMENT_NODE; +var fragContent = node.nodeType === Node.DOCUMENT_FRAGMENT_NODE && !node.__noContent && Polymer.dom(node).querySelector(CONTENT); +var wrappedContent = fragContent && Polymer.dom(fragContent).parentNode.nodeType !== Node.DOCUMENT_FRAGMENT_NODE; var hasContent = fragContent || node.localName === CONTENT; if (hasContent) { var root = this._ownerShadyRootForNode(parent); @@ -1083,8 +1091,8 @@ return parentNeedsDist || hasContent && !wrappedContent; }, _tryRemoveUndistributedNode: function (node) { if (this.node.shadyRoot) { -if (node.parentNode) { -nativeRemoveChild.call(node.parentNode, node); +if (node._composedParent) { +nativeRemoveChild.call(node._composedParent, node); } return true; } @@ -1093,7 +1101,7 @@ _updateInsertionPoints: function (host) { host.shadyRoot._insertionPoints = factory(host.shadyRoot).querySelectorAll(CONTENT); }, _nodeIsInLogicalTree: function (node) { -return Boolean(node._lightParent || node._isShadyRoot || this._ownerShadyRootForNode(node) || node.shadyRoot); +return Boolean(node._lightParent !== undefined || node._isShadyRoot || this._ownerShadyRootForNode(node) || node.shadyRoot); }, _parentNeedsDistribution: function (parent) { return parent && parent.shadyRoot && hasInsertionPoint(parent.shadyRoot); @@ -1127,7 +1135,7 @@ if (this._contains(container, content)) { var dc$ = factory(content).getDistributedNodes(); for (var j = 0; j < dc$.length; j++) { hostNeedsDist = true; -var node = dc$[i]; +var node = dc$[j]; var parent = node.parentNode; if (parent) { removeFromComposedParent(parent, node); @@ -1266,6 +1274,31 @@ _distributeParent: function () { if (this._parentNeedsDistribution(this.parentNode)) { this._lazyDistribute(this.parentNode); } +}, +cloneNode: function (deep) { +var n = nativeCloneNode.call(this.node, false); +if (deep) { +var c$ = this.childNodes; +var d = factory(n); +for (var i = 0, nc; i < c$.length; i++) { +nc = factory(c$[i]).cloneNode(true); +d.appendChild(nc); +} +} +return n; +}, +importNode: function (externalNode, deep) { +var doc = this.node instanceof HTMLDocument ? this.node : this.node.ownerDocument; +var n = nativeImportNode.call(doc, externalNode, false); +if (deep) { +var c$ = factory(externalNode).childNodes; +var d = factory(n); +for (var i = 0, nc; i < c$.length; i++) { +nc = factory(doc).importNode(c$[i], true); +d.appendChild(nc); +} +} +return n; } }; Object.defineProperty(DomApi.prototype, 'classList', { @@ -1293,6 +1326,9 @@ this.domApi._distributeParent(); toggle: function () { this.node.classList.toggle.apply(this.node.classList, arguments); this.domApi._distributeParent(); +}, +contains: function () { +return this.node.classList.contains.apply(this.node.classList, arguments); } }; if (!Settings.useShadow) { @@ -1411,8 +1447,9 @@ if (this.node.nodeType !== Node.TEXT_NODE) { this._clear(); var d = document.createElement('div'); d.innerHTML = text; -for (var e = d.firstChild; e; e = e.nextSibling) { -this.appendChild(e); +var c$ = Array.prototype.slice.call(d.childNodes); +for (var i = 0; i < c$.length; i++) { +this.appendChild(c$[i]); } } }, @@ -1435,6 +1472,13 @@ return n; n = n.parentNode; } }; +DomApi.prototype.cloneNode = function (deep) { +return this.node.cloneNode(deep); +}; +DomApi.prototype.importNode = function (externalNode, deep) { +var doc = this.node instanceof HTMLDocument ? this.node : this.node.ownerDocument; +return doc.importNode(externalNode, deep); +}; DomApi.prototype.getDestinationInsertionPoints = function () { var n$ = this.node.getDestinationInsertionPoints(); return n$ ? Array.prototype.slice.call(n$) : []; @@ -1579,9 +1623,6 @@ factory: factory Polymer.Base._addFeature({ _prepShady: function () { this._useContent = this._useContent || Boolean(this._template); -if (this._useContent) { -this._template._hasInsertionPoint = this._template.content.querySelector('content'); -} }, _poolContent: function () { if (this._useContent) { @@ -1601,7 +1642,7 @@ this.shadyRoot = this.root; this.shadyRoot._distributionClean = false; this.shadyRoot._isShadyRoot = true; this.shadyRoot._dirtyRoots = []; -this.shadyRoot._insertionPoints = this._template._hasInsertionPoint ? this.shadyRoot.querySelectorAll('content') : []; +this.shadyRoot._insertionPoints = !this._notes || this._notes._hasContent ? this.shadyRoot.querySelectorAll('content') : []; saveLightChildrenIfNeeded(this.shadyRoot); this.shadyRoot.host = this; }, @@ -1961,6 +2002,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); @@ -2320,6 +2364,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') { @@ -2344,6 +2389,9 @@ document.removeEventListener(en, mouseCanceller, true); } } function ignoreMouse() { +if (IS_TOUCH_ONLY) { +return; +} if (!POINTERSTATE.mouse.mouseIgnoreJob) { setupTeardownMouseCanceller(true); } @@ -2392,6 +2440,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; @@ -2476,12 +2530,18 @@ 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) { @@ -2499,9 +2559,10 @@ dep = deps[i]; gd = gobj[dep]; if (gd && gd[name]) { gd[name] = (gd[name] || 1) - 1; -if (gd[name] === 0) { -node.removeEventListener(dep, this.handleNative); +gd._count = (gd._count || 1) - 1; } +if (gd._count === 0) { +node.removeEventListener(dep, this.handleNative); } } } @@ -2563,7 +2624,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); @@ -2573,10 +2634,10 @@ 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; @@ -2632,7 +2693,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; @@ -2666,7 +2727,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)) { @@ -2680,7 +2741,7 @@ 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) { Gestures.prevent('tap'); @@ -2756,9 +2817,10 @@ this.forward(e.changedTouches[0]); forward: function (e) { 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 (!this.info.prevent) { -Gestures.fire(e.target, 'tap', { +Gestures.fire(t, 'tap', { x: e.clientX, y: e.clientY, sourceEvent: e @@ -2796,50 +2858,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) { @@ -2994,28 +3061,23 @@ 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 && (old === old || value === value)) { this.__data__[property] = value; @@ -3026,16 +3088,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); }, @@ -3093,10 +3164,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; } @@ -3167,11 +3241,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]; @@ -3197,7 +3273,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')); } @@ -3270,6 +3346,7 @@ if (prop.observer) { this._addObserverEffect(p, prop.observer); } if (prop.computed) { +prop.readOnly = true; this._addComputedEffect(p, prop.computed); } if (prop.notify) { @@ -3460,12 +3537,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); }, @@ -3509,18 +3587,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); } } }, @@ -3549,12 +3622,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); +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) { @@ -3587,6 +3661,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); @@ -3740,9 +3823,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) { @@ -3888,12 +3970,12 @@ var VAR_START = '--'; var MEDIA_START = '@media'; var AT_START = '@'; var rx = { -comments: /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim, +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; @@ -4069,25 +4151,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; }); @@ -4106,7 +4196,8 @@ stop = true; return { value: selector, combinator: combinator, -stop: stop +stop: stop, +hostContext: hostContext }; }, _transformSimpleSelector: function (selector, scope) { @@ -4138,6 +4229,8 @@ 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 = '.'; @@ -4518,7 +4611,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); } } @@ -4539,14 +4632,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'], @@ -4559,41 +4661,6 @@ var v = 1 << n % 32; bits[o] = (bits[o] || 0) | v; } }(); -Polymer.StyleDefaults = function () { -var styleProperties = Polymer.StyleProperties; -var styleUtil = Polymer.StyleUtil; -var api = { -_styles: [], -_properties: null, -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.reify(this._properties); -} -return this._properties; -}, -_needsStyleProperties: function () { -}, -_computeStyleProperties: function () { -return this._styleProperties; -}, -updateStyles: function () { -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 () { Polymer.StyleCache = function () { this.cache = {}; @@ -4624,8 +4691,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; } } @@ -4633,9 +4702,55 @@ 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; @@ -4665,6 +4780,7 @@ 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) { @@ -4679,15 +4795,14 @@ info = styleCache.retrieve(this.is, this._ownStyleProperties, this._styles); var globalCached = Boolean(info) && !scopeCached; 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); @@ -4704,7 +4819,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; }, @@ -4721,10 +4836,10 @@ _applyStyleProperties: function (info) { var oldScopeSelector = this._scopeSelector; this._scopeSelector = info ? info._scopeSelector : this.is + '-' + this.__proto__._scopeCount++; var style = propertyUtils.applyElementStyle(this, this._styleProperties, this._scopeSelector, info && info.style); -if ((style || oldScopeSelector) && !nativeShadow) { +if (!nativeShadow) { propertyUtils.applyElementScopeSelector(this, this._scopeSelector, oldScopeSelector, this._scopeCssViaAttr); } -return style || {}; +return style; }, serializeValueToAttribute: function (value, attribute, node) { node = node || this; @@ -4743,8 +4858,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 { @@ -4768,8 +4886,8 @@ c.updateStyles(); } } }); -Polymer.updateStyles = function () { -styleDefaults.updateStyles(); +Polymer.updateStyles = function (properties) { +styleDefaults.updateStyles(properties); Polymer.Base._updateRootStyles(document); }; var styleCache = new Polymer.StyleCache(); @@ -4866,7 +4984,7 @@ styleTransformer.documentRule(rule); }); }()); Polymer.Templatizer = { -properties: { _hideTemplateChildren: { observer: '_showHideChildren' } }, +properties: { __hideTemplateChildren__: { observer: '_showHideChildren' } }, _templatizerStatic: { count: 0, callbacks: {}, @@ -4895,6 +5013,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); @@ -4907,7 +5026,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); @@ -4930,6 +5057,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; @@ -4988,18 +5118,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('.'); @@ -5022,6 +5163,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(); @@ -5033,6 +5175,9 @@ children.push(n); n._templateInstance = this; } this._children = children; +if (host.__hideTemplateChildren__) { +this._showHideChildren(true); +} this._tryReady(); }, _listenImpl: function (node, eventName, methodName) { @@ -5059,6 +5204,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({ @@ -5105,7 +5264,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]; @@ -5117,7 +5276,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]; @@ -5126,8 +5285,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]; @@ -5289,7 +5457,7 @@ return; }, render: function () { this._fullRefresh = true; -this.debounce('render', this._render); +this._debounceTemplate(this._render); this._flushTemplates(); }, _render: function () { @@ -5321,9 +5489,9 @@ 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; +row.__setProperty(this.as, item, true); +row.__setProperty('__key__', key, true); +row.__setProperty(this.indexAs, i, true); } for (; i < this.rows.length; i++) { this._detachRow(i); @@ -5477,27 +5645,30 @@ return row; _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; +this.rows[i]._showHideChildren(hidden); } } +}, +_forwardInstanceProp: function (row, prop, value) { +if (prop == this.as) { +var idx; +if (this._sortFn || this._filterFn) { +idx = this.items.indexOf(this.collection.getItem(row.__key__)); +} else { +idx = row[this.indexAs]; +} +this.set('items.' + idx, value); } }, _forwardInstancePath: function (row, path, value) { if (path.indexOf(this.as + '.') === 0) { this.notifyPath('items.' + row.__key__ + '.' + path.slice(this.as.length + 1), value); -return true; } }, _forwardParentProp: function (prop, value) { if (this.rows) { this.rows.forEach(function (row) { -row[prop] = value; +row.__setProperty(prop, value, true); }, this); } }, @@ -5519,25 +5690,11 @@ if (dot >= 0) { path = this.as + '.' + path.substring(dot + 1); row.notifyPath(path, value, true); } else { -row[this.as] = value; +row.__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]; @@ -5627,15 +5784,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); }, @@ -5691,7 +5849,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); @@ -5700,14 +5858,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) { @@ -6031,11 +6184,11 @@ this._removeChildren(); @@ -13406,9 +13642,10 @@ typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Yn._=Zn, def /** * `Polymer.NeonAnimationRunnerBehavior` adds a method to run animations. - * @polymerBehavior + * + * @polymerBehavior Polymer.NeonAnimationRunnerBehavior */ - Polymer.NeonAnimationRunnerBehavior = [Polymer.NeonAnimatableBehavior, { + Polymer.NeonAnimationRunnerBehaviorImpl = { properties: { @@ -13500,8 +13737,13 @@ typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Yn._=Zn, def this._player.cancel(); } } + }; - }]; + /** @polymerBehavior Polymer.NeonAnimationRunnerBehavior */ + Polymer.NeonAnimationRunnerBehavior = [ + Polymer.NeonAnimatableBehavior, + Polymer.NeonAnimationRunnerBehaviorImpl + ]; @@ -17612,6 +17703,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN