// For learning purposes, I studied the following cards: // https://github.com/robmarkoski/ha-clockwork-card/blob/master/clockwork-card.js // Examples of using an HA entity's attributes: // This example looks into HA entity (sensor.spotify_playlist), the attribute called 'Unorganized', and sub attribute 'name' // const entityId = this.config.entity; // const playlist = hass.states[entityId].attributes; // ${playlist['Unorganized']['name']} // ${playlist['Unorganized']['image']} // ${playlist['Unorganized']['uri']} class SpotifyPlaylistCard extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); } setConfig(config) { const root = this.shadowRoot; if (root.lastChild) root.removeChild(root.lastChild); // Contains values of this Lovelace card configuration const cardConfig = Object.assign({}, config); // Default values of config options. Uses ternary statements const columns = config.columns ? config.columns : 3; const gradientLevel = config.gradient_level ? config.gradient_level : 0.8; const gridGap = config.grid_gap ? config.grid_gap : '8px'; // changes opacity to 0 to hide playlist title const showPlaylistTitles = config.show_playlist_titles ? 1 : 0; if (!config.sensor) { throw new Error('Please define the name of the Spotify Playlist sensor.'); } const card = document.createElement('div'); const content = document.createElement('div'); const style = document.createElement('style'); // Ideas: if 'column' and/or 'row' are not defined in options, then use this CSS to automatically organize playlists: // 'grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));' style.textContent = ` .outercontainer { margin:auto; display: grid; grid-template-columns: repeat(${columns}, 1fr); grid-gap: ${gridGap}; } .grid-item { position: relative; background-repeat: no-repeat; background-size: cover; background-position: center center; border-radius: 3px; } .grid-item::before { content: ''; display: block; padding-top: 100%; } .content { border-radius: 0 0 3px 3px; position: absolute; bottom: 0; opacity: ${showPlaylistTitles}; width: 100%; padding: 20px 10px 10px 10px; border: 0; text-align: left; color: rgba(255,255,255,1); box-sizing: border-box; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; background: rgb(0,0,0); background: -moz-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,${gradientLevel}) 30%, rgba(0,0,0,${gradientLevel}) 100%); background: -webkit-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,${gradientLevel}) 30%,rgba(0,0,0,${gradientLevel}) 100%); background: linear-gradient(to bottom, rgba(0,0,0,0) 0%,rgba(0,0,0,${gradientLevel}) 30%,rgba(0,0,0,${gradientLevel}) 100%); filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00000000', endColorstr='#db000000',GradientType=0 ); } `; content.innerHTML = `