I want to change the parent of an iframe which is used for embedding a YouTube video.
When I change the parent:
Firefox and Chrome: Player stops playing and displays a new (stopped) player in new parent.
IE: Player continues playing and displays a new (stopped) player in second div. So user sees a stopped player but hears video.
Here is the sample fiddle: https://jsfiddle.net/mehmetatas/znuUf/1/
try {
var div1 = $('#div1')
var video = div1.find('.video')[0];
var div2 = $('<div id="div2"></div>');
$(video).appendTo(div2);
div2.appendTo($('.parent'));
div1.remove();
}
catch (e) {
alert(e.message);
}
It seems like iframe content is getting refreshed when parent changes.
Is it possible to video continues playing in new parent?
If not, Firefox and Chrome's behavior is OK, then how can I fix IE's behavior?
What I can think of is you use classes instead of ids in you HTML/CSS like this:
<input id="btn" type="button" value="move"></input>
<div class="parent">
<div class="div1">
<div class="video">
<iframe width="300" height="200" src="http://www.youtube.com/embed/98LHnO0xiMY" frameborder="0" allowfullscreen></iframe>
</div>
</div>
</div>
and
.div1 {
position: absolute;
top: 50px;
width: 300px;
height: 200px;
border: solid 3px green;
}
.div2 {
position: absolute;
top: 50px;
left: 325px;
width: 300px;
height: 200px;
border: solid 3px red;
}
This way in your js script you simply need to state:
var div1 = $('.div1')
div1.removeClass('div1')
div1.addClass('div2')
this way your div will be positioned as the new div2 class says and move without stopping or refreshing.
HERE IS THE UPDATED FIDDLE
Hope this is what you were looking for.
Related
I have a two div which HAVE to be displayed above each others using z-index;
Both however have to react to the same click event as if the event was propergated from a child to a parent.
Is this possible in any way?
here is an example
<body>
<div id="upper" style=" position: absolute; z-index: 1; width: 100px; height: 100px; background-color: #000"></div>
<div id="lower" style="position: absolute; z-index: 0; width: 120px; height: 120px; background-color: #00f"></div>
</body>
Both should be listening to native click events since the lower sibling could hold an iframe.
EDIT For More Clerifications
The Goal is to make the youtube iframe in this example clickable as well as keep all the controls on the canvas element.
https://playground.babylonjs.com/#1DX9UE#51
Just write a Javascript event listener to click the other button when one is clicked.
document.getElementById('upper').addEvenListener('click', () => {
console.log('parent clicked')
})
document.getElementById('lower').addEvenListener('click', () => {
document.getElementById('upper').click()
})
I have an iframe element that I'd like to make resizable and draggable. I'd also like for the user to be able to drag it around by clicking and dragging inside the iframe.
Here is a jsfiddle:
http://jsfiddle.net/t9DT8/9/
iframe element is wrapped into a container div. The container div is made resizable and draggable.
The problem is that when using pointer-events: none on the iframe, it passes the click event nicely, but then when dragging it around it becomes glued to the cursor and click events doesn't come through anymore. Try dragging the youtube video in jsfiddle for the demo.
Question: how to make iframe element draggable so that you can drag it by clicking inside the iframe element, and it would let you go once you stop dragging?
HTML:
<div class="demo">
<div id="resizable" class="ui-widget-content">
<iframe width="100%" height="100%" src="//www.youtube.com/embed/9ZkWjkvaKpA" class="ui-widget-content" frameborder="no" id="test" allowfullscreen></iframe>
</div>
</div>
JS:
$(function () {
$("#resizable").resizable({
helper: "ui-resizable-helper"
});
$("#resizable").draggable();
});
And CSS:
#resizable {
width: 150px;
padding: 15px;
cursor: move;
z-index: 1;
}
.ui-resizable-helper {
border: 10px solid #efefef;
margin: -10px;
}
#resizable iframe {
pointer-events: none;
z-index: 100;
}
Update: The solution appears to work fine on Firefox, "gluing" problem is only reproducible on Chrome :/
Here, my code works fine in IE10 but the scroll bar appears in chrome as well as the firefox.
it navigates to the link only when it is clicked by the border of the iframe. Moreover, the iframe is not clickable. Help me out....
<style>
.icon-remove-sign {
position: absolute;
top: 0;
right: 0;
</style>
$(document).ready(function(){
$('i.icon-remove-sign').on('click',function(e){
e.preventDefault();
pdfID = $(this).closest('.imagewrap')[0].id;
$('#dialog').dialog('open');
alert('Deleting '+pdfID+'');
$(this).closest('.imagewrap')
.fadeTo(300,0,function(){
$(this)
.animate({width:0},200,function(){
$(this)
.remove();
});
});
});
});
<div class="imagewrap">
<iframe src="http://team358.org/files/website/Basic_HTML_Tutorial.pdf#scrollbar=0&scrolling=0" width="150" height="100" scrolling="no"></iframe>
<i class=" icon-remove-sign"></i>
</div>
The scrollbar belongs to the PDF plugin, not to the <iframe>. So, as far as I know, you cannot control its appearance using HTML or CSS. That is also why the link only works when you click on the border : the border still belongs to the HTML page, but the PDF plugin doesn't delegate the clicks it receives back to the browser (I can't imagine how it could!)
Also, putting an <iframe> inside an <a> tag ? I've never seen that before and I'm not sure why you would want to do this.
Maybe you want to set your iframe to be the target of your link, like this ?
<iframe width="100%" height="100%" name="pdf_frame"></iframe>
<a href="http://team358.org/files/website/Basic_HTML_Tutorial.pdf"
target="pdf_frame">HTML Tutorial</a>
http://jsfiddle.net/p75wM/2/
EDIT : now that I understood your question, I think you'll find good information here : (also check out the update to that post)
<style>
.iframe_thumb {
position : relative;
overflow : hidden;
}
.iframe_thumb a {
position : absolute;
top : 0;
left : 0;
width : 100%;
height : 100%;
z-index : 10;
}
.iframe_thumb .delete {
postion : absolute;
top : 5px;
right: 0;
z-index : 11;
}
</style>
<div class="iframe_thumb">
<iframe src="http://team358.org/files/website/Basic_HTML_Tutorial.pdf#scrollbar=0&scrolling=0" width="100" height="100" scrolling="no"></iframe>
<img src="images/delete.png" />
</div>
Use a container div with style
<style>
#container{width: 500px; height: 300px; overflow: hidden;}
iframe{width: 518px; height: 318px;}
</style>
<body style="margin:0px; padding:0px; overflow:hidden;">
<div id="container">
<a href="http://team358.org/files/website/Basic_HTML_Tutorial.pdf">
<iframe src="http://team358.org/files/website/Basic_HTML_Tutorial.pdf" frameborder="0" scrolling="no" >
</iframe></a>
</div>
When I use image tags in html, I try to specify its width and height in the img tag, so that the browser will reserve the space for them even before the images are loaded, so when they finish loading, the page does not reflow (the elements do not move around). For example:
<img width="600" height="400" src="..."/>
The problem is now I want to create a more "responsive" version, where for the "single column case" I'd like to do this:
<img style="max-width: 100%" src="..."/>
but, if I mix this with explicitly specified width and height, like:
<img style="max-width: 100%" width="600" height="400" src="..."/>
and the image is wider than the available space, then the image is resized ignoring the aspect ratio. I understand why this happens (because I "fixed" the height of the image), and I would like to fix this, but I have no idea how.
To summarize: I want to be able to specify max-width: 100%, and also somehow make sure the content is not reflowed when the images are loaded.
UPDATE 2: (Dec 2019)
Firefox and Chrome now deal with this by default. Simply add the width and height attributes as normal. See this blog post for more details.
UPDATE 1: (July 2018)
I found a much cleverer alternate version of this: http://cssmojo.com/aspect-ratio-using-custom-properties-and-calc/. This still requires a wrapper element and it requires CSS custom properties, but I think it's much more elegant. Codepen example is here (credit to Chris Coyier's original).
ORIGINAL:
From this blog post by Jonathan Hollin: add the image's height and width as part of an inline style. This reserves space for the image, preventing reflow when the image loads, but it's also responsive.
HTML
<figure style="padding-bottom: calc((400/600)*100%)">
<img src="/images/kitten.jpg" />
</figure>
CSS
figure {
position: relative;
}
img {
max-width: 100%;
position: absolute;
}
The figure can be replaced with a div or any other container of your choice. This solution relies on CSS calc() which has pretty wide browser support.
Working Codepen can be seen here.
I'm also looking for the answer to this problem. With max-width, width= and height=, the browser has enough data that it should be able to leave the right amount of space for an image but it just doesn't seem to work that way.
I worked around this with a jQuery solution for now. It requires you to provide the width= and height= for your <img> tags.
CSS:
img { max-width: 100%; height: auto; }
HTML:
<img src="image.png" width="400" height="300" />
jQuery:
$('img').each(function() {
var aspect_ratio = $(this).attr('height') / $(this).attr('width') * 100;
$(this).wrap('<div style="padding-bottom: ' + aspect_ratio + '%">');
});
This automatically applies the technique seen on: http://andmag.se/2012/10/responsive-images-how-to-prevent-reflow/
At first I would like to write about the answer from october 2013. This was incomplete copied and because of them it is not correct. Do not use it. Why? We can see it in this snippet (scroll the executed snippet to the bottom):
$('img').each(function() {
var aspect_ratio = $(this).attr('height') / $(this).attr('width') * 100;
$(this).wrap('<div style="padding-bottom: ' + aspect_ratio + '%">');
});
img { max-width: 100%; height: auto; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="width:300px;border:1px solid red">
<img width="400" height="300" src="data:image/png;base64,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"/>
Some text
</div>
And we can see the text is afar from bottom. What is in this example incomplete/ incorrect? I will show it with correct example with pure JavaScript (we do not need to download jQuery for that).
Correct example with pure JavaScript
Please scroll the executed snippet to the bottom.
var imgs = document.querySelectorAll('img');
for(var i = 0; i < imgs.length; i++)
{
var aspectRatio = imgs[i].getAttribute('height') /
imgs[i].getAttribute('width') * 100;
var div = document.createElement('div');
div.style.paddingBottom = aspectRatio + '%';
imgs[i].parentNode.insertBefore(div, imgs[i]);
div.appendChild(imgs[i]);
}
.restrict-container div{position:relative}
img
{
position:absolute;
max-width:100%;
top:0; left:0;
height:auto
}
<div class="restrict-container" style="width:300px;border:1px solid red">
<img width="400" height="300" src="data:image/png;base64,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"/>
Some text<br>
<img width="400" height="300" src="data:image/png;base64,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"/>
Some text
</div>
The mistake from answer from october 2013: the image should be placed absolute (position:absolute) to the wrapped container but it is not so placed.
This is the end of my answer to this question.
For further information read more about:
What could we do with the new HTML5 technology for responsive images too? (this is previous extended version of my posting here. See there the second part).
For a css only solution, you can wrap the img in a container where the padding-bottom percentage reserves space on the page until the image loads, preventing reflow.
Unfortunately, this approach does require you to include the image aspect ratio in your css (but no need for inline styles) by calculating (or letting css calculate for you) the padding-bottom percentage based on the image height and width.
If many of your images can be grouped into a few standard aspect ratios, then you could create a class for each aspect ratio to apply the appropriate padding-bottom percentage to all images with that aspect ratio. This may save you a little time and effort if you are not dealing with a wide variety of image aspect ratios.
Following is some example html and css for an image with a 2:1 aspect ratio:
HTML
<div class="container">
<img id="image" src="https://via.placeholder.com/300x150" />
</div>
CSS
.container {
display: block;
position: relative;
padding-bottom: 50%; /* calc(100%/(300/150)); */
height: 0;
}
.container img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
The snippet below adds some extra html, css and javascript to create some visual top and bottom reference points and mimic a very slow loading image so you can visually see how the reflow is prevented with this approach.
const image = document.getElementById('image');
const source = 'https://via.placeholder.com/300x150';
const changeSource = () => image.src = source;
setTimeout(changeSource, 3000);
.container {
display: block;
position: relative;
padding-bottom: 50%; /* calc(100%/(300/150)); */
height: 0;
}
.container img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.top, .bottom {
background-color: green;
width: 100%;
height: 20px;
}
<div class="top"></div>
<div class="container">
<img id="image" src="" />
</div>
<div class="bottom"></div>
If I understand the requirements ok, you want to be able to set an image size, where this size is known only on content (HTML) generation, so it can be set as inline styles.
But this has to be independent of the CSS, and also prior to image loading, so also independent from this image sizes.
I have come to a solution tha involves wrapping the image in a div, and including in this div an svg that can be set to have proportions directly as an inline style.
Obviously this is not much semantic, but at least it works
The containing div has a class named img to show that it , well, should be an img
To try to reproduce the loading stage, the images have a broken src
.container {
margin: 10px;
border: solid 1px black;
width: 200px;
height: 400px;
position: relative;
}
.img {
border: solid 1px red;
width: fit-content;
max-width: 100%;
position: relative;
}
svg {
max-width: 100%;
background-color: lightgreen;
opacity: 0.1;
}
#ct2 {
width: 500px;
}
.img img {
position: absolute;
width: 100%;
height: 100%;
max-height: 100%;
max-width: 100%;
top: 0px;
left: 0px;
box-shadow: inset 0px 0px 10px blue;
}
<div class="container" id="ct1">
<div class="img">
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 400 300" width="400">
</svg>
<img width="400" height="300" src="missing.jpg">
</div>
</div>
<div class="container" id="ct2">
<div class="img">
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 40 30" width="400">
</svg>
<img width="400" height="300" src="missing.jpg">
</div>
</div>
I find the best solution is to create a transparent base64 gif with corresponding dimensions as a placeholder for img tags where loading is triggered via js after page is loaded.
<img data-src="/image.png" src="data:image/gif;base64,R0lGODlhyAAsAYABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==">
For blog posts and such I use this PHP function to create them automatically
function CreatePreloadPlaceholderGif($width, $height) {
$wHex = str_split(str_pad(dechex($width), 4, "0", STR_PAD_LEFT), 2);
$hHex = str_split(str_pad(dechex($height), 4, "0", STR_PAD_LEFT), 2);
$hex = "474946383961".$wHex[1].$wHex[0].$hHex[1].$hHex[0]."800100ffffff00000021f904010a0001002c00000000010001000002024c01003b";
$base64= '';
foreach(str_split($hex, 2) as $pair){
$base64.= chr(hexdec($pair));
}
return base64_encode($base64);
}
echo CreatePreloadPlaceholderGif(300, 500);
// R0lGODlhLAH0AYABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
On the frontend the result is something like this
function loadimage() {
elements = document.querySelectorAll('img[data-src]');
elements.forEach( el => {
el.setAttribute('src', el.getAttribute('data-src'))
});
}
img {
background-color:#696969;
}
<div>300x500 image placeholder</div>
<img data-src="https://ibec.or.id/wp-content/uploads/2018/10/300x500.png" src="data:image/gif;base64,R0lGODlhLAH0AYABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==">
<div>After page load, run js command to replace src attribute with data-src</div>
<button onclick="loadimage()">Load image</button>
I'm relatively new to Web dev. The question is generic, but I'll pose specific user-cases.
Use-case 1:
I have a div element on a web page. When the page loads the first time, this div runs a small 5 sec animation. What I wish to do is, when this animation ends, I want the same div to contain some other element - it could be an image, a link, another animation etc.
That is, one container - the div - hosting multiple elements on a time-scale. First 5 secs animation , followed by an image or a link.
What Javascript methods will allow me to do so?
Use-case 2:
Again, I have a div element in a page. Now this div element is like a tabbed browser - you click on a different tab to view a different web page. Similarly, I wish to make this a "tabbed" div. As in, when the user hovers the mouse on tab 1, the div would show a video, when hovered over tab 2, it would show another video in the same div - that is, replacing the old video. The tabs can be considered as a fancy looking link.
Or, in the first place, is there an alternative to 'div' to do the things mentioned above?
Thanks,
SMK.
Solution for use case 2 -
This is a slightly lengthy solution but its extremely flexible and can be scaled up to any number of tabs very easily
We will divide the solution into 3 parts - The CSS, HTML and JQuery.
Lets take a look at the CSS part first
<style>
#tab_holder {
width: 350px; !important
}
#tab_holder .tabs {
float: left;
height: 20px;
padding: 5px;
border: 1px solid #eee;
border-bottom: none;
width: 50px;
cursor: pointer;
border-radius: 5px 5px 0 0;
}
#tab_holder .tabs:hover {
background-color: #eee;
}
#tab_holder #content_holder {
width: 400px; !important
margin: 0 0 0 0;
border: 1px solid #000;
padding: 10px;
float: left;
border-radius: 0 5px 5px 5px;
}
.content {
visibility: hidden;
}
</style>
Let us now take a look at the HTML part of this solution
<div id="tab_holder">
<div id="tab1" class="tabs">Video1</div>
<div id="tab2" class="tabs">Video2</div>
<div id="tab3" class="tabs">Video3</div>
<div id="content_holder">
<div id="main_content">Select a tab to see the video..</div>
</div>
</div>
<!-- These are divs in which you put your actual content.
They are always hidden -->
<div id="content1" class="content">
<iframe width="200" height="200" src="http://www.youtube.com/embed/4Z6YUGGlwtA?rel=0" frameborder="0" allowfullscreen></iframe>
< /div>
<div id="content2" class="content">
<iframe width="200" height="200" src="http://www.youtube.com/embed/s13dLaTIHSg?rel=0" frameborder="0" allowfullscreen></iframe>
</div>
<div id="content3" class="content">
<iframe width="200" height="200" src="http://www.youtube.com/embed/I1qHVVbYG8Y?rel=0" frameborder="0" allowfullscreen></iframe>
</div>
You can see that each tab is represented by a div which is using the "tabs" class from the CSS section. If you need to add a new tab, all you have to do is add a new div and give is a new id. For example to add a forth tab, you can say -
<div id="tab4" class="tabs">Video4</div>
It is as simple as that.
Now the thing I like about this approach is that you can place the content to be displayed also in div's, rather that nesting it under jquery. In this case we use the div's with the id content1 content2 content3
This gives you the flexibility to expand as you enter content into the div and use normal markup without getting confused and at ease.
These div's are not visible as we have set their visibility to hidden is CSS.
If you add a new tab div you must also add a new content div.
Now we move onto the JQuery part -
$(document).ready(function (){
/* Add the listeners. */
$("#tab1").mouseover(function (){
switch_content('content1')
});
$("#tab2").mouseover(function (){
switch_content('content2')
});
$("#tab3").mouseover(function (){
switch_content('content3')
});
});
function switch_content(name){
$("#main_content").fadeOut('fast',function (){
$("#main_content").html($("#"+name).html());
$("#main_content").fadeIn('fast');
});
}
The above JQuery function is extremely straight forward. Each tab is attached a action listener which is fired by a mousover event. So if you add another tab with the id=tab4 and its respective content div with the id=content4 then all you have to add in the jQuery is:
$("#tab4").mouseover(function (){
switch_content('content4')
});
So it becomes very easy to expand the code.
You can find a working demo of this on my website demo section
Tips -
Avoid using hover because it creates an annoying user experience due to accidental hovers and it is hard for mobile platforms to emulate this event. Most of them fall back to click. So I suggest use the click event instead.
If you must use, make use of the HTML video tag and pause the video using JS if the user hovers on another tab. This will render a better user experience.
Here is an example for use-case 1.
In your html you need to include the 5 second animation, i persume this is a gif? Although it can be any content. For the sake of this example i will show it as a div.
The html i have used:
<div id="example">
<div id="somecontent"> </div>
<div id="morecontent"> </div>
</div>
The CSS:
#example
{
width:500px;
height:500px;
background-color:#f00;
padding:10px;
}
#somecontent
{
width:200px;
height:200px;
background-color:#fff;
}
#morecontent
{
width:200px;
display:none;
height:200px;
background-color:#000;
}
and the javascript(using jQuery):
setTimeout(function() {
$("#somecontent").fadeOut("slow", function() {
$("#morecontent").fadeIn("slow");
});
}, 5000);
Have a look at this jsfiddle for it in action - http://jsfiddle.net/fntWZ/
For use case 2 it will be more complicated. Try having a look for some different plugins that could help with this
answer for use-case:1
css :
<style>
#myDiv {
height:0;
width:0;
position:absolute;
border:1px solid red;
}
</style>
script :
$(document).ready(function(){
$("#myDiv").animate({width:"100px", height:"100px"},5000, function(){
var image = new Image();
image.src = "dropdownContainerBottomMiddle.png"; //your image src goes here
$("#myDiv").append(image);
//you can append more content by using setTimeout function
setTimeout(function(){
var anc = "stackoverflow";
$("#myDiv").append(anc);
}, 1000);
});
});
html:
<div id="myDiv"></div>