[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2665
  • Last Modified:

Alternate Row Color Every two Rows

How can i change the following to alternate the row color every two rows instead of each row ??


<cfoutput query="Get_Contact_Details" startrow="#URL.StartRow#" maxrows="#RowsPerPage#">
<!--- Use class "DataA" or "DataB" for alternate rows --->
<CFSET Class = IIF(Get_Contact_Details.CurrentRow MOD 2 EQ 0, "'DataA'", "'DataB'")>
<tr>
<td class="#Class#">#Get_Contact_Details.position#</td>
<td class="#Class#">#Get_Contact_Details.workno#</td>
<td class="#Class#">#Get_Contact_Details.mobileno#</td>
<td class="#Class#"><a target="_blank" href="mailto:#Get_Contact_Details.email#">#Get_Contact_Details.email#</a></td>
</tr>
</cfoutput>

Cheers

JT
0
jturkington
Asked:
jturkington
  • 8
  • 6
  • 3
  • +2
4 Solutions
 
mrichmonCommented:

<cfset rowClass= "DataA">
<cfoutput query="Get_Contact_Details" startrow="#URL.StartRow#" maxrows="#RowsPerPage#">
<cfif Get_Contact_Details.CurrentRow MOD 2 EQ 0>
    <cfset rowClass= IIF(rowClass EQ "DataA", "DataB", "DataA")>
</cfif>
<tr>
<td class="#rowClass#">#Get_Contact_Details.position#</td>
<td class="#rowClass#">#Get_Contact_Details.workno#</td>
<td class="#rowClass#">#Get_Contact_Details.mobileno#</td>
<td class="#rowClass#"><a target="_blank" href="mailto:#Get_Contact_Details.email#">#Get_Contact_Details.email#</a></td>
</tr>
</cfoutput>
0
 
mrichmonCommented:
Note I changed to rowClass since "class" is a reserved word
0
 
danrosenthalCommented:
Change:
<CFSET Class = IIF(Get_Contact_Details.CurrentRow MOD 2 EQ 0, "'DataA'", "'DataB'")>

To:
<CFSET Class = IIF(CEILING(Get_Contact_Details.CurrentRow/2) MOD 2 EQ 0, "'DataA'", "'DataB'")>
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
Jerry_PangCommented:
this also works
from
<!--- Use class "DataA" or "DataB" for alternate rows --->
<CFSET Class = IIF(Get_Contact_Details.CurrentRow MOD 2 EQ 0, "'DataA'", "'DataB'")>

to
<CFSET tmpMod= Get_Contact_Details.CurrentRow MOD 4>
<CFSET Class = IIF(tmpMod EQ 3 or tmpMod EQ 4, "'DataA'", "'DataB'")>

0
 
sunnyhiraiCommented:
I think you guys have it wrong. JT is asking to alternate colors every TWO ROWS not every SECOND row. It should be something like this:

<cfif (currentrow mod 4) le 2>
<cfset className="DataA">
<cfelse>
<cfset className="DataB">
</cfif>

Note a couple of differences:

1. I mod by 4 and check for values of 1&2 (i.e. le 2). This means the first two rows are DataA and the second two rows are DataB.

2. I use cfif instead of iif. While iif looks smaller (and hence appears to perform better) cfif is the better performer. This is because iif runs an evaluate function on the second and third argument which is slow.

I didn't put the rest of the code in since I think it is pretty obvious.

That said, the class code could be cleaned up too. You should use something like this:

<tr class="#className#">
<td>stuff in here</td>
<td>more stuff</td>
</tr>

Then when defining your style sheet, you should use something like this:

tr.DataA td {
background-color:silver;
}
tr.DataB td {
background-color:white;
}

Then you don't have to put a class on EVERY td. Instead just put it on the tr.

Sunny
0
 
mrichmonCommented:
danrosenthal,
1/2 = 0 mod 2 = 0
2/2 = 1 mod 2 = 1
3/2 = 1 mod 2 = 1
4/2 = 2 mod 2 = 0
5/2 = 2 mod 2 = 0

so that works after the first row, but it does not get teh first 2 rows the same color which is why I did not use that suggestion


sunnyhirai,
sorry but MOD arithmethic returns values 0 1 2 3 so yours is checking for 0 1 and 2 which would give 3 rows of one color and 1 row of the other color.


Jerry_Pang,
tmpMod EQ 4 will NEVER be true because mod 4 arithmetic returns values of 0 1 2 3 - so you, like sunnyhirai, are coloring 3 rows one color and 1 row the other color
0
 
sunnyhiraiCommented:
Oops. You are right there. And I thought I could just do it in my head. Since I've done it before, I didn't bother to check my code; however, it is important to note that your original post also gives you incorrect results. You get every second row alternating instead of every two rows alternating. But the fix is easy.

You can change the if statement to read

<cfif (currentrow-1) mod 4 le 1>
<cfset className="DataA">
<cfelse>
<cfset className="DataB">
</cfif>

And you will then get the right results.

Note also that the rest of my post is a better way. You aren't outputting the className over and over and taking out the iif statement will give better code. But there is actually a way that probably looks nicer and executes better because it doesn't use an if or iif statement at all.

<cfoutput>
      <style>
            table.grid {
                  width:640px;
                  border-collapse:collapse;
                  }
            table.grid td {
                  border-top:1px solid silver;
                  border-bottom:1px solid silver;
                  }
            table.grid tr.row1 td, table.grid tr.row2 td {
                  background-color:##f0f0f0;
                  }
            table.grid trl.row0 td, table.grid tr.row3 td {
                  background-color:white;
                  }
      </style>

      <table class="grid">
            <cfloop query="query">
                  <tr class="row#query.currentrow mod 4#">
                        <td>#query.id#</td>
                        <td>#query.name#</td>
                  </tr>
            </cfloop>
      </table>
</cfoutput>

It uses very simply mod 4 arithmetic for the fastest execution speed and relies on the definition of the styles to alternate every two rows. FYI, the order of classnames would be row1, row2, row3, row0, row1, row2, row3, row0, etc... You could add a little more math to get the row numberings more logical but I kind of like having minimal math.

By the way, this works great for every second row coloring as well. For example, just use #currentrow mod 2# instead and define for row1 and row0 only. No if statements so you get ultra clean code.

Sunny
0
 
mrichmonCommented:
Actually you get every two rows alternating not every second row.

Look that first I do a mod and only do the next part if the mod is 0

So:

1 mod 2 = 1
2 mod 2 = 0
3 mod 1 = 1
4 mod 2 = 0

So the second part only happens on row 2 and row 4 and row 6 etc...

And the second part does this:
<cfset rowClass= IIF(rowClass EQ "DataA", "DataB", "DataA")>

which says if the color is DataA make it DataB - if it is not DataA (i.e. is DataB) then make it DataA.

Although I should have put the change code at the end of the loop like this:

<cfset rowClass= "DataA">
<cfoutput query="Get_Contact_Details" startrow="#URL.StartRow#" maxrows="#RowsPerPage#">
<tr>
<td class="#rowClass#">#Get_Contact_Details.position#</td>
<td class="#rowClass#">#Get_Contact_Details.workno#</td>
<td class="#rowClass#">#Get_Contact_Details.mobileno#</td>
<td class="#rowClass#"><a target="_blank" href="mailto:#Get_Contact_Details.email#">#Get_Contact_Details.email#</a></td>
</tr>
<cfif Get_Contact_Details.CurrentRow MOD 2 EQ 0>
    <cfset rowClass= IIF(rowClass EQ "DataA", "DataB", "DataA")>
</cfif>
</cfoutput>


Which makes row 1 = does nothing so it is DataA
row 2 prints DataA then changes to DataB
row 3 prints DataB
row 4 prints DataB then changes to DataA
row 5 prints DataA
row 6 prints DataA then changes to DataB
etc...


I didn't look at changing the css code or I too would have done it as a class on the row.

I also thought of having classes named on the MOD values, BUT the question asked to use DataA and DataB.

There is an error however in this line of your code:
<tr class="row#query.currentrow mod 4#">
This will throw an error.

You can do #Evaluate(query.currentrow mod 4)# but that is inefficinet
of you can do <cfset rowclass = query.currentrow mod 4>
but that isn't the greatest either...

Anyway the questiona sked to use DataA and DataB which was why I wrote the answer the way I did.
0
 
sunnyhiraiCommented:
Even if using DataA and DataB, I think the original method is a little inefficent and very confusing but you are right in that it will provide the right result; however, you can still use the if statement I mentioned and get cleaner and faster executing code.

I'm referring to this code:

<cfif (currentrow-1) mod 4 le 1>
<cfset className="DataA">
<cfelse>
<cfset className="DataB">
</cfif>

There is no error in this code of mine you mentioned though.

<tr class="row#query.currentrow mod 4#">

I know because I ran it and it works. The only exception is if you are running a version of ColdFusion older than 6.0 I believe. The new java-based versions of ColdFusion allows you to put full expressions within # signs.

Sunny
0
 
jturkingtonAuthor Commented:
Thanks guys for all your help, i am open to changing the CSS code as well if you want to give me an example on what way to change it

Cheers

JT
0
 
sunnyhiraiCommented:
Hi JT,

This code I used earlier will work with minor modifications to fit your query. I know it works because I tried it. Furthermore, this code runs fast and is easy to read:

<cfoutput>
     <style>
          table.grid {
               width:640px;
               border-collapse:collapse;
               }
          table.grid td {
               border-top:1px solid silver;
               border-bottom:1px solid silver;
               }
          table.grid tr.row1 td, table.grid tr.row2 td {
               background-color:##f0f0f0;
               }
          table.grid trl.row0 td, table.grid tr.row3 td {
               background-color:white;
               }
     </style>

     <table class="grid">
          <cfloop query="query">
               <tr class="row#query.currentrow mod 4#">
                    <td>#query.id#</td>
                    <td>#query.name#</td>
               </tr>
          </cfloop>
     </table>
</cfoutput>

There are other ways to do it but most of them require at least one "if" statement and a variable assignment. I'm not against variable assignments when they make the code easier to understand but in this case, I think the code is cleaner and more clear without it.

Basically the #query.currentrow mod 4# part will start looping starting with 1 then goes to 3 then back to 0 like this:

1, 2, 3, 0, 1, 2, 3, 0

Therefore your class styles should reflect that the first two rows should have a class of row1 and row2 while the second alternate set should have a class of row3 and row0 (as shown in the example).

In case you aren't a CSS guru, the class definitions like this:

table.grid tr.row1 td

means that it applies to a td INSIDE OF a tr with class row1 INSIDE OF a table with class grid. The comma then create another definition so the full definition is something like this:

          table.grid tr.row1 td, table.grid tr.row2 td {
               background-color:##f0f0f0;
               }

This defines both for tr.row1 and tr.row2 together so you don't have to have two separate definitions.

I threw in a few others definitions (like lines between rows and border-collapse) just to make the table prettier. You can style as you please.

Sunny
0
 
mrichmonCommented:
sunnyhirai,

Well I got an error with #query.currentrow mod 4# on CFMX 6 so maybe it works in 7, but not in all of 6.

jturkington,
either the method I showed or the last method sunnyhurai showed will work.
If you are willing to change the class names then naming the classes based on mod arithemtic and abtracting to a class on the cells in a row as opposed to defineing the class per row is more efficeint.
0
 
sunnyhiraiCommented:
Hi Rich,

You shouldn't get an error. I'm running 6 and it works fine. Did you name your query "query" instead of "get_contact_details"? I didn't make the exact translation for the code to work in the original post. It is just an example of how you could do it.

I think to be exact, I am running 6.1 but if you haven't upgraded to at least 6.1 I'd highly recommend it since there is a huge performance difference with respect to code compilation. In fact, I couldn't use 6 because it was too slow for me while developing.

Sunny
0
 
Jerry_PangCommented:
yep correction it should be
<CFSET tmpMod= Get_Contact_Details.CurrentRow MOD 4>
<CFSET Class = IIF(tmpMod EQ 3 or tmpMod EQ 0, "'DataA'", "'DataB'")>


1 mod 4 = 1   If 3 then A or 0 then B = 0
2 mod 4 = 2   If 3 then A or 0 then B = 0
3 mod 4 = 3   If 3 then A or 0 then B = 1
4 mod 4 = 0   If 3 then A or 0 then B = 1
5 mod 4 = 1   If 3 then A or 0 then B = 0
6 mod 4 = 2   If 3 then A or 0 then B = 0
7 mod 4 = 3   If 3 then A or 0 then B = 1
8 mod 4 = 0   If 3 then A or 0 then B = 1

my formula still works.
0
 
Jerry_PangCommented:
if 3 or 0 i mean..

mod the current row. if mod is 0 or 3 then false else true.
0
 
mrichmonCommented:
Sunny... I assume "Rich" is referring to me?  I can only guess since that isn't my name or my username.

I have used 6.1.  It gives an error... just something ot be awareof, but not worth going into since it distracts from tehuser's question.

Jerry_Pang
Yep with that correction it does work.
0
 
danrosenthalCommented:
My code works. Did you try it?

to mrichmon:
Note that in my first post I used the CEILING function (which rounds up to the next integer) which will give the desired result.

Formula: CEILING(x/2) MOD 2
where x is the current rownumber:
x=1, CEILING(1/2) = 1 mod 2 = 1
x=2, CEILING(2/2) = 1 mod 2 = 1
x=3, CEILING(3/2) = 2 mod 2 = 0
x=4, CEILING(4/2) = 2 mod 2 = 0
x=5, CEILING(5/2) = 3 mod 2 = 1
x=6, CEILING(6/2) = 3 mod 2 = 1
etc.




0
 
mrichmonCommented:
Ah I missed the ceiling.
0
 
mrichmonCommented:
jturkington,

I think you will see that there are many answers that will do what you want ;o)
0
 
sunnyhiraiCommented:
Sorry, mrichmon = rich yes.

What kind of an error? Seriously. I ran the code. It outputs. It looks fine.

Furthermore, I often put complex expressions in pound signs for efficiency.

Sunny
0

Featured Post

Upgrade your Question Security!

Add Premium security features to your question to ensure its privacy or anonymity. Learn more about your ability to control Question Security today.

  • 8
  • 6
  • 3
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now