//** Drill Down Menu v1.0- (c) Dynamic Drive DHTML code library: http://www.dynamicdrive.com
//** Script Download/ instructions page: http://www.dynamicdrive.com/dynamicindex1/drilldownmenu.htm
//** June 8th, 2009: Script Creation date
//** June 10th, 2009: v1.01: Minor update

//Version 1.5: June 21st, 09':
//**1) Ability to include menu from external file and added to page via Ajax
//**2) Adds support for arbitrary links to act as "back buttons" for a drill menu. Just give the link a rel="drillback-menuid" attribute
//**3) Adds drillmenuinstance.back() method, which can be called on demand to go back one level within drill menu
//**4) Fixes bug with background ULs being visible following foreground UL contents
//**5) Updated css so browsers with JS disabled will get a scrolling, fixed height UL

//Version 1.6: August 9th, 09': Adds ability to specify explicit height for main menu, instead of defaulting to top UL's natural height.


function drilldownmenu(setting){
	this.sublevelarrow={src:'images/drilldown/right.gif', width:'14px', top:'2px', left:'3px', heigt:'14px'} //full URL to image used to indicate there's a sub level
	this.breadcrumbarrow='images/drilldown/right.gif' //full URL to image separating breadcrumb links (if it's defined)
	this.loadingimage='images/drilldown/loader.gif' //full URL to 'loading' image, if menu is loaded via Ajax
	this.homecrumbtext='Home Dir' //Top level crumb text
	this.titlelength=35 //length of parent LI text to extract from to use as crumb titles
	this.backarrow='images/drilldown/leftarrow.gif' //full URL to image added in front of back LI 

	////////// No need to edit beyond here /////////////
	this.menuid=setting.menuid
	this.jQuerymenudiv=null
	this.mainul=null
	this.jQueryuls=null
	this.navdivs={}
	this.menuheight=setting.menuheight || 'auto'
	this.selectedul=setting.selectedul || null
	this.speed=setting.speed || 70
	this.persist=setting.persist || {enable: false, overrideselectedurl: false}
	this.jQueryarrowimgs=null
	this.currentul=0
	this.filesetting=setting.filesetting || {url: null, targetElement: null}
	this.zIndexvalue=100
	this.arrowposx=0 //default arrow x position relative to parent LI
	var thisdrill=this
	jQuery.noConflict()
	jQuery(document).ready(function(jQuery){
		if (thisdrill.filesetting.url && thisdrill.filesetting.url.length>0){ //menu defined inside external file (use Ajax)?
			var jQuerydest=(typeof thisdrill.filesetting.targetElement=="string")? jQuery('#'+thisdrill.filesetting.targetElement) : null
			if (!jQuerydest || jQuerydest.length!=1){ //if target element isn't defined or multiple targets found
				alert("Error: The target element \"" + thisdrill.filesetting.targetElement + "\" to add the menu into doesn't exist or is incorrectly specified.")
				return
			}
			jQuerydest.html('<img src="'+thisdrill.loadingimage+'" style="vertical-align:middle" /> <b>Loading Drill Down Menu...</b>')
			jQuery.ajax({
				url: thisdrill.filesetting.url,
				error:function(ajaxrequest){
					alert('Error fetching Ajax content.\nServer Response: '+ajaxrequest.responseText)
				}, //end error
				success:function(content){
					jQuerydest.html(content)
					thisdrill.init(jQuery, setting)
				} //end success
			}) //end ajax
		}
		else{ //if inline menu
			thisdrill.init(jQuery, setting)
		}
	}) //end document.ready
}

drilldownmenu.prototype.init=function(jQuery, setting){
		var thisdrill=this
		var jQuerymaindiv=jQuery('#'+setting.menuid).css({position:'relative'}) //relative position main DIV
		var jQueryuls=jQuerymaindiv.find('ul')
		jQueryuls.css({position:'absolute', left:0, top:0, visibility:'hidden'}) //absolutely position ULs
		this.jQuerymaindiv=jQuerymaindiv
		this.jQueryuls=jQueryuls
		this.navdivs.jQuerycrumb=jQuery('#'+setting.breadcrumbid)
		this.navdivs.jQuerybackbuttons=jQuery('a[rel^="drillback-'+setting.menuid+'"]').css({outline:'none'}).click(function(e){
			thisdrill.back()
			e.preventDefault()
		})
		this.buildmenu(jQuery)
		jQuery(window).bind('unload', function(){
			thisdrill.uninit()
		})
		setting=null	
}

