Friday, 1 July 2011

ASP, CSS & jQuery: dynamic styles and jQuery code for accordion menus

   


In a recent project I developed, I had to create a dynamic accordion with jQuery. The accordion is basically a gallery menu, and the tree structure of the menu itself is taken from a table in a database. What I had to do was to apply different styles to elements that needed to have different ids. Why different ids? Because I had to apply different behaviours to every single tree element with jQuery.
To do so I created a loop to style the elements and dynamically generate the related jQuery code. The following example uses asp, css style sheets and jQuery, all together.

We start from here
Some assumptions have to be taken. First of all, there's a database with a table containing the menu. Something like:
msm
DrawingsHand drawn
DrawingsPrinted
PhotosColour photos
PhotosBlack and white
The above table is called menugallery. What we want is a tree menu with an accordion effect. The menu will be dynamically generated from the table.


Creating the menu
To generate the HTML part of our page, we just need to create our repeat region and display the menu items in a bulleted list. The only trick we use here is to dynamically assign classes to the menu elements. To do so we will create a variable (called aa) and inside the loop every submenu element will have a different id.
<%
Dim aa
aa = 0
%>
We need a nested repeat region. I don't know if you've ever created one, however it's not that difficult (even if it's tricky). Let's consider the above table again. The first column is called m (which stands for menu) and the second column is called sm (submenu). We prepare the connection and get the recordset (menu), which will have a
<%=(menu.Fields.Item("m").Value)%>
and a
<%=(menu.Fields.Item("sm").Value)%>
Respectively, the menu items and the submenu items. Now we can create a nested repeat region. I assume, you know how to get the recordset.
The nested repeat region is:
<%
  menu_numRows = 0
%>
<%
  Dim numRows
  Dim index
   numRows = -1
   index = 0
   menu_numRows = menu_numRows + numRows
%>
 <%
  While ((numRows <> 0) AND (NOT menu.EOF))
%>
<%
  nest = menu.Fields.Item("m").Value
  If last_nest <> nest Then
   last_nest = nest
   aa=aa+1
%>
<%
  if index <> 0 then
%>
<%
  response.write "</ul></ul>"
%>
<%
  end if
%>
Then we create the menu itself:
<ul class="menu">
  <li><br>
     <a href="javascript:void(0)" class="submenuguide<%=aa%>"> <%=(menu.Fields.Item("m").Value)%></a>
  </li>
  <li>
   <ul id="submenu<%=aa%>">
    <%
     End If 'End of Nested Repeat
    %>
  <li>
   <ul>
     <li>
        <a href="yourlink"><%=(menu.Fields.Item("sm").Value)%></a>
    </li>
   </ul>
  </li>
<%
index=index+1
numRows=numRows-1
menu.MoveNext()
Wend
%>
The only customization needed here is yourlink. That is the link to open when a submenu item is clicked. Normally that would be another page with a variable (possibly the submenu item). As you can see, the repeat region will create a correct bulleted list. The rendered HTML code will be (don't use it, this is just for explanatory purposes):
<ul class="menu">
  <li><br>
    <a href="javascript:void(0)" class="submenuguide1">Drawings</a>
  </li>
  <li>
    <ul style="display: block;" id="submenu1">
      <li>       
       <ul>
         <li><a href="yourlink">Hand drawn</a></li>
       </ul>
     </li>
     <li>
      <ul>
        <li><a href="yourlink">Printed</a></li>
      </ul>
     </li>
   </ul>
  </li>
</ul>
<ul class="menu">
  <li><br>
    <a href="javascript:void(0)" class="submenuguide2">Photos</a></li>
  <li>
    <ul id="submenu2">
     <li>
      <ul>
       <li><a href="yourlink">Colour photos</a></li>
     </ul>
    </li>
    <li>
     <ul>
       <li><a href="yourlink">Black and white</a></li>
    </ul>
   </li>
  </ul>
 </li>
</ul>
Now we need to style everything and create the jQuery part.

The CSS and jQuery
From the above rendered code, we understand that we have a menu class and a submenu id. The latter is infact two ids in our example (submenu1 and submenu2). Those ids are dynamically created with the aa variable. We can style the menu, the <a> tag and the <ul> and the <li> tags the way we prefer. We need to concentrate on the two submenus because we need to style them dynamically.
In the head of our document, we create a new recordset called mc (menu content). The query we need is something counting the number of menu items in the menugallery table. That query is:
SELECT Count(*) AS MC FROM (select distinct m from menugallery)
That will give us the number of items in the table (the number of distinct m items in the menugallery table where m is the first column; in our case the result is 2). Now we use that value to create a loop region to style our submenus.
<%
dim mca
dim mc1
mca = mc.fields.item("MC").value+1
mc1 = 1%>
<%
Do while mc1 <> mca
%>
<style type="text/css">
ul#submenu<%=mc1%> {
    display:none;
    margin:0;
    padding:0;
    list-style:none;
    background: #808080;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 10px;
    font-weight: normal;
}
</style>
The given style is just an example. You can obviously change it.
Now we need to add the jQuery part and close the loop:
<script type="text/javascript" language="javascript">
<!--
$(document).ready(function(){

    $(".submenuguide<%=mc1%>").click(function(){
      if ($("#submenu<%=mc1%>").is(":hidden")) {
        $("ul[id*='submenu']").slideUp("slow");
        $("#submenu<%=mc1%>").slideDown("slow");
       } else {
        $("#submenu<%=mc1%>").slideUp("slow");
      }
    });
});
// -->
</script>
<%
mc1=mc1+1
Loop
%>
The above code will create the styles for submenu1 and submenu2, and the related jQuery code to open and close the submenus, when the menu items are clicked (note the submenuguide). Ah! Don't forget to put the link to the jQuery library in the head of your document...

It is clear that if we add some items to the menugallery table, the menu will change accordingly. That is quite useful, because we only need to add records to the table, but we don't need to change the code.

That was complicated! I hope I've been clear enough and that you will find this solution helpful. If you need help, just ask.

Happy coding to all of you!

0 thoughts:

Post a Comment

Comments are moderated. I apologize if I don't publish comments immediately.

However, I do answer to all the comments.