Polymer .9: convert dev tools

This commit is contained in:
Paulus Schoutsen 2015-05-19 23:38:32 -07:00
parent 33122701b9
commit 5baf16ad6e
7 changed files with 372 additions and 381 deletions

View File

@ -1,60 +1,53 @@
<link rel="import" href="../bower_components/polymer/polymer.html"> <link rel="import" href="../bower_components/polymer/polymer.html">
<polymer-element name="entity-list" attributes="cbEntityClicked"> <dom-module id="entity-list">
<style>
ul {
margin: 0;
padding: 0;
}
li {
list-style: none;
line-height: 2em;
}
a {
color: var(--accent-color);
}
</style>
<template> <template>
<style> <ul>
:host { <template is='dom-repeat' items='[[entities]]' as='entity'>
display: block; <li><a href='#' on-click='entitySelected'>[[entity]]</a></li>
}
.entityContainer {
font-size: 1rem;
}
</style>
<template if={{cbEntityClicked}}>
<style>
a {
text-decoration: underline;
cursor: pointer;
}
</style>
</template>
<div>
<template repeat="{{entityID in entityIDs}}">
<div class='eventContainer'>
<a on-click={{handleClick}}>{{entityID}}</a>
</div>
</template> </template>
</ul>
</div>
</template> </template>
<script> </dom-module>
var storeListenerMixIn = window.hass.storeListenerMixIn;
Polymer(Polymer.mixin({ <script>
cbEventClicked: null, (function() {
entityIDs: [], Polymer({
is: 'entity-list',
attached: function() { behaviors: [StoreListenerBehavior],
this.listenToStores(true);
},
detached: function() { properties: {
this.stopListeningToStores(); entities: {
type: Array,
value: [],
},
}, },
stateStoreChanged: function(stateStore) { stateStoreChanged: function(stateStore) {
this.entityIDs = stateStore.entityIDs.toArray(); this.entities = stateStore.entityIDs.toArray();
}, },
handleClick: function(ev) { entitySelected: function(ev) {
if(this.cbEntityClicked) { ev.preventDefault();
this.cbEntityClicked(ev.path[0].innerHTML); this.fire('entity-selected', {entityId: ev.model.entity});
}
}, },
});
}, storeListenerMixIn)); })();
</script> </script>
</polymer-element>

View File

@ -1,62 +1,56 @@
<link rel="import" href="../bower_components/polymer/polymer.html"> <link rel="import" href="../bower_components/polymer/polymer.html">
<polymer-element name="events-list" attributes="cbEventClicked"> <dom-module id="events-list">
<style>
ul {
margin: 0;
padding: 0;
}
li {
list-style: none;
line-height: 2em;
}
a {
color: var(--accent-color);
}
</style>
<template> <template>
<style> <ul>
:host { <template is='dom-repeat' items='[[events]]' as='event'>
display: block; <li>
} <a href='#' on-click='eventSelected'>{{event.event}}</a>
<span> (</span><span>{{event.listener_count}}</span><span> listeners)</span>
.eventContainer { </li>
font-size: 1rem;
}
</style>
<template if={{cbEventClicked}}>
<style>
a {
text-decoration: underline;
cursor: pointer;
}
</style>
</template>
<div>
<template repeat="{{event in events}}">
<div class='eventContainer'>
<a on-click={{handleClick}}>{{event.event}}</a>
({{event.listener_count}} listeners)
</div>
</template> </template>
</ul>
</div>
</template> </template>
<script> </dom-module>
var storeListenerMixIn = window.hass.storeListenerMixIn;
Polymer(Polymer.mixin({ <script>
cbEventClicked: null, (function() {
events: [], Polymer({
is: 'events-list',
attached: function() { behaviors: [StoreListenerBehavior],
this.listenToStores(true);
},
detached: function() { properties: {
this.stopListeningToStores(); events: {
type: Array,
value: [],
},
}, },
eventStoreChanged: function(eventStore) { eventStoreChanged: function(eventStore) {
this.events = eventStore.all.toArray(); this.events = eventStore.all.toArray();
}, },
handleClick: function(ev) { eventSelected: function(ev) {
if(this.cbEventClicked) { ev.preventDefault();
this.cbEventClicked(ev.path[0].innerHTML); this.fire('event-selected', {eventType: ev.model.event.event});
}
}, },
});
}, storeListenerMixIn)); })();
</script> </script>
</polymer-element>

