This is something I've done many times in the past, but I thought I'd whip up a quick example and share it. Imagine you have a set of data you need to display in columns. With a table it's trivial. You loop and simply begin a new TR every two cells. But what if you aren't using tables? Imagine a CSS based layout with two columns side by side. The contents of the left column need to be every other item, starting with the first one. The contents of the right column need to be every other item, starting with the second one. Here is a quick snippet of code that demonstrates this.
<cfset col1 = []>
<cfset col2 = []> <cfloop index="x" from="1" to="#arrayLen(data)#">
<cfset item = data[x]>
<cfif x mod 2 is 1>
<cfset arrayAppend(col1, item)>
<cfelse>
<cfset arrayAppend(col2, item)>
</cfif>
</cfloop>
<cfset data = [1,2,3,4,5,6,7,8,9]>
I create an initial set of data with 9 items. I then create two arrays - one for each column. Finally I loop over the data set and if odd, add it to column 1, and if even, add it to column two. So to render this I just output my HTML/CSS and loop over each column.
<style>
#left {
float: left;
width: 200px;
}
#right {
float: left;
width: 200px;
}
</style> <div id="left">
<b>col1</b><br/>
<cfloop index="i" array="#col1#">
<cfoutput>
#i#<br/>
</cfoutput>
</cfloop>
</div>
<div id="right">
<b>col2</b><br/>
<cfloop index="i" array="#col2#">
<cfoutput>
#i#<br/>
</cfoutput>
</cfloop>
</div>
Here is how it looks - fancy, eh?
Archived Comments
one of other ways to do teh same thing would be so:
<cfset data = [1,2,3,4,5,6,7,8,9]>
<style>
#left {
float: left;
width: 200px;
}
#right {
float: left;
width: 200px;
}
</style>
<div id="left">
<b>col1</b><br/>
<cfloop index="x" from="1" to="#arrayLen(data)#">
<cfif x mod 2 eq 1>
<cfoutput>
#data[x]#<br/>
</cfoutput>
</cfif>
</cfloop>
</div>
<div id="right">
<b>col2</b><br/>
<cfloop index="x" from="1" to="#arrayLen(data)#">
<cfif x mod 2 eq 0>
<cfoutput>
#data[x]#<br/>
</cfoutput>
</cfif>
</cfloop>
</div>
Don't forget about the handy dandy "step" option in cfloops.
<cfset data = [1,2,3,4,5,6,7,8,9]>
<style>
#left {
float: left;
width: 200px;
}
#right {
float: left;
width: 200px;
}
</style>
<div id="left">
<b>col1</b><br/>
<cfloop index="x" from="1" to="#arrayLen(data)#" step="2">
<cfoutput>
#data[x]#<br/>
</cfoutput>
</cfloop>
</div>
<div id="right">
<b>col2</b><br/>
<cfloop index="x" from="2" to="#arrayLen(data)#" step="2">
<cfoutput>
#data[x]#<br/>
</cfoutput>
</cfloop>
</div>
#right {
float: left;
width: 200px;
}
</style>
<div id="left">
<b>col1</b><br/>
<cfloop index="x" from="1" to="#arrayLen(data)# step="2">
<cfoutput>
#data[x]#<br/>
</cfoutput>
</cfloop>
</div>
<div id="right">
<b>col2</b><br/>
<cfloop index="2" from="1" to="#arrayLen(data)#" step="2">
<cfoutput>
#data[x]#<br/>
</cfoutput>
</cfloop>
</div>
Good alternatives guys.
I am not sure how the code posted twice but, I will try it again.
Don't forget about the handy dandy "step" option for cfloops we can simplify code further.
<cfset data = [1,2,3,4,5,6,7,8,9]>
<style>
#left {
float: left;
width: 200px;
}
#right {
float: left;
width: 200px;
}
</style>
<div id="left">
<b>col1</b><br/>
<cfloop index="x" from="1" to="#arrayLen(data)#" step="2">
<cfoutput>
#data[x]#<br/>
</cfoutput>
</cfloop>
</div>
<div id="right">
<b>col2</b><br/>
<cfloop index="x" from="2" to="#arrayLen(data)#" step="2">
<cfoutput>
#data[x]#<br/>
</cfoutput>
</cfloop>
</div>
A float-left is enough if you want more than 2 columns:
<cfset data = [1,2,3,4,5,6,7,8,9]>
<cfset nrOfColumns=3>
<style>
#left {
float: left;
width: 200px;
}
</style>
<cfoutput>
<cfloop index="x" from="1" to="#arrayLen(data)#">
<div id="left">
#data[x]#
<cfif x MOD nrOfColumns EQ 0>
<hr>
</cfif>
</div>
</cfloop>
</cfoutput>
here is another alternative, all in one loop
<style>
#left {
float: left;
width: 200px;
}
#right {
float: left;
width: 200px;
}
</style>
<cfparam name="left_content" default="">
<cfparam name="right_content" default="">
<cfset data = [1,2,3,4,5,6,7,8,9,10]>
<cfloop index="x" from="1" to="#arrayLen(data)#">
<cfset item = data[x]>
<cfif x mod 2 is 1>
<cfset left_content=left_content&"#item#<br/>">
<cfelse>
<cfset right_content=right_content&"#item#<br/>">
</cfif>
</cfloop>
<div id="left">
<b>col1</b><br/>
<cfoutput>#left_content#</cfoutput>
</div>
<b>col2</b><br/>
<cfoutput>#right_content#</cfoutput>
</div>
Thank you for sharing this code. It does what I need ( I think) except I can't get it to pull my data from a list of subjects in my database. Can the data array be anything other than numbers? I have a database with field sub_name. Items in this list change so I don't want to have to manually make an array with this list of subjects, so I'd like the array to pull this list of sub_names and then display them in two columns (and of course I want the impossible--for the list to be alphabetical left column and flow up to the right column) Any insights appreciated and most welcome as I'm not a programmer. Thank you!
The data can be anything. If you did a db query, then line 6 in the first snippet would change to a cfloop query="'.
Exactly what I needed. Perfect, as usual.
Thanks Ray!
While this is very cool, most recordsets come from a database table or saved query (Access), right? So the <CFSET data="query_name_or_table"> seems like it may be worth looking into, shouldn't it?
'Just a thought....
I'm not quite sure I understand you. Whether or not it comes from a db table my solution still applies. Your comment, cfset data="somequery", doesn't make any sense. I just used an array to make it quicker. You could easily switch it to a query.