Solved

Dynamic Menu Control

Posted on 2006-07-06
26
417 Views
Last Modified: 2010-05-19
I used the following short tutorial to create my collapseable menus:
     http://javascript.about.com/library/blclmenu.htm

I built and modified a menu based on the short tutorial above.

What I need is a way to keep the menu open once the user navigates to another page page in the site with the same menu. I have thought about a few ways but I can't seem to get a solid grasp on it.

How can I remember the state of the menu to render it the same on the next page? ( open vs. collapsed)?
0
Comment
Question by:cipiWeb
  • 15
  • 6
  • 4
  • +1
26 Comments
 
LVL 11

Expert Comment

by:walkerke
ID: 17053235
Isn't the page they're viewing directly relative to their selection from the menu? If so, you could add a js variable in the head of each page with a different value that would indicate the menu state. Your js script would then open or collapse menu based on that value.
0
 

Author Comment

by:cipiWeb
ID: 17053543
Could you give me an example? I have thought of it, but I am not sure how to efficiently implement it between the javascript and the cookies.
0
 
LVL 11

Expert Comment

by:walkerke
ID: 17053772
Something like this:


<html>
    <head>
          <title>Testing</title>
        <style type="text/css">
             .menu { visibility: hidden; }
        </style>
        <script type="text/javascript"><!--
            var pageLoadLevel = 4;
            // the following would be better in an external javascript file:
           function menuLevel() {
              for (i=1; i<=pageLoadLevel; i++) {
                   document.getElementById("menuLevel" + i).style.visibility = "visible";
             }
           }
--></script>
    <body onload="javascript:menuLevel();">
        <div class="menu" id="menuLevel1">Menu Level 1</div>
        <div class="menu" id="menuLevel2">Menu Level 2</div>
        <div class="menu" id="menuLevel3">Menu Level 3</div>
        <div class="menu" id="menuLevel4">Menu Level 4</div>
        <div class="menu" id="menuLevel5">Menu Level 5</div>
        <div class="menu" id="menuLevel6">Menu Level 6</div>
        <div class="menu" id="menuLevel7">Menu Level 7</div>
        <div class="menu" id="menuLevel8">Menu Level 8</div>
    </body>
</html>
0
 

Author Comment

by:cipiWeb
ID: 17057783
Wouldn't that open all menus 1-4?

I'm looking for if say... menu 3, and 7 are opened at the time the user navigates to another page, those two menus are open on the next page.
0
 
LVL 11

Expert Comment

by:walkerke
ID: 17058691
Yes it would. It's just a sample -- I assumed you were using cascading menus. However, if the page being displayed is directly relative to the menu selection, then if menu 3 and 7 are opened, you would have to be displaying pages 3 and 7 at the same time in the same window.

Post your code so I can see what you're really doing -- at least the menu part of it.
0
 

Author Comment

by:cipiWeb
ID: 17059750
I have three kinds of blocks here:
 - One is both a header and a link (no sub menu to open or collapse). When you click you go somewhere
     - - The Anchor display is set to Block
 - One is a header. when you click on it, it opens and closes the menu
 - One is the sub menu elements, when you click on them, you go somewhere.
     - - The Anchor display is set to Block


function toggleMenu(objID){
      if(!document.getElementById){
            return;
      } else {
            var ob = document.getElementById(objID).style;
            ob.display = (ob.display == 'block')? 'none': 'block';
                  //Conditional Operator
                  //variablename=(condition)? valueifTrue:valueifFalse
      }
}

<!--Begin HeaderLink-->
<div id="menuCS_H" class="mH">
      <a id="menuCS" class="mHL" href="#">
            &ensp; Header Link
      </a>
</div>
<!--End HeaderLink-->
<!--Begin Header-->
<div id="menuCP_H" class="mH">
      <div id="menuCP" class="mHL" onclick="toggleMenu('menuCPSub')">
            + Header
      </div>
</div>
      <div id="menuCPSub" class="mL">
            <a id="menuCPSub1" class="mV" href="#">
                  Sub Link 1
            </a>
            <a id="menuCPSub2" class="mV" href="#">
                  Sub Link 2
            </a>
            <a id="menuCPSub3" class="mV" href="#">
                  Sub Link 3
            </a>
      </div>
<!--End Header-->
0
 
LVL 11

Expert Comment

by:walkerke
ID: 17060203
As I understand it, this menu is on every page and according to the code above, the only collapsable menu items are ids menuCPSub1-3. Also as I understand it, when you navigate to a page using one of the collapsable menu items, you would like that menu item to remain uncollapsed.

Is the menu added to the other pages with an include or is it actually a part of that page? If it is a part of that page, I'd just change the class for that menu item on that page. For example, on the page that is referenced by menuCPSub1, I'd change the class attribute for menuCPSub1 to a visible class.

If the menu is in a remote file and included in the page, I'd add the following attribute to the body tag:

onload="javascript:document.getElementById("menuCPSub1").style.display=block;"

That would make just that menu item visible on that page until you click on the header menu.
0
 

Author Comment

by:cipiWeb
ID: 17060780
That was an example of the menu. Every menu on the website follows that format but may contain different contents. the menu is an ASP include. Say anyting in section A will have the menuA.asp include. Section B have menuB.asp include and so on. each and every item will have a unique ID, such as menuCP, menuAB, menuML, etc. its not the answer I was looking for, but i think you have set me in a new direction which might help. I'll get back to you once I have more.
0
 
LVL 13

Expert Comment

by:Mark_FreeSoftware
ID: 17069196

if you have a php enabled server,
you can make use of a session
0
 

Author Comment

by:cipiWeb
ID: 17072131
unfortunatley I am working with an ASP server side language.
0
 
LVL 6

Expert Comment

by:Dragonlaird
ID: 17081461
Session Cookies are accessible in ASP, PHP or JavaScript (plus many other languages) - I've already replied to this thread in the newly opened ASP question for the same problem...

http://www.experts-exchange.com/Web/Web_Languages/ASP/Q_21913753.html

For extra info on how to embellish the use of a Session Cookie to remember ALL menu items, feel free to continue the thread in this area as this can easily be achieved in JavaScript.

