Initial commit
This commit is contained in:
commit
2f3cf2b508
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
q-card.js binary
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
node_modules/
|
21
LICENSE.txt
Normal file
21
LICENSE.txt
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Thomas Lovén
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
105
README.md
Normal file
105
README.md
Normal file
@ -0,0 +1,105 @@
|
||||
q-card
|
||||
=================
|
||||
|
||||
<!--[](https://github.com/custom-components/hacs)-->
|
||||
|
||||
**EXPERIMENTAL**
|
||||
|
||||
Use the same lovelace card in multiple places (but only one at a time).
|
||||
|
||||
For installation instructions [see this guide](https://github.com/thomasloven/hass-config/wiki/Lovelace-Plugins).
|
||||
|
||||
Install `q-card.js` as a `module`. Ignore all other files in this repo.
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
- url: /local/q-card.js
|
||||
type: module
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
1. Define q-cards in `ui-lovelace.yaml`
|
||||
|
||||
* Either globally:
|
||||
```yaml
|
||||
title: My awesome lovelace configuration
|
||||
resources:
|
||||
- url: /local/q-card.js
|
||||
type: module
|
||||
q_cards:
|
||||
card1:
|
||||
type: entities
|
||||
entities:
|
||||
- light.bed_light
|
||||
- light.kitchen_lights
|
||||
- light.ceiling_lights
|
||||
views:
|
||||
...
|
||||
```
|
||||
|
||||
* Or locally in a view
|
||||
```yaml
|
||||
views:
|
||||
- title: My first view
|
||||
q_cards:
|
||||
card2:
|
||||
type: glance
|
||||
entities:
|
||||
- light.bed_light
|
||||
- light.kitchen_lights
|
||||
- light.ceiling_lights
|
||||
cards:
|
||||
...
|
||||
```
|
||||
> Note: Local cards takes precedence.
|
||||
|
||||
2. Use the card:
|
||||
```yaml
|
||||
views:
|
||||
- title: One view
|
||||
cards:
|
||||
- type: q-card
|
||||
card: card1
|
||||
- title: Another view
|
||||
cards:
|
||||
- type: q-card
|
||||
card: card1
|
||||
```
|
||||
|
||||
The same card will now show up in both views.
|
||||
|
||||
So what? You can already do this with:
|
||||
|
||||
- [decluttering-card](https://github.com/custom-cards/decluttering-card)
|
||||
- [lovelace_gen](https://github.com/thomasloven/hass-lovelace_gen)
|
||||
- [YAML node anchors](https://github.com/thomasloven/hass-config/wiki/Misc-tricks#node-anchors)
|
||||
|
||||
What's the difference?
|
||||
|
||||
Well, the difference is that the **SAME** card will show up in both views.
|
||||
It's not an equal card - it's actually the *very same* card being moved over from one view to another.
|
||||
|
||||
This has two main advantages (besides simplifying your configuration as the alternatives mentioned above do):
|
||||
|
||||
- Memory
|
||||
|
||||
By only creating and loading a card once you can preserve some RAM and performance. This could also be a great advantage e.g. for [state-switch](https://github.com/thomasloven/lovelace-state-switch) and similar cards.
|
||||
|
||||
- Persistance.
|
||||
|
||||
Say you have a card with a [fold-entity-row](https://github.com/thomasloven/lovelace-fold-entity-row) in it. Now, you can unfold that in one view, and when you move to another view, it's still unfolded.
|
||||
|
||||
This also means you can only have the same q-card visible once in the same browser window.
|
||||
|
||||
# FAQ
|
||||
|
||||
### What's Q for in the name?
|
||||
Quantum. You know how quantum teleportation works and how quantum particles can be in two different places at the same time*.
|
||||
|
||||
This is nothing like that.
|
||||
|
||||
\* They can't _really_...
|
||||
|
||||
---
|
||||
<a href="https://www.buymeacoffee.com/uqD6KHCdJ" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/white_img.png" alt="Buy Me A Coffee" style="height: auto !important;width: auto !important;" ></a>
|
4078
package-lock.json
generated
Normal file
4078
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
25
package.json
Normal file
25
package.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "q-card",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"scripts": {
|
||||
"build": "webpack",
|
||||
"watch": "webpack --watch --mode=development",
|
||||
"update-card-tools": "npm uninstall card-tools && npm install thomasloven/lovelace-card-tools"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "github.com:thomasloven/lovelace-q-card"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Thomas Lovén",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"webpack": "^4.41.5",
|
||||
"webpack-cli": "^3.3.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"card-tools": "github:thomasloven/lovelace-card-tools"
|
||||
}
|
||||
}
|
1
q-card.js
Normal file
1
q-card.js
Normal file
@ -0,0 +1 @@
|
||||
!function(e){var t={};function o(n){if(t[n])return t[n].exports;var r=t[n]={i:n,l:!1,exports:{}};return e[n].call(r.exports,r,r.exports,o),r.l=!0,r.exports}o.m=e,o.c=t,o.d=function(e,t,n){o.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)o.d(n,r,function(t){return e[t]}.bind(null,r));return n},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,"a",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p="",o(o.s=0)}([function(e,t,o){"use strict";o.r(t);const n=customElements.get("home-assistant-main")?Object.getPrototypeOf(customElements.get("home-assistant-main")):Object.getPrototypeOf(customElements.get("hui-view"));n.prototype.html,n.prototype.css;function r(){var e,t=document.querySelector("hc-main");return t?((e=t._lovelaceConfig).current_view=t._lovelacePath,e):(t=(t=(t=(t=(t=(t=(t=(t=(t=document.querySelector("home-assistant"))&&t.shadowRoot)&&t.querySelector("home-assistant-main"))&&t.shadowRoot)&&t.querySelector("app-drawer-layout partial-panel-resolver"))&&t.shadowRoot||t)&&t.querySelector("ha-panel-lovelace"))&&t.shadowRoot)&&t.querySelector("hui-root"))?((e=t.lovelace).current_view=t.___curView,e):null}function s(e,t,o=null){if((e=new Event(e,{bubbles:!0,cancelable:!1,composed:!0})).detail=t||{},o)o.dispatchEvent(e);else{var n=function(){var e=document.querySelector("hc-main");return e=e?(e=(e=(e=e&&e.shadowRoot)&&e.querySelector("hc-lovelace"))&&e.shadowRoot)&&e.querySelector("hui-view"):(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=document.querySelector("home-assistant"))&&e.shadowRoot)&&e.querySelector("home-assistant-main"))&&e.shadowRoot)&&e.querySelector("app-drawer-layout partial-panel-resolver"))&&e.shadowRoot||e)&&e.querySelector("ha-panel-lovelace"))&&e.shadowRoot)&&e.querySelector("hui-root"))&&e.shadowRoot)&&e.querySelector("ha-app-layout #view"))&&e.firstElementChild}();n&&n.dispatchEvent(e)}}function a(e,t){const o=document.createElement("hui-error-card");return o.setConfig({type:"error",error:e,origConfig:t}),o}function i(e,t){if(!t||"object"!=typeof t||!t.type)return a(`No ${e} type configured`,t);let o=t.type;if(o=o.startsWith("custom:")?o.substr("custom:".length):`hui-${o}-${e}`,customElements.get(o))return function(e,t){const o=document.createElement(e);try{o.setConfig(t)}catch(e){return a(e,t)}return o}(o,t);const n=a(`Custom element doesn't exist: ${o}.`,t);n.style.display="None";const r=setTimeout(()=>{n.style.display=""},2e3);return customElements.whenDefined(o).then(()=>{clearTimeout(r),s("ll-rebuild",{},n)}),n}function c(e){return i("card",e)}customElements.get("q-card")||customElements.define("q-card",class extends n{setConfig(e){this.name=e.card,this.localname=`__local_${r().current_view}_${e.card}`,window.qCards||(window.qCards={});const t=r().config.q_cards,o=r().config.views[r().current_view].q_cards;t&&t[this.name]&&!window.qCards[this.name]&&(window.qCards[this.name]=c(t[this.name])),o&&o[this.name]&&!window.qCards[this.localname]&&(window.qCards[this.localname]=c(o[this.name])),window.addEventListener("location-changed",()=>this.update()),this.update()}connectedCallback(){this.update()}update(){window.setTimeout(()=>{window.qCards&&0!==Object.keys(window.qCards).length&&(!this.shadowRoot.firstElementChild&&this.offsetParent&&this.shadowRoot.appendChild(window.qCards[this.localname]||window.qCards[this.name]),this.shadowRoot.firstElementChild&&(this.shadowRoot.firstElementChild.hass=this._hass))},1)}set hass(e){this._hass=e,this.update()}})}]);
|
48
src/main.js
Normal file
48
src/main.js
Normal file
@ -0,0 +1,48 @@
|
||||
import { LitElement } from "card-tools/src/lit-element";
|
||||
import {lovelace} from "card-tools/src/hass";
|
||||
import {createCard} from "card-tools/src/lovelace-element";
|
||||
|
||||
class QCard extends LitElement {
|
||||
|
||||
setConfig(config) {
|
||||
this.name = config.card;
|
||||
this.localname = `__local_${lovelace().current_view}_${config.card}`;
|
||||
if(!window.qCards)
|
||||
window.qCards = {};
|
||||
|
||||
const globals = lovelace().config.q_cards;
|
||||
const locals = lovelace().config.views[lovelace().current_view].q_cards;
|
||||
|
||||
if(globals && globals[this.name] && !window.qCards[this.name]) {
|
||||
window.qCards[this.name] = createCard(globals[this.name]);
|
||||
}
|
||||
if(locals && locals[this.name] && !window.qCards[this.localname]) {
|
||||
window.qCards[this.localname] = createCard(locals[this.name]);
|
||||
}
|
||||
|
||||
window.addEventListener("location-changed", () => this.update());
|
||||
this.update();
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.update();
|
||||
}
|
||||
|
||||
update() {
|
||||
window.setTimeout(() => {
|
||||
if(!window.qCards || Object.keys(window.qCards).length === 0) return;
|
||||
if(!this.shadowRoot.firstElementChild && this.offsetParent)
|
||||
this.shadowRoot.appendChild(window.qCards[this.localname]
|
||||
|| window.qCards[this.name]);
|
||||
if(this.shadowRoot.firstElementChild) this.shadowRoot.firstElementChild.hass = this._hass;
|
||||
}, 1);
|
||||
}
|
||||
|
||||
set hass(hass) {
|
||||
this._hass = hass;
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
if(!customElements.get("q-card"))
|
||||
customElements.define("q-card", QCard);
|
10
webpack.config.js
Normal file
10
webpack.config.js
Normal file
@ -0,0 +1,10 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: './src/main.js',
|
||||
mode: 'production',
|
||||
output: {
|
||||
filename: 'q-card.js',
|
||||
path: path.resolve(__dirname)
|
||||
}
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user