Skip to content

Commit

Permalink
New version
Browse files Browse the repository at this point in the history
  • Loading branch information
ofekashery committed Mar 22, 2020
1 parent 8797405 commit 150f290
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 114 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ Vertical Stack In Card allows you to group multiple cards in one card.

Bash:
```bash
wget https://raw.githubusercontent.com/custom-cards/vertical-stack-in-card/master/vertical-stack-in-card.js
wget https://raw.githubusercontent.com/ofekashery/vertical-stack-in-card/master/vertical-stack-in-card.js
mv vertical-stack-in-card.js /config/www/
```

2. Link `vertical-stack-in-card` inside your `ui-lovelace.yaml`

```yaml
resources:
- url: /local/vertical-stack-in-card.js?v=0.1.3
- url: /local/vertical-stack-in-card.js?v=0.3.0
type: js
```
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.2.1
0.3.0
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 0.3.0
- Fix [#75](https://github.com/ofekashery/vertical-stack-in-card/issues/75), [#78](https://github.com/ofekashery/vertical-stack-in-card/issues/78).

## 0.2.1
- Fix [#57](https://github.com/custom-cards/vertical-stack-in-card/issues/57), [#59](https://github.com/custom-cards/vertical-stack-in-card/issues/59), [#66](https://github.com/custom-cards/vertical-stack-in-card/issues/66), [#67](https://github.com/custom-cards/vertical-stack-in-card/issues/67), [#68](https://github.com/custom-cards/vertical-stack-in-card/issues/68).

Expand Down
198 changes: 87 additions & 111 deletions vertical-stack-in-card.js
Original file line number Diff line number Diff line change
@@ -1,165 +1,141 @@
class VerticalStackInCard extends HTMLElement {
constructor() {
super();
// Make use of shadowRoot to avoid conflicts when reusing
this.attachShadow({ mode: 'open' });
}

setConfig(config) {
async setConfig(config) {
if (!config || !config.cards || !Array.isArray(config.cards)) {
throw new Error('Card config incorrect');
}

const shadow = this.shadowRoot;
while (shadow.hasChildNodes()) {
shadow.removeChild(shadow.lastChild);
}

const card = document.createElement("ha-card");
const cardContent = document.createElement("div");

card.header = config.title;
this._config = config;
this._refCards = [];

if (window.loadCardHelpers) {
this.helpers = await window.loadCardHelpers();
}

this.renderCard();
}

renderCard() {
const config = this._config;
const promises = config.cards.map(config => this.createCardElement(config));
Promise.all(promises).then((cards) => {
cards.forEach(card => {
if (card.updateComplete) {
card.updateComplete.then(() => this.styleCard(card));
} else {
this.styleCard(card);
}
});

this._refCards = cards;
const card = document.createElement('ha-card');
const cardContent = document.createElement('div');
card.header = config.title;
cards.forEach(card => cardContent.appendChild(card));
card.appendChild(cardContent);

while (this.hasChildNodes()) {
this.removeChild(this.lastChild);
}
this.appendChild(card);
})
}

async createCardElement(cardConfig) {
const createError = (error, config) => {
return createThing('hui-error-card', {
type: 'error',
error,
config,
});
};

const _createThing = (tag, config) => {
const createThing = (tag, config) => {
if (this.helpers) {
if (config.type === 'divider') {
return this.helpers.createRowElement(config)
} else {
return this.helpers.createCardElement(config);
}
}

const element = document.createElement(tag);
try {
element.setConfig(config);
} catch (err) {
console.error(tag, err);
return _createError(err.message, config);
return createError(err.message, config);
}
return element;
};

const _createError = (error, config) => {
return _createThing("hui-error-card", {
type: "error",
error,
config,
});
};

const _fireEvent = (ev, detail, entity=null) => {
ev = new Event(ev, {
bubbles: true,
cancelable: false,
composed: true,
});
ev.detail = detail || {};

if (entity) {
entity.dispatchEvent(ev);
} else {
document
.querySelector("home-assistant")
.shadowRoot.querySelector("home-assistant-main")
.shadowRoot.querySelector("app-drawer-layout partial-panel-resolver")
.shadowRoot.querySelector("ha-panel-lovelace")
.shadowRoot.querySelector("hui-root")
.shadowRoot.querySelector("ha-app-layout #view")
.firstElementChild
.dispatchEvent(ev);
}
let tag = cardConfig.type;
if (tag.startsWith('divider')) {
tag = `hui-divider-row`;
} else if (tag.startsWith('custom:')) {
tag = tag.substr('custom:'.length);
} else {
tag = `hui-${tag}-card`;
}

config.cards.forEach((item) => {
let tag = item.type;

if (tag.startsWith("divider")) {
tag = `hui-divider-row`;
} else if (tag.startsWith("custom:")) {
tag = tag.substr("custom:".length);
} else {
tag = `hui-${tag}-card`;
}

if (customElements.get(tag)) {
const element = _createThing(tag, item);
cardContent.appendChild(element);
this._refCards.push(element);
} else {
// If element doesn't exist (yet) create an error
const element = _createError(
`Custom element doesn't exist: ${tag}.`,
item
);
element.style.display = "None";

const time = setTimeout(() => {
element.style.display = "";
}, 2000);

// Remove error if element is defined later
customElements.whenDefined(tag).then(() => {
clearTimeout(time);
_fireEvent("ll-rebuild", {}, element);
const element = createThing(tag, cardConfig);
element.hass = this._hass;
element.addEventListener(
'll-rebuild',
ev => {
ev.stopPropagation();
this.createCardElement(cardConfig).then(() => {
this.renderCard();
});

cardContent.appendChild(element);
this._refCards.push(element);
}
});
card.appendChild(cardContent);
shadow.appendChild(card);
},
{ once: true },
);
return element;
}

set hass(hass) {
this._hass = hass
if (this._refCards) {
this._refCards.forEach((card) => {
card.hass = hass;
});
}
}

connectedCallback() {
this._refCards.forEach((element) => {
let fn = () => {
this._card(element);
};

if(element.updateComplete) {
element.updateComplete.then(fn);
} else {
fn();
}
});
}

_card(element) {
styleCard(element) {
if (element.shadowRoot) {
if (!element.shadowRoot.querySelector('ha-card')) {
let searchEles = element.shadowRoot.getElementById("root");
if (element.shadowRoot.querySelector('ha-card')) {
let ele = element.shadowRoot.querySelector('ha-card')
ele.style.boxShadow = 'none';
ele.style.borderRadius = '0';
} else {
let searchEles = element.shadowRoot.getElementById('root');
if (!searchEles) {
searchEles = element.shadowRoot.getElementById("card");
searchEles = element.shadowRoot.getElementById('card');
}
if (!searchEles) return;
searchEles = searchEles.childNodes;
for (let i = 0; i < searchEles.length; i++) {
if(searchEles[i].style !== undefined){
searchEles[i].style.margin = "0px";
if (searchEles[i].style){
searchEles[i].style.margin = '0px';
}
this._card(searchEles[i]);
this.styleCard(searchEles[i]);
}
} else {
let ele = element.shadowRoot.querySelector('ha-card')
ele.style.boxShadow = 'none';
ele.style.background = 'transparent';
ele.style.borderRadius = '0';
}
} else {
if (typeof element.querySelector === 'function' && element.querySelector('ha-card')) {
let ele = element.querySelector('ha-card')
ele.style.boxShadow = 'none';
ele.style.background = 'transparent';
ele.style.borderRadius = '0';
}
let searchEles = element.childNodes;
for (let i = 0; i < searchEles.length; i++) {
if (searchEles[i] && searchEles[i].style) {
searchEles[i].style.margin = "0px";
searchEles[i].style.margin = '0px';
}
this._card(searchEles[i]);
this.styleCard(searchEles[i]);
}
}
}
Expand Down

0 comments on commit 150f290

Please sign in to comment.