Using Masonry, jQuery, and PHP to make an album cover gallery
Asked Answered
D

4

7

I read about Masonry and after failing to get image appending to work was advised to switch to the successor Isotope. I was trying to improve or create variations on an album cover gallery, something I've done once or twice before using the same PHP classes.

I can get the basic functionality to work, but a button to click to add more images has always failed to work. I keep reading jQuery documentation and I've tried various JavaScript debuggers but I always end up with no images being added to my gallery when I click.

Trial and error is definitely required to get the best looking layout.

The biggest album cover seems to be 500 pixels with the smallest found in APIs was 75, choosing the right column width helps. I'm currently using 75 but 50 might have worked better. I just want to get adding images to work and be done with this little experiment.

I wanted to try something similar to this technique of appending more images to the bottom. I want to append more album covers which I fetch from various APIs (Amazon Product API, Last.fm, iTunes) using PHP. All the album covers come from APIs and I use PHP to find the URLs given the album title and artist. My code is running: http://www.muschamp.ca/Muskie/cdCoverGalleryV4.php

I've changed the CSS rule many times, now I just have the default CSS suggested by the Isotope author.

PHP Code that loops and produces 10 divs with one image per div

$myAlbumCollection->randomMember();
    $count = 0;
    print('<div id="container">');

    while ( $count < 10 )
    {
        // Check that current album is in Amazon 
        $buyLink = $myAlbumCollection->currentAlbumAmazonProductURL();
        $imageURL = $myAlbumCollection->currentAlbumRandomImageURL();
        if ( (strcmp($buyLink, '#') != 0) && (strcmp($imageURL, myInfo::MISSING_COVER_URL) != 0))
        {
            $count++;
            print('<div class="item">'); 
            print('<a href="' . $buyLink . '">');
            print('<img src="' . $imageURL . '" />');
            print('</a>');
            print('</div>');
        }
        $myAlbumCollection->goToNextAlbum(); // This could loop forever if it doesn't find enough album covers, but in reality will timeout 
    }
    print('</div>');

And lastly here is the javascript, the final problem is in here somewhere:

<script>
$(function(){

  var $container = $('#container');


  $('#insert a').click(function(){
    var $newEls = $.get('./moreAlbumCovers.php');
    $container.isotope( 'insert', $newEls );

    return false;
  });

  $container.isotope({
    itemSelector: '.item',
    masonry: {
    columnWidth: 75
    }
  });

});
</script>

The link gets called when clicked, I've stepped through it. The PHP produces DIVs As and IMG tags. I really am not sure what I'm doing wrong and repeated readings of the documentation isn't solving it. I've never really been a JavaScript guy. I'm not even a PHP guy, it seems right but repeated efforts to make it go have failed despite generous assistance and offering a bounty.

Thanks for the help.

Daw answered 21/2, 2013 at 17:34 Comment(7)
Hi Muskie, would you clarify what your specific question is?Outlaw
Is that clearer? Basically the code does stuff, but not the brick wall effect with my current settings. Eventually I want to get appending to work too.Daw
I keep reading the instructions here: masonry.desandro.com/demos/basic-multi-column.html and altering item width CSS entry and columnWidth javascript argument and I keep getting two columns and a lot of white space in my browser...Daw
It's really well explained in other answer #12115537Deaden
I can try switching to isotope maybe later tonight. From a client calling them they are very similar, I still don't have jQuery and PHP interaction down. I appreciate the help. I'm not sure why this problem has proven so stubborn.Daw
I think I gave up on the fetching more images ala Pinterest. Instead I just fetch 20 or 25 and lay them out pretty. The effect can be seen on my homepage muschamp.ca but it looks best if the images are the same width in my opinion.Daw
Apparently this thread got popular, or popular for my random website hacking, the original gallery returned 404 which is odd as I try to leave up even failed experiments but I have Isotope running on my homepage as linked to in the comment above, I gave up on appointing I just load a nice number of images and lay them out.Daw
K
4

Try adjusting the columnWidh value and width of item. Masonry aligns element with best fit column first layout. It works on mathematical equations. So a perfect, brick wall fitting is only hypothetical ideal case. It takes me a few tries on firebug and other tools to get the masonry working with ideally fitted layout. The key is to get the value of columnWidth and width, gutter etc in such a way that it solves the logic equations in good values.

:: EDIT ::
I found a link saved in my pockets page, of which i totally forgot about. It is a great tutorial. So i came back to give it here. Recommended to everyone who have trouble getting started with this plugin.

http://www.netmagazine.com/tutorials/get-started-jquery-masonry

