// bcNav - to establish navigating context for category menu
// version: 1.7.0 (concept, major, minor - including bug fixes)

( function($) {
	
	$.fn.bcNav = function(args) {

		if( this.length === 0 ) {
			return;
		}
		
		// Globals/Environment
		options = $.extend( $.fn.bcNav.settings, args );
		methods.setGlobals(this);
		options.parentclass = '.' + options.parentclass;
		
		// Run helper functions if specified
		if( typeof methods[args] === 'function' ) {
			return methods[args].call(this, options);
		}
		
		return this.each(function(i, e) {
			
			// check if URI has valid location, if this returns true we exit (not valid)
			if( methods.checkRootLevel(options) ) return;

			var mytree = methods.findTarget($.fn.bcNav.level, methods.getLocation(options), options.menutreelabel);
			var $mytree = $(mytree);
			// Exit if no match (error, this shouldn't happen however does on Safari)
			if( $.fn.bcNav.match == false ) { 
				return;
			} else if( $mytree.children('ul').length == 0 ) {
				// if this is true we've reached the end of the tree
				// this is normal when viewing categories that have no children
				// if root is up one level do nothing
				if( $.fn.bcNav.current_level == 3 ) { 
					return; 
				} else { 
					// if root is not up one level, grab the next level up
					mytree = mytree.parentNode.parentNode; 
					}
				$mytree = $(mytree);
			}

			if( options.inserttree ) {

				$mytree = $mytree.clone(true);
				var header_txt = $mytree.find("a:first").html();
				$mytree.children('ul:first').css({'display':'block','visibility':'visible'});
				$mytree.find("a:first").remove();
		
				if( options.keepclass ) {
					$(this).find(options.parentclass + ' ul').attr('class');
					$mytree.children("ul:first").addClass(
						$(this).find(options.parentclass + ' ul').attr('class')
					);
				}
				if( options.replaceheader ) {
					$(this).find(options.headingtype + ':first').empty();
					$(this).find(options.headingtype + ':first').html(header_txt);
				}
				if( options.removeheading ) {
					$(this).find(options.headingtype + ':first').remove();
				}

				// Insert new menu
				$(this).find(options.parentclass + ' ul').remove();
				$(this).find(options.parentclass).prepend($mytree.html());
				$mytree = null;
			}
    	});
	};
	
	var methods = {
		setGlobals: function( jquery ) {
			$.fn.bcNav.level = 2;
			$.fn.bcNav.match = new Boolean();
			$.fn.bcNav.menu_id = jquery.attr('id');
			$.fn.bcNav.current_level = 0;
		},
		isRoot: function() {
			return methods.checkRootLevel(options);
		},
		classActive: function(options) {
			menu_el = methods.findTarget($.fn.bcNav.level, methods.getLocation(options, 3));
			$(menu_el).parent().addClass("Active");
			return;
		},
		handleArgs: function(){
			
		},
		checkRootLevel: function(options) {
			var _loc = methods.getLocation(options);
			var tmp_location = _loc[_loc.length - $.fn.bcNav.level];
		
			// if we are on the root category page, not subcategory, exit
			// also if the location object isn't a URI from the category or product pages, exit
			if ( tmp_location == _loc[1] || _loc.length - $.fn.bcNav.level < $.fn.bcNav.level ) { 
				return true;
			} else {
				return false;
			}
		},
		format: function( format_str ) {
			//var tmpstring = encodeURIComponent(format_str);
			//var tmpstring2 = decodeURIComponent(format_str);
			//return format_str.replace(/-/g," ");
			//return decodeURIComponent(format_str);
			return format_str;
		},
		getLocation: function(options, depth) {
		    if( options.context ) {
				var tmp_loc = options.context;
			} else {
				// create category page, or product page loc object (product page based off breadcrumb)
				var tmp_loc = "";
				if( location.pathname.split("/")[1] == "products" ) {
					// products page - derive location object via breadcrumb
					if( $("#ProductBreadcrumb ul").length == 0 ) {
						// product breadcrumb isn't enabled, return mock location so no match will be found
						tmp_loc = "/0123456789abcdef";
					} else {
						var href = $("#ProductBreadcrumb ul:first li:nth-child(2) a").attr('href');
						strip_txt = methods.getURLHostString(href);
						href = href.replace(strip_txt, "");
						tmp_loc = href;
					}
				} else if( location.pathname.split("/")[1] == "categories" ) {
					// category page
					tmp_loc = location.pathname;
				} else {
					// couldn't match a product or category page, insert a mock URL
					tmp_loc = "/0123456789abcdef";
				}
			}
		    // needed by classActive() to return a location object thats only 1 level deep
		    if( depth ) {
		    	
		    	//for( var i = 0; tmp_loc.split("/").length < depth; i++ ) {
		    	tmp_loc_holder = tmp_loc.split("/");
		    	for( var i = 0; i < depth; i++ ) {
		    		if( i == 0 ) {
		    			tmp_loc = "/" 
		    		} else {
		    			tmp_loc += tmp_loc_holder[i].toString() + "/";
		    		}
		    	}
		    	//alert("tmp_loc: " + tmp_loc);
		    }
			return tmp_loc.split("/");
		},
		getURLHostString: function(a) {
			var proto = a.substring(0, a.indexOf("/")) + "//";
			var host = a.replace(proto, "");
				host = host.substring(0, host.indexOf("/"));
			var strip_txt = proto + host;
			
			return strip_txt;
		},
		formatHREF: function( href, level ) {
			var strip_txt = methods.getURLHostString(href);
			
			var sub = href.replace(strip_txt, "");
			var sub_split = sub.split("/");
			if( sub_split[level] == undefined ) {
				return "";
			}
			return sub_split[level];
		},
		// find <a> element who's innerHTML is equal to the location
		findTarget: function( level, loc_array, classlabel ) {
			
			$.fn.bcNav.match = false;
			$.fn.bcNav.current_level = level;
			//var loc_array = methods.getLocation(options);
			var target_el = document.getElementById($.fn.bcNav.menu_id);
			var supportsNodeIterator = typeof document.createNodeIterator == "function";
			if( supportsNodeIterator ) {
			
				var filter = function(node){
					return node.tagName.toLowerCase() == "a" ?
						NodeFilter.FILTER_ACCEPT :
						NodeFilter.FILTER_SKIP;
					};
				for( a=level; a <= loc_array.length - level; a++ ) {
	
					var re = new RegExp('^' + methods.format( loc_array[a] ) + '$');
					var iterator = document.createNodeIterator(target_el, NodeFilter.SHOW_ELEMENT,filter, false);
					var node = iterator.nextNode();
					var label = classlabel + "-" + ( $.fn.bcNav.current_level - level );
					while (node !== null) {
						var href_txt = methods.formatHREF( node.href, $.fn.bcNav.current_level );
						//var txt = ( typeof node.innerText == "undefined" ) ? node.textContent : node.innerText; //node.innerHTML;
						//var a_href = node.href;
						if( href_txt.match(re) ) {
							if( a == loc_array.length - level ) {
								$(node.parentNode).addClass( "active" ); 
								$(node.parentNode.parentNode).addClass( "activemenu" ); 
							}
							$(node.parentNode.parentNode).addClass( label ); 
							$.fn.bcNav.match = true;
							target_el = node.parentNode;
							break;
						} else {
							node = iterator.nextNode();
						}
					}
					$.fn.bcNav.current_level++;
				}
			} else { // NodeFilter and NodeIterator not supported by IE. support IE here by using jquery
				var $_target_el = $(target_el);
				// tmp_match is to prohibit further matching, see below
				var tmp_match = false;
				for( a = level; a <= loc_array.length - level; a++ ) {
					var re = new RegExp('^' + methods.format( loc_array[a] ) + '$');
					var label = classlabel + "-" + ( $.fn.bcNav.current_level - level );
					current_context_level = $.fn.bcNav.current_level;
					$_target_el.find('a').each( function() {
						var href_txt = methods.formatHREF($(this).attr('href'), $.fn.bcNav.current_level);
						if( href_txt.match(re) ) {
							// tmp_match is to prohibit further matches for the this function.
							// we are assuming first match is always the correct one, for the current level
							if( !tmp_match ) {
								if( a == loc_array.length - level ) {
									$(this).parent().parent().addClass( "activemenu" );
									$(this).parent().addClass( "active" ); 
								}
								$(this).parent().parent().addClass( label ); 
								$_target_el = $(this).parent();
								target_el = this.parentNode;
								tmp_match = true;
							}
							// if we are at the end of the loop with a match, set the global match variable to true
							if( a == loc_array.length - level ) {
								$.fn.bcNav.match = true;
							}
						}
					});
					$.fn.bcNav.current_level++;
					tmp_match = false;
				}
			}
			return target_el;
		}
	};
	
	$.fn.bcNav.settings = {
		'followurl'     	: true,								// Automatically establish categorical context
		'replaceheader' 	: true,								// Replace the text inside header to relevant category name
		'headingtype'   	: 'h2',								// Change default HTML heading tag to a different tag
		'context'       	: null,								// If 'followurl' is set to fale, define a default context to show always (if left blank bcNav determines this automatically)
		'parentclass'   	: 'SideCategoryListClassic',		// Define the HTML container where menu's live in
		'keepclass'     	: false,							// Keep existing css class's applied to menu before processing
		'removeheading' 	: false,							// Removes the menu's heading
		'menutreelabel'		: 'catlevel',						// Define what label will be applied to the <body> tag when 'classTree' is set to true
		'inserttree'		: true
	};
})(jQuery);



