Skip to content

Instantly share code, notes, and snippets.

@ericmann
Last active October 25, 2016 08:41
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save ericmann/bf50405dafbc64427bba to your computer and use it in GitHub Desktop.
Save ericmann/bf50405dafbc64427bba to your computer and use it in GitHub Desktop.
Lazy-Loading Tutorial Parts
( function( window, $, undefined ) {
var $window = $( window ),
images = $( 'img[data-lazy]'),
throttle_id;
/**
* Determine whether or not a given image is in the current viewport.
*
* @param {DOMElement} image
*
* @return {Boolean}
*/
function inView( image ) {
var $image = $( image ),
view_top = $window.scrollTop() - 300,
view_bottom = view_top + $window.height() + 600,
height = $image.height(),
_top = $image.offset().top,
_bottom = _top + height;
// Only fire on elements with non-zero heights.If the top edge is above the bottom threshold, or the bottom
// edge is below the top threshold, then the image is visible and should be loaded. Otherwise, return false.
return ( height > 0 ) && ( _top <= view_bottom ) && ( _bottom >= view_top );
}
/**
* Iterate through a jQuery array of images and, if they're visible, load them into the page.
*
* @param {Array} images
*/
function maybeLoad( images ) {
var did_lazy_load = false;
// Iterate through every image on the page that has a `data-lazy` attribute.
images.each( function( i, image ) {
if ( image.hasAttribute( 'data-lazy') && inView( image ) ) {
image.src = image.getAttribute( 'data-lazy' );
image.removeAttribute( 'data-lazy' );
// Fire a jQuery event on the image in case anyone else is watching.
$( image ).trigger( 'lazy-load' );
// Keep track that we need to repopulate the `images` array
did_lazy_load = true;
}
} );
// Repopulate our `images` array
if ( did_lazy_load ) {
images = $( 'img[data-lazy]' );
}
}
$window.on( 'scroll', function() {
if ( undefined === throttle_id ) {
// We're already living in a throttled environment, so exit
return;
}
// If we've gotten this far, it means it's the first call to 'scroll' the application has received.
// Set up a timeout to fire our callback in 250 milliseconds
throttle_id = window.setTimeout(
function() {
maybeLoad( images );
throttle_id = undefined;
},
250
);
} );
// Fire our image parser immediately to force visible images into the display
maybeLoad( images );
} )( window, jQuery );
( function( window, $, undefined ) {
var document = window.document,
$document = $( document );
/**
* Universal callback to load a video player iFrame into a modal window.
*
* @param {Event} e
*/
function play_video( e ) {
var $this = $( this ),
video = this.getAttribute( 'data-embed' ),
content = document.createElement( 'iframe' ),
overlay = document.createElement( 'div' ),
modal = document.createElement( 'div' ),
closer = document.createElement( 'a' ),
$overlay = $( overlay ), $modal = $( modal ), $closer = $( closer ),
close_video;
// Build out the iFrame that will contain our video player. We want the iFrame to be full-screen in this implementation.
content.width = '100%';
content.height = '100%';
content.src = video;
content.className = 'iframe_video';
// Set up the styling for the modal overlay atop which the player will display.
overlay.style.cssText = 'position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: #000;z-index: 159900;';
// jQuery is used to set the overlay's opacity for cross browser-compatibility. Immediately wire close_video as a click
// callback - we've declared the variable already so it's available, but we'll define the callback function itself later.
$overlay.css( 'opacity', 0.7 ).on( 'click', close_video );
// Set up the styling for the modal window in which the video plays.
modal.style.cssText = 'position: fixed; top: 30px; left: 30px; right: 30px; bottom: 30px; background-color: #fff; z-index: 160000;';
// Set up an anchor tag to serve as our close trigger. This tag, when clicked, will remove the video and overlay from the DOM.
closer.className = 'iframe_close';
closer.href = '#';
closer.innerText = 'close';
$closer.on( 'click', function( e ) {
e.preventDefault();
close_video();
} );
modal.appendChild( closer );
/**
* Define the close video callback. Both `$modal` and `$overlay` must be defined first before we can build out the function.
*/
close_video = function() {
$modal.remove();
$overlay.remove();
};
// Append our elements to the page
modal.appendChild( content );
document.appendChild( modal );
}
$document.on( 'click', '.iframe_play', play_video );
} )( window, jQuery );
@alixbergeret
Copy link

Hi,
I can't get this to work at all, am I missing something obvious?
http://mi-linux.wlv.ac.uk/~in9352/lazy/
The JS is exactly as above, and the markup is pretty simple... where am I going wrong?
Cheers,
Alix

@alixbergeret
Copy link

Sorry I forgot to say, my "images" collection seems empty, its lenght = 0 when debugging on line 36 (you can see it in the console).

Cheers!

@ericmann
Copy link
Author

ericmann commented Jan 6, 2015

Yep, there was a typo in my first script - there are two references to images = $( 'image[data-lazy]' ). These should be images = $( 'img[data-lazy]' ) and has been corrected above.

Additionally, the jQuery trigger for 'lazy-load' is attempting to fire against a vanilla JS object rather than a jQuery-wrapped object (line 41 of the image loader). I've corrected this above as well.

@AlchemyUnited
Copy link

Gave you tried using lazyload with picture / picturefill.js? I thinking that instead of faux'ing the src, I can do the srcset instead. But I'm also concerned some browsers might not like that idea. Perhaps you've seen this or similar? Picture + lazyload would be the ultimate, eh?

@AlchemyUnited
Copy link

Also, what about expanding the size of the inView as the loading finishes? That is +300 in each direction, then +300 more, and so on. I guess 300 doesn't feel like much in an image heavy / scroll happy world. That said, perhaps 250 ms is too often? I mean, maybe there's a way to factor in scroll speed as well. No sense thinking about loading if we're flying right past it, eh?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment