Skip to content

Commit

Permalink
Support for long press / hold action (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
RomRider authored and iantrich committed Apr 21, 2019
1 parent 1d744b8 commit 92b1dc9
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 15 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Lovelace Button card for your entities.
## Features

- works with any toggleable entity
- 5 actions on tap `none`, `toggle`, `more-info`, `navigate` and `call-service`
- 6 available actions on **tap** and/or **hold**: `none`, `toggle`, `more-info`, `navigate`, `url` and `call-service`
- state display (optional)
- custom color (optional), or based on light rgb value
- custom state definition with customizable color, icon and style (optional)
Expand Down Expand Up @@ -46,7 +46,8 @@ Lovelace Button card for your entities.
| `color_type` | string | `icon` | `icon` \| `card` \| `blank-card` \| `label-card` | Color either the background of the card or the icon inside the card. Setting this to `card` enable automatic `font` and `icon` color. This allows the text/icon to be readable even if the background color is bright/dark. Additional color-type options `blank-card` and `label-card` can be used for organisation (see examples). |
| `color` | string | optional | `auto` \| `rgb(28, 128, 199)` | Color of the icon/card. `auto` sets the color based on the color of a light. By default, if the entity state is `off`, the color will be `var(--paper-item-icon-active-color)`, for `on` it will be `var(--paper-item-icon-color)` and for any other state it will be `var(--primary-text-color)`. You can redefine each colors using `state` |
| `size` | string | `40%` | `20px` | Size of the icon. Can be percentage or pixel |
| `tap_action` | object | optional | See [Service](#Action) | Define the type of action, if undefined, toggle will be used. |
| `tap_action` | object | optional | See [Action](#Action) | Define the type of action on click, if undefined, toggle will be used. |
| `hold_action` | object | optional | See [Action](#Action) | Define the type of action on hold, if undefined, nothing happens. |
| `name` | string | optional | `Air conditioner` | Define an optional text to show below the icon |
| `show_name` | boolean | `true` | `true` \| `false` | Wether to show the name or not. Will pick entity_id's name by default, unless redefined in the `name` property or in any state `name` property |
| `show_state` | boolean | `false` | `true` \| `false` | Show the state on the card. defaults to false if not set |
Expand Down
39 changes: 26 additions & 13 deletions button-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,18 @@ export default function domainIcon(domain, state) {
`;
}

longpress(element) {
customElements.whenDefined("long-press").then(() => {
const longpress = document.body.querySelector("long-press");
longpress.bind(element);
});
return element;
}

firstUpdated() {
this.longpress(this.shadowRoot.querySelector('ha-card'));
}

render() {
const state = this.__hass.states[this.config.entity];
const configState = this.testConfigState(state, this.config)
Expand Down Expand Up @@ -387,7 +399,7 @@ export default function domainIcon(domain, state) {
clickable = false
}
} else {
clickable = !(config.tap_action.action == 'none')
clickable = (config.tap_action.action != 'none' || config.hold_action && config.hold_action.action != 'none')
}
return clickable;
}
Expand All @@ -412,7 +424,7 @@ export default function domainIcon(domain, state) {
const style = this.buildStyle(state, config, configState);
const name = this.buildName(state, configState);
return html`
<ha-card class="${this.isClickable(state, config) ? '' : "disabled"}" style="color: ${fontColor}; position: relative;" @tap="${ev => this._handleTap(state, config)}">
<ha-card class="${this.isClickable(state, config) ? '' : "disabled"}" style="color: ${fontColor}; position: relative;" @ha-click="${ev => this._handleTap(state, config, false)}" @ha-hold="${ev => this._handleTap(state, config, true)}">
<div class="button-card-background-color" style="background-color: ${color};">
<div class="button-card-main" style="${style}">
${config.show_icon && icon ? html`<ha-icon style="width: ${config.size}; height: auto;" icon="${icon}" class="${this.rotate(configState)}"></ha-icon>` : ''}
Expand All @@ -431,7 +443,7 @@ export default function domainIcon(domain, state) {
const style = this.buildStyle(state, config, configState);
const name = this.buildName(state, configState);
return html`
<ha-card class="${this.isClickable(state, config) ? '' : "disabled"}" style="color: ${fontColor}; position: relative;" @tap="${ev => this._handleTap(state, config)}">
<ha-card class="${this.isClickable(state, config) ? '' : "disabled"}" style="color: ${fontColor}; position: relative;" @ha-click="${ev => this._handleTap(state, config, false)}" @ha-hold="${ev => this._handleTap(state, config, true)}">
<div class="button-card-background-color" style="background-color: ${color};">
<div class="button-card-main" style="${style}">
${config.show_icon && icon ? html`<ha-icon style="width: ${config.size}; height: auto;" icon="${icon}" class="${this.rotate(configState)}"></ha-icon>` : ''}
Expand All @@ -450,7 +462,7 @@ export default function domainIcon(domain, state) {
const style = this.buildStyle(state, config, configState);
const name = this.buildName(state, configState);
return html`
<ha-card class="${this.isClickable(state, config) ? '' : "disabled"}" style="position: relative;" @tap="${ev => this._handleTap(state, config)}">
<ha-card class="${this.isClickable(state, config) ? '' : "disabled"}" style="position: relative;" @ha-click="${ev => this._handleTap(state, config, false)}" @ha-hold="${ev => this._handleTap(state, config, true)}">
<div class="button-card-main" style="${style}">
${config.show_icon && icon ? html`<ha-icon style="color: ${color}; width: ${config.size}; height: auto;" icon="${icon}" class="${this.rotate(configState)}"></ha-icon>` : ''}
${config.show_name && name ? html`<div>${name}</div>` : ''}
Expand Down Expand Up @@ -482,15 +494,16 @@ export default function domainIcon(domain, state) {
return 3;
}

_handleTap(state, config) {
_handleTap(state, config, hold) {
if (config.confirmation &&
!confirm("Confirm tap")) {
return;
}

if (config.tap_action) {
let action = hold ? config.hold_action : config.tap_action;
if (action) {
let event;
switch (config.tap_action.action) {
switch (action.action) {
case 'none':
break;
case 'more-info':
Expand All @@ -503,8 +516,8 @@ export default function domainIcon(domain, state) {
this.shadowRoot.dispatchEvent(event);
break;
case 'navigate':
if (!config.tap_action.navigation_path) break;
history.pushState(null, "", config.tap_action.navigation_path);
if (!action.navigation_path) break;
history.pushState(null, "", action.navigation_path);
event = new Event('location-changed', {
bubbles: true,
cancelable: false,
Expand All @@ -515,14 +528,14 @@ export default function domainIcon(domain, state) {
break;
case 'service':
case 'call-service':
if (!config.tap_action.service) {
if (!action.service) {
return;
}
const [domain, service] = config.tap_action.service.split('.', 2);
this.hass.callService(domain, service, config.tap_action.service_data);
const [domain, service] = action.service.split('.', 2);
this.hass.callService(domain, service, action.service_data);
break;
case 'url':
config.tap_action.url && window.open(config.tap_action.url);
action.url && window.open(action.url);
break;
case 'toggle':
default:
Expand Down

0 comments on commit 92b1dc9

Please sign in to comment.