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">
<template>
<style> <style>
:host { ul {
display: block; margin: 0;
padding: 0;
} }
.entityContainer { li {
font-size: 1rem; list-style: none;
line-height: 2em;
} }
</style>
<template if={{cbEntityClicked}}>
<style>
a { a {
text-decoration: underline; color: var(--accent-color);
cursor: pointer;
} }
</style> </style>
<template>
<ul>
<template is='dom-repeat' items='[[entities]]' as='entity'>
<li><a href='#' on-click='entitySelected'>[[entity]]</a></li>
</template> </template>
</ul>
<div>
<template repeat="{{entityID in entityIDs}}">
<div class='eventContainer'>
<a on-click={{handleClick}}>{{entityID}}</a>
</div>
</template> </template>
</dom-module>
</div> <script>
</template> (function() {
<script> Polymer({
var storeListenerMixIn = window.hass.storeListenerMixIn; is: 'entity-list',
Polymer(Polymer.mixin({ behaviors: [StoreListenerBehavior],
cbEventClicked: null,
entityIDs: [],
attached: function() { properties: {
this.listenToStores(true); entities: {
type: Array,
value: [],
}, },
detached: function() {
this.stopListeningToStores();
}, },
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">
<template>
<style> <style>
:host { ul {
display: block; margin: 0;
padding: 0;
} }
.eventContainer { li {
font-size: 1rem; list-style: none;
line-height: 2em;
} }
</style>
<template if={{cbEventClicked}}>
<style>
a { a {
text-decoration: underline; color: var(--accent-color);
cursor: pointer;
} }
</style> </style>
<template>
<ul>
<template is='dom-repeat' items='[[events]]' as='event'>
<li>
<a href='#' on-click='eventSelected'>{{event.event}}</a>
<span> (</span><span>{{event.listener_count}}</span><span> listeners)</span>
</li>
</template> </template>
</ul>
<div>
<template repeat="{{event in events}}">
<div class='eventContainer'>
<a on-click={{handleClick}}>{{event.event}}</a>
({{event.listener_count}} listeners)
</div>
</template> </template>
</dom-module>
</div> <script>
</template> (function() {
<script> Polymer({
var storeListenerMixIn = window.hass.storeListenerMixIn; is: 'events-list',
Polymer(Polymer.mixin({ behaviors: [StoreListenerBehavior],
cbEventClicked: null,
events: [],
attached: function() { properties: {
this.listenToStores(true); events: {
type: Array,
value: [],
}, },
detached: function() {
this.stopListeningToStores();
}, },
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>
:host { ul {
display: block; margin: 0;
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>
<div>
<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> </template>
</core-submenu> </ul>
</template> </template>
</dom-module>
</core-menu> <script>
(function() {
Polymer({
is: 'services-list',
</div> behaviors: [StoreListenerBehavior],
</template>
<script>
var storeListenerMixIn = window.hass.storeListenerMixIn;
Polymer(Polymer.mixin({ properties: {
domains: [], domains: {
services: null, type: Array,
cbServiceClicked: null, value: [],
attached: function() {
this.listenToStores(true);
}, },
detached: function() { services: {
this.stopListeningToStores(); type: Object,
},
}, },
getIcon: function(domain) { computeServices: 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;
} }
</style>
<partial-base narrow="{{narrow}}" togglePanel="{{togglePanel}}"> .ha-form {
margin-right: 16px;
}
</style>
<template>
<partial-base narrow="[[narrow]]">
<span header-title>Call Service</span> <span header-title>Call Service</span>
<div class='form' fit> <div class='form fit'>
<p> <p>
Call a service from a component. Call a service from a component.
</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 id="inputDomain" label="Domain" floatingLabel="true" autofocus required></paper-input> <paper-input label="Domain" autofocus value='{{domain}}'></paper-input>
<paper-input id="inputService" label="Service" floatingLabel="true" required></paper-input> <paper-input label="Service" value='{{service}}'></paper-input>
<paper-input-decorator <paper-textarea label="Service Data (JSON, optional)" value='{{serviceData}}'></paper-textarea>
label="Service Data (JSON, optional)" <paper-button on-click='callService' raised>Call Service</paper-button>
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>
<div class='sidebar'> <div>
<b>Available services:</b> <h4>Available services:</h4>
<services-list cbServiceClicked={{serviceSelected}}></services-list> <services-list on-service-selected='serviceSelected'></services-list>
</div> </div>
</div> </div>
</div> </div>
</partial-base> </partial-base>
</template>
</dom-module>
</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); properties: {
narrow: {
type: Boolean,
value: false,
}, },
setService: function(domain, service) { domain: {
this.$.inputDomain.value = domain; type: String,
this.$.inputService.value = service; value: '',
}, },
serviceSelected: function(domain, service) { service: {
this.setService(domain, service); type: String,
value: '',
}, },
clickCallService: function() { serviceData: {
type: String,
value: '',
},
},
serviceSelected: function(ev) {
this.domain = ev.detail.domain;
this.service = ev.detail.service;
},
callService: function() {
var serviceData;
try { try {
serviceActions.callService( serviceData = this.serviceData ? JSON.parse(this.serviceData): {};
this.$.inputDomain.value,
this.$.inputService.value,
this.$.inputData.value ? JSON.parse(this.$.inputData.value) : {});
} catch (err) { } catch (err) {
alert("Error parsing JSON: " + 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>
<partial-base narrow="{{narrow}}">
<span header-title>Fire Event</span> <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
label="Event Data (JSON, optional)"
floatingLabel="true">
<paper-autogrow-textarea id="inputDataWrapper">
<textarea id="inputData"></textarea>
</paper-autogrow-textarea>
</paper-input-decorator>
<paper-button on-click={{clickFireEvent}}>Fire Event</paper-button>
</div> </div>
<div class='sidebar'> <div>
<b>Available events:</b> <h4>Available events:</h4>
<events-list cbEventClicked={{eventSelected}}></event-list> <events-list on-event-selected='eventSelected'></event-list>
</div> </div>
</div> </div>
</div> </div>
</partial-base> </partial-base>
</template> </template>
<script> </dom-module>
var eventActions = window.hass.eventActions;
Polymer({ <script>
ready: function() { (function() {
// to ensure callback methods work.. var eventActions = window.hass.eventActions;
this.eventSelected = this.eventSelected.bind(this);
Polymer({
is: 'partial-dev-fire-event',
properties: {
eventType: {
type: String,
value: '',
}, },
eventSelected: function(eventType) { eventData: {
this.$.inputType.value = eventType; type: String,
value: '',
},
},
eventSelected: function(ev) {
this.eventType = ev.detail.eventType;
}, },
clickFireEvent: function() { clickFireEvent: function() {
var eventData;
try { try {
eventActions.fire( eventData = this.eventData ? JSON.parse(this.eventData) : {};
this.$.inputType.value,
this.$.inputData.value ? JSON.parse(this.$.inputData.value) : {});
} catch (err) { } catch (err) {
alert("Error parsing JSON: " + 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,75 +2,75 @@
<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>
<partial-base narrow="[[narrow]]">
<span header-title>Set State</span> <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>
<div layout horizontal?="{{!narrow}}" vertical?="{{narrow}}"> <div class$='[[computeFormClasses(narrow)]]'>
<div class='ha-form' flex?="{{!narrow}}"> <div class='ha-form flex'>
<paper-input id="inputEntityID" label="Entity ID" floatingLabel="true" autofocus required></paper-input> <paper-input label="Entity ID" autofocus required value='{{entityId}}'></paper-input>
<paper-input id="inputState" label="State" floatingLabel="true" required></paper-input> <paper-input label="State" required value='{{state}}'></paper-input>
<paper-input-decorator <paper-textarea label="State attributes (JSON, optional)" value='{{stateAttributes}}'></paper-textarea>
label="State attributes (JSON, optional)" <paper-button on-click='handleSetState' raised>Set State</paper-button>
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='sidebar'>
<b>Current entities:</b> <h4>Current entities:</h4>
<entity-list cbEntityClicked={{entitySelected}}></entity-list> <entity-list on-entity-selected='entitySelected'></entity-list>
</div> </div>
</div> </div>
</div> </div>
</partial-base> </partial-base>
</template>
</dom-module>
</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); properties: {
entityId: {
type: String,
value: '',
}, },
setEntityId: function(entityId) { state: {
this.$.inputEntityID.value = entityId; type: String,
value: '',
}, },
setState: function(state) { stateAttributes: {
this.$.inputState.value = state; type: String,
value: '',
},
}, },
setStateData: function(stateData) { setStateData: function(stateData) {
@ -82,25 +82,29 @@ Polymer({
this.$.inputDataWrapper.update(this.$.inputData); this.$.inputDataWrapper.update(this.$.inputData);
}, },
entitySelected: function(entityId) { entitySelected: function(ev) {
this.setEntityId(entityId); var state = stateStore.get(ev.detail.entityId);
var state = stateStore.get(entityId); this.entityId = state.entityId;
this.setState(state.state); this.state = state.state;
this.setStateData(state.attributes); this.stateAttributes = JSON.stringify(state.attributes, null, ' ');
}, },
clickSetState: function(ev) { handleSetState: function() {
var attr;
try { try {
stateActions.set( attr = this.stateAttributes ? JSON.parse(this.stateAttributes) : {};
this.$.inputEntityID.value,
this.$.inputState.value,
this.$.inputData.value ? JSON.parse(this.$.inputData.value) : {}
);
} catch (err) { } catch (err) {
alert("Error parsing JSON: " + 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>