My javascript looks like the following:
<script type="text/javascript">
$(document).ready(function() {
// isotope
var $container = $('#content');
$container.imagesLoaded( function(){
$container.isotope({
filter: '*',
itemSelector : '.element',
getSortData : {
colors : function( $elem ) {
return $elem.find('.colors').text();
},
number : function( $elem ) {
return $elem.find('.number');
}
}
});
var $sortedItems = $container.data('isotope').$filteredAtoms;
// filter items when filter link is clicked
$('#filter a').click(function(){
alert("filter");
var selector = $(this).attr('data-filter');
$container.isotope({ filter: selector });
return false;
});
// sorting
$('#sort a').click(function(){
var sortType = $(this).attr('data-sort');
$container.isotope({ sortBy : sortType });
return false;
});
});
});
function updateContent(path, args) {
$.ajax({
url: (path+args),
type: "POST",
success: function( data ){
$(allCards).remove();
$("#content").html( data );
$('#content').isotope( 'reLayout', callback );
}
});
}
function callback() {
alert("success: "+$('#content').height());
}
</script>
Whenever I use the updateContent() function the height of the #content div becomes 0. I think there could be a race condition happening due to the content not having been fully loaded and isotope initializing before the next set of images have been loaded.
It works fine when I first load the document. However when I load a new set of images with updateContent() it sets the #content div height to 0. Ideally I'd like to be able to load a new set of images and isotope would initialize as it normally does and height should be an appropriate value for all of the images to fit inside the #content div.
The following part needs to be fixed and this is what I have so far...
$(allCards).remove(); // remove all previous images
$("#content").html( data ); // load new images
$('#content').isotope( 'reLayout', callback ); // <- reinit isotope to manage the new images
Basically I'd like it to remove all previous images and load all the new images in data and isotope would work with the new images.
I solved the issue by prepending. I'm putting this up so people don't have to suffer like I did.
$("#content").isotope( 'remove', $(".element"), function(){
$("#content").prepend($(data)).isotope( 'reloadItems' ).isotope({ sortBy: 'original-order' });
});
Have a look at http://isotope.metafizzy.co/docs/methods.html
Firstly make sure the markup your appending to $("#content") has the .element class.
If they don't have it, you'll need to append it to them before attempting to insert them into the isotope container.
Secondly try using the inbuilt method for removing appending objects
.isotope( 'addItems', $items, callback )
In your case it would be:
$("#content").isotope( 'remove', $(".element"), function(){
$("#content").isotope( 'addItems', $(data), function(){
$("#content").isotope( 'reLayout' callback );
});
});
You probably do not need to utilize the callbacks from 'remove' and 'addItems', but without a jsfiddle example it's hard to tell.
Related
I am trying to build my own 'infinite scroll' so I have more control than using a plugin.
I currently have the below:
$(window).scroll(function(){
if ($(window).scrollTop() == $(document).height() - $(window).height()){
loadNew();
}
});
function loadNew(){
var next = $('a.next').attr('href');
$.ajax({
url: next,
success: function(html){
** GET ALL '.grid-item' TO USE BELOW**
var $newElems = $( **ALL .grid-item** ).css({ opacity: 0 });
$newElems.imagesLoaded(function(){
$newElems.animate({ opacity: 1 });
$container.masonry( 'appended', $newElems, true );
});
}
});
return false;
}
This is so far triggering when the user scrolls to the bottom of the page, its then getting the 'next' URL from the pagination and returning the full HTML of the page in the success call.
As you can see in my code, I want to get all divs with the class '.grid-item' to be used by the code below.
I am really struggling to get the '.grid-item' divs seperated to be used.
Is anyone able to explain how I can do this?
What you can do is convert the returned html to a jQuery object so that you can parse it using find() to get the relevant elements. This is done easily by wrapping the html like this, $(html), but if there is a doctype declaration then that will break it. What I normally do is make sure I've only got data that starts from the opening html tag.
Try this...
function loadNew(){
var next = $('a.next').attr('href');
$.ajax({
url: next,
success: function(html){
html = html.substr("<html"); // remove the doctype
var $newElems = $(html).find(".grid-item").css({ opacity: 0 });
$newElems.imagesLoaded(function(){
$container.append($newElems).masonry("appended", $newElems, true);
$newElems.css({ opacity: 1 });
});
}
});
return false;
}
Also, you need to first append the elements to the container, and then tell masonry that you've done so. The masonry appended call doesn't actually append anything.
Hi everyone i have one problem about masonry items.
I have created this DEMO from codepen.io
In this demo you can see there is this javascript code:
$(window).load(function()
{
$( function() {
var $container = $('.posts-holder');
$container.masonry({
isFitWidth: true,
itemSelector: '.kesif-gonderi-alani'
});
});
});
I show only 10 posts when a page is opened. If user want to show other 10 posts then user needs to click (show more button). I created this ajax function for show more posts.
$('.showmore').live("click",function(event)
{
event.preventDefault();
var ID = $(this).attr("id");
var P_ID = $(this).attr("rel");
var URL=$.base_url+'diger_fotograflar_ajax.php';
var dataString = "lastid="+ ID+"&profile_id="+P_ID;
if(ID)
{
$.ajax({
type: "POST",
url: URL,
data: dataString,
cache: false,
beforeSend: function(){ $("#more"+ID).html('<img src="wall_icons/ajaxloader.gif" />'); },
success: function(html){
$("div.posts-holder").append(html).each(function(){
$('.posts-holder').masonry('reloadItems');
});
$("#more"+ID).remove();
}
});
}
else
{
$("#more").html('The End');// no results
}
return false;
});
this code working when clicking showmore button $('.posts-holder').masonry('reloadItems'); but collecting new posts in one place. But when I change the width of the page everything is improving.
I think that you can use $container.masonry(); after adding your elements, like this :
$("div.posts-holder").append(html).each(function(){
$('.posts-holder').masonry('reloadItems');
});
$container.masonry();
You can see it working here.
Hope that can help.
you have to use the appended method of masonry ... otherwise how would it know that you have added any new element.
Adding the elements simply wont align them as masonry doesnt have any event listner for new element added.
var el = $('<div class="kesif-gonderi-alani" style="height:300px;"></div>')
$container.masonry().append( el ).masonry( 'appended',el );
Hers is small demo on codepen http://codepen.io/knaman2609/pen/xbJMRY
Click on the button to append elements dynamically
http://masonry.desandro.com/methods.html
I'm using infinite scroll with masonry everything works fine and lines up correctly. I have a button that when i click it makes that div bigger and shows extra content. the button works and loads fine when the page initially loads but when i scroll down and infinite loads new items and if i click the button to show more it jumps to the top of the screen.
I'm guessing i have to do some callback? Im kinda confused on this. How should I approach it?
this is the code im using:
$(function(){
$(".fancybox").fancybox();
var $container = $('.main_containera');
$container.imagesLoaded(function(){
$container.masonry({
itemSelector: '.item1',
columnWidth: 0
});
});
var nextSelector = '.pagination-next a';
var origNextUrl = $(nextSelector).attr('href');
var offsetRegex = /(offset=)([0-9]+)/;
var offset = origNextUrl.match(offsetRegex)[2];
$container.infinitescroll({
navSelector : '.paginate', // selector for the paged navigation
nextSelector : '.pagination-next a', // selector for the NEXT link (to page 2)
itemSelector : '.item1', // selector for all items you'll retrieve
loading: {
finishedMsg: 'No more pages to load.',
img: 'http://i.imgur.com/6RMhx.gif'
}
},
// 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 );
});
}
);
$('.comment_tr').click(function (e) {
$(this).toggleClass('disabled');
$(this).parent().parent().parent().find('form').slideToggle(250, function () {
$('.main_containera').masonry();
});
e.preventDefault();
});
});
Try changing
$('.comment_tr').click(function (e) {
$(this).toggleClass('disabled');
$(this).parent().parent().parent().find('form').slideToggle(250, function () {
$('.main_containera').masonry();
});
e.preventDefault();
});
to
$('.comment_tr').click(function (e) {
$(this).toggleClass('disabled');
$(this).parent().parent().parent().find('form').slideToggle(250, function () {
$('.main_containera').masonry();
});
e.preventDefault();
e.stopPropagation( );
});
The click event may be propagating up to another link element which has an empty href or one that returns the user to the same page which usually just takes you back to the top. Alternatively, you could replace e.preventDefault(); and e.stopPropagation(); with return false;.
It's hard to say for sure that that's the issue without seeing the HTML though.
Could you post the HTML if that change doesn't work?
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
});
I have searched just about every forum out there and found several ways to make a Isotope masonry layout with filtering work with Infinite Scroll running Wordpress. And none of them seem to be giving me what I'm looking for.
At the moment I got the Masonry layout working, with filtering. When I implement Infinite Scroll it loads the content underneath the other content, a pretty common issue working with Isotope and Infinite scroll. However, when applying the .appended method in order to sort the newly loaded posts into my site, it messes up my whole layout.
I suspect I'm not entering the .appended line at the right place. Here's my js without the .append:
$(function () {
var $page = $('#page')
});
$(function () {
var $container = $('#content'),
filters = {},
// get filter from hash, remove leading '#'
filterSelector = window.location.hash.slice(1);
$container.imagesLoaded(function () {
// bind isotope to window resize
$(window).smartresize(function () {
// jQuery has issues with percentage widths
// so we'll manually calulate it
var colW = Math.floor($container.width() * 0.49);
$container.isotope({
});
// trigger resize so isotope layout is triggered
}).smartresize();
});
$('#nav a').click(function () {
// store filter value in object
// i.e. filters.color = 'red'
var $this = $(this),
name = $this.attr('data-filter-name'),
value = $this.attr('data-filter-value'),
isoFilters = [],
filterName, prop;
filters[ name ] = value;
for (prop in filters) {
isoFilters.push(filters[ prop ]);
}
var filterSelector = isoFilters.join('');
// trigger isotope if its ready
if ($container.data('isotope')) {
$container.isotope({filter: filterSelector});
}
window.location.hash = filterSelector;
// toggle highlight
$this.parents('ul').find('.selected').removeClass('selected');
$this.parent().addClass('selected');
return false;
});
// if there was a filter, trigger a click on the
// corresponding option
if (filterSelector) {
var selectorClasses = filterSelector.split('.').slice(1);
$.each(selectorClasses, function (i, selectorClass) {
$('#nav a[data-filter-value=".' + selectorClass + '"]').click();
});
}
$container.isotope({
itemSelector: '.box',
filter: filterSelector,
animationOptions: {
duration: 750,
easing: 'linear',
queue: false,
}
});
});
#nav being my menu, #content being my container, and .box being my posts.
Could anyone advise me as to where I need to insert the .appended command?