//-----------------------------------------------------------
var sMMProg = "main_menu_ajax.js";
var sMMVers = "20120213";
//
// This contains code primarily related to the new container-based main
// menu and AJAX processing.
//
// 20120213 :dms:changed "logout.asp" to "endSession.asp"
// 20120113 :dms:Remove "JSON" from generic error message when no data returned from Ajax call
// 20120103 :dms:Handle JSON parse errors where cannot reach db
// 20111118 :dms:Fix bug when non-known type param sent to returnReport
// 20111116 :dms:Fix legacy memory leak in dhtmlLoadScript by preventing duplicate script loads; specifically set
//               'Loading' to say 'Working...' since it changes to 'Formatting...' when running through fhHeader code;
//               temporarily remove (comment out) call to restoreLastReport on login; rewrite returnReport function
//               as a generic solution to handle FAVORITE, TARGET, DRILL, etc REPORTS plus INPUTFORM; remove 
//               returnTarget function
// 20111031 :dms:Syntax error fixed - too many "}"
// 20111027 :dms:Add handling for MSG_REDIRECT in main menu init where error displayed and redirect to new url
// 20111024 :dms:Adjustments to "Loading" activation and delays to better mask login lapse
// 20110914 :dms:Parameter mod to shadowbox to allow select boxes to display in the background as applicable
// 20110909 :dms:modify returnReport to set drill details if report based on a saved favorite
// 20110720 :dms:reduce loading shadow display again - to 500ms
// 20110715 :dms:reduce loading shadow display to 1000ms
// 20110701 :dms:added displayLoadingMgr in an attempt to better manage screen shadowing
// 20110624 :dms:add minor error chking to rplogo easter egg; add new easter egg behind rslogo
// 20110624 :dms:modify loading shadow fade out in an effort to reduce possibility that it lingers/doesn't disappear
// 20110531 :dms:modify displayLoading in an effort to improve loading and shadow fade-in and fade-out consistency
// 20110510 :dms:change displayLoading to differentiate between ajax and non-ajax changes
// 20110505 :dms:modified ajax shadow config so it can be used outside of just ajax processing (in support of scroll table usage)
//               also increased the menu width to help prevent wrapping within the menu box
// 20110415 :dms:Conversion to superfish menu technology; includes three callback customization functions 
//              :hid menu if ajax error (incl login) and display it after setting up in initMenu
// 20110323 :dms:Externalized 'loading' code from dom:loaded so it can be called separately
// 20101229 :dms:Added function returnTarget in support of restoring saved target; moved line to clear container
//               when initializing menu to only happen when loading dashboard or previous report
// 20101118 :dms:Tweaks to improve the look and feel of the startup lightbox based on input
// 20101116 :dms:Added more elaborate post-login functionality with restoreLastReport method
//           dms:Tweaked the startup 'loading' a little by adding refresh=1 to main_menu.asp and retailer_menu.asp
// 20101115 :dms:Modified returnReport to clear existing error messages if they exist prior to displaying new report;
//               Modified handleError to clean report generated up to point of error, if exists
// 20100915 :dms:Removed call to check recovery table on index.html page load, prior to initializing menu, because it
//               was redundant and, on new session, forcing login?mode=expired login box to flash unnecessarily
// 20100909 :dms:Changed the Ajax.Responders component of dimming the screen and displaying the loading message by 
//               including activeRequestCount to prevent 'finishing' before its actually done
// 20100909 :dms:Changed the Ajax.Responders component of dimming the screen and displaying the loading message by 
//               including activeRequestCount to prevent 'finishing' before its actually done
// 20100909 :dms:Incorporated check for potential recovery in event.observe on load; also when loading menu, if 
//               report recovered, ask whether user wants to see recovered report or continue to default dashboard report
// 20100903 :dms:In assessJsonResponse, added logic for handling login without timeout message
// 20100819 :dms:Moved favorites code to its own file
// 20100813 :dms:refactored to disallow user from saving a favorite that already exists (as identified by unique
//               request id/params/username/advances combo; offers option to rename existing favorite instead;
//               refactored ajax calls to have common failure handling
// 20100812 :dms:refactored AJAX methods to accept JSON requests/responses; moved all favorites method's window close to 
//               submit button onclick event instead of form onsubmit event; added 'return false' to onclick event;
//               added more error handling to AJAX onsuccess callback
// 20100804b:dms:refactored handleFavorites to address possibility of not having params to send to calling routine
// 20100804a:dms:fixed bug to change the modal box title name for renaming favorite
// 20100803 :dms:minor favorites refactor + addition of rename and delete favorites functionality
// 20100802 :dms:removed rptPU global variable since it wasn't serving it's purpose anymore; see report_ajax.js for details
// 20100727 :dms:added displayNav option to shadowbox in handleFavorites method to remove "X" below box
// 20100707 :dms:changed window load function to call other function (init) so init could be called outside of
//               the window load event;  added evalscripts=true to ajax.updater calls; added call to default dashboard
// 20100706 :dms:added evalScripts to params for login.asp call
//-----------------------------------------------------------------------------------------