View File

@ -1,72 +1,58 @@
<link rel="import" href="../bower_components/polymer/polymer.html"> <link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/core-menu/core-menu.html">
<link rel="import" href="../bower_components/core-menu/core-submenu.html"> <link rel="import" href="../bower_components/paper-menu/paper-menu.html">
<link rel="import" href="../bower_components/core-item/core-item.html">
<link rel="import" href="domain-icon.html"> <link rel="import" href="domain-icon.html">
<polymer-element name="services-list" attributes="cbServiceClicked"> <dom-module id="services-list" attributes="cbServiceClicked">
<template> <style>
<style> ul {
:host { margin: 0;
display: block; padding: 0;
} }
core-menu { li {
margin-top: 0; list-style: none;
font-size: 1rem; line-height: 2em;
} }
a { a {
display: block; color: var(--accent-color);
} }
</style> </style>
<template if={{cbServiceClicked}}> <template>
<style> <ul>
a, core-submenu { <template is='dom-repeat' items="[[domains]]" as="domain">
text-decoration: underline; <template is='dom-repeat' items="[[computeServices(domain)]]" as="service">
cursor: pointer; <li><a href='#' on-click='serviceClicked'>
} <span>[[domain]]</span>/<span>[[service]]</span>
</style> </a></li>
</template> </template>
</template>
<div> </ul>
<core-menu selected="0">
<template repeat="{{domain in domains}}">
<core-submenu icon="{{domain | getIcon}}" label="{{domain}}">
<template repeat="{{service in domain | getServices}}">
<a on-click={{serviceClicked}} data-domain={{domain}}>{{service}}</a>
</template>
</core-submenu>
</template>
</core-menu>
</div>
</template> </template>
<script> </dom-module>
var storeListenerMixIn = window.hass.storeListenerMixIn;
Polymer(Polymer.mixin({ <script>
domains: [], (function() {
services: null, Polymer({
cbServiceClicked: null, is: 'services-list',
attached: function() { behaviors: [StoreListenerBehavior],
this.listenToStores(true);
properties: {
domains: {
type: Array,
value: [],
},
services: {
type: Object,
},
}, },
detached: function() { computeServices: function(domain) {
this.stopListeningToStores();
},
getIcon: function(domain) {
return hass.uiUtil.domainIcon(domain);
},
getServices: function(domain) {
return this.services.get(domain).toArray(); return this.services.get(domain).toArray();
}, },
@ -76,15 +62,10 @@
}, },
serviceClicked: function(ev) { serviceClicked: function(ev) {
if(this.cbServiceClicked) { ev.preventDefault();
var target = ev.path[0]; this.fire(
var domain = target.getAttributeNode("data-domain").value; 'service-selected', {domain: ev.model.domain, service: ev.model.service});
var service = target.innerHTML; },
});
this.cbServiceClicked(domain, service); })();
} </script>
}
}, storeListenerMixIn));
</script>
</polymer-element>

View File

