Appending div to dynamic grid layout - javascript

I am using this jquery plugin http://packery.metafizzy.co/ to create a dynamic grid layout. The plugin is working perfectly.
The problem is :
I am trying to create an option to add a dynamic grid on click event. If I hand code the html code for grid then the grid shows up perfectly but if I append the grid code to my template layout using jquery then the grid shows up from the very top of the layout and the plugin doesn't seem to adjust the grid position.
You can check my code and see the problem live here: http://jsfiddle.net/A7ubj/2/
I think the plugin is not adjusting the grid because my jquery append code is making the grid seat on the top.
Could you please tell me how to append the grid so that the plugin can adjust the grid perfectly?
This is how I am appending:
$(function(){
$('#myID').click(function(){
$( "#container" ).append( $( '<div class="item diff">Grid</div>' ) );
});
});
And this is my entire code:
JS:
<script src="http://code.jquery.com/jquery-1.10.2.min.js" type="text/javascript"></script>
<script src="packery.pkgd.min.js" type="text/javascript"></script>
<script>
$( document ).ready(function() {
var $container = $('#container');
// initialize
$container.packery({
itemSelector: '.item',
gutter: 10
});
});
</script>
<script>
$(function(){
$('#myID').click(function(){
$( "#container" ).append( $( '<div class="item diff">Grid</div>' ) );
});
});
</script>
CSS:
#container{
background-color:#F00;
width: 1130px;
margin:0px auto;
}
.item { width: 275px; background-color:#0C0;}
.item.w2 { width: 560px; background-color:#036; }
.diff{
min-height:300px;
}
.diff2{
min-height:250px;
}
HTML:
<button id="myID">Click</button>
<div id="container">
<div class="item diff">Grid</div>
<div class="item w2 diff2">Grid</div>
</div>

You can call packery.reload() or just use the packery initialization function again after you have append the images and to calculate every new image position. I use the masonry plugin and masonry.reload().
Update: To make masonry work with infinitescroll use a callback function: How to enable infinite scrolling with masonry?
Here is the code from my website. I use jquery templates and prepend. You can see that it call masonry('reload') after the prepend. It also init masonry from the new container. It also correct the width and the height of each image because I think there is an error in masonry. I think it's not really what you need because I don't cache the brick but I rebuild the entire container when I need it to show a new category. In your example you physically add a brick but I don't understand why it didn't work. The result is the same but not so clean.
$j.getJSON($j("#tag") function(response)
{
// Start masonry animated
if (response && response.length)
{
var container = $j('#container');
container.masonry({
itemSelector: '.brick',
columnWidth: brick_width,
isAnimated: !Modernizr.csstransitions
});
boxCount = response.length;
counter = 0;
$j.each(response, function(idx, ele)
{
container.prepend($j("#brickTemplate").tmpl(ele)).masonry('reload');
}
container.imagesLoaded(function()
{
$j("#brick").each(function()
{
var content = $j(this).find(">div");
var height = $j(this).find("img").attr("height");
if ( height == undefined )
{
content.css({
height: "300px"
});
} else {
content.css({
height: height
});
}
// bricks fade in
$j(this).delay(Math.floor(Math.random() * 1600)).fadeIn('slow');
// Bind Mousemove
$j(this).mousemove(function()
{
.....
}
}
}
}

Related

Centering elements in isotope

Hello everyone and I hope you're doing well. I am using Isotope and below you can see the JavaScript that I have written. I find it impossible to center li elements if they are the Isotope elements. To see what I mean by centering, please see the images below. I've managed to center the whole Isotope to the screen but I need the elements to be centered too and not just float to the left side.
Let's start with my script code:
<script>
$(document).ready(function(e) {
$(".ullist li").addClass('element-item');
});
</script>
<script>
$(document).ready(function(e) {
// external js: isotope.pkgd.js
// init Isotope
var $grid = $('.grid').isotope({
itemSelector: '.element-item',
//layoutMode: 'fitRows',
});
//$('.grid').isotope({ layoutMode : 'fitRows' });
// filter functions
var filterFns = {
// show if number is greater than 50
numberGreaterThan50: function() {
var number = $(this).find('.number').text();
return parseInt( number, 10 ) > 50;
},
// show if name ends with -ium
ium: function() {
var name = $(this).find('.name').text();
return name.match( /ium$/ );
}
};
// bind filter button click
$('#filters').on( 'click', 'a', function() {
var filterValue = $( this ).attr('data-filter');
// use filterFn if matches value
filterValue = filterFns[ filterValue ] || filterValue;
$grid.isotope({ filter: filterValue });
});
// change is-checked class on buttons
$('.secmenu ul a').each( function( i, buttonGroup ) {
var $buttonGroup = $( buttonGroup );
$buttonGroup.on( 'click', 'a', function() {
$buttonGroup.find('.is-checked').removeClass('is-checked');
$( this ).addClass('is-checked');
});
});});
</script>
<script>
$(function(){
var $container = $('.grid'),
$body = $('body'),
colW = 20,
columns = null;
$container.isotope({
// disable window resizing
resizable: true,
masonry: {
columnWidth: colW,
isFitWidth: true
}
});
$(window).smartresize(function(){
// check if columns has changed
var currentColumns = Math.floor( ( $body.width() -10 ) / colW );
if ( currentColumns !== columns ) {
// set new column count
columns = currentColumns;
// apply width to container manually, then trigger relayout
$container.width( columns * colW )
.isotope('reLayout');
}
}).smartresize(); // trigger resize to set container width
});
</script>
Basic HTML structure:
<ul class="ullist grid">
<li> ... </li>
<li> ... </li>
<li> ... </li>
<li> ... </li>
</ul>
Isotope works pretty well with no issues (so far). This is my current layout:
And this is the desired layout.
I even checked here and tried to use David DeSandro's repository but with no success. So please guys can you help me here to achieve the layout above?
Thank you all in advance.
jQuery isotope centering
You might need to add some extra markup and increase the number of columns that Isotope is fitting items into.
<ul class="ullist grid">
<li><span class="box">...</span></li>
<li><span class="box">...</span></li>
<li><span class="box">...</span></li>
<li><span class="box">...</span></li>
</ul>
You'll then set the number of columns to something that is divisible by both 2 and 3. If you create 6, you can have the first 6 li items span two columns, and the final two span 3:
Then, use CSS to position your .boxes within the li items.
This gets tricky if you don't know how many 'stray' items you'll have at the end - you might need to use javascript to figure this out, append a class (such as .span-2, .span-3, .span-6
The best solution for this is using the flex-box if you not concerned to support for old browsers(below IE8). Check this pen for flex-box solution codepen Link.
ul {
width: 600px;
list-style: none;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
}
li {
width: calc((100% / 3) - 60px);
height: 200px;
background-color: #d91c5c;
margin: 30px;
}`

Imagesloaded not working with Infinite Ajax Scroll and Masonry

I have a website the uses bootstrap and the news that I have created with masonry, I used the Infinite Ajax Scroll, that call other news in a different div instead the pre-default. Very often, however, if one scrolls the page quickly, or if you have a slow connection, the elements overlap and do not return to their place, and I think this is due to the fact that it can't load images.
I tried to integrate Imagesloaded but it seems not work properly... and I don't know what to do...
Here is the source as I have proceeded,
HTML:
<div class="row masonry_base altre">
{$news}
</div>
<div class="row masonry altre">
<div class="col-lg-4 col-md-6 col-xs-12 post-grid">
{$news_scroll}
</div>
</div>
JS:
<script>
(function($) {
"use strict";
var $container = $('.masonry_base');
$($container).imagesLoaded( function(){
$($container).masonry({
itemSelector: '.post-grid',
columnWidth: '.post-grid'
});
});
})(jQuery);
</script>
<script type="text/javascript">
var container = document.querySelector('.masonry');
var msnry = new Masonry( container, {
itemSelector: '.post-grid',
gutterWidth: 20
});
msnry.reloadItems()
var $container = $('.masonry');
$($container).imagesLoaded( function(){
$($container).masonry({
itemSelector: '.post-grid',
columnWidth: '.grid',
gutterWidth: 20
});
});
var ias = $.ias({
container: ".masonry",
item: ".post-grid",
pagination: "#pagination",
next: ".next a",
delay: 1200
});
ias.on('render', function(items) {
$(items).css({ opacity: 0 });
});
ias.on('rendered', function(items) {
msnry.appended(items);
});
ias.extension(new IASSpinnerExtension());
ias.extension(new IASNoneLeftExtension({
html: '<div class="btn btn-info btn-block btn-icon-left ias-noneleft" style="text-align:center"><p><em>No news</em></p></div>'
}));
</script>
This code :
$($container).imagesLoaded( function(){
$($container).masonry({
itemSelector: '.post-grid',
columnWidth: '.grid',
gutterWidth: 20
});
});
Only applies imagesLoaded to whatever $container happens to be at its execution. It doesn't apply to dynamically added content. You should call this function again to the dynamic content added. Perhaps in your rendered callback.
Also, you should just call msnry.layout() to adjust content after the images had been loaded (It's not necessary to call $.masonry again)
Hope it helps

center single column in Masonry layout

I'm using the jquery/css masonry layout for a menu layout. Some menu pages only have one column so I need to centre the column, any idea how to do this? Currently using the following javascript:
<script>
var msnry;
function triggerMasonry() {
// don't proceed if masonry has not been initialized
if ( !msnry ) {
return;
}
msnry.layout();
}
// initialize masonry on document ready
docReady( function() {
var container = document.querySelector('.menu-columns');
msnry = new Masonry( container, {
gutter: 10
});
});
// trigger masonry when fonts have loaded
Typekit.load({
active: triggerMasonry,
inactive: triggerMasonry
});
</script>
You can add empty or hidden bricks to replace the wanted column.

Jquery tabs: autoHeight for expanding content

I am using jquery sliding tabs from this SITE, which work very nice. The only problem is that the autoHeight jquery function does not adjust to expanding content. Rephrase: The tab container will ajust to the height of the inactive content but the issue is that once the content inside container becomes active and expands vertically it will no longer fit and not be seen <--- It fails to adjust to that. Here is the example JSFFIDLE
I try doing this to adjust the height to expanding content but it is not working:
<script>
var height = 50 // Set to the height you want
$('.st_view').css('height', height+'px')
});​
</script>
Overall Jquery
<script>
$(document).ready(function() {
$('div#st_horizontal').slideTabs({
// Options
contentAnim: 'slideH',
autoHeight: true,
contentAnimTime: 600,
contentEasing: 'easeInOutExpo',
tabsAnimTime: 300
});
var height = 50 // Set to the height you want
$('.st_view').css('height', height+'px')
});​
</script>
If it is only togglers that cause the content to expand, you can modify your toggler code like this:
$('#title').click(function() {
$(this).toggleClass('active');
$('#content').toggle();
var $tab = $(this).closest('.st_tab_view');
$tab.closest('.st_view').css('height', $tab.height());
});
For a more general solution, get the jQuery resize plugin, and add this code:
$('.st_tab_view').resize(function() {
var $this = $(this);
$this.closest('.st_view').css('height', $this.height());
});

How can I Animate an Element to its natural height using jQuery [duplicate]

This question already has answers here:
Animate element to auto height with jQuery
(21 answers)
Closed 7 years ago.
I'm trying to get an element to animate to its "natural" height - i.e. the height it would be if it had height: auto;.
I've come up with this:
var currentHeight = $this.height();
$this.css('height', 'auto');
var height = $this.height();
$this.css('height', currentHeight + 'px');
$this.animate({'height': height});
Is there a better way to do this? It feels like a bit of a hack.
Edit:
Here's a complete script to play with for anyone that wants to test.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<title>jQuery</title>
<style type="text/css">
p { overflow: hidden; background-color: red; border: 1px solid black; }
.closed { height: 1px; }
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
<script type="text/javascript">
$().ready(function()
{
$('div').click(function()
{
$('p').each(function()
{
var $this = $(this);
if ($this.hasClass('closed'))
{
var currentHeight = $this.height();
$this.css('height', 'auto');
var height = $this.height();
$this.css('height', currentHeight + 'px');
$this.animate({'height': height});
}
else
{
$this.animate({'height': 1});
}
$this.toggleClass('closed');
});
});
});
</script>
</head>
<body>
<div>Click Me</div>
<p>Hello - I started open</p>
<p class="closed">Hello - I started closed</p>
</body>
</html>
I permit myself to answer this thread, even if it's been answered a long time ago, cuz it just helped me.
In fact, i don't understand the first answer : why opening a half-closed element to get its height, and then closing it again ?
At the beginning, you hide the element so that just a part of it appears, right ? The best way (i believe) to do this is onready, with javascript. So, when you hide the element onready, just save the orig height in a var, so you don't have to hide(onready)-show-save height-hide to be able to toggle the elements visibility.
Look at what i did, it works perfectly :
$(document).ready(function(){
var origHeight = $("#foo").css('height');
$("#foo").css({"height" : "80px"});
$("#foo .toggle").bind("click", function(event){ toggleFoo(event, lastSearchesMidHeight); });
});
Here, when you call your toggle function, you know what is your original element height without wanking around.
I wrote it fast, hoping it could help someone in the future.
the easiest solution I found was to simply wrap the content element with a div that is limited in height and set to overflow:hidden. This truncates the inner content element to the height of the wrapping div. when the user clicks, hovers, etc. to show the full height of the content element - simply animate the wrapping div to the height of the inner content div.
I could suggest an equally-hackish solution...Clone the element, position it out of view, and get its height...then delete it and animate your original.
That aside, you could also use $.slideUp() and $.slideDown():
$this.hasClass('closed') ? $(this).slideDown() : $(this).slideUp() ;
If you need to keep a 1px line, you can apply that with a parent element:
<div style='border-top:1px solid #333333'>
<div class='toggleMe'>Hello World</div>
</div>
And apply the slidingUp/Down on the .toggleMe div.
I'd also like to chime in on this old thread, if I may, in case my solution helps anyone. My specific situation is this: I have some div's that are set with a max-height value that limits them to three lines tall, and when the user mouseovers them I want them to expand to their natural height; and when the mouse cursor leaves the div, I want them to shrink back down to the clipped, max-three-lines-tall height. I need to use the CSS max-height property, rather than height, because I have some div's that contain only one or two lines of text and I don't want them unnecessarily tall.
I tried many of the solutions in this thread, and the one that worked for me was the 'hackish suggestion' involving cloned elements suggested by Jonathan Sampson. I translated his idea into the following code. Please feel free to suggest improvements.
The functions are delegated to a parent element to handle div's created via an Ajax call. The div.overflow_expandable class has the following declaration: { max-height: 5em; overflow: hidden; }
$('#results').delegate('div.overflow_expandable', 'mouseenter', function() {
var $this = $(this);
// Close any other open divs
$('#results div.overflow_expandable').not($(this)).trigger('mouseleave');
// We need to convert the div's current natural height (which is less than
// or equal to its CSS max-height) to be a defined CSS 'height' property,
// which can then animate; and we unset max-height so that it doesn't
// prevent the div from growing taller.
if (!$this.data('originalHeight')) {
$this.data('originalHeight', $this.height());
$this.data('originalMaxHeight', parseInt($this.css('max-height')));
$this.css({ 'max-height':'none',
height: $this.data('originalHeight') });
}
// Now slide out if the div is at its original height
// (i.e. in 'closed' state) and if its original height was equal to
// its original 'max-height' (so when closed, it had overflow clipped)
if ($this.height() == $this.data('originalHeight') &&
$this.data('originalMaxHeight') == $this.data('originalHeight')) {
// To figure out the new height, clone the original element and set
// its height to auto, then measure the cloned element's new height;
// then animate our div to that height
var $clone = $this.clone().css({ height: 'auto', position: 'absolute',
zIndex: '-9999', left: '-9999px', width: $this.width() })
.appendTo($this);
$this.animate({ height: $clone.height() }, 'slow');
$clone.detach();
}
}).delegate('div.overflow_expandable', 'mouseleave', function() {
var $this = $(this);
// If the div has 'originalHeight' defined (it's been opened before) and
// if it's current height is greater than 'originalHeight' (it's open
// now), slide it back to its original height
if ($this.data('originalHeight') &&
$this.height() > $this.data('originalHeight'))
$this.animate({ height: $this.data('originalHeight') }, 'slow');
});
Found this post and end up using Greg's original 1px suggestion - works great!
Just added a callback to the animate function, to set the height of the element to 'auto' when the animation ends (in my case, the content of that specific element could change and be bigger).
$('div').click(function() {
if($('p').is(':hidden')) {
$('p').slideUp();
} else {
$('p').slideDown(function() { $('p').css('height','1px'); });
}
}
That should set the height of the p tags to be 1px once they've finished sliding.
This worked for me.
<div class="product-category">
<div class="category-name">
Cars
</div>
<div class="category-products" style="display: none; overflow: hidden;">
<div class="product">Red Car</div>
<div class="product">Green Car</div>
<div class="product">Yellow Car</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('.product-category .category-name').click(function() {
if ($(this).parent().hasClass('active')) {
$(this).parent().removeClass('active');
var height = $(this).parent().find('.category-products').height();
$(this).parent().find('.category-products').animate({ height : '0px' }, 600, function() {
$(this).parent().find('.category-products').height(height).hide();
});
} else {
$(this).parent().addClass('active');
var height = $(this).parent().find('.category-products').height();
$(this).parent().find('.category-products').height(0).show().animate({ height : height + 'px' }, 600);
}
});
});
</script>
My solution is to store in the data attribute of the close button the original size of container (could have been stored also in the container itself, if you don't use the same button to also show again the container):
$(document).ready(function(){
$('.infoBox .closeBtn').toggle(hideBox, showBox);
});
function hideBox()
{
var parent = $(this).parent();
$(this).text('Show').data('originalHeight', parent.css('height'));
parent.animate({'height': 20});
return false;
}
function showBox()
{
var parent = $(this).parent();
$(this).text('Hide');
parent.animate({
'height': $(this).data('originalHeight')
});
return false;
}
I wanted to point to this answer, which suggest setting the height to "show" with the animate() function. I had to edit my "slideUp" style animate to use height:"hide" to work with it.

Categories

Resources