Thanks again, Bryan. Great app!
Sharp tools?
Nice! Care to share your tile settings? Like the size of the tiles for an iPhone.
Standard HE Dashboard
nice work, thanks
Would love to see the code!
I plan to release the full dashboard. Iām going to get another hub that I can share development dashboards from.
Hi, I like your tiles; I have added a test dashboard to my setup and applied your code, but I have one query. Have you worked out to apply the css to the different states of a tile? For example, the switch tile has two states (on and off), I would like to apply a different border color to each of these states, but can't work out how to do it. I see that you have applied a border using css to the date-clock tile, but I suspect that this has only one state.
What is the URL you are using for theweather.com? I couldn't figure that one out.
That widget is completely customizable and then you get your own URL to use.
Take a look here.
Unfortunately (until CSS psuedo :has() selector is adopted by browsers) it's not possible without the use of jQuery/JavaScript which at this point I haven't found a way to inject. An option would be to have the border match one state color, so that when the state changes, it will stand out more. From a design perspective, doing this with a white "off" state would show a white border around the "on" state and it wouldn't be visible for the "off" state (would simply blend in to the off tile color).
I've done significant development on the smartly system and should be releasing in the next few weeks. If you'd like to help test, PM me! It's an online copy and paste one click updater where it intelligently updates the JSON for you. Additionally it allows an extra step for title replacement, custom labels for video and image tiles, individual tile icon replacement (per state!), useable (and visually pleasing) half-height tiles, screen-zoom calibration helper tile to perfectly visually fit the right number of tiles widthwise on any device.
Edit: looking for testers, PM me!
Thanks. Hadn't seen that page. Got a great customized weather widget now!
@anon81541053 What is your CSS code that changes the color of your tiles?
@spelcheck I suck at page design, but one thing I can help with is injecting Javascript, here's an example driver that does that for a custom attribute tile. It could be used together with some real data so as to not end up with an unused tile.
There's some limitations in this as of now, to inject the javascript "clear" and then "refresh" have to be run AFTER opening the Dashboard on which this tile is displayed. This is a problem that can be fixed, I just haven't had the time yet. But throwing this out there and maybe someone with time can fix that last bit and we can get to see some cool things done. CSS needs to be saved in the Dashboard since there's only 2*1024 characters available. 1024 characters per attribute is available.
This example code just shows an ugly modal dialog, but it does showcase all you need to insert external JS as well as arbitrary HTML.
I want a temperature tile which changes color gradually depending on temperature... Anyone up for the challenge in javascript?
metadata {
definition(name: "JavaScript Injector", namespace: "markus-li", author: "Markus Liljergren") {
command "refresh"
command "clear"
attribute "javascript", "string"
attribute "javascriptLength", "number"
attribute "html", "string"
attribute "htmlLength", "number"
}
preferences {
}
}
void updated() {
log.info "Updated..."
refresh()
}
String escapeForInsert(String myInsert) {
myInsert = myInsert.replace('"', '\\\"').replace("'", "'")
escapedInsert = ""
myInsert.eachLine {
escapedInsert += it.trim() // '\\\n'
}
return escapedInsert
}
void refresh() {
// Do NOT use single-quotes (') in tags or any markup, ONLY use doubles-quotes (")!
// Don't put CSS directly after "'''", start on the line below
// The CSS needs to be saved MANUALLY into the Dashboard
// There's not enough characters to insert it from here...
String myCSS = '''
.modal {
font-family: -apple-system,BlinkMacSystemFont,avenir next,avenir,helvetica neue,helvetica,ubuntu,roboto,noto,segoe ui,arial,sans-serif;
display: none;
position: absolute;
background-color: yellow;
z-index: 9999;
top: 50%;
left: 50%;
width: 200px;
height: 200px;
}
.modal.is-open {
display: block;
}
.modal-close-btn {
background-color: grey;
}
''' // Make sure this is on an empty last line, no CSS on this line
// Don't put HTML directly after "'''", start on the line below
String myHTML = '''
<div id="modal-1" class="modal" aria-hidden="true">
<div tabindex="-1" data-micromodal-close>
<div role="dialog" aria-modal="true" aria-labelledby="modal-1-title" >
<header>
<h2 id="modal-1-title">
Modal Title
</h2>
<button class="modal-close-btn" aria-label="Close modal" data-micromodal-close>Close Me</button>
</header>
<div id="modal-1-content">
Modal Content
</div>
</div>
</div>
</div>
''' // Make sure this is on an empty last line, no HTML on this line
// <div style="display:none;"></title></style></textarea></script></xmp><svg/onload='+/"/+/onmouseover=1/+/[*/[]/+function(){
String myScript = '''
<svg style="display: none;" onload='
var body = document.getElementsByTagName("body")[0];
var script = document.getElementById("inserted-body-script");
var hasScript = script != null;
if(!hasScript) {
script = document.createElement("script");
script.setAttribute("id", "inserted-body-script")
}
script.type = "text/javascript";
script.src = "https://cdn.jsdelivr.net/npm/micromodal/dist/micromodal.min.js";
if(!hasScript) {
body.appendChild(script);
alert(6);
} else {
MicroModal.show("modal-1");
alert(10);
}
script.onload = function() {
MicroModal.init({debugMode: true});
MicroModal.show("modal-1");
alert(2);
}
'></svg>'''
//}()//</div>'>
//'''
String myHTMLScript = '''
<a href="#" data-micromodal-trigger="modal-1">Open modal dialog</a>
<svg style="display: none;" onload='
var body = document.getElementsByTagName("body")[0];
var div = document.getElementById("inserted-body-html");
var hasDiv = div != null;
if(!hasDiv) {
div = document.createElement("div")
div.setAttribute("id", "inserted-body-html")
}
div.innerHTML = "\
''' + escapeForInsert(myHTML) + '''\
\
";
if(!hasDiv) {
body.prepend(div);
}
var script = document.getElementById("inserted-body-script");
if(script!=null) {
MicroModal.init({debugMode: true});
MicroModal.show("modal-1");
alert(9);
}
//alert(1);
'></svg>'''
String myJSMsg = "ms1 ${now()} ${myScript}"
sendEvent(name: "javascript", value: "${myJSMsg}", isStateChange: true)
sendEvent(name: "javascriptLength", value: "${myJSMsg.length()}", isStateChange: true)
String myHTMLMsg = "ht1 ${now()} ${myHTMLScript}"
sendEvent(name: "html", value: "${myHTMLMsg}", isStateChange: true)
sendEvent(name: "htmlLength", value: "${myHTMLMsg.length()}", isStateChange: true)
log.debug "Now: ${now()}, JS length: ${myJSMsg.length()}, HTTP length: ${myHTMLMsg.length()} Maximum is 1024"
}
void clear() {
sendEvent(name: "html", value: "No JS", isStateChange: true)
sendEvent(name: "javascript", value: "No JS", isStateChange: true)
}
void installed() {
log.info "Installed..."
refresh()
}
For staff: PLEASE don't patch this without providing an official way of injecting Javascript into dashboards...
Bravo my man! I'll PM you when I start testing, but well done exactly what was needed.
Where I can see we'd really benefit from this would be a recursive find and insert to take the actual status class from tile-primary and placing it at the parent tile level. It's crazy that all tile status classes are far within the tile itself, and colors are instead hard-coded in style of the tile element itself. The second thing we could really use this for is fixing the annoyances of ios webkit, like overscroll bounce, scroll-through, z-index shenanigans and heck even font size adjustments. Another worthwhile thing would be to hide and show (or minimize and maximize) the header on scroll down and up. Having the header just hard cut-off the scrollable area below it containing the tiles is very harsh. Having a background color fade in, and the entire header minimize would be pretty slick.
The flashiest thing we could do with it is enable parallax background effect, but that would really be icing on the cake.
I'll reach out to you, but I promise this will be used. +1 to HE not patching something like this until they offer a legitimate way to insert JS.
Considering that they do give us a way to use CSS it would be nice if they could tag the elements properly... But yes, now there is a way
Looking forward to it! There are many minor annoyances to fix.
See these are the flashy things I was hoping someone could do with this! I wouldn't have the time, too many other projects as well as rest of life...
I'm really hoping for a temperature tile with gradually changing colors based on if the temperature is above or below a set range. Set range in green (most intense in the middle, gradually changing towards the edges), above range fade towards red, below towards blue... Something like that, maybe a bit differently since this might not be clear, but you get my idea.
With this we can do whatever we want really, just a matter of time and effort. The limiting factor is code-length, but external JS can take care of that. It can be hosted locally on anything that can serve static files, so should be feasible for just about anyone.
Combined with tagging attributes in a custom driver and then use JS to extract and insert that class we can get really nice dynamic designs. Looking forward to seeing what you come up with using this
I've still not thought of (or at least not implemented) a way to host the JS files on HE, but if I do, that would make this 100% local to the hub... Though it wouldn't work in the cloud version of the dashboard with any of the methods I have in mind trying.
Which do reminds me, I've not tested this in the cloud version of the dashboard since I don't use that, but it does require testing. It "should" work, but let's not assume anything...
Do you know of a way to "embed" JS inside the CSS markup (without screwing it up) and then extract that using JS and insert it into the DOM as JS? That could make it possible to host JS locally "inside" the CSS field... Or maybe in the JSON configuration structure and parse that, since JSON is easy to work with in JS anyway. Will see if the JSON config can be reached through some undocumented API...
EDIT: I checked, the JSON is readily available from "/apps/api/1/dashboard/<dashboard id>/layout" and you can store whatever your want in that JSON, for example a "customJS" attribute Then just extract that attribute and insert it into the DOM...
EDIT 2: Moving this discussion to this thread.