var loadDashboard = true;
var doNOTloadDashboard = false;
var shadowActivationCount = 0;
var shadowDisplayTimer = null;                             //used to manage many display change requests at a time
var dynamicallyLoadedFiles = $H();                         //list of files that have already been dynamically loaded

document.observe("dom:loaded", function() {

   // This is a special purpose function that registers global ajax onCreate and onComplete responders (listeners)
   // such that they fire whenever an AJAX call is made.  They are currently used to gray out the page and display
   // a 'loading' image while the AJAX process is running.  Fading and the loading image will NOT be done when 
   // an AJAX report refresh process is running.
   Ajax.Responders.register({
      onCreate: function(oXHR) {                           // when the AJAX process is created
         if ((String(oXHR.url)).indexOf("refresh") == -1 && Ajax.activeRequestCount > 0) {
            displayLoadingMgr(true, false, false);
         }
      },
      onComplete: function(oXHR) {                         // when the AJAX process is completed
         if (Ajax.activeRequestCount == 0) {
            displayLoadingMgr(false, false, ((String(oXHR.url)).indexOf("refresh") != -1));
         }
      }
   });

   // This is a special purpose function used for debugging purposes.  It displays the browser viewport dimensions
   // if CTRL-Click on the rp logo at the same time.
   $('rpLogo').observe('click', function(e){
      e.stop();
      if (!e.ctrlKey) {
         var d = document.viewport.getDimensions();
         alert("Browser viewport width: "+d.width+"; viewport height: "+d.height);
      } else {
         var w = prompt("Please enter your desired viewport width.","800");
         if (w != null) {
            var h = prompt("Please enter your desired viewport height.","600");
            if (h != null) {
               window.moveTo(0,0);
               window.resizeTo(screen.availWidth,screen.availHeight);
               var d = document.viewport.getDimensions();
               var diffW = screen.availWidth-d.width;
               var diffH = screen.availHeight-d.height;
               window.resizeTo(parseInt(w)+diffW,parseInt(h)+diffH);
            }
         }
      }
   });

   // This is a special purpose function used for debugging purposes.  It displays the tech details for the report
   // if Click on the rs logo.
   $('rsLogo').observe('click', function(e){
      e.stop();
      Effect.SlideUp('footer_container');
      setTimeout("$('footer_container').show();", 30000);
   });

});

//-----------------------------------------------------------

function displayLoadingMgr(bActivate, bNonAjaxActivation, bDelayDisplay) {
   // Purpose:   Single thread and manage multiple calls to displayLoading process
   // Arguments: bActivate - boolean dictating whether loading animation, etc is displayed or not
   //            bNonAjaxActivation - controls loading display independent of Ajax-controlled activation
   //            bDelayDisplay - used to determine whether to delay longer or shorter
   if (shadowDisplayTimer != null) {
      clearTimeout(shadowDisplayTimer);
      shadowDisplayTimer = null;
   }
   
   var delay = (bDelayDisplay ? 1000 : 500);
   if (bActivate) {
      delay = 300;
   }
   shadowDisplayTimer = setTimeout('displayLoading('+bActivate+', '+bNonAjaxActivation+')', delay);
   
}//displayLoadingMgr

//-----------------------------------------------------------

