Masonry Events: Call event after imagesLoaded and layoutComplete - javascript

So here's what I'm trying to do. I have a grid with a lot of images, so I'm using the imagesLoaded library along with masonry.
Here's my CSS:
.grid {
opacity:0;
}
And HTML:
<div class="grid">
<div class="grid-sizer"></div>
<div class="gutter-sizer"></div>
<div class="item">image</div>
<div class="item">image</div>
<div class="item">image</div>
</div>
And here's my JS:
var $container = $('.grid');
// initialize Masonry after all images have loaded
$container.imagesLoaded( function() {
$container.masonry({
columnWidth: '.grid-sizer',
itemSelector: '.item',
gutter: '.gutter-sizer'
});
$container.masonry('on', 'layoutComplete', function(){
console.log('got here');
$container.animate({'opacity':1});
});
});
My goal is to have the grid hidden until all images are load and the layout is complete, and then fade it in. For some reason in my code above, it's never getting into the on layoutComplete block.
If I move that block outside of imagesLoaded, $container.masonry is undefined that point.
Any ideas?
FIDDLE HERE
If you change the grid opacity to 1 you can see everything is getting laid out fine. Just trying to figure out how to get the layoutComplete to call to set the opacity to 1.

You don't need to use the layoutComplete event on masonry. As you can just add your animation code under the masonry initialization .
When all images are loaded, the imageLoaded function will execute. You can then create the masonry object and animate right away like so:
var $grid = $('.grid').imagesLoaded( function() {
// init Masonry after all images have loaded
$grid.masonry({
columnWidth: 200,
itemSelector: '.item',
gutter: 10
});
console.log('got here');
$('.grid').animate({'opacity':1});
});
Here is a jsfiddle that demonstrate that

jQuery(document).ready(function($){
var wdm_wait = function(){
jQuery("body").find("img").each(function(i) {
if(!this.complete)
{
return false;
}
});
// when code reaches here Its assured that all the images are loaded
clearInterval(waiting);
console.log('got here');
var $container = $('.grid');
// initialize Masonry after all images have loaded
$container.masonry({
columnWidth: 100,
itemSelector: '.item',
gutter: 10
});
$container.animate({'opacity':1});
}
waiting = setInterval(wdm_wait,100);
});
This would certainly assure that your js code executes only after all the images have been loaded (rendered)
Hope this helps! :)

have you ever try this one, I think this is your answer
var $container = $('.grid').masonry({
columnWidth: 200,
itemSelector: '.item',
gutter: 10
});
$container.masonry( 'on', 'layoutComplete', function() {
$container.animate({'opacity':1});
});
$container.masonry();

Related

Re apply javascript after pageload

I have an issue with my masonry code.
It works fine on pageload, but the items that are inside the masonry can be filtered, I am doing this using ajax and I'm replacing the entire div with elements to show the filtered items.
After this happens, the masonry code is not applied again and it falls apart.
How can I make sure the masonry stays applied even when content changes after pageload?
In my footer I have the following code:
<script type="text/javascript">
$(document).ready(function() {
$('.gridlist').isotope({
itemSelector: '.masonryitem',
layoutMode: 'masonry',
});
});
</script>
Then in my custom.js I have the following:
$( document ).ready(function() {
/* Ajax code voor aanbiedingen */
$("#branche").on('change', function() {
var option = $('#branche > option').filter(':selected');
if(option.val() == 'default'){
$.post("includes/ledenall.php", {
filter: option.val()
}, function(result){
$("#content1").html(result);
});
}else{
$.post("includes/leden.php?option=" + option.val(), {
filter: option.val()
}, function(result){
$("#content1").html(result);
});
}
});
});
Which returns my php file, but this time without the masonry being applied.
What can I do about this?
You can try reapplying your isotope library after changing the DOM:
/* Ajax code voor aanbiedingen */
$("#branche").on('change', function() {
var option = $('#branche > option').filter(':selected');
if(option.val() == 'default'){
$.post("includes/ledenall.php", {
filter: option.val()
}, function(result){
$("#content1").html(result);
$('.gridlist').isotope({
itemSelector: '.masonryitem',
layoutMode: 'masonry',
});
});
}else{
$.post("includes/leden.php?option=" + option.val(), {
filter: option.val()
}, function(result){
$("#content1").html(result);
$('.gridlist').isotope({
itemSelector: '.masonryitem',
layoutMode: 'masonry',
});
});
}
});
I don't know if .gridlist is totally replaced in your updated DOM. If not, you may need to somehow "remove" the old isotope instance, but something like this is what you need to do.
Add your code to a function
function func() {
$('.gridlist').isotope({
itemSelector: '.masonryitem',
layoutMode: 'masonry',
});
}
Then you can call the function and apply your isotope at any point you want

Make lightbox work even before all images are loaded

