

/*
 * DNN Search Keywords Enhancement
 *
 * Author: Kris McKernan (Objective Associates Ltd)
 * Modified: 12/04/2010
 *
 * Description: creates a dropdown list of search keywords provided by DNN's own search module, the dropdown list is populated via an ajax request as the user types,
 */

var search = {
	textBox : "input#dnn_ctr388_PropertySearch_SearchTextBox",
	url : "/SearchResults.aspx?Search=",
	dropDown : {
		dom : "#keywords",
		index : 1,
		keyEventHandler : function(code) {
			var items = $jq(this.dom + ' ul li').size();
			if (code == 40 && (items > 0) && (this.index < items)) { // down arrow
				this.next();
			} else if (code == 38 && (items > 0) && (this.index > 1)) { // up arrow
				this.prev();
			}
			this.select(this.index-1);
		},
		next : function() {
			this.index = this.index + 1;
			$jq(search.textBox).attr("value", this.text());
		},
		prev : function() {
			this.index = this.index - 1;
			$jq(search.textBox).attr("value", this.text());
		},
		select : function (index) {
			$jq(this.dom + ' ul li').each(function(i) {
				$jq(this).removeClass('selected');
				if (i == index) {
					$jq(this).addClass('selected');
				}			
			});	
		},
		text : function() {
			var txt = "";
			$jq(this.dom + ' ul li').each(function(i) {
				if (i == search.dropDown.index-1) {
					txt = $jq(this).text();
				}
			});
			return txt;
		}
	},
	keywords : {
		max : 20,
		highlight : true,
		url : "/DesktopModules/Keywords/SearchKeywords.aspx?t=",
		request : null,
		get : function () {
			// cancel last request if it is still pending
			if (this.request != null) {
				this.request.abort();
			}			
			setTimeout(function() {			
				// create new ajax request for keywords
				search.keywords.request = $jq.ajax({
					url: (search.keywords.url + $jq(search.textBox).attr("value")),
					cache: true,
					success: function(data) {
						// add keywords to dropdown
						var d = search.dropDown;
						$jq(d.dom).html(data);
						
						// tidy up latest set of keywords
						search.keywords.cleanup(d.dom + " li");
						
						// display drop down
						if ($jq(d.dom + " li").size() > 0) {
							$jq(d.dom).show();
						} else {
							$jq(d.dom).hide();
						}
						// reset dropdown index
						d.index = 0; d.select(-1);
					}
				});
			}, 10);	// timer is required to get the correct search term from the textbox
		},
		cleanup : function(words) {
			this.remDuplicates(words);
			this.filter(words);
			this.trim(words);
			this.addHighlight(words);
		},
		remDuplicates : function(words) {
			// removes duplicate keywords
			var lastWord = "";
			$jq(words).each(function(i) {
				if ($jq(this).text().toLowerCase() == lastWord) {
					$jq(this).remove();
				}
				lastWord = $jq(this).text().toLowerCase();
			});
		},
		trim : function(words) {
			// enforces max keywords limit
			$jq(words).each(function(i) {
				if (i > search.keywords.max) {
					$jq(this).remove();
				}
			});
		},
		filter : function(words) {			
			// removes keywords with unwanted characters
			var restricted = ["@", ":", ";", " ", "/", "'", ","];	// limit restricted character set to catch known DNN issues
			
			$jq(words).each(function(i) {
				// fix white space
				$jq(this).html($jq(this).html().replace("&nbsp;", " "));
				
				// check keyword does not start or end with a unicode symbol
				var f_char = $jq(this).text().charCodeAt(0);
				var l_char = $jq(this).text().charCodeAt($jq(this).text().length-1);				
				if (f_char > 122 || f_char < 64 || l_char > 122 || l_char < 64) {					
					$jq(this).remove();
				}
				// check for match against restricted characters
				for (j = 0; j < restricted.length; j++) {
					if ($jq(this).text().match(restricted[j])) {		
						$jq(this).remove();
					}
				}
			});
		},
		addHighlight : function(words) {
			if (this.highlight) {
				hString = $jq(search.textBox).attr("value").toLowerCase();
				$jq(words).each(function(i) {
					// get start and end points of partial string
					var start = $jq(this).text().toLowerCase().indexOf(hString);
					var end = start + hString.length;
					
					// build new html string for keyword
					var html = $jq(this).text().substring(0, start) + "<strong>" + hString + "</strong>" + $jq(this).text().substr(end);					
					$jq(this).html(html);
				});
			}
		}
	},
	submit: function() {
		$jq("input#dnn_ctr388_PropertySearch_SearchButton").click();
	},
	text : {
		value : "e.g. Glasgow",
		color_blur : "#999",
		color_focus : "#323232",
		display : function() {
			if ($jq(search.textBox).attr("value") == "") {
				$jq(search.textBox).attr("value", this.value).css("color", this.color_blur);
			}
		},
		hide : function() {
			if ($jq(search.textBox).attr("value") == this.value) {
				$jq(search.textBox).attr("value", "").css("color", this.color_focus);
			}
		}
	},
	init : function() {
		// set default search text
		$jq(search.textBox).focus(function() {
			search.text.hide();
		});
		$jq(search.textBox).blur(function() {
			search.text.display();
		});
		search.text.display();
		
		// create container div for keywords if required
		if ($jq(search.dropDown.dom).size() == 0) {
			$jq("input#dnn_ctr388_PropertySearch_SearchButton").after("<div id='keywords'></div>");
		}
		
		// add key press event listener to search text box (keydown for IE compatability)
		$jq(search.textBox).keydown(function(e) {
			var code = (e.keyCode ? e.keyCode : e.which);
			
			if(code == 13) { // perform search (on keyword if selected)
				search.submit();
				return false;
			} else if (code != 40 && code != 38){ // get keywords
				search.keywords.get();		
			} else { // pass keycode to drop down object
				search.dropDown.keyEventHandler(code);
			}
		});
		
		// add mouse click listener to dropdown
		$jq(search.dropDown.dom).click(function(e) {
			if ($jq(e.target).is('li')) {
				$jq(search.textBox).attr("value", $jq(e.target).text());
				search.submit();
			} 
		});
	}
};

$jq(document).ready(function() {	
	search.init();
});
