Group elements by position
A #gal
container is loaded with lots of images 开发者_StackOverflow(~60), all with defined CSS height (100px) and margin 5px;
Now, logically, the images widths may vary and when all images are visible, we cannot count the same number of images-per-'line' as they are all floated down if not room available to fit the #gal
width:
| ___ __ _____ _ | <--- the #gal with images inside
| __ ______ |
| ______ _ __ __ |
| __ ______ |
| _______ ____ _ |
How to group all images in the 'first' line (second... third...) by wrap()
ing them into a DIV ?
So here is a first idea:
- after the page is loaded and images are positioned - we could group all the images by its .position().top
:
5 5 5 5
120 120
245 245 245 245
380 380
525 525 525
EXAMPLE
Any idea?
Try something like this:
var div = $('<div />'); // The current working div
var pos = $('#gal img').position().top; // The position of the first image
$('#gal img').each(function(){
// If the next image has a different position from the one before it
// then add the working div to #gal and create a new working div.
if (pos != $(this).position().top) {
$('#gal').append(div);
div = $('<div />');
}
// Append a cloned copy of the image to the working div.
// This is important: we don't want to move the image
// because it will reflow the other images and mess up
// the rows.
div.append($(this).clone());
// Set the new position
pos = $(this).position().top;
});
// Now remove all of the old images
$('#gal > img').remove();
Fiddle: http://jsfiddle.net/PuqZe/1/
You could try something like this:
var groups = {};
$('#gal img').each(function(){
var pos = $(this).position().top;
if(typeof groups[pos] == 'undefined')
{
groups[pos] = [];
}
groups[pos].push(this);
});
$.each(groups, function (pos, elements) {
$('#gal').append('<div id="wrapper_'+pos+'" class="wrapper"></div>');
var wrapper = $('#gal #wrapper_'+pos);
$.each(elements, function () {
wrapper.append(this);
});
});
It will wrap all the images with the same position top in a wrapper div.
This will do it: http://jsfiddle.net/ebiewener/kr57a/2/
var gal = $('#gal');
gal.children('img').each(function(){
var el = $(this);
el[0].Pos = el.position().top;
})
.each(function(){
var el = $(this);
var rowWrapper = gal.children('.group' + el[0].Pos);
if(rowWrapper.length === 0){
el.wrap('<div class="wrapper group' + el[0].Pos + '"></div>');
}else{
el.appendTo(rowWrapper);
}
});
We loop through the images twice. The first time gets their position, storing it as a property on the HTML element object (el[0]). The second loop does the wrapping. The reason we need two loops is because the wrapping can affect the position of the other unwrapped elements in the same row, causing them not to get wrapped with the first element in that row.
- Create a function that returns the
".wrapper"
Element using jQuery's Object Element creator. - Inside a single loop check for the
.next()
element position is greater than the current one's.
If true, pass to the$wrap()
function a set of elements in the range of last-known-index to current index + 1 by using.slice()
. - Insert the generated wrappers Elements into and array, and once the work is done append that array to the
#gal
parent.
const wrapGalImg = () => {
const $el = $('#gal img'),
$wrap = ($ch) => $('<div>', {'class':'wrapper', append:$ch}),
wraps = []; // Array of wrapper elements with children
let i = 0;
$el.each((ei, ele) => {
const $next = $(ele).next();
if($next[0] && $next.position().top == $(ele).position().top) return;
wraps.push($wrap($el.slice(i, ei+1)));
i = ei+1;
});
$('#gal').append( wraps ); // Append all wrappers. Once.
}
$(window).on('load', wrapGalImg);
*{margin: 0;}
#gal img {
vertical-align: top;
height: 60px;
}
.wrapper {
background: #f00;
margin: 1px 0;
}
<div id="gal">
<img src="http://dummyimage.com/180x120/000/fff?text=FIRST">
<img src="http://dummyimage.com/175x104/f0f/fff">
<img src="http://dummyimage.com/150x100/a3d/fff">
<img src="http://dummyimage.com/278x125/cf5/fff">
<img src="http://dummyimage.com/199x120/e46/fff">
<img src="http://dummyimage.com/207x480/361/fff">
<img src="http://dummyimage.com/400x107/081/fff">
<img src="http://dummyimage.com/50x40/cc3/fff">
<img src="http://dummyimage.com/700x500/233/fff">
<img src="http://dummyimage.com/300x120/a26/fff">
<img src="http://dummyimage.com/301x177/f1d/fff">
<img src="http://dummyimage.com/164x239/d34/fff">
<img src="http://dummyimage.com/200x300/34e/fff">
<img src="http://dummyimage.com/175x120/72a/fff">
<img src="http://dummyimage.com/210x110/112/fff">
<img src="http://dummyimage.com/278x225/644/fff">
<img src="http://dummyimage.com/300x120/dc3/fff">
<img src="http://dummyimage.com/90x104/b30/fff">
<img src="http://dummyimage.com/120x60/bb3/fff">
<img src="http://dummyimage.com/140x125/aa3/fff?text=LAST">
</div>
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
So, no need for multiple loops, cloning or removing elements.
精彩评论