function displayLoading(bActivate, bNonAjaxActivation) {
   // Purpose:   Grays out page transparently and displays a loading animation if true argument; turns it off otherwise
   // Arguments: bActivate - boolean dictating whether loading animation, etc is displayed or not
   //            bNonAjaxActivation - controls loading display independent of Ajax-controlled activation

   if (bActivate) {                                        //display loading animation, etc
      $('shadow', 'loading').invoke('setOpacity','0').invoke('show');
      new Effect.Opacity('shadow', { from: 0, to: 0.3, duration: 0.3 });
      $('loading').update('Working...');
      new Effect.Opacity('loading', { from: 0, to: 1, duration: 0.5 });
      if (bNonAjaxActivation) { shadowActivationCount++; }
   } else {                                                //stop displaying loading animation, etc
      if (bNonAjaxActivation) { shadowActivationCount--; }
      if (shadowActivationCount <= 0 && Ajax.activeRequestCount == 0) {
//         new Effect.Opacity('shadow', { from: 0.3, to: 0, duration: 0.2 });
//         new Effect.Opacity('loading', { from: 1, to: 0, duration: 0.4 });
//         setTimeout("$('shadow','loading').invoke('setOpacity','0').invoke('hide')",1000); 
         $('shadow','loading').invoke('hide');
         shadowActivationCount = 0;
      }
   }
}

//-----------------------------------------------------------

function dhtmlLoadScript(url) {

   // Purpose:   Since introducing the notion of a container within which all activity takes place for this system,
   //            loading javascript traditionally via inclusion in the head tags is no longer possible.  This function
   //            provides the ability to load javascript dynamically, as needed, during the generation of page contents
   //            within the asp program.
   //
   // Arguments: URL to the javascript script file.  It can be absolute or relative.
   //
   // Returns:   neither true or false
   var head;
   var script;

   if (dynamicallyLoadedFiles.get(url) == undefined) {
      head = $$('head')[0];
      if (head) {
         script = new Element('script', { type: 'text/javascript', src: url });
         head.appendChild(script);
      }
      dynamicallyLoadedFiles.set(url, true);
   }
}

//-----------------------------------------------------------

Event.observe(window, 'load', function() {

   // Purpose:   On window load, initializes system
   //
   // Arguments: none
   //
   // Returns:   neither true or false
   initMenu (loadDashboard);
});


function initMenu(bLoadDashboard) {
   // Purpose:   This function executes main_menu.asp to get the data necessary for the 
   //            main menu to display appropriately.  If, while processing, main_menu.asp determines that the
   //            user is not logged in or the retailer is not set, it will respond accordingly and this function
   //            will forward to another asp appropriately.
   //
   //            Otherwise, after main_menu.asp collects the necessary menu information, it will update the 
   //            navigation container and run the menu formatting javascript.
   //
   //            Failure and exceptions are handled via javascript alerts for lack of anything better right now, 
   //            though this might be revisited.
   //
   // Arguments: bLoadDashboard:  true or false as to whether or not to load dashboard
   //
   // Returns:   neither true or false
   var task = "initMainMenu";

   new Ajax.Request('main_menu.asp?refresh=1', {
      method: 'post',
      evalJSON: 'force',
      requestHeaders: {Accept: 'application/json'},
      onSuccess: function(transport) { 
         var json = transport.responseJSON;
         if (assessJsonResponse(json, task) == "success") {
            if (json.result.toUpperCase() == 'MSG-REDIRECT') {
               var msg = json.msg.toQueryParams();
               handleErr(msg.code, msg.loc, msg.prog, msg.ver, msg.msg, json.dest);               
            } else {
               $('navbar_content').update(json.result); 
               $('navbar_content').show();
               jQuery(function(){
                  jQuery('ul.sf-menu')
                     .supersubs({
                        minWidth: 10, 
                        maxWidth: 50, 
                        extraWidth: 1
                     })
                     .superfish({
                        animation: {opacity:'show', height:'show'},
                        dropShadows: false,
                        speed: 'fast',
                        onInit:        function(){ setClickEvent(this); adjustUlMenus(this); },
                        onBeforeShow:  function(){ checkMenuOffset(this); }
                     }); 
               });

               //check to see if there is a recovery restore point saved; if so, ask to see if user wants to restore or default
               if (bLoadDashboard) {
                  $('body_content').update(''); 
//                  if (recoverSession) {                       //set in report_ajax.js
//                     restoreLastReport();
//                  } else {
                     new Ajax.Updater({success: 'body_content', failure: 'error' }, 'dashboard.asp?DEFAULT=1', {evalScripts: "true"});
//                  }
               }
            }
         }
      },
      onFailure: function(transport) { 
         handleErr('C100', 'ZB100', sMMProg+".initMenu", sMMVers, "Failure: " + transport.status);
      },
      onException: function(request, err) { 
         //Msg returned is SUPPOSED to be a JSON reponse.  However, if returned from global.asa, it cannot be
         //JSON since global.asa doesn't allow a JSON response content type.  Parsing the non-JSON response will 
         //result in an exception and will be handled here.  As such, we need to check to see if this is a valid
         //response from global.asa first and, if so, handle accordingly.
         var resp = request.transport.response;
         if (resp.length > 0 && resp.indexOf("global.asa") != -1) {
            var parsedResp = resp.toQueryParams();
            handleErr(parsedResp.code, parsedResp.loc, parsedResp.prog, parsedResp.ver, parsedResp.msg, parsedResp.msgredirect);               
         } else {
            handleErr('C100', 'ZB101', sMMProg+".initMenu", sMMVers, "Exception: " + err.message);
         }
      }
   });
}

