// Notes // Feedparser data loads each RSS feed data entry as an HA entity's attribute. The name of the attribute is the name of the author, like 'Oscar Wilde'. // The quote's data is stored as a dictionary under key 'Oscar Wilde'. Access an entry by hass.states[config.entity].attributes[author name][column name] let oldStates = {} class QuoteOfTheDayCard extends HTMLElement { constructor() { super(); oldStates = {} this.attachShadow({ mode: 'open' }); } setConfig(config) { if (!config.entity) { throw new Error('Please define an entity.'); } const root = this.shadowRoot; if (root.lastChild) root.removeChild(root.lastChild); const cardConfig = Object.assign({}, config); const card = document.createElement('ha-card'); const content = document.createElement('div'); const style = document.createElement('style'); style.textContent = ` ha-card { /* sample css */ ha-card-box-shadow: var(--box-shadow); border-radius: var(--border-radius); } body { margin: 0; font-family: Arial, Helvetica, sans-serif; } .quotecontainer { position: relative; width: 100%; } .quotecenter { margin: auto; width: 90%; position: absolute; text-align: center; padding: 1px; line-height: 1; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; } .quotecontainer img { display: block; margin-left: auto; margin-right: auto; width: 100%; height: auto; ha-card-box-shadow: var(--box-shadow); border-radius: var(--border-radius); } /*=== Trigger ===*/ .animate { -webkit-animation-duration: 1s; animation-duration: 1s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } /*=== Optional Delays, change values here ===*/ .one { -webkit-animation-delay: 0.7s; -moz-animation-delay: 0.7s; animation-delay: 0.7s; } /*=== Animations start here ===*/ /*=== FADE IN ===*/ @-webkit-keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .fadeIn { -webkit-animation-name: fadeIn; animation-name: fadeIn; } `; content.innerHTML = `
`; card.appendChild(content); card.appendChild(style); root.appendChild(card); this._config = cardConfig; } // Helper method that checks if there are any changes to the states before it refreshes the card. See @swampen PR #41 in air-visual-card shouldNotUpdate(config, hass) { let clone = JSON.parse(JSON.stringify(config)) // Here, delete any config attribute that should not be checked for updates delete clone["image"] delete clone["feed_attribute"] delete clone["type"] let states = {} for (let entity of Object.values(clone)) { states[entity] = hass.states[entity] } if (JSON.stringify(oldStates) === JSON.stringify(states)) { return true } oldStates = states return false } set hass(hass) { const config = this._config; const root = this.shadowRoot; const card = root.lastChild; if (this.shouldNotUpdate(config, hass)) { return } this.myhass = hass; let card_content = ''; let quote_content = ``; const image = config.image || "/hacsfiles/quote-of-the-day-card/bg.jpg"; const entity = config.entity; const feed_attribute = config.feed_attribute; card_content += `
`; if (hass.states[entity]) { const quoteList = feed_attribute ? hass.states[entity].attributes[feed_attribute] : hass.states[entity].attributes; var quoteArray = []; // Build an array of keys while walking through quoteList dictionary. // The If statement filters out common HA entity attributes like 'friendly_name', 'icon,' and 'homebridge_hidden'. Assumes remaining attributes are the RSS feed entries for (var quote in quoteList) { if (quoteList.hasOwnProperty(quote) && quote !== "friendly_name" && quote !== "icon" && quote !== "homebridge_hidden") { quoteArray.push(quote); } } // Selects random quote var quoteAuthor = quoteArray[quoteArray.length * Math.random() << 0]; var quote = quoteList[quoteAuthor] if (!quoteList) { throw new Error("Feed is !feed"); debugger; } if (quoteList == undefined) { throw new Error("Feed is undefined"); debugger; } // If statement also checks for values in 'summary' and 'title'. if (quote['summary'].length >= 60) { quote_content += `

${quote['summary']}

`; } else if (quote['summary'].length >= 140) { quote_content += `

${quote['summary']}

`; } else { quote_content += `

${quote['summary']}

`; } quote_content += `

${quote['title']}

`; card_content += quote_content card_content += `
` }; root.lastChild.hass = hass; root.getElementById('content').innerHTML = card_content; } getCardSize() { return 1; } } customElements.define('quote-of-the-day-card', QuoteOfTheDayCard);