I want to display a web page in kiosk mode on a 1080p monitor showing "what's on". The data can be scraped from an existing web page (which I don't control). It must then be displayed with some new formatting (background image, no scroll bars, new header and footer).
The original web page is updated at infrequent intervals. I am happy for my page to update every 15 minutes or so. My page should maximise the fonts to display as large as possible (and reduce the font on any overflow).
This is all being done on a Raspberry Pi Zero so horsepower is limited.
I am currently scraping the original web page using a perl program scheduled with cron. This program extracts the relevant table of data and adds new header and footer. To try to make the change seamless, my web page includes this new page as an iframe - actually two iframes that it swaps between so the rendering is invisible:
<body onload="load(); update();">
<h1>What's on this week</h1>
<div id="floating-div">
<iframe src="iframe.html" allowtransparency="true" frameborder="0" style="width:100%;height:100%;" id="if1"></iframe>
<iframe src="iframe.html" allowtransparency="true" frameborder="0" style="width:100%;height:100%;" id="if2"></iframe>
</div>
</body>
function update() {
if1 = document.getElementById("if1");
if2 = document.getElementById("if2");
if (if1.style.display == "none") {
if1.style.display = "block";
if2.style.display = "none";
if2.src = "iframe.html";
} else {
if2.style.display = "block";
if1.style.display = "none";
if1.src = "iframe.html";
}
}
function load() {
setInterval(update, 15000);
}
The iframe.html page (created by perl) is:
<body onload="set_size();">
<div class="cdiv">
<table id="calendar" class="weekly">
...
</table>
</div>
</body>
I am struggling on how to adjust the font size dynamically in the set_size() function. I can adjust the size on the visible iframe but this doesn't work on the one loading while invisible. The function I am using to detect overflow is:
function check(el) {
var curOverf = el.style.overflow;
if (!curOverf || curOverf === "visible")
el.style.overflow = "hidden";
var isOverflowing = el.clientWidth < el.scrollWidth ||
el.clientHeight < el.scrollHeight;
el.style.overflow = curOverf;
return isOverflowing;
}
How can I do this seamless display update with dynamic font sizing?
Apologies for the long post but I wanted to explain the whole problem I am trying to solve.
Ok, so I gave up on my original approach. I have now re-written the perl program to implement a Web Socket server which scrapes the web site every 15 minutes. If there is a change in the scraped data, it sends it to any connections.
The javascript in the local web page receives this data via a web socket and replaces the table that it had with the new table. The font resize routine then runs as before. Since the page is visible, it works as intended.
The downside is that this update will be visible. However, updates for the current week are infrequent so this is acceptable.
I use Squarespace for my portfolio site. They have a "block" that allows me to use embedded Adobe XD code (below) to show my app prototype. The prototype works fine but when the page loads, it automatically shifts half way down the page to the prototype. link to page
<center>
<iframe id="nautilab" width="414" height="736" src="https://xd.adobe.com/embed/afb3c48a-11a6-4296-73d9-068cd5b0c5ef-d982" allowfullscreen" frameborder="0">
</iframe>
</center>
I would like for my page to remain at the top when fully loaded instead of jumping down mid-page to the prototype. I've tried countless solutions such as using sandbox, lazy loading, and loading on scroll view. I've tried using "data src=""" as well among other options.
Unfortunately none of these solutions worked. The only time it doesn't jump down to the prototype is when it doesn't load at all (which happened with lazy loading, loading on scroll). How can I fix this? I'm able to use HTML, CSS, and JavaScript as well.
My best guess is to delay loading the prototype until it's in view. The only other option would be placing the prototype at the top of the page, which is not what I want (it messes up the flow of the project).
Any help is greatly appreciated!
Option 1: Use the "sandbox" attribute.
This appears to be a known issue within the Adobe Community site, with a solution proposed using the sandbox iframe attribute.
<iframe id="nautilab" width="414" height="736" src="https://xd.adobe.com/embed/afb3c48a-11a6-4296-73d9-068cd5b0c5ef-d982" allowfullscreen" frameborder="0" sandbox="allow-same-origin allow-forms allow-scripts"></iframe>
Or, possibly even more restrictive (which may cause the iframe not to work):
<iframe id="nautilab" width="414" height="736" src="https://xd.adobe.com/embed/afb3c48a-11a6-4296-73d9-068cd5b0c5ef-d982" allowfullscreen" frameborder="0" sandbox></iframe>
Option 2: Use the "onload" attribute with "scroll()"
If neither of the above work, you could try using the onload attribute to force the scroll position:
<iframe id="nautilab" width="414" height="736" src="https://xd.adobe.com/embed/afb3c48a-11a6-4296-73d9-068cd5b0c5ef-d982" allowfullscreen" frameborder="0" onload="scroll(0,0);"></iframe>
Option 3: Load the iframe only when in view.
If neither option 1 or 2 work, you could only load the iframe once it is already in view for the user (once they have scrolled down). For browsers that don't support IntersectionObserver, keep the external link as you have it. For browsers that do, hide the link and load the iframe. Insert the following via a code block above the image block that has your external link:
<iframe id="nautilab" width="0" height="0" frameborder="0" allowFullScreen></iframe>
Then insert the following via sitewide footer code injection
<script>
(function() {
var target,
io,
ioCallback,
ioOptions,
linkBlock;
// Exit if id "nautilab" not found.
target = document.querySelector('#nautilab');
if (!target) {
return;
}
// Check for IntersectionObserver Support: https://github.com/w3c/IntersectionObserver/issues/296#issuecomment-452230176
if (!('IntersectionObserver' in window) ||
!('IntersectionObserverEntry' in window) ||
!('intersectionRatio' in window.IntersectionObserverEntry.prototype)) {
target.style.display = "none";
return;
}
// Because IntersectionObserver is supported, hide external link to prototype.
linkBlock = document.querySelector('#block-yui_3_17_2_1_1574114822673_377170');
linkBlock.style.display = "none";
// Loads the iframe when the 'target' is in view.
ioCallback = function(entries, observer) {
entries.forEach(function(entry) {
if (entry.intersectionRatio) {
observer.disconnect();
target.height = "736"
target.width = "414";
target.src = "https://xd.adobe.com/embed/afb3c48a-11a6-4296-73d9-068cd5b0c5ef-d982";
}
});
};
ioOptions = {
root: null,
rootMargin: "0px",
threshold: 1
};
// Observe for 'target' to be in view.
io = new IntersectionObserver(ioCallback, ioOptions);
io.observe(target);
})();
</script>
You'll still have to center the prototype using CSS, which shouldn't be too difficult.
I'm building a portfolio site; it's a one pager with a lightbox functionality. So, basically I am showing HTML5 ads I have built, which I am embedding in an iFrame. These ads have audio, so when I close out of the lightbox the audio continues to play. Now I have tried different methods but have been unsuccessful. I have tested one method which worked, where I removed the src of the iFrame (ONE iFrame which I assigned an ID). Like so:
**HTML:**
<iframe id="test" class="iframe-src" src="media/rogue-nation/300x250-progressive-post/index.html" width="300" height="250" style="border:none"></iframe>
**JavaScript:**
var test;
var lightbox;
test = document.getElementById('test');
lightbox = document.getElementById('lightbox');
lightbox.addEventListener("click", closeLightbox, false);
function closeLightbox() {
...
test.src = "none";
}
So...my questions are:
What is the "best" way to apply this method to each iFrame depending on which one was interacted with (tried, getElementsByClassName but was unsuccessful)
Is there a way to disable the scripts within an iFrame so I don't have to use this method, as I am not so crazy about it
Also, please don't post jQuery solutions or advise me to use jQuery, as it will not be helpful because I am writing plain JavaScript
Thanks in advance!
If your iframe content lives on the same domain it is easy. You could do something like this when your lightbox closes:
function closeLightbox() {
// get the iframe which is playing audio
var iframe = document.getElementById('iframe');
// make sure you can reference the audio element on the iframe
// e.g. with an id.
var sound = iframe.contentWindow.document.getElementById('sound');
sound.pause();
sound.currentTime = 0;
// then close the lightbox with some other code
// ...
}
JSBin Demo
<body style="margin:0px;padding:0px;overflow:hidden" onload="img.src='http://sjabbo.net/logo.png?'+(+new Date())">
<img id="img"
onload="iframe.src='http://sjabbo.net'"
onerror="iframe.src='offline.html'"
width="0px" height="0px">
<iframe width="100%" height="1000px"></iframe>
</body>
So, if the local user has an internet connection, then the iframe should change to "http://sjabbo.net" but if not, then "offline.html"
but it does not seem to work.
How about this:
<body style="margin:0px;padding:0px;overflow:hidden">
<img id="img" src="http://sjabbo.net/logo.png"
onload="document.getElementById('iframe').src='http://sjabbo.net'"/>
<iframe src="offline.html" id="iframe" width="100%" height="1000px"></iframe>
</body>
You could introduce "testing" page like this:
<body style="margin:0px;padding:0px;overflow:hidden">
<img id="img" src="http://sjabbo.net/logo.png"
onload="document.getElementById('iframe').src='http://sjabbo.net'"
onerror="document.getElementById('iframe').src='offline.html'"/>
<iframe src="testing.html" id="iframe" width="100%" height="1000px"></iframe>
</body>
First, you can't just use "img", because, to JavaScript, it's not defined anywhere globally. If you want to access the image by its ID, you need to do the following. Also, I'm guessing you want to have a timestamp instead of the long date. Put something like this in your onload:
document.getElementById('img').src = 'http://sjabbo.net/logo.png?' + (new Date()).getTime()
Do the same with your iframe (you'll have to assign it an ID first).
I don't think you've understood how web works.
You don't need to add an onload to every element that has a child. Each element is created one after another. So for now remove all your onloads.
You seem to want to wait to know if your image gets loaded correctly or not. Depending on this you want to activate your iframe.
You'll want to create a javascript tag ( or for good practice, create a js file ).
var img = document.getElementById('img'),
iframe = document.getElementById('iframe'); //add iframe as an id to your iframe
img.onload = function(){
//this is called when the image is finished loading.
iframe.src = 'http://sjabbo.net';
};
img.onerror = function(){
//this is called when the image wasn't able to load properly
iframe.src = 'offline.html'; //To be honest this doesn't make much sense
//You should instead just hide the iframe and the image
iframe.style.visibility = 'none';
img.style.visibility = 'none';
};
img.src = 'http://sjabbo.net/logo.png?' + (new Date()).getTime();
For future programming please try to seperate your js and css from your html. It is not good practice what you are currently doing.
I have a hidden div containing a YouTube video in an <iframe>. When the user clicks on a link, this div becomes visible, the user should then be able to play the video.
When the user closes the panel, the video should stop playback. How can I achieve this?
Code:
<!-- link to open popupVid -->
<p>Click here to see my presenting showreel, to give you an idea of my style - usually described as authoritative, affable and and engaging.</p>
<!-- popup and contents -->
<div id="popupVid" style="position:absolute;left:0px;top:87px;width:500px;background-color:#D05F27;height:auto;display:none;z-index:200;">
<iframe width="500" height="315" src="http://www.youtube.com/embed/T39hYJAwR40" frameborder="0" allowfullscreen></iframe>
<br /><br />
<a href="javascript:;" onClick="document.getElementById('popupVid').style.display='none';">
close
</a>
</div><!--end of popupVid -->
The easiest way to implement this behaviour is by calling the pauseVideo and playVideo methods, when necessary. Inspired by the result of my previous answer, I have written a pluginless function to achieve the desired behaviour.
The only adjustments:
I have added a function, toggleVideo
I have added ?enablejsapi=1 to YouTube's URL, to enable the feature
Demo: http://jsfiddle.net/ZcMkt/
Code:
<script>
function toggleVideo(state) {
// if state == 'hide', hide. Else: show video
var div = document.getElementById("popupVid");
var iframe = div.getElementsByTagName("iframe")[0].contentWindow;
div.style.display = state == 'hide' ? 'none' : '';
func = state == 'hide' ? 'pauseVideo' : 'playVideo';
iframe.postMessage('{"event":"command","func":"' + func + '","args":""}', '*');
}
</script>
<p>Click here to see my presenting showreel, to give you an idea of my style - usually described as authoritative, affable and and engaging.</p>
<!-- popup and contents -->
<div id="popupVid" style="position:absolute;left:0px;top:87px;width:500px;background-color:#D05F27;height:auto;display:none;z-index:200;">
<iframe width="500" height="315" src="http://www.youtube.com/embed/T39hYJAwR40?enablejsapi=1" frameborder="0" allowfullscreen></iframe>
<br /><br />
close
Here's a jQuery take on RobW's answer for use hiding /pausing an iframe in a modal window:
function toggleVideo(state) {
if(state == 'hide'){
$('#video-div').modal('hide');
document.getElementById('video-iframe'+id).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*');
}
else {
$('#video-div').modal('show');
document.getElementById('video-iframe'+id).contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
}
}
The html elements referred to are the modal div itself (#video-div) calling the show / hide methods, and the iframe (#video-iframe) which has the video url as is src="" and has the suffix enablejsapi=1? which enables programmatic control of the player (ex. .
For more on the html see RobW's answer.
Here is a simple jQuery snippet to pause all videos on the page based off of RobW's and DrewT's answers:
jQuery("iframe").each(function() {
jQuery(this)[0].contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*')
});
Hey an easy way is to simply set the src of the video to nothing, so that the video will desapear while it's hidden an then set the src back to the video you want when you click on the link that opens the video.. to do that simply set an id to the youtube iframe and call the src function using that id like this:
<script type="text/javascript">
function deleteVideo()
{
document.getElementById('VideoPlayer').src='';
}
function LoadVideo()
{
document.getElementById('VideoPlayer').src='http://www.youtube.com/embed/WHAT,EVER,YOUTUBE,VIDEO,YOU,WHANT';
}
</script>
<body>
<p onclick="LoadVideo()">LOAD VIDEO</P>
<p onclick="deleteVideo()">CLOSE</P>
<iframe id="VideoPlayer" width="853" height="480" src="http://www.youtube.com/WHAT,EVER,YOUTUBE,VIDEO,YOU,HAVE" frameborder="0" allowfullscreen></iframe>
</boby>
Since you need to set ?enablejsapi=true in the src of the iframe before you can use the playVideo / pauseVideo commands mentioned in other answers, it might be useful to add this programmatically via Javascript (especially if, eg. you want this behaviour to apply to videos embedded by other users who have just cut and paste a YouTube embed code). In that case, something like this might be useful:
function initVideos() {
// Find all video iframes on the page:
var iframes = $(".video").find("iframe");
// For each of them:
for (var i = 0; i < iframes.length; i++) {
// If "enablejsapi" is not set on the iframe's src, set it:
if (iframes[i].src.indexOf("enablejsapi") === -1) {
// ...check whether there is already a query string or not:
// (ie. whether to prefix "enablejsapi" with a "?" or an "&")
var prefix = (iframes[i].src.indexOf("?") === -1) ? "?" : "&";
iframes[i].src += prefix + "enablejsapi=true";
}
}
}
...if you call this on document.ready then all iframes in a div with a class of "video" will have enablejsapi=true added to their source, which allows the playVideo / pauseVideo commands to work on them.
(nb. this example uses jQuery for that one line that sets var iframes, but the general approach should work just as well with pure Javascript if you're not using jQuery).
I wanted to share a solution I came up with using jQuery that works if you have multiple YouTube videos embedded on a single page. In my case, I have defined a modal popup for each video as follows:
<div id="videoModalXX">
...
<button onclick="stopVideo(videoID);" type="button" class="close"></button>
...
<iframe width="90%" height="400" src="//www.youtube-nocookie.com/embed/video_id?rel=0&enablejsapi=1&version=3" frameborder="0" allowfullscreen></iframe>
...
</div>
In this case, videoModalXX represents a unique id for the video. Then, the following function stops the video:
function stopVideo(id)
{
$("#videoModal" + id + " iframe")[0].contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*');
}
I like this approach because it keeps the video paused where you left off in case you want to go back and continue watching later. It works well for me because it's looking for the iframe inside of the video modal with a specific id. No special YouTube element ID is required. Hopefully, someone will find this useful as well.
You can stop the video by calling the stopVideo() method on the YouTube player instance before hiding the div e.g.
player.stopVideo()
For more details see here: http://code.google.com/apis/youtube/js_api_reference.html#Playback_controls
RobW's way worked great for me. For people using jQuery here's a simplified version that I ended up using:
var iframe = $(video_player_div).find('iframe');
var src = $(iframe).attr('src');
$(iframe).attr('src', '').attr('src', src);
In this example "video_player" is a parent div containing the iframe.
just remove src of iframe
$('button.close').click(function(){
$('iframe').attr('src','');;
});
Rob W answer helped me figure out how to pause a video over iframe when a slider is hidden. Yet, I needed some modifications before I could get it to work. Here is snippet of my html:
<div class="flexslider" style="height: 330px;">
<ul class="slides">
<li class="post-64"><img src="http://localhost/.../Banner_image.jpg"></li>
<li class="post-65><img src="http://localhost/..../banner_image_2.jpg "></li>
<li class="post-67 ">
<div class="fluid-width-video-wrapper ">
<iframe frameborder="0 " allowfullscreen=" " src="//www.youtube.com/embed/video-ID?enablejsapi=1 " id="fitvid831673 "></iframe>
</div>
</li>
</ul>
</div>
Observe that this works on localhosts and also as Rob W mentioned "enablejsapi=1" was added to the end of the video URL.
Following is my JS file:
jQuery(document).ready(function($){
jQuery(".flexslider").click(function (e) {
setTimeout(checkiframe, 1000); //Checking the DOM if iframe is hidden. Timer is used to wait for 1 second before checking the DOM if its updated
});
});
function checkiframe(){
var iframe_flag =jQuery("iframe").is(":visible"); //Flagging if iFrame is Visible
console.log(iframe_flag);
var tooglePlay=0;
if (iframe_flag) { //If Visible then AutoPlaying the Video
tooglePlay=1;
setTimeout(toogleVideo, 1000); //Also using timeout here
}
if (!iframe_flag) {
tooglePlay =0;
setTimeout(toogleVideo('hide'), 1000);
}
}
function toogleVideo(state) {
var div = document.getElementsByTagName("iframe")[0].contentWindow;
func = state == 'hide' ? 'pauseVideo' : 'playVideo';
div.postMessage('{"event":"command","func":"' + func + '","args":""}', '*');
};
Also, as a simpler example, check this out on JSFiddle
This approach requires jQuery. First, select your iframe:
var yourIframe = $('iframe#yourId');
//yourId or something to select your iframe.
Now you select button play/pause of this iframe and click it
$('button.ytp-play-button.ytp-button', yourIframe).click();
I hope it will help you.
RobW's answers here and elsewhere were very helpful, but I found my needs to be much simpler. I've answered this elsewhere, but perhaps it will be useful here also.
I have a method where I form an HTML string to be loaded in a UIWebView:
NSString *urlString = [NSString stringWithFormat:#"https://www.youtube.com/embed/%#",videoID];
preparedHTML = [NSString stringWithFormat:#"<html><body style='background:none; text-align:center;'><script type='text/javascript' src='http://www.youtube.com/iframe_api'></script><script type='text/javascript'>var player; function onYouTubeIframeAPIReady(){player=new YT.Player('player')}</script><iframe id='player' class='youtube-player' type='text/html' width='%f' height='%f' src='%#?rel=0&showinfo=0&enablejsapi=1' style='text-align:center; border: 6px solid; border-radius:5px; background-color:transparent;' rel=nofollow allowfullscreen></iframe></body></html>", 628.0f, 352.0f, urlString];
You can ignore the styling stuff in the preparedHTML string. The important aspects are:
Using the API to create the "YT.player" object. At one point, I only had the video in the iFrame tag and that prevented me from referencing the "player" object later with JS.
I've seen a few examples on the web where the first script tag (the one with the iframe_api src tag) is omitted, but I definitely needed that to get this working.
Creating the "player" variable at the beginning of the API script. I have also seen some examples that have omitted that line.
Adding an id tag to the iFrame to be referenced in the API script. I almost forgot that part.
Adding "enablejsapi=1" to the end of the iFrame src tag. That hung me up for a while, as I initially had it as an attribute of the iFrame tag, which does not work/did not work for me.
When I need to pause the video, I just run this:
[webView stringByEvaluatingJavaScriptFromString:#"player.pauseVideo();"];
Hope that helps!
This is working fine to me with YT player
createPlayer(): void {
return new window['YT'].Player(this.youtube.playerId, {
height: this.youtube.playerHeight,
width: this.youtube.playerWidth,
playerVars: {
rel: 0,
showinfo: 0
}
});
}
this.youtube.player.pauseVideo();
A more concise, elegant, and secure answer: add “?enablejsapi=1” to the end of the video URL, then construct and stringify an ordinary object representing the pause command:
const YouTube_pause_video_command_JSON = JSON.stringify(Object.create(null, {
"event": {
"value": "command",
"enumerable": true
},
"func": {
"value": "pauseVideo",
"enumerable": true
}
}));
Use the Window.postMessage method to send the resulting JSON string to the embedded video document:
// |iframe_element| is defined elsewhere.
const video_URL = iframe_element.getAttributeNS(null, "src");
iframe_element.contentWindow.postMessage(YouTube_pause_video_command_JSON, video_URL);
Make sure you specify the video URL for the Window.postMessage method’s targetOrigin argument to ensure that your messages won’t be sent to any unintended recipient.