From 3e4d0b3a9d3cc8f66a1600eff484f5f7d0067c8a Mon Sep 17 00:00:00 2001 From: JRK Date: Mon, 4 Nov 2019 00:26:04 +0100 Subject: [PATCH 1/7] Remove forgotten console log --- src/button-card.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/button-card.ts b/src/button-card.ts index 24e825f..e769b18 100644 --- a/src/button-card.ts +++ b/src/button-card.ts @@ -929,6 +929,5 @@ class ButtonCard extends LitElement { private _stopPropagation(ev) { ev.stopPropagation(); - console.log('BRRRR'); } } From 029876fbb38c944153c1a80870be6affb2c499dc Mon Sep 17 00:00:00 2001 From: Gilles Callebaut Date: Wed, 27 Nov 2019 22:53:31 +0100 Subject: [PATCH 2/7] Added new holdReleased event `hold_released_action` --- src/button-card.ts | 6 ++++++ src/long-press.ts | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/button-card.ts b/src/button-card.ts index 24e825f..af8a725 100644 --- a/src/button-card.ts +++ b/src/button-card.ts @@ -654,6 +654,7 @@ class ButtonCard extends LitElement { style=${styleMap(cardStyle)} @ha-click="${this._handleTap}" @ha-hold="${this._handleHold}" + @ha-holdReleased="${this._handleHoldReleased}" @ha-dblclick=${this._handleDblTap} .hasDblClick=${this.config!.double_tap_action!.action !== 'none'} .repeat=${ifDefined(this.config!.hold_action!.repeat)} @@ -868,6 +869,11 @@ class ButtonCard extends LitElement { handleClick(this, this.hass!, this._evalActions(config, 'hold_action'), true, false); } + private _handleHoldReleased(ev): void { + const config = ev.target.config; + handleClick(this, this.hass!, this._evalActions(config, 'hold_released_action'), true, false); + } + private _handleDblTap(ev): void { const config = ev.target.config; handleClick(this, this.hass!, this._evalActions(config, 'double_tap_action'), false, true); diff --git a/src/long-press.ts b/src/long-press.ts index 39bbec5..7723edf 100644 --- a/src/long-press.ts +++ b/src/long-press.ts @@ -127,6 +127,9 @@ class LongPress extends HTMLElement implements LongPress { this.repeatTimeout = setInterval(() => { element.dispatchEvent(new Event('ha-hold')); }, element.repeat); + }else{ + // only fire onces when hold down is detected + element.dispatchEvent(new Event('ha-hold')); } }, this.holdTime); @@ -155,7 +158,7 @@ class LongPress extends HTMLElement implements LongPress { this.timer = undefined; if (this.held) { if (!element.repeat) { - element.dispatchEvent(new Event('ha-hold')); + element.dispatchEvent(new Event('ha-released')); } } else if (element.hasDblClick) { if (this.nbClicks === 0) { From 3b994972ba890069d54540c9feb550c03fb09ebb Mon Sep 17 00:00:00 2001 From: Gilles Callebaut Date: Wed, 27 Nov 2019 22:58:48 +0100 Subject: [PATCH 3/7] fixed wrong event name --- src/button-card.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/button-card.ts b/src/button-card.ts index af8a725..1d82fbe 100644 --- a/src/button-card.ts +++ b/src/button-card.ts @@ -654,7 +654,7 @@ class ButtonCard extends LitElement { style=${styleMap(cardStyle)} @ha-click="${this._handleTap}" @ha-hold="${this._handleHold}" - @ha-holdReleased="${this._handleHoldReleased}" + @ha-released="${this._handleHoldReleased}" @ha-dblclick=${this._handleDblTap} .hasDblClick=${this.config!.double_tap_action!.action !== 'none'} .repeat=${ifDefined(this.config!.hold_action!.repeat)} From 560a7c57e7b73409c38f02a79275944987aed764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Wiedemann?= Date: Fri, 3 Jan 2020 20:47:50 +0100 Subject: [PATCH 4/7] Fix iPad OS double clicks --- package-lock.json | 211 +++++++++++++++++++++++++--------------------- package.json | 5 +- src/long-press.ts | 15 ++-- src/styles.ts | 8 ++ 4 files changed, 130 insertions(+), 109 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3e52395..ef3b97f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1073,11 +1073,6 @@ "dev": true, "optional": true }, - "bowser": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.7.0.tgz", - "integrity": "sha512-aIlMvstvu8x+34KEiOHD3AsBgdrzg6sxALYiukOWhFvGMbQI6TRP/iY0LMhUrHs56aD6P1G0Z7h45PUJaa5m9w==" - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3395,12 +3390,12 @@ } }, "jest-worker": { - "version": "24.6.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.6.0.tgz", - "integrity": "sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", "dev": true, "requires": { - "merge-stream": "^1.0.1", + "merge-stream": "^2.0.0", "supports-color": "^6.1.0" }, "dependencies": { @@ -3618,13 +3613,10 @@ "optional": true }, "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true }, "merge2": { "version": "1.3.0", @@ -3822,9 +3814,9 @@ } }, "npm": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/npm/-/npm-6.12.0.tgz", - "integrity": "sha512-juj5VkB3/k+PWbJUnXD7A/8oc8zLusDnK/sV9PybSalsbOVOTIp5vSE0rz5rQ7BsmUgQS47f/L2GYQnWXaKgnQ==", + "version": "6.13.4", + "resolved": "https://registry.npmjs.org/npm/-/npm-6.13.4.tgz", + "integrity": "sha512-vTcUL4SCg3AzwInWTbqg1OIaOXlzKSS8Mb8kc5avwrJpcvevDA5J9BhYSuei+fNs3pwOp4lzA5x2FVDXACvoXA==", "dev": true, "requires": { "JSONStream": "^1.3.5", @@ -3833,12 +3825,12 @@ "ansistyles": "~0.1.3", "aproba": "^2.0.0", "archy": "~1.0.0", - "bin-links": "^1.1.3", + "bin-links": "^1.1.6", "bluebird": "^3.5.5", "byte-size": "^5.0.1", "cacache": "^12.0.3", "call-limit": "^1.1.1", - "chownr": "^1.1.2", + "chownr": "^1.1.3", "ci-info": "^2.0.0", "cli-columns": "^3.1.2", "cli-table3": "^0.5.1", @@ -3854,9 +3846,9 @@ "find-npm-prefix": "^1.0.2", "fs-vacuum": "~1.2.10", "fs-write-stream-atomic": "~1.0.10", - "gentle-fs": "^2.2.1", + "gentle-fs": "^2.3.0", "glob": "^7.1.4", - "graceful-fs": "^4.2.2", + "graceful-fs": "^4.2.3", "has-unicode": "~2.0.1", "hosted-git-info": "^2.8.5", "iferr": "^1.0.2", @@ -3869,7 +3861,7 @@ "is-cidr": "^3.0.0", "json-parse-better-errors": "^1.0.2", "lazy-property": "~1.0.0", - "libcipm": "^4.0.4", + "libcipm": "^4.0.7", "libnpm": "^3.0.1", "libnpmaccess": "^3.0.2", "libnpmhook": "^5.0.3", @@ -3903,25 +3895,25 @@ "npm-install-checks": "^3.0.2", "npm-lifecycle": "^3.1.4", "npm-package-arg": "^6.1.1", - "npm-packlist": "^1.4.4", + "npm-packlist": "^1.4.7", "npm-pick-manifest": "^3.0.2", "npm-profile": "^4.0.2", - "npm-registry-fetch": "^4.0.0", + "npm-registry-fetch": "^4.0.2", "npm-user-validate": "~1.0.0", "npmlog": "~4.1.2", "once": "~1.4.0", "opener": "^1.5.1", "osenv": "^0.1.5", - "pacote": "^9.5.8", + "pacote": "^9.5.11", "path-is-inside": "~1.0.2", "promise-inflight": "~1.0.1", "qrcode-terminal": "^0.12.0", "query-string": "^6.8.2", "qw": "~1.0.1", "read": "~1.0.7", - "read-cmd-shim": "^1.0.4", + "read-cmd-shim": "^1.0.5", "read-installed": "~4.0.3", - "read-package-json": "^2.1.0", + "read-package-json": "^2.1.1", "read-package-tree": "^5.3.1", "readable-stream": "^3.4.0", "readdir-scoped-modules": "^1.1.0", @@ -3936,7 +3928,7 @@ "sorted-union-stream": "~2.1.3", "ssri": "^6.0.1", "stringify-package": "^1.0.1", - "tar": "^4.4.12", + "tar": "^4.4.13", "text-table": "~0.2.0", "tiny-relative-date": "^1.3.0", "uid-number": "0.0.6", @@ -3944,7 +3936,7 @@ "unique-filename": "^1.1.1", "unpipe": "~1.0.0", "update-notifier": "^2.5.0", - "uuid": "^3.3.2", + "uuid": "^3.3.3", "validate-npm-package-license": "^3.0.4", "validate-npm-package-name": "~3.0.0", "which": "^1.3.1", @@ -4115,14 +4107,15 @@ } }, "bin-links": { - "version": "1.1.3", + "version": "1.1.6", "bundled": true, "dev": true, "requires": { "bluebird": "^3.5.3", "cmd-shim": "^3.0.0", - "gentle-fs": "^2.0.1", + "gentle-fs": "^2.3.0", "graceful-fs": "^4.1.15", + "npm-normalize-package-bin": "^1.0.0", "write-file-atomic": "^2.3.0" } }, @@ -4227,7 +4220,7 @@ } }, "chownr": { - "version": "1.1.2", + "version": "1.1.3", "bundled": true, "dev": true }, @@ -4873,7 +4866,7 @@ }, "dependencies": { "minipass": { - "version": "2.8.6", + "version": "2.9.0", "bundled": true, "dev": true, "requires": { @@ -4981,12 +4974,13 @@ "dev": true }, "gentle-fs": { - "version": "2.2.1", + "version": "2.3.0", "bundled": true, "dev": true, "requires": { "aproba": "^1.1.2", "chownr": "^1.1.2", + "cmd-shim": "^3.0.3", "fs-vacuum": "^1.2.10", "graceful-fs": "^4.1.11", "iferr": "^0.1.5", @@ -5077,7 +5071,7 @@ } }, "graceful-fs": { - "version": "4.2.2", + "version": "4.2.3", "bundled": true, "dev": true }, @@ -5148,7 +5142,7 @@ } }, "https-proxy-agent": { - "version": "2.2.2", + "version": "2.2.4", "bundled": true, "dev": true, "requires": { @@ -5178,7 +5172,7 @@ "dev": true }, "ignore-walk": { - "version": "3.0.1", + "version": "3.0.3", "bundled": true, "dev": true, "requires": { @@ -5432,7 +5426,7 @@ } }, "libcipm": { - "version": "4.0.4", + "version": "4.0.7", "bundled": true, "dev": true, "requires": { @@ -5735,7 +5729,7 @@ } }, "make-fetch-happen": { - "version": "5.0.0", + "version": "5.0.2", "bundled": true, "dev": true, "requires": { @@ -5743,7 +5737,7 @@ "cacache": "^12.0.0", "http-cache-semantics": "^3.8.1", "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", + "https-proxy-agent": "^2.2.3", "lru-cache": "^5.1.1", "mississippi": "^3.0.0", "node-fetch-npm": "^2.0.2", @@ -5796,30 +5790,25 @@ "bundled": true, "dev": true }, - "minipass": { - "version": "2.3.3", + "minizlib": { + "version": "1.3.3", "bundled": true, "dev": true, "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "minipass": "^2.9.0" }, "dependencies": { - "yallist": { - "version": "3.0.2", + "minipass": { + "version": "2.9.0", "bundled": true, - "dev": true + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } } } }, - "minizlib": { - "version": "1.2.2", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^2.2.1" - } - }, "mississippi": { "version": "3.0.0", "bundled": true, @@ -5958,9 +5947,12 @@ } }, "npm-bundled": { - "version": "1.0.6", + "version": "1.1.1", "bundled": true, - "dev": true + "dev": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } }, "npm-cache-filename": { "version": "1.0.2", @@ -5995,6 +5987,11 @@ "bundled": true, "dev": true }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, "npm-package-arg": { "version": "6.1.1", "bundled": true, @@ -6007,7 +6004,7 @@ } }, "npm-packlist": { - "version": "1.4.4", + "version": "1.4.7", "bundled": true, "dev": true, "requires": { @@ -6036,7 +6033,7 @@ } }, "npm-registry-fetch": { - "version": "4.0.0", + "version": "4.0.2", "bundled": true, "dev": true, "requires": { @@ -6045,7 +6042,15 @@ "figgy-pudding": "^3.4.1", "lru-cache": "^5.1.1", "make-fetch-happen": "^5.0.0", - "npm-package-arg": "^6.1.0" + "npm-package-arg": "^6.1.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.0", + "bundled": true, + "dev": true + } } }, "npm-run-path": { @@ -6181,7 +6186,7 @@ } }, "pacote": { - "version": "9.5.8", + "version": "9.5.11", "bundled": true, "dev": true, "requires": { @@ -6199,6 +6204,7 @@ "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "normalize-package-data": "^2.4.0", + "npm-normalize-package-bin": "^1.0.0", "npm-package-arg": "^6.1.0", "npm-packlist": "^1.1.12", "npm-pick-manifest": "^3.0.0", @@ -6217,7 +6223,7 @@ }, "dependencies": { "minipass": { - "version": "2.3.5", + "version": "2.9.0", "bundled": true, "dev": true, "requires": { @@ -6450,7 +6456,7 @@ } }, "read-cmd-shim": { - "version": "1.0.4", + "version": "1.0.5", "bundled": true, "dev": true, "requires": { @@ -6472,7 +6478,7 @@ } }, "read-package-json": { - "version": "2.1.0", + "version": "2.1.1", "bundled": true, "dev": true, "requires": { @@ -6480,7 +6486,7 @@ "graceful-fs": "^4.1.2", "json-parse-better-errors": "^1.0.1", "normalize-package-data": "^2.0.0", - "slash": "^1.0.0" + "npm-normalize-package-bin": "^1.0.0" } }, "read-package-tree": { @@ -6655,28 +6661,23 @@ "bundled": true, "dev": true }, - "slash": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, "slide": { "version": "1.1.6", "bundled": true, "dev": true }, "smart-buffer": { - "version": "4.0.2", + "version": "4.1.0", "bundled": true, "dev": true }, "socks": { - "version": "2.3.2", + "version": "2.3.3", "bundled": true, "dev": true, "requires": { - "ip": "^1.1.5", - "smart-buffer": "4.0.2" + "ip": "1.1.5", + "smart-buffer": "^4.1.0" } }, "socks-proxy-agent": { @@ -6922,7 +6923,7 @@ } }, "tar": { - "version": "4.4.12", + "version": "4.4.13", "bundled": true, "dev": true, "requires": { @@ -6936,7 +6937,7 @@ }, "dependencies": { "minipass": { - "version": "2.8.6", + "version": "2.9.0", "bundled": true, "dev": true, "requires": { @@ -7123,7 +7124,7 @@ } }, "uuid": { - "version": "3.3.2", + "version": "3.3.3", "bundled": true, "dev": true }, @@ -8305,15 +8306,33 @@ } }, "rollup-plugin-terser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-4.0.4.tgz", - "integrity": "sha512-wPANT5XKVJJ8RDUN0+wIr7UPd0lIXBo4UdJ59VmlPCtlFsE20AM+14pe+tk7YunCsWEiuzkDBY3QIkSCjtrPXg==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.1.3.tgz", + "integrity": "sha512-FuFuXE5QUJ7snyxHLPp/0LFXJhdomKlIx/aK7Tg88Yubsx/UU/lmInoJafXJ4jwVVNcORJ1wRUC5T9cy5yk0wA==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "jest-worker": "^24.0.0", - "serialize-javascript": "^1.6.1", - "terser": "^3.14.1" + "jest-worker": "^24.6.0", + "rollup-pluginutils": "^2.8.1", + "serialize-javascript": "^2.1.2", + "terser": "^4.1.0" + }, + "dependencies": { + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + } + } } }, "rollup-plugin-typescript2": { @@ -8985,9 +9004,9 @@ "dev": true }, "serialize-javascript": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", - "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", "dev": true }, "set-value": { @@ -9432,14 +9451,14 @@ } }, "terser": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", - "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.5.1.tgz", + "integrity": "sha512-lH9zLIbX8PRBEFCTvfHGCy0s9HEKnNso1Dx9swSopF3VUnFLB8DpQ61tHxoofovNC/sG0spajJM3EIIRSTByiQ==", "dev": true, "requires": { - "commander": "^2.19.0", + "commander": "^2.20.0", "source-map": "~0.6.1", - "source-map-support": "~0.5.10" + "source-map-support": "~0.5.12" }, "dependencies": { "source-map": { @@ -9449,9 +9468,9 @@ "dev": true }, "source-map-support": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", - "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", "dev": true, "requires": { "buffer-from": "^1.0.0", diff --git a/package.json b/package.json index 686e453..39aca28 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "eslint": "^5.16.0", "eslint-config-airbnb-base": "^13.2.0", "eslint-plugin-import": "^2.18.2", - "npm": "^6.12.0", + "npm": "^6.13.4", "pre-commit": "^1.2.2", "prettier": "^1.18.2", "rollup": "^1.25.0", @@ -50,7 +50,7 @@ "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-json": "^4.0.0", "rollup-plugin-node-resolve": "^4.2.4", - "rollup-plugin-terser": "^4.0.4", + "rollup-plugin-terser": "^5.1.3", "rollup-plugin-typescript2": "^0.20.1", "ts-lit-plugin": "^1.1.9", "typescript": "^3.6.4", @@ -58,7 +58,6 @@ }, "dependencies": { "@ctrl/tinycolor": "^2.5.4", - "bowser": "^2.7.0", "custom-card-helpers": "^1.2.7", "home-assistant-js-websocket": "^3.4.0", "lit-element": "^2.2.1", diff --git a/src/long-press.ts b/src/long-press.ts index 39bbec5..cb212d8 100644 --- a/src/long-press.ts +++ b/src/long-press.ts @@ -1,5 +1,4 @@ import { directive, PropertyPart } from 'lit-html'; -import Bowser from 'bowser'; // See https://github.com/home-assistant/home-assistant-polymer/pull/2457 // on how to undo mwc -> paper migration // import '@material/mwc-ripple'; @@ -178,18 +177,14 @@ class LongPress extends HTMLElement implements LongPress { window.setTimeout(() => (this.cooldownEnd = false), 100); }; - const br = Bowser.getParser(window.navigator.userAgent); - const isCrazyBrowser = br.satisfies({ - mobile: { - safari: '>=13', - }, - }); - const ios13 = new RegExp('^13\\..*', 'gm'); - const isCrazyBrowser2 = br.getOSName() === 'iOS' && (br.getOSVersion().match(ios13) ? true : false); element.addEventListener('touchstart', clickStart, { passive: true }); element.addEventListener('touchend', clickEnd); element.addEventListener('touchcancel', clickEnd); - if (!isCrazyBrowser && !isCrazyBrowser2) { + // avoid double click on iPad OS... + const isIpadOS = navigator.platform === 'MacIntel' + && navigator.maxTouchPoints > 1 + && !window.MSStream; + if (!isIpadOS) { element.addEventListener('mousedown', clickStart, { passive: true }); element.addEventListener('click', clickEnd); } diff --git a/src/styles.ts b/src/styles.ts index bda12d5..91d9377 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -9,6 +9,14 @@ export const styles = css` display: flex; justify-content: center; align-items: center; + + -webkit-touch-callout: none; /* iOS Safari */ + -webkit-user-select: none; /* Safari */ + -khtml-user-select: none; /* Konqueror HTML */ + -moz-user-select: none; /* Old versions of Firefox */ + -ms-user-select: none; /* Internet Explorer/Edge */ + user-select: none; /* Non-prefixed version, currently + supported by Chrome, Opera and Firefox */ } ha-card.disabled { pointer-events: none; From e9f0a7cb1b6e0a42bbfaffe51d5e9d29d2d7e9ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Wiedemann?= Date: Sun, 5 Jan 2020 12:50:20 +0100 Subject: [PATCH 5/7] Support for cast.home-assistant.io --- src/button-card.ts | 3 ++- src/helpers.ts | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/button-card.ts b/src/button-card.ts index e769b18..f5fef2a 100644 --- a/src/button-card.ts +++ b/src/button-card.ts @@ -42,6 +42,7 @@ import { getLightColorBasedOnTemperature, mergeDeep, mergeStatesById, + getLovelaceCast, } from './helpers'; import { styles } from './styles'; import myComputeStateDisplay from './compute_state_display'; @@ -781,7 +782,7 @@ class ButtonCard extends LitElement { throw new Error('Invalid configuration'); } - const ll = getLovelace(); + const ll = getLovelace() || getLovelaceCast(); let template: ButtonCardConfig = { ...config }; let tplName: string | undefined = template.template; let mergedStateConfig: StateConfig[] | undefined = config.state; diff --git a/src/helpers.ts b/src/helpers.ts index 93930a2..1e08eb7 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -156,3 +156,17 @@ export function mergeStatesById( } return resultStateConfigs; } + +export function getLovelaceCast() { + let root: any = document.querySelector('hc-main'); + root = root && root.shadowRoot; + root = root && root.querySelector('hc-lovelace'); + root = root && root.shadowRoot; + root = root && root.querySelector('hui-view'); + if (root) { + const ll = root.lovelace; + ll.current_view = root.___curView; + return ll; + } + return null; +} From e784bfc61f12d9d4baa1d0b02b56a06a3cc18241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Wiedemann?= Date: Sun, 5 Jan 2020 13:50:51 +0100 Subject: [PATCH 6/7] Template support in custom_fields' cards config --- README.md | 1 + src/button-card.ts | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 99f82bc..7c9b7ac 100644 --- a/README.md +++ b/README.md @@ -254,6 +254,7 @@ Those are the configuration fields which support templating: * Everything field in `*_action` * The confirmation text (`confirmation.text`) * The lock being enabled or not (`lock.enabled`) +* all the `card` parameters in a `custom_field` Inside the javascript code, you'll have access to those variables: * `entity`: The current entity object, if the entity is defined in the card diff --git a/src/button-card.ts b/src/button-card.ts index f5fef2a..ee161e1 100644 --- a/src/button-card.ts +++ b/src/button-card.ts @@ -221,12 +221,26 @@ class ButtonCard extends LitElement { .call(this, this.hass!.states, state, this.hass!.user, this.hass); } + private _objectEvalTemplate( + state: HassEntity | undefined, + obj: any | undefined, + ) { + const objClone = JSON.parse(JSON.stringify(obj)); + return this._getTemplateOrValue(state, objClone); + } + private _getTemplateOrValue( state: HassEntity | undefined, value: any | undefined, ): any | undefined { if (['number', 'boolean'].includes(typeof value)) return value; if (!value) return value; + if (['object'].includes(typeof value)) { + Object.keys(value).forEach((key) => { + value[key] = this._getTemplateOrValue(state, value[key]); + }); + return value; + } const trimmed = value.trim(); if ( trimmed.substring(0, 3) === '[[[' @@ -504,7 +518,7 @@ class ButtonCard extends LitElement { if (!value.card) { fields[key] = this._getTemplateOrValue(state, value); } else { - cards[key] = value.card; + cards[key] = this._objectEvalTemplate(state, value.card); } }); } @@ -514,7 +528,7 @@ class ButtonCard extends LitElement { if (!value!.card) { fields[key] = this._getTemplateOrValue(state, value); } else { - cards[key] = value.card; + cards[key] = this._objectEvalTemplate(state, value.card); } }); } From be1d00aa09289e0286d7daa8e73da3b7ac89ebe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Wiedemann?= Date: Sun, 5 Jan 2020 14:09:15 +0100 Subject: [PATCH 7/7] Support for variables in the templates --- README.md | 28 ++++++++++++++++++++++++++++ src/button-card.ts | 4 ++-- src/types.ts | 5 +++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7c9b7ac..e8071a5 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Lovelace Button card for your entities. - [Configuration Templates](#configuration-templates) - [General](#general) - [Merging state by id](#merging-state-by-id) + - [Variables](#variables) - [Installation](#installation) - [Manual Installation](#manual-installation) - [Installation and tracking with hacs](#installation-and-tracking-with-hacs) @@ -111,6 +112,7 @@ Lovelace Button card for your entities. | `lock` | object | optional | See [Lock Object](#lock-object) | Displays a lock on the button | | `layout` | string | optional | See [Layout](#Layout) | The layout of the button can be modified using this option | | `custom_fields` | object | optional | See [Custom Fields](#Custom-Fields) | +| `variables` | object | optional | See [Variables](#Variables) | ### Action @@ -261,6 +263,7 @@ Inside the javascript code, you'll have access to those variables: * `states`: An object with all the states of all the entities (equivalent to `hass.states`) * `user`: The user object (equivalent to `hass.user`) * `hass`: The complete `hass` object +* `variables`: an object containing all your variables defined in the configuration. See [Variables](#variables) See [here](#templates-support) for some examples or [here](#custom-fields) for some crazy advanced stuff using templates! @@ -707,6 +710,31 @@ state: value: 25 ``` +#### Variables + +You can add variables to your templates and overload them in the instance of your button card. This lets you easily work with templates without the need to redefine everything for a small change. +An exemple below: +```yaml +button_card_templates: + variable_test: + var_name: "var_value" + var_name2: "var_value2" + +[...] + +- type: custom:button-card + template: variable_test + entity: sensor.test + name: '[[[ return variables.var_name ]]]' # The name will be "var_value" + +- type: custom:button-card + template: variable_test + entity: sensor.test + variables: + var_name: "My local Value" + name: '[[[ return variables.var_name ]]]' # The name will be "My local Value" +``` + ## Installation ### Manual Installation diff --git a/src/button-card.ts b/src/button-card.ts index ee161e1..5b1884f 100644 --- a/src/button-card.ts +++ b/src/button-card.ts @@ -216,9 +216,9 @@ class ButtonCard extends LitElement { private _evalTemplate(state: HassEntity | undefined, func: any): any { /* eslint no-new-func: 0 */ - return new Function('states', 'entity', 'user', 'hass', + return new Function('states', 'entity', 'user', 'hass', 'variables', `'use strict'; ${func}`) - .call(this, this.hass!.states, state, this.hass!.user, this.hass); + .call(this, this.hass!.states, state, this.hass!.user, this.hass, this.config!.variables); } private _objectEvalTemplate( diff --git a/src/types.ts b/src/types.ts index 8ba805a..664765e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -33,6 +33,7 @@ export interface ButtonCardConfig { color_on: string; color_off: string; custom_fields?: CustomFields; + variables?: Variables; } export type Layout = 'vertical' @@ -98,3 +99,7 @@ export interface CssStyleConfig { export interface CustomFields { [key: string]: any; } + +export interface Variables { + [key: string]: any; +}