//-----------------------------------------------------------

function returnReport(rptType, rptName) {

   // Purpose:   Using AJAX, provide a standard means to run a report or inputform.  This was created to be 
   //            called from the programmatically-generated code behind the main menu.
   //
   // Arguments: 
   //            rptType: type of item to manage; valid values are FAVORITE, TARGET, REPORT, INPUTFORM
   //            rptName: name of the asp to run plus associated base parameters (ex: report.asp?id=######)
   //
   // Returns:   false
   
   var sUrl = "";
   var sTask = "";
   var bSkipSetup = false;
   var params = rptName.parseQuery();
   $('error').update('');

   switch(rptType) {                                       //manage types separately
      case "FAVORITE":
         sTask = "getFavoriteDrillDetails";
         sUrl = "favorites.asp?task=" + sTask + "&dsplyrqstid="+params.dsplyrqstid+'&favid='+params.favid
         break;
      case "TARGET":
         sTask = "getTargetDrillDetails";
         sUrl = "targets.asp?task=" + sTask + "&trgtrqstid="+params.trgtrqstid+"&trgtid="+params.trgtid
         break;
      case "DRILLREPORT":
         sTask = "getReportDrillDetails";
         sUrl = "recovery.asp?task=" + sTask + "&dsplyrqstid="+params.dsplyrqstid+"&logid="+params.logid
         break;
      case "REPORT":
         new Ajax.Updater({ success: "body_content", failure: "error" }, rptName, {evalScripts: "true"});
         bSkipSetup = true;
         break;         
      case "INPUTFORM":
         new Ajax.Updater({ success: "body_content", failure: "error" }, rptName, {evalScripts: "true"});
         bSkipSetup = true;
         break;
      default:
         new Ajax.Updater({ success: "body_content", failure: "error" }, rptName, {evalScripts: "true"});
         bSkipSetup = true;
   }
      
   if (!bSkipSetup) {                                      //if pre-report setup required, do it
      new Ajax.Request(sUrl, {                             //run pre-report setup (ie drill details)
         method: 'post',
         evalJSON: 'force',
         requestHeaders: {Accept: 'application/json'},
         onSuccess: function(transport) { 
            var json = transport.responseJSON;
            if (assessJsonResponse(json, sTask) == "success") { //if pre-report setup successful, run report
//               if (rptType == "TARGET") {
//                  rptName = rptName.replace("trgtid","trgtrqstid"); //address discrepancy between modules re target id key
//               }
               new Ajax.Updater({ success: "body_content", failure: "error" }, rptName, {evalScripts: "true"});
            }
         },
         onFailure: function(transport) { 
            handleErr('C100', 'ZB107', sMMProg+".returnReport", sMMVers, "Failure: " + transport.status);
         },
         onException: function(request, err) { 
            handleErr('C100', 'ZB108', sMMProg+".returnReport", sMMVers, "Exception: " + err.message);
         }
      });
   }
   
   return false;
}

//-----------------------------------------------------------

function handleError (msg) {

   // Purpose:   Using AJAX, provide a standard means to report an error within the page container.  
   //
   // Arguments: Message to be displayed.  Additional parameters may be added to the end of the message without harm.
   //            (ex. 'This is an error.&err=login')
   //
   // Returns:   false

   $('body_content').update('');

   var url = "err_msg.asp?msg=" + msg
   new Ajax.Updater({success: 'error', failure: 'error' }, url);
   return false;
}