@ -12,11 +12,11 @@
<link rel="import" href="../layouts/partial-states.html"> <link rel="import" href="../layouts/partial-states.html">
<link rel="import" href="../layouts/partial-logbook.html"> <link rel="import" href="../layouts/partial-logbook.html">
<link rel="import" href="../layouts/partial-history.html"> <link rel="import" href="../layouts/partial-history.html">
<!-- <link rel="import" href="../layouts/partial-dev-fire-event.html">
<link rel="import" href="../layouts/partial-dev-call-service.html"> <link rel="import" href="../layouts/partial-dev-call-service.html">
<link rel="import" href="../layouts/partial-dev-fire-event.html">
<link rel="import" href="../layouts/partial-dev-set-state.html"> <link rel="import" href="../layouts/partial-dev-set-state.html">
<link rel="import" href="../components/ha-notifications.html"> <!--<link rel="import" href="../components/ha-notifications.html">
<link rel="import" href="../components/ha-modals.html"> --> <link rel="import" href="../components/ha-modals.html"> -->
<link rel="import" href="../components/stream-status.html"> <link rel="import" href="../components/stream-status.html">
@ -59,7 +59,7 @@
<!-- <ha-notifications></ha-notifications> --> <!-- <ha-notifications></ha-notifications> -->
<!-- <ha-modals></ha-modals> --> <!-- <ha-modals></ha-modals> -->
<paper-drawer-panel id="drawer" on-paper-responsive-change="responsiveChanged"> <paper-drawer-panel id="drawer" narrow='{{narrow}}'>
<paper-header-panel mode="scroll" drawer class='sidenav fit'> <paper-header-panel mode="scroll" drawer class='sidenav fit'>
<paper-toolbar> <paper-toolbar>
Home Assistant Home Assistant
@ -108,13 +108,13 @@
<div class='text label divider'>Developer Tools</div> <div class='text label divider'>Developer Tools</div>
<div class='dev-tools layout horizontal justified'> <div class='dev-tools layout horizontal justified'>
<paper-icon-button <paper-icon-button
icon="settings-remote" data-panel='[[selectedDevService]]' icon="settings-remote" data-panel$='[[selectedDevService]]'
on-click="handleDevClick"></paper-icon-button> on-click="handleDevClick"></paper-icon-button>
<paper-icon-button <paper-icon-button
icon="settings-ethernet" data-panel='[[selectedSetState]]' icon="settings-ethernet" data-panel$='[[selectedDevState]]'
on-click="handleDevClick"></paper-icon-button> on-click="handleDevClick"></paper-icon-button>
<paper-icon-button <paper-icon-button
icon="settings-input-antenna" data-panel='[[selectedDevEvent]]' icon="settings-input-antenna" data-panel$='[[selectedDevEvent]]'
on-click="handleDevClick"></paper-icon-button> on-click="handleDevClick"></paper-icon-button>
</div> </div>
</paper-menu> </paper-menu>
@ -124,27 +124,26 @@
This is the main partial, never remove it from the DOM but hide it This is the main partial, never remove it from the DOM but hide it
to speed up when people click on states. to speed up when people click on states.
--> -->
<partial-states hidden$="{{hideStates}}" <partial-states hidden$="[[hideStates]]"
main narrow="{{narrow}}" main narrow="[[narrow]]"
filter="{{stateFilter}}"> filter="[[stateFilter]]">
</partial-states> </partial-states>
<template is='dom-if' if="{{isSelectedLogbook}}"> <template is='dom-if' if="[[isSelectedLogbook]]">
<partial-logbook main narrow="{{narrow}}"></partial-logbook> <partial-logbook main narrow="[[narrow]]"></partial-logbook>
</template> </template>
<template is='dom-if' if="{{isSelectedHistory}}"> <template is='dom-if' if="[[isSelectedHistory]]">
<partial-history main narrow="{{narrow}}"></partial-history> <partial-history main narrow="[[narrow]]"></partial-history>
</template> </template>
<!-- <template is='dom-if' if="[[isSelectedDevService]]">
<template is='dom-if' if="{{selected == 'fire-event'}}"> <partial-dev-call-service main narrow="[[narrow]]"></partial-dev-call-service>
<partial-dev-fire-event main narrow="{{narrow}}"></partial-dev-fire-event>
</template> </template>
<template is='dom-if' if="{{selected == 'set-state'}}"> <template is='dom-if' if="[[isSelectedDevEvent]]">
<partial-dev-set-state main narrow="{{narrow}}"></partial-dev-set-state> <partial-dev-fire-event main narrow="[[narrow]]"></partial-dev-fire-event>
</template>
<template is='dom-if' if="[[isSelectedDevState]]">
<partial-dev-set-state main narrow="[[narrow]]"></partial-dev-set-state>
</template> </template>
<template is='dom-if' if="{{selected == 'call-service'}}">
<partial-dev-call-service main narrow="{{narrow}}"></partial-dev-call-service>
</template>-->
</paper-drawer-panel> </paper-drawer-panel>
</template> </template>
@ -311,10 +310,6 @@
} }
}, },
responsiveChanged: function(ev, detail, sender) {
this.narrow = detail.narrow;
},
closeDrawer: function() { closeDrawer: function() {
this.$.drawer.closeDrawer(); this.$.drawer.closeDrawer();
}, },

View File