Dragon
0
 
LVL 6

Expert Comment

by:Dragonlaird
ID: 17081517
Hint: If you're wanting to keep open all the previously opened menus when the next page loads, consider appending the menu names to the existing session cookie value - use the Split function to separate the cookie contents back into separate menu ID's... It's really not a hard process (ASP has a Split function too that does the same thing) and at least this way, you'll get to learn a little about what you may need to maintain/repair in the future...
0
 

Author Comment

by:cipiWeb
ID: 17081823
Oh, wow... I wasn't expecting that. Give me some time to look over everything and then I'll post some feed back.
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:cipiWeb
ID: 17081881
Too keep everything  on the same string I am going to post your response to this thread.

Comment from Dragonlaird
Date: 07/11/2006 06:48AM PDT                  Comment

OK, I've downloaded/created the original JS, CSS and HTML page of the sample site you quoted in your other thread. From what I gather, you simply want to leave the last menu open on the next page...? If so, read on...

Using JavaScript, replace your clmenu.js file contents with the following...
===
function toggleMenu(objID) {
  if (!document.getElementById) return;
  var ob = document.getElementById(objID);
  if(ob) {
    if(ob.style.display == 'block') {
      ob.style.display = 'none';
    }
    else
    {
      ob.style.display = 'block';
      // Remember the last Menu Opened
      writeCookie("LastMenu", objID);
    };
  };
};
function logMenu(objItem) {
  // Trap which item was clicked and store the ID in a Session Cookie
 if(objItem.id) {
  writeCookie("LastMenu", objItem.id);
 }
 else
 {
  writeCookie("LastMenu", '');
 };
};
function openMenu() {
  // Find the saved Menu ID stored in our cookie and toggle it
  var strMenu = readCookie("LastMenu");
  if(!strMenu) return false; // No menu saved
  writeCookie("LastMenu", "");
  toggleMenu(strMenu);
};
function readCookie(nam) {
  var tC = document.cookie.split('; ');
  for (var i = tC.length - 1; i >= 0; i--) {
    var x = tC[i].split('=');
    if (nam == x[0]) return unescape(x[1]);
  }
  return null;
};
function writeCookie(nam,val) {
  document.cookie = nam + '=' + escape(val);
};
===
Now modify the body tag of each page containing the menu to this...
<body onload="openMenu();">

Thats it... No need for ASP, all done in JS - If the menu exists on the next page, it will open automatically. It's also worth noting that ONLY the last menu will be opened, all other menus will be closed.

Hope this helps...

Dragon
0
 
LVL 6

Expert Comment

by:Dragonlaird
ID: 17082010
No problem - Like I mentioned above, the code I supplied is only designed to open the LAST menu item selected but it can be easily modified to keep a history of all menus open at the time the page was left...
0
 

Author Comment

by:cipiWeb
ID: 17082172
First, Dragon, i want to thank you for a great response. Quickly looking through the code, it looks good, but I don't understand it completely. I apologize as it seems I left some things unclear so I will answer them now and post other issues I am confronted with to try and give a better understanding of my situation.

First, the menu itself.
 - Yes, I want any menu that is open to remain open on the next page. (all though, for reusability, I like the idea that you can set it to be just the last menu opened, could this be done with a variable and if statement?) I have a few concerns.
 - - What if the last menu opened is not the menu that contains the link that is clicked?
 - - Looking at the code it seems to me that it accounts for if the menu was opened. What happens if the menu is closed?

Ideal(?) Conditions
 - - I am trying to rely upon client side cookies as little as possible, not required, but if there is a way around it I would appreciate it.
 - - How concerned should I be about people who have Javascript disabled? I am trying to keep alot of my functions/procedures server side to avoid this scenario. If I could get the menu to work using serverside rather than client side I would, but the changes ( collapse and open ) occur after the server has dealt with the page and sent it to the browser.

So my only real concerns for conditions are, is javascript allowed, are cookies allowed? A lot of people may turn them off or have security software in place that blocks script from running.

