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'
}
});
});
Related
I'm using Isotope masonry library, Each items has different height according to their content
So I'm using this code for displaying them :
$(window).on('load', function() {
var $container = $('.members_results').imagesLoaded( function() {
$container.isotope({
itemSelector : '.block-member',
layoutMode : 'masonry',
percentPosition: true
});
});
});
But I have this displayed :
They are overlapping themselves, and I don't know how to fix it..
By the way I set height: auto; for .block-member
Thanks for your help !
You are assigning the $container variable to the result of a function, within which the variable is used. I believe you should assign it first, something like this:
$(window).on('load', function() {
var $container = $('.members_results');
$container.imagesLoaded( function() {
$container.isotope({
itemSelector : '.block-member',
layoutMode : 'masonry',
percentPosition: true
});
});
});
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);
}
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);
I have a Meteor app, where I load a collection into a Isotope grid. The items are sortable using Isotope's sort function.
My problem is that the filters does not fire when the items are listed the first time. I've put all the Isotope functions inside Template.CatchesList.onRendered but somehow I have to navigate from CatchesList page to another page, and then back again before the filters will work.
I've also wrapped the whole thing inside imagesLoadedto make sure all of the grid items images is loaded before Isotope render, to avoid any weird floats.
Template.CatchesList.onRendered(function() {
$('.grid').imagesLoaded( function() {
// quick search regex
var qsRegex;
// init Isotope
var $container = $('.grid').isotope({
itemSelector: '.grid-item',
layoutMode: 'masonry',
getSortData: {
river: '.river',
species: '.species',
sex: '.sex',
weight: '.weight parseFloat',
date: '[data-date]',
},
sortBy: ['date'],
sortAscending: {
river: true,
species: true,
sex: true,
weight: false,
date: false
},
filter: function() {
return qsRegex ? $(this).text().match(qsRegex) : true;
}
});
// use value of search field to filter
var $quicksearch = $('.quicksearch').keyup(debounce(function() {
qsRegex = new RegExp($quicksearch.val(), 'gi');
$container.isotope({
filter: function() {
return qsRegex ? $(this).text().match(qsRegex) : true;
}
});
}));
// filter results on label click
$('#filter').on('click', 'label', function() {
var filterValue = $(this).attr('data-filter');
$('.quicksearch').val('')
$container.isotope({
filter: filterValue
});
});
// sort results on label click
$('#sorts').on('click', 'label', function() {
var sortByValue = $(this).attr('data-sort-by');
$('.quicksearch').val('')
$container.isotope({
sortBy: sortByValue
});
});
});
});
Is there any reason why the filters don't fire at first render? Can I do something different to make sure all grid items are loaded before I filter them?
Should I have some of these functions inside Template.CatchesList.onCreated instead? Or can I use a sort of timeout to delay the filters?
Here is the site.
When I resize my window, the layout isn't triggered. So after I resize, I have to refresh the browser in order to see the reconfigured layout. I looked through the Masonry docs and found this page which I think describes my problem: http://masonry.desandro.com/methods.html#bindresize
$container.masonry('bindResize')
However, I'm not sure where I'm supposed to implement it. Below is the code that I'm currently using.
if(jQuery().isotope) {
$container = jQuery('#masonry');
$container.imagesLoaded( function() {
$container.isotope({
itemSelector : '.item',
masonry: {
columnWidth: $(document).width() > 1035 ? 240 : 320
},
getSortData: {
order: function($elem) {
return parseInt($elem.attr('data-order'));
}
},
sortBy: 'order'
}, function() {
// Isotope Chrome Fix
setTimeout(function () {
jQuery('#masonry').isotope('reLayout');
}, 1000);
});
});
// filter items when filter link is clicked
$container = jQuery('#masonry');
jQuery('#filter li').click(function(){
jQuery('#filter li').removeClass('active');
jQuery(this).addClass('active');
var selector = jQuery(this).find('a').attr('data-filter');
$container.isotope({ filter: selector });
return false;
});
}
Can someone help me out?
if(jQuery().isotope) {
$container = jQuery('#masonry');
$container.imagesLoaded( function() {
$container.isotope({
itemSelector : '.item',
masonry: {
columnWidth: 240
},
getSortData: {
order: function($elem) {
return parseInt($elem.attr('data-order'));
}
},
sortBy: 'order'
}, function() {
// Isotope Chrome Fix
setTimeout(function () {
jQuery('#masonry').isotope('reLayout');
}, 1000);
});
});
// filter items when filter link is clicked
$container = jQuery('#masonry');
jQuery('#filter li').click(function(){
jQuery('#filter li').removeClass('active');
jQuery(this).addClass('active');
var selector = jQuery(this).find('a').attr('data-filter');
$container.isotope({ filter: selector });
return false;
});
//added this line
jQuery(window).resize(function(){jQuery('#masonry').isotope('reLayout'); });
}
I have just added a single line in last and it will work.
Did you tried to insert the bindResize Snippet after your $container var?
// filter items when filter link is clicked
$container = jQuery('#masonry');
$container.masonry('bindResize');
jQuery('#filter li').click(function(){
...
}
The bindResize method should triggered on the Resize-Event so you don’t need to add it to the event manually. But the Amit’s solution should work too. But can you please remove the refreshing on the demo-site on resize? i can’t really test anything there.