I have a responsive site with a carousel. The user can embed a youtube video as one of the slides. On desktop this works fine. On mobile however the iframe apparently eats all the swipe events and you cannot swipe past the video. We had to hack around this by substituting an image of the video and then using window.open() open a new window with the video.
It sucks.
Is there a good way to overcome this?
In short, I discovered I was doing it wrong.
The slider script works very well on both desktop. On mobile it works except you cant swipe past the iframe that embeds the video.
My example iframe is:
<iframe width="1280" height="720" src="//www.youtube.com/embed/Lzbr6fPDmkE" frameborder="0" allowfullscreen></iframe> (fyi, its a funny video if you're an Army vet)
I discovered the (somewhat obvious) fact that youtube has a thumbnail url as well. So on mobile I add the following img tag:
<img src="http://i.ytimg.com/vi/Lzbr6fPDmkE/hqdefault.jpg" alt="1300x650" />
I found the answer in this article
The url I used is different than theirs because I ripped it off of an imbedded youtube thumbnail inside a gmail message.
Its mandatory to include below attribute in URL.
rel=0&enablejsapi=1
Note: Go through comment lines and add those slider library files in head section and save it. once everything added you have to open the file in browser. You can able to see the slider. If find any issue please comment below.
$('.slider').click();
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('videoSwipe', {
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(e) {
$('.youTubeVideo').find('.video').addClass('video-overlay');
}
function OverlayOnVideo(playerStatus) {
if (playerStatus == 2) {
$('.youTubeVideo').find('.video').addClass('video-overlay');
var iframeHeight=$('#videoSwipe').height()-40;
var overlayHeight=$(document).find('.video-overlay');
if ( overlayHeight.length >= 1 ) {
overlayHeight.css('height', iframeHeight+'px');
}else{
$('.youTubeVideo .tube').removeAttr( 'style' );
}
}
}
function onPlayerStateChange(e) {
OverlayOnVideo(e.data);
}
$(document).on("click", ".video-overlay", function() {
if (player) {
player.playVideo();
$('.youTubeVideo').find('.video').removeClass('video-overlay');
$('.youTubeVideo .tube').removeAttr( 'style' );
}
});
.youTubeVideo {
position: relative;
}
#wrapper {
width: 30%;
margin: auto;
}
.slick-list draggable {
margin-top: 3%;
}
body {
outline: none;
background: black;
}
:focus {
outline: none;
}
.slick-list.draggable {
margin-top: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<div class="slider">
<div><img src="http://placekitten.com/500/480" alt="" width="500" height="400"></div>
<div class="youTubeVideo">
<div class="video tube"></div>
<iframe id="videoSwipe" width="465" height="400" src="https://www.youtube.com/embed/exUQkIkyBBI?rel=0&enablejsapi=1"></iframe>
</div>
<div><img src="http://placekitten.com/500/480" alt="" width="500" height="400"></div>
<div><img src="http://placekitten.com/500/460" alt="" width="500" height="400"></div>
<div><img src="http://placekitten.com/500/440" alt="" width="500" height="400"></div>
<div><img src="http://placekitten.com/500/420" alt="" width="500" height="400"></div>
</div>
</div>
Related
I'm building a portfolio website that contains several embed Vimeo videos and they're slowing down the page loading a lot. So I was thinking of lazy load them so that the browser has to load them only when they actually appear in the page.
I've tried adding the loading="lazy" to the iframe tag but it didn't change anything. So I tried with this code but it seems to work just for one iframe element.
Can you help me understand how to adjust that code to apply the lazyloading to all of the iframe elements in the page?
var iframe = document.querySelector('iframe');
function handleLazyLoad() {
if (iframe.classList.contains('lazyload')) {
const storeSRC = iframe.dataset.src;
iframe.addEventListener('lazyloaded', () => {
delete iframe.dataset.src;
iframe.src = storeSRC;
initPlayer();
});
}
}
function initPlayer() {
var player = new Vimeo.Player(iframe);
player.ready().then(function (){
console.log('player is ready!');
// These events are not attaching? Why?
player.on('play', function () {
console.log('played the video!');
});
player.on('ended', function () {
console.log('the video has ended');
});
});
}
handleLazyLoad();
.content-block {
width: 200px;
height: 2000px;
background-color: red;
}
<div class="content-block"></div>
<iframe class="lazyload" data-src="https://player.vimeo.com/video/76979871?autoplay=1&muted=1" width="640" height="360" frameborder="0" webkitallowfullscreen
mozallowfullscreen allowfullscreen allow="autoplay; encrypted-media"></iframe><div style="position: relative;">
<div style="padding:53.02% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/495827819?autoplay=1&loop=1&color=c9ff23&title=0&byline=0&portrait=0&autopause=0" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="autoplay; fullscreen" allowfullscreen></iframe></div>
</div>
<div style="position: relative;">
<div style="padding:53.02% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/495827819?autoplay=1&loop=1&color=c9ff23&title=0&byline=0&portrait=0&autopause=0" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allow="autoplay; fullscreen" allowfullscreen></iframe></div>
</div>
Thank you!
I have VERY recently started coding and been asked to code our company website from scratch.
I have coded a team page on the website with a PNG of each member of the team. At the moment when the user hovers over any of the PNGs they turn into a little animated GIF of them waving/doing something.
This is the javascript:
$(document).ready(function()
{
$("#imgAnimateBeth").hover(
function(){
this.src = "images/Team/Videos/Beth.gif";
},
function(){
this.src = "images/Team/Static-shots/Beth.png";
}
);
});
The issue I am having is that I also want to introduce a click state that would bring up a popup with a video of that person and their job description but I can't get it to work.
I have tried creating a CSS overlay but it refuses to work alongside the hover effect (JavaScript) so my assumption is that they don't play well together (??).
Below is the HTML for the section above. Can anyone enlighten me as to how this could be done? Simple language please!
<div class="teamsection">
<img src="images/Team/Static-shots/Beth.png" id="imgAnimateBeth">
<img src="images/Team/Static-shots/Kiemia.png" id="imgAnimateKiemia">
<img src="images/Team/Static-shots/Emma-B.png" id="imgAnimateEmmaB">
<img src="images/Team/Static-shots/Mathew.png" id="imgAnimateMathew">
<img src="images/Team/Static-shots/Sydney.png" id="imgAnimateSydney">
<img src="images/Team/Static-shots/Liz.png" id="imgAnimateLiz">
<img src="images/Team/Static-shots/Russ.png" id="imgAnimateRuss">
<img src="images/Team/Static-shots/Jill.png" id="imgAnimateJill">
<img src="images/Team/Static-shots/Merry.png" id="imgAnimateMerry">
<img src="images/Team/Static-shots/Caroline.png" id="imgAnimateCaroline">
<img src="images/Team/Static-shots/Charlotte.png" id="imgAnimateCharlotte">
<img src="images/Team/Static-shots/Lucien.png" id="imgAnimateLucien">
<img src="images/Team/Static-shots/Sarah.png" id="imgAnimateSarah">
<img src="images/Team/Static-shots/Emma-S.png" id="imgAnimateEmmaS">
<img src="images/Team/Static-shots/David.png" id="imgAnimateDavid">
<img src="images/Team/Static-shots/Kathryn.png" id="imgAnimateKathryn">
</div>
Also, if you need me to upload anything else, just shout.
The CSS overlay was like this:
The CSS code overlay was like this:
.popup {
display: none;
position: fixed;
padding: 30px 70px;
width: 700px;
height: 100%;
z-index: 20;
left: 50px;
top: 20px;
background: rgba(0, 0, 0, 0.9);
overflow: scroll;
}
With a little bit of Javascript:
$ = function(id) {
return document.getElementById(id);
}
var show = function(id) {
$(id).style.display ='block';
}
var hide = function(id) {
$(id).style.display ='none';
}
And I basically did this to the HTML:
<div>
<a href="javascript:void(0)" onclick="show('beth')">
<img src="images/Team/Static-shots/Beth.png" id="imgAnimateBeth">
</a>
</div>
<div class="popup" id="beth">
<div class="close-button">
<i class="fa fa-times" aria-hidden="true"></i> Close
</div>
<h4>CONTENT HERE</h4>
</div>
Maybe this will give you some ideas:
var members = document.querySelectorAll('.team-member');
members.forEach(function(member) {
member.addEventListener('mouseenter', memberShowGIF);
member.addEventListener('mouseleave', memberShowPNG);
member.addEventListener('click', memberVideo);
});
function memberShowGIF(event) {
this.src = this.dataset.gif;
}
function memberShowPNG(event) {
this.src = this.dataset.png;
}
function memberVideo(event) {
console.log('The video thing for: ' + this.id);
}
<div class="teamsection">
<img id="Beth" class="team-member"
src="https://via.placeholder.com/200?text=Beth.png"
data-png="https://via.placeholder.com/200?text=Beth.png"
data-gif="https://via.placeholder.com/200?text=Beth.gif">
<img id="Kiemia" class="team-member"
src="https://via.placeholder.com/200?text=Kiemia.png"
data-png="https://via.placeholder.com/200?text=Kiemia.png"
data-gif="https://via.placeholder.com/200?text=Kiemia.gif">
</div>
The most important learnings here are:
querySelectorAll (as a vanilla alternative to jQuery for selecting nodes)
addEventListener
Data attributes
$(document).ready(function() {
$('#map').addClass('scrolloff');
$('#overlay').on("mouseup",function(){
$('#map').addClass('scrolloff');
});
$('#overlay').on("mousedown",function(){
$('#map').removeClass('scrolloff');
});
$("#map").mouseleave(function () {
$('#map').addClass('scrolloff');
});
});
.scrolloff {
pointer - events: none;
}
iframe {
width: 100 % ;
height: 260 px;
}
<div class="overlay" class="map-container">
<iframe id="map" src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2549.8391302717027!2d-74.51093153882466!3d40.53525165221866!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x89c3c0b7401dac15%3A0x209d581c4bc2ba2a!2s11+Cedar+Grove+Ln%2C+Somerset%2C+NJ+08873%2C+USA!5e0!3m2!1sen!2sin!4v1456722671076" allowfullscreen></iframe>
</div>
I have attached my full code i m working on i have simply applied the concept of the pointer-event function to stop the scrolling of the google. But my code is not working on these iframe. I have to applied the same code to other projects they are working smoothly. But it is not working on these iframe. If i change the iframe address it is working.
I see spaces in pointer-events css property
pointer - events: none;
it should be:
pointer-events: none;
a div with an .overlay exactly before each gmap iframe
Code will something like this.
<html>
<div class="overlay" onClick="style.pointerEvents='none'"></div>
<iframe src="https://mapsengine.google.com/map/embed?mid=some_map_id" width="640" height="480"></iframe>
</html>
CSS create the class:
.overlay {
background:transparent;
position:relative;
width:640px;
height:480px; /* your iframe height */
top:480px; /* your iframe height */
margin-top:-480px; /* your iframe height */
}
The div will cover the map, preventing pointer events from getting to it. But if you click on the div, it becomes transparent to pointer events, activating the map again!
I hope get helped you :)
If you use iframe code, try this:
HTML: wrap iframe in to div ;
CSS: add .scrolloff{pointer-events:none};
Javascript: add the code below;
jQuery(document).ready(function() {
jQuery('.map-canvas').addClass('scrolloff');
jQuery('.my-map').on('click', function() {
jQuery('.map-canvas').removeClass('scrolloff');
});
jQuery('.map-canvas').mouseleave(function() {
jQuery('.map-canvas').addClass('scrolloff');
});
});
.scrolloff{pointer-events:none}
<script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'></script>
<div class="map-canvas"><iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2875.295699663181!2d11.09368201550548!3d43.89114207911383!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x132af65dc5ef10bb%3A0x4983a428073d6747!2sVia+Ermolao+Rubieri%2C+29%2C+59100+Prato+PO!5e0!3m2!1sit!2sit!4v1465019144237" width="600" height="450" frameborder="0" style="border:0" allowfullscreen></iframe></div>
I am seeing a lot of sites these days, mainly tutorial sites that have a lot of images and they only load images further down the page once they come into the view port?
How would I go about doing this?
As you scroll down the page the images who were below the viewport fade in
<img loading="lazy" does it without any Javascript
We are now getting more and more support for this standardized no-JavaScript method, which is very exciting!
https://caniuse.com/#feat=loading-lazy-attr
https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-loading
You can see this at work in the code snippet below.
To see that the loading is actually lazy, open Chrome DevTools in the Network tab.
Then, as you scroll down the snippet, you will see that the images only load when you see them.
I've also added an optional JavaScript button to show that you can change lazy back to the default eager from JavaScript, and images will then start to load immediately.
document.getElementById('load-now').addEventListener('click', function(){
for (const img of document.getElementsByTagName('img')) {
img.loading = 'eager';
}
});
.separator {
height: 1000px;
width: 100px;
border: 5px solid red;
}
img {
height: 340px;
border: 5px solid black;
}
#load-now {
border: 5px solid black;
}
<div id="load-now">Click me to load all images now!</div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/5/56/Donald_Trump_official_portrait.jpg"></div>
<div class="separator"></div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/8/8d/President_Barack_Obama.jpg"></div>
<div class="separator"></div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/d/d4/George-W-Bush.jpeg"></div>
<div class="separator"></div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/d/d3/Bill_Clinton.jpg"></div>
<div class="separator"></div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/9/90/George_H._W._Bush%2C_President_of_the_United_States%2C_1989_official_portrait_%28cropped%29.jpg"></div>
<div class="separator"></div>
<div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/1/16/Official_Portrait_of_President_Reagan_1981.jpg"></div>
One really cool thing about this method is that it is fully SEO friendly, since the src= attribute contains the image source as usual, see also: Lazy image loading with semantic markup
Tested in Chromium Chromium 81 and Firefox 77.0.1, both worked and loaded lazily.
IntersectionObserver minimal runnable example
This is a JavaScript method that would work before img loading="lazy" was implemented.
This is essentially the technique used at: https://appelsiini.net/projects/lazyload/ which was mentioned at: https://stackoverflow.com/a/2322042/895245
Web APIs have evolved so much now that it is not hard to code it from scratch!
var observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach(entry => {
if (entry.intersectionRatio > 0.0) {
img = entry.target;
if (!img.hasAttribute('src')) {
alert('will load the image!!!');
img.setAttribute('src', img.dataset.src);
}
}
});
},
{}
)
for (let img of document.getElementsByTagName('img')) {
observer.observe(img);
}
.separator {
height: 1000px;
width: 100px;
border: 5px solid red;
}
img {
height: 340px;
border: 5px solid black;
}
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/5/56/Donald_Trump_official_portrait.jpg"></div>
<div class="separator"></div>
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/8/8d/President_Barack_Obama.jpg"></div>
<div class="separator"></div>
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/d/d4/George-W-Bush.jpeg"></div>
<div class="separator"></div>
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/d/d3/Bill_Clinton.jpg"></div>
<div class="separator"></div>
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/9/90/George_H._W._Bush%2C_President_of_the_United_States%2C_1989_official_portrait_%28cropped%29.jpg"></div>
<div class="separator"></div>
<div><img data-src="https://upload.wikimedia.org/wikipedia/commons/1/16/Official_Portrait_of_President_Reagan_1981.jpg"></div>
Full page demo: https://cirosantilli.com/web-cheat/js-image-load-viewport.html
GitHub upstream: https://github.com/cirosantilli/cirosantilli.github.io/blob/1f637bf4791b115777300f48f427f0a6bb409fc1/web-cheat/js-image-load-viewport.html
This technique is just a combination of:
What is the best JavaScript code to create an img element
How can I tell if a DOM element is visible in the current viewport?
Tested in Chromium 76.
Change load order to nearest first
This is the last use case missing after loading="lazy" for me: a method that downloads eagerly, but changes the download order to download first on viewport, then below, and then above: Change loading order of images already on page
Maybe we can do something with querySelectorAll() to solve jQuery find next/prev elements of a certain class but not necessarily siblings and then remove loading=lazy from images in the JavaScript! This would both degrade gracefully, and be SEO friendly.
The last issue is how to get the first visible element though:
How to get the first DOM element that is visible in a viewport?
How to select the last element on viewport
I haven't seen a very good solution for this yet.
Lazy load video
Not sure why, but neither Chromium 81 nor Firefox 77.0.1 can lazy load video, now sure why did they do it just for img?
Chromium 81 did implement it for iframe however, which is what YouTube embeds use, while Firefox 77.0.1 didn't: lazy load iframe (delay src http call) with jquery
A simple pure JavaScript solution:
<script>
document.addEventListener("DOMContentLoaded", function () {
let images = document.querySelectorAll("img[data-src]");
function loadImagesLazily(e) {
for (let i = 0; i < images.length; i++) {
let rect = images[i].getBoundingClientRect();
if (images[i].hasAttribute("data-src")
&& rect.bottom > 0 && rect.top < window.innerHeight
&& rect.right > 0 && rect.left < window.innerWidth) {
images[i].setAttribute("src", images[i].getAttribute("data-src"));
images[i].removeAttribute("data-src");
}
}
};
window.addEventListener('scroll', loadImagesLazily);
window.addEventListener('resize', loadImagesLazily);
loadImagesLazily();
});
</script>
http://www.appelsiini.net/projects/lazyload
https://github.com/tuupola/jquery_lazyload
Demo:
http://www.appelsiini.net/projects/lazyload/enabled.html
Replace your images with placeholders (e.g. just change the "src" attribute to something else so the image won't load, but the url will still be accessible), and then bind the window scroll event to a function which will find all images at the current scroll position, and swap the image src into a real img tag.
Here's the code. It's untested, but this should be the basic idea:
<img src="" realsrc="/myimage.png" />
$(document).ready(function(){
$(window).scroll(function(){
$('img[realsrc]').each(function(i){
var t = $(this);
if(t.position().top > ($(window).scrollTop()+$(window).height()){
t.attr('src', t.attr('realsrc')); // trigger the image load
t.removeAttr('realsrc'); // so we only process this image once
}
});
})
});
How do I link to snapshots of embedded flash videos instead of the actual flash videos to reduce loading times of a site?
Yes, and in fact this is a method that is often employed. You start with an image with a play button overlay. When it's clicked, the image element is replaced with a flash element that plays the video.
Perhaps something like the following:
<script>
$(function () {
$("img.thumbnail").click(function (e) {
$(e.parentNode).addClass("play");
});
});
</script>
<style>
.toggler .player { display: none; }
.toggler.play .player { display: block }
.toggler.play .thumbnail { display: none }
</style>
<div class="toggler">
<img class="thumbnail" src="thumbnail.jpg">
<div class="player">
<!-- embed your player here -->
</div>
</div>