I'm using Featherlite as my lightbox and my problem is, I have a lot of images (thumbnails) to load on my page and when it's loading and I click one of the loaded image, the lightbox doesn't work. Therefore, it will go to the jpeg file on to the other page instead of a modal window.
How can I make my lightbox even after all the images are all loaded. By the way, I'm putting this on my WordPress but I don't want to use a plugin. Also I'm using FoundationPress.
Here's the code I use to initiate my lightbox
$(document).ready(function(){
$('a.gallery').featherlight({
targetAttr: 'href'
});
});
I have images loaded script but I'm using it on my masonry. How can I put the lightbox scripts inside the images loaded plugin?
(function() {
// Main content container
var $container = $('.grid');
var $grid = $('.grid').masonry({
// options
columnWidth: '.grid-sizer',
itemSelector: '.grid-item',
percentPosition: true
});
// layout Masonry after each image loads
$grid.imagesLoaded().progress( function() {
$grid.masonry('layout');
});
// Infinite Scroll
$container.infinitescroll({
navSelector : '.pagination', // selector for the paged navigation
nextSelector : '.pagination a.next', // selector for the NEXT link (to page 2)
itemSelector : '.grid-item', // selector for all items you'll retrieve
loading: {
msg: null,
msgText: '<i class="fa fa-circle-o-notch fa-spin"></i>',
finishedMsg: '<i class="fa fa-check"></i>',
img: null
}
},
// Trigger Masonry as a callback
function( newElements ) {
// hide new items while they are loading
var $newElems = $( newElements ).css({ opacity: 0 });
// ensure that images load before adding to masonry layout
$newElems.imagesLoaded(function(){
// show elems now they're ready
$newElems.animate({ opacity: 1 });
$container.masonry( 'appended', $newElems, true );
});
});
})();
I'm not exactly sure if I understood correctly what solution you would like, but you could use
https://github.com/desandro/imagesloaded
which is specifically made for use cases like masonry plugin layouts,
to check if all images have finished loading and then execute functions / other scripts.
For example:
$('#your-container').imagesLoaded( {
},
function() {
$('a.gallery').featherlight({
targetAttr: 'href'
});
}
);
Hope this helps a bit?

Combining Flexslider with Masonry

I'm combining some jQuery: Flexslider and Masonry.
Flexslider is triggered by global.js:
$(window).load(function() {
// Banner FlexSlider
$('#side-slider').flexslider({
animation: 'slide',
slideshow: true,
smoothHeight: false,
controlNav: false,
directionNav: false,
slideshowSpeed: 5000,
controlsContainer: ".flexslider-container",
});
}); // End on window load
The masonry is trigger in nwmasonry_init.js:
jQuery(document).on('ready', function() {
var $ = jQuery;
//Masonry
var container = document.querySelector('.overzicht');
var msnry = new Masonry(container, {
itemSelector: '.bedrijven',
gutter: '.gutter-sizer',
transitionDuration: 0,
});
});
On initial pageload, like can be seen here http://nieuws.ditisonzewijk.nl/category/brandevoort/ the slider on the top in the middle overlaps with another content block.
As soon as you resize the window, the slider resizes it's width and therefore the height of the slider is corrected.
Anybody have an idea on how to get the heigth of the slider right on the initial load?
You need to use imagesloaded.js. Overlapping is caused by masonry firing before all the images are loaded. Load the imagesloaded script and try this code:
jQuery(document).on('ready', function() {
var $ = jQuery;
//Masonry
var container = document.querySelector('.overzicht');
imagesLoaded(container, function() {
var msnry = new Masonry(container, {
itemSelector: '.bedrijven',
gutter: '.gutter-sizer',
transitionDuration: 0,
});
});
});
I've found a fix for this, even though it isn't pretty. I've put a delay on the masonry init.
function loadMasonry() {
***fire masonry***
}
setTimeout(loadMasonry, 500);
Now it's working correctly. Anybody an idea on how to fix this properly?

jquery running when new images load

So I have a site that has 2 containers #container and #container2. I use jquery to append content that is of a certain size to one container, and the others to the other. Here is that code:
$(document).ready(function() {
$('.entry').each(function() {
if ($(this).height() > 200) {
$('#container2').append(this);
}
else {
$('#container').append(this);
}
});
});
So my issue is that with the infinite scroll and masonry, when the new content becomes available, the jquery does not run again in order to append the content to the right container. What can I add so that it will be able to append the content to the correct container?
Note: Each container can have tens of thousands of images.
Update:
Here is my masonry code:
$(window).load(function() {
var $wall = $('#container');
$wall.imagesLoaded(function() {
$wall.masonry({
itemSelector: '.entry, .entry_photo',
isAnimated: false
});
});
$wall.infinitescroll({
navSelector: '#page-nav',
nextSelector: '#page-nav a',
itemSelector: '.entry, .entry_photo',
bufferPx: 2000,
debug: false,
errorCallback: function() {
$('#infscr-loading').fadeOut('normal');
}},
function(newElements) {
var $newElems = $(newElements);
$newElems.hide();
$newElems.imagesLoaded(function() {
$wall.masonry('appended', $newElems, {isAnimated: false}, function() {
$newElems.fadeIn('slow');
});
});
});
$('#container').show(500);
});
So what happens is that the next posts when they load, all load into #container regardless of their height. This clearly shows that masonry is working fine, but it's just not calling the jquery again when they load. Is there any way to insure that it calls the jquery I need? How do I do that?
I think you have to initialize masonry plugin after adding your content in containers
like,
$(document).ready(function(){
$('.entry').each(function(){
if($(this).height()>200){
$('#container2').append(this);
}
else{
$('#container').append(this);
}
});
// masonry plugin initialization after adding content to div
});

Executing code before isotope relayouts

I want an item to span over the hole container area so that when the window resizes my item does that to. There is a "onLayout"-callback that has everything i need except it executes to late. here is what i want to do.
$container.isotope({
itemSelector: '.puff',
layoutMode: 'masonry',
itemPositionDataEnabled: true,
masonry: {
columnWidth: columnWidth
},
onLayout: function ($elems, instance) {
$spanningItem.width(this.width()-20);
}
});
And a fiddle

Categories