drilldownmenu.prototype.buildmenu=function(jQuery){
	var thisdrill=this
	this.jQueryuls.each(function(i){ //loop through each UL
		var jQuerythisul=jQuery(this)
		if (i==0){ //if topmost UL
			jQuery('<li class="backcontroltitle">I want to search by:</li>').prependTo(jQuerythisul).click(function(e){e.preventDefault()})
			thisdrill.jQuerymaindiv.css({height:(thisdrill.menuheight=='auto')? jQuerythisul.outerHeight() : parseInt(thisdrill.menuheight), overflow:'hidden'}) //set main menu DIV's height to top level UL's height
				.data('h', parseInt(thisdrill.jQuerymaindiv.css('height')))
			
		}
		else{ //if this isn't the topmost UL
			var jQueryparentul=jQuerythisul.parents('ul:eq(0)')
			var jQueryparentli=jQuerythisul.parents('li:eq(0)')
			jQuery('<li class="backcontrol"><img src="'+thisdrill.backarrow+'" style="border-width:0" /> Back one level</li>') //add back LI item
				.click(function(e){thisdrill.back(); e.preventDefault()})
				.prependTo(jQuerythisul)
			var jQueryanchorlink=jQueryparentli.children('a:eq(0)').css({outline:'none'}).data('control', {order:i}) //remove outline from anchor links
			var jQueryarrowimg=jQuery('<img class="arrowclass" />').attr('src', thisdrill.sublevelarrow.src).css({position:'absolute', borderWidth:0, paddingTop:thisdrill.sublevelarrow.top, left:jQueryparentli.width()-parseInt(thisdrill.sublevelarrow.width)-parseInt(thisdrill.sublevelarrow.left)}).prependTo(jQueryanchorlink)
			jQueryanchorlink.click(function(e){ //assign click behavior to anchor link
				thisdrill.slidemenu(jQuery(this).data('control').order)
				e.preventDefault()
			})
		}
		var ulheight=(jQuerythisul.outerHeight() < thisdrill.jQuerymaindiv.data('h'))? thisdrill.jQuerymaindiv.data('h') : 'auto'
		jQuerythisul.css({visibility:'visible', width:'100%', height:ulheight, left:(i==0)? 'auto' : jQueryparentli.outerWidth(), top:0})
		jQuerythisul.data('specs', {w:jQuerythisul.outerWidth(), h:jQuerythisul.outerHeight(), order:i, parentorder:(i==0)? -1 : jQueryanchorlink.parents('ul:eq(0)').data('specs').order, x:(i==0)? jQuerythisul.position().left : jQueryparentul.data('specs').x+jQueryparentul.data('specs').w, title:(i==0)? thisdrill.homecrumbtext : jQueryparentli.find('a:eq(0)').text().substring(0, thisdrill.titlelength)})
	}) //end UL loop
	var selectedulcheck=this.selectedul && document.getElementById(this.selectedul) //check if "selectedul" defined, plus if actual element exists
	this.jQueryarrowimgs=this.jQuerymaindiv.find('img.arrowclass')
	this.arrowposx=parseInt(this.jQueryarrowimgs.eq(0).css('left')) //get default x position of arrow
	if (window.opera)
		this.jQueryuls.eq(0).css({zIndex: this.zIndexvalue}) //Opera seems to require this in order for top level arrows to show
	if (this.persist.enable && (this.persist.overrideselectedul || !this.persist.overrideselectedul && !selectedulcheck) && drilldownmenu.routines.getCookie(this.menuid)){ //go to last persisted UL?
		var ulorder=parseInt(drilldownmenu.routines.getCookie(this.menuid))
		this.slidemenu(ulorder, true)
	}
	else if (selectedulcheck){ //if "selectedul" setting defined, slide to that UL by default
		var ulorder=jQuery('#'+this.selectedul).data('specs').order
		this.slidemenu(ulorder, true)
	}
	else{
		this.slidemenu(0, true)
	}
	this.navdivs.jQuerycrumb.click(function(e){ //assign click behavior to breadcrumb div
		if (e.target.tagName=="A"){
			var order=parseInt(e.target.getAttribute('rel'))
			if (!isNaN(order)){ //check link contains a valid rel attribute int value (is anchor link)
				thisdrill.slidemenu(order)
				e.preventDefault()
			}
		}
	})
}

