Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pressed and released event to allow usage as momentary button #360

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Lovelace Button card for your entities.
## Features

- works with any toggleable entity
- 6 available actions on **tap** and/or **hold** and/or **double click**: `none`, `toggle`, `more-info`, `navigate`, `url` and `call-service`
- 6 available actions on **tap** and/or **hold** and/or **double click** and/or **press**and/or **release**: `none`, `toggle`, `more-info`, `navigate`, `url` and `call-service`
- state display (optional)
- custom color (optional), or based on light rgb value/temperature
- custom state definition with customizable color, icon and style (optional)
Expand Down Expand Up @@ -101,6 +101,8 @@ Lovelace Button card for your entities.
| `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. |
| `double_tap_action` | object | optional | See [Action](#Action) | Define the type of action on double click, if undefined, nothing happens. |
| `press_action` | object | optional | See [Action](#Action) | Define the type of action on press (triggers the moment your finger presses the button), if undefined, nothing happens. |
| `release_action` | object | optional | See [Action](#Action) | Define the type of action on releasing the button, if undefined, nothing happens. |
| `name` | string | optional | `Air conditioner` | Define an optional text to show below the icon. Supports templates, see [templates](#javascript-templates) |
| `state_display` | string | optional | `On` | Override the way the state is displayed. Supports templates, see [templates](#javascript-templates) |
| `label` | string | optional | Any string that you want | Display a label below the card. See [Layouts](#layout) for more information. Supports templates, see [templates](#javascript-templates) |
Expand All @@ -124,7 +126,6 @@ Lovelace Button card for your entities.
| `variables` | object | optional | See [Variables](#Variables) |
| `card_size` | number | 3 | Any number | Configure the card size seen by the auto layout feature of lovelace (lovelace will multiply the value by about 50px) |
| `tooltip` | string | optional | Any string | (Not supported on touchscreens) You can configure the tooltip displayed after hovering the card for 1.5 seconds . Supports templates, see [templates](#javascript-templates) |

### Action

All the fields support templates, see [templates](#javascript-templates).
Expand Down Expand Up @@ -750,7 +751,7 @@ Examples are better than a long text, so here you go:

#### General

- Define your config template in the main lovelace configuration and then use it in your button-card. This will avoid a lot of repetitions! It's basically YAML anchors, but without using YAML anchors and is very useful if you split your config in multiple files 😄
- Define your config template in the main lovelace configuration and then use it in your button-card. This will avoid a lot of repetitions! It's basically YAML anchors, but without using YAML anchors and is very useful if you split your config in multiple files 😄
- You can overload any parameter with a new one
- You can merge states together **by `id`** when using templates. The states you want to merge have to have the same `id`. This `id` parameter is new and can be anything (string, number, ...). States without `id` will be appended to the state array. Styles embedded in a state are merged together as usual. See [here](#merging-state-by-id) for an example.
- You can also inherit another template from within a template.
Expand All @@ -768,7 +769,7 @@ Examples are better than a long text, so here you go:
Make sure which type of lovelace dashboard you are using before changing the main lovelace configuration:
* **`managed`** changes are managed by lovelace ui - add the template configuration to configuration in raw editor
* go to your dashboard
* click three dots and `Edit dashboard` button
* click three dots and `Edit dashboard` button
* click three dots again and click `Raw configuration editor` button
* **`yaml`** - add template configuration to your `ui-lovelace.yaml`

Expand Down
4 changes: 3 additions & 1 deletion src/action-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface ActionHandler extends HTMLElement {
}

export interface ActionHandlerDetail {
action: 'hold' | 'tap' | 'double_tap';
action: 'hold' | 'tap' | 'double_tap' | 'press' | 'release';
}

export interface ActionHandlerOptions {
Expand Down Expand Up @@ -132,6 +132,7 @@ class ActionHandler extends HTMLElement implements ActionHandler {
}

element.actionHandler.start = (ev: Event) => {
myFireEvent(element, 'action', { action: 'press' });
this.cancelled = false;
let x;
let y;
Expand Down Expand Up @@ -172,6 +173,7 @@ class ActionHandler extends HTMLElement implements ActionHandler {
if (ev.cancelable) {
ev.preventDefault();
}
myFireEvent(element, 'action', { action: 'release' });
if (options.hasHold) {
clearTimeout(this.timer);
if (this.isRepeating && this.repeatTimeout) {
Expand Down
37 changes: 36 additions & 1 deletion src/button-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
stateIcon,
HomeAssistant,
handleClick,
handleActionConfig,
getLovelace,
timerTimeRemaining,
secondsToDuration,
Expand Down Expand Up @@ -653,7 +654,15 @@ class ButtonCard extends LitElement {
const tap_action = this._getTemplateOrValue(state, this._config!.tap_action!.action);
const hold_action = this._getTemplateOrValue(state, this._config!.hold_action!.action);
const double_tap_action = this._getTemplateOrValue(state, this._config!.double_tap_action!.action);
if (tap_action != 'none' || hold_action != 'none' || double_tap_action != 'none') {
const press_action = this._getTemplateOrValue(state, this._config!.press_action!.action);
const release_action = this._getTemplateOrValue(state, this._config!.release_action!.action);
if (
tap_action != 'none' ||
hold_action != 'none' ||
double_tap_action != 'none' ||
press_action != 'none' ||
release_action != 'none'
) {
clickable = true;
} else {
clickable = false;
Expand Down Expand Up @@ -969,6 +978,8 @@ class ButtonCard extends LitElement {
group_expand: false,
hold_action: { action: 'none' },
double_tap_action: { action: 'none' },
press_action: { action: 'none' },
release_action: { action: 'none' },
layout: 'vertical',
size: '40%',
color_type: 'icon',
Expand Down Expand Up @@ -1117,6 +1128,12 @@ class ButtonCard extends LitElement {
private _handleAction(ev: any): void {
if (ev.detail?.action) {
switch (ev.detail.action) {
case 'press':
this._handlePress();
break;
case 'release':
this._handleRelease();
break;
case 'tap':
this._handleTap();
break;
Expand All @@ -1132,6 +1149,24 @@ class ButtonCard extends LitElement {
}
}

private _handlePress(): void {
const config = this._config;
if (!config) return;
const actionConfig = this._evalActions(config, 'press_action');
if (!actionConfig || !actionConfig.press_action) return;

handleActionConfig(this, this._hass!, actionConfig, actionConfig.press_action);
}

private _handleRelease(): void {
const config = this._config;
if (!config) return;
const actionConfig = this._evalActions(config, 'release_action');
if (!actionConfig || !actionConfig.release_action) return;

handleActionConfig(this, this._hass!, actionConfig, actionConfig.release_action);
}

private _handleTap(): void {
const config = this._config;
if (!config) return;
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export interface ButtonCardConfig {
tap_action?: ActionConfig;
hold_action?: ActionConfig;
double_tap_action?: ActionConfig;
press_action?: ActionConfig;
release_action?: ActionConfig;
show_name?: boolean;
show_state?: boolean;
show_icon?: boolean;
Expand Down