Help with Jquery + Masonry Plugin: How to expand/collapse boxes to reveal content
I'm using the masonry jquery plugin on a project: (http://desandro.com/resources/jquery-masonry)
Basically I have a set of boxes (thumbnails) in a grid. When one is clicked, I want it to expand to a larger size to show more content (additional images a开发者_如何学Cnd text). I'm struggling with how to make the thumbnail dissappear and then have new content appear in the expanded box. I don't know how to make the new content appear or where to store it on my page--and it needs to have a close button? The creator of the plugin gave me a quick tip for the expanding part, but the code I'm using has a set height and width and I want them to be variable depending on how much content is in the expanded state.
Here's my jquery code so far: http://pastie.org/1002101
This is a similar example of the behaviour I want to achieve (except my boxes will have have varying expanded sizes): (http://www.learnsomethingeveryday.co.uk)
You'll also notice from that example that it only allows 1 box to be expanded at a time--I would also like to have that functionality.
Sorry for all the questions--I'm pretty new to jquery, any help would be amazing!
Try this (demo here):
$(document).ready(function(){
$('#grid').masonry({
singleMode: false,
itemSelector: '.box',
animate: true
});
$('.box').click(function(){
if ($(this).is('.expanded')){
restoreBoxes();
} else {
restoreBoxes();
$(this)
// save original box size
.data('size', [ $(this).width(), $(this).height() ])
.animate({
width: 335,
height: 335
}, function(){
$('#grid').masonry();
})
.addClass('expanded');
}
function restoreBoxes(){
var len = $('.expanded').length - 1;
$('.expanded').each(function(i){
var box = $(this).data('size');
$(this).animate({
width: ( box[0] || 100 ),
height: ( box[1] || 'auto' )
}, function(){
if (i >= len) {
$('#grid').masonry();
}
})
.removeClass('expanded');
})
}
});
});
Update: Hi Jam, I didn't know you left a comment for me, next time please add comments under the answer or update your question. Also you can put "@" in front of the person's name and they will get a message flag.
In response to your question about set size and hidden content, I modified the demo (pretty much all of the HTML and CSS included) to show varying width boxes. Having the clicked box to expand to contain all of the hidden content has a slight problem. Normally, hidden content has a height and width of zero. But jQuery is able to determine the hidden content size, but it still has some problems because you might need to limit the width or height of the hidden content. So what I ended up doing was adding the hidden content in a inside of the box and adding a data-size
attribute to the box which contains the width and height of the expanded hidden content, for example:
<div class="box" data-size="380,380">
<p>This is the visible content.</p>
<div class="expandable">
This is the hidden content which shows when the box is clicked.
</div>
</div>
I've also included a way to hide the visible content when the box is expanded, by adding a hideable
class to the content, since the image you provided seems to have the original content hidden:
<div class="box" data-size="380,380">
<p class="hideable">This is the visible content.</p>
<div class="expandable">
This is the hidden content which shows when the box is clicked.
</div>
</div>
If the data-size
attribute is not set, then the script will default to the defaultSize
setting:
Note the demo is using $(document).ready(function(){...})
instead of $(window).load(function(){...})
as recommended by the author of masonry because jFiddle just doesn't want to work with window load.
$(window).load(function () {
var defaultSize = [180, 180]; // expanded box size: [width , height]
$('#grid').masonry({
singleMode: false,
columnWidth: 100,
resizeable: true,
itemSelector: '.box',
animate: true
});
$('.box').click(function () {
if ($(this).is('.expanded')) {
restoreBoxes();
} else {
var size = ($(this).attr('data-size')) ? $(this).attr('data-size').split(',') : defaultSize;
$(this)
// save original box size
.data('size', [$(this).width(), $(this).height()]).animate({
width: size[0],
height: size[1]
}, function () {
// show hidden content when box has expanded completely
$(this).find('.expandable').show('slow');
$(this).find('.hideable').hide('slow');
$('#grid').masonry();
});
restoreBoxes();
$(this).addClass('expanded');
}
function restoreBoxes() {
var len = $('.expanded').length - 1;
$('.expanded').each(function (i) {
var box = $(this).data('size');
$(this).find('.expandable').hide('slow');
$(this).find('.hideable').show('slow');
$(this).animate({
width: (box[0] || 100),
height: (box[1] || 'auto')
}, function () {
if (i >= len) {
$('#grid').masonry();
}
}).removeClass('expanded');
})
}
});
});
- sorry, I can't comment on others questions yet (hence the answer box)
@fudgey
I have this working with the jquery filter fudgey helped my with. My issue is that for whatever reason, in google chrome, the masonry items don't seem to finish positioning on page load. After something is clicked, all is fine, just the initial page load is problematic. Where/how would I set a loading time for masonry?
Additionally, is there anyway to get a pointer cursor working on this? Currently, a user would not know to click the elements.
I have an idea for this. You could change the code to this:
$('.box').click(function(){
restoreBoxes();
$(this)
// save original box size
.data('size', [ $(this).width(), $(this).height() ])
.animate({
width: 335,
height: 335
}, function(){
$('#grid').masonry();
})
.addClass('expanded');
}
$( '.expanded' ).find('.main_img').click(function() {
restoreBoxes();
});
You'll still need the code that defines the restoreBoxes function and the call to Masonry at the top, I only included the code that needs to be added. So the full code would look like this:
$(document).ready(function(){
$('#grid').masonry({
singleMode: false,
itemSelector: '.box',
animate: true
});
$('.box').click(function(){
restoreBoxes();
$(this)
// save original box size
.data('size', [ $(this).width(), $(this).height() ])
.animate({
width: 335,
height: 335
}, function(){
$('#grid').masonry();
})
.addClass('expanded');
}
$( '.expanded' ).find('.main_img').click(function() {
restoreBoxes();
});
function restoreBoxes(){
var len = $('.expanded').length - 1;
$('.expanded').each(function(i){
var box = $(this).data('size');
$(this).animate({
width: ( box[0] || 100 ),
height: ( box[1] || 'auto' )
}, function(){
if (i >= len) {
$('#grid').masonry();
}
})
.removeClass('expanded');
})
}
});
});
I'm not sure if this is the most efficient way, but I tried a version of this on a site I'm working on and was successful. This should make the div collapse only when you click on an image within the expanded div with the class ".main_img". You can replace this with whatever class name you want, but make sure that the image you want to click on to close the div has this class. If you wanted any image in the expanded div to close the div, you could simply use "img" instead of ".main_img". Let me know how this works, and if you get any errors, post them here.
精彩评论