masonry not working when the page has loaded - javascript

I put these code at the last lows before </body>
<script type="text/javascript">
var $grid = $('.grid').masonry({
// options
itemSelector: '.grid-item',
columnWidth: 230
});
$grid.masonry(); //not work
function test() {
$grid.masonry(); //it work
}
</script>
when I run the page, show this:
http://i.stack.imgur.com/P3OgW.jpg masonry is not working.
Now I change the webbrowser(chrome/IE/Firefox)width, is work. http://i.stack.imgur.com/ZumGW.jpg
So, I create a function name test with code " $grid.masonry();" and run it, it work.
I'm surprised that the javascript will run after the page has load ready as unually, but here i must run the function test manually to achieve it.
what’s going on?
/************************ and still not working ***************************/
<script type="text/javascript">
$(document).ready(function() {
var $grid = $('.grid').masonry({
// options
itemSelector: '.grid-item',
columnWidth: 230
});
$grid.masonry(); // not work
console.log('the code is running!'); // it work
});
function test() {
var $grid = $('.grid').masonry({
// options
itemSelector: '.grid-item',
columnWidth: 230
});
$grid.masonry(); // it work
}
</script>
/*****************************************************************/
OK,I found a way to resolved it but not elegant. like this:
var timeId = setTimeout(function() {
$grid.masonry();
}, 100);

Related

When new data loads masonry js not reloading (Masonry JS and Handlebars)