//-----------------------------------------------------------

function restoreLastReport () {

   // Purpose:   Display a lightbox asking if user wants to restore previous report and respond accordingly
   //
   // Arguments: 
   //
   // Returns:   false

   var task = "getRecoveryReportName";

   //first, query db to get name of restorable report
   new Ajax.Request('recovery.asp?task=' + task + '&refresh=1', {
      method: 'post',
      evalJSON: 'force',
      requestHeaders: {Accept: 'application/json'},
      onSuccess: function(transport) { 
         var json = transport.responseJSON;
         if (assessJsonResponse(json, task) == "success") { 
            //show lightbox containing choices of what to do next
            var blank = "<img src='Images/space.gif' width='50' />";
            var node = "";
            node = node + " <form id='restoreForm' name='restoreForm' method='POST'>";
            node = node + "  <table style='font-size:10pt;'>";
            node = node + "   <tr style='height:40px;'>";
            node = node + "    <td style='width:25%;'></td>";
            node = node + "    <td style='width:auto;'>";
            node = node + "     <input type='radio' name='restoreChoice' id='restoreHome' value='home' checked />";
            node = node + "     <label for='restoreHome'>  My Home Page</label>";
            node = node + "    </td>";
            node = node + "    <td style='width:5%;'></td>";
            node = node + "   </tr>";
            node = node + "   <tr>";
            node = node + "    <td style='width:25%;'></td>";
            node = node + "    <td style='width:auto;'>";
            node = node + "     <input type='radio' name='restoreChoice' id='restoreLast' value='last' />";
            node = node + "     <label for='restoreLast'>  Last Report Viewed</label><br/>";
            node = node + "     <span style='float:right;font-size:8pt;'>(" + json.result + ")</span>";
            node = node + "    </td>";
            node = node + "    <td style='width:5%;'></td>";
            node = node + "   </tr>";
            node = node + "   <tr>";
            node = node + "    <td style='width:25%;'></td>";
            node = node + "    <td style='width:auto;'>";
            node = node + "     <input type='radio' name='restoreChoice' id='restoreExit' value='exit' />";
            node = node + "     <label for='restoreExit'>  Logout</label>"
            node = node + "    </td>";
            node = node + "    <td style='width:5%;'></td>";
            node = node + "   </tr>";
            node = node + "  </table>";
            node = node + "  <table style='font-size:10pt;'>";
            node = node + "   <tr style='height:50px;'>";
            node = node + "    <td style='width:100%;padding-left:85px;padding-right:85px;'>";
            node = node + "     <input type='submit' value='OK' id='restoreContinue' onClick='handleRestore(this.form); window.parent.Shadowbox.close(); return false;' />";
            node = node + "     <input type='button' value='Cancel' id='restoreCancel' onClick='window.parent.Shadowbox.close()' />";
            node = node + "    </td>";
            node = node + "   </tr>";
            node = node + "  </table>";
            node = node + " </form>";

            //display modal box
            Shadowbox.open({
               content: node.valueOf(),
               title: 'Starting Point',
               player: 'html',
               height: 175,
               width: 300,
               options: {
                  enableKeys:false,
                  displayNav:false,
                  troubleElements:["object", "embed", "canvas"],
                  onFinish: function(element) { },
                  onOpen: function(element) { },
                  onClose: function(element){ }
               }
            });
         }
      },
      onFailure: function(transport) { 
         handleErr('C100', 'ZB102', sMMProg+".restoreLastReport", sMMVers, "Failure: " + transport.status);
      },
      onException: function(request, err) { 
         handleErr('C100', 'ZB103', sMMProg+".restoreLastReport", sMMVers, "Exception: " + err.message);
      }
   });

   return false;
}

//-----------------------------------------------------------

