Reorder DOM elements
I have CSS floated elements with predefined width and I want them to transpose from rows to columns. Actually reordering them to look as if they were ordered by columns instead of rows as is usual with floated elements...
So the easiest way to put elements in columns is to use float: left;
on them. The problem is that we get ordering from left to right & top to bottom instead of top to bottom & left to right (as we can see in phone books for instance that use columns and data flows in columns not rows). The latter is much easily searchable when elements are ordered alphabetically because it's easier to follow columns than rows.
Anyway.
I know I could use CSS3 columns which list elements in the top-bottom-left-right order, but the problem is that IE still doesn't support them even in IE9.
What I actually need
What I need is a jQuery plugin that determines the number of floated elements per row and reorder them, so that they appear in the top-bottom-left-right order.
This can only work of course when floated elements have开发者_运维问答 a predefined fixed width. If they don't they don't appear being columns anyway.
Question
Is there a plugin for this functionality so I don't have to write my own? Because otherwise I will obviously have to.
Note for future reference: I've written such jQuery plugin which can be found here
Don't know if there is a plugin but here you go (accompanied fiddle: http://jsfiddle.net/58akv/1/):
jQuery:
// This is me being lazy and not wanting to copy/paste box 50 times
var box = $('div.box');
for (var i = 1; i < 50; i++) {
box.clone().text(i).appendTo(box.parent());
}
// Now that we have all elements
var i = 0;
// Specify how many you'd like per row, if you want to
var rowsPerColumn = 0;
var cols = 0;
$('.box').each(function() {
// remove float
$(this).css("float", "none");
if ($(this).parent('.col').length == 0) {
// if rowsPerColumn is 0 or undefined, figure it out ourselves
if (rowsPerColumn == 0 || !rowsPerColumn) {
// calculate how many fit into given width
var totalColumns = Math.floor($("#wrapper")[0].clientWidth / $(this).outerWidth(true));
// calculate how many boxes go into each column
rowsPerColumn = Math.ceil($('.box', '#wrapper').length / totalColumns);
}
// wrap this and next in col
var parent = $(this).parent();
var els = $(this).add($(this).siblings('.box').slice(0, rowsPerColumn-1));
parent.append($('<div></div>').addClass('col').append(els).attr('id', 'col'+ (++cols).toString()))
}
});
CSS (for example purposes):
.box {
background-color: #333;
width: 90px;
height: 90px;
margin: 5px;
color: #eee;
font-size: 2em;
float: left;
}
.col { float: left; }
HTML (for example purposes):
<div id="wrapper">
<div class="box">0</div>
</div>
Funny, because I literally JUST coded something like this for a project. I had a UL with a list of items in alphabetical order, but the ordering went from left to right instead of top/down per column.
The following script reorders the LIs accordingly:
var $lists = $('ul.list');
var columnCount = 3;
// reorder the ul so that the columns are left to right and still alphabetized
$lists.each(function() {
var $ul = $(this);
var $newList = $('<ul class="list" />');
var $lis = $ul.children('li');
var itemCount = $lis.size();
var leftovers = itemCount % columnCount;
var itemsPerColumn = [];
for (var i = 0; i < columnCount; i++){
itemsPerColumn[i] = Math.floor(itemCount / columnCount) + (i < leftovers ? 1 : 0);
}
var offsetIndex = 0;
var rowIndex = 0;
$lis.each(function(i){
var $li = $(this);
var columnIndex = i % columnCount;
$lis.eq(offsetIndex).clone().appendTo($newList)
offsetIndex += itemsPerColumn[columnIndex];
if (offsetIndex >= itemCount) offsetIndex = ++rowIndex;
});
$ul.replaceWith($newList);
});
Here's plugin; tried it, works great! https://github.com/litera/jquery-transpose
精彩评论