Kassa answered 22/2, 2013 at 19:18 Comment(7)
I tried lots of values, and I started to see the behaviour I was expecting with I had no item width in my CSS rule which I must have typed at about the same time as your answer though maybe I was 57 minutes later. ;-)Daw
Thanks I'll check out the link. I still am not understanding how to append.Daw
Append what?? There is a demo for adding new elements on the masonry website.Kassa
I'm trying to append album covers, did you go to the link of my code running. The append demo calls another javascript which makes boxes on the fly. I need to modify it to call PHP that fetches album cover images from APIs...Daw
Tried on chrome dev tools and fireflow (firefox). The thing is that nothing happens when button is clicked. Try using jquery bind() instead of click() in the script. Or better if you first try the old-school <button id="append" onclick="append()"> just to see if the binding was the problem or something else with the request.Kassa
I tried both your suggestions bind() instead of click() does nothing but changing the button got the following error: "Unhandled Error: 'append' is not a function" The masonry function must have a longer more complicated name but I believe it is using some sort of listener anyway to clicking of the button id="append". I'm going to have to do more JavaScript research, or put up a bounty or something. The only good news is I solved a bunch of my other PHP issues while I was away from this problem.Daw
The function looks good enough to me. Check if it is actually getting success and alert the 'response'. As for Unhandled Error. I was suggesting that you create a function named append, instead of directly using the .click(), Just to resolve whether the problem is in the binding of the function, or in the ajax part of the function. If the old-skool worked, then there is issue in the event binding. If not, Then you are not getting the ajax properly. Since you only look for success: , Try getting response for fail, timeout etc.Kassa
T
3

Masonry isn't a very descriptive name for it. In fact it's an optimizing problem. It's something that is called np problem because there is too many permutations to check. Especially the masonry jquery plugin is a 1d bin-packing solver and it's arrange the bricks in vertical columns. Css by default arrange the bricks in horizontal order. In other words it's a depth-first sort of an adjacent tree model.

Update: Try adding masonry to your dummy div and delete everthing else:

           $('#dummy').load('./moreAlbumCovers.php').masonry("reload"); 

I think you overthink it. The variable is empty because you assign it to a dom object. It's most likely become also an object and not usefull.

Twila answered 23/2, 2013 at 18:45 Comment(3)
Thanks, I think I need to learn more about jQuery and JavaScript to solve this problem, either that or I'm totally not getting appending. I understand masonry isn't perfect, I'm giving it random sized images from APIs it does the best it can. A certain amount of trial and error is necessary to get the widths right.Daw
I only added the #dummy div because I couldn't call load on container... I'll try this but it doesn't seem like it will append, rather it will replace my grid with a different grid...Daw
Strange it doesn't quite work... I hit the button and nothing, but when I refresh with the browser refresh, 5 more CD covers show up at the top, they go in the blank #dummy div which is something, but I want them to be appended to the container... I'll have to think and consult the documentation again. Thanks.Daw
D
3

It's relly well explained here Jquery Masonry Seamless Responsive Image Grid + I would try to do exactly the same with isotope http://isotope.metafizzy.co/

edit: I think isoptope and masonry just sorting out 1 dimensional bin packing, and what you are maybe looking after is 2 dimensional bin packing

like this http://codeincomplete.com/posts/2011/5/7/bin_packing/example/ (check complex case it fits all boxes perfectly )

and lib for that https://github.com/jakesgordon/bin-packing/

Deaden answered 7/3, 2013 at 1:59 Comment(3)
So your suggestion is to switch to either isotope or yet another Javascript? I still think what I am trying to do can be accomplished with Masonry it seems to fit into the examples and is not dissimilar from Pinterest's layout. Pinterest has all their boxes the same width, it is the height that varies. I'm getting random sized images though I know what the largest and smallest size will be.Daw
Your problem is very different from pinterest due not fixed column width. You can try to have 1x 2x 4x width ( with powers of two it may work ), otherwise it won't sorry. I'am thinking now trying isotope will have exactly the same result (sorry), the bin_packing will work, but probably need some more integration, and the bin_packing lib fits the biggest boxes first and that also may not be what you want. If you would like archive something similar to pinterest set columns width to one value, and do only some height manipulation. You could resize images and just have one width.Deaden
I don't need perfection, I'm just trying to find a new and exciting way to display my record collection. I fetch all the album covers from various APIs (Amazon, Last.fm, iTunes, etc.) so they each use slightly different sizes. I could force the browser to resize them or I could resize them myself with PHP but that will just slow things down... Thanks for trying to help. I'll take a fresh look at it soon.Daw
D
2

To get the more brick wall like effect you don't set an item width using CSS. This wasn't crystal clear given the instructions here. But a lot of testing seems to indicate that just specifying a columnWidth and then letting the browser and javascript do it's best gets closer to the performance I'm looking for. Will have to tweak and eventually try appending...

Daw answered 22/2, 2013 at 20:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.