From 12854807dd5cdd3ff6847da6c40e8fc8e8f73d32 Mon Sep 17 00:00:00 2001 From: luixal Date: Sat, 30 Dec 2023 13:42:26 +0100 Subject: [PATCH 1/3] Adds support for templates in image field --- media-source-image-card.js | 55 ++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/media-source-image-card.js b/media-source-image-card.js index f103a93..5a86c3e 100644 --- a/media-source-image-card.js +++ b/media-source-image-card.js @@ -32,6 +32,11 @@ class MediaSourceImageCard extends HTMLElement { -webkit-filter: grayscale(); } + .error { + font-size: large; + color: red; + } +
@@ -44,6 +49,31 @@ class MediaSourceImageCard extends HTMLElement { } } + renderTemplate(template) { + return new Promise( + resolve => { + this._hass.connection.subscribeMessage( + output => { + return resolve(output.result); + }, + { + type: 'render_template', + template + } + ); + } + ); + } + + getImageUrl(image) { + return new Promise( + resolve => { + if (this.config.image.indexOf('{{') > -1) return resolve(this.renderTemplate(image)); + return resolve(image); + } + ); + } + setConfig(config) { if (!config.image) { throw new Error('You have to provide an url for a media source image'); @@ -57,16 +87,19 @@ class MediaSourceImageCard extends HTMLElement { if (!this.content) this.renderBase(); // resolve image from media source and render it: if (!this.image || this.image != this.config.image) { - this.image = this.config.image; - hass.callWS({ - type: "media_source/resolve_media", - media_content_id: this.config.image - }).then(response => { - this.content.innerHTML = ` - - `; - } - ); + this.getImageUrl(this.config.image) + .then(imageUrl => { + this.image = imageUrl; + hass.callWS({ + type: "media_source/resolve_media", + media_content_id: this.image + }).then(response => { + this.content.innerHTML = ``; + }).catch(error => { + this.content.innerHTML = `Error loading image: ${error.message} `; + console.error({config: this.config, error}); + }); + }) } // apply grayscale: if (this.config.entity_id) { @@ -124,7 +157,7 @@ window.customCards.push({ }); console.info( - `%c MEDIA SOURCE IMAGE CARD %c Version 0.1.0 `, + `%c MEDIA SOURCE IMAGE CARD %c Version 0.1.2 `, 'color: orange; font-weight: bold; background: black', 'color: white; font-weight: bold; background: dimgray', ); From 04897b3a669abf2f8fbdde895a71f6a549d6320c Mon Sep 17 00:00:00 2001 From: luixal Date: Sat, 30 Dec 2023 14:11:57 +0100 Subject: [PATCH 2/3] Adds support for JS templates in image field --- media-source-image-card.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/media-source-image-card.js b/media-source-image-card.js index 5a86c3e..4a5fe48 100644 --- a/media-source-image-card.js +++ b/media-source-image-card.js @@ -65,10 +65,16 @@ class MediaSourceImageCard extends HTMLElement { ); } + renderJsTemplate(template) { + let _template = template.replace('[[[', '').replace(']]]', ''); + return new Function('hass', 'states', 'user', 'config', `'use strict'; ${_template}`).call(this, this._hass, this._hass.states, this._hass.user, this.config); + } + getImageUrl(image) { return new Promise( resolve => { if (this.config.image.indexOf('{{') > -1) return resolve(this.renderTemplate(image)); + if (this.config.image.indexOf('[[[') > -1) return resolve(this.renderJsTemplate(image)); return resolve(image); } ); From f4b344f222973370552fca2cd28ebdc626e73c9b Mon Sep 17 00:00:00 2001 From: luixal Date: Sat, 30 Dec 2023 14:20:13 +0100 Subject: [PATCH 3/3] Add templating docs --- README.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/README.md b/README.md index 5cc073e..14693a3 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,57 @@ tap_action: If no `target` is provided, the `entity_id` field is used. +### Templating +You can use templates in the `image` field. In fact, you can use jinja2 and javascript templates. + +The main difference is that jinja templates are rendered in the server and tend to hit perfomance overall while javascript templates run locally in the browser and need no additional messaging with the server. + +Personally, I prefer javascript templates :) + +#### Jinja2 Templates +You can use jinja templates like this: + +```yaml +type: custom:media-source-image-card +image: | + media-source://media_source/local/{{ states('input_text.image') }} +entity_id: input_boolean.boolean_test +apply_grayscale: true +tap_action: + action: call-service + service: input_boolean.turn_on + target: + entity_id: input_boolean.boolean_test +``` + +#### Javascript Templates +You can also provide a javascript template like this: + +```yaml +type: custom:media-source-image-card +image: | + [[[ + return `media-source://media_source/local/${ hass.states['input_text.texting'].state }`; + ]]] +entity_id: input_boolean.boolean_test +apply_grayscale: true +tap_action: + action: call-service + service: input_boolean.turn_on + target: + entity_id: input_boolean.boolean_test +``` + +You need to enclose your function between triple brackets ('[[[' and ']]]'). The variables available in the function are: + +| Variable | Description | +| -------- | ----------- | +| hass | The whole hass object where you can access everything | +| states | The states object inside `hass` | +| user | The object with information about the logged user | +| config | The card config itself | + + ## Examples ### Simple Image