[RELEASE] iFrameAdvanced

I made an advanced version of what was discussed here:

iFrameAdvanced

available via github or HPM
https://raw.githubusercontent.com/michaelbarone/hubitat/master/drivers/iFrameAdvanced.groovy

This driver will create 2 types of iFrames for you when you specify a url in the preferences:

  1. A basic iFrame attribute tile, that when set will display the content in a tile.

  2. a button (iFrameLauncher attribute) that will open a full screen overlay with the iFrame content.

See the test dashboard below using the webcam for my 3d printer, on the right is type 1 and on the left is the button for type 2

Check out this gif to see how 2 works.
iFrameAdvanced

type 2 has the following unique preferences:
The text for "Show", "Refresh" and "Close" can be edited in the device preferences along with an options for the height/width % of the iFrame when shown, and an option to load the iFrame content only when visible and unload when closed or have the iFrame content loaded when the dashboard loads.

Troubleshooting/limitations:

  • The link must be within 1024 characters or else an error will occur. The work around is to use an URL Shortener (Eg. Bitly). This is a limitation of hubitat dashboard tiles.
  • "REFUSED TO CONNECT" ERROR Due to security policies, some websites have an HTTP Header that do not allow iframes. If the URL does not work, try seeing if they have an "embed URL" OR "widget URL" instead.
  • If you receive a 500 error when adding new link in the driver, it is not related to the iframe. Instead, look to see if you have a valid link.

Changelog:

iFrameAdvanced
V1.0.0: 2021-07-02

  • Initial Release
12 Likes

This is amazing. Can't wait to try and use this to overlay a simple dashboard with something like a thermostat control, perhaps housed inside a local html file to include a semi-transparent background to make it seem like the controls are opening up over the main dashboard.

EDIT: Posted some early playing with the driver here:

is there a way to get it to pop up in the middle of the screen?

Yes, but you will have to play with the code a little bit to center it depending on what you are displaying, and your screen size. I have not had time to really fine tune this addon.

If you make progress or find something that works, please post here or feel free to submit a pull request for additional functionality.

line 98 just add top:25%;left:25%; and it puts in bang in the middle for a 50% frame

        launcher = launcher + " style='height:${height}%;width:${width}%;border:none;left:0;position:absolute;top:25%;left:25%;'></iframe></div>"
1 Like

and 10% by 10% for an 80% by 80% frame
just don't fully understand the relationship

unless
10%80%10% =100
25%5025% = 100

posleft = (100 - width )/2 +"%"
posright = (100 - width)/2 +"%"

also added larger font for the exit button

<font size='+3'> <b> ${closeText} </b> </font>

updated code with character count

Summary
/**
 *  dashboard iFrame Advanced
 *
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *
 *
 *
 *  Directions:  
 *     1   Create a virtual device with this driver.  
 *     2   add the url you want to embed to the preferences of this device.
 *     3   add this device to your dashboard, select the attribute and choose the "iFrame" attribute
 *
 *	   optional:
 *     4   update the css to style the iframe tile on the dashboard:
 *
 *		// replace '#tile-33' with this driver/device on your dashboard
 *	
 *		#tile-33 .tile-title {
 *			display:none;
 *		}
 *
 *
 *
 *
 *
 *
 *  Change History:
 *
 *    Date            Who            What
 *    ----            ---            ----
 * 	 07-02-2021 	mbarone			initial release 
 */

def setVersion(){
	state.version = "1.0.1"
}

preferences {
        input("src", "text", title: "iFrame Url",  required: true)
        input("openText", "text", title: "Button text to Open iFrame", defaultValue:"Show",  required: false)
        input("closeText", "text", title: "Button text to close iFrame", defaultValue:"Close", required: false)
        input("refreshText", "text", title: "Button text to refresh iFrame content", defaultValue:"Refresh", required: false)
		input("width", "number", title: "Width of iFrame when in view as a percentage (default: 100)", defaultValue:100, required: false)
		input("height", "number", title: "Height of iFrame when in view as a percentage (default: 100)", defaultValue:100, required: false)
        input("delayLoad", "bool", title: "On Demand iFrame Loading", description: "When DISABLED the iFrame will load with the dashboard and remain connected even when not visible.  When ENABLED the iFrame will only load content when visible, it will unload when closed and reload each time you open it.", defaultValue:false,  required: false)
    }
