2

I've looked through various questions on SO regarding this question, but none seems to solve my problem.

When the page first loads, I initiated masonry on the first ten images as follows:

$('img').load(function(){
    var masonry = $('#gallery').masonry({
        itemSelector: '.item',
});
});

Next, when a user scrolls to the bottom of a page, I call an ajax:

if ($(window).scrollTop() >= $(document).height() - $(window).height() + 5) {
            request_pending = true;
            $('#loading').show();
            $.ajax({
                url: '/timeline/getPhotosAPI',
                type: 'POST',
                data: { id:'<?=$id?>', offset: offset },
                success: function(html){
                    if(html.length > 0){
                        var response = JSON.parse(html);
                        $.each(response, function(i, item){
                            $('#gallery').append(item);
                            var $html = $(item);
                            $('#gallery').find('.item').masonry('appended', $html, true);
                        });
                        $('#loading').hide();
                        offset = parseInt(offset) + 10;
                        request_pending = false;
                    }else{
                        alert('fail');
                    }
                }
            });
        }

Where response is a JSON string of html DOMS from my php that looks something like :

array( 0 => '<div class="items"><img src="xyz" /></div>" );

The above code successfully appends my images into my #gallery container, but masonry doesnt read my ".item" classes and append the respective positioning to my newly appended items.

Any ideas?

He Hui
  • 2,196
  • 4
  • 29
  • 46

2 Answers2

1

Seems like Masonry doesn't work with html strings.

This is my code that works:

<script>
    var offset = 10;
    var request_pending = false;
    var container = document.querySelector('#gallery');
    var msnry = new Masonry(container, {
        itemSelector: '.item',
    });

    $(document).ready(function(){
            $(window).scroll(function () { 
            if (request_pending) {
                return;
            }
            if ($(window).scrollTop() >= $(document).height() - $(window).height() + 5) {
                request_pending = true;
                $('#loading').show();
                $.ajax({
                    url: '/timeline/getPhotosAPI',
                    type: 'POST',
                    data: { id:'<?=$id?>', offset: offset },
                    success: function(pictures){
                        if(pictures.length > 0){
                            var response = JSON.parse(pictures);
                            var elems = [];
                            var fragment = document.createDocumentFragment();

                            $.each(response, function(i, item){
                                var img = document.createElement("img");
                                $(img).attr("src", item['photo_file']);
                                var div = document.createElement("div");
                                $(div).addClass("item");
                                $(div).append(img);
                                fragment.appendChild( div );
                                elems.push( div );
                            });
                            // append elements to container
                            container.appendChild( fragment );
                            // add and lay out newly appended elements
                            $('#gallery').imagesLoaded( function(){
                                msnry.appended( elems );
                            });
                            $('#loading').hide();
                            offset = parseInt(offset) + 10;
                            request_pending = false;
                        }else{
                            alert('fail');
                        }
                    }
                });
            }
        });
    });
</script>

So my php returns a JSON string of image sources rather than HTML strings. Masonry only accepts DOM elements.

Note: imageLoaded.js is used here to prevent image stacking. Masonry refuses to work properly without it.

He Hui
  • 2,196
  • 4
  • 29
  • 46
  • Anybody facing this issue. It is possible to push STRINGS into Isotope for layout. However it is not documented. Check this CodePen from the developer themselves http://codepen.io/desandro/pen/jKrmF?editors=001. As well as this http://stackoverflow.com/questions/10034213/issues-with-isotope-appending – Komsomol Jul 16 '14 at 11:10
0

It looks like in the Masonry docs they are appending items to the container and then informing Masonry that they were appended.

var container = document.querySelector('#container');
var msnry = new Masonry( container );
container.appendChild( elem );
msnry.appended( elem );
msnry.layout();

See Masonry : Methods

$.each(response, function(i, item){
    $('#gallery').append(item);
    msnry.appedned(item);
});

You would need to set the msnry variable as a global, or at least higher level, when you create it.

After everything has been added, I believe you need to call msnry.layout(); to "activate" the new items.

whoacowboy
  • 6,982
  • 6
  • 44
  • 78
  • I've declared msnry at a global level (as suggested) and called msnry.layout(), but to no avail. The images are still not sorted. – He Hui Dec 08 '13 at 03:43
  • I assume you are appending them as well. I don't know if you are or not, but it might be good to call msnry.layout(); outside of your loop. Do you have a test site where I could check out what is happening when the JSON is loaded? – whoacowboy Dec 08 '13 at 04:18
  • I've made a fiddle that somewhat represents the issue i'm having right now. http://jsfiddle.net/limhehui/8Kp5w/1/ – He Hui Dec 08 '13 at 08:52