@ -2,87 +2,100 @@
<link rel="import" href="../bower_components/paper-button/paper-button.html"> <link rel="import" href="../bower_components/paper-button/paper-button.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html"> <link rel="import" href="../bower_components/paper-input/paper-input.html">
<link rel="import" href="../bower_components/paper-input/paper-input-decorator.html"> <link rel="import" href="../bower_components/paper-input/paper-textarea.html">
<link rel="import" href="../bower_components/paper-input/paper-autogrow-textarea.html">
<link rel="import" href="./partial-base.html"> <link rel="import" href="./partial-base.html">
<link rel="import" href="../components/services-list.html"> <link rel="import" href="../components/services-list.html">
<polymer-element name="partial-dev-call-service" attributes="narrow togglePanel"> <dom-module id="partial-dev-call-service">
<template>
<style> <style>
.form { .form {
padding: 24px; padding: 24px;
background-color: white; background-color: white;
} }
.ha-form {
margin-right: 16px;
}
</style> </style>
<template>
<partial-base narrow="[[narrow]]">
<span header-title>Call Service</span>
<partial-base narrow="{{narrow}}" togglePanel="{{togglePanel}}"> <div class='form fit'>
<span header-title>Call Service</span> <p>
Call a service from a component.
</p>
<div class='form' fit> <div class$='[[computeFormClasses(narrow)]]'>
<p> <div class='ha-form flex'>
Call a service from a component. <paper-input label="Domain" autofocus value='{{domain}}'></paper-input>
</p> <paper-input label="Service" value='{{service}}'></paper-input>
<paper-textarea label="Service Data (JSON, optional)" value='{{serviceData}}'></paper-textarea>
<paper-button on-click='callService' raised>Call Service</paper-button>
</div>
<div layout horizontal?="{{!narrow}}" vertical?="{{narrow}}"> <div>
<div class='ha-form' flex?="{{!narrow}}"> <h4>Available services:</h4>
<paper-input id="inputDomain" label="Domain" floatingLabel="true" autofocus required></paper-input> <services-list on-service-selected='serviceSelected'></services-list>
<paper-input id="inputService" label="Service" floatingLabel="true" required></paper-input> </div>
<paper-input-decorator
label="Service Data (JSON, optional)"
floatingLabel="true">
<paper-autogrow-textarea id="inputDataWrapper">
<textarea id="inputData"></textarea>
</paper-autogrow-textarea>
</paper-input-decorator>
<paper-button on-click={{clickCallService}}>Call Service</paper-button>
</div>
<div class='sidebar'>
<b>Available services:</b>
<services-list cbServiceClicked={{serviceSelected}}></services-list>
</div> </div>
</div> </div>
</div> </partial-base>
</template>
</dom-module>
</partial-base>
</template>
<script> <script>
var serviceActions = window.hass.serviceActions; (function() {
var serviceActions = window.hass.serviceActions;
Polymer({ Polymer({
ready: function() { is: 'partial-dev-call-service',
// to ensure callback methods work..
this.serviceSelected = this.serviceSelected.bind(this);
},
setService: function(domain, service) { properties: {
this.$.inputDomain.value = domain; narrow: {
this.$.inputService.value = service; type: Boolean,
}, value: false,
},
serviceSelected: function(domain, service) { domain: {
this.setService(domain, service); type: String,
}, value: '',
},
clickCallService: function() { service: {
try { type: String,
serviceActions.callService( value: '',
this.$.inputDomain.value, },
this.$.inputService.value,
this.$.inputData.value ? JSON.parse(this.$.inputData.value) : {});
} catch (err) {
alert("Error parsing JSON: " + err);
}
}
}); serviceData: {
type: String,
value: '',
},
},
serviceSelected: function(ev) {
this.domain = ev.detail.domain;
this.service = ev.detail.service;
},
callService: function() {
var serviceData;
try {
serviceData = this.serviceData ? JSON.parse(this.serviceData): {};
} catch (err) {
alert("Error parsing JSON: " + err);
return;
}
serviceActions.callService(this.domain, this.service, serviceData);
},
computeFormClasses: function(narrow) {
return 'layout ' + (narrow ? 'vertical' : 'horizontal');
},
});
})();
</script> </script>
</polymer-element>

View File

