From 71e7cf8d4fe86ae92fd0dc0a42e500c76603ea03 Mon Sep 17 00:00:00 2001 From: Sian Croser Date: Wed, 29 Apr 2020 04:53:46 +0930 Subject: [PATCH 1/2] Code cleanup and fireEvent added --- README.md | 2 +- src/helpers.js | 17 ++++++++++++++++- src/honeycomb-menu-item.js | 4 +--- src/honeycomb-menu.js | 16 +++++----------- src/xy-pad.js | 29 ++++++++++++----------------- 5 files changed, 35 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index fd37e58..3803599 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ styes { --honeycomb-menu-icon-active-color: var(--paper-item-icon-active-color); --honeycomb-menu-background-color: var(--paper-card-background-color); --honeycomb-menu-active-background-color: var(--paper-card-active-background-color, var(--paper-card-background-color)); - --honeycomb-menu-disabled: #9a9a9a6e + --honeycomb-menu-disabled: #9a9a9a6e; } ``` diff --git a/src/helpers.js b/src/helpers.js index 885ebd7..3e79bca 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -4,10 +4,25 @@ * @Email: CQoute@gmail.com * @Filename: helpers.js * @Last modified by: Sian Croser - * @Last modified time: 2020-04-26T07:33:31+09:30 + * @Last modified time: 2020-04-29T04:40:46+09:30 * @License: GPL-3 */ +export function fireEvent( _node, _event, _detail = {}, _options = {}) +{ + const event = new Event( _event, Object.assign( {}, { + bubbles: true, + cancelable: false, + composed: true + }, _options) ); + + event.detail = _detail; + + _node.dispatchEvent(event); + + return event; +} + export function evalTemplate(hass, state, func) { try { diff --git a/src/honeycomb-menu-item.js b/src/honeycomb-menu-item.js index 683d3fc..4948746 100644 --- a/src/honeycomb-menu-item.js +++ b/src/honeycomb-menu-item.js @@ -4,12 +4,10 @@ * @Email: CQoute@gmail.com * @Filename: comb.js * @Last modified by: Sian Croser - * @Last modified time: 2020-04-27T06:55:33+09:30 + * @Last modified time: 2020-04-29T04:21:19+09:30 * @License: GPL-3 */ -var cardTools = customElements.get('card-tools'); - class HoneycombMenuItem extends Polymer.Element { static get is() diff --git a/src/honeycomb-menu.js b/src/honeycomb-menu.js index 34fa757..35daea2 100644 --- a/src/honeycomb-menu.js +++ b/src/honeycomb-menu.js @@ -4,7 +4,7 @@ * @Email: CQoute@gmail.com * @Filename: honeycomb-menu.js * @Last modified by: Sian Croser - * @Last modified time: 2020-04-27T15:19:26+09:30 + * @Last modified time: 2020-04-29T04:43:12+09:30 * @License: GPL-3 */ @@ -13,7 +13,7 @@ const _ = require('lodash'); import EventManager from './event-manager.js'; import "./honeycomb-menu-item.js"; import "./xy-pad.js"; -import { objectEvalTemplate } from "./helpers.js"; +import { objectEvalTemplate, fireEvent } from "./helpers.js"; // Hook / Hack the HaCard to handle our needs and allow instantiating the hoeycomb customElements.whenDefined('ha-card').then(() => { @@ -326,7 +326,7 @@ class HoneycombMenu extends Polymer.Element this._setCssVars(); } - close( _item ) + close( _item = null ) { if( this.closing ) return; @@ -335,20 +335,14 @@ class HoneycombMenu extends Polymer.Element if( _item ) _item.setAttribute('selected', ''); - var details = { - detail: { - item: _item || false - } - }; - - this.dispatchEvent( new CustomEvent('closing', details) ); + fireEvent(this, 'closing', { item: _item }); // Remove shade div earlier to allow clicking of other lovelace elements while the animation continues this.$.shade.addEventListener('animationend', function(e) { this.remove(); }); this.shadowRoot.querySelectorAll('honeycomb-menu-item')[5].addEventListener('animationend', e => { this.remove(); - this.dispatchEvent( new CustomEvent('closed', details) ); + fireEvent(this, 'closed', { item: _item }); }); } diff --git a/src/xy-pad.js b/src/xy-pad.js index b6a3704..65534e4 100644 --- a/src/xy-pad.js +++ b/src/xy-pad.js @@ -4,10 +4,12 @@ * @Email: CQoute@gmail.com * @Filename: xy_pad.js * @Last modified by: Sian Croser - * @Last modified time: 2020-04-24T06:34:31+09:30 + * @Last modified time: 2020-04-29T04:50:53+09:30 * @License: GPL-3 */ +import { fireEvent } from "./helpers.js"; + class XYPad extends Polymer.Element { static get is() @@ -120,11 +122,11 @@ class XYPad extends Polymer.Element this.active = true; this.style.zIndex = 100; - this.dispatchEvent( this.__constructEvent('drag-start') ); + fireEvent(this, 'drag-start', this.__eventData()); if( this.config.repeat ) this._interval = setInterval(e => { - this.dispatchEvent( this.__constructEvent('drag-interval') ); + fireEvent(this, 'drag-interval', this.__eventData()); }, this.config.repeat); } @@ -137,7 +139,7 @@ class XYPad extends Polymer.Element this.$.joystick.style.transform = `translate3d(${this._current.x}px, ${this._current.y}px, 0)`; - this.dispatchEvent( this.__constructEvent('drag') ); + fireEvent(this, 'drag', this.__eventData()); } _handleOnDrag(e) @@ -159,26 +161,19 @@ class XYPad extends Polymer.Element _handleOnDragEnd(e) { - this.dispatchEvent( this.__constructEvent('drag-end') ); + fireEvent(this, 'drag-end', this.__eventData()); this._reset(); } - __constructEvent( _name ) - { - return new CustomEvent(_name, this.__constructEventData() ); - } - - __constructEventData() + __eventData() { let x = (this.config.x && this.config.x.invert) ? -(this._current.x) : this._current.x; let y = (this.config.y && this.config.y.invert) ? -(this._current.y) : this._current.y; return { - detail: { - x: x, - y: y, - x_percentage: x / this.clampX * 100, - y_percentage: y / this.clampY * 100 - } + x: x, + y: y, + x_percentage: x / this.clampX * 100, + y_percentage: y / this.clampY * 100 }; } }; From eb1ed8ec3dbb6c82e52c302c40c506369fe4c0d8 Mon Sep 17 00:00:00 2001 From: Sian Croser Date: Thu, 30 Apr 2020 16:18:26 +0930 Subject: [PATCH 2/2] Added a inheritance system --- README.md | 72 ++++++++++++++++++++++++++++++++++---- package.json | 2 +- src/helpers.js | 8 ++--- src/honeycomb-menu-item.js | 27 ++++++++------ src/honeycomb-menu.js | 56 ++++++++++++++++++++--------- 5 files changed, 126 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 3803599..a502a05 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ The module uses a hierarchy override for honeycomb options and sub options so yo ## Requirements 1. [Card Tools](https://github.com/thomasloven/lovelace-card-tools) +1. [button-card](https://github.com/custom-cards/button-card) ## How to install 1. Download the [module](https://github.com/Sian-Lee-SA/honeycomb-menu/releases) @@ -55,8 +56,8 @@ Option | Values | Default | Details -- | - |- |- action | `'tap' \| 'hold' \| 'double_tap'` | `hold` | Define the action that will activate the honeycomb menu (the action is bound to the card). It maybe wise to ensure this action doesn't bubble that will execute the cards default action; so for [custom:button-card](https://github.com/custom-cards/button-card) just make sure the options for that card doesn't conflict with same action that opens honeycomb unless you have unique reasons to do so. entity | `str:entity_id` | `card:entity` | This will call actions on the entity (entity_id) defined. If omitted then the card entity will be used. -template_buttons | _list[0-5]_: [Button](#button-options) `\| 'break'` | `null` | if using template or card options then this will allow the use of both card and template button configs. `break` will disable the honeycomb on the index. -buttons | _list[0-5]_: [Button](#button-options) `\| 'skip' \| 'break'` | `null \| template_buttons` | The buttons are your honeycombs :grinning:. There are a max of 6 buttons that you can define. _* note: list indexes start at `0`_. Matching indexes with **template_buttons** will be overridden. Using the string `skip` on an index will use the `template_button` for that index and the string `break` will instead disable that honeycomb position regardless of the `template_button` value for that index. +template | `str:template_name` | `null` | If templated has been added to your lovelace config, then this options will merge with the menu. The higher up on the hierarchy takes precedence. For more info see [Inheritance](#inheritance). +buttons | _list[0-5]_: [Button](#button-options) `\| 'skip' \| 'break'` | `null` | The buttons are your honeycombs :grinning:. There are a max of 6 buttons that you can define. _* note: list indexes start at `0`_. Matching indexes with inherited buttons will be overridden. Using the string `skip` on an inherited index will use the inherited button for that index. The string `break` will instead disable that honeycomb position regardless any inheritance. active | `boolean` | `false` | Setting this to true will apply active styles based on the entity it's assigned to autoclose | `boolean` | `true` | Close the menu if a button is pressed audio | `str:url_path` | `null` | Point to a audio file that will play when a button has been tapped @@ -68,15 +69,16 @@ spacing | `int:px` | `2` | This will assign the padding in px for each honeycomb Option | Values | Default | Details -- | - | - | - -type | `any:card` | `custom:button-card` | The base card to use for the button **Be sure to set the underlying card to 100% height or it may not display correctly** active | `boolean` | `honeycomb:active` | Override the honeycomb active property for this button item autoclose | `boolean` | `honeycomb:autoclose` | Override the honeycomb autoclose property for this button audio | `str:url_path` | `honeycomb:audio` | Override the honeycomb audio property for this button entity | `str:entity_id` | `honeycomb:entity` | You can define the entity that this button targets. Omitted will resort to the honeycombs entity. icon | `str:icon` | `null` | Only adding here for reference to custom:button-card so you can show an icon for the item -color | `str:css_color` | `var(--honeycomb-menu-icon-color)` | Color of icon or background (depending on custom:button-card config). Leaving the default value allows the theme to handle the color +color | `str:css_color` | `var(--honeycomb-menu-icon-color)` | Color of icon. Leaving the default value allows the theme to handle the color show_name | `boolean` | `false` | Only relevant for cards that support this option -Any other options for `Button:type` | - | - | - +tap_action | [Action](https://github.com/custom-cards/button-card#action) | `null` | Assign the action to take if this button has been tapped +hold_action | [Action](https://github.com/custom-cards/button-card#action) | `null` | Assign the action to take if this button has been held +double_tap_action | [Action](https://github.com/custom-cards/button-card#action) | `null` | Assign the action to take if this button has been tapped twice quickly ## `XYPad` Options @@ -100,6 +102,64 @@ invert | `boolean` | `false` | x or y will swap negative and positive values so service | `str:service` | `null` | The service to call eg. light.turn_on. If this value is omitted then the ball pin will have no effect on this axis service_data | `dict` | `null` | Provide any service data as a dictionary / object. This property will be processed through the template system allowing access to variables and javascript. See [Templating](#templating). +## Inheritance + +You may add templates for your honeycomb menu to inherit from. A template can also derive from another template and so on. Add `honeycomb_menu_templates` property to your lovelace config. + +Edit your lovelace yaml file +```yaml +title: Home Assistant +honeycomb_menu_templates: !include ../honeycomb-menu-templates.yaml +``` +To keep things neat and tidy, it's a good idea to include the templates from a separate file like shown above. + +Your templates can hold any value that `honeycomb:` accepts. The name of the template needs to be defined with the properties and values assigned to the template name. See below for an example of how to define a template and how the light template also inherits the base template. + +The example shows that both light and base have action assigned. The result will be action: hold because base in inherited which in turn gets overridden on matching values. `skip` and `break` are also valid buttons where skip will resort to it's inherited button value. +```yaml +base: + action: tap + +light: + template: base + action: hold + audio: /local/audio/pin-drop.ogg + xy_pad: + repeat: 500 + y: + invert: true + service: light.relative_brightnesss + service_data: + entity_id: entity + brightness: '[[[ return {{ y_percentage }} / 10; ]]]' + percentage: true + buttons: + - icon: 'mdi:lightbulb' + active: true + - icon: 'mdi:information-variant' + tap_action: + action: more-info + - icon: 'mdi:page-next' + autoclose: false + tap_action: + action: call-service + service: light.cycle_light_profile + service_data: + entity_id: entity +``` + +Once your templates are done, you can simply inherit them by adding template with the value being your template name to your honeycomb config. + +```yaml +type: custom:button-card +entity: light.livingroom_main +template: light +honeycomb: + template: light +``` + +If using button card or something similar with a template system then you could add honeycomb to the cards template instead. Keep in mind that Custom Button Card assigns their template values. So if adding a honeycomb to a card that has a template, then the honeycomb will assign the values instead of merging and may give undesired results. This is a result of how the developer designs their cards. + ## Theme Styles and Defaults Adding the following style properties to your theme `.yaml` file will override the defaults @@ -110,7 +170,7 @@ styes { --honeycomb-menu-icon-active-color: var(--paper-item-icon-active-color); --honeycomb-menu-background-color: var(--paper-card-background-color); --honeycomb-menu-active-background-color: var(--paper-card-active-background-color, var(--paper-card-background-color)); - --honeycomb-menu-disabled: #9a9a9a6e; + --honeycomb-menu-disabled: #9a9a9a6e; } ``` diff --git a/package.json b/package.json index 278aff4..7d242fa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "honeycomb-menu", - "version": "0.8.0", + "version": "0.8.9", "description": "Display a popup menu for Home Assistant lovelace cards via tap, hold or double tap", "scripts": { "build": "webpack", diff --git a/src/helpers.js b/src/helpers.js index 3e79bca..b9a3eea 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -3,18 +3,18 @@ * @Date: 2020-04-23T02:41:27+09:30 * @Email: CQoute@gmail.com * @Filename: helpers.js - * @Last modified by: Sian Croser - * @Last modified time: 2020-04-29T04:40:46+09:30 + * @Last modified by: Sian Croser + * @Last modified time: 2020-04-29T05:08:15+09:30 * @License: GPL-3 */ export function fireEvent( _node, _event, _detail = {}, _options = {}) { - const event = new Event( _event, Object.assign( {}, { + const event = new Event( _event, Object.assign({ bubbles: true, cancelable: false, composed: true - }, _options) ); + }, _options)); event.detail = _detail; diff --git a/src/honeycomb-menu-item.js b/src/honeycomb-menu-item.js index 4948746..5ca1321 100644 --- a/src/honeycomb-menu-item.js +++ b/src/honeycomb-menu-item.js @@ -3,8 +3,8 @@ * @Date: 2020-04-19T19:45:08+09:30 * @Email: CQoute@gmail.com * @Filename: comb.js - * @Last modified by: Sian Croser - * @Last modified time: 2020-04-29T04:21:19+09:30 + * @Last modified by: Sian Croser + * @Last modified time: 2020-04-30T16:16:53+09:30 * @License: GPL-3 */ @@ -47,6 +47,7 @@ class HoneycombMenuItem extends Polymer.Element return Polymer.html`