I am using Handlebars http://handlebarsjs.com/ and Masonry https://masonry.desandro.com/ to get some JSON data and add it to the dom every 5 mins using Jquery prepend.
The problem I am having is the first time I add the data to the dom Masonry works fine and displays horizontally
eg.
but 5 mins later when the new data gets added it just drops it vertically. It is supposed to prepend and move the other elements across.
eg.
function to add to dom.
function AddToDom() {
console.log("AddToDom");
setTimeout(function() {
cardContainer.prepend(compiledCardTemplate(model)).masonry({
itemSelector: '.grid-item',
columnWidth: '.grid-item',
// percentPosition: true,
horizontalOrder: true,
fitWidth: true
});
}, 1000);
}
I am using setTimeout as a delay from the retrieval of data to adding to dom.
edit:
After suggestions from Ali, I tried this
function AddToDom() {
setTimeout(function() {
let $items = compiledCardTemplate(model);
cardContainer.append($items).masonry('prepended', $items);
}, 1000);
}
but I am getting this error
masonry not initialized. Cannot call methods, i.e. $().masonry("prepended")
edit: for clarity
let cardContainer = $(".wrapper");
let cardTemplate = $("#card-template").html();
let compiledCardTemplate = Handlebars.compile(cardTemplate);
let model = {
posts: []
}
edit: called functions
// docuemnt init
$(document).ready(function () {
GetData();
AddToDom();
setInterval(AddToDom, 50000);
});
Any help much appreciated.
Thanks in advance.
Assuming your cardContainer is a Masonry Grid, to add to the start (prepend to start) more items to the Grid you need to call Masonry#prepended().
The above snippet can be written as:
function addToDOM(model) {
setTimeout(function() {
var $item = $(compiledCardTemplate(model));
$cardContainer
.prepend($item) // to prepend to DOM node
.masonry('prepended', $items); // to notify masonry
}, 1000);
}
Solved the issue with code below (Many thanks to #riyza-ali)
function AddToDom() {
setTimeout(function () {
let items = compiledCardTemplate(model);
let $items = $(items);
let grid = wrapper.masonry({
itemSelector: '.grid-item',
columnWidth: '.grid-item',
horizontalOrder: true,
fitWidth: true
});
grid.prepend($items).masonry('prepended', $items);
}, 1000);
setTimeout(AddToDom, 50000);
}

Masonry not working on loading... Elements don't re-align themselves until I resize the window

Example - http://paulmatheson.net/webdev.html
Resize the window and the elements will move accordingly.
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="js/masonry.pkgd.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.imagesloaded/4.1.2/imagesloaded.min.js"></script>
<script type="text/javascript">
var $container = jQuery('.masonry-grid');
$container.imagesLoaded(function() {
$container.masonry({
columnWidth: 225,
gutter: 10,
itemSelector: '.dev-grid-item'
});
$container.imagesLoaded.done( function() {
$container.masonry('layout');
});
});
</script>
<script src="js/lightbox.min.js"></script>
<script src="js/main.js"></script>
My script - Now I think it has to do with imagesLoaded because the console lends some info. It says imagesLoaded.done is not a function but I never had this issue before redesigning a few elements today. Anyone know why it would pop up now?
Your error is with $container.imagesLoaded.done
Try this code:
var $container = jQuery('.masonry-grid');
$container.imagesLoaded(function() {
$container.masonry({
columnWidth: 225,
gutter: 10,
itemSelector: '.dev-grid-item'
});
$container.imagesLoaded().done( function( instance ) {
$container.masonry('layout');
});
});

jQuery Isotope layout initializing with inconsistent spacing

I am using Isotope for a layout. As you can see below, the grid initializes with inconsistent spacing. If I immediately called the isotope function again with filtering, the issue persists. But if I wrap it in a setTimeout, the issue is fixed.
Here is the JavaScript that creates the layout with inconsistent spacing:
var $container = $('#isotope').isotope({
itemSelector: '.tag-box',
layoutMode: 'fitRows',
sortBy: 'name',
getSortData: {
name: '.tag-name'
}
});
// This will fix the issue:
// setTimeout(function() {
// $container.isotope({filter: '*'});
// }, 0);
$('#filters').on('click', 'button', function() {
var filterValue = $(this).attr('data-filter');
$container.isotope({filter: filterValue});
});
The setTimeout is fine for now, but is there a way to initialize the layout with even spacing?
Without a jsfiddle or link it is difficult to see but why use setTimeout when you can do this:
$(document).ready(function() {
var $container = $('#isotope').isotope({
itemSelector: '.tag-box',
layoutMode: 'fitRows',
filter: '*',
sortBy: 'name',
getSortData: {
name: '.tag-name'
}
});
});

JQuery Infinite Scroll Help - passing variables to second page

Problem: I have implemented an infinitescroll plugin in my rails app, along with JQuery Masonry. It works perfectly but I am facing one little problem: starting from the second page, the hover function does not get triggered. This problem is very similar to this post on Stackoverflow. I'm supposed to call my hover function again after the Masonry callback.
My original code:
<script>
$(function () {
var $container = $('#container_masonry');
$container.infinitescroll({
navSelector: '.pagination'
nextSelector: '.pagination a',
itemSelector: '.image_masonry'
loading: {
finishedMsg: 'Done loading'
img: 'http://i.imgur.com/6RMhx.gif'
}
},
// trigger Masonry as a callback
function(newElements) {
//hide new items while loading
var $newElems = $(newElements).css({ opacity: 0 });
//images must be loaded completely before adding to layout
$newElems.imagesLoaded(function(){
//they are loaded and ready to be showed
$newElems.animate({ opacity: 1 });
$container.masonry( 'appended', $newElems, true );
});
}
);
$container.imagesLoaded(function(){
$container.masonry({
itemSelector: '.image_masonry',
columnWidth: 10,
isAnimated: true,
animationOptions: { duration: 400 },
isResizable: true,
isFitWidth: true
});
$('.image_masonry').hover(
function(){
$('.title',this).fadeIn();
$('.like_num',this).show();
var buttonDiv= $(this).children('.button');
buttonDiv.toggle();
}, function(){
$('.title',this).fadeOut();
$('.like_num',this).hide();
var buttonDiv= $(this).children('.button');
buttonDiv.toggle();
});
});
});
</script>
I should add the following,
$('.image_masonry').hover(
function(){
$('.title',this).fadeIn();
$('.like_num',this).show();
var buttonDiv= $(this).children('.button');
buttonDiv.toggle();
}, function(){
$('.title',this).fadeOut();
$('.like_num',this).hide();
var buttonDiv= $(this).children('.button');
buttonDiv.toggle();
});
to right after,
$newElems.imagesLoaded(function(){
//they are loaded and ready to be showed
$newElems.animate({ opacity: 1 });
$container.masonry( 'appended', $newElems, true );
//ADD HOVER FCN HERE
However, simply adding the whole hover function did not work. I'm new to jQuery so I'm not entirely sure, but I need to pass in the related variables along with the function for it to work (got this hint from the similar post. So I should add something like
$('.image_masonry').hover(
function(SOME-RELATED-VARIABLES){
$('.title',this).fadeIn();
$('.like_num',this).show();
var buttonDiv= $(this).children('.button');
buttonDiv.toggle();
}, function(SOME-RELATED-VARIABLES){
$('.title',this).fadeOut();
$('.like_num',this).hide();
var buttonDiv= $(this).children('.button');
buttonDiv.toggle();
});
But I need someone to teach me what I should put in there. I'm struggling because of my lack of familiarity with jQuery. I appreciate your help a lot!
You were missing some commas between rows 5-11. Also if you're loading external content at a later time, you need to delegate the hover event with on or delegate depending on your version. I added on below.
$(function () {
var $container = $('#container_masonry');
$container.infinitescroll({
navSelector: '.pagination',
nextSelector: '.pagination a',
itemSelector: '.image_masonry',
loading: {
finishedMsg: 'Done loading',
img: 'http://i.imgur.com/6RMhx.gif'
}
},
// trigger Masonry as a callback
function (newElements) {
//hide new items while loading
var $newElems = $(newElements).css({
opacity: 0
});
//images must be loaded completely before adding to layout
$newElems.imagesLoaded(function () {
//they are loaded and ready to be showed
$newElems.animate({
opacity: 1
});
$container.masonry('appended', $newElems, true);
});
});
$container.imagesLoaded(function () {
$container.masonry({
itemSelector: '.image_masonry',
columnWidth: 10,
isAnimated: true,
animationOptions: {
duration: 400
},
isResizable: true,
isFitWidth: true
});
$('body').on({
mouseenter: function () {
$('.title', this).fadeIn();
$('.like_num', this).show();
var buttonDiv = $(this).children('.button');
buttonDiv.toggle();
},
mouseleave: function () {
$('.title', this).fadeOut();
$('.like_num', this).hide();
var buttonDiv = $(this).children('.button');
buttonDiv.toggle();
}
}, '.image_masonry');
});
});

jquery.masonry. imagesLoaded plugin dont running in <head>

What I should add to this script for running in head. When I put in the end of body it run well. I think this is due to the fact that the script starts before images are loaded. Example http://masonry.desandro.com/docs/intro.html
<script>var $container = $('#container');
$container.imagesLoaded(function(){
$container.masonry({
itemSelector : '.item',
columnWidth : 300
});
});
</script>
The body (also the container) doesn't exist when the code will be executed. In the head you should wrap your code in a $(document).ready(function() { ... });:
<script>
$(document).ready(function() {
var $container = $('#container');
$container.imagesLoaded(function(){
$container.masonry({
itemSelector : '.item',
columnWidth : 300
});
});
});
</script>

Categories

Resources