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 24e825f1..e769b189 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 24e825f1..af8a7251 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 39bbec5e..7723edff 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 af8a7251..1d82fbe9 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 3e523953..ef3b97f3 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 686e453e..39aca286 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 39bbec5e..cb212d86 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 bda12d5b..91d93773 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 e769b189..f5fef2a2 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 93930a2c..1e08eb73 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 99f82bc3..7c9b7acf 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 f5fef2a2..ee161e1d 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 7c9b7acf..e8071a55 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 ee161e1d..5b1884f2 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 8ba805a2..664765ec 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; +}