jQuery.column
jQuery.column v1.0
Simulate CSS3-style automatic columnization for the few browsers (IE) that don’t support it.
It tries to follow CSS3 specification (http://www.w3.org/TR/css3-multicol/) closely.
Demo: http://www.vanderlee.com/martijn/demo/column
Source: https://github.com/vanderlee/column (MIT licensed)
Syntax:
$(<context>).column(<options>);
Arguments:
- context (required)
This should point to the DOM node(s) that hold the content to be columnized.
Typically this is a <div> element, but other elements are possible. - options (required)
An array or object containing any of the following options (based on CSS3 options). - width (default ‘auto’)
This option works like CSS3 “column-width”. Use it to specify the width of each individual column in pixels or set to ‘auto’ to use the “count” option. - count (default ‘auto’)
Works like CSS3 “column-count”. Set the number of columns to use. If “width” is set, “count” is ignored. If both “width” and “count” are set to ‘auto’ (default), the content will NOT be columnized. - gap (default ‘normal’)
Like CSS3 “column-gap”. Set the distance between two columns in pixels. If set to the default ‘normal’ value, the gap will be 1em, dependant on the context. - rule_color (default ” (empty string))
Like CSS3 “column-rule-color”. Specify the color olf the rule between two columns using any valid CSS color qualifier or name such as ‘black’, ‘#ab37e9′ or ’rgba(255,0,0,.5)’. If no color is specified or the value is set to an empty string, the color will be the same as CSS ‘color’ option. - rule_style (default ‘none’)
Like CSS3 “column-rule-style”. Sets the line-style of the rule. These allowed names are the same as the border-style names. To show the ruler, you need to atleast set a visible rule-style such as ‘solid’ or ‘dotted’. - rule_width (default ‘medium’)
Like CSS3 “column-rule-width”. Specify the width of the rule line between columns. You can either specify the width in pixels by using an integer number or use any of the border-width names ‘thin’, ‘medium’ or ‘thick’. - split (default ‘word’)
jQuery.column works by splitting the content up in parts which may be rearranged over the columns. By default any text at the top DOM level is split at every whitespace. The ‘word’ mode most closely (though not completely) matches CSS3 splitting. Alternatively you can choose ‘sentence’, which splits text at punctuation end-marks or create your own method.
Return:
- Returns the selected DOM elements so you can chain this plug-in like regulaer jQuery.
Examples:
$('body').column(); // Doesn't columnize content, since neither "width" nor "count" is specified.
$('body').column({count: 3}); // Spreads the content of <body> over 3 columns. Columns are stretched to fit the available width.
$('body').column({width: 250}); // Spreads the content of <body> over columns of 250px. Number of columns depends on the available space.
$('body').column({ // Columnize with all options...
width: 'auto', // Default, this line is redundant.
count: 4, // Spread over 4 columns.
gap: 20, // Space columns 20 pixels apart.
rule_style: 'dotted', // Show a dotted rule between columns.
rule_width: 'thin', // Set width of rule to 'thin' (usually 1 pixel).
rule_color: '#ccc', // Set color of rule to a light gray.
split: 'sentence' // Keeps sentences together.
});
Checklist:
- Make sure you set atleast one of ‘count’ or ‘width’ to enable columnization.
Also see:
- http://welcome.totheinter.net/2008/07/22/multi-column-layout-with-css-and-jquery/
A similar plug-in which works in a different way with different features
Is this supposed to be able to work with images? I tried it out on a div full of images (each wrapped in their own divs) and it made a mess. It made three columns but the second two are empty and it put all the sub divs underneath the first one in the hierarchy!
The reason is that currently only top-level elements are handled; if it’s text, the text will be split up into separate words, if not, the element will be handled as is. This has to do with styling issues; divs would have to be split into two, at which point things like
margin-topcannot readily be copied to clone divs. That being said, it should handle separate divs as separate elements.Do you have an example of HTML that is handled incorrectly?
Doesn’t seem to work on ie checked on 7 & 8.
Can this thing handle tables that are bigger then a single column. Say I want to have a article, then a table, where the article content would flow around the table in a “S” motion or even turn the table on its side to fit the other content on the next page and the table will fit on its own page.
I tested it on IE8/9 myself. Could you please send me an example of code that doesn’t work in IE7/8?
Currently not. The problem with handling tables and such is that they may have style applied to the top and bottom of the table.
Cutting the table in multiple parts would duplicate these styles so until I’ve figured out a way to handle this, it’s seen as a large, single, undivideable block, like an image.
Your example does not works on IE 7, 8 and 9 on Windows.
The problem seems to be with the WordPress popup for the demo; open the URL in IE and it works fine.
I’ll figure out what the problem is and fix it.
line 140 should be:
+ (c > 0? 'left:'+(left - Math.floor(column_gap / 2))+'px;' : '')
(you need to subtract the padding-left from the left: or else everything after the first column gets bumped too far to the right)
Thanks for the plugin… hope you figure out an IE fix soon, because it works nice.
@gv: Thanks for the fix, it’s in github now.
Works fine in IE8 and IE9. I don’t have a system with IE7 to test.
Works for me in IE8, but in IE9 it throws this error, if it helps:
SCRIPT16389: Incorrect function.
jquery.column-1.0.js, line 66 character 9
I tried googling the error briefly, but haven’t had a chance to look deeper.
@gv: From what I can see, this issue is a problem with IE9.
I’ve applied a simple workaround so it works on IE9 again. Latest version is not in github.
I used this on a section that had a definition list in it. In order to do so, I had to go several levels deeper. I replaced:
function _split(parent) {
var contents = new Array;
$(parent).contents().each( function(index, value) {
if (value.nodeType == 3) { // Node.TEXT_NODE
contents = contents.concat(split_strategies[settings.split](value));
} else {
contents.push(value);
}
});
return contents;
}
with:
function _split(parent) {
var contents = new Array;
$(parent).contents().each( function(index, value) {
if (value.nodeType == 3) { // Node.TEXT_NODE
contents = contents.concat(split_strategies[settings.split](value));
} else {
$(value).contents().each( function(index, child) {
if (value.nodeType == 3) {
contents = contents.concat(split_strategies[settings.split](child));
} else {
$(child).contents().each( function(index, grandchild) {
if (value.nodeType == 3) {
contents = contents.concat(split_strategies[settings.split](grandchild));
} else {
contents.push(child);
}
});
}
});
contents.push(value);
}
});
return contents;
}
Perhaps you could add some recursion to make this work as deep as it needs to go?
I tried your ie9 fix, and it caused a bit of a ruckus… it worked fine in your demo, but on my site, everything got pushed to the last column. I did some digging around and found a cause and fix for the ie9 bug on the previous version of your code…
change line 67 from:
node = node.splitText(split);
to:
if (split < node.length) {
node = node.splitText(split);
} else {
split = 0;
}
Apparently, IE9 is the only browser that can't handle splitText when the divider equals the length, so if you just check for that, everything's kosher. (btw, this should also be done under the sentence function as well…)
Thanks again for an awesome script.
@gv, I’ve just pushed your fix to github.
@Xandor: I haven’t included your patch. The problem is that by doing it the way you describe, you’re actually altering the structure of HTML. It might look right for definition lists but it doesn’t work for numbered lists or paragraphs, for example.
It’s quite a hard problem, that I don’t think is possible to fix without a ridiculous amount of code (essentially you’d need special code for each HTML tag and CSS style)
If you still want it, you can replace the block of code you added inside the _split function with
contents.concat(_split(value));, which does proper recursion to any depth.Pingback: 2012년 4월 2일 it 기술 동향 |
Hi Martijn,
Thanks for a great plugin! I’m trying to solve a problem with a responsive layout and I think your plugin is the closest I can find to a solution. I’m curious if it can be modified to use a maximum height, so users can read a long article of continuous text in multiple columns and rows without scrolling up and down to start the next column.
That’s a mouthful, but see this StackOverflow post if you want a better explanation with images: http://stackoverflow.com/questions/14188659/managing-text-columns-in-responsive-layout
Thanks again,
Duncan
What about the height of the columns, how can you define that?
Currently you cannot.
The reason is that you’d then need to either crop any overflow or generate additional (sets of) columns on the fly, neither of which I considered desirable when I created .column().
Great piece of work.
I needed to use it “nested” within a layout – i.e. one where the columns would appear next to other elements. This meant the first column was not on the far left of the screen, but would be positioned to the left of another element.
To do this I just changed the script around line 135 from
var left = 0
to
var position = $(element).offset().
var left = position;
Seems to work fine and keeps works for responsive web design. Not sure if it is useful to anyone else, or whether there would be wider implications of its usage.
Also – I found that I was getting an occassional bug (even before I amended the script) in ie (where esle!). It would make the first column disapear. To overcome this I called the function on window.load. Again – might be useful for someone.