From f146a1d80f5b956cb0c8cbaea6ab8d47ad6cc091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Wed, 17 Oct 2018 22:16:17 +0200 Subject: [PATCH] Lovelace: Allow press-and-hold on picture-elements elements. (#1745) * Allow press-and-hold on picture-elements elements. --- package.json | 1 + .../cards/hui-picture-elements-card.js | 3 - .../lovelace/elements/hui-icon-element.js | 12 ++- .../lovelace/elements/hui-image-element.js | 6 +- .../elements/hui-state-icon-element.js | 12 ++- .../elements/hui-state-label-element.js | 4 +- .../lovelace/mixins/element-click-mixin.js | 84 ++++++++++++++++++- yarn.lock | 42 ++++++++++ 8 files changed, 139 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 6d4d4bafde..d3366ce751 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "author": "Paulus Schoutsen (http://paulusschoutsen.nl)", "license": "Apache-2.0", "dependencies": { + "@material/mwc-ripple": "^0.3.1", "@mdi/svg": "^2.7.94", "@polymer/app-layout": "^3.0.1", "@polymer/app-localize-behavior": "^3.0.1", diff --git a/src/panels/lovelace/cards/hui-picture-elements-card.js b/src/panels/lovelace/cards/hui-picture-elements-card.js index 1bb7b9efc9..2dc138bf7b 100644 --- a/src/panels/lovelace/cards/hui-picture-elements-card.js +++ b/src/panels/lovelace/cards/hui-picture-elements-card.js @@ -22,9 +22,6 @@ class HuiPictureElementsCard extends PolymerElement { position: absolute; transform: translate(-50%, -50%); } - hui-image-element { - overflow-y: hidden; - } diff --git a/src/panels/lovelace/elements/hui-icon-element.js b/src/panels/lovelace/elements/hui-icon-element.js index 3a907e515b..2606bcb184 100644 --- a/src/panels/lovelace/elements/hui-icon-element.js +++ b/src/panels/lovelace/elements/hui-icon-element.js @@ -13,13 +13,13 @@ class HuiIconElement extends ElementClickMixin(PolymerElement) { return html` - + > `; } @@ -32,9 +32,7 @@ class HuiIconElement extends ElementClickMixin(PolymerElement) { ready() { super.ready(); - this.addEventListener("click", () => - this.handleClick(this.hass, this._config) - ); + this.registerMouse(this._config); } setConfig(config) { diff --git a/src/panels/lovelace/elements/hui-image-element.js b/src/panels/lovelace/elements/hui-image-element.js index b2823ed5f7..978414ecef 100644 --- a/src/panels/lovelace/elements/hui-image-element.js +++ b/src/panels/lovelace/elements/hui-image-element.js @@ -14,9 +14,11 @@ class HuiImageElement extends ElementClickMixin(PolymerElement) { - this.handleClick(this.hass, this._config) - ); + this.registerMouse(this._config); } setConfig(config) { diff --git a/src/panels/lovelace/elements/hui-state-icon-element.js b/src/panels/lovelace/elements/hui-state-icon-element.js index ac835513f8..398d98f868 100644 --- a/src/panels/lovelace/elements/hui-state-icon-element.js +++ b/src/panels/lovelace/elements/hui-state-icon-element.js @@ -13,13 +13,13 @@ class HuiStateIconElement extends ElementClickMixin(PolymerElement) { return html` - + > `; } @@ -36,9 +36,7 @@ class HuiStateIconElement extends ElementClickMixin(PolymerElement) { ready() { super.ready(); - this.addEventListener("click", () => - this.handleClick(this.hass, this._config) - ); + this.registerMouse(this._config); } setConfig(config) { diff --git a/src/panels/lovelace/elements/hui-state-label-element.js b/src/panels/lovelace/elements/hui-state-label-element.js index e33d711eba..f66fa128c1 100644 --- a/src/panels/lovelace/elements/hui-state-label-element.js +++ b/src/panels/lovelace/elements/hui-state-label-element.js @@ -45,9 +45,7 @@ class HuiStateLabelElement extends LocalizeMixin( ready() { super.ready(); - this.addEventListener("click", () => - this.handleClick(this.hass, this._config) - ); + this.registerMouse(this._config); } setConfig(config) { diff --git a/src/panels/lovelace/mixins/element-click-mixin.js b/src/panels/lovelace/mixins/element-click-mixin.js index 639c2b4e8b..cc2022019e 100644 --- a/src/panels/lovelace/mixins/element-click-mixin.js +++ b/src/panels/lovelace/mixins/element-click-mixin.js @@ -3,6 +3,7 @@ import toggleEntity from "../common/entity/toggle-entity.js"; import NavigateMixin from "../../../mixins/navigate-mixin"; import EventsMixin from "../../../mixins/events-mixin.js"; import computeStateName from "../../../common/entity/compute_state_name"; +import "@material/mwc-ripple"; /* * @polymerMixin @@ -12,8 +13,87 @@ import computeStateName from "../../../common/entity/compute_state_name"; export default dedupingMixin( (superClass) => class extends NavigateMixin(EventsMixin(superClass)) { - handleClick(hass, config) { - const tapAction = config.tap_action || "more-info"; + registerMouse(config) { + var isTouch = + "ontouchstart" in window || + navigator.MaxTouchPoints > 0 || + navigator.msMaxTouchPoints > 0; + + let ripple = null; + const rippleWrapper = document.createElement("div"); + this.shadowRoot.appendChild(rippleWrapper); + Object.assign(rippleWrapper.style, { + position: "absolute", + width: isTouch ? "100px" : "50px", + height: isTouch ? "100px" : "50px", + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + pointerEvents: "none", + }); + + const loadRipple = () => { + if (ripple) return; + ripple = document.createElement("mwc-ripple"); + rippleWrapper.appendChild(ripple); + ripple.unbounded = true; + ripple.primary = true; + }; + const startAnimation = () => { + ripple.style.visibility = "visible"; + ripple.disabled = false; + ripple.active = true; + }; + const stopAnimation = () => { + if (ripple) { + ripple.active = false; + ripple.disabled = true; + ripple.style.visibility = "hidden"; + } + }; + + var mouseDown = isTouch ? "touchstart" : "mousedown"; + var mouseOut = isTouch ? "touchcancel" : "mouseout"; + var click = isTouch ? "touchend" : "click"; + + var timer = null; + var held = false; + var holdTime = config.hold_time || 500; + + this.addEventListener(mouseDown, () => { + held = false; + loadRipple(); + timer = setTimeout(() => { + startAnimation(); + held = true; + }, holdTime); + }); + + this.addEventListener(click, () => { + stopAnimation(); + this.handleClick(this.hass, config, held); + }); + + [ + mouseOut, + "mouseup", + "touchmove", + "mousewheel", + "wheel", + "scroll", + ].forEach((ev) => { + document.addEventListener(ev, () => { + clearTimeout(timer); + stopAnimation(); + }); + }); + } + + handleClick(hass, config, held = false) { + let tapAction = config.tap_action || "more-info"; + if (held) { + tapAction = config.hold_action || "none"; + } if (tapAction === "none") return; switch (tapAction) { diff --git a/yarn.lock b/yarn.lock index 14d75ba2f9..05917754b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1266,6 +1266,48 @@ dependencies: base64-js "^1.3.0" +"@material/animation@^0.40.1": + version "0.40.1" + resolved "https://registry.yarnpkg.com/@material/animation/-/animation-0.40.1.tgz#c5ff31e7d7e17324a0045e889d3530b150b9fcec" + integrity sha512-HtxFUw04EHg4S6pXfTA3Z0wKxnNDNcDhe1Np2Y2geo+lAk2Hb7m8yCL/GaL9o2I/eRYsgUXC0U7+Mk74GCz3zw== + +"@material/base@^0.40.1": + version "0.40.1" + resolved "https://registry.yarnpkg.com/@material/base/-/base-0.40.1.tgz#a0d8e19cee98dae0f96dbf0887a14b3f7acd2aac" + integrity sha512-vrbOK8hONVCYgURQ9h7nkXvMdYnZVVNmAfFFijF8fbWQdwnoPcNTdqV6RoQlhBEqHYHQqLNfdUDlznAPKLclGQ== + +"@material/mwc-base@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@material/mwc-base/-/mwc-base-0.3.1.tgz#5e1440aa09e0a83633be36eb8102ff88d3fddae8" + integrity sha512-7AdcBu6rxARcUteEBNSJKCen3hP47T/NRsfw+RMn6IedHlEGp2GKwF6YqYDCVSsQbm0IjsJ4ft4+nVXlFVYO2g== + dependencies: + "@polymer/lit-element" "^0.6.2" + lit-html "^0.12.0" + +"@material/mwc-ripple@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@material/mwc-ripple/-/mwc-ripple-0.3.1.tgz#da812516d0bd0b15b0c4793b783fbdb9e04cd7a0" + integrity sha512-pOdBkP6NJyGz9UftvKjrx8sXvz+yIXMC8q6Qx/LgGw67tgU4qM/1Hy22iePiw1UFNhlqD8ZwtdPLXKVaisGauQ== + dependencies: + "@material/mwc-base" "^0.3.1" + "@material/ripple" "^0.40.0" + "@polymer/lit-element" "^0.6.2" + lit-html "^0.12.0" + +"@material/ripple@^0.40.0": + version "0.40.1" + resolved "https://registry.yarnpkg.com/@material/ripple/-/ripple-0.40.1.tgz#57cbc689303b48282229cb9b62556af7442e852a" + integrity sha512-sndeTS4VHa0v1UGj7MNcxMCuO9LJ1DjoL1EjE6BH3Lm3M1MnXJHdsBo2CgPbU/FI84tt6+eyHGOYPdPrEDJhCA== + dependencies: + "@material/animation" "^0.40.1" + "@material/base" "^0.40.1" + "@material/theme" "^0.40.1" + +"@material/theme@^0.40.1": + version "0.40.1" + resolved "https://registry.yarnpkg.com/@material/theme/-/theme-0.40.1.tgz#3cc3f1bf87ee9581df03e347a1979e53ae617221" + integrity sha512-cH1CsGIDisEQ2oroZhLTypV0Ir00x3WIwFXnPo7qv3832tuIDkZY623U3rUax6KNPz4Hh1j0tNpTwgrNZwvwWA== + "@mdi/svg@^2.7.94": version "2.8.94" resolved "https://registry.yarnpkg.com/@mdi/svg/-/svg-2.8.94.tgz#574da5953fb8ccd58b660d95061d43add53f5704"