Is it possible to loop and display nested iframes one by one in javaScript?
for instance:
<iframe id="iframe1" style="border: 0; position: absolute; display: none; width: 100%; height: 100%; left: 0; top: 0">
<p>iframe 1</p>
<iframe id="iframe2" style="border: 0; position: absolute; display: none; width: 100%; height: 100%; left: 0; top: 0">
<p>iframe 2</p>
<iframe id="iframe3" style="border: 0; position: absolute; display: none; width: 100%; height: 100%; left: 0; top: 0">
<p>iframe 3</p>
</iframe>
</iframe>
</iframe>
Well i can just say, explicitly if you dont need it to work this way (you can change the enviroment) change it!
for everyone else theres this little piece of code (well its bad but it works):
/* ty to -> https://stackoverflow.com/questions/1452871/how-can-i-access-iframe-elements-with-javascript */
function iframeRef( frameRef ) {
return frameRef.contentWindow ? frameRef.contentWindow.document : frameRef.contentDocument;
}
/* loop through frames and iframes, starts default at top */
function frameLooper(cb, rec = 0, base = top.document) {
return base.querySelectorAll('iframe:not(.hiddenFrame), frame:not(.hiddenFrame)').forEach(function(el, index){
var doc = iframeRef(el);
/* empty body -> gtfo */
if (!doc.body || !doc.body.children.length){
return true;
}
/* execute callback with -> iframe.document */
typeof cb == 'function' && cb(doc);
/* recursive callback */
rec && frameLooper(cb, rec, doc);
});
}
just go with your callback function as executable, you're getting the iframe document as parameter. And if you want to use this for nested frames too, set the second param to something truthy.
so as an example you may just start with
top.frameLooper(function(e){console.log(e);}, 1);
Edit:
forgott to mention that if you want the frame to get exluded add the class "hiddenFrame" to the iframe / frame.
Related
How can we move the iframe behind the div.
Here an sample below, I want to show "custom_title" div in front of the iframe.
It's initially showing but when we click the fullscreen, the "custom_title" div eventually gone.
Someone knows how to achieve this? I have here the codepen
Note: fullscreen icon does not display in the snippet, i don't know why. But you check out the codepen.
.title_container {
position: fixed;
z-index: 9999;
left: 50%;
transform: translateX(-50%);
top: 10%;
background-color: white;
color: black;
}
<div>
<iframe src="https://player.vimeo.com/video/347119375?color=ef2200&byline=0&portrait=0" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen="true" style="position:absolute;top:0;left:0;width:100%;height:100%;" title="0vid1.mp4" data-ready="true"></iframe>
<div class="title_container">Custom Title</div>
</div>
Fullscreen move pulls the video out of the document for the purposes of rendering. This leaves the text you positioned on top of it behind.
To achieve this you would need to make the div fullscreen and not the video (and then you'd need to format the video appropriately to get it to full the div).
I doubt you can override Vimeo's button to achieve that, so you'd need to add your own.
Full Screen option is disabled below so that Users use the button to make the iframe full screen.
To make the iframe full screen and show the div you can use:
Note: Try saving and running the code locally on your device as Stack Overflow's compiler is facing issues runnning it.
//https://jsfiddle.net/jlam55555/o5njka95/6/
function requestFullScreen(element) {
// Supports most browsers and their versions.
var requestMethod = element.requestFullScreen || element.webkitRequestFullScreen || element.mozRequestFullScreen || element.msRequestFullscreen;
if (requestMethod) { // Native full screen.
requestMethod.call(element);
} else if (typeof window.ActiveXObject !== "undefined") { // Older IE.
var wscript = new ActiveXObject("WScript.Shell");
if (wscript !== null) {
wscript.SendKeys("{F11}");
}
}
}
function makeFullScreen() {
document.getElementsByTagName("iframe")[0].className = "fullScreen";
var elem = document.body;
requestFullScreen(elem);
}
.title_container {
position: fixed;
z-index: 9999;
left: 50%;
transform: translateX(-50%);
top: 10%;
background-color: white;
color: black;
}
button{
position: fixed;
z-index: 9999;
left: 50%;
transform: translateX(-50%);
bottom: 20%;
}
iframe.fullScreen {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
<div>
<!-- Full Sceen option is disabled-->
<iframe src="https://player.vimeo.com/video/347119375?color=ef2200&byline=0&portrait=0" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" disablefullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="0vid1.mp4" data-ready="true"></iframe>
<div class="title_container">Custom Title</div>
</div>
<button onclick="makeFullScreen()">Make Full Screen</button>
Or you can disable the controls and use the Vimeo Player.js to add more functionalities and I ,also, think that the problem can be solved without hiding the full-screen option and using the button to make the iframe full screen, by the Vimeo Player.js, but that was complicated, so, you can try, but I am not sure.
I'm afraid specifically in this case there is no way to achieve this, because of how fullscreen api is working. If you want some-element to display in fullscreen mode you need this some-element to be inside of DOM element which is displaying in fullscreen.
In your case you need .title_container to be inside vimeo player's element, but you could not put it inside iframe unless there is no specific api to do this.
Read more about fullscreen on MDN https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API/Guide
Simple example of how it can be done by adding custom fullscreen button.
Try to run on your local environment, fullscreen seems to be not working on stackoverflow:
let $btn = document.querySelector('#toggle'),
$iframe = document.querySelector('iframe'),
$video = document.querySelector('#video');
$btn.addEventListener('click', function() {
if (document.fullscreenElement) {
document.exitFullscreen();
return;
}
$video.requestFullscreen();
})
document.addEventListener('fullscreenchange', (event) => {
if (document.fullscreenElement) {
$btn.innerHTML = 'Exit fullscreen'
} else {
$btn.innerHTML = 'Fullscreen'
}
});
#video {
position: relative;
display: inline-flex;
}
#video:fullscreen iframe {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
}
.title_container {
position: absolute;
z-index: 9999;
left: 50%;
transform: translateX(-50%);
top: 10%;
background-color: white;
color: black;
}
#video:fullscreen button {
position: absolute;
}
button {
position: absolute;
bottom: 4px;
right: 24px;
}
<div id='video'>
<iframe src="https://player.vimeo.com/video/347119375?color=ef2200&byline=0&portrait=0" frameborder="0" allow="autoplay; picture-in-picture" title="0vid1.mp4" data-ready="true"></iframe>
<div class="title_container">Custom Title</div>
<button id='toggle'>Fullscreen</button>
</div>
I am using an iframe tag to play a 9:16 aspect ratio video from my google drive. The iframe is wrapped around a div and the div is styled so that there are no black bars. The video is maintaining its aspect ratio but the thumbnail is not. The thumbnail covers all the wrapper's height but not the width. I want the thumbnail to also maintain the aspect ratio of 9:16.
Also, I did not add a custom thumbnail.
.potrait_9by16
{
position: relative;
overflow: hidden;
width: 100%;
padding-bottom: 177.777%; /* 9:16 Aspect Ratio*/
}
.potrait_9by16 iframe
{
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 100%;
height: 100%;
}
<div className="potrait_9by16">
<iframe
width="100%"
height="100%"
frameborder="0"
src={videoObject.src}
allow="fullscreen"
></iframe>
</div>
Here is an image of the wrapper
Try below at https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_video:
<!DOCTYPE html>
<html>
<body>
<style>
div.outer { overflow: hidden }
div.outer > div.inner { position: relative; margin: 0 -109.7283%; padding: 88.8888888% 0; overflow: hidden }
div.outer > div.inner > iframe { position: absolute; top: 0; right: 0; bottom: 0; left: 0 }
</style>
<div class="outer">
<div class="inner">
<iframe width="100%" height="100%" src="https://drive.google.com/file/d/16iDKGJXBszk2nI9h9BNG3rJ2zD85FSNy/preview">
</iframe>
</div>
</div>
</body>
</html>
It may mess up the video playback, though. The video controls (progress-bar etc.) get cropped when playback starts.
Replace the code there with the one I have provided.
I just checked your code, and looks like what you need is:
.x { overflow: hidden }
.neg { position: relative; margin: 0 -109.7283; padding: 88.8888888% 0 }
.neg > iframe { position: absolute; top: 0; right: 0; bottom: 0; left: 0 }
and use only x class for outer div, only neg class for inner div. That should probably do it.
I thought about removing the negative margin on playback, and was experimenting with something along those lines, but didn't get around to completing it. It should work to some extent, but what I found was that the black bordered thumbnail may be displayed for a short time before the playback starts (at least the way I tried it). If that's Ok, you could try that method. What I thought of was to display an invisible div (transparent overlay) covering the iframe that can capture a click and switch the iframe src to autoplay=1 URL. See if you can get that to work. If I have some time, I may look further into that.
I was adding a div using JavaScript with the same style as the iframe, just after the iframe:
.overlay { position: absolute; top: 0; right: 0; bottom: 0; left: 0 }
If this div is added last, it will already be topmost. Otherwise, use z-index.
Then handle the 'click' event on the div.
The above div overlay technique has it's limitations. The below technique may be better:
<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<title>Player</title>
<div id="player"></div>
body { background: #efe; padding: 2em; color: #575 }
h1:first-child { margin-top: 0 }
.player, #player { overflow: hidden }
.player > div, #player > div { position: relative; padding: 88.88888% 0; overflow: hidden }
.player video, .player iframe,
#player video, #player iframe
{ position: absolute; top: 0; right: 0; bottom: 0; left: 0 }
.player:not(.playing) > div, #player:not(.playing) > div
{ margin: 0 -109.7283% }
((W, D) => {
let $ = a => document.getElementById(a)
class Player {}
Player.play = (id, url) => {
let p = $(id)
, f = D.createElement('iframe')
, d = D.createElement('div')
f.src = url
f.setAttribute('frameborder', 0)
f.height =
f.width = '100%'
f.addEventListener( 'mouseover', e => f.dataset.overMe = 1 )
f.addEventListener( 'mouseout', e => delete f.dataset.overMe )
W.addEventListener( 'blur', e => {
if (f.dataset.overMe === '1')
setTimeout(a => p.classList.add('playing'), 1000)
} )
p.innerHTML = ''
d.appendChild(f)
p.appendChild(d)
}
W.Player = Player
})(window, document);
Player.play('player', 'https://drive.google.com/file/d/16iDKGJXBszk2nI9h9BNG3rJ2zD85FSNy/preview')
See if you can use this latest update with multiple iframes...
Your issue could be because you may be using an id (maybe the same id) with all player divs. When using multiple player divs, you need to use unique ids and use class="player" for the divs instead of id="player":
<div id="player-1" class="player"></div>
<div id="player-2" class="player"></div>
<div id="player-3" class="player"></div>
If it still doesn't work, show me a demo (on your site, maybe), and I'll take a look. Call the play method with the id like
Player.play('player-1', 'https://drive.google.com/file/d/16iDKGJXBszk2nI9h9BNG3rJ2zD85FSNy/preview')
Player.play('player-2', 'https://drive.google.com/file/d/16iDKGJXBszk2nI9h9BNG3rJ2zD85FSNy/preview')
I have added an attribute "id" to the slide. this id I need to work with, however I am not able to get this id somehow
jssor_slider2.$On($JssorSlider$.$EVT_PARK, function (slideIndex, fromIndex) {
//it fires when current slide swith to another
});
The moment this fires I want to be able to get this id, tried $(this).attr("id") and getElementById but does not work all result is undefined.
This is how my slide looks like:
<div id="330" debug-id="slide-0" style="width: 600px; height: 800px; top: 0px; left: -600px; position: absolute; overflow: hidden; transform: perspective(2000px);"><div class="slider" style="transform: perspective(2000px);">uhedcwecnw0</div><div u="thumb" class="" style="display: none; transform: perspective(2000px);"><img src="http://192.168.0.16:8081/img/home.gif" style="height: 25px; transform: perspective(2000px);"></div><div style="width: 600px; height: 800px; top: 0px; left: 0px; z-index: 1000; display: none;"></div></div>
Any simple way to get this id?
Assuming you want the slide corresponding to slideIndex or fromIndex.
jssor_slider1.$On($JssorSlider$.$EVT_PARK, function (slideIndex, fromIndex) {
var oldSlide = $('div[debug-id="slide-' + fromIndex + '"]').attr('id');
var newSlide = $('div[debug-id="slide-' + slideIndex + '"]').attr('id');
});
jssor_slider1.$On($JssorSlider$.$EVT_PARK, function (slideIndex, fromIndex) {
var content = $("#330").html();
});
how can i fix this? when i click "smile" it appears smile but when i click sad it also appear a smiley face.
SMILE<br>
<div id="light"><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Smiley.svg/1024px-Smiley.svg.png" width=100 height=100></div>
SAD
<div id="light"><img src="http://www.clipartbest.com/cliparts/MiL/kkB/MiLkkBAia.png" width=100 height=100></div>
<div id="fade" onClick="lightbox_close();"></div>
CSS: fade for the close and light is for the the lightbox.
#fade{
display: none;
position: fixed;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
background-color: #000;
z-index:1001;
-moz-opacity: 0.7;
opacity:.70;
filter: alpha(opacity=70);
}
#light{
display: none;
position: absolute;
top: 50%;
left: 50%;
width: 300px;
height: 200px;
margin-left: -150px;
margin-top: -100px;
padding: 10px;
border: 2px solid #FFF;
background: #CCC;
z-index:1002;
overflow:visible;
javascript: for the open and close function
window.document.onkeydown = function (e)
{
if (!e){
e = event;
}
if (e.keyCode == 27){
lightbox_close();
}
}
function lightbox_open(){
window.scrollTo(0,0);
document.getElementById('light').style.display='block';
document.getElementById('fade').style.display='block';
}
function lightbox_close(){
document.getElementById('light').style.display='none';
document.getElementById('fade').style.display='none';
You cannot use the same ID twice. You must use unique ID's.
Try this:
In the HTML, give your two light divs each a unique ID, for example lightSmile and lightSad.
In order to be able to use the same CSS for both lightboxes, give both boxes a class lightbox, and in the CSS, change the #light to .lightbox.
Finally, change the lightbox_open() function to the one below here.
HTML
SMILE<br>
<div class="lightbox" id="lightSmile"><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Smiley.svg/1024px-Smiley.svg.png" width=100 height=100></div>
SAD
<div class="lightbox" id="lightSad"><img src="http://www.clipartbest.com/cliparts/MiL/kkB/MiLkkBAia.png" width=100 height=100></div>
<div id="fade" onClick="lightbox_close();"></div>
CSS
.lightbox{
display: none;
...
}
JS
function lightbox_open(id){
window.scrollTo(0,0);
document.getElementById(id).style.display='block';
document.getElementById('fade').style.display='block';
}
function lightbox_close(){
document.getElementById('lightSmile').style.display='none';
document.getElementById('lightSad').style.display='none';
document.getElementById('fade').style.display='none';
}
If you look at the HTML, you see that now a string of the lightbox's ID is send along when lightbox_open() is called.
In the function, this ID-string is supplied as a variable (between the brackets: id). And in the line where lightbox's display-style is changed, this id is used.
In the close-function, the display-style of both the lightbox's is set back to default.
UPDATE
If you have a lot of lightboxes, it's easier to access the lightboxes by classname in the close-function:
function lightbox_close(){
var list = document.getElementsByClassName('lightbox');
for (var i=0; i<list.length; i++) {
list[i].style.display = 'none';
}
document.getElementById('fade').style.display='none';
}
And if you're willing to use jQuery, you can do that with one line (and probably more reliably cross-browser):
function lightbox_close(){
$('.lightbox').css('display','none'); //<--------------jQuery
document.getElementById('fade').style.display='none';
}
I want to trigger an event whenever the user scrolls up or down inside an invisible div (a 'scroller'). Imagine the below setup :
CSS
#scroller {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 50px;
}
#scroller div {
position: absolute;
top: 0px;
left: 0px;
height: 50000px;
width: 100%;
}
span {
position: absolute;
top: 20px;
left: 100px;
}
HTML
<div id="scroller"><div></div></div>
<span></span>
Javascript
var timeout;
$("#scroller").scroll(function ()
{
clearTimeout(timeout);
$('span').text('scrolling');
timeout = setTimeout(function ()
{
$('span').text('');
}, 1000);
});
Whenever the user scrolls inside the above div, the word "scrolling" should appear on the screen. You can play around with this fiddle : http://jsfiddle.net/f1hxndt4/4/
There are two problems with the above :
Scrolling inside the 'scroller' obviously needs to be infinite (up and down) - Currently it only allows a 50000px scroll.
The "scroller" needs to be invisible. Currently the scrollbars are visible.
Any suggestions would be much appreciated, thank you!
Here is the solution in case anyone is interested : http://jsfiddle.net/f1hxndt4/14/
CSS
#scroller{
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 50px;
overflow: hidden;
}
#scroller .parent{
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100px;
overflow-x:hidden;
}
#scroller .child {
position: absolute;
top: 0px;
left: 0px;
height: 50000px;
width: 100%;
}
span {
position: absolute;
top: 20px;
left: 100px;
}
HTML
<div id="scroller">
<div class="parent">
<div class="child"></div>
</div>
</div>
<span></span>
Javascript
var timeout;
$("#scroller .parent").scroll(function ()
{
clearTimeout(timeout);
$('span').text('scrolling');
timeout = setTimeout(function ()
{
$('span').text('');
}, 1000);
});
Explanation :
You need to create a scrollable <div> : $('#scroller .parent') and then place that inside a narrower <div> : $('#scroller'). Set the overflow of the latter to 'hidden'.
That way the scrollbar on the right side of $('#scroller .parent') will not be visible anymore.
If you bind to the 'scroll' event, then you will need to make the area scrollable (which as you say, defeats the point of the what you're trying to acheive!). Instead, you need to listen for the events that would otherwise usually cause scrolling, such as listening for mousehweel events. You may also wish to listen for swipe events etc.
You can calculate scroll distance by using the wheelData property of the event to detemrine the scroll delta. (In Firefox and opera you will need to use the detail property instead.)
var onMouseWheelEvent = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll"
: "mousewheel";
var timeout;
$("#scroller").on(onMouseWheelEvent, function (e)
{
clearTimeout(timeout);
$('span').text('scrolling');
var scrollEvent = e.originalEvent;
var delta = scrollEvent.detail? scrollEvent.detail*(-120) : scrollEvent.wheelDelta
console.log(e.originalEvent.wheelDelta);
timeout = setTimeout(function ()
{
$('span').text('');
}, 1000);
});
Demo: http://jsfiddle.net/techsin/o2n2q5p4/
Improved: http://jsfiddle.net/techsin/o2n2q5p4/1/
This is similar to link you posted however it dosen't rely on scrolled up amount but creates its own amount relying on mousewheel data. I tried to solve your original problem instead.
if anything is unclear just ask: (no jquery used just for challenge)
var a=0, topSpeed = 20, deg=0;
window.addEventListener('mousewheel', function(e){
if (a<topSpeed) {
a = a + ((e.wheelDelta/1000) * topSpeed);
}
});
var img = document.getElementById('gear');
function animate() {
a = +(a*.95).toFixed(2);
if (Math.abs(a)<1) a=0;
deg = (deg+a) % 360;
img.style.transform = 'rotate('+deg+'deg)';
requestAnimationFrame(animate);
}
animate();