views:

52

answers:

2

This problem is similar to when creating alternate colour table-rows, only we are dealing with divs and margins instead of table rows and their colours.

The following code creates as many layers as there are genres returned from a query (if three genres are found, three layers are created); and within each layer created, the code creates as many layers as there are titles within that genre (for example, if there are five titles per genre, there will be three "genreName" layers, and inside each one there will be five "titleName" layers).

<cfoutput query="MyQuery" group="genreName">
    <div class="Genres">
        #MyQuery.GenreName#
        <cfoutput>
            <div class="Titles">
            #MyQuery.TitleName#
            <div>
        </cfoutput>
    </div>
</cfoutput>

This also means that all layers in each class are clones. If I have a columns layout where I do not want to assign a left/right margin to the first/last columns, this format breaks.

Is there a programmatic way to assign margins based on the layer number (record number, essentially) where I can apply conditional formatting (in this case, a left and right margin for the middle columns, and no left/right margins for first/last columns)?

Many thanks,

+1  A: 

Yes, create three different classes for left (with no left margin), middle (with both) and right (with no right), or however you need it set up.

Next, keep track of a counter (either at the genre loop or the title loop depending on what level you are doing your columns) and use the modulus operator to assign the correct class.

<cfset titleCount = 1> <!--- reset your title count --->
<cfoutput>
   <cfswitch expression="#titleCount MOD 3#">
      <cfcase value="1"><cfset titleClass = "titleleft"></cfcase>
      <cfcase value="2"><cfset titleClass = "titlemiddle"></cfcase>
      <cfcase value="3"><cfset titleClass = "titleright"></cfcase>
      <cfdefaultcase><cfset titleClass = ""><!--- should never get here ---></cfdefaultcase>
   </cfswitch>
   <div class="#titleClass#">
      #MyQuery.TitleName#
   <div>
   <cfset titleCount = titleCount + 1>
</cfoutput>

The key is that you need to keep your own counter because MyQuery.currentRow isn't going to tell you where you are in your current layer.

Jeff Price
Many thanks, Jeff; I think I will try the approach above first simply because it's a CSS solution and does not require me writing extra CF.
Mel
I agree. I wasn't aware of those css3 selectors. It's a very nice solution!
Jeff Price
+2  A: 

If what you actually want to do is having a fixed margin between elements, but none before the first nor after the last, you can use the first-child pseudo-class to overrule the general case:

has_margin { margin-left: 20px; }
column_container:first-child { margin-left: 0px; }

...
<div class="column_container">
     <div class="has_margin">...</div>
     <div class="has_margin">...</div>
     <div class="has_margin">...</div>
     <div class="has_margin">...</div>
     <div class="has_margin">...</div>
</div>

CSS3 defines a 'structural pseudo selector' that allows you to select every an+b'th child of an element. Setting a to the number of class clones allows you to define that many rules for each layer.

xtofl
@xtofl, thanks. I just tried this and it works for the first column, but not the last. Any ideas why?#content {width:960px; margin:0 auto; padding:30px;}#content .column {float:left; margin:20px;}#content .column:first-child {margin-left:0;}#content .column:last-child {margin-right:0;}<br />HTML is: <div id="content"> <div class="column">*3 </div></div>
Mel
My bad. It actually works, but I missed the clearing break I added under the float layers, which was becoming the last child. Is there an equivalent to one-before-last designation?
Mel
Figured it out, cheers!
Mel
Hmm... as expected, IE is throwing a fit... it's an awesome solution, but thanks to IE's absolute #$@% standard compliance, I may have to write a separate style sheet... this is just ridiculous a company as big as Microsoft can't write a decent browser.
Mel