/*-------------------------------------------------------------------
Name:       Search Buddy JS
Author:     $Author: aremick $
Last Mod:   $DateTime: 2011/05/19 12:16:30 $
Revision:   $Revision: #1 $ 
-------------------------------------------------------------------*/

/**
 * @class Autocomplete behavior for search fields
 * @author Jenny Mok <mok#adobe.com>
 */
SearchBuddy = (function() {
	/*--- Create Objects for IDs and CSS classes to be used and changed once if needed (don't have to repeat) ---*/
	_SearchBuddy = {};
	_SearchBuddy.IDS = {
		gnavForm			:	"#globalnav-search",
		siteSearch			:	"#site-search",
		searchInput			:	"#search-input",
		searchBuddySubmit	:	"search-buddy-submit",
		resultsContainer	:	"sb-results",
		resultsBody			: 	"sb-results-body",
		resultsList			: 	"sb-result-list"
	};

	_SearchBuddy.CSS = {
		activated			:	"activated",
		highlight			:	"highlight",
		noResult			:	"no-result",
		searchResult		:	"search-result",
		pulloutItem			:	"pullout-item",
		pulloutContent		:	"pullout-content",
		linkList			:	"link-list",
		searchSuggestion	:	"search-suggestion",
		searchAll			:	"txtright search-all"
	};
	/*--- Create object instance returned by calling Search Buddy function ---*/
	var _SearchBuddyInstance = $.Class.create({
		/*--- Start up! ---*/
		initialize : function(URLS,STRINGS) {
			/*--- Make sure globalnav exists (checks for ID set above) ---*/
			if($(_SearchBuddy.IDS.gnavForm)==null) return;	
			/*--- Only run for EN_US currently ---*/
			if(!$(_SearchBuddy.IDS.gnavForm).hasClass("en")) return;
			/*--- Local URL variables ---*/
			this.URLS = $.extend({
				searchBuddy		:	"/cfusion/search/buddy/searchbuddy.cfm",
				searchResults	:	"/cfusion/search/index.cfm"
			},URLS);
			/*--- Local string variables ---*/
			this.STRINGS = $.extend({
				searchForElipsis	:	"Search for...",
				searchFor			:	"Search for",
				seeAllResults		:	"See all search results &#8250;",
				delay				:	100
			},STRINGS);		
			/*--- Set up local variables ---*/
			this.gnavForm = $(_SearchBuddy.IDS.gnavForm);
			this.siteSearch = $(_SearchBuddy.IDS.siteSearch);
			this.input = $(_SearchBuddy.IDS.searchInput);
			this.term = this.input.val();

            /* prevent default auto complete behavior */
            this.input.attr("autocomplete", "off");
            
			/*--- Set up default Event handlers  ---*/
			this.input.keyup($.proxy(this,"handleKeyCheck"));
			this.gnavForm.bind("submit",$.proxy(this,"handleFormSubmit"));
			/*--- goURL set for key navigation so if keyed down on then ENTER pressed, page goes to that link ---*/
			this.goURL = "";				
			/*--- Get locale variable set within the Gnav HTML and set to pass to Search page ---*/
			this.loc = "en_us";
			/*--- Call URLParser, it will define URLParser as the object with info about the URL ---*/
			this.setupForResults();
		},
		/*--- Setup HTML elements to hold SB results in ---*/
		setupForResults : function() {
			/*--- <div> containers for the results if/when they come ---*/
			this.resultsContainer = $('<div />',{ "id" : _SearchBuddy.IDS.resultsContainer});
			this.resultsBody = $('<div />', { "id" : _SearchBuddy.IDS.resultsBody});		
			this.resultsContainer.appendTo(this.siteSearch);
			this.resultsBody.appendTo(this.resultsContainer);			
			/*--- Create a hidden input with site section/subsection ---*/		
			this.siteSection = URLParser.siteLevel;
			this.siteSection = (this.siteSection=="") ? "home" : this.siteSection;
			this.siteSection = (URLParser.subdomain == "get") ? ("get:"+this.siteSection) : this.siteSection;
			this.siteSection = (URLParser.subdomain == "kb") ? ("kb:"+this.siteSection) : this.siteSection;
			this.siteSection += (URLParser.siteSection==null || URLParser.siteSection=="") ? "" : ":" + URLParser.siteSection;	
			var siteSection_input = $("<input>",{
				"name" : "siteSection",
				"type" : "hidden",
				"value": this.siteSection
			});		
			siteSection_input.appendTo(this.gnavForm);
			var loc_input = $("<input>",{
				"name" : "loc",
				"type" : "hidden",
				"value": this.loc
			});
			loc_input.appendTo(this.gnavForm);
		},
		/*--- 
			Determine whether to submit the GNAV Form based on:
			. goURL is set then do nothing (return false)
			. search term is empty 
			. search term is set to the title attribute of the input
			. event type (click, return
		---*/
		handleFormSubmit : function(event) {		
			var keyCode = event.keyCode || event.which;
			if(this.goURL!="" || this.input.val() =="" || this.input.val() == this.input.attr("title")) { 
				return false; 
			}
			if(event.type=="click" || keyCode=="13" || keyCode=="0") {	
				/*--- clear the input value from "Search for..." which is in the title of the input	---*/
				if(this.input.val()==this.input.attr("title")) this.input.val("");
				this.gnavForm.trigger("submit");
			}
		},
		/*--- document the keycode and then deal with keyboard navigation ---*/
		handleKeyCheck : function(e) {	
			/*--- Not all browsers know keyCode	---*/
			var keyEvent = e.keyCode || e.which;
			/*--- Set up map of keys pressed ---*/
			this.keyMap = {
				SHIFT : e.shiftKey,
				ALT : e.altKey,
				CTRL : e.ctrlKey,
				ESC : keyEvent == 27,
				RETURN : keyEvent == 13,
				TAB : keyEvent == 9,
				DELETE : keyEvent == 8 || keyEvent == 46,
				DOWN : keyEvent == 40,
				UP : keyEvent == 38,
				ALPHANUMERIC : ((keyEvent >=48 && keyEvent <= 57) || (keyEvent >= 65 && keyEvent <= 90))
			};
			/*--- Modifer keys generally will have some kind of alternate navigation action ---*/
			if(this.keyMap.ALPHANUMERIC || this.keyMap.DELETE || this.keyMap.BACKSPACE) {
				this.setTerm();
			} else {				
				this.handleMenuNavigation(e);
			}			
		},		
		/*--- Keyboard commands ---*/
		handleMenuNavigation : function(e) {
			/*--- Don't do anything if there's no results ---*/
			if(!this.json) { 
				e.preventDefault(); 
				return; 
			}
			/*--- RETURN key ---*/
			if(this.keyMap.RETURN) {
				e.preventDefault();
				/*--- If empty term or term is equal to title attribute --> do nothing ---*/
				if (this.input.val()=="" || this.input.val()==this.input.attr("title")) { 
					return false;
				/*--- If goURL is not set --> submit the form (from key nav) ---*/
				} else if(this.goURL=="") {
					this.gnavForm.submit();
					return false;
				/*--- If goURL is set --> go to that link ---*/
				} else {	
					window.location.href=this.goURL;
					return;			
				}
			}
			/*--- ESC gets out of menu ---*/
			if(this.keyMap.ESC) {
				this.deactivateMenu();
				this.goURL="";
				this.input.value = "";
			}
			/*--- TAB out of menu ---*/
			if(this.keyMap.TAB) {
				if(this.goURL.empty()) {
					this.deactivateMenu();
				}
			}
			/*--- BACKSPACE/DEL continues getting results  ---*/
			if(this.keyMap.DELETE) {
				this.handleResultsMenu();
			}
			/*--- Array of links in results ---*/
			var resultLinks = $('#'+_SearchBuddy.IDS.resultsBody + ' a');		
			/*--- DOWN stops default page down event and navigates down result links  ---*/
			if(this.keyMap.DOWN) {	
				e.preventDefault();
				if(this.selectedIndex < resultLinks.length) {
					/*--- if current link is an image, skip over it and increase selected index ---*/
					if($(resultLinks[this.selectedIndex]).has("img").length) this.selectedIndex++;
					/*--- link to highlight ---*/
					var currentLink = $(resultLinks[this.selectedIndex]);
					/*--- remove highlight from anything previously highlighted ---*/
					if(this.selectedIndex > 1) {
						var lastLink = resultLinks[this.selectedIndex-1];
						/*--- Remove one before last if an image ---*/
						if($(resultLinks[this.selectedIndex]).has("img").length) lastLink = resultLinks[this.selectedIndex-2];
						$(lastLink).removeClass(_SearchBuddy.CSS.highlight);
					}
					/*--- highlight current link ---*/
					currentLink.addClass(_SearchBuddy.CSS.highlight);
					/*--- increase index ---*/
					this.selectedIndex++;
					/*--- get the HREF and set status (if available and goURL for if RETURN is hit on it		 ---*/
					var linkString = (currentLink.attr("href")) ? currentLink.attr("href").toString() : false;
					window.status= (linkString) ? linkString : "";
					this.goURL = (linkString) ? linkString : "";
										
				} else if(resultLinks.length==1) {
					/*--- If there are no search results, highlight the search all link ---*/
					$(resultLinks[0]).addClass(_SearchBuddy.CSS.highlight);
				}
						
			}
			/*--- STOP page up and navigate up through result links  ---*/
			if(this.keyMap.UP) {
				e.preventDefault();
				/*--- reduce selectedIndex to move up ---*/
				this.selectedIndex--;
				/*--- if top link, set index to 2 (because it is 2 skipped over #1 which is the image) ---*/
				if(this.selectedIndex == 1) this.selectedIndex=2;
				/*--- if not the top and before the end ---*/
				if(this.selectedIndex > 1 && this.selectedIndex < resultLinks.length) {
					/*--- if link is the image, then skip over it   ---*/
					if($(resultLinks[this.selectedIndex-1]).has("img").length) {
						/*--- unhighlight previous link ---*/
						$(resultLinks[this.selectedIndex]).removeClass(_SearchBuddy.CSS.highlight);
						/*--- reduce selectedIndex to skip over image ---*/
						this.selectedIndex--;
						/*--- highlight next link up ---*/
						$(resultLinks[this.selectedIndex-1]).addClass(_SearchBuddy.CSS.highlight);				
					} else {
						/*--- otherwise, run normally ---*/
						$(resultLinks[this.selectedIndex]).removeClass(_SearchBuddy.CSS.highlight);
						$(resultLinks[this.selectedIndex-1]).addClass(_SearchBuddy.CSS.highlight);				
					}
					/*--- get the HREF and set status (if available and goURL for if RETURN is hit on it		 ---*/
					var linkString = ($(resultLinks[this.selectedIndex-1]).attr("href")) ? $(resultLinks[this.selectedIndex-1]).attr("href") : ""
					window.status=linkString;			
					this.goURL = linkString; /*--- set up link URL to go to if "RETURN" is hit ---*/ 
				}
			}
		},		
		/*--- Determine what input is and search only if not empty ---*/
		setTerm : function() {
			this.term = this.input.val();
			if(this.term=="") {
				this.deactivateMenu();	/*--- don't show menu ---*/
			} else {
				_search = this.search(this.term);	/*--- setup global/private to use for delay ---*/
				setTimeout('_search',this.STRINGS.delay);	/*--- get JSON results ---*/
			}
		},
		/*--- Send query to CF/AJAX to get JSON results ---*/
		search : function() {
			this.baseURL = this.URLS.searchBuddy;					
			var sURL = this.baseURL + "?pre=" + this.term + "&s=" + this.siteSection + "&loc=" + this.loc;				
			$.getJSON(sURL,$.proxy(this,"loadJSON"));
			 				 
			this.selectedIndex = 1;	/*--- always reset keyboard navigation index when new results come in ---*/
			this.goURL = "";	/*--- reset goURL so it won't go there if search term deleted after arrowed down to something (BUG 88029) ---*/
		},
		/*--- LOAD JSON results and show results ---*/
		loadJSON : function(originalRequest) {
			this.json = originalRequest;
			if($('#'+_SearchBuddy.IDS.resultsList)!=null) { $('#'+_SearchBuddy.IDS.resultsList).remove(); }
			if(this.json.HUBLETS.length==0 && this.json.SUGGESTIONS.length==0) {
				this.renderNoResults(); /*--- no results from JSON search ---*/
			} else {
				this.renderResults();  /*--- show results ---*/				
			}
		},		
		/*--- Add activated class to show the results menu ---*/
		activateMenu : function() {
			$(_SearchBuddy.IDS.siteSearch).addClass(_SearchBuddy.CSS.activated);		
		},
		/*--- if there's results, hide/delete them then make sure to quit observing it ---*/
		deactivateMenu : function() {
			//this.undoSelectFix();
			this.gnavForm.trigger("searchbuddy:closed");
			if($("#"+_SearchBuddy.IDS.resultsList) != null) {
				$("#"+_SearchBuddy.IDS.resultsList).remove(); 
				this.siteSearch.removeClass(_SearchBuddy.CSS.activated);
				this.ignoreMouseHover();
			}
		},
		/*--- For no results from JSON, create a link with whatever term is entered w/ link to search results page ---*/
		renderNoResults : function() {
			this.deactivateMenu();
			this.activateMenu();
			var dl = $('<dl/>',{ "id" : _SearchBuddy.IDS.resultsList });
			
			var ddLink = this.URLS.searchResults + "?loc=" + this.loc + "&term=" + this.term;
			var ddText = this.STRINGS.searchFor + ' "' + this.term + '" &#8250;';
			var dd = $('<dd/>', { 'class': _SearchBuddy.CSS.noResult })
				.html($('<a/>', { 'href' : ddLink })
				.html(ddText));
			
			this.resultsBody.append(dl);
			dl.append(dd);
			
			this.goURL = ""; /*--- make sure to empty go to URL if this link is selected ---*/
			
			this.watchDocumentClicks();
		},
		/*--- Show results from JSON (Hublets and Suggestions) in pullout-left DD's and a link to results page with term ---*/
		renderResults : function(json) {	
			/*--- Turn on the menu (add class name basically) ---*/
			this.activateMenu();
			/*--- Set up variable to hold result types ---*/
			var hublets = this.json.HUBLETS;
			var suggestions = this.json.SUGGESTIONS;
			/*--- Create container to hold results append to the results container (added in the beginning) ---*/
			var dl = $('<dl/>',{ id : _SearchBuddy.IDS.resultsList });
			dl.appendTo(this.resultsBody);
			/*--- Loop over Hublet (with mnemonic) results ---*/
			$.each(hublets,function(index,hub){
				/*--- Setup ID based on which number it is ---*/
				var sbrIndex = "sbr-"+index;
				var imgURL = "http://wwwimages.adobe.com/www.adobe.com/" + hub.ICONURL;	/*--- Make sure to call mnemonic from CDN ---*/
				/*--- Create HTML elements and add classnames specified on top ---*/
				var dd = $('<dd/>', { 'id': sbrIndex, 'class': _SearchBuddy.CSS.searchResult });
							
				var image = $('<div/>',{ 'class' : _SearchBuddy.CSS.pulloutItem })
					.html($('<a/>', { 'href' : hub.HOMEPAGEURL })
					.html($('<img>',{ 'src': imgURL})));
				
				var content = $('<div/>',{ 'class' : _SearchBuddy.CSS.pulloutContent });
					
				var h4 = $('<h4/>', { 'href': hub.HOMEPAGEURL})
					.html($('<a/>', { 'href': hub.HOMEPAGEURL })
					.html(hub.TITLE));
					
				var linklist = $('<ul/>',{ 'class' : _SearchBuddy.CSS.linkList});
				/*--- Loop over Links from Hublet results (Buy, Try, Support) ---*/
				$.each(hub.LINKS,function(index,link) {
					var li = $('<li/>').html($('<a/>', { 'href': link.URL}).html(link.TITLE));
					linklist.append(li);
				});
				/*--- Insert all elements into the DOM ---*/
				dl.append(dd);	
				dd.append(image);
				dd.append(content);
				content.append(h4).append(linklist);			
			});
			/*--- Loop over Suggestion results and create HTML elements for them ---*/
			$.each(suggestions,function(index,suggest) {
				var dd = $('<dd/>', { 'id': "sbs-"+index, 'class': _SearchBuddy.CSS.searchSuggestion });
				var link = $('<h4/>').html($('<a/>',{ 'href': suggest.DESTINATIONURL }).html(suggest.TITLE));
				var p = $('<p/>').html(suggest.BLURB);
				/*--- Insert all elements into the DOM ---*/
				dl.append(dd);
				dd.append(link);
				dd.append(p);
			});		
			/*--- Add Search All link below results and add click/keydown handler to submit the form based on input value ---*/
			var searchAllDD = $('<dd/>',{ "class" : _SearchBuddy.CSS.searchAll});
			var searchAllLink = $('<a/>', { 'id': _SearchBuddy.IDS.searchBuddySubmit })
				.html(this.STRINGS.seeAllResults)
				.bind({
					'click': $.proxy(this,"handleFormSubmit"),
					'keydown': $.proxy(this,"handleFormSubmit")
			});
			/*--- Insert into the DOM ---*/
			searchAllDD.append(searchAllLink);
			dl.append(searchAllDD);
			/*--- Watch clicks on document that closes menu ---*/
			this.watchDocumentClicks();
			/*--- Watch hover events to toggle highlight from key event ---*/
			this.watchMouseHover();			
		},
		/*--- OBSERVER FOR CLICK ---/		
		/*--- Handle clicks if outside of the menu to hide it and ignore clicks if so --*/
		handleOutsideClicks : function(event) {			
			var inResultsContainer = $(event.target).parents('#'+_SearchBuddy.IDS.resultsContainer).length > 0;
			var isInputField = $(event.target).is("#search-input");
			if(!inResultsContainer && !isInputField) { 
				this.deactivateMenu();
				this.ignoreDocumentClicks();
				return;
			}
		},
		/*--- Set up click observer on document to hide menu if clicked outside of menu ---*/
		watchDocumentClicks : function() {
			$(document).bind('click', $.proxy(this,"handleOutsideClicks"));
		},
		/*--- Stop observing clicks on document if no results ---*/
		ignoreDocumentClicks : function() {
			$(document).unbind('click', $.proxy(this,"handleOutsideClicks"));
		},
		/*--- OBSERVER FOR MOUSEOVER ---/
		/*--- If any results are highlighted through key navigation, turn them off if hover happens over any other ---*/
		handleMouseHover : function(event) {
			$('#'+_SearchBuddy.IDS.resultsList + " a."+_SearchBuddy.CSS.highlight).removeClass(_SearchBuddy.CSS.highlight);
			this.selectedIndex = 1;
		},
		/*--- Set up mousehover observer on results --*/
		watchMouseHover : function() {
			this.resultsBody.bind('mouseover', $.proxy(this,"handleMouseHover"));
		},
		/*--- Stop observing mousehover on results --*/
		ignoreMouseHover : function() {
			this.resultsBody.unbind('mouseover', $.proxy(this,"handleMouseHover"));
		}
	});
	/*--- Return an instane of the SB ---*/
	return _SearchBuddyInstance;	
})();