@ -2,79 +2,90 @@
<link rel="import" href="../bower_components/paper-button/paper-button.html"> <link rel="import" href="../bower_components/paper-button/paper-button.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html"> <link rel="import" href="../bower_components/paper-input/paper-input.html">
<link rel="import" href="../bower_components/paper-input/paper-input-decorator.html"> <link rel="import" href="../bower_components/paper-input/paper-textarea.html">
<link rel="import" href="../bower_components/paper-input/paper-autogrow-textarea.html">
<link rel="import" href="./partial-base.html"> <link rel="import" href="./partial-base.html">
<link rel="import" href="../components/events-list.html"> <link rel="import" href="../components/events-list.html">
<polymer-element name="partial-dev-fire-event" attributes="narrow togglePanel"> <dom-module id="partial-dev-fire-event">
<template>
<style> <style>
.form { .form {
padding: 24px; padding: 24px;
background-color: white; background-color: white;
} }
.ha-form {
margin-right: 16px;
}
</style> </style>
<partial-base narrow="{{narrow}}" togglePanel="{{togglePanel}}"> <template>
<span header-title>Fire Event</span> <partial-base narrow="{{narrow}}">
<span header-title>Fire Event</span>
<div class='form' fit> <div class='form fit'>
<p> <p>
Fire an event on the event bus. Fire an event on the event bus.
</p> </p>
<div layout horizontal?="{{!narrow}}" vertical?="{{narrow}}"> <div class$='[[computeFormClasses(narrow)]]'>
<div class='ha-form' flex?="{{!narrow}}"> <div class='ha-form flex'>
<paper-input <paper-input label="Event Type" autofocus required value='{{eventType}}'></paper-input>
id="inputType" label="Event Type" floatingLabel="true" <paper-textarea label="Event Data (JSON, optional)" value='{{eventData}}'></paper-textarea>
autofocus required></paper-input> <paper-button on-click='fireEvent' raised>Fire Event</paper-button>
<paper-input-decorator </div>
label="Event Data (JSON, optional)"
floatingLabel="true">
<paper-autogrow-textarea id="inputDataWrapper"> <div>
<textarea id="inputData"></textarea> <h4>Available events:</h4>
</paper-autogrow-textarea> <events-list on-event-selected='eventSelected'></event-list>
</paper-input-decorator> </div>
<paper-button on-click={{clickFireEvent}}>Fire Event</paper-button>
</div>
<div class='sidebar'>
<b>Available events:</b>
<events-list cbEventClicked={{eventSelected}}></event-list>
</div> </div>
</div> </div>
</div> </partial-base>
</partial-base>
</template>
</dom-module>
</template>
<script> <script>
var eventActions = window.hass.eventActions; (function() {
var eventActions = window.hass.eventActions;
Polymer({ Polymer({
ready: function() { is: 'partial-dev-fire-event',
// to ensure callback methods work..
this.eventSelected = this.eventSelected.bind(this);
},
eventSelected: function(eventType) { properties: {
this.$.inputType.value = eventType; eventType: {
}, type: String,
value: '',
},
clickFireEvent: function() { eventData: {
try { type: String,
eventActions.fire( value: '',
this.$.inputType.value, },
this.$.inputData.value ? JSON.parse(this.$.inputData.value) : {}); },
} catch (err) {
alert("Error parsing JSON: " + err); eventSelected: function(ev) {
} this.eventType = ev.detail.eventType;
} },
});
clickFireEvent: function() {
var eventData;
try {
eventData = this.eventData ? JSON.parse(this.eventData) : {};
} catch (err) {
alert("Error parsing JSON: " + err);
return;
}
eventActions.fire(this.eventType, eventData);
},
computeFormClasses: function(narrow) {
return 'layout ' + (narrow ? 'vertical' : 'horizontal');
},
});
})();
</script> </script>
</polymer-element>

View File