metadata {
    definition (name: "iFrameAdvanced", namespace: "mbarone", author: "mbarone", importUrl: "https://raw.githubusercontent.com/michaelbarone/hubitat/master/drivers/iFrameAdvanced.groovy") {
        capability "Actuator"
        attribute "iFrame", "text"
        attribute "iFrameLauncher", "text"
        attribute "urlSize", "text"
    }
}
def installed() {
    setIframe()
}
def updated() {
    setIframe()
}
def setIframe() {
    if(src && src != ""){
        sendEvent(name: "iFrame", value: "<div style='height: 100%; width: 100%'><iframe src='${src}' style='height: 100%; width:100%; border: none;'></iframe><div>")
        
        String posL = (100 - width )/2 +"%"
        String posR = (100 - height)/2 +"%"

        String launcher = ""
        
        if(delayLoad == true){
            launcher = launcher + "<button style='height:100%;width:100%;' onclick=document.getElementById('${device.displayName.replaceAll('\\s','')}').style.display='block';document.getElementById('${device.displayName.replaceAll('\\s','')}-iframe').src='${src}';>${openText}</button>"
        } else {
            launcher = launcher + "<button style='height:100%;width:100%;' onclick=document.getElementById('${device.displayName.replaceAll('\\s','')}').style.display='block';>${openText}</button>"
        }
        launcher = launcher + "<div id=${device.displayName.replaceAll('\\s','')} class='modal' style='display:none;position:fixed;top:0;left:0;width:100%;height:100%;z-index:100;background-color:rgba(0,0,0,.85);'>"
        
        if(delayLoad == true){
            launcher = launcher + "<button onclick=document.getElementById('${device.displayName.replaceAll('\\s','')}').style.display='none';document.getElementById('${device.displayName.replaceAll('\\s','')}-iframe').src=''; style='float:right;margin:20px;'><font size='+3'><b>${closeText}</b></font></button>"
        } else {
            launcher = launcher + "<button onclick=document.getElementById('${device.displayName.replaceAll('\\s','')}').style.display='none'; style='float:right;margin:20px;'><font size='+3'><b>${closeText}</b></font></button>"
        }
        launcher = launcher + "<button onclick=document.getElementById('${device.displayName.replaceAll('\\s','')}-iframe').src='${src}'; style='float:right;margin:20px;'>${refreshText}</button>"

        if(delayLoad == true){
            launcher = launcher + "<iframe id='${device.displayName.replaceAll('\\s','')}-iframe' src=''"
        } else {
            launcher = launcher + "<iframe id='${device.displayName.replaceAll('\\s','')}-iframe' src=${src}"
        }
        if(width > 90 && height > 95){
            launcher = launcher + " style='height:${height}%;width:${width}%;border:none;'></iframe></div>"
        } else {
            launcher = launcher + " style='height:${height}%;width:${width}%;border:none;left:0;position:absolute;top:${posR};left:${posL};'></iframe></div>"
        }
        
        theCount = launcher.size()
        sendEvent(name: "urlSize", value: theCount)
        sendEvent(name: "iFrameLauncher", value: launcher)
        launcher = ""
    } 
    else {
        log.warn "No website to embed.  Set iFrame Url in device preferences."
    }
}

Screen_Recording_20211209-191534_Chrome_1_2_1

1 Like

More interesting possibilities to achieve a similar experience to folders on my android phone...

FolderIFrame

Is there a how to or support guide anywhere for how to create one? Is there an additional app we need to create one?

I have simply installed the driver then created a virtual device that uses the driver, adjusting the settings to suit. Are you familiar with these steps or are there particular parts you are needing help with?

I thought that it would need to be added as a virtual device. But I don't seem to have a Type in the dropdown when creating one that seems to match. What device type do you select?

I just rebooted the hub and now there's an iframe option. Must have been stuck

1 Like

I'm new to this so hoping someone can provide a more detailed set of instructions how to use this driver. Specifically, are only certain formats for the "iFrame URL *" field. My utimiate goal is to get this page WunderMap® | Interactive Weather Map and Radar | Weather Underground to show-up on my Dashboard

If I enter that URL into my Virtual Driver nothing loads

All I can say at this stage is that you are not alone, I saw the same behaviour when I attempted to create an iFrame device using the same URL, whereas I was able to access it through a browser normally. I'm not sure if the HTTPS would cause any issues... I'd like to think not... Perhaps there is something in the site setup that prevents it from being embedded in an iFrame....

This…

Generally a meta tag with one of:

X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN

Edit: Looks like your site is using crossorigin checks in the JS to prevent loading.

2 Likes

Tried to put some google stuff in a frame, came up with the same issue

Thanks it does appear HTTPS is part of the problem as I took a local news site page and pasted URL and it didnt work. Removed the "s" and the iframe loaded so now I know at least the driver can work. My utimate goal is to get a google map to appear on my dashboard that shows traffic going from my house to work

1 Like

I would expect with Google they may provide you with a spot on the site where you can get the code to do the embedding in an iframe.

1 Like

You certainly get options to embed a map from the maps page (trust me, there is an option to embed, it just didn't get picked up in the screenshot)

I just don't know how to include live traffic.... Looks like there's some cool options on there.... Might even be worth a separate thread to this iFrame one...

When I was playing in that arena 10-12 years ago, the “cool” stuff required a developer key to get to the APIs, and you were limited to a few hundred accesses per day unless you went to the paid tiers.