URLParser = (function() {
	var pageURL = window.location.toString();

	var urlArray = new Array();
	var pathArray = new Array();

	urlArray = pageURL.split('//');
	pathArray = urlArray[1].split('/');

	/*--- SUBDOMAIN ---*/
	var subDomain = pathArray[0].split('.')[0];

	/*--- WORKAREA ---*/
	var isWorkarea = (pathArray[1] == "WORKAREA") ? true : false;
	var workareaName = (isWorkarea) ? pathArray[2] : "";

	if(isWorkarea) { pathArray.splice(1,2); }

	/*--- LOCALE ---*/
	var locale = pathArray[1];
	locale = (locale.length == 2) ? locale : "en_us";
	if(locale == "en_us") {	pathArray.splice(1, 0, locale); }

	/*--- SITE LEVEL ---*/
	var siteLevel = pathArray[2];

	/*--- SITE SECTION or PRODUCT ---*/
	var siteSection = pathArray[3];
	var productName = (siteLevel == "products") ? product = pathArray[3] : "";

	/*--- SITE SUBSECTION or PRODUCT SECTION ---*/
	var siteSubSection = pathArray[4];
	var productSection = (siteLevel == "products") ? product = pathArray[4] : "";

	/*--- SUB DIRECTORIES ---*/
	var productSubSection = (siteLevel == "products") ? product = pathArray[5] : "";

	var pageInfo = {
		"url":					window.location,
		"path":					window.location.pathname,
		"protocol":				window.location.protocol,
		"hash":					window.location.hash,
		"subDomain" : 			subDomain,
		"host":					pathArray[0],
		"isWorkarea":			isWorkarea,
		"workarea":				workareaName,
		"locale":				locale,
		"siteLevel":			siteLevel,
		"siteSection":			siteSection,
		"productName":			productName,
		"siteSubSection":		siteSubSection,
		"productSection":		productSection,
		"productSubSection":	productSubSection
	};

	return pageInfo;
})();

$(document).ready(function(){
	new SearchBuddy();
});

