Cleanup and variable column widths

This commit is contained in:
Thomas Lovén 2019-02-28 12:38:53 +01:00
parent e0ec2f21ad
commit 25d4d4615f

View File

@ -1,174 +1,169 @@
customElements.whenDefined('card-tools').then(() => { customElements.whenDefined('card-tools').then(() => {
class LayoutCard extends Polymer.Element { let cardTools = customElements.get('card-tools');
class LayoutCard extends cardTools.LitElement {
static get template() { async setConfig(config) {
return Polymer.html` this.config = config;
<style> this.layout = config.layout || 'auto';
this.minCols = config.column_num || 1;
this.maxCols = config.max_columns || 100;
this.colWidth = config.column_width || 300;
this.maxWidth = config.max_width || 500;
this.minHeight = config.min_height || 5;
this.cardSize = 1;
window.addEventListener('resize', () => this.build());
window.addEventListener('hass-open-menu', () => setTimeout(() => this.build(), 100));
window.addEventListener('hass-close-menu', () => setTimeout(() => this.build(), 100));
}
render() {
return cardTools.LitHtml`
<div id="columns"></div>
`;
}
firstUpdated() {
this.build();
}
static get styles() {
return cardTools.LitCSS`
#columns { #columns {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: center; justify-content: center;
} }
.column { .column {
flex-basis: 0; flex-basis: 0;
flex-grow: 1; flex-grow: 1;
max-width: 500px;
overflow-x: hidden; overflow-x: hidden;
} }
.column > *:first-child {
margin-top: 0;
}
.column > * { .column > * {
display: block; display: block;
margin: 4px 4px 8px; margin: 4px 4px 8px;
} }
</style>
<div id="columns"></div> .column > *:first-child {
margin-top: 0;
}
`; `;
} }
setConfig(config) { make_cards() {
cardTools.checkVersion(0.1); this.cards = this.config.cards.map((c) => {
this.config = config;
this.colnum = 0;
this.config.min_height = this.config.minheight || 5;
this.config.column_width = this.config.column_width || 300;
this.config.layout = this.config.layout || 'auto';
this.config.max_columns = this.config.max_columns || 100;
window.addEventListener('resize', () => this._updateColumns());
window.addEventListener('hass-open-menu', () => setTimeout(() => this._updateColumns(), 10));
window.addEventListener('hass-close-menu', () => setTimeout(() => this._updateColumns(), 10));
setTimeout(() => this._updateColumns(), 10);
}
connectedCallback() {
super.connectedCallback();
this._updateColumns();
this._build();
}
_updateColumns() {
if (this.parentElement && this.parentElement.id === "view")
{
this.style.padding = "8px 4px 0";
this.style.display = "block";
} else {
this.style.marginRight = "0";
this.style.marginLeft = "0";
}
let numcols = 0;
if (this.config.column_num) {
numcols = this.config.column_num;
} else {
const cardWidth = this.$.columns.clientWidth || (this.parentElement && this.parentElement.clientWidth);
numcols = Math.max(1, Math.floor(cardWidth/this.config.column_width));
}
numcols = Math.min(numcols, this.config.max_columns);
if(numcols != this.colnum) {
this.colnum = numcols;
this._build();
}
}
_build() {
if(!this.$) return;
const root = this.$.columns;
while(root.lastChild) root.removeChild(root.lastChild);
this._cards = this.config.cards.map((c) => {
if (typeof c === 'string') return c; if (typeof c === 'string') return c;
let el = cardTools.createCard(c); const card = cardTools.createCard(c);
if (this._hass) el.hass = this._hass; if(this._hass) card.hass = this._hass;
return el; this.appendChild(card); // Place card in DOM to get size
return card;
}); });
}
update_columns() {
const width = (this.shadowRoot && this.shadowRoot.querySelector("#columns").clientWidth) || (this.parentElement && this.parentElement.clientWidth);
if(typeof(this.colWidth) === 'object')
this.colNum = this.colWidth.length;
else
this.colNum = Math.floor(width / this.colWidth);
this.colNum = Math.max(this.colNum, this.minCols);
this.colNum = Math.min(this.colNum, this.maxCols);
}
build() {
const root = this.shadowRoot.querySelector("#columns");
while(root.lastChild) {
root.removeChild(root.lastChild);
}
this.update_columns();
if(!this.cards) this.make_cards();
let cols = []; let cols = [];
let colLen = []; let colSize = [];
for(let i = 0; i < this.colnum; i++) { for(let i = 0; i < this.colNum; i++) {
cols.push([]); cols.push([]);
colLen.push(0); colSize.push(0);
} }
let shortest = () => { const shortestCol = () => {
let i = 0; let i = 0;
for(let j = 0; j < colLen.length; j++) { for(let j = 0; j < this.colNum; j++) {
if(colLen[j] < this.config.min_height) { if(colSize[j] < this.min_height)
i = j; return j;
break; if(colSize[j] < colSize[i])
}
if(colLen[j] < colLen[i])
i = j; i = j;
} }
return i; return i;
} }
let i = 0; let i = 0;
this._cards.forEach((c) => { this.cards.forEach((c) => {
let sz; const isBreak = (typeof(c) === 'string');
if(typeof c !== 'string') { const sz = c.getCardSize ? c.getCardSize() : 1;
this.appendChild(c);
sz = typeof c.getCardSize === 'function' ? c.getCardSize() : 1; switch(this.layout) {
} case 'horizontal':
switch (this.config.layout) { if(i >= this.colNum) i = 0;
case 'auto': i += 1;
if(typeof c === 'string') break; if(isBreak) break;
cols[shortest()].push(c); cols[i-1].push(c);
colLen[shortest()] += sz; colSize[i-1] += sz;
break; break;
case 'vertical': case 'vertical':
if(typeof c === 'string') { if(isBreak){
i += 1; i += 1;
} else { if(i >= this.colNum)
if (i >= this.colnum) i = 0; i = 0;
cols[i].push(c);
colLen[i] += sz;
}
break; break;
case 'horizontal':
if(c instanceof String) {
i += 1;
} else {
if (i >= this.colnum) i = 0;
cols[i].push(c);
colLen[i] += sz;
i += 1;
} }
cols[i].push(c);
colSize[i] += sz;
break;
case 'auto':
default:
if(isBreak) break;
cols[shortestCol()].push(c);
colSize[shortestCol()] += sz;
break; break;
} }
}); });
cols = cols.filter(c => c.length > 0); cols = cols.filter((c) => c.length > 0);
let maxlen = 0; cols.forEach((c, i) => {
cols.forEach( c => { const div = document.createElement('div');
const cEl = document.createElement('div'); div.classList.add('column');
cEl.classList.add('column'); c.forEach((e) => div.appendChild(e));
c.filter(e => typeof e !== 'string').forEach(e => cEl.appendChild(e)); root.appendChild(div);
root.appendChild(cEl); if(typeof(this.colWidth) === 'object') {
if(c.length > maxlen) maxlen = c.length; div.style.setProperty('max-width', this.colWidth[i]);
} else {
div.style.setProperty('max-width', this.maxWidth+'px');
}
}); });
this.maxlen = maxlen; this.cardSize = Math.max.apply(null, colSize);
} }
set hass(hass) { set hass(hass) {
this._hass = hass; this._hass = hass;
if(this._cards) if(this.cards)
this._cards.filter(c => typeof c !== 'string').forEach(c => c.hass = hass); this.cards
.filter((c) => typeof(c) !== 'string')
.forEach((c) => c.hass = hass);
} }
getCardSize() { getCardSize() {
return this.maxlen; return this.cardSize;
} }
} }
customElements.define('layout-card', LayoutCard); customElements.define('layout-card', LayoutCard);
}); });
window.setTimeout(() => { window.setTimeout(() => {
if(customElements.get('card-tools')) return; if(customElements.get('card-tools')) return;
customElements.define('layout-card', class extends HTMLElement{ customElements.define('layout-card', class extends HTMLElement{