//** Smooth Navigational Menu- By Dynamic Drive DHTML code library: http://www.dynamicdrive.com //** Script Download/ instructions page: http://www.dynamicdrive.com/dynamicindex1/ddlevelsmenu/ //** Menu created: Nov 12, 2008 //** Dec 12th, 08" (v1.01): Fixed Shadow issue when multiple LIs within the same UL (level) contain sub menus: http://www.dynamicdrive.com/forums/showthread.php?t=39177&highlight=smooth //** Feb 11th, 09" (v1.02): The currently active main menu item (LI A) now gets a CSS class of ".selected", including sub menu items. //** May 1st, 09" (v1.3): //** 1) Now supports vertical (side bar) menu mode- set "orientation" to 'v' //** 2) In IE6, shadows are now always disabled //** July 27th, 09" (v1.31): Fixed bug so shadows can be disabled if desired. //** Feb 2nd, 10" (v1.4): Adds ability to specify delay before sub menus appear and disappear, respectively. See showhidedelay variable below //** Dec 17th, 10" (v1.5): Updated menu shadow to use CSS3 box shadows when the browser is FF3.5+, IE9+, Opera9.5+, or Safari3+/Chrome. Only .js file changed. //** Jun 28th, 2012: Unofficial update adds optional hover images for down and right arrows in the format: filename_over.ext //** These must be present for whichever or both of the arrow(s) are used and will preload. //** Dec 23rd, 2012 Unofficial update to fixed configurable z-index, add method option to init "toggle" which activates on click or "hover" //** which activates on mouse over/out - defaults to "toggle" (click activation), with detection of touch devices to activate on click for them. //** Add option for when there are two or more menus using "toggle" activation, whether or not all previously opened menus collapse //** on new menu activation, or just those within that specific menu //** See: http://www.dynamicdrive.com/forums/showthread.php?72449-PLEASE-HELP-with-Smooth-Navigational-Menu-(v1-51)&p=288466#post288466 //** Feb 7th, 2013 Unofficial update change fixed configurable z-index back to graduated for cases of main UL wrapping. Update off menu click detection in //** ipad/iphone to touchstart because document click wasn't registering. see: http://www.dynamicdrive.com/forums/showthread.php?72825 //** Feb 14th, 2013 Add window.ontouchstart to means tests for detecting touch browsers - thanks DD! //** Feb 15th, 2013 Add 'ontouchstart' in window and 'ontouchstart' in document.documentElement to means tests for detecting touch browsers - thanks DD! //** Feb 20th, 2013 correct for IE 9+ sometimes adding a pixel to the offsetHeight of the top level trigger for horizontal menus //** Feb 23rd, 2013 move CSS3 shadow adjustment for IE 9+ to the script, add resize event for all browsers to reposition open toggle //** menus and shadows in window if they would have gone to a different position at the new window dimensions //** Feb 25th, 2013 (v2.0) All unofficial updates by John merged into official and now called v2.0. Changed "method" option's default value to "hover" //** May 14th, 2013 (v2.1) Adds class 'repositioned' to menus moved due to being too close to the browser's right edge //** May 30th, 2013 (v2.1) Change from version sniffing to means testing for jQuery versions which require added code for click toggle event handling //** Sept 15th, 2013 add workaround for false positives for touch on Chrome //** Sept 22nd, 2013 (v2.2) Add vertical repositioning if sub menu will not fit in the viewable vertical area. May be turned off by setting // repositionv: false, //** in the init. Sub menus that are vertically repositioned will have the class 'repositionedv' added to them. //** March 17th, 15' (v3.0): Adds fully mobile friendly, compact version of menu that's activated in mobile and small screen browsers. //** Refines drop down menu behaviour when there's neither space to the right nor left to accommodate sub menu; in that case sub menu overlaps parent menu. //** Nov 3rd, 15' (v3.01): Fixed long drop down menus causing a vertical document scrollbar when page loads var ddsmoothmenu = { ///////////////////////// Global Configuration Options: ///////////////////////// mobilemediaquery: "screen and (max-width: 700px)", // CSS media query string that when matched activates mobile menu (while hiding default) //Specify full URL to down and right arrow images (23 is padding-right for top level LIs with drop downs, 6 is for vertical top level items with fly outs): arrowimages: {down:['downarrowclass', 'js/ddsmoothmenu/down.gif', 23], right:['rightarrowclass', 'js/ddsmoothmenu/right.gif', 6], left:['leftarrowclass', 'js/ddsmoothmenu/left.gif']}, transition: {overtime:300, outtime:300}, //duration of slide in/ out animation, in milliseconds mobiletransition: 200, // duration of slide animation in mobile menu, in milliseconds shadow: false, //enable shadow? (offsets now set in ddsmoothmenu.css stylesheet) showhidedelay: {showdelay: 100, hidedelay: 200}, //set delay in milliseconds before sub menus appear and disappear, respectively zindexvalue: 1000, //set z-index value for menus closeonnonmenuclick: true, //when clicking outside of any "toggle" method menu, should all "toggle" menus close? closeonmouseout: false, //when leaving a "toggle" menu, should all "toggle" menus close? Will not work on touchscreen /////////////////////// End Global Configuration Options //////////////////////// overarrowre: /(?=\.(gif|jpg|jpeg|png|bmp))/i, overarrowaddtofilename: '_over', detecttouch: !!('ontouchstart' in window) || !!('ontouchstart' in document.documentElement) || !!window.ontouchstart || (!!window.Touch && !!window.Touch.length) || !!window.onmsgesturechange || (window.DocumentTouch && window.document instanceof window.DocumentTouch), detectwebkit: navigator.userAgent.toLowerCase().indexOf("applewebkit") > -1, //detect WebKit browsers (Safari, Chrome etc) idevice: /ipad|iphone/i.test(navigator.userAgent), detectie6: (function(){var ie; return (ie = /MSIE (\d+)/.exec(navigator.userAgent)) && ie[1] < 7;})(), detectie9: (function(){var ie; return (ie = /MSIE (\d+)/.exec(navigator.userAgent)) && ie[1] > 8;})(), ie9shadow: function(){}, css3support: typeof document.documentElement.style.boxShadow === 'string' || (!document.all && document.querySelector), //detect browsers that support CSS3 box shadows (ie9+ or FF3.5+, Safari3+, Chrome etc) prevobjs: [], menus: null, mobilecontainer: {$main: null, $topulsdiv: null, $toggler: null, hidetimer: null}, mobilezindexvalue: 2000, // mobile menus starting zIndex executelink: function($, prevobjs, e){ var prevscount = prevobjs.length, link = e.target; while(--prevscount > -1){ if(prevobjs[prevscount] === this){ prevobjs.splice(prevscount, 1); if(link.href !== ddsmoothmenu.emptyhash && link.href && $(link).is('a') && !$(link).children('span.' + ddsmoothmenu.arrowimages.down[0] +', span.' + ddsmoothmenu.arrowimages.right[0]).length){ if(link.target && link.target !== '_self'){ window.open(link.href, link.target); } else { window.location.href = link.href; } e.stopPropagation(); } } } }, repositionv: function($subul, $link, newtop, winheight, doctop, method, menutop){ menutop = menutop || 0; var topinc = 0, doclimit = winheight + doctop; $subul.css({top: newtop, display: 'block'}); while($subul.offset().top < doctop) { $subul.css({top: ++newtop}); ++topinc; } if(!topinc && $link.offset().top + $link.outerHeight() < doclimit && $subul.data('height') + $subul.offset().top > doclimit){ $subul.css({top: doctop - $link.parents('ul').last().offset().top - $link.position().top}); } method === 'toggle' && $subul.css({display: 'none'}); if(newtop !== menutop){$subul.addClass('repositionedv');} return [topinc, newtop]; }, updateprev: function($, prevobjs, $curobj){ var prevscount = prevobjs.length, prevobj, $indexobj = $curobj.parents().add(this); while(--prevscount > -1){ if($indexobj.index((prevobj = prevobjs[prevscount])) < 0){ $(prevobj).trigger('click', [1]); prevobjs.splice(prevscount, 1); } } prevobjs.push(this); }, subulpreventemptyclose: function(e){ var link = e.target; if(link.href === ddsmoothmenu.emptyhash && $(link).parent('li').find('ul').length < 1){ e.preventDefault(); e.stopPropagation(); } }, getajaxmenu: function($, setting, nobuild){ //function to fetch external page containing the panel DIVs var $menucontainer=$('#'+setting.contentsource[0]); //reference empty div on page that will hold menu $menucontainer.html("Loading Menu..."); $.ajax({ url: setting.contentsource[1], //path to external menu file async: true, dataType: 'html', error: function(ajaxrequest){ setting.menustate = "error" $menucontainer.html('Error fetching content. Server Response: '+ajaxrequest.responseText); }, success: function(content){ setting.menustate = "fetched" $menucontainer.html(content).find('#' + setting.mainmenuid).css('display', 'block'); !!!nobuild && ddsmoothmenu.buildmenu($, setting); } }); }, getajaxmenuMobile: function($, setting){ //function to fetch external page containing the primary menu UL setting.mobilemenustate = 'fetching' $.ajax({ url: setting.contentsource[1], //path to external menu file async: true, dataType: 'html', error: function(ajaxrequest){ setting.mobilemenustate = 'error' alert("Error fetching Ajax content " + ajaxrequest.responseText) }, success: function(content){ var $ul = $(content).find('>ul') setting.mobilemenustate = 'fetched' ddsmoothmenu.buildmobilemenu($, setting, $ul); } }); }, closeall: function(e){ var smoothmenu = ddsmoothmenu, prevscount; if(!smoothmenu.globaltrackopen){return;} if(e.type === 'mouseleave' || ((e.type === 'click' || e.type === 'touchstart') && smoothmenu.menus.index(e.target) < 0)){ prevscount = smoothmenu.prevobjs.length; while(--prevscount > -1){ $(smoothmenu.prevobjs[prevscount]).trigger('click'); smoothmenu.prevobjs.splice(prevscount, 1); } } }, emptyhash: $('').get(0).href, togglemobile: function(action, duration){ if (!this.mobilecontainer.$main) return clearTimeout(this.mobilecontainer.hidetimer) var $mobilemenu = this.mobilecontainer.$main var duration = duration || this.mobiletransition if ($mobilemenu.css('visibility') == 'hidden' && (!action || action == 'open')){ $mobilemenu.css({left: '-100%', visibility: 'visible'}).animate({left: 0}, duration) this.mobilecontainer.$toggler.addClass('open') } else if ($mobilemenu.css('visibility') == 'visible' && (!action || action != 'open')){ $mobilemenu.animate({left: '-100%'}, duration, function(){this.style.visibility = 'hidden'}) this.mobilecontainer.$toggler.removeClass('open') } return false }, buildmobilemenu: function($, setting, $ul){ function flattenuls($mainul, cloneulBol, callback, finalcall){ var callback = callback || function(){} var finalcall = finalcall || function(){} var $headers = $mainul.find('ul').parent() var $mainulcopy = cloneulBol? $mainul.clone() : $mainul var $flattened = jQuery(document.createDocumentFragment()) var $headers = $mainulcopy.find('ul').parent() for (var i=$headers.length-1; i>=0; i--){ // loop through headers backwards, so we end up with topmost UL last var $header = $headers.eq(i) var $subul = $header.find('>ul').prependTo($flattened) callback(i, $header, $subul) } $mainulcopy.prependTo($flattened) // Add top most UL to collection finalcall($mainulcopy) return $flattened } var $mainmenu = $('#' + setting.mainmenuid) var $mainul = $ul var $topulref = null var flattened = flattenuls($mainul, false, function(i, $header, $subul){ // loop through header LIs and sub ULs $subul.addClass("submenu") var $breadcrumb = $('