function handleRestore (frm) {

   // Purpose:   Based on form radio box selection, respond accordingly
   //
   // Arguments: 
   //
   // Returns:   false

   var radio = $('restoreForm').elements['restoreChoice'];
   var task;
   for(var i = 0; i < radio.length; i++) {
      if(radio[i].checked) {
         task = radio[i].value;
      }
   }

   switch(task) {
      case "home":
         new Ajax.Updater({success: 'body_content', failure: 'error' }, 'dashboard.asp?DEFAULT=1', {evalScripts: "true"});
         break;
      case "last":
         retrieveFromRecovery();
         break;
      case "exit":
         new Ajax.Updater({success: 'body_content', failure: 'error' }, 'endSession.asp', {evalScripts: 'true'});
         new Ajax.Updater({success: 'body_content', failure: 'error' }, 'login.asp', {evalScripts: 'true'});
         break;
   }

   return false;
}

//-----------------------------------------------------------

function assessJsonResponse(j, task) {

   // Purpose:   Utility function to externalize failure scenarios from all the AJAX calls since it all 
   //            is processed in the same fashion.  If AJAX call is successful, corresponding message
   //            is returned to calling routine so it can be handled locally
   //
   // Arguments: j    - AJAX JSON response object
   //            task - task of what was being attempted
   //
   // Returns:   "success" or "failure handled"
   if (j == null) {                                        //error causing no json-formatted response at all
      handleErr('C100', 'ZB104', sMMProg+", assessing response from: "+task, sMMVers, "An unexpected null result occurred.");
   } else if (j.status == 'failure') {                     //managed error from called process
      $('navbar_content').hide();
      var errObj = j.result.parseQuery();
      if (errObj.msg == 'missing username') {                //timeout occurred - need to log in again
         new Ajax.Updater({success: 'body_content', failure: 'error' }, 'login.asp?mode=timeout', {evalScripts: 'true'});
      } else if (errObj.msg == 'missing login') {            //haven't logged in yet - only seen in main_menu.asp
         new Ajax.Updater({success: 'body_content', failure: 'error' }, 'login.asp', {evalScripts: "true"});
      } else if (errObj.msg == 'missing retailer') {
         new Ajax.Updater({success: 'body_content', failure: 'error' }, 'retailer_menu.asp?refresh=1', {evalScripts: "true"});
      } else {                                             //catch-all error handler for managed failures
         handleErr(errObj.code, errObj.loc, errObj.prog, errObj.ver, j.status+": " + errObj.msg);
      }
   } else if (j.status == 'success') {                     //if success returned, all good, managed in calling routine
      return "success";
   } else { 
      handleErr('C100', 'ZB106', sMMProg+", assessing response from: "+task, sMMVers, "Unhandled status: "+j.status+": " + j.result);
   }
   return "failure handled"
}

//-----------------------------------------------------------

function adjustUlMenus(topLevelUl) {
   // Purpose:   For aesthetic purposes only, increase the individual UL menu sizes by 10px in order to 
   //            have a 5px radius rounded corners.  Subsequently, keep the internal LI nodes at original size
   // Arguments: topLevelUl - the top level UL node
   var Uls = jQuery(topLevelUl).find('ul');
   var ulMenu;
   Uls.each(function(ul) {
      ulMenu = jQuery(Uls[ul]);
      ulMenu.css('width',(ulMenu.width()+10)+'px');

      var $LIs = ulMenu.children();
      $LIs.css({'width' : (ulMenu.width()-10)+'px'});
   });
}

function checkMenuOffset(ulMenu) {
   // Purpose:   Check the location of a menu about to be displayed and determine if it should
   //            be displayed to the left or right.
   // Arguments: ulMenu - the menu to be displayed

   var pUl = ulMenu.parent().parent();                     //get parent UL element
   if (pUl.get(0) === jQuery("#main_menu").get(0)) { //work with 1st level drop down boxes
      ulMenu.css('left','-5px');
   } else {
      if ((pUl.offset() != undefined) && (pUl.offset().left+pUl.width()+ulMenu.width())>(jQuery(window).width())) {  //too big, open to the left
         ulMenu.css('left',(0-(ulMenu.width()+5))+'px');       //shift to the left
      } else {
         ulMenu.css('left', (pUl.width()-5)+'px');
      }      
   }                  
}

function setClickEvent(ulMenu) {
   // Purpose:   Assign a click event to leaf nodes for the purpose of closing the menu upon clicking a leaf node
   // Arguments: ulMenu - the menu to be displayed
   var As = jQuery(ulMenu).find("a.leafClassIsLeaf");
   As.each(function(a) {
      jQuery(As[a]).click(function() {
         jQuery('#main_menu li.sfHover').hideSuperfishUl();
      });
   });
}