drilldownmenu.prototype.slidemenu=function(order, disableanimate){
	var order=isNaN(order)? 0 : order
	this.jQueryuls.css({display: 'none'})
	var jQuerytargetul=this.jQueryuls.eq(order).css({zIndex: this.zIndexvalue++})
	jQuerytargetul.parents('ul').andSelf().css({display: 'block'})
	this.currentul=order
	if (jQuerytargetul.data('specs').h > this.jQuerymaindiv.data('h')){
		this.jQuerymaindiv.css({overflowY:'auto'}).scrollTop(0)
		this.jQueryarrowimgs.css('left', this.arrowposx-15) //adjust arrow position if scrollbar is added
	}
	else{
		this.jQuerymaindiv.css({overflowY: 'hidden'}).scrollTop(0)
		this.jQueryarrowimgs.css('left', this.arrowposx)
	}
	this.updatenav(jQuery, order)
	this.jQueryuls.eq(0).animate({left:-jQuerytargetul.data('specs').x}, typeof disableanimate!="undefined"? 0 : this.speed)
}

drilldownmenu.prototype.back=function(){
	if (this.currentul>0){
		var order=this.jQueryuls.eq(this.currentul).parents('ul:eq(0)').data('specs').order
		this.slidemenu(order)
	}
}

drilldownmenu.prototype.updatenav=function(jQuery, endorder){
	var jQuerycurrentul=this.jQueryuls.eq(endorder)
	if (this.navdivs.jQuerycrumb.length==1){ //if breadcrumb div defined
		var jQuerycrumb=this.navdivs.jQuerycrumb.empty()
		if (endorder>0){ //if this isn't the topmost UL (no point in showing crumbs if it is)
			var crumbhtml=''
			while (jQuerycurrentul && jQuerycurrentul.data('specs').order>=0){
				crumbhtml=' <img src="'+this.breadcrumbarrow+'" /> <a href="#nav" rel="'+jQuerycurrentul.data('specs').order+'">'+jQuerycurrentul.data('specs').title+'</a>'+crumbhtml
				jQuerycurrentul=(jQuerycurrentul.data('specs').order>0)? this.jQueryuls.eq(jQuerycurrentul.data('specs').parentorder) : null
			}
			jQuerycrumb.append(crumbhtml).find('img:eq(0)').remove().end().find('a:last').replaceWith(this.jQueryuls.eq(endorder).data('specs').title) //remove link from very last crumb trail
		}
		else{
			jQuerycrumb.append(this.homecrumbtext)
		}
	}
	if (this.navdivs.jQuerybackbuttons.length>0){ //if back buttons found
		if	(!/Safari/i.test(navigator.userAgent)) //exclude Safari from button state toggling due to bug when the button is an image link
			this.navdivs.jQuerybackbuttons.css((endorder>0)? {opacity:1, cursor:'pointer'} : {opacity:0.5, cursor:'default'})
	}
}

drilldownmenu.prototype.uninit=function(){
	if (this.persist.enable)
		drilldownmenu.routines.setCookie(this.menuid, this.currentul)
}

drilldownmenu.routines={

	getCookie:function(Name){ 
		var re=new RegExp(Name+"=[^;]*", "i"); //construct RE to search for target name/value pair
		if (document.cookie.match(re)) //if cookie found
			return document.cookie.match(re)[0].split("=")[1] //return its value
		return null
	},

	setCookie:function(name, value){
		document.cookie = name+"="+value+"; path=/"
	}

}