@ -2,105 +2,109 @@
<link rel="import" href="../bower_components/paper-button/paper-button.html"> <link rel="import" href="../bower_components/paper-button/paper-button.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html"> <link rel="import" href="../bower_components/paper-input/paper-input.html">
<link rel="import" href="../bower_components/paper-input/paper-input-decorator.html"> <link rel="import" href="../bower_components/paper-input/paper-textarea.html">
<link rel="import" href="../bower_components/paper-input/paper-autogrow-textarea.html">
<link rel="import" href="./partial-base.html"> <link rel="import" href="./partial-base.html">
<link rel="import" href="../components/entity-list.html"> <link rel="import" href="../components/entity-list.html">
<polymer-element name="partial-dev-set-state" attributes="narrow togglePanel"> <dom-module id="partial-dev-set-state">
<template>
<style> <style>
.form { .form {
padding: 24px; padding: 24px;
background-color: white; background-color: white;
} }
.ha-form {
margin-right: 16px;
}
</style> </style>
<partial-base narrow="{{narrow}}" togglePanel="{{togglePanel}}"> <template>
<span header-title>Set State</span> <partial-base narrow="[[narrow]]">
<span header-title>Set State</span>
<div class='form' fit> <div class='form fit'>
<div> <div>
Set the representation of a device within Home Assistant.<br /> Set the representation of a device within Home Assistant.<br />
This will not communicate with the actual device. This will not communicate with the actual device.
</div>
<div layout horizontal?="{{!narrow}}" vertical?="{{narrow}}">
<div class='ha-form' flex?="{{!narrow}}">
<paper-input id="inputEntityID" label="Entity ID" floatingLabel="true" autofocus required></paper-input>
<paper-input id="inputState" label="State" floatingLabel="true" required></paper-input>
<paper-input-decorator
label="State attributes (JSON, optional)"
floatingLabel="true">
<paper-autogrow-textarea id="inputDataWrapper">
<textarea id="inputData"></textarea>
</paper-autogrow-textarea>
</paper-input-decorator>
<paper-button on-click={{clickSetState}}>Set State</paper-button>
</div> </div>
<div class='sidebar'> <div class$='[[computeFormClasses(narrow)]]'>
<b>Current entities:</b> <div class='ha-form flex'>
<entity-list cbEntityClicked={{entitySelected}}></entity-list> <paper-input label="Entity ID" autofocus required value='{{entityId}}'></paper-input>
<paper-input label="State" required value='{{state}}'></paper-input>
<paper-textarea label="State attributes (JSON, optional)" value='{{stateAttributes}}'></paper-textarea>
<paper-button on-click='handleSetState' raised>Set State</paper-button>
</div>
<div class='sidebar'>
<h4>Current entities:</h4>
<entity-list on-entity-selected='entitySelected'></entity-list>
</div>
</div> </div>
</div> </div>
</partial-base>
</template>
</dom-module>
</div>
</partial-base>
</template>
<script> <script>
var stateStore = window.hass.stateStore; (function() {
var stateActions = window.hass.stateActions; var stateStore = window.hass.stateStore;
var stateActions = window.hass.stateActions;
Polymer({ Polymer({
ready: function() { is: 'partial-dev-set-state',
// to ensure callback methods work..
this.entitySelected = this.entitySelected.bind(this);
},
setEntityId: function(entityId) { properties: {
this.$.inputEntityID.value = entityId; entityId: {
}, type: String,
value: '',
},
setState: function(state) { state: {
this.$.inputState.value = state; type: String,
}, value: '',
},
setStateData: function(stateData) { stateAttributes: {
var value = stateData ? JSON.stringify(stateData, null, ' ') : ""; type: String,
value: '',
},
},
this.$.inputData.value = value; setStateData: function(stateData) {
var value = stateData ? JSON.stringify(stateData, null, ' ') : "";
// not according to the spec but it works... this.$.inputData.value = value;
this.$.inputDataWrapper.update(this.$.inputData);
},
entitySelected: function(entityId) { // not according to the spec but it works...
this.setEntityId(entityId); this.$.inputDataWrapper.update(this.$.inputData);
},
var state = stateStore.get(entityId); entitySelected: function(ev) {
this.setState(state.state); var state = stateStore.get(ev.detail.entityId);
this.setStateData(state.attributes);
},
clickSetState: function(ev) { this.entityId = state.entityId;
try { this.state = state.state;
stateActions.set( this.stateAttributes = JSON.stringify(state.attributes, null, ' ');
this.$.inputEntityID.value, },
this.$.inputState.value,
this.$.inputData.value ? JSON.parse(this.$.inputData.value) : {} handleSetState: function() {
); var attr;
} catch (err) { try {
alert("Error parsing JSON: " + err); attr = this.stateAttributes ? JSON.parse(this.stateAttributes) : {};
} } catch (err) {
} alert("Error parsing JSON: " + err);
}); return;
}
stateActions.set(this.entityId, this.state, attr);
},
computeFormClasses: function(narrow) {
return 'layout ' + (narrow ? 'vertical' : 'horizontal');
},
});
})();
</script> </script>
</polymer-element>