Looking forward:
Once this question is resolved I plan on posting a new thread asking the following: How can I highlight the active page? If the current page is listed on the menu, I would like for it to be highlighted. Additionally I would like for it not to be clickable(your already on that page, no need for it to link to itself. This should include any query strings that may set variables for the page by forcing the GET request. Example:  www.domain.com/index.asp?variable=value

Once this question ( keeping the menu open) is done, I will post a link to the next thread upon accepting an answer.

My code differs slightly from the code used on that page. I will post it here for you.
0
 

Author Comment

by:cipiWeb
ID: 17082228
***File: sideMenuScripts.js***
***********************
function toggleMenu(objID){
      if(!document.getElementById){
            return;
      } else {
            var ob = document.getElementById(objID).style;
            ob.display = (ob.display == 'block')? 'none': 'block';
                  //Conditional Operator
                  //variablename=(condition)? valueifTrue:valueifFalse
      }
}
function setClass(){
/*      This function is set up so that you may change the class of more than one object at a time.
      Simply pass the information in object, class pairs.
      Example:
            onmouseup="setClass('id1','class1','id2','class2')"
*/
      var arg = setClass.arguments; //  Function.arguments for backwards compatability
      for(var i=0;i<arg.length;i+=2){
          var obj = arg[i];
          var name = arg[i+1];
            //alert("ID: " + obj + ";  Class: " + name + "."); //Test
            document.getElementById(obj).className = name;
      }
}

**File: sideMenuStyles.css***
***********************
/*Alphabetically Ordered*/
/* Index of Styles
.mC
.menuArrow
.mH
.mhBoxDefault
.mhBoxHover
.mHL
.mHLDown
.mHLHover
.mL
.mV
.mVDown
.mVHover
*/
.mC{
/*Menu Container - Wrapper that holds the entire menu.*/
      /*Display, Position, Dimensions, Margins & Padding*/
            float:left; /*Float Menu to the side of the container holding the menu.*/
            margin:0px; /*Sets the margin outside the menu.*/
            width:250px; /*Sets the width of the menu*/
      /*Formatting*/
            border-bottom:      2px solid #003366;/*Dark Border to create 3D effect*/
            border-left:      2px solid #3399CC;/*Light Border to create 3D effect*/
            border-right:      2px solid #003366;/*Dark Border to create 3D effect*/
            border-top:            2px solid #3399CC;/*Light Border to create 3D effect*/
            /*color: #FFFFFF;*/
            font-family: Arial, Verdana, san-serif, sans-serif;
            text-align: left;
}
.menuArrow{float:right;}
.mH {
/*Menu Heading - Cell that holds Top Level Links and Headers*/
      /*Formatting*/
            background-color: #006699;
            border-bottom:1px solid #FFFFFF;
            color: #FFFFFF;
}
.mhBoxDefault{
/*Box to the left of a link*/
      /*Display, Position, Dimensions, Margins & Padding*/
            display: block;
            float:left;
            position:relative;
            right:10px;
            width:10px;
            visibility: hidden;
      /*Formatting*/
            background-color: transparent;
            color: #FFFFFF;
}
.mhBoxHover{
/*Box to the left of a link*/
      /*Display, Position, Dimensions, Margins & Padding*/
            display: block;
            float:left;
            position:relative;
            right:10px;
            width:10px;
            visibility: visible;
      /*Formatting*/
            background-color:#FFFFFF;
            color: #00FF00;
}
.mHL{
/*Header Link*/
      /*Display, Position, Dimensions, Margins & Padding*/
            display: block;/*Anchor fills container*/
            padding-left: 1px;
      /*Formatting*/
            background-color: #006699;
            color:#DDDDDD;
            cursor:pointer; /*'pointer' lets users know this is clickable*/
            font-size: 12px;
            font-weight:bold;
            text-decoration: none;
}
.mHLDown{
      /*Display, Position, Dimensions, Margins & Padding*/
            display: block;
            padding-left: 1px;
      /*Formatting*/
      background-color: #333333;
      color:#999999;
      cursor:pointer; /*'pointer' lets users know this is clickable*/
      font-size: 12px;
      font-weight:bold;
      text-decoration: none;
}
.mHLHover{
      /*Display, Position, Dimensions, Margins & Padding*/
            display: block;
            padding-left: 1px;
      /*Formatting*/
            background-color: #000099;
            color:#CCCCCC;
            cursor:pointer; /*'pointer' lets users know this is clickable*/
            font-size: 12px;
            font-weight:bold;
            text-decoration: none;
}
.mL{
/*Menu List Hidden*/
      /*Display, Position, Dimensions, Margins & Padding*/
            display:none;/*hides the list when the page initially loads*/
            padding-bottom:10px;/*Ensures that the content underneath the expanded menu(heading) is not hard up against the last menu entry.*/
            background-color: #006699;
            color: #FFFFFF;
}
.mV{
/*Visable List*/
      /*Display, Position, Dimensions, Margins & Padding*/
            display:block;/*display collapsed content/ make visable*/
            padding-left:10px;/*Indent entry from the heading. Use padding or margin.*/
            padding-right: 5px;
      /*Formatting*/
            background-color: #006699;
            border-bottom:1px solid #006699;
            color: #FFFFFF;
            font-size: 12px;
            text-decoration: none;
}
.mVDown{
/*Visable List*/
      /*Display, Position, Dimensions, Margins & Padding*/
            display:block;/*display collapsed content/ make visable*/
            padding-left:10px;/*Indent entry from the heading. Use padding or margin.*/
      /*Formatting*/
            background-color: #333333;
            border-bottom:1px solid #000000;
            color: #999999;
            font-size: 12px;
            text-decoration: none;
}
.mVHover{
/*Visable List*/
      /*Display, Position, Dimensions, Margins & Padding*/
            display:block;/*display collapsed content/ make visable*/
            padding-left:10px;/*Indent entry from the heading. Use padding or margin.*/
            background-color: #003366;
      /*Formatting*/
            border-bottom:1px solid #841515;
            color: #CCCCCC;
            font-size: 12px;
            text-decoration: none;
}

***File: _incSideMenuProducts.asp***
*****************************
<!--Begin Products Menu-->
      <div class="mC">
            <!--Begin NEW Products-->
            <div id="menuNP_H" class="mH">
                  <a id="menuNP" class="mHL" href="#"
                  onmouseover="setClass('menuNP','mHLHover')"
                  onmousedown="setClass('menuNP','mHLDown')"
                  onmouseup  ="setClass('menuNP','mHLHover')"
                  onmouseout ="setClass('menuNP','mHL')">
                        &ensp; <%Response.Write strMNP%> <!--enspace used to account for the space of the plus(+) sign in collapsable Menus-->
                  </a>
            </div>
            <!--End NEW Products-->
            <!--Begin Closeout Specials-->
            <div id="menuCS_H" class="mH">
                  <a id="menuCS" class="mHL" href="#"
                  onmouseover="setClass('menuCS','mHLHover')"
                  onmousedown="setClass('menuCS','mHLDown')"
                  onmouseup  ="setClass('menuCS','mHLHover')"
                  onmouseout ="setClass('menuCS','mHL')">
                        &ensp; <%Response.Write strMCS%>
                  </a>
            </div>
            <!--End Closeout Specials-->
            <!--Begin Custom Products-->
            <div id="menuCP_H" class="mH">
                  <div id="menuCP" class="mHL" onclick="toggleMenu('menuCPSub')"
                  onmouseover="setClass('menuCP','mHLHover')"
                  onmousedown="setClass('menuCP','mHLDown')"
                  onmouseup  ="setClass('menuCP','mHLHover')"
                  onmouseout ="setClass('menuCP','mHL')">
                        + <%Response.Write strMCP%>
                  </div>
            </div>
                  <div id="menuCPSub" class="mL">
                        <a id="menuCPSub1" class="mV" href="#"
                        onmouseover="setClass('menuCPSub1','mVHover','menuCPSub1Box','mhBoxHover')"
                        onmousedown="setClass('menuCPSub1','mVDown')"
                        onmouseup  ="setClass('menuCPSub1','mVHover')"
                        onmouseout ="setClass('menuCPSub1','mV','menuCPSub1Box','mhBoxDefault')">
                              <span id="menuCPSub1Arr" class="menuArrow">&raquo;</span>
                              <span id="menuCPSub1Box" class="mhBoxDefault">&nbsp;</span><!--use span with display set to block for validation. Naturally block elements such as DIV are not allowed within an inline element, such as A, or SPAN according XHTML 1.0 Trans-->
                              <%Response.Write strMCPSUB1%>
                        </a>
                        <a id="menuCPSub2" class="mV" href="#"
                        onmouseover="setClass('menuCPSub2','mVHover','menuCPSub2Box','mhBoxHover')"
                        onmousedown="setClass('menuCPSub2','mVDown')"
                        onmouseup  ="setClass('menuCPSub2','mVHover')"
                        onmouseout ="setClass('menuCPSub2','mV','menuCPSub2Box','mhBoxDefault')">
                              <span id="menuCPSub2Arr" class="menuArrow">&raquo;</span>
                              <span id="menuCPSub2Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMCPSUB2%>
                        </a>
                        <a id="menuCPSub3" class="mV" href="#"
                        onmouseover="setClass('menuCPSub3','mVHover','menuCPSub3Box','mhBoxHover')"
                        onmousedown="setClass('menuCPSub3','mVDown')"
                        onmouseup  ="setClass('menuCPSub3','mVHover')"
                        onmouseout ="setClass('menuCPSub3','mV','menuCPSub3Box','mhBoxDefault')">
                              <span id="menuCPSub3Arr" class="menuArrow">&raquo;</span>
                              <span id="menuCPSub3Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMCPSUB3%>
                        </a>
                  </div>
            <!--End Custom Products-->
            <!--Begin Attachment Products-->
            <div id="menuAP_H" class="mH">
                  <div id="menuAP" class="mHL" onclick="toggleMenu('menuAPSub')"
                  onmouseover="setClass('menuAP','mHLHover')"
                  onmousedown="setClass('menuAP','mHLDown')"
                  onmouseup  ="setClass('menuAP','mHLHover')"
                  onmouseout ="setClass('menuAP','mHL')">
                        + <%Response.Write strMAP%>
                  </div>
            </div>
                  <div id="menuAPSub" class="mL">
                        <a id="menuAPSub1" class="mV" href="#"
                        onmouseover="setClass('menuAPSub1','mVHover','menuAPSub1Box','mhBoxHover')"
                        onmousedown="setClass('menuAPSub1','mVDown')"
                        onmouseup  ="setClass('menuAPSub1','mVHover')"
                        onmouseout ="setClass('menuAPSub1','mV','menuAPSub1Box','mhBoxDefault')">
                              <span id="menuAPSub1Arr" class="menuArrow">&raquo;</span>
                              <span id="menuAPSub1Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMAPSUB1%>
                        </a>
                        <a id="menuAPSub2" class="mV" href="#"
                        onmouseover="setClass('menuAPSub2','mVHover','menuAPSub2Box','mhBoxHover')"
                        onmousedown="setClass('menuAPSub2','mVDown')"
                        onmouseup  ="setClass('menuAPSub2','mVHover')"
                        onmouseout ="setClass('menuAPSub2','mV','menuAPSub2Box','mhBoxDefault')">
                              <span id="menuAPSub2Arr" class="menuArrow">&raquo;</span>
                              <span id="menuAPSub2Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMAPSUB2%>
                        </a>
                        <a id="menuAPSub3" class="mV" href="#"
                        onmouseover="setClass('menuAPSub3','mVHover','menuAPSub3Box','mhBoxHover')"
                        onmousedown="setClass('menuAPSub3','mVDown')"
                        onmouseup  ="setClass('menuAPSub3','mVHover')"
                        onmouseout ="setClass('menuAPSub3','mV','menuAPSub3Box','mhBoxDefault')">
                              <span id="menuAPSub3Arr" class="menuArrow">&raquo;</span>
                              <span id="menuAPSub3Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMAPSUB3%>
                        </a>
                        <a id="menuAPSub4" class="mV" href="#"
                        onmouseover="setClass('menuAPSub4','mVHover','menuAPSub4Box','mhBoxHover')"
                        onmousedown="setClass('menuAPSub4','mVDown')"
                        onmouseup  ="setClass('menuAPSub4','mVHover')"
                        onmouseout ="setClass('menuAPSub4','mV','menuAPSub4Box','mhBoxDefault')">
                              <span id="menuAPSub4Arr" class="menuArrow">&raquo;</span>
                              <span id="menuAPSub4Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMAPSUB4%>
                        </a>
                        <a id="menuAPSub5" class="mV" href="#"
                        onmouseover="setClass('menuAPSub5','mVHover','menuAPSub5Box','mhBoxHover')"
                        onmousedown="setClass('menuAPSub5','mVDown')"
                        onmouseup  ="setClass('menuAPSub5','mVHover')"
                        onmouseout ="setClass('menuAPSub5','mV','menuAPSub5Box','mhBoxDefault')">
                              <span id="menuAPSub5Arr" class="menuArrow">&raquo;</span>
                              <span id="menuAPSub5Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMAPSUB5%>
                        </a>
                        <a id="menuAPSub6" class="mV" href="#"
                        onmouseover="setClass('menuAPSub6','mVHover','menuAPSub6Box','mhBoxHover')"
                        onmousedown="setClass('menuAPSub6','mVDown')"
                        onmouseup  ="setClass('menuAPSub6','mVHover')"
                        onmouseout ="setClass('menuAPSub6','mV','menuAPSub6Box','mhBoxDefault')">
                              <span id="menuAPSub6Arr" class="menuArrow">&raquo;</span>
                              <span id="menuAPSub6Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMAPSUB6%>
                        </a>
                        <a id="menuAPSub7" class="mV" href="#"
                        onmouseover="setClass('menuAPSub7','mVHover','menuAPSub7Box','mhBoxHover')"
                        onmousedown="setClass('menuAPSub7','mVDown')"
                        onmouseup  ="setClass('menuAPSub7','mVHover')"
                        onmouseout ="setClass('menuAPSub7','mV','menuAPSub7Box','mhBoxDefault')">
                              <span id="menuAPSub7Arr" class="menuArrow">&raquo;</span>
                              <span id="menuAPSub7Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMAPSUB7%>
                        </a>
                        <a id="menuAPSub8" class="mV" href="#"
                        onmouseover="setClass('menuAPSub8','mVHover','menuAPSub8Box','mhBoxHover')"
                        onmousedown="setClass('menuAPSub8','mVDown')"
                        onmouseup  ="setClass('menuAPSub8','mVHover')"
                        onmouseout ="setClass('menuAPSub8','mV','menuAPSub8Box','mhBoxDefault')">
                              <span id="menuAPSub8Arr" class="menuArrow">&raquo;</span>
                              <span id="menuAPSub8Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMAPSUB8%>
                        </a>
                        <a id="menuAPSub9" class="mV" href="#"
                        onmouseover="setClass('menuAPSub9','mVHover','menuAPSub9Box','mhBoxHover')"
                        onmousedown="setClass('menuAPSub9','mVDown')"
                        onmouseup  ="setClass('menuAPSub9','mVHover')"
                        onmouseout ="setClass('menuAPSub9','mV','menuAPSub9Box','mhBoxDefault')">
                              <span id="menuAPSub9Arr" class="menuArrow">&raquo;</span>
                              <span id="menuAPSub9Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMAPSUB9%>
                        </a>
                  </div>
            <!--End Attachment Products-->
            <!--Begin Equipment & Supplies Products-->
            <div id="menuESP_H" class="mH">
                  <div id="menuESP" class="mHL" onclick="toggleMenu('menuESPSub')"
                  onmouseover="setClass('menuESP','mHLHover')"
                  onmousedown="setClass('menuESP','mHLDown')"
                  onmouseup  ="setClass('menuESP','mHLHover')"
                  onmouseout ="setClass('menuESP','mHL')">
                        + <%Response.Write strMESP%>
                  </div>
            </div>
                  <div id="menuESPSub" class="mL">
                        <a id="menuESPSub1" class="mV" href="#"
                        onmouseover="setClass('menuESPSub1','mVHover','menuESPSub1Box','mhBoxHover')"
                        onmousedown="setClass('menuESPSub1','mVDown')"
                        onmouseup  ="setClass('menuESPSub1','mVHover')"
                        onmouseout ="setClass('menuESPSub1','mV','menuESPSub1Box','mhBoxDefault')">
                              <span id="menuESPSub1Arr" class="menuArrow">&raquo;</span>
                              <span id="menuESPSub1Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMESPSUB1%>
                        </a>
                        <a id="menuESPSub2" class="mV" href="#"
                        onmouseover="setClass('menuESPSub2','mVHover','menuESPSub2Box','mhBoxHover')"
                        onmousedown="setClass('menuESPSub2','mVDown')"
                        onmouseup  ="setClass('menuESPSub2','mVHover')"
                        onmouseout ="setClass('menuESPSub2','mV','menuESPSub2Box','mhBoxDefault')">
                              <span id="menuESPSub2Arr" class="menuArrow">&raquo;</span>
                              <span id="menuESPSub2Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMESPSUB2%>
                        </a>
                        <a id="menuESPSub3" class="mV" href="#"
                        onmouseover="setClass('menuESPSub3','mVHover','menuESPSub3Box','mhBoxHover')"
                        onmousedown="setClass('menuESPSub3','mVDown')"
                        onmouseup  ="setClass('menuESPSub3','mVHover')"
                        onmouseout ="setClass('menuESPSub3','mV','menuESPSub3Box','mhBoxDefault')">
                              <span id="menuESPSub3Arr" class="menuArrow">&raquo;</span>
                              <span id="menuESPSub3Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMESPSUB3%>
                        </a>
                        <a id="menuESPSub4" class="mV" href="#"
                        onmouseover="setClass('menuESPSub4','mVHover','menuESPSub4Box','mhBoxHover')"
                        onmousedown="setClass('menuESPSub4','mVDown')"
                        onmouseup  ="setClass('menuESPSub4','mVHover')"
                        onmouseout ="setClass('menuESPSub4','mV','menuESPSub4Box','mhBoxDefault')">
                              <span id="menuESPSub4Arr" class="menuArrow">&raquo;</span>
                              <span id="menuESPSub4Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMESPSUB4%>
                        </a>
                        <a id="menuESPSub5" class="mV" href="#"
                        onmouseover="setClass('menuESPSub5','mVHover','menuESPSub5Box','mhBoxHover')"
                        onmousedown="setClass('menuESPSub5','mVDown')"
                        onmouseup  ="setClass('menuESPSub5','mVHover')"
                        onmouseout ="setClass('menuESPSub5','mV','menuESPSub5Box','mhBoxDefault')">
                              <span id="menuESPSub5Arr" class="menuArrow">&raquo;</span>
                              <span id="menuESPSub5Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMESPSUB5%>
                        </a>
                        <a id="menuESPSub6" class="mV" href="#"
                        onmouseover="setClass('menuESPSub6','mVHover','menuESPSub6Box','mhBoxHover')"
                        onmousedown="setClass('menuESPSub6','mVDown')"
                        onmouseup  ="setClass('menuESPSub6','mVHover')"
                        onmouseout ="setClass('menuESPSub6','mV','menuESPSub6Box','mhBoxDefault')">
                              <span id="menuESPSub6Arr" class="menuArrow">&raquo;</span>
                              <span id="menuESPSub6Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMESPSUB6%>
                        </a>
                        <a id="menuESPSub7" class="mV" href="#"
                        onmouseover="setClass('menuESPSub7','mVHover','menuESPSub7Box','mhBoxHover')"
                        onmousedown="setClass('menuESPSub7','mVDown')"
                        onmouseup  ="setClass('menuESPSub7','mVHover')"
                        onmouseout ="setClass('menuESPSub7','mV','menuESPSub7Box','mhBoxDefault')">
                              <span id="menuESPSub7Arr" class="menuArrow">&raquo;</span>
                              <span id="menuESPSub7Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMESPSUB7%>
                        </a>
                        <a id="menuESPSub8" class="mV" href="#"
                        onmouseover="setClass('menuESPSub8','mVHover','menuESPSub8Box','mhBoxHover')"
                        onmousedown="setClass('menuESPSub8','mVDown')"
                        onmouseup  ="setClass('menuESPSub8','mVHover')"
                        onmouseout ="setClass('menuESPSub8','mV','menuESPSub8Box','mhBoxDefault')">
                              <span id="menuESPSub8Arr" class="menuArrow">&raquo;</span>
                              <span id="menuESPSub8Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMESPSUB8%>
                        </a>
                  </div>
            <!--End Equipment & Supplies Products-->
            <!--Begin ID Software-->
            <div id="menuIDS_H" class="mH">
                  <div id="menuIDS" class="mHL" onclick="toggleMenu('menuIDSSub')"
                  onmouseover="setClass('menuIDS','mHLHover')"
                  onmousedown="setClass('menuIDS','mHLDown')"
                  onmouseup  ="setClass('menuIDS','mHLHover')"
                  onmouseout ="setClass('menuIDS','mHL')">
                        + <%Response.Write strMIDS%>
                  </div>
            </div>
                  <div id="menuIDSSub" class="mL">
                        <a id="menuIDSSub1" class="mV" href="#"
                        onmouseover="setClass('menuIDSSub1','mVHover','menuIDSSub1Box','mhBoxHover')"
                        onmousedown="setClass('menuIDSSub1','mVDown')"
                        onmouseup  ="setClass('menuIDSSub1','mVHover')"
                        onmouseout ="setClass('menuIDSSub1','mV','menuIDSSub1Box','mhBoxDefault')">
                              <span id="menuIDSSub1Arr" class="menuArrow">&raquo;</span>
                              <span id="menuIDSSub1Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMIDSSUB1%>
                        </a>
                        <a id="menuIDSSub2" class="mV" href="#"
                        onmouseover="setClass('menuIDSSub2','mVHover','menuIDSSub2Box','mhBoxHover')"
                        onmousedown="setClass('menuIDSSub2','mVDown')"
                        onmouseup  ="setClass('menuIDSSub2','mVHover')"
                        onmouseout ="setClass('menuIDSSub2','mV','menuIDSSub2Box','mhBoxDefault')">
                              <span id="menuIDSSub2Arr" class="menuArrow">&raquo;</span>
                              <span id="menuIDSSub2Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMIDSSUB2%>
                        </a>
                  </div>
            <!--End ID Software-->
            <!--Begin Visitor Management Systems-->
            <div id="menuVMS_H" class="mH">
                  <div id="menuVMS" class="mHL" onclick="toggleMenu('menuVMSSub')"
                  onmouseover="setClass('menuVMS','mHLHover')"
                  onmousedown="setClass('menuVMS','mHLDown')"
                  onmouseup  ="setClass('menuVMS','mHLHover')"
                  onmouseout ="setClass('menuVMS','mHL')">
                        + <%Response.Write strMVMS%>
                  </div>
            </div>
                  <div id="menuVMSSub" class="mL">
                        <a id="menuVMSSub1" class="mV" href="#"
                        onmouseover="setClass('menuVMSSub1','mVHover','menuVMSSub1Box','mhBoxHover')"
                        onmousedown="setClass('menuVMSSub1','mVDown')"
                        onmouseup  ="setClass('menuVMSSub1','mVHover')"
                        onmouseout ="setClass('menuVMSSub1','mV','menuVMSSub1Box','mhBoxDefault')">
                              <span id="menuVMSSub1Arr" class="menuArrow">&raquo;</span>
                              <span id="menuVMSSub1Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMVMSSUB1%>
                        </a>
                        <a id="menuVMSSub2" class="mV" href="#"
                        onmouseover="setClass('menuVMSSub2','mVHover','menuVMSSub2Box','mhBoxHover')"
                        onmousedown="setClass('menuVMSSub2','mVDown')"
                        onmouseup  ="setClass('menuVMSSub2','mVHover')"
                        onmouseout ="setClass('menuVMSSub2','mV','menuVMSSub2Box','mhBoxDefault')">
                              <span id="menuVMSSub2Arr" class="menuArrow">&raquo;</span>
                              <span id="menuVMSSub2Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMVMSSUB2%>
                        </a>
                        <a id="menuVMSSub3" class="mV" href="#"
                        onmouseover="setClass('menuVMSSub3','mVHover','menuVMSSub3Box','mhBoxHover')"
                        onmousedown="setClass('menuVMSSub3','mVDown')"
                        onmouseup  ="setClass('menuVMSSub3','mVHover')"
                        onmouseout ="setClass('menuVMSSub3','mV','menuVMSSub3Box','mhBoxDefault')">
                              <span id="menuVMSSub3Arr" class="menuArrow">&raquo;</span>
                              <span id="menuVMSSub3Box" class="mhBoxDefault">&nbsp;</span>
                              <%Response.Write strMVMSSUB3%>
                        </a>
                  </div>
            <!--End Visitor Management Systems-->
      </div>
<!--End Products Menu-->
0
 

Author Comment

by:cipiWeb
ID: 17083962
-.-o did I scare people away with a huge block of code?
0
 
LVL 6

Expert Comment

by:Dragonlaird
ID: 17089803
OK, first let me clarify a few answers for you from your questions above...

 - - Yes, I want any menu that is open to remain open on the next page. (all though, for reusability, I like the idea that you can set it to be just the last menu opened, could this be done with a variable and if statement?)

This is pretty much irrelevant now since we know you definately want to remember all the open menus, we could use a variable but we're writing this to suit your needs and hence, the variable would never be used again so why bother?

 - - What if the last menu opened is not the menu that contains the link that is clicked?

Very good point, and thus the reason you need to remember all the open menus, I hadn't thought of this...

 - - Looking at the code it seems to me that it accounts for if the menu was opened. What happens if the menu is closed?

Again, irrelevant now as we're writing to code to keep track of all open/closed menus

 - - I am trying to rely upon client side cookies as little as possible, not required, but if there is a way around it I would appreciate it.

The cookies used are Session Cookies, not first or third party cookies and thus, safe and generally switched on by default in most browsers...  If they don't allow these cookies, all that will happen is they won't have the menus opened automatically when the go to their next page (no real loss).

 - - How concerned should I be about people who have Javascript disabled? I am trying to keep alot of my functions/procedures server side to avoid this scenario.

Erm... If they have JavaScript disabled, they won't even be able to open the menu, never mind keep track of the open menus.

And now for the funky stuff... Thanks for posting the extra info above but to be truthful, having looked at it, the only file I'm interested in is sideMenuScripts.js. The CSS and ASP page only contain static content so they really aren't anything to worry about...

I'll answer your question before you ask it, yes, the script below will remember ALL the open menus for you...

Incidently, I've modified the code for the new version for you so that you don't even need to add the 'onload' property to the body of each page any more, it's done automatically for you...

OK - In the file above, remove the function 'toggleMenu' and replace it with the full text below (be afraid... hehe)...

===
function toggleMenu(objID) {
  if (!document.getElementById) return;
  var ob = document.getElementById(objID);
  if(ob) {
    if(ob.style.display == 'block') {
      // Close Menu, remove from Open Menu List
      ob.style.display = 'none';
      showStatus('Forget Menu: '+objID);
      saveMenu(objID, false);
    }
    else
    {
      ob.style.display = 'block';
      // Remember the last Menu Opened
      showStatus('Remember Menu: '+objID);
      saveMenu(objID, true);
    };
  };
  showStatus('Last Menu: '+readCookie("LastMenu"));
};

function logMenu(objItem) {
  // Trap which item was clicked and store the ID in a Session Cookie
 if(objItem.id) {
  saveMenu(objItem.id, true);
 }
 else
 {
  writeCookie("LastMenu", '');
 };
};

function saveMenu(strMenu, bAdd) {
  // If bAdd, add strMenu to cookie if it doesn't already exist
  // If NOT bAdd, remove strMenu from cookie if it exists
  var sMenus=readCookie("LastMenu")
  var arrMenus = new Array();
  if(sMenus) {
    arrMenus = sMenus.split(";");
  };
  for(var iCount = 0; iCount<arrMenus.length; iCount++) {
    if(arrMenus[iCount] == strMenu) {
      switch(bAdd) {
        case true:
          // Adding Menu but already exists so ignore
          return;
        default:
          // Removing menu from list
          arrMenus[iCount]='';
      };
    };
  };
  if(bAdd) {
    arrMenus[arrMenus.length] = strMenu;
  };
  // Reconstruct cookie
  strMenu = '';
  for(iCount = 0; iCount < arrMenus.length; iCount++) {
    if(arrMenus[iCount] != '') {
      strMenu += arrMenus[iCount] + ';';
    };
  };
  writeCookie("LastMenu", strMenu);
};

function openMenu() {
  // Find the saved Menu ID stored in our cookie and toggle it
  showStatus('Open Last Menu');
  var strMenu = readCookie("LastMenu")
  if(!strMenu) return;
  strMenu = strMenu.split(";");
  showStatus('Menu: '+strMenu.length);
  if(strMenu.length == 0) return false; // No menu saved
  showStatus('Wipe Menu Save');
  writeCookie("LastMenu", "");
  for(var iCount = 0; iCount < strMenu.length; iCount++) {
    showStatus('Open Menu: '+strMenu[iCount]);
    toggleMenu(strMenu[iCount]);
  };
};

function readCookie(nam) {
  var tC = document.cookie.split('; ');
  for (var i = tC.length - 1; i >= 0; i--) {
    var x = tC[i].split('=');
    if (nam == x[0]) return unescape(x[1]);
  }
  return null;
}

function writeCookie(nam,val) {
  document.cookie = nam + '=' + escape(val);
};

function showStatus(sText) {
  // Show sText on Status Bar as a Debug Aid
  window.status=sText;
  //document.title=sText
};
window.onload=openMenu;
===
0
 

Author Comment

by:cipiWeb
ID: 17090414
Wow, Thank you for the detailed response. I am still in the process of looking through your code. Something came to mind. How will this affect none menu items that have display styles set to block or none?

Just a few initial questions.

  if(bAdd) {
    arrMenus[arrMenus.length] = strMenu;
  };
  // Reconstruct cookie
  strMenu = '';

If we are setting strMenu equal to the value of the last object in the array why are we immediatley setting it to nothing? In general I am having trouble following what is instanciated where and how is it used. I know you've already put alot of work into this, but could you comment the code up some more?
0
 
LVL 6

Accepted Solution

by:
Dragonlaird earned 500 total points
ID: 17090966
The toggleMenu function is passed the ID of the item who's display needs to be changed. This is the only item who's display style will be changed and depending on what it is changed to (e.g. Block or None) determines if the menu is added or removed from the Open Menu list we have saved in our session cookie.

To comment the code a bit better, please read on... Same code, just comments added...

===
function toggleMenu(objID) {
  // Replaces our old function. Simply toggles the display style of an object on the page
  if (!document.getElementById) return;
  // Find out object, store it in ob
  var ob = document.getElementById(objID);
  if(ob) {
    // We found our object, check if it's currently visible or hidden
    if(ob.style.display == 'block') {
      // Close Menu, remove from Open Menu List
      ob.style.display = 'none';
      showStatus('Forget Menu: '+objID); // This isn't needed, it's a little debug code for testing
      saveMenu(objID, false);
    }
    else
    {
      // Menu us currently closed, open it and add it to our list of opened menus
      ob.style.display = 'block';
      // Remember the last Menu Opened
      showStatus('Remember Menu: '+objID); // Again, not required, debug code
      saveMenu(objID, true);
    };
  };
  showStatus('Last Menu: '+readCookie("LastMenu")); // Guess what? More debug code that's surplus to requirements
};

/*
function logMenu(objItem) {
      //  This function is no-longer needed as menu items are now added to the cookie in the saveMenu function below
};
*/

function saveMenu(strMenu, bAdd) {
  // strMenu is the ID of the menu we're adding/removing from our Open List
  // bAdd is either True or False to show we want to either add or remove the item from the list
  // If bAdd, add strMenu to cookie (if it doesn't already exist)
  // If NOT bAdd, remove strMenu from cookie (if it exists)
  var sMenus=readCookie("LastMenu")
  // arrMenus will contain all the menus to remain open
  var arrMenus = new Array();
  if(sMenus) {
    // Separate our menu list into the array using a semi-colon (;) as the delimeter
    arrMenus = sMenus.split(";");
  };
  // Check each item in our list and see if any matches our strMenu name
  for(var iCount = 0; iCount<arrMenus.length; iCount++) {
    if(arrMenus[iCount] == strMenu) {
      // Found a match in our array - Now are we meant to be adding or removing the menu?
      switch(bAdd) {
        case true:
          // Adding Menu but already exists so ignore (nothing to do - abort)
          return;
        default:
          // Removing menu from list, just set it to an empty string, we'll remote it in a minute
          arrMenus[iCount]='';
      };
    };
  };
  if(bAdd) {
    // OK, we're adding our menu to the list, this item doesn't already exist so we'll append it to the end of our array
    arrMenus[arrMenus.length] = strMenu;
  };
  // Reconstruct cookie, we've finished with the variable strMenu so we can re-use it to save time
  // strMenu will contain the delimeted string of all our open menus ready to be written back to the cookie
  strMenu = '';
  for(iCount = 0; iCount < arrMenus.length; iCount++) {
    if(arrMenus[iCount] != '') {
      // Found a menu item in our array, add it to our delimeted string with a semi-colon (;)
      strMenu += arrMenus[iCount] + ';';
    };
  };
  // strMenu now contains a full list of all our open menu names, write it to our cookie, overwriting the existing contents
  writeCookie("LastMenu", strMenu);
};

function openMenu() {
  // This function is first called when our page is loaded.
  // It checks to see if we have a cookie containing a list of open menu items
  // If there is, we go through each one and open it using the function toggleMenu above
  showStatus('Open Last Menu'); // Oh look, some more redundant debug code...
  var strMenu = readCookie("LastMenu");
  // We have our full list of menus in a delimeted string, or it will be null/empty if this is the first visit to the page or if cookies are turned off
  if(!strMenu) return;  // Nothing to open so we just exit the function...
  // At this point we must have at least 1 menu item to open... Convert the list into an array (re-use the same variable for ease)
  strMenu = strMenu.split(";");
  showStatus('Menu: '+strMenu.length); // Tum-te-tum... Debug code again ;-)
  if(strMenu.length == 0) return false; // Hmmm - Just a double check but if we have no elements in our array, there's nothing to open
  showStatus('Wipe Menu Save'); // Damn debugger, damn him all to hell I tell ya...
  writeCookie("LastMenu", ""); // OK, here we wipe the currently saved cookie list of open menus, we're gonna rebuild it soon anyway
  for(var iCount = 0; iCount < strMenu.length; iCount++) {
    showStatus('Open Menu: '+strMenu[iCount]); // Anyone got any debug spray???
    toggleMenu(strMenu[iCount]); // OK, lets open our menu - remember this also adds our menu to the cookie list again
  };
};

function readCookie(nam) {
  // Reading cookies? Surely we eat them?
  var tC = document.cookie.split('; ');
  for (var i = tC.length - 1; i >= 0; i--) {
    var x = tC[i].split('=');
    if (nam == x[0]) return unescape(x[1]);
  }
  return null;
}

function writeCookie(nam,val) {
  // These are less fattening cos they are session cookies
  document.cookie = nam + '=' + escape(val);
};

function showStatus(sText) {
  // Show sText on Status Bar as a Debug Aid
  // Feel free to comment out the line below or remove all calls to this routine and just delete the who function...
  window.status=sText;
  //document.title=sText
};
// Once all the functions are loaded into memory, we can tell the web page to run the first one when it has finished loading and redering the page...
window.onload=openMenu;
===

OK, not sure how much more I can comment in there but if you're still unsure, let me know and I'll re-write war and peace for ya...
0
 
LVL 6

Expert Comment

by:Dragonlaird
ID: 17090994
Please note, the function logMenu is superflous and can be safely deleted...

Also, if you want to streamline the code further, remove all the calls to the showStatus function and then delete that function too, it was only a bit of debug code to show me what was happening when I was writing the code for U...
0
 

Author Comment

by:cipiWeb
ID: 17091773
I was wondering what purpose logMenu served. It was puzzling the hell out of me. I am looking through it now (still reading) and noticed something.

in your statments such as if(blah blah balh){code};

 you have a semicolon after the bracket. I was wondering why.
0
 

Author Comment

by:cipiWeb
ID: 17092074
Remote = Remove?
     default:
               // Removing menu from list, just set it to an empty string, we'll remote it in a minute
               arrMenus[iCount]='';

I tried testing your code and it didn't work. am i doing something wrong?
0
 

Author Comment

by:cipiWeb
ID: 17092098
correction, it works. While eating one too many cookies, I failed to realize I needed to save the darn changes before uploading the document. What a newb error.
0
 

Author Comment

by:cipiWeb
ID: 17092505
Thank You Dragon. I wish I had more than 500 to give considering the problem started at 500 Pts and you significantly stepped it up going beyond the original question in explaining it to me.

Top Marks to you.

~CIPI Developer(Nick)
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Suggested Solutions

What is Node.js? Node.js is a server side scripting language much like PHP or ASP but is used to implement the complete package of HTTP webserver and application framework. The difference is that Node.js’s execution engine is asynchronous and event…
Browsers only know CSS so your awesome SASS code needs to be translated into normal CSS. Here I'll try to explain what you should aim for in order to take full advantage of SASS.
The viewer will the learn the benefit of plain text editors and code an HTML5 based template for use in further tutorials.
HTML5 has deprecated a few of the older ways of showing media as well as offering up a new way to create games and animations. Audio, video, and canvas are just a few of the adjustments made between XHTML and HTML5. As we learned in our last micr…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now