6

So I am using jQuery Masonry and I want to call some jQuery every time it loads posts:

function manipulate(id) {
    $(id).each(function(){
    if($(this).height()>200){
        $('#container2').append(this);
    } else{
        $('#container').append(this);
    };
  });
};

So I want to call this function every single time that the next item in the Masonry container loads. This way it manipulates the item in the correct manner. How do I do that?

Update: description of Masonry

Masonry is a Javascript plug in that is like CSS floats forced to fit perfectly + infinite scrolling. It completely hides everything that would not be on page 1 if there was no infinite scroll, and then loads them when necessary. This means that my function will not affect any of the hidden items and needs to be recalled whenever Masonry loads the next set of items so that they appear in the right places. This could mean that without knowing Masonry, it is not necessarily possible for you to solve my problem, but you still can. A the end, Masonry "appends" the items to the Masonry container, and then "shows" them. So I guess what I need to do is append them to the correct containers after they have been appended to the Masonry container, but before it gets shown.

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');} );
      });
    }); $('.entry').show(500);
  });

I have tried putting the function in the Masonry blocks and even as the $newElems function to see if it will work when more images load, but it does not, and in fact somewhat breaks it.

How can I get it to run all the new elements loaded by Masonry through my jQuery so that they get appended to the right container?

dda
  • 6,030
  • 2
  • 25
  • 34
Ryan Saxe
  • 17,123
  • 23
  • 80
  • 128
  • I attempted to answer your question but cannot because the question is not clear to me. If it is not strictly necessary to understand what `masonry` is in order to answer your question, then you might want to clarify some details. For example, what will trigger the jQuery to fire? Is there a div called "masonry" that will have changed data? What has changed on the page due to user interaction? – cssyphus Jun 03 '13 at 23:12
  • @gibberish, [masonry](http://masonry.desandro.com/) is a jquery plugin to do a dynamic tile layout where the tile sizes can vary. – Charles Jun 03 '13 at 23:19
  • @gibberish yes it is and it also has infinite scroll, which is the relevant part of it here. I added a detailed description of masonry and the specific parts of masonry that are specific to my issue – Ryan Saxe Jun 03 '13 at 23:21
  • Man, the first line of the mansonry docs is `Methods`. The first described method is `appendend`. It gives an exemple on how perform something on new added elements – TCHdvlp Jun 03 '13 at 23:53
  • I know, and I use them in my code, but for some reason it wont run an outside function unless I am missing something. I will post my masonry code for you. The reason that my appending does not work in this case is that it wont append it to two separate containers. – Ryan Saxe Jun 04 '13 at 00:10
  • Maybe you could set a jsfiddle regarding your issue, no? – A. Wolff Jun 06 '13 at 10:59
  • jsfiddle wont show the next loading. Here is the [jsfiddle](http://jsfiddle.net/3TxR9/13/). If you want to see the issue, I have it hosted on a [tumblr page](http://testingjquery.tumblr.com/). You'll notice that when you scroll down and the next posts load, the posts that should load in the container on the right because they have height larger than 200px, load in the container on the left because that is the original masonry container. If I make the original container anything else, it would load there. – Ryan Saxe Jun 06 '13 at 14:36

3 Answers3

1

You only declared one Masonry instance for container, container2 has no Masonry instance, so it can't infinitely scroll anything. Also, ($(this).height()>200) will always be false if the image has not loaded yet, it'll default to undefined -> 0 > 200, which is always false. Either you need to wait for the image to load before placing it, or somehow get the dimensions of the image when the content is being loaded. You could hide it by default and place it in container, then on imagesloaded, check the height, and move it to the appropriate container and show it.

Ford
  • 2,559
  • 1
  • 22
  • 27
  • This is the complete and right answer, and should be accepted! Even though your question is very unclear !!! – arty Jun 11 '13 at 16:17
  • I know all of this, my question was how to do the jquery on any images that load, because when I put my function in the imagesloaded function, it didn't work as I stated on the question already posted. – Ryan Saxe Jun 11 '13 at 23:28
  • In order to make the imagesLoaded works correctly, detach the $newElems from the DOM tree, then execute the $newElems.imagesLoaded(callback), try this ! this should work – arty Jun 12 '13 at 08:17
  • how to I detach it from the DOM tree? – Ryan Saxe Jun 12 '13 at 18:25
  • because running `$newElems.imagesLoaded(manipulate('.entry'));` is not working at the moment – Ryan Saxe Jun 12 '13 at 18:35
0

Another idea is to bind an action to jQuery's .on() ( http://api.jquery.com/on/ ). on() binds on future elements as well, assuming they are properly attached to the DOM (for example through .append() ). So for example you can bind .click() events, on elements that have not been created yet.

Finally you can do a neat trick and make .append() trigger an event. Then attach a handler for that event to the big container where things are appended, so a function is automatically called. Here is a good example of that on append() do something, and a jsfiddle http://jsfiddle.net/rzRVu/

PS. on a sidenote, I see you function takes as input an ID, but then you call .each(). Id's in html code should be unique.

Update. I missed that you tried to do it properly through masonry, what breaks exactly? I see you are calling .imagesLoaded() on a jQuery variable, is that a plugin?

Community
  • 1
  • 1
alianos-
  • 886
  • 10
  • 21
  • imagesLoaded() is part of masonry I believe, and if I put it in the masonry, then the next images don't show, but the containers get bigger as if the images were appended. Also, I said ID, but in the actual code it is a class called `.entry` – Ryan Saxe Jun 07 '13 at 18:26
0

So using things said on the answers provided, I messed around and discovered how it was done...so the 'appended' part in imagesLoaded just needed to be replaced with the function! It was really a simple answer...I just had to replace this:

$wall.masonry( 'appended', $newElems,{isAnimated: false},
function(){$newElems.fadeIn('slow');} );

with this:

$wall.masonry(manipulate($newElems) ,{isAnimated: false},
function(){$newElems.fadeIn('slow');} );

Problem solved!

Ryan Saxe
  • 17,123
  • 23
  • 80
  • 128