/**
 *  @package yahoo.search.answers
 *	@author walter punsapy
 **/
YAHOO.namespace('search.answers');
YAHOO.search.answers = {
	application : {
		config : {
			IS_SEARCH_AHEAD_ENABLED : true,
			IS_SPELLCHECK_ENABLED : true,
			IS_SPELLCHECK_RUNNING : false //not used yet
		},
		name : "Yahoo! Answers",
		version : "",
		locale: 'en_GB',
		
		logger : function() {
		    var _logger;
		    var _configs = { 
			    height: "22em", // Height of container 
			    footerEnabled: true, // Don't show filters/pause/resume/clear UI 
			    verboseOutput: true,
			    logReaderEnabled: true // Pause right away (should be true all the time)
			};
		    return {
		        init: function() {
		            _logger = new YAHOO.widget.LogReader('y-ks-error-log',_configs);
		            _logger.setTitle("Yahoo! Answers [debug]");
		        },
		
		        hide: function() {
		            _logger.hide();
		        },
		        
		        show: function() {
		            _logger.show();
		        }
		    }
		}()
	},
	bookmarks : {
		save : function (title, url, myweburl) {
    		window.open(myweburl+'myresults/bookmarklet?t=' + escape(title) + '&u='+encodeURIComponent(url)+'&ei=UTF-8','popup','width=520px,height=420px,status=0,location=0,resizable=1,scrollbars=1,left=100,top=50',0);
		}
	},
	messenger : {
		MINIMUM_VERSION : 8,
		isValidMessengerClient : function(pMessengerObject) {
			var _m = pMessengerObject;
			var obj = _m.detect();
			if (obj.installed) {
				var ver = obj.version.split(",");
				var majorVersion = ver[0];
				if (majorVersion >= this.MINIMUM_VERSION) return true;
			}
			return false;
		}
	},
	// relationships - ajax 
	relationships : { 
		
		request_handler : "/common/util/ks-urp-xhr-handler.php",

		ACTION_ADD : "add",
		ACTION_REMOVE : "remove", 
		
		ACTION_CONSTANT : "action",
		ACTION_SUCCESS : "action_success",
		ACTION_ERROR : "action_error",	
		
		getRequestHandler : function() { return this.request_handler; },
		
		callback : function() {
			try {
				alert("Friend has been added!");
	    	}
	        catch (e) {
	        	// alert(e.message);
	    	}
		},
		
		update : function(pUri) {
			var _ajax = YAHOO.search.answers.util.Ajax.getInstance();
	    	ygConn.http.asyncRequest(_ajax, 'GET', pUri, false, this.callback, null);
		},
		
		addFriend : function(pUserFromKey,pUserFromYid,pUserFromRegTime,pUserToKey,pUserToYid,pUserToRegTime) {
			try {
				var _uri = this.request_handler + "?" + this.ACTION_CONSTANT + "=" + this.ACTION_ADD + 
					"&fr_k=" + pUserFromKey + "&to_k=" + pUserToKey +
					"&fr_y=" + pUserFromYid + "&to_y=" + pUserToYid +
					"&fr_reg=" + pUserFromRegTime + "&to_reg=" + pUserToRegTime;
					Util.debug("request uri" + _uri);
					this.update(_uri);
			} 
			catch(e) {
				// alert("failure:" + e.message);
			}
		},
		
		removeFriend : function(pUserFromKey,pUserFromYid,pUserFromRegTime,pUserToKey,pUserToYid,pUserToRegTime) {
			try {
				var _uri = this.request_handler + "?" + this.ACTION_CONSTANT + "=" + this.ACTION_REMOVE + 
					"&fr_k=" + pUserFromKey + "&to_k=" + pUserToKey +
					"&fr_y=" + pUserFromYid + "&to_y=" + pUserToYid +
					"&fr_reg=" + pUserFromRegTime + "&to_reg=" + pUserToRegTime;
					Util.debug("request uri" + _uri);
					this.update(_uri);
			} 
			catch(e) {
				// alert("failure:" + e.message);
			}
		}
	},
	search_ahead : {
		TIMEOUT_HANDLE_IN_MILLISECONDS : 750,
		NTH_WORD_TRIGGER : 3,
		SEARCH_AHEAD_SUGGESTED_QUESTIONS : "suggestionsQuestions",
		
		timeout_handle : null,
		request_handler : "/common/util/ks-yfed-search-handler.php"
	},
    cache : {
        data : {
        },
        setData : function(key, value){
            this.data[key] = value;
        },
        getData : function(key){
            return this.data[key];
        }
    },
        category : {

            doToggleCategorySelection : function(pId){
                var _question_prefix = "ks-question-"; // ks-question-autocat-tab
                var _tabs_array = ['autocat','browse'];

                // hide all tabs
                for (var _i=0;_i<_tabs_array.length;_i++) 
                {
                    Util.debug("prefix: " + _question_prefix + _tabs_array[_i]);
                    var elem = document.getElementById(_question_prefix + _tabs_array[_i]);  

                    if (elem){ elem.style.display = "none"; }

                }

                // hide all lists
                for (var _i=0;_i<_tabs_array.length;_i++){ var elem =  document.getElementById(_question_prefix + _tabs_array[_i] + "-tab");  if (elem){ elem.className = ""; }}
                document.getElementById(pId).style.display = "block";
                document.getElementById(pId + "-tab").className = "selected";
                document.catForm.onfocus.value = pId;

                //auto expansion for category browser
                if(pId == 'ks-question-browse')
                {
                    for (var i = 0; i < document.catForm.elements.length; i++) 
                    {
                        if (document.catForm.elements[i].type == 'radio' && document.catForm.elements[i].checked) 
                        {
                            autoExpandByID(document.catForm.elements[i].value); 
                            break;
                        }
                    }
                }

                return false;
            }

        },
    abuse : {
        dialog : {
        },
        submitCallback : function(obj) {
            var response = obj.responseText;
        },

        submitFailure : function(obj) {
            alert("Submission failed: " + obj.status);
        },
        
        init : function(){
            var handleCancel = function() {
                this.cancel();
            }

            var handleSubmit = function() {
                this.submit();
            }
        
            this.dialog = new YAHOO.widget.Dialog("abusedlg", { modal:true, visible:false, 
                width:"350px", fixedcenter:true, constraintoviewport:true, draggable:false });
            this.dialog.callback.success = this.submitCallback;
            this.dialog.callback.failure = this.submitFailure;

            var listeners = new YAHOO.util.KeyListener(document, { keys : 27 }, 
                {fn:handleCancel,scope:this.dialog,correctScope:true} );
            this.dialog.cfg.queueProperty("keylisteners", listeners);
            
            this.dialog.cfg.queueProperty("buttons", [ { text:"Submit", handler:this.handleSubmit } ]);
            this.dialog.render();
        },

        activate : function(title){
            document.getElementById('abusedlg_title').innerHTML = title;
            this.dialog.show();
        }
    },
    starflag : {
        toggleFlagMenu : function(qid){
            var name = 'qflag-menu-' + qid;
            var cached = oCache.getData(name + '-timer');
            if (cached){
                clearTimeout(cached);
                oCache.setData(name + '-timer', null);
            }
            else {
      			var _elem = Util.gObj(name);
                _elem.style.display = "block";
            }
        },
        hideFlagMenu : function(qid){
            var name = 'qflag-menu-' + qid;
  			var _elem = Util.gObj(name);
            _elem.style.display = "none";
            oCache.setData(name + '-timer', null);
        },
        startFlagTimer : function(qid){
            var name = 'qflag-menu-' + qid + "-timer";
            var cached = oCache.getData(name);
            if (cached){
                clearTimeout(cached);
	            var timer = setTimeout("oAnswers.starflag.hideFlagMenu('" + qid + "')", 500);
                oCache.setData(name, timer);
            }
            else {
	            var timer = setTimeout("oAnswers.starflag.hideFlagMenu('" + qid + "')", 500);
                oCache.setData(name, timer);
            }
        },
        starToggle: function(qid, count, starred, page){
            var method = (starred? "unStarItem" : "starItem");
            var uri = "/common/util/ks-qa-xhr-handler.php" +
               "?method=" + method + "&qid=" + qid + "&stars=" + count + "&p=" + page;
            var callback = { success: oAnswers.starflag.getStarToggleResponse,
                             failure: oAnswers.starflag.getStarToggleResponse,
                             argument: [qid, page, starred] }
            oAnswers.util.Ajax.request(uri, callback);
        },
        getStarToggleResponse : function(response){
            var args = response.argument;
            oAnswers.starflag.getGenericStarFlagResponse(response);
            var qid = args[0];
            var page = args[1];
            if (page == 2){
                var starred = !args[2];
                if (starred){
                    // remove handler
                    YAHOO.util.Event.purgeElement("abuse-report-" + qid);
                }
                else {
                    // add handler
                    YAHOO.util.Event.addListener("abuse-report-" + qid, "mouseover", function() {
                        openActionMenu("abuse-report", qid); });	
                }
            }
        },
        getGenericStarFlagResponse : function(response){
            var rsp = response.responseText;
            var tid = response.tId;
            var args = response.argument;
            if ((tid == null && args == null) || (response.status == 0))
                return false;
            var qid = args[0];
            var jsonText = (null != rsp)? rsp : "";
            var json = Util.evalJson(jsonText);
            if (json && !json.error){
                var star = Util.gObj("starflag_area-" + qid);
                var html = json["html"];
                star.innerHTML = html;
                return true;
            }
            else return false;
        },
        justHideIt : function(qid, stars,page){
            var uri = "/common/util/ks-qa-xhr-handler.php" +
               "?method=hideItem&qid=" + qid + "&stars=" + stars + "&p=" + page;
            var callback = { success: oAnswers.starflag.justHideItResponse,
                             failure: oAnswers.starflag.justHideItResponse,
                             argument: [qid, page] }
            oAnswers.util.Ajax.request(uri, callback);
        },
        justHideItResponse : function(response){
            var args = response.argument;
            oAnswers.starflag.getGenericStarFlagResponse(response);
            if (args != null){
                var page = args[1];
                if (page == 0){
                    oAnswers.starflag.hideFlagMenu(args[0]);
                    oAnswers.starflag.fadeItem("q_row_" + args[0]);
                }
            }
        },
        fadeItem : function(id){
            var root = document.getElementById(id);
            oAnswers.starflag.fadeItemHelper(root, 'td', 5);
            oAnswers.starflag.fadeItemHelper(root, 'img', 9);
        },
        fadeItemHelper : function(root, id, wholeOpacity){
            var items = root.getElementsByTagName(id);
            for (i=0; i<items.length; i++){
                YAHOO.util.Dom.setStyle(items[i], '-moz-opacity', wholeOpacity/10);
                items[i].style.filter = 'alpha(opacity=' + wholeOpacity*10 + ')';
            }
        }
    },
	profile : {
		// for the question / answers page
        doToggleProfileStatsList : function(pId){
			var _profile_prefix = "ks-user-profile-"; // ks-user-profile-questions-tab
			var _tabs_array = ['summary-list','details'];
			// hide all tabs
			for (var _i=0;_i<_tabs_array.length;_i++) {
				Util.debug("prefix: " + _profile_prefix + _tabs_array[_i]);
				var elem = document.getElementById(_profile_prefix + _tabs_array[_i]);  if (elem){ elem.style.display = "none"; }
				
			}
			// hide all lists
			for (var _i=0;_i<_tabs_array.length;_i++){ var elem =  document.getElementById(_profile_prefix + _tabs_array[_i] + "-tab");  if (elem){ elem.className = ""; }}
			document.getElementById(pId).style.display = "block";
			document.getElementById(pId + "-tab").className = "selected";
			return false;
        },

		doToggleProfileQAList : function(pId) {
			var _profile_prefix = "ks-user-profile-"; // ks-user-profile-questions-tab
			var _tabs_array = ['questions','answers','watchlist','starred'];
			
			// hide all tabs
			for (var _i=0;_i<_tabs_array.length;_i++) {
				Util.debug("prefix: " + _profile_prefix + _tabs_array[_i]);
				var elem = document.getElementById(_profile_prefix + _tabs_array[_i]);  if (elem){ elem.style.display = "none"; }
				
			}
			// hide all lists
			for (var _i=0;_i<_tabs_array.length;_i++){ var elem =  document.getElementById(_profile_prefix + _tabs_array[_i] + "-tab");  if (elem){ elem.className = ""; }}
			document.getElementById(pId).style.display = "block";
			document.getElementById(pId + "-tab").className = "selected";
			return false;
		},
		// for the stats module
		doToggleProfileStats : function(pChar,pAnchor) {
			var _ele_q = document.getElementById('ks-stats-chart-q');
			var _ele_a = document.getElementById('ks-stats-chart-a');
			var _anchor_q = document.getElementById('ks-stats-chart-nav-q');
			var _anchor_a = document.getElementById('ks-stats-chart-nav-a');
			
			var _totals_q = document.getElementById('ks-stats-total-qcount');
			var _totals_a = document.getElementById('ks-stats-total-acount');

			if ("q"==pChar) {
				_ele_q.style.visibility = "visible";
				_ele_a.style.visibility = "hidden";
				_anchor_q.className = "selected";
				_anchor_a.className = "unselected";
                _totals_q.style.display = "block";
                _totals_a.style.display = "none";
			}
			else if ("a"==pChar) {
				_ele_q.style.visibility = "hidden";
				_ele_a.style.visibility = "visible";
				_anchor_q.className = "unselected";
				_anchor_a.className = "selected";
                _totals_a.style.display = "block";
                _totals_q.style.display = "none";
			}
		},
        // for profile mouseover
		onAvatarOver : function(pKid, toggle) {
            var loading_text = "Loading...";
            var image_loading_url = "http://us.i1.yimg.com/us.yimg.com/i/in/se/an/loading_greyarial_in.gifgif";

			var _elem = Util.gObj('profile-info-' + pKid);
            if (toggle){
                _elem.style.visibility = "visible";
                var cached = oCache.getData('profile_kid_data');
                var best_answer_count = Util.gObj("member-answers-best-val_" + pKid);
                var ptweek = Util.gObj("member-points-this-week-val_" + pKid);
                var tpts = Util.gObj("member-total-answers-val_" + pKid);

                if (cached){
                    var cache = oCache.getData('profile_kid_data')[pKid];
                    var weekly = cache["weekly"] *= 1;
                    var best_ans_cnt = cache["best_ans_cnt"] *= 1;
                    var total_ans_cnt = cache["total_ans_cnt"] *= 1;
                    var percent = cache["percent"];
                    best_answer_count.innerHTML = best_ans_cnt +
                        " (" + percent + "% of Total)";
                    ptweek.innerHTML = weekly;
                    tpts.innerHTML = total_ans_cnt;
                }
                else {
                    var kids = Util.gObj('kidarr').value;
                    var uri = "/common/util/ks-qa-xhr-handler.php" +
                       "?method=getKidData&kidarr=" + kids;
                    best_answer_count.innerHTML = "<img src=\"" + image_loading_url +
                        "\" alt=\"" + loading_text + "\">";

                    ptweek.innerHTML = "<img src=\"" + image_loading_url +
                        "\" alt=\"" + loading_text + "\">";

                    tpts.innerHTML = "<img src=\"" + image_loading_url + "\" alt=\"" + 
                        loading_text + "\">";
                    var callback = { success: oProfile.getKidsResponse,
                                     failure: oProfile.getKidsResponse,
                                     argument: [pKid, best_answer_count, ptweek, tpts] }
                    oAnswers.util.Ajax.request(uri, callback);
                }
            }
            else _elem.style.visibility = "hidden";
        },
        getKidsResponse : function(response){
            var rsp = response.responseText;
            var tid = response.tId;
            var args = response.argument;
            if ((tid == null && args == null) || (response.status == 0)){
                if (args != null){
                    var errstr = "Oops, there is an error.";
                    args[1].innerHTML = errstr;
                    args[2].innerHTML = errstr;
                    args[3].innerHTML = errstr;
                }
                else {
                   // this really shouldn't happen...
                }
                return false;
            }

            var kid = args[0];
            var best_answer_count = args[1];
            var ptweek = args[2];
            var tpts = args[3];

            var jsonText = (null != rsp)? rsp : "";
            var json = Util.evalJson(jsonText);
            if (json && !json.error){
                var weekly = json[kid]["weekly"] *= 1;
                var best_ans_cnt = json[kid]["best_ans_cnt"] *= 1;
                var total_ans_cnt = json[kid]["total_ans_cnt"] *= 1;
                var percent = json[kid]["percent"];
                best_answer_count.innerHTML = best_ans_cnt +
                    " (" + percent + "% of Total)";
                ptweek.innerHTML = weekly;
                tpts.innerHTML = total_ans_cnt;
            }
            else {
                var errstr = "Oops, there is an error.";
                best_answer_count.innerHTML = errstr;
                ptweek.innerHTML = errstr;
                tpts.innerHTML = errstr;
            }
            oCache.setData('profile_kid_data', json);
        }
	},
	spellcheck : {	
		SpellController : {},	
		data : {
			Speller : {
			
			}
		}		
	},
	util : {
		isNull : function(pEle) {
			//
		},
		oSearchOptionMenu : {
			_oMenu : null,
			isOpen : false,		
			_FORM_ELEMENT_ID : "ks-inline-search",
			_ELEMENT_OPTIONS_ID : "ks-inline-search-options",
			_ELEMENT_CLICK_FOR_OPTIONS_ID : "ks-inline-search-click-for-options",	
			init : function(pIntl,pNodeToAppendTo) {
				var _intl = pIntl || "us";
				var _node_to_attach_to = pNodeToAppendTo || document.body;
				var _aMenuItemData = [  
					{ text: "Yahoo! Search", config: { url:"javascript:void(0);" }, elementId : "option-yahoo-search", icoClassName : "ico-yahoo" },
	                { text: "Wikipedia", config: { url:"javascript:void(0);" }, elementId : "option-wikipedia-search", icoClassName : "ico-wikipedia" }
				];
				var oMenuItem = null;
				var nMenuItems = _aMenuItemData.length;
				try {
					_oMenu = new YAHOO.widget.Menu(YAHOO.search.answers.util.oSearchOptionMenu._ELEMENT_OPTIONS_ID);  
					for (var i=0; i<nMenuItems; i++) {
		            	oMenuItem = new YAHOO.widget.MenuItem(_aMenuItemData[i].text,_aMenuItemData[i].config);
		            	oMenuItem.element.id = _aMenuItemData[i].elementId;	            	
		            	oMenuItem.clickEvent.subscribe(YAHOO.search.answers.util.oSearchOptionMenu.toggle,_aMenuItemData[i].icoClassName);
						_oMenu.addItem(oMenuItem);
					}    
					_oMenu.render(_node_to_attach_to);
					YAHOO.util.Event.addListener(
						YAHOO.search.answers.util.oSearchOptionMenu._ELEMENT_CLICK_FOR_OPTIONS_ID, 
						"click", 
						function(){ YAHOO.search.answers.util.oSearchOptionMenu.open(); }
					);
				}
				catch(e) {
				
				}
				finally {
					oMenuItem = null;
					_aMenuItemData = null;
					_node_to_attach_to = null;
				}
			},
			toggle : function(pType, pArguments, pClassName) { //subscribe event always returns Event, Event Arguments and additional args[]
				var _ele = document.getElementById(YAHOO.search.answers.util.oSearchOptionMenu._ELEMENT_CLICK_FOR_OPTIONS_ID); //options-selector
				var _form = document.getElementById(YAHOO.search.answers.util.oSearchOptionMenu._FORM_ELEMENT_ID);
				try {
					if (null != _ele && "undefined" != _ele) {
						_ele.className = "options-selector " + pClassName;
					}
					var _ele_hidden_id = pClassName + "-search-value";
					var _ele_hidden = document.getElementById(_ele_hidden_id);
					if (null != _ele_hidden && "undefined" != _ele_hidden && null != _form && "undefined" != _form) {
						_form.action = _ele_hidden.value;
					}
				}
				catch(e) { }
				finally {
					_ele = null;
					_form = null;
				}
			},
			open : function() {
				try {
					_oMenu.show();
					setTimeout(function() { YAHOO.util.Event.addListener(document.body, "click", function(){ YAHOO.search.answers.util.oSearchOptionMenu.close(); }) },600);
				}
				catch(e) { }
			},
			close : function() {
				try {
					_oMenu.hide();
					var bRemoved = YAHOO.util.Event.purgeElement(document.body, false, "click");
				}
				catch(e) { }
				finally { }
			},			
			openTargetWindow : function() {
				var _form_id = YAHOO.search.answers.util.oSearchOptionMenu._FORM_ELEMENT_ID;
				var _form_obj = document.getElementById(_form_id);
    			var _window_name = _form_id + (new Date().getTime().toString());
    			_form_obj.target = _window_name;
    			try {
    				window.open('', _window_name, 'width=750,height=450,resizable=1,scrollbars=1,location=yes,menubar,status, scrollbar, directories, toolbar');
				}
				catch(e) {
					
				}
				finally {
					_form_id = null;
					_form_obj = null;
					_window_name = null;
				}
			}
		},
		setCursor : function(pStr) {
			document.body.style.cursor = pStr;
		},
		setDocumentTitle : function(pStr) {
			document.title = pStr;
		},
		isNull : function(pEle) {
		    return (null==pEle || "undefined"==pEle || ""==pEle);
		},		
		
		ERROR_NOTICE : { key : "8", value : "notice" },
		ERROR_INFO :   { key : "4", value : "info"   },
		ERROR_WARN :   { key : "2", value : "warn"   },
		ERROR_ERROR :  { key : "1", value : "error"  },
		
		debug : function(pStr,pLevel) {
			YAHOO.search.answers.debug(pStr,pLevel);
		},
				
		$ : function() {
			var elements=[];
			for (var i=0; i < arguments.length; i++) {
				var e = arguments[i];
				if (typeof e == 'string') e = document.getElementById(e);
				if (arguments.length == 1) return e;
				elements.push(e);
			}
			return elements;
		},
		
		Ajax : {
			connection : null,
			getInstance : function() { // DEP: ygConn 1.1.3
				if (!ygConn) return null;
				if (null == this.connection) {
					this.connection = ygConn.getObject();
				}
				return this.connection;
			},
			// use YUI Connection Manager 2.0
			request : function(pUrl, pCallback, pFormMethodType) {
				var _formType = pFormMethodType || 'GET';
				try {
					YAHOO.util.Connect.asyncRequest(_formType, pUrl, pCallback); 
				}
				catch(e) {
					//TODO
				}
			}			
		}
	},
	debug : function(pStr,pLevel) {
		if (Util) Util.debug(pStr,pLevel); // TODO: must be rewritten
	},
	eggs : {
		CONTRA_CODE_INIT : "rbaS"
	},
	translations: {
		SPELLCHECKER_ERROR : 'Oops, the Spellcheck is having problems, please try again.'
	}
}


/*
 *  @description SpellChecker Library
 				 - SpellController namespace
 				 - Speller object
 *  @requires YAHOO.util.Event
 *  @requires ygConn
 *
 */

/******************************************************************************/

/*  @requires SpellController
 *  @description Speller manages the spell check features, using utilities from 
 *               SpellController for help
 *
 */

YAHOO.search.answers.spellcheck.data.Speller=function(pSuggestions) {
	this.text = "";
	this.textInitPos = -1;
	this.textEndPos = -1;
    this.corrections = pSuggestions; //array of suggested replacement words
    this.changes = "";
    this.current = 0;
    this.ignore = []; //array of strings to ignore
	this.isSpellchecking = false; //is user spellchecking?
	
	this.lastIndex = 0;
	this.lastDelta = 0;
	
	var self = this; //I HATE THIS
	
	// The following are all different if editor is an iframe
	// They will be one and the same if it is a textarea
	this.editBox = null;		// Outer frame for editor sizing & event capture
	this.editDoc = null;		// Document for event capture
	this.editContent = null;	// Container for setting innerHTML
	this.isText = false;        // this is for textarea / text elements, NOT RTE functions
    this.spellTimer = null;
    
    //this property has the text to be parsed
    this.setText = function( pStr ) { this.current=0; this.text=pStr; }
    this.getText = function() { return this.text; }
    
    this.onChange = function() { this.onProcess(true); }
    this.onIgnore = function() { this.onProcess(false); }

    this.onProcess = function(pChange) {
        var isChanging = pChange || false;
		if ( this.current < this.corrections.length ) {
		    if (isChanging) this.changeWord( this.current );
		    this.nextWord();
		}
    }

    this.onChangeAll = function() { this.onProcessAll(true); }
    this.onIgnoreAll = function() { this.onProcessAll(false); }
    
    this.onProcessAll = function(pChange) {
        var isChanging = pChange || false;
        var c_corrections = this.corrections.length;
		var cur = this.corrections[this.current];
		if ( this.current < c_corrections ) {
		    var currentWord = this.text.substr( parseInt(cur.offset), parseInt(cur.word.length) );
		    for ( var i = this.current + 1; i < c_corrections; i++ ) {
				var corr = this.corrections[i];
				if ( ! this.ignore[i] && this.text.substr( parseInt(corr.offset), corr.word.length ) == currentWord ) {
                    if (isChanging) this.changeWord(i);
				    this.ignore[i] = true;
				}
		    }
		    this.nextWord();
		}
    }

	this.isIgnoredWord = function(pStr) {
		for (var g=0; g< this.ignore.length; g++) {
			if (this.ignore[g]==pStr) return true;
		}
		return false;
	}

    this.onKeyPressWord = function( evt ) {	
		if (evt == null) evt = window.event; 
		if (evt.keyCode == 13) {
			this.onChange();
			return false;
		}
    }

    this.nextWord = function() {
		while ( this.current++ < this.corrections.length && this.ignore[this.current] )
			;
		this.update();
    }
    
    this.setEditor = function( editBox, id ) {
    	SpellController.debug("setEditor()");
		this.editBox = editBox;
        switch (editBox.tagName.toUpperCase()) {
            case "IFRAME": //what?
			    this.editDoc = editBox.contentWindow.document;
			    this.editContent = this.editDoc.body;
                break;
		    case "TEXTAREA":
            case "INPUT": //should check for type = text
       			this.editDoc = editBox;
	       		this.editContent = editBox;
            	this.isText = true;
                break;
		    default:
			    SpellController.throwExeception(e.message);
		}
		self.trapFocus(true);
	}

    /*	@returns void  
     *	@description sets focus / unfocus to the textarea element
     *  @param (boolean) pTrapping: toggles the click event
     */
	this.trapFocus = function(pTrapping) {
        // SpellController.debug("trapFocus() event set for \"click\" event, addListener: " + pTrapping);
        
		if (null != SpellController.getSearchInput()) {
			if (pTrapping) {
				YAHOO.util.Event.addListener(SpellController.getSearchInput(), "click", function() { SpellController.pause(); } );
			}
			else {
				YAHOO.util.Event.addListener(SpellController.getSearchInput(), "click", function() { SpellController.pause(); } );
			}
		}
	}

    /*  @description set focus
     *  @param (boolean) pTrapping: toggles the click event
     */
	this.toggleSpellchecking = function(isEnabled) {
		// if true == enable spelling
		// else false == disable spelling
		
		this.isSpellchecking = isEnabled || false; // spell checking is disabled
		var done_action = document.getElementById(SpellController['UI']['TOGGLE_MODE_BUTTON']);
        
        if (isEnabled) self.trapFocus(isEnabled);
		
		try {
			// start spellcheck
			if (isEnabled) {
				SpellController.toggleMessage(null,false);
				done_action.innerHTML = SpellController['UI']['DONE_COMMAND']; // set to DONE label
			}
			// pause spellcheck
			else {
				SpellController.toggleMessage("SPELL_DISABLED", true);
				done_action.innerHTML = SpellController['UI']['RESUME_COMMAND'];
			}
		}
		catch (e) {
			SpellController.throwException(e.message);
		}
		if (isEnabled) this.spellTimer = setTimeout(SpellController.restart,700); //let's start again
	
	}
    
    /*  @description enable spellchecking tool
     */
	this.enableSpellchecking=function() { this.toggleSpellchecking(true); }
    
    /*  @description disable spellchecking
     */
	this.disableSpellchecking=function() { this.toggleSpellchecking(false); }
	
	this.offsetDelta = function( theText, offset )	{
		var i = 0;
		var count = 0;
		if ( offset >= this.lastIndex ) {
			i = this.lastIndex;
			count = this.lastDelta;
		}
		var len = Math.min( offset, theText.length );
		while ( i < len ) {
			if ( theText.charCodeAt( i ) == 13 ) {
				count++;
			}
			i++;
		}		
		this.lastIndex = i;
		this.lastDelta = count;
		return count;
	}

    /*	@returns boolean  
     *  @description DEPRECATED
     *  @param (String) word that is being checked
     */
	this.isMisspelled =function(pStr) {
		var _misspelled_words = SpellController.getSearchObject();
		var _words = SpellController.getSearchInput().value;
		for (var j=0; j<_misspelled_words.length; j++) {
			for (var i=0; i<_words.length; i++) {
				if (_misspelled_words[j] == _words[i]) return true;
			}
		}
		return false;
	}

    /*  @description run through the words and checks for misspellings
     */
	this.update = function() {
		var theDoc = this.editDoc;
		var word = document.getElementById( SpellController['UI']['WORD_ELEMENT'] ); //input id="word"
		var suggSelect = document.getElementById( SpellController['UI']['SUGGESTIONS_ELEMENT'] ); //suggestions list box
    	if (null != this.corrections && this.current < this.corrections.length) {
            var cur = this.corrections[this.current];
		    this.editDoc.value = this.text;

        	var _words = SpellController.getSearchInput().value;
        	
        	this.textInitPos = _words.indexOf(cur.word,this.textInitPos);
   			this.textEndPos = parseInt(this.textInitPos) + parseInt(cur.word.length);   				
   			this.highlightWord();
			
			// reset suggestions array
		    suggSelect.options.length = 0; //reset suggestions list
		    var n = cur.suggestions.length;
		    // if NO suggestions, then tell user that they're hosed
		    if ( n == 0 ) {
				word.value = this.text.substr(cur[i].offset, cur[i].word.length);
				suggSelect.options[0] = new Option( SpellController['UI']['NO_SUGGESTIONS'], "", true, true );
		    } 
            else { // suggestions found!
				word.value = cur.suggestions[0];
				for (var i = 0; i < n; i++) {
                    var w = cur.suggestions[i]
				    suggSelect.options[i] = new Option( w, w, (i == 0), (i == 0));
			    }
			    suggSelect.selectedIndex = 0;
	        }
	    } 
        else { // no spelling corrections needed
		    if (null != this.text && "" != this.text) {
			    if ( !this.isText ) { // should never go here. it's plain text
            	    this.editContent.innerHTML = this.text;
			    }
                else {
				    this.editDoc.value = this.text;
			    }
		    }
			var msg = (this.corrections.length > 0) ? "NO_MORE_MISSPELLINGS" : "NO_MISSPELLINGS";
    		SpellController.toggleMessage(msg,true);
	    	SpellController.disableItem(SpellController['UI']['CHANGE_BUTTON'],true);
		    SpellController.disableItem(SpellController['UI']['IGNORE_BUTTON'],true);
	    }
    }

	this.highlightWord = function() {
		var ua = navigator.userAgent.toLowerCase();
		if (ua.indexOf("msie") != -1) {
			var selectedWord = this.editBox.createTextRange();
			if (null != selectedWord) {
				var adjustedStart = this.textInitPos - this.offsetDelta(this.text,this.textInitPos);
				selectedWord.collapse(true);
				selectedWord.moveStart("character",adjustedStart);
				selectedWord.moveEnd("character",(this.textEndPos - this.textInitPos));
			}
			selectedWord.scrollIntoView();
			selectedWord.select();
		}
		else {
			if (this.textEndPos > this.textInitPos > 0) {
   				this.editBox.selectionStart = this.textInitPos;
   				this.editBox.selectionEnd = this.textEndPos;
				this.editBox.focus();
			}
   		}
	}

    /*  @returns void
     */
    this.changeWord = function( index ) {
		var newText = "";
		var w = document.getElementById(SpellController['UI']['WORD_ELEMENT']).value;
		var cur = this.corrections[index]; //get the string to replace
		newText += this.text.substr( 0, parseInt(this.textInitPos) ); //get everythign before the word
		newText += w; //this is the value to replace with
		newText += this.text.substr( parseInt(this.textInitPos) + parseInt(cur.word.length), 
									 parseInt(this.text.length) - (parseInt(this.textInitPos) + parseInt(cur.word.length)) );
		this.adjustOffsets( parseInt(w.length) - parseInt(cur.word.length), (parseInt(index) + 1) );
		this.text = newText;
    }

	
    /*  @returns void
     *  @description adjusts for carraige returns across diff. browsers and platforms ?
     */
    this.adjustOffsets = function( delta, start ) {
		for (var i = start; i < this.corrections.length; i++) {
            var cur = this.corrections[i];
		    var tmpNum = parseInt(cur.offset);
		    cur.offset = tmpNum + delta;
		}
    }
}

/**
 * SpellController Helper 
 * @returns void
 **/
YAHOO.search.answers.spellcheck.SpellController = {
	UI : {
	
		// function types
		FUNCTION_ATTACH_INIT : "function_on_init",
		FUNCTION_ATTACH_EXIT : "function_on_exit",
	
		// system messages
    	NO_SUGGESTIONS : "No Suggestions",
		NO_MORE_MISSPELLINGS : "No more misspellings",
		NO_MISSPELLINGS : "No misspellings found",
		SPELL_DISABLED : "Spelling disabled, click Resume to continue",
		
		// element IDs
        ANCHOR_INIT_SPELLCHECK_ELEMENT : "anchor_init_spellcheck",
        SPELLCONTROLLER_ELEMENT : "spellcontrol",
        SPELLBOX_ELEMENT : "spellbox",       
        SPELLMESSAGE_ELEMENT : "spellmsg",         
        SUGGESTIONS_ELEMENT : "suggestions",
        WORD_ELEMENT : "word",
        CORRECTION_ELEMENT: "correction",
        IFRAME_PROXY_ELEMENT: "iframeproxy",
        BUTTON_BOX_ELEMENT: "btnbox",
        SELETION_BOX_ELEMENT: "slbox",
        DONE_BUTTON : "doneButton",
		CHANGE_BUTTON : "changeButton",
		CLOSE_BUTTON : "closeButton",
        IGNORE_BUTTON : "ignoreButton",
        
		// Action and Label descriptors
		CHANGE_LABEL : "Change to:",
		SUGGESTION_LABEL: "Suggestions:",        
        
        // Command Labels
		DONE_COMMAND : "Done",
		CHANGE_COMMAND : "Change",
		IGNORE_COMMAND : "Ignore",
		CLOSE_COMMAND : "Close",
		RESUME_COMMAND : "Resume",		
		CHANGE_ONE_ITEM_COMMAND : "Change this word",
		CHANGE_ALL_ITEM_COMMAND : "Change all occurrences",
		IGNORE_ONE_ITEM_COMMAND : "Ignore this word",
		IGNORE_ALL_ITEM_COMMAND : "Ignore all occurrences",
		
		COLOR_DISABLED_ELEMENT : "#999",
		COLOR_ENABLED_ELEMENT  : "#000",
        
        SPELLCHECK_REQUEST_HANDLER : "/common/util/ks-spellcheck.php",
        
        HACK_ELEMENT_OFFSET : 2, // the window becomes 2 pixels bigger
        
        IMG_LOADING : '<img src="http://us.i1.yimg.com/us.yimg.com/i/us/pim/dclient/img/md5/c8ad9845c9414424cb5854238af212b0_1.gif" style="border:none;">'
	},
	
	oldHeight : -1,
	
	getUserAgent : function() { return navigator.userAgent.toLowerCase(); },
	
    getSpellerObject : function () { if (this.speller) return this.speller; return null; },
    setSpellerObject : function (pObj) { this.speller = pObj; },
    
    getSearchInput : function () { if (this.searchInput) return this.searchInput; return null; },
    setSearchInput : function (pObj) { this.searchInput = pObj; },
    
    initFunction : null,
    exitFunction : null,
    
    debug : function(pStr) { if (Util) Util.debug(pStr); },
    throwException : function(pStr) {
    	//arguments.caller.name
		SpellController.debug("EXCEPTION(): " + pStr);
    },    
    
    isPaused : false,
    getIsPaused : function() { return SpellController.isPaused; },
    setIsPaused : function(pBool) { SpellController.isPaused = pBool; },
    
	/*  @returns boolean
     *  @description which browsers do we NOT support
     */
    isFilteredBrowser : function() {
	    var ua = navigator.userAgent.toLowerCase();
            if (
        		(ua.indexOf("opera") != -1) ||
                // (ua.indexOf("firefox/1.0.") != -1) ||
                // (ua.indexOf("safari") != -1) ||
        		(ua.indexOf("msie 5.") != -1)
    		) 
        {
		    return true;
	    }
	    return false;
    },
	
	/*  @returns boolean
     *  @description which browsers should use the iframe-powered remote scripting
     */
    isIframePoweredBrowser : function() {
	    var ua = navigator.userAgent.toLowerCase();
            if (
        	    false // use iframes for these browsers
    		) 
        {
		    return true;
	    }
	    return false;
    },
	
	doHandleCallback : function() {
	    SpellController.initController(arguments[0], arguments[1], arguments[2]); 
	},
	
	setFunction : function(pFunction,pEventName) {
		if ("function" == typeof pFunction && null != pEventName) {
			if (SpellController['UI']['FUNCTION_ATTACH_EXIT'] == pEventName.toLowerCase()) {
				this.exitFunction = pFunction;
			}
			else if (SpellController['UI']['FUNCTION_ATTACH_INIT'] == pEventName.toLowerCase()) {
				this.initFunction = pFunction;
			}
		}
	},
	
	
	/*  @returns void
     *  @description 
     */
    init : function (pInputField,pForm) {
    	//don't let these user-agents access the spell-check wil we can fix
        if (SpellController.isFilteredBrowser()) return;
        
        //should we use an iframe for remote scripting?
        var isUsingIframe = SpellController.isIframePoweredBrowser();
        
        if (document.getElementById && document.createElement) { 
            document.writeln(SpellController.writeSpellcheckerButton(pInputField,pForm,isUsingIframe));
        }
    },
    
	/*  @returns (String)
     *  @description which browsers should use the iframe-powered remote scripting
     */
    writeSpellcheckerButton : function (pInputField,pForm,isUsingIframe) {    
        var s = '';
        s += '<a id="' + SpellController['UI']['ANCHOR_INIT_SPELLCHECK_ELEMENT'] + '" ';
        s += ' class="check_spelling_icon" href="javascript:void(0);" title="Check your spelling before submitting!" ';
        s += ' onclick="SpellController.start(\'' + pInputField + '\',document.' + pForm + ',' + isUsingIframe +'); return false;" ';
        // s += ' onfocus="javascript:this.blur();"
        s += '>';
        s += '<span style="font-size:88%;">Check Spelling</span></a>';
        s += '<span style="font-size:100%;">&nbsp;</span>'; //hack for UI stability
        return s;    
    },
    
    pause : function() {
    	var _speller = SpellController.getSpellerObject();
    	if (null != _speller) {
    		_speller.disableSpellchecking();
			if ( null != _speller.corrections ) {
				_speller.current = _speller.corrections.length;	// jump to the end
				_speller.update();
				_speller.setText(null); //reset
			}
		}
    },
    
    restart : function() {
    	if (null != SpellController.initFunction) SpellController.initFunction();
    	SpellController.debug("restart()");
    	SpellController.loadDisplay();
        var searchStr = SpellController.getSearchInput();
        //set new search string
        try { SpellController.setSearchInput(searchStr); }
        catch(e) { SpellController.throwException(e.message); }
        
        SpellController.fetch();
    },
    
    start : function( pId, pForm, pIsUseIframe ) {
    	if (null != SpellController.initFunction) SpellController.initFunction();
        var isUseIframe = pIsUseIframe || false; //SpellController.isIframePoweredBrowser();
        SpellController.debug("start()");
        if (null == SpellController.getSearchInput()) {
            try { SpellController.setSearchInput(eval("document." + pForm.name + "." + pId)); }
            catch(e) { SpellController.throwException(e.message); }
        }
        
		//if iframe-powered, then let's create
        if (isUseIframe) SpellController.addIframe(SpellController.getSearchInput());
        
		SpellController.fetch();
    },
    
    fetch : function() {
        try { SpellController.addDisplay(SpellController.getSearchInput());	}
		catch(e) { SpellController.throwException("could not add display");	}
		
        try { SpellController.getSuggestions(); } 
        catch(e) { SpellController.throwException("could not retrieve suggestions via ajax"); }
        
        SpellController.debug("fetch()");
    },
    
    showError : function(pErrMessage) {
        var eleInstance = document.getElementById(SpellController['UI']['SPELLCONTROLLER_ELEMENT']);
        var errStr='<span style="padding:2px 5px; color:red;">' + oAnswers.translations['SPELLCHECKER_ERROR'] + '</span>';
        if (null != eleInstance && "" != eleInstance) eleInstance.innerHTML = errStr;
    },
    
    addIframe : function(pParentNode) {
        var eleInstance = document.getElementById(SpellController['UI']['IFRAME_PROXY_ELEMENT']);
        if (document.createElement && (null == eleInstance || "undefined" == eleInstance)) {
            try {
            	var ele = document.createElement( "IFRAME" );
                ele.setAttribute( "id", SpellController['UI']['IFRAME_PROXY_ELEMENT'] );
                ele.setAttribute( "src", "about:blank" );
                ele.setAttribute( "style", "position:relative; top:0; left:0; width:1px; height:1px; display:none;" );
                pParentNode.parentNode.insertBefore( ele, pParentNode );
            }
            catch(e) {
                SpellController.throwException(e.message);
            }            
        }
        SpellController.debug("created IFRAME success");
    },
    
    // evaluate / create the Speller Object
    setSpeller : function(pData) {
        try {
            if (typeof pData == "string") {
                var tmpData = "SpellController.setSpellerObject(new Speller(" + pData.replace( /<\!--.*-->/g, "" ) + "))";    
                eval(tmpData);
            }
            else if (typeof pData == "object") {
                SpellController.setSpellerObject(new Speller(pData));
        	}
        } 
        catch(e) {
            SpellController.throwException(e.message);
        }
        return;
    },
    
    getSuggestions : function() { 
        // var dd = document.domain;
        // if (dd.toLowerCase().indexOf("yahoo.com") != -1) document.domain = "yahoo.com";
        var iformat = "text";
        var oformat = "js";
        var str = SpellController.getSearchInput().value;
        var uri = SpellController['UI']['SPELLCHECK_REQUEST_HANDLER'];
        	uri+= "?text=" + encodeURI(str) + "&iformat=" + iformat + "&oformat=" + oformat + "&lang=" + YAHOO.search.answers.application.locale;	      
        if (SpellController.isIframePoweredBrowser()) { //should never be true
            try {
                var ifr = document.getElementById(SpellController['UI']['IFRAME_PROXY_ELEMENT']);
                ifr.src = uri + "&iframe=1";
            }
            catch (e) {
                SpellController.throwException("get iframe is NULL: " + e.message);
            }
        }
        else {
            SpellController.doAjaxRequest(uri);
        }
        SpellController.debug("getSuggestions()");
    },
    
    doAjaxResponseSuccess : function(pResponse) {
	    this.initController(pResponse.responseText,pResponse.status,pResponse.tId);
    },
    
    doAjaxResponseFailure : function(pResponse) {
    	SpellController.debug("doAjaxResponse(): failure");
    },
    
	doAjaxResponse : { 
    	// scope : this,
    	success : function(response) { SpellController.doAjaxResponseSuccess(response) }, 
    	failure : function(response) { SpellController.doAjaxResponseFailure(response) },
    	timeout : 5000
    },
    
    doAjaxRequest : function (pUri) {
        var spellcheck_ajax = null;
        try { // do remote call
        	oAnswers.util.Ajax.request(pUri,this.doAjaxResponse);
        	//spellcheck_ajax = YAHOO.search.answers.util.Ajax.getInstance();
            //ygConn.http.asyncRequest( spellcheck_ajax, 'GET', pUri, false, pCallback, null );
        }
        catch(e) {
            SpellController.throwException("can't do async call: " + e.message);
            SpellController.showError();
        }
        finally {
        	spellcheck_ajax = null;
        }
    },
    
	doToggleResumeOrFinish : function(evt) {
		if (null == evt) evt = window.event; 
		var ele = (evt.target) ? evt.target : evt.srcElement;
		if (SpellController['UI']['DONE_COMMAND']==ele.innerHTML) {
			SpellController.finish();
		}
		else {
			SpellController.resume();
		}
	},

	resume : function() {	
        var _speller = SpellController.getSpellerObject();
    	if (null != _speller && "undefined" != _speller) {
    		SpellController.setSpellerObject(null); // set as empty
    	}
    	this.spellTimer = setTimeout(function() { SpellController.restart(); },700);
	},

    finish : function () {
		// SpellController.debug(arguments.callee.name + "()");
        var _speller = SpellController.getSpellerObject();
    	if (null != _speller) {
			if ( null != _speller.corrections ) {
				_speller.current = _speller.corrections.length;	// jump to the end
				_speller.update();
				_speller.setText(null); //reset
			}
    		SpellController.hideController(SpellController['UI']['SPELLCONTROLLER_ELEMENT']);
    		SpellController.setSpellerObject(null); // set as empty
    	}
    	if (null != SpellController.exitFunction) SpellController.exitFunction();
    	SpellController.showDisplay(false);
    },	
    
    // Spelling stuff
    initController : function() {
    	var _search_term = SpellController.getSearchInput(); //form input element
        var message = null;
    	try {
            SpellController.setSpeller(arguments[0]);
	        SpellController.debug("initController()" + arguments[0]);
    	} 
        catch (e) {
    		if (e.message.toLowerCase().indexOf("syntax error") != -1 ) {
    			SpellController.setSpeller(new Speller([])); // WHY?
    		}
    		SpellController.throwException(e.message);
    	}
    	//if (null==args) args=[0]; //initialize args? why?
   		if (null != SpellController.getSpellerObject()) {
   			SpellController.getSpellerObject().setText(SpellController.getSearchInput().value);
    	}
    	
    	SpellController.showController(_search_term);
    	if (null != SpellController.getSpellerObject()) {
            SpellController.getSpellerObject().setEditor( _search_term, arg=[0] );
        	SpellController.getSpellerObject().update();
        }
        SpellController.debug("initController()");
    },
    
	addController : function( pEle ) {
		var ele = document.getElementById(pEle);
		var _selectMenuSize = 3;
		var ua = navigator.userAgent.toLowerCase();
        if (ua.indexOf("safari") != -1) _selectMenuSize = 2;
		var html = "";
		html += '<div id="' + SpellController['UI']['SPELLBOX_ELEMENT'] + '" class="clearfix">';
			html += '<div id="btnbox" class="first">';
				html += '<div id="' + SpellController['UI']['SPELLMESSAGE_ELEMENT'] + '" style="display:none"></div>';
				html += '<div id="' + SpellController['UI']['CORRECTION_ELEMENT'] + '"><label for="' + SpellController['UI']['WORD_ELEMENT'] + '">' + SpellController['UI']['CHANGE_LABEL'] + '&nbsp;</label>';
                html += '<input id="' + SpellController['UI']['WORD_ELEMENT'] + '" onkeypress="SpellController.getSpellerObject().onKeyPressWord(event)" /></div>';
				html += '<button id="' + SpellController['UI']['CHANGE_BUTTON'] + '" class="hasdefaultstate" type="button" value="' + SpellController['UI']['CHANGE_COMMAND'] + '" onclick="SpellController.changeClick(event)">' + SpellController['UI']['CHANGE_COMMAND'] + '</button>';
				html += '<button id="' + SpellController['UI']['IGNORE_BUTTON'] + '" class="hasdefaultstate" type="button" value="' + SpellController['UI']['IGNORE_COMMAND'] + '" onclick="SpellController.ignoreClick(event)">' + SpellController['UI']['IGNORE_COMMAND'] + '</button>';
				html += '<button id="' + SpellController['UI']['TOGGLE_MODE_BUTTON'] + '" type="button" value="' + SpellController['UI']['CLOSE_COMMAND'] + '" onclick="SpellController.doToggleResumeOrFinish(event)">' + SpellController['UI']['DONE_COMMAND'] + '</button>';
			html += '</div>';
			html += '<div id="slbox">';
				html += '<label id="sugglabel" for="' + SpellController['UI']['SUGGESTIONS_ELEMENT'] + '">' + SpellController['UI']['SUGGESTION_LABEL'] + '&nbsp;</label>';
				html += '<select id="' + SpellController['UI']['SUGGESTIONS_ELEMENT'] + '" size="' + _selectMenuSize + '" onchange="SpellController.onChangeSuggestions()"></select>';
			html += '</div>';
		html += '</div>';
        
        ele.innerHTML = html;
        
		/* put to rest for now
		html += '<div id="changemenu" class="buttonmenu" container="' + ele.id +'">';
		    html += '<strong>Change Options</strong>';
		    html += '<ul>';
		        html += '<li value="0">' + SpellController['UI']['CHANGE_ONE_ITEM_COMMAND'] + '</li>';
		        html += '<li value="1">' + SpellController['UI']['CHANGE_ALL_ITEM_COMMAND'] + '</li>';
		    html += '</ul>';
		html += '</div>';
		
		html += '<div id="ignoremenu" class="buttonmenu" container="' + container.id +'">';
		    html += '<strong>Change Options</strong>';
		    html += '<ul>';
		        html += '<li value="0">' + SpellController['UI']['IGNORE_ONE_ITEM_COMMAND'] ) + '</li>';
		        html += '<li value="1">' + SpellController['UI']['IGNORE_ALL_ITEM_COMMAND'] ) + '</li>';
		    html += '</ul>';
		html += '</div>';
		
        //var oChangeMenu = MenuButton( SpellController['UI']['CHANGE_COMMAND'], SpellController.changeClick, 'changemenu', SpellController.changeMenuClick );
		//var oSkipMenu = MenuButton( SpellController['UI']['IGNORE_COMMAND'], SpellController.ignoreClick, 'ignoremenu', SpellController.ignoreMenuClick );
		*/
		
	},
	 	 
	showController : function(pEditBox) { // object reference
		var editBox = pEditBox;
		var spellBox = document.getElementById(SpellController['UI']['SPELLBOX_ELEMENT']);
		if (null == spellBox || "undefined" == spellBox) {
			SpellController.addController(SpellController['UI']['SPELLCONTROLLER_ELEMENT']);
			spellBox = document.getElementById(SpellController['UI']['SPELLBOX_ELEMENT']);
		}
		if (null != spellBox) {
			spellBox.style.display = "block";

			if (null != editBox && "undefined" != editBox) {
				if (-1 == this.oldHeight) {
					this.oldHeight = parseInt(editBox.clientHeight);
					this.editBox = editBox;
                    var newHeight = (parseInt(editBox.clientHeight) - parseInt(spellBox.offsetHeight) + SpellController['UI']['HACK_ELEMENT_OFFSET']);
					//alert(editBox.id + " - ||| - " + newHeight);
					//editBox.height = newHeight + "px";
				}
				// If it's a TEXTAREA, the user may have set the size.  We need to match that.
				if ( editBox.tagName.toUpperCase() == "TEXTAREA" || 
					(editBox.tagName.toUpperCase() == "INPUT" && editBox.type.toUpperCase() == "TEXT") ) {
					// don't do it for IE cause it causes the dropdown to lay on top of the editbox
                    if ( !(this.getUserAgent().indexOf("msie") != -1) ) {
                        this.setBoxWidth( editBox, spellBox );
	                }
    			}
			}
			this.toggleMessage(null,false);
			// Make sure everything is enabled!
			this.enableItem( SpellController['UI']['CHANGE_BUTTON'] );
			this.enableItem( SpellController['UI']['IGNORE_BUTTON'] );
			this.enableItem( SpellController['UI']['TOGGLE_MODE_BUTTON'] );
			this.enableItem( SpellController['UI']['WORD_ELEMENT'] );
			this.enableItem( SpellController['UI']['SUGGESTIONS_ELEMENT'] );
		}
	},

    showDisplay : function( pIsEnabled ) {
        var ele = document.getElementById(SpellController['UI']['SPELLCONTROLLER_ELEMENT']);
        ele.style.display = (pIsEnabled) ? "block" : "none";
        SpellController.debug("showDisplay(" + pIsEnabled.toString() + ")");
    },

    addDisplay : function(pParentNode) {
        var eleName = SpellController['UI']['SPELLCONTROLLER_ELEMENT'];
        var eleInstance = document.getElementById(eleName);
        if (document.createElement && (null == eleInstance || "undefined" == eleInstance)) {
            try {
            	var ele = document.createElement("DIV");
                ele.setAttribute("id", eleName);
                ele.setAttribute("style", "position:relative; top:0; left:0; width:350px!important; display:block;");
                ele.setAttribute("class", "clearfix");
                pParentNode.parentNode.insertBefore(ele, pParentNode);
                SpellController.setBoxWidth(pParentNode, ele);
            }
            catch(e) {
                SpellController.throwException(e.message);
            }
        }
        SpellController.loadDisplay();
    	SpellController.debug("addDisplay()");
    },
    
    loadDisplay : function() {
    	var ele = document.getElementById(SpellController['UI']['SPELLCONTROLLER_ELEMENT']);
    	ele.innerHTML = SpellController['UI']['IMG_LOADING'];
    	SpellController.showDisplay(true);
    	SpellController.debug("loadDisplay()");
    },
    
    /*  @returns void
     *  @description set the width of the input box to a width set in the object
     *
     */
	setBoxWidth : function( editBox, spellBox ) {
		// We only need to do this once...
		if (null != spellBox.getAttribute("width_set")) return;
		
		var width = editBox.offsetWidth;
		spellBox.style.width = width.toString() + "px";
        
		// You'd think that since we've set the width, we're done!
		// But the W3C in its infinite wisdom won't set the width
		// the the value you asked for!  We need to see what width
		// we ended up with and subtract any offsets that were added in...
		var delta = (spellBox.offsetWidth - width);
		if (0 != delta) {
			width -= delta;
			spellBox.style.width = width + "px";
		}
		
		var btnbox = document.getElementById( "btnbox" );
		var slbox = document.getElementById( "slbox" );

		if ( btnbox != null && slbox != null ) {			
			var delta = (width - (btnbox.offsetWidth + slbox.offsetWidth)) / 2;
			var word = document.getElementById(SpellController['UI']['WORD_ELEMENT']);
			var suggestions = document.getElementById(SpellController['UI']['SUGGESTIONS_ELEMENT']);
			
			if (delta > 0 && null != word) {
				word.style.width = (word.offsetWidth + delta) + "px";
			}
			
			if (null != suggestions) {
				suggestions.style.width = (suggestions.offsetWidth + delta) + "px";
			}
		}
		spellBox.setAttribute( "width_set", "1" );
	},
	
    /*  @returns void
     *  @description set the height of the input box to a height saved (this.oldHeight)
     *
     */
	hideController : function( id ) {
		var ele = document.getElementById(SpellController['UI']['SPELLBOX_ELEMENT']);
		if (null != ele) {
			if ( this.editBox != null && this.oldHeight != -1 ) {
				 this.editBox.style.height = this.oldHeight + "px";
				 this.oldHeight = -1;
			}
			ele.style.display = "none";
		}
	},
    
    /*  @description enable an element / button
     *
     */
	enableItem : function( pId ) {
    	SpellController.disableItem(pId, false);
	},
	
    /*  @description disable an element / button
     *
     */
	disableItem : function(pId, isDisabled) {
    	var _color = (isDisabled) ? SpellController['UI']['COLOR_DISABLED_ELEMENT'] : SpellController['UI']['COLOR_ENABLED_ELEMENT'];
    	var ele = document.getElementById(pId);
    	if (null != ele) {
    		ele.disabled = isDisabled;
    		ele.style.color = _color;
    	}
	},
	
    ignoreClick : function(evt) {
		if ( evt == null )  evt = window.event; 
        var mainWidth = parseInt( this.offsetWidth );
        mainWidth -= 22;
        var nOffsetX = (evt.layerX) ? (evt.layerX) : evt.offsetX;
        
        if ( nOffsetX > mainWidth ) {
            var leMenu = this.Menu;
            if ( leMenu != null ) {
    			leMenu.style.zIndex = 100;
                leMenu.Show();
    			leMenu.hideCB = SpellController.getSpellerObject().hideShim;
    			showIFrameShim( leMenu );
            }
        } 
        else {
            SpellController.getSpellerObject().onIgnore();
        }
    },

    changeClick : function(evt) {
		if ( evt == null )  evt = window.event; 
        var mainWidth = parseInt( this.offsetWidth );
        mainWidth -= 22;
        var nOffsetX = (evt.layerX) ? (evt.layerX) : evt.offsetX;
        
        if ( nOffsetX > mainWidth ) {
            var leMenu = this.Menu;
            if ( leMenu != null ) {
    			leMenu.style.zIndex = 100;
                leMenu.Show();
    			leMenu.hideCB = speller.hideShim;
    			//showIFrameShim( leMenu );
            }
        } 
        else {
            SpellController.getSpellerObject().onChange();
        }
    },

    /*  @description set the suggestion text field to the selected option from the suggestions list
     *
     */
    onChangeSuggestions : function() {
		var aSuggestions = document.getElementById(SpellController['UI']['SUGGESTIONS_ELEMENT']); //drop-down list box
		var s = aSuggestions.options[aSuggestions.selectedIndex].value;
		if ( s != "" ) document.getElementById(SpellController['UI']['WORD_ELEMENT']).value = s;
		SpellController.getSpellerObject().highlightWord();
    },
	
    /*  @description set the message for this SpellController widget
     *
     */	
    toggleMessage : function(pMsg,pBool) {
        var sDisplayStyle = (pBool) ? "none" : "block";
        var msg_display = document.getElementById( SpellController['UI']['SPELLMESSAGE_ELEMENT'] );
        if (null != msg_display) {
            if (pBool && null != pMsg) msg_display.innerHTML = SpellController['UI'][pMsg];
            msg_display.style.display = (pBool) ? "block" : "none";
            
            var ele = null;
            ele = document.getElementById( "correction" );
          	    if ( ele != null ) ele.style.display = sDisplayStyle; 
            ele = document.getElementById( "sugglabel" );
         		if ( ele != null ) ele.style.display = sDisplayStyle;
            ele = document.getElementById( SpellController['UI']['SUGGESTIONS_ELEMENT'] );
        		if ( ele != null ) ele.style.display = sDisplayStyle;
        }
    }
}

var oAnswers =				YAHOO.search.answers;
var oCache = 		        oAnswers.cache;
var oProfile = 		        oAnswers.profile;
var oRelationships = 		oAnswers.relationships;
var oLogger = 				oAnswers.application.logger;
var SpellController = 		oAnswers.spellcheck.SpellController;
var Speller = 				oAnswers.spellcheck.data.Speller;
 
/* @requires KS_Util (instance name: Util)
 * @returns array
 */
function KS_infoLayer(pId,pDivId,pDivAuxId,pNotepad,pOffsetTop,pIncentiveEvents,pX,pY) {
    this.id=pId;
    this.window_url=location.href.toLowerCase();
    this.isD=(this.window_url.indexOf("5555")!=-1 || this.window_url.indexOf("6666")!=-1 || this.window_url.indexOf("7777")!=-1); 
    this.e=document.getElementById(pDivId);
    this.aux_e=document.getElementById(pDivAuxId);
    this.notepad=document.getElementById(pNotepad);
    this.offsetX=pX || 0;
    this.offsetY=pY || 0;
    this.move_handler=null;
    this.parentOffsetY=parseInt(pOffsetTop) || 0;
    this.incentive_events=pIncentiveEvents || [];
    this.notification_count=0;
    this.TIME_DELAY=0.7;
    this.ELEMENT_WIDTH=300;
    this.ELEMENT_HEIGHT=this.parentOffsetY; //minimum height of the element
    this.TIMEOUT_IN_SECONDS=10;
    this.STATES=new Array(
        '',
'You get 100 points to start',
'Thanks for visiting! (1 point)',
'You asked a question (-5 points)',
'Asking a question anonymously',
'Neglecting my question',
'You chose a best answer (3 points)',
'You answered a question (2 points)',
'Deleted an answer (-2 points)',
'Your answer was picked as best! (10 points)',
'You voted for a best answer (1 point)',
'You rated a best answer (1 point)',
'Evaluated with excellence!',
'Honorable contribution',
'A violation in a question',
'A violation in an answer',
'A violation in a comment',
'A best answer is considered a violation',
'Other naughty things',
'Thumbs-up for your best answer! (1 point)',
'You chose to call a vote',
'Maximum awards for answer evaluated as positive',
'Number of events to keep in history per user',
'',
'Your question had no best answer (5 points)'
    );
}

KS_infoLayer.prototype.timeoutAndDisappear=function(){
    var self=this;
    setTimeout(function(){ self.moveUp() },(self.TIMEOUT_IN_SECONDS * 1000));
}

KS_infoLayer.prototype.doCorrectPos=function() {
    // var someXY = this.setInitialPos();
}

/* @returns void 
    set home coordinates */
KS_infoLayer.prototype.setCoordinates=function(pXY) {
    this.setPos(this.getPos(this.e));
    this.setPos(this.getPos(this.aux_e));
}

/* @returns array */
KS_infoLayer.prototype.getPos=function(pEle){ return ygPos.getPos(pEle || this.e);}

/* @returns void
    store the x,y position of the element */
KS_infoLayer.prototype.setPos=function(pXY){ this.offsetX=pXY[0]; this.offsetY=pXY[1]; }
    
/* @returns void */    
KS_infoLayer.prototype.init=function(){
    var g = Util.gObj('y-ks-info-static-user-layer');
    //this.setCoordinates();
    
    if (this.incentive_events.length > 0) {
        var s = this.parseAndAggregateEvents();
        if (s.length > 0) {
            this.insertText(s);
            // Util.gObj('y-ks-info-layer-menu-layer-notify-count').innerHTML = " ("+ this.notification_count.toString() +")";
            this.moveDown();
            this.timeoutAndDisappear();
            
        }
        this.resetCounter();
    }
}

KS_infoLayer.prototype.resetCounter=function() { this.notification_count=0; }

KS_infoLayer.prototype.show=function() {
    this.e.style.visibility='visible';
    this.aux_e.style.visibility='hidden';
}

KS_infoLayer.prototype.hide=function() {
    this.e.style.visibility='hidden';
    this.aux_e.style.visibility='visible';
}

KS_infoLayer.prototype.getPointsFromLoggingIn=function() {
    var c_events = this.incentive_events.length;
    var count = 0;
    for (var cpe=0; cpe < c_events; cpe++) {
        if (parseInt(this.incentive_events[cpe].getOid())==2) count++; //the number 2 is a hack
    }
    if (count > 0) this.notification_count++;
    return count;
}

KS_infoLayer.prototype.wrapHTMLToIncentiveEvent=function(pObj,pIsFirst) {    
    s =  '<div class="incentive_event" style="'+((!pIsFirst)?"border-top:1px solid #ccc;":"")+'">';
    s += '<div class="display-point-total">' +pObj.getPoints()+ '</div>';
    s += '<strong>'+((this.isD)?"["+pObj.getOid().toString()+"] ":"")+this.STATES[pObj.getOid()]+ '</strong><br/>';
    s += '<em>(' +pObj.getTime()+ ' ago)</em><br/>';
    s += ("0"!=pObj.getQid()) ? '<p align="right"><a href="/question/index?qid='+pObj.getQid() +'">View Question</a></p>' : '';
    s += '</div>';
    return s;
}

KS_infoLayer.prototype.wrapHTMLToAggregatedIncentiveEvents=function(pCount) {    
    s =  '<div class="incentive_event">';
    //s += '<div class="display-point-total">'+pCount+'</div>';
    s += '<strong>You\'ve earned ' +parseInt(pCount)+ ' point'+ ((pCount==1) ? "" : "s") +'</strong><br/>';
    s += '</div>';
    return s;
}

KS_infoLayer.prototype.parseAndAggregateEvents=function(){
    var s='';                
    var isFirst=true;
    var count=0;
    var c_events = this.incentive_events.length;
    for (var ce=0; ce < c_events; ce++) {
        var obj = this.incentive_events[ce];
        if (parseInt(obj.getOid()) == 23) {
            if (ce == 0) { // it's the first and most recent event
                var tmpUrl = "/my/my?link=question&more=y";
                s += '<div class="new"><strong>Some of <a href="' + tmpUrl + '">your questions</a> need attention!</strong></div>';
                break;
            }
            else {
                continue;
            }
        }
        if (parseInt(obj.getOid())== 1 && !obj.isBruteForceAction()); //filter out the activation
        count += parseInt(obj.getPoints());
        this.notification_count++;
    }
    if (count > 0) s += this.wrapHTMLToAggregatedIncentiveEvents(count);
    return s;
}

KS_infoLayer.prototype.parseAndFormatIncentiveEvents=function(){
    var s='';
    var c_login=this.getPointsFromLoggingIn();
    if (c_login > 0) s+='<div class="incentive_event">You\'ve earned <strong>'+c_login.toString() +'</strong> points from logging in!</div>';
    var c_events = this.incentive_events.length;
    for (var ce=0; ce < c_events; ce++) {
        var isFirst = (ce==0);
        var obj = this.incentive_events[ce];
        if (parseInt(obj.getOid())== 1 && !obj.isBruteForceAction()) continue; //filter out activation events
        s += this.wrapHTMLToIncentiveEvent(obj,isFirst);
        this.notification_count++;
    }
    return s;
}

/* @returns void
 */
KS_infoLayer.prototype.moveUp=function() {
    var h=(this.e.offsetHeight > this.ELEMENT_HEIGHT) ? (-1*(this.e.offsetHeight-this.ELEMENT_HEIGHT)) : 0;
    var self=this;
    var tmpele = Util.gObj('y-ks-info-static-user-layer');
    var someXY = this.getPos(tmpele);

    this.move([someXY[0], h]);
    setTimeout( function() { self.hide() }, 1000 );
    return false;
}

KS_infoLayer.prototype.setInitialPos=function() {
    var tmpele = Util.gObj('y-ks-info-static-user-layer');
    var someXY = this.getPos(tmpele);
    this.setPos(someXY);
    return someXY;
}

/* @returns void
 */
KS_infoLayer.prototype.moveDown=function() {
    var someXY = this.setInitialPos();
    this.show();
    this.move([parseInt(someXY[0]), this.parentOffsetY]);
    Util.debug("setting to: " + parseInt(someXY[0]) + " " + this.parentOffsetY.toString());
    return false;
}


KS_infoLayer.prototype.move=function(pCoord){
    if (null==this.move_handler) {
        this.move_handler=new ygAnim_Move(this.e,this.TIME_DELAY,pCoord);
        this.move_handler.animate();
        this.setCoordinates();
        this.move_handler=null;
    }
}

/* 
 * @returns void
 *   insert text
 */
KS_infoLayer.prototype.insertText=function(pStr) { this.notepad.innerHTML=pStr; }

/* @returns void
 */
KS_infoLayer.prototype.appendText=function(pStr) {
    var t=this.notepad.innerHTML;
    this.notepad.innerHTML=t+pStr+"<br/>";
}

KS_infoLayer.prototype.getWidth=function(){ return this.e.style.width; }
KS_infoLayer.prototype.setIncentiveEventsArray=function(pObj){ this.incentive_events=pObj; }
KS_infoLayer.prototype.getIncentiveEventsArray=function(){ return this.incentive_events; }

/*  @returns void
 *  - add new incentive event to the menu
 */
KS_infoLayer.prototype.addIncentiveEvent=function(pObj) {
    if (typeof pObj == "object") { 
        this.incentive_events[this.incentive_events.length]=pObj;
        this.appendText(this.wrapHTMLToIncentiveEvent(pObj));
    }
    else if (arguments.length >= 5) { //pass in strings to create a new event
        this.incentive_events[this.incentive_events.length]=new KS_Incentive_Event(pKid,pOid,pPoints,pTime,pQid);
        this.appendText(this.wrapHTMLToIncentiveEvent(pObj));
    }
    return;
}

function KS_Incentive_Event(pKid,pOid,pPoints,pTime,pQid,pBruteForceAction){
    this.kid=pKid;
    this.oid=pOid;
    this.points=pPoints;
    this.time=pTime;
    this.qid=pQid;
    this.brute_force=pBruteForceAction || false;
}

KS_Incentive_Event.prototype.getKid=function() { return this.kid; }
KS_Incentive_Event.prototype.setKid=function(pStr) { this.kid=pStr; }
KS_Incentive_Event.prototype.getOid=function() { return this.oid; }
KS_Incentive_Event.prototype.setOid=function(pStr) { this.oid=pStr; }
KS_Incentive_Event.prototype.getPoints=function() { return this.points; }
KS_Incentive_Event.prototype.setPoints=function(pStr) { this.points=pStr; }
KS_Incentive_Event.prototype.getTime=function() { return this.time; }
KS_Incentive_Event.prototype.setTime=function(pStr) { this.time=pStr; }
KS_Incentive_Event.prototype.getQid=function() { return this.qid; }
KS_Incentive_Event.prototype.setQid=function(pStr) { this.qid=pStr; }
KS_Incentive_Event.prototype.isBruteForceAction=function() { return this.brute_force; }

function advancedSearch() {
	var f = Util.gObj("ks-mantle-search-form");
	var l = Util.gObj("ks-mantle-search-advanced-link");
	if(f.p.value.length > 0) {
		var link = l.href;
		var searchTerm = escape(f.p.value);
		if(link.indexOf("?p=") > 0) {
			var re = /p=.*/i;
			link = link.replace(re, "p="+searchTerm);
		} else {
			link = link+"?p="+searchTerm;
		}
		l.href = link;
	}
}

function doCheckMessageForPreview(pForm) {
	var error = false;
	var subject = String.trim(pForm.subject.value);
    
   	if (subject.length == 0) {
   		helpString = "You must enter a subject";
   		Util.displayErrorInfo("messageSubject", helpString, true);
        if (pForm.subject) pForm.subject.focus();
   		error = true;
   	} else {
   		Util.displayErrorInfo("subject", "", false);
   	}
 	
	if(error) window.scroll(0,0);
	return !error;
}

function doCheckMyEditForPreview(pForm) {
	var error = false;
	var nickChoice = Util.getRadioValue(pForm.nick_type);
	var nickString = String.trim(pForm.k_nick.value);
    
    if ("k" == nickChoice.toLowerCase()) {
    	if (nickString.length == 0 || nickString.length > 32) {
    		helpString = "You must enter a nickname with a max of 32 characters";
    		Util.displayErrorInfo("k_nick", helpString, true);
            if (pForm.k_nick) pForm.k_nick.focus();
    		error = true;
    	} else {
    		Util.displayErrorInfo("k_nick", "", false);
    	}
    }
 	
	if (error) window.scroll(0,0);
	if (!error) {
		document.getElementById('profile_create_form_submit').disabled = true;
	}
	return !error;
    // return false;
}

function getElementByName(){
    //void()
}

function doCheckAddEmailAddressForm(pForm) {
	eF = pForm.form_email;
	error = false;

	if(eF) {
		email = String.trim(eF.value);	
		//note: validateEmail function resides in the -qa file, will still work because we're consolidating js files together
		err = validateEmail(email, 1);
		if(err.length > 0) {
			helpString = "Please enter a valid email address";
			Util.displayErrorInfo("form_email", helpString, true);
			error = true;
		}
	} else { 
		error = true;
	}

	if(!error) {
		Util.displayErrorInfo("form_email", "", false);
	}
	
	return !error;
}

function doCheckProfileActivation(pForm) {
    var hasError = false;
    var ele = eval('document.' + pForm.name + '.profile_create_email');
    var email_value = Util.getRadioValue(ele);
    if (null==email_value || ""==email_value) {
		helpString = "Please select an email address";
		Util.displayErrorInfo("email", helpString, true);
    	hasError = true;
    }
    else {
		Util.displayErrorInfo("email", "", false);
        hasError = false;
	}
    return !hasError;
}

/** Test to see if any words in the sentence are greater than wordLength in length
*/
function wordLengthOk(sentence, wordLength) {
    sentence = sentence.replace(/\n/g, " ");
    var words = sentence.split(" ");
    for(var i = 0 ; i < words.length ; i++) {
	w = words[i];
	w = String.trim(w);
        if(w.length >  wordLength) {
            return false;
        }
    }
    
    return true;
}

/** for the question ask page, let's do some validation
  * @param pAction: page action string
  * @param pMaxLimit: weird param, but necessary
  */ 
function catFormSubmitCheck(pAction,pMaxLimit) { // param is the action of the page - it is set as $link
    var deeperThanSixLevels = false;
    var error = false;
    if(pAction && 'ask' == pAction || pAction && 'ask_suggestion' == pAction ) {
        inputStr = String.trim(Util.gObj("title").value);
        helpString = "Please enter a question.<br/><br/>";
        helpString2 = "Your question must be at least 10 characters in length.<br/><br/>";

	capsHelp = "Please do not use ALL CAPS.  It's rude.";

        if(inputStr) {
            if(10 > inputStr.length && inputStr.length > 0) {
		Util.displayErrorInfo("title", helpString2, true);
                Util.gObj("title").value=inputStr; //set the trimmed string
		        error = true;
	        } 
	    else if (inputStr.toLowerCase() != inputStr.toUpperCase() && inputStr == inputStr.toUpperCase()) {
			Util.displayErrorInfo("title", capsHelp, true);
		error = true;
	    }
            else {
	           Util.displayErrorInfo("title", "", false);
            }
        } 
        else {
            Util.displayErrorInfo("title", helpString, true);
		    error = true;
        }
    } 
  
    // qautocat refers to a request from question-suggestion page
    if(pAction && 'qautocat' == pAction )  
    {
        helpString = "<br/><br/><br/><br/><br/>";

        if(document.catForm.onfocus.value == 'ks-question-browse')
        {
            if (!selectedCatID) {
                Util.displayErrorInfo("menu", helpString, true);
                error = true;
            } else {
                if (cA[selectedCatID]) {
                        if (selectedMenuName != "menu_2") {
                            helpString2 = "Please select a subcategory under: " + getPath() + '<br/><br/><br/><br/><br/>';
                            Util.displayErrorInfo("menu", helpString2, true);
                            error = true;
                        }
                } 
                else {
                        //Hide the error message
                        Util.displayErrorInfo("menu", helpString, false);
                }
            }
        }
        else if(document.catForm.onfocus.value == 'ks-question-autocat') 
        {
            error = true;

            for (var i = 0; i < document.catForm.elements.length; i++) 
            {
                if (document.catForm.elements[i].type == 'radio' && document.catForm.elements[i].checked) 
                {
                    error = false;
                    break;
                }
            }

            if(error)
            {
                Util.displayErrorInfo("menu", helpString, true);
            }
        }
    }
    
    //This code is reserved for backward-compatibility since question autocat is English-only 
    if((pAction && 'ask_suggestion' != pAction) &&  (pAction && 'qautocat' != pAction)) 
    {
        helpString = "<br/><br/><br/><br/>";
    
        if (!selectedCatID) {
            Util.displayErrorInfo("menu", helpString, true);
            error = true;
        } else {
            if (cA[selectedCatID]) {
                    if (selectedMenuName != "menu_2") {
                        //alert("Please select a subcategory under: " + getPath());
                        helpString2 = "Please select a subcategory under: " + getPath() + '<br/><br/><br/><br/>';
                        Util.displayErrorInfo("menu", helpString2, true);
                        error = true;
                    }
            } 
            else {
                    //Hide the error message
                    Util.displayErrorInfo("menu", helpString, false);
            }
        }
    }
    
    if(error) {
	    scroll(0,0); //helps alert user that error happened
	    return false;
    } else { 	
	return true;
    }
}
/*  /question/question_ask_add : when writing supplemental questions
 *  @param reference to the form
 */
function doAddSupplementToQuestion(pForm) {
    var MaxLen = 300;
    inputStr = pForm.textarea.value;
    strlength= inputStr.length;
    if (strlength > MaxLen ) {
        alert('You have exceeded the character limit.');
        return false;
    }
    return true;
}

/*  Question related functions
 *  /question/question.tpl.php
 */
function doCheckQuestionFormSubmit(pForm) {
    if (!Util.isNull(pForm.qid.value) && !Util.isNull(pForm.link.value)){
        return true;
    }
    return false;
}

/*  Set up voting by owner?
 *  /question/question.tpl.php
 */ 
function doSetVotingOnQuestion(pQid,pKid,pForm,pAction) {
    var f = document.forms[pForm];
    //var flag = window.confirm("Are you sure you want the community to choose a best answer for your question?\n (Voting will be open for 5 days.)");
    //if (flag) {
        f.qid.value = pQid;
        f.link.value = pAction;
        f.submit();
    //}
}

function doExtendQuestionExpirationTime(pQid,pAction,pForm) {
    var f = document.forms[pForm];
    //alert(typeof f);
    //var flag = window.confirm("Are you sure you you want to extend the question expiration period?\n (You can only extend once for 5 days.)");
    //if (flag) {
        f.qid.value = pQid;
        f.link.value = pAction;
        f.submit();
    //}
}

//deprecated
function doDeleteQuestionNoAnswer(pQid,pAction,pForm) { doDeleteQuestion(pQid,pAction,pForm); }
    
/*  Owner deletes the question
 *  /question/question.tpl.php
 */ 
function doDeleteQuestion(pQid,pAction,pForm) {
    var f = document.forms[pForm];
    var flag = window.confirm("Are you sure you want to delete this question?\n");
    if (flag) {
        f.qid.value = pQid;
        f.link.value = pAction;
        f.submit();
    }
}


/*  Answer related functions
 *  /question/answer.tpl.php
 */
function doDeleteAnswer(pQid,pAction,pForm){
    var f = document.forms[pForm];
    //alert(f + "==" + typeof f);
    var flag = window.confirm("Are you sure? You will not be able to submit a new answer for this question.\n\nTo edit your current answer:\n1. Click on \"Cancel\".\n2. Go to your answer and click on the \"Edit\" link below it.");
    if (flag) {
        f.link.value = pAction;
        f.qid.value = pQid;
        f.submit();
    }
}

function doVoteOnAnswer(pQid,pKid,pAction,pForm){
    var f = document.forms[pForm];
    var flag = window.confirm("Are you sure you want to send your reply?");
    if (flag) {
        f.qid.value = pQid;
        f.kid.value = pKid;
        f.link.value = pAction;
        f.submit();
    }
}

function doCheckAnswerFormSubmit(pForm) {
    if (!Util.isNull(pForm.qid.value) && !Util.isNull(pForm.link.value)){
        return true;
    }
    return false;
}

/*  Best Answer related functions
 *  /question/best_answer_include_tpl.php
 */

function setCommentsElementDisplayStyle(pObj,pAnchorElement){
    var el = document.getElementById(pObj);
    var bIsDisplay = (el.style.display=="none" || el.style.display=="");
    // var anchor = (Util.isNull(pAnchorElement)) ? Util.gObj('ks-widget-comment-toggle') : pAnchorElement;
    // anchor.className = (bIsDisplay) ? "open" : "closed";
    Util.sDisplay(pObj,bIsDisplay);
    if ("" != pAnchorElement && "undefined" != pAnchorElement.firstChild.nodeValue) {
        var msg = (bIsDisplay) ? "Hide Comments" : "Add/View Comments (" + gNumComments + ")";
        pAnchorElement.firstChild.nodeValue = msg;
    }
    
    // setTimeout(function() { Util.fixFooter() },800);
}

function doGiveBestAnswerEval(pQid,pForm) {
    var val = null;
    for (var i=0; i < pForm.elements.length; i++) {
        if (pForm.elements[i].type=="radio" && pForm.elements[i].checked) {
            val = pForm.elements[i].value;
            break;
        }
    }
    if (Util.isNull(val))
        alert("Please choose a rating for the answer");
    else {
        //var flag = window.confirm("Are you sure?");
        //if (flag) {
            pForm.qid.value = pQid;
            pForm.eval.value = val;
            // pForm.onsubmit();
            // pForm.submit();
            return true;
        //}
    }
    return false;
}

function doCheckCommentFormSubmit(pForm) {
    var iMaxLength= 300;
    /*
    if(0 == (String.trim(pForm.type.value)).length) {
        alert('please choose a category for your question');
        return false;
    }
    */
    var helpString="";;
    var inputStr = String.trim(pForm.textfield.value);
    var strlength= inputStr.length;
    if (strlength == 0) {
        //alert('Please enter your comment'); 
	    helpString = "Please enter a valid comment";
        Util.displayErrorInfo("titleComments", helpString, true);
        return false;
    }
    if (strlength > iMaxLength ) {
        //alert('The number of words in the content of the comment has exceeded the limit'); 
	    helpString = "Please limit to 300 characters.";
        Util.displayErrorInfo("titleComments", helpString, true);
        return false;
    }
    // pForm.submit();

	pForm.submit4.disabled = true;
    return true;
}
    
function openCommentsWindow(pObj){ 
    setCommentsElementDisplayStyle(pObj, Util.gObj('ks-widget-comment-toggle')); 
}


function doDeleteComment(pEle) {
    var flag = window.confirm("Are you sure you want to delete your comment?");
    if (flag) Util.sendRedirect(pEle.href);
    return false;
}


function fixup_textarea_size(ta) {
    var row_intervals = [5, 15];
    var MIN_ROWS = 1;
    var MAX_ROWS = 15;
    var MIN_COLS = 30;
    var MAX_COLS = 30;

    var text_length = ta.value.length;
    var num_rows = 0;

    var lines = ta.value.split("\n");

    for (var ii=0; ii <= lines.length-1; ii++) {
        num_rows++;
        if (lines[ii].length > MAX_COLS-5) {
            num_rows += Math.floor(lines[ii].length/MAX_COLS)
        }   
    } 
    if (text_length == 0) {
        ta.cols = MIN_COLS;
        ta.rows = MIN_ROWS;
    } 
    else {
        if (num_rows <= 1) {
            ta.cols = ((text_length % MAX_COLS) + 1 >= MIN_COLS )
                ? ((text_length % MAX_COLS) + 1) 
                : MIN_COLS;
        } 
        else {
            ta.cols = MAX_COLS;
            ta.rows = MAX_ROWS;
            for (var ii=0; ii <= row_intervals.length-1; ii++) {
                if (num_rows < row_intervals[ii]) {
                    ta.rows = row_intervals[ii];
                    break;
                }
            }
        }
    }
}
/* DEPRECATED */
/*
function doCheckAbuseReportReason(pForm) {
	// if( document.abuse.reason.value > 17 || document.abuse.reason.value < 6 ){
	if ( pForm.reason.value == 0 ){
		alert('Please choose the type of the abuse.');
	} else {
		if( pForm.pmesg.value == ''  ) {
            alert('Please enter what you want to report '); 
		}
        else {
            return true;
        }
	}
    return false;
}
*/

function doCheckAnswerQuestionFormSubmit(pFrom) {
    inputStr = String.trim(pFrom.textarea2.value);
    if(pFrom.textarea2.value == 0) {
	    var helpString = "Please enter an answer.";
        Util.displayErrorInfo("titleAnswer", helpString, true);
        //alert("Please input your answer.");
        return false;
    }

    return true;
}

function doCheckSupplmentalQuestions(pForm) {
    var MaxLen= 1000;
    var inputStr = pForm.textarea.value;
    var strlength = inputStr.length;
	
    Util.displayErrorInfo("details", "", false);   
    err = false;

    if (strlength < 10) {
        helpString = "You must enter at least 10 characters";
        Util.displayErrorInfo("details", helpString, true);
        err = true;
    }
    if (strlength > MaxLen ) {
        alert('You have exceeded the character limit.');
        err = true;
    }

    return !err;
}


function doTracking(qid, exp, crm, add) {
	var baseUrl = "/my/my_add_trace_q?qid";
	if(!add) { baseUrl = "/my/my_del_trace_q?qlist"; }
	params = new Array();
	params[0] = add;
	Util.ajaxCall(baseUrl+"=<?php echo $qid; ?>&expires=<?php echo $expires; ?>&.crumb=<?php echo $crumb; ?>", "GET", doTrackingDone, params, false, null);
	tS = Util.gObj("traceSpan");
	if(tS != null) {
		tS.innerHTML = "Saving...";
	}

	return false;
}

function doTrackingDone() {
	if(arguments[2]) {

		var add = !arguments[2][0];
		var baseUrl = "/my/my_add_trace_q";
                       if(!add) { baseUrl = "/my/my_del_trace_q"; }
	
		var newUrl = baseUrl+"?qid=rl+?qid=<?php echo $qid; ?>&expires=<?php echo $expires; ?>&.crumb=<?php echo $crumb; ?>";
		var newOnClick = "return doTracking(<?php echo $qid; ?>, <?php echo $expires; ?>, \'<?php echo $crumb; ?>\', "+add+");";
		var newText = "+ Add to my Watch List";
			
		if(!add) { newText = "Remove from Watch List"; }

		tS = Util.gObj("traceSpan");
		if(tS != null) {
			tS.innerHTML = '<a id="traceLink" style="font-weight:bold;" href="'+newUrl+'" onclick="'+newOnClick+'">'+newText+'</a>';
			Util.fadeElement("traceSpan", 60, 1800, "#fcd576", "#fff");
		}
	} else {
		tS = Util.gObj("traceSpan");
		if(tS != null) {
			tS.innerHTML = "Oops, there is an error.";
		}		
	}

	return false;
}

function doCheckAbuseReportForm(pForm) {
	var hasErr=false;
	if ("" == pForm.reason.options[pForm.reason.options.selectedIndex].value) {
		var helpString = "Please choose a category";
		Util.displayErrorInfo("abuseReport", helpString, true);
		hasErr=true;
	} else {
		Util.displayErrorInfo("abuseReport", "", false);
		pForm.submit_button.disabled=true;
	}

	/* optional now
	   if ("" == pForm.pmesg.value) {
	   var helpString = "Please describe this abuse";
	   Util.displayErrorInfo("abuseComments", helpString, true);
	   hasErr=true;
	   } else {
	   Util.displayErrorInfo("abuseComments", "", false);
	   }
	 */

	return !hasErr;
}

    
    function doCheckSelectBestAnswerForm(pForm) {
        var hasErr=false;
        var c_eles = pForm.elements.length;
        var n=-1;
        for(var i=0; i<c_eles; i++) {
            if ("radio"==pForm.elements[i].type && pForm.elements[i].checked) {
                n = pForm.elements[i].value;
                break;
            }
        }   
        if(-1 == n) {
            var helpString = "Please choose a rating for the answer";
            Util.displayErrorInfo("ratings", helpString, true);
            hasErr=true;
        } else {
            Util.displayErrorInfo("ratings", "", false);
        }
        var inputStr = String.trim(pForm.textarea.value);
        var strlength = inputStr.length;
        if (strlength < 1 ) {
            var helpString = "Please enter a comment";
            Util.displayErrorInfo("moreComments", helpString, true);
            hasErr=true;
        }
        else if ( strlength > 300 ) {
            var helpString = "Your comment has too many characters";
            Util.displayErrorInfo("moreComments", helpString, true);
            hasErr=true;
        } else {
            Util.displayErrorInfo("moreComments", "", false);
        }
        return !hasErr;
    }

    function mailFormSubmitCheck(pForm) {
        var MailMaxLen = 200;
        var MaxLen= 500;
        var hasErr = false;
        var tmpEmail = pForm.remail;
        
        //Change semicolons to commas so backend check doesn't fail 
        var inputStr = tmpEmail.value;
        inputStr = inputStr.replace(";", ",");
	//get rid of trailing commas
	inputStr = inputStr.replace(/[,\s]*$/, "");
        var strlength = inputStr.length;
        Util.debug("remail - string value:" + inputStr);
        var helpString = "";
        
        var eS="";
        if (strlength == 0) { 
            helpString = 'Enter an email address';
            Util.displayErrorInfo("emailInput", helpString, true);
            hasErr = true;
        } 
        else {
            eS = validateCollectionEmails(inputStr);
            if(eS.length > 0) {
    	        Util.displayErrorInfo("emailInput", eS, true);
    	        hasErr = true;
            } else {
                Util.displayErrorInfo("emailInput", "", false);
            }
       }
    
       if (strlength > MailMaxLen ) {
           helpString = 'The number of characters in the email addresses field has exceeded the limit';
           Util.displayErrorInfo("emailInput", helpString, true);
           hasErr = true;
       } else {
           if(strlength > 0 && eS.length == 0) {
               Util.displayErrorInfo("emailInput", "", false);
           }
       }
       
       inputStr = pForm.pmesg.value;
       strlength= inputStr.length;
       
       /*
       if (strlength == 0 ) {
           helpString = 'Please add your message';
           Util.displayErrorInfo("pmesg", helpString, true);
           hasErr = true;
       } else {
           Util.displayErrorInfo("pmesg", "", false);
       }
       */
       
       if (strlength > MaxLen ) {
           helpString = 'The number of characters in your message has exceeded the limit';
           Util.displayErrorInfo("pmesg", helpString, true);
           hasErr = true;
       } else {
           if(strlength > 0) {
               Util.displayErrorInfo("pmesg", "", false);
           }
       }
       
       return !hasErr;
    }

    function validateCollectionEmails(emailStr) {
		var errString = "";
		var email = emailStr.split(',');
        try {
		    for (var i = 0; i < email.length; i++) {
		        tmpStr = validateEmail(String.trim(email[i]), 1);
			    if (tmpStr.length > 0) errString = tmpStr;
		    }
        }
        catch(e) {
            this.debug(e.message);
        }
		return errString;
    }

    function validateEmail(addr,man) {
		try {
            var err = false;
    		var errString = "";
    		if (addr == '' && man) {
    		   errString = 'Please enter an email address';
    		   err = true;
    		}
    		var invalidChars = '\/\'\\ ":?!()[]\{\}^|';
    		for (i=0; i<invalidChars.length; i++) {
    		   if ((addr.indexOf(invalidChars.charAt(i),0) > -1) || (addr.charCodeAt(i)>127)) {
    			  errString = 'Please enter a valid email address';
    			  err = true;
    		   }
    		}		
    		var atPos = addr.indexOf('@',0);
    		if ((atPos == -1) || (addr.indexOf('..',0) != -1) || (atPos == 0) ||
                (addr.indexOf('@', atPos + 1) > - 1) || (addr.indexOf('.', atPos) == -1) ||
                (addr.indexOf('@.',0) != -1) || (addr.indexOf('.@',0) != -1) || (addr.indexOf('..',0) != -1)) {
    		    errString = 'Please enter a valid email address';
    		    err = true;
    		}
    		var suffix = addr.substring(addr.lastIndexOf('.')+1);
        }
        catch(e) {
            this.debug(e.message);
        }
		return errString;
    }


function rateTargetResponse(o) {
	var rsp  = o.responseText; //Response text/html | or error
	var tid  = o.tId; //Transaction id
	var args = o.argument; //Arguments, if any, created during initial ajax call
	
	//Was there a transport error?  (true if arguments[1] and arguments[2] are null)
	if((tid == null && args == null) || o.status == 0) {
		return false;
	}
	
	var targetName = args[0];
	var rating = args[1];
	var jsonText = (null != rsp) ? rsp : "";
	var json = Util.evalJson(jsonText);
	
	if(json) {
		var ratingElement = Util.gObj("rating-area-"+targetName);
		var ratingElementHidden = Util.gObj("rating-area-hidden-"+targetName);
		var messagingArea = Util.gObj("messaging-area-"+targetName);
		if(!json.error) {
			messagingArea.innerHTML = json.message;
		
			/*
			var anim = new YAHOO.util.Anim('answer-container-'+targetName, { height: {to: 40} }, 1, YAHOO.util.Easing.easeBoth);
			anim.onComplete.subscribe(function() { hideAnswer(targetName); });
			anim.animate();
			*/
			if(rating == -1) {
				setTimeout("hideAnswer('"+targetName+"');", 1200);

				answerHiddenDesc = Util.gObj("hide-desc-"+targetName);
				answerHiddenDescO = Util.gObj("hide-desc-o-"+targetName);
				answerHiddenDesc.innerHTML = "You gave this answer a low rating:";
				answerHiddenDescO.innerHTML = "You gave this answer a low rating:";
			}

			ratingElement.className = ratingElement.className + " inactive";
			if(ratingElementHidden) {
				ratingElementHidden.innerHTML = json.html;
			}
		} else {
			messagingArea.innerHTML = "<span class=\"error\">"+json.error+"</span>";
		}
		ratingElement.innerHTML = json.html;
	}
}

function rateTarget(targetName, targetType, actionUrl, rating) {
	//var ajax = YAHOO.search.answers.util.Ajax.getInstance();
	var ratingElement = Util.gObj("rating-area-"+targetName);
	var messagingArea = Util.gObj("messaging-area-"+targetName);
	var uri = actionUrl;

	var callback =
	{
		success: rateTargetResponse,
		failure: rateTargetResponse,
		argument: [targetName, rating]
	}
	
	messagingArea.innerHTML = '<img alt="Saving..." src="http://us.i1.yimg.com/us.yimg.com/i/us/sch/gr2/saving_grnarial.gif">&nbsp;';
	YAHOO.search.answers.util.Ajax.request(uri, callback);
	
	//disable links so they don't double submit
	var children = YAHOO.util.Dom.getElementsByClassName("link", "a", ratingElement);
    for(var i = 0 ; i < children.length ; i++) {
		children[i].onclick = function() { return false; };
    }
	children = null;
}

function hideAnswer(ansId) {
	answerContainer = Util.gObj("answer-container-"+ansId);
	answerHideControl = Util.gObj("answer-hide-control-"+ansId);
	answerHidden = Util.gObj("answer-hidden-"+ansId);
	answerHiddenDesc = Util.gObj("hide-desc-"+ansId);
	
	if(answerContainer && answerHideControl && answerHidden) {
		answerHiddenDesc.innerHTML = "You gave this answer a low rating:";
		answerHidden.style.display = "block";
		answerContainer.style.display = "none";
		answerHideControl.style.display = "block";

		contClass = answerContainer.className;
		if(contClass.indexOf("hidable") == -1) {
			answerContainer.className = answerContainer.className + " hidable";
		}
		
		//another IE display problem hack, this seems to jog the image back into place
		var hiddenUserImages = YAHOO.util.Dom.getElementsByClassName("hidden-user-image", "img", "middle");
		for(var i = 0 ; i < hiddenUserImages.length ; i++) {
            hiddenUserImages[i].style.display = "none";
            hiddenUserImages[i].style.display = "inline";
		}
	}

	answerHidden = null;
	answerContainer = null;
	answerHideControl = null;
}

function unhideAnswer(ansId) {
	answerContainer = Util.gObj("answer-container-"+ansId);
	answerHideControl = Util.gObj("answer-hide-control-"+ansId);
	answerHidden = Util.gObj("answer-hidden-"+ansId);
	reportAbuseIcon = Util.gObj("abuse-report-"+ansId);

	if(answerContainer && answerHideControl && answerHidden) {
		answerHidden.style.display = "none";
		answerContainer.style.display = "block";
		answerHideControl.style.display = "block";
		reportAbuseIcon.style.display = "none"; //IE hack for display bug
		reportAbuseIcon.style.display = "inline"; //IE hack for display bug
	}

	answerHidden = null;
	answerContainer = null;
	answerHideControl = null;
}


ACTION_MENU_ID = "actionBarMenu";
YAHOO.namespace("search.answers.overlay");
YAHOO.search.answers.overlay.menu = null;
YAHOO.search.answers.overlay.timer = null;
YAHOO.search.answers.overlay.activeMenuName = null;
YAHOO.search.answers.overlay.activeMenuState = null;
YAHOO.search.answers.overlay.activeContextId = null;
YAHOO.search.answers.overlay.activeContextType = null;
function openActionMenu(type, itemId, heightOffset) {
	//just in case
	initGlobalActionMenu();
	contextDivName = type+"-"+itemId;
	menuDivName = type+"-menu-"+itemId;
	contextDiv = Util.gObj(contextDivName);
	menuDiv = Util.gObj(menuDivName);

	menu = YAHOO.search.answers.overlay.menu;
	activeMenuName = YAHOO.search.answers.overlay.activeMenuName;
	activeMenuState = YAHOO.search.answers.overlay.activeMenuState;

	//check if this menu is already open, if it is, we're done
	if(activeMenuName == menuDivName && activeMenuState == "open") {
		return; 
	}

	//only re-render if we're on a different menu than before
	if(activeMenuName != menuDivName) {
		menu.setBody(menuDiv.innerHTML);
		menu.cfg.setProperty("context",[contextDivName, "tl", "bl"]);
		menu.render();
	}

	YAHOO.util.Event.addListener(menu.element, "mouseover",
        function() { clearTimeout(YAHOO.search.answers.overlay.timer); });
	YAHOO.util.Event.addListener(menu.element, "mouseout",
        function() { YAHOO.search.answers.overlay.timer =
            setTimeout("closeActionMenu()", 1000); });

    if (YAHOO.search.answers.overlay.activeContextType == null){
        YAHOO.util.Event.addListener(contextDiv, "mouseover",
            function() { clearTimeout(YAHOO.search.answers.overlay.timer); });
        YAHOO.util.Event.addListener(contextDiv, "mouseout",
            function() { YAHOO.search.answers.overlay.timer =
                setTimeout("closeActionMenu()", 1000); });
    }

//    YAHOO.search.answers.overlay.timer =
//        setTimeout("closeActionMenu()", 1000);

	//let's see it
	menu.show();

	//shift it up a few pixels to clean up the context alignment the firsttime we open this menu
	if(activeMenuName != menuDivName) {
	    menuY = YAHOO.util.Dom.getY(ACTION_MENU_ID);
    	menu.cfg.setProperty("y", menuY - 2);
	}

	//store the state and name
	activeMenuState = "open";
	activeMenuName = menuDivName;
	YAHOO.search.answers.overlay.activeMenuName = activeMenuName;
    YAHOO.search.answers.overlay.activeMenuState = activeMenuState;
    YAHOO.search.answers.overlay.activeContextId = itemId;
    YAHOO.search.answers.overlay.activeContextType = type;
}


function closeActionMenu() {
	menu = YAHOO.search.answers.overlay.menu;
    clearTimeout(YAHOO.search.answers.overlay.timer);

    YAHOO.util.Event.purgeElement(menu.element);
    initSpecificActionMenu(YAHOO.search.answers.overlay.activeContextType,
                           YAHOO.search.answers.overlay.activeContextId);

	activeMenuState = YAHOO.search.answers.overlay.activeMenuState; 
	if(menu != null && activeMenuState == "open") {
		menu.hide();
		YAHOO.search.answers.overlay.activeMenuState = "closed";
	}
}

function initSpecificActionMenu(type, itemId) {
	contextDivName = type+"-"+itemId;
	YAHOO.util.Event.purgeElement(contextDivName);
	YAHOO.util.Event.addListener(contextDivName, "mouseover", function() { openActionMenu(type, itemId); } );
}

YAHOO.util.Event.addListener(window, "load", initGlobalActionMenu );
function initGlobalActionMenu() {
	menu = YAHOO.search.answers.overlay.menu;
	if(menu == null) {
		ks = Util.gObj("y-body-green-knowledge-search");
		menu = new YAHOO.widget.Overlay(ACTION_MENU_ID, {visible:false} );
		menu.render(ks);
		YAHOO.search.answers.overlay.menu = menu;

		//a click anywhere on the page will close the open menu
		YAHOO.util.Event.addListener(document, "click", function() { closeActionMenu(); } );

		//mouseover on any of the other action bar elements will hide any open menus
		/*var actionItems = YAHOO.util.Dom.getElementsByClassName("separator", "div", "middle");
		for(var i = 0 ; i < actionItems.length ; i++) {
			YAHOO.util.Event.addListener(actionItems[i], "mouseover", function() { closeActionMenu(); } );
		}
		var actionItems = YAHOO.util.Dom.getElementsByClassName("border-right", "div", "middle");
		for(var i = 0 ; i < actionItems.length ; i++) {
			YAHOO.util.Event.addListener(actionItems[i], "mouseover", function() { closeActionMenu(); } );
		}*/
		actionItems = null;
	}
}
/** 
 *  global constants first 
 *  - these suck, and only used cause wrapping objects with objects confuses "this" scope / context
 */
var IS_SEARCH_AHEAD_ENABLED = true;
var RESULTS_FOUND_MESSAGE = "We have found similar questions: ";
var NO_RESULTS_FOUND_MESSAGE = "No similar questions found ";
var KP_YFED_SEARCH_HANDLER = "/common/util/ks-yfed-search-handler.php";
var NTH_WORD_INDEX = 3;
var SEARCH_AHEAD_TIMEOUT = 750;
var SET_STRING_TO_NULL = "COUNT_TO-NULL";

var hasWindowLoaded = false;
var isQuestionAskPage = false;
var timerAjaxId = null;
var numYfedResults = 5;
var resultsYfedHash = [];
var currYfedStr = "";
var ajax = null;
var isSpellchecking = false;

/*
 ***************************************************** */ 
/* 
 *  global functions second 
 *  - these suck, and only used cause wrapping objects with objects confuses "this" scope / context
 */
function handleInfoLayerOnResize() { if (mm) mm.doCorrectPos(); }

/*  handles form submission when user hits 'enter' button
 *  use on form element's keyup event handler
 */
function doHandleEnterKeyStroke(pForm,e) {
    if (!e) e=window.event;
    if (13==e.keyCode) {
        pForm.submit();
    }
    return false;
}

function doRolloverAction(pImgElement,pImgPath) {
    if (document.getElementById && hasWindowLoaded) {
        document.getElementById(pImgElement).src = pImgPath;
    }
}

function doChangeFormAction(pForm,pActionValue) { if (null != pForm && null != pActionValue) pForm.action = pActionValue; }

function doPrepSuggestedQuestionsRequest() {
    var el = document.getElementById(oAnswers.search_ahead.SEARCH_AHEAD_SUGGESTED_QUESTIONS);
    clearTimeout(oAnswers.search_ahead.timer_handle);
    oAnswers.search_ahead.timer_handle = setTimeout('doGetSuggestedQuestionsRequest()',oAnswers.search_ahead.TIMEOUT_HANDLE_IN_MILLISECONDS);
}

function doGetSuggestedQuestionsRequest() {
    if (isSpellCheckActive()) { // if spell checking then clear the pane
        doSetSuggestedQuestionsResults(null);
    }
    else {
        var pStr = document.forms["catForm"].title.value;
        if (!document.getElementById || !IS_SEARCH_AHEAD_ENABLED) return;
        //ygConn.http.abort(sugg_ajax);
        var el = document.getElementById(oAnswers.search_ahead.SEARCH_AHEAD_SUGGESTED_QUESTIONS);
        var tmpStr = pStr;
        currYfedStr = tmpStr;
        // if cached results
        if (resultsYfedHash[currYfedStr]) {
            doSetSuggestedQuestionsResults(resultsYfedHash[currYfedStr]);
            Util.debug("Found results for " + currYfedStr);
        }
        else {
            if (Util.isNthWord(pStr)  || pStr.lastIndexOf(oAnswers.eggs.CONTRA_CODE_INIT) != -1) {
                try {
                    oAnswers.util.setCursor('wait');
                    var _uri = oAnswers.search_ahead.request_handler + "?action=get_related_questions&scope=subject&q=" + encodeURI(pStr) + "&n=" + numYfedResults + "&type=html&lang=en_US";
                	oAnswers.util.Ajax.request(_uri,doSuggestedQuestionsResultsCallback);
                }
                catch(e) {
                    Util.debug(Util.EXCEPTION_STRING + ": couldn't finish " + e.message);
                    resultsYfedHash[currYfedStr] = "";
                    //timerAjaxId = setTimeout('doGetSuggestedQuestionsRequest()',SEARCH_AHEAD_TIMEOUT);
                }
                finally {
                    oAnswers.util.setCursor('auto');
                }
            }
        }
    }
}

function isSpellCheckActive() {
    return isSpellchecking;
}

function doFinishSpellCheckAndEnableSuggestedQuestionsResults() {
    isSpellchecking = false;
    doPrepSuggestedQuestionsRequest();
}

function doSetSuggestedQuestionsResultsNull() { 
	doSetSuggestedQuestionsResults(SET_STRING_TO_NULL);
	isSpellchecking = true;
}

var doSuggestedQuestionsResultsCallback =  { 
	success: function(response) { doGetSuggestedQuestionsResponse(response) }, 
	failure: function(response) { doSetSuggestedQuestionsResults(response) }
}

function doSetSuggestedQuestionsResults(pStr) {
	//Util.debug("Let's set the HTML for search string");
	var _str = pStr;
    var _ele = document.getElementById(oAnswers.search_ahead.SEARCH_AHEAD_SUGGESTED_QUESTIONS);
    if (null != _ele && "undefined" != _ele) {
        var tmpStr = "<strong>" + NO_RESULTS_FOUND_MESSAGE + "</strong>";
        if (isSpellCheckActive() || SET_STRING_TO_NULL == _str) {
            tmpStr = "&nbsp;";
        }
        if (null!= _str && "" != _str && SET_STRING_TO_NULL != _str) {
            tmpStr = "<strong>" + RESULTS_FOUND_MESSAGE + "</strong>" + _str;
            _ele.style.display = "block";
            resultsYfedHash[currYfedStr] = _str;
            oAnswers.util.setCursor('auto');
        }
        // highlights words
        // ele.innerHTML = Util.highlightWords(document.forms["catForm"].title.value,tmpStr);
        _ele.innerHTML = tmpStr;
    }
    return;
}

/*	@description callback for handling the search results response
 */
function doGetSuggestedQuestionsResponse(pResponse) {
	var _responseText = (null != pResponse.responseText) ? pResponse.responseText : "";
    doSetSuggestedQuestionsResults(( (_responseText.indexOf("ks-look-head-questions") != -1) ? _responseText : null ) );
    oAnswers.util.setCursor('auto');
}

function doInitSuggestedQuestionsResponse() { 
    doGetSuggestedQuestionsRequest(document.forms["catForm"].title.value); 
    oAnswers.util.setCursor('auto');
}

// DEP: answers.bookmarks.save 
function AnswersMyWeb2Save(title, url) {
    window.open('http://myweb2.search.yahoo.com/myresults/bookmarklet?t=' + escape(title) + '&u='+encodeURIComponent(url)+'&ei=UTF-8','popup','width=520px,height=420px,status=0,location=0,resizable=1,scrollbars=1,left=100,top=50',0);
}

// DEP: answers.bookmarks.save 
function AnswersMyWebIntlLegacySave(title, url, myweburl) {
    window.open(myweburl+'myresults/bookmarklet?t=' + escape(title) + '&u='+encodeURIComponent(url)+'&ei=UTF-8','popup','width=520px,height=420px,status=0,location=0,resizable=1,scrollbars=1,left=100,top=50',0);
}
// DEP: answers.profile.doToggleProfileStats
function doToggleQAChart(pChar,pAnchor) {
	var _ele_q = document.getElementById('ks-stats-chart-q');
	var _ele_a = document.getElementById('ks-stats-chart-a');
	var _anchor_q = document.getElementById('ks-stats-chart-nav-q');
	var _anchor_a = document.getElementById('ks-stats-chart-nav-a');
	
	if ("q"==pChar) {
		_ele_q.style.visibility="visible";
		_ele_a.style.visibility="hidden";
		_anchor_q.className = "selected";
		_anchor_a.className = "unselected";
	}
	else if ("a"==pChar) {
		_ele_q.style.visibility="hidden";
		_ele_a.style.visibility="visible";
		_anchor_q.className = "unselected";
		_anchor_a.className = "selected";
	}
}

/* Util object that we use to do stuff
 ***************************************************** */ 

function KS_Util(pId,pBrowserObj,pIsDebug,pKid,pKNickname){
    this.id=pId;
    this.kid=(!this.isNull(pKid)) ? pKid : null;
    this.nick=(!this.isNull(pKNickname)) ? pKNickname : null;
    this.ua=(!this.isNull(pBrowserObj)) ? pBrowserObj : new yg_Browser();
    this.DATATYPE_OBJECT="object";
    this.OFFSET_BODY_HEIGHT=100;
    this.EXCEPTION_STRING="EXCEPTION";
    
    this.IS_JAVASCRIPT_DEBUG=pIsDebug||false;
    this.DEBUG_CONSOLE='y-ks-error-log';
    this.DISPLAY_WIDGET_STAR='<img src="http://us.i1.yimg.com/us.yimg.com/i/us/sch/gr/pointsstar.gif" border="0" />';
    this.DISPLAY_WIDGET_ALERT='http://us.i1.yimg.com/us.yimg.com/i/us/sch/gr/alrt12_1.gif';
    this.DISPLAY_WIDGET_1= 'y-ks-header-user-profile-widget-msg-1';
    this.DISPLAY_WIDGET_2= 'y-ks-header-user-profile-widget-msg-2';
    this.current_widget_display=this.DISPLAY_WIDGET_1;
    this.DISPLAY_WIDGET_NOTIFICATION_STATES=new Array(
        '',
'You get 100 points to start',
'Thanks for visiting! (1 point)',
'You asked a question (-5 points)',
'Asking a question anonymously',
'Neglecting my question',
'You chose a best answer (3 points)',
'You answered a question (2 points)',
'Deleted an answer (-2 points)',
'Your answer was picked as best! (10 points)',
'You voted for a best answer (1 point)',
'You rated a best answer (1 point)',
'Evaluated with excellence!',
'Honorable contribution',
'A violation in a question',
'A violation in an answer',
'A violation in a comment',
'A best answer is considered a violation',
'Other naughty things',
'Thumbs-up for your best answer! (1 point)',
'You chose to call a vote',
'Maximum awards for answer evaluated as positive',
'Number of events to keep in history per user',
'',
'Your question had no best answer (5 points)'
    );
}

KS_Util.prototype.highlightWords = function(pStr,pResponseText) {
    this.highlight_tag = "strong";
    var tmpStr = String.trim(pStr);
    var tmpArr = tmpStr.split(' ');
    if (tmpArr.length > 0) {
        for (var ii=0; ii< tmpArr.length; ii++) {
            var p = new RegExp (tmpArr[ii],'ig');
            pResponseText = pResponseText.replace(p,"<" + this.highlight_tag + ">"+tmpArr[ii]+"</" + this.highlight_tag + ">");
        }
    }
    return pResponseText;
}


/**
 *  @returns boolean
 *  @description returns whether the string has 'n' words, delimiting by space
 */
KS_Util.prototype.isNthWord = function(pStr) {
    var tmpStr = String.trim(pStr);
    if (tmpStr.length > 0) {
        var tmpArr = tmpStr.split(' ');
        if ((tmpArr.length > (NTH_WORD_INDEX - 1)) && "" != tmpArr[NTH_WORD_INDEX - 1]) return true;
    }
    return false;
}

KS_Util.prototype.isNull=function(pEle){
    return (null==pEle || "undefined"==pEle || ""==pEle);
}

 /**
  * @function gObj - returns a reference to an element
  * @param pObj - string or object
  * @returns - reference to the document node or NULL
  */  
KS_Util.prototype.gObj=function(pObj){
    var tmp=null;
    if (document.getElementById) {
        tmp = (typeof pObj==this.DATATYPE_OBJECT) ? pObj : document.getElementById(pObj);
    }
    else if (document.all) {
        tmp = (typeof pObj==this.DATATYPE_OBJECT) ? pObj : document.all[pObj];
    }
    if (!this.isNull(tmp)) {
        return tmp;
    }
    return null;
}

KS_Util.prototype.setDocumentTitle=function(pStr) {
    var tmpTitle=document.title;
    document.title = tmpTitle + " - " + pStr;
}

KS_Util.prototype.debug=function(pStr,pLevel) {
    //if (this.IS_JAVASCRIPT_DEBUG && "string" == typeof pStr) {
    	/*
        var d = this.gObj(this.DEBUG_CONSOLE);
        var parent_function = arguments.caller;
        var current_function = arguments.callee;
        if (pStr.indexOf(this.EXCEPTION_STRING) != -1) pStr = "<span style=\"background-color:red;color:#fff;\">" + pStr + "</span>";
        if (null!=d) {
            var tmpStr = d.innerHTML;
            d.innerHTML = tmpStr + ((tmpStr.length > 5) ? "<br/>" : "") + "&gt; " + pStr;
        }
        */
        if (null==pLevel || ""==pLevel || !typeof pLevel=="string") pLevel = "info";
        try {
	        YAHOO.log(pStr,pLevel);
    	}
    	catch(e) {
    		//alert("error: " + e.message);
    	}
    //}
}

KS_Util.prototype.writeWidgetMessage=function(pPt) {
	var s="";
	if (pPt < 0) s +='<span style="">Alert</span>';
	else if (pPt == 0) s +='<span style="">Alert</span>';
	else if (pPt > 0) s +='<span style="color:#52be0a">Thanks!</span>';
	else s +='<span style="">Alert</span>';
	return s;
}


KS_Util.prototype.doAggregateIncentiveEvents=function(pIncentiveArray) { 
	var _ele = this.gObj(this.current_widget_display);
	if (null == _ele || ""==_ele || "undefined"==_ele) return;
    var incentiveArray = pIncentiveArray;
    var c_events = incentiveArray.length;
    var s='';
    var isDisplayed = true;
    var hasNoSystemEvents = false;
    if (c_events <= 0) {
        /*
        if (!this.isNull(this.kid)) {
            hasNoSystemEvents = true;        
            var random = Math.floor(Math.random() * 10);
            Util.debug("random number: " + random);
            if (random == 3 && null != this.nick) {
                s += '<span class="alert">Hi <a href="/my/my">' + this.nick + '</a>! Check your <a href="/my/my?link=question&more=y">questions</a> for a best answer</span>';
            }
            else {
                isDisplayed = false;
            }
        }
        */
    }
    else {
        // begin parsing system events
       	s += '<table style="height:50px;" cellpadding="0" cellspacing="0" border="0"><tr>';
        // for EVENT #23, tell em this message
        if (parseInt(incentiveArray[0].getOid()) == 23) {
			s += '<td style="width:60px; height:50px; vertical-align:middle; text-align:center;"><img src="http://us.i1.yimg.com/us.yimg.com/i/us/sch/gr2/medal.gif" vspace="12" style="border:none;" /></td>';
        	// alert user of questions that need attn
            var tmpUrl = "/my/my?link=question&more=y";
            s += '<td style="height:50px; vertical-align:middle; text-align:center;"><span class="new"><strong>Some of <a href="' + tmpUrl + '">your questions</a> need attention!</strong></span></td>';
        }
        else {
	       	s += '<td style="width:60px; height:50px; vertical-align:middle; text-align:center;"><img src="http://us.i1.yimg.com/us.yimg.com/i/us/sch/gr2/medal.gif" vspace="12" style="border:none;" /></td>';
    		
            if (1 == c_events) {
            	var obj = incentiveArray[0];
	            s += '<td style="height:50px; vertical-align:middle;"><strong style="margin-top:12px; font-size:115%;">'+this.writeWidgetMessage(parseInt(obj.getPoints()))+'</strong><br/>';
                //s += 'You\'ve earned '+ obj.getPoints() +' point'+( (parseInt(obj.getPoints()) > 0) ? "s" : "") +' for ';
                var msgStr = this.DISPLAY_WIDGET_NOTIFICATION_STATES[parseInt(obj.getOid())];
				//strip out any point info in the string, lame
				msgStr = msgStr.replace(msgStr.substring(msgStr.lastIndexOf("("), msgStr.length), "");
				s += msgStr;
				//append the correct point data to the string
				pointStr = (parseInt(obj.getPoints()) == 1) ? "point" : "points";
				pointStr = " (" + obj.getPoints() + "&nbsp;" + pointStr + ")";
				s += pointStr;
            }
            else { // multiple points
                var count=0;
                s += '<td style="height:50px; vertical-align:middle;">';
                for (var ce=0; ce < c_events; ce++) {
                    var obj = incentiveArray[ce];
                    if (parseInt(obj.getOid()) == 23) continue;
                    this.debug('Util.doAggregateIncentiveEvents() in loop, print string ' + s);
                    var obj = incentiveArray[ce];
                    count += parseInt(obj.getPoints());
                }
                if (count >= 0) {
					s += '<strong style="margin-top:12px; font-size:115%;">Whoa!</strong><br/>';
                	s += "You\'ve earned <strong>"+ count + "</strong> points!";
                	s +=' </span>';//need the space for aesthetic reasons
                } else {
					s += '<strong style="margin-top:12px; font-size:115%;">Alert</strong><br/>';
					var _num = (count * -1);
                	s += "You\'re down <strong>" + _num + "</strong> points!";
                	s +=' </span>';//need the space for aesthetic reasons
                }
            }
            s += '</td>';
        }
        s+= '</tr></table>';
    }
    // s+= (c_events > 1 && !hasNoSystemEvents && isDisplayed) ? '<br/><span style="padding-left:18px;"><a href="/info/scoring_system.php">Tell Me More</a></span>' : '';

    var self=this;
    if (isDisplayed && s.length > 0) {
        self.doReplaceWidgetDisplay(s);
        setTimeout(function(){ self.doReplaceWidgetDisplay(null) } , 10000);
    }
}

// toggle btwn 1 + 2
KS_Util.prototype.doReplaceWidgetDisplay=function(pMsg) {
    this.fadeElement(this.gObj(this.current_widget_display),false);
    this.current_widget_display=(this.DISPLAY_WIDGET_1==this.current_widget_display) ? this.DISPLAY_WIDGET_2 : this.DISPLAY_WIDGET_1;
    this.fadeElement(this.gObj(this.current_widget_display),true,pMsg);
    var z = parseInt(this.gObj(this.current_widget_display).style.zIndex);
    this.gObj(this.current_widget_display).style.zIndex=(z+2);
}

KS_Util.prototype.fadeElement=function(pEle,pFadeVisible,pMsg) {
     var ele = Util.gObj(pEle);
     if (null!=pMsg && ""!=pMsg) ele.innerHTML = pMsg;
     var oAnim=null;
     if (pFadeVisible) {
   	 	oAnim = new YAHOO.util.Anim(pEle, { opacity: { to: 1, from : 0 } }, 1.9, YAHOO.util.Easing.easeNone);
	 }
	 else { //hidden
   	 	oAnim = new YAHOO.util.Anim(pEle, { opacity: { to: 0, from : 1 } }, 1.9, YAHOO.util.Easing.easeNone);
	 }
	 // YAHOO.util.Event.on(document, 'click', oAnim.animate, anim, true);
   
     //if (pFadeVisible) oAnim.onStart = function() { 
     ele.style.visibility = 'visible';
     oAnim.animate();
     return false;
}

/**
 * @function gObj - set display style
 * @param pObj - string or object
 */  
KS_Util.prototype.sDisplay=function(pObj,pBool) {
    this.gObj(pObj).style.display = (pBool) ? "block" : "none";
}

/** redirect the user to a fully qualified URL
  * @param pUrl - URL
  */ 
KS_Util.prototype.sendRedirect=function(pUrl) {
    parent.location.href = pUrl;
}

KS_Util.prototype.setWindowStatus=function(pStr) {
    if (pStr) window.status = pStr;
}

KS_Util.prototype.doFocusOnLoginBox=function() {
    var f=document.login_form;
    if (f) {
       if (f.username && f.username.value=="") f.username.focus();
       else if (f.passwd && f.passwd.value=="") f.passwd.focus();
    }
    return;
}

KS_Util.prototype.openTargetWindow = function(form, features, windowName) {
    if (!windowName) windowName = 'formTarget' + (new Date().getTime().toString());
    form.target = windowName;
    window.open ('', windowName, features);
}


KS_Util.prototype.fixFooter=function() {
	var l = this.gObj("left");
	var m = this.gObj("middle");
	var r = this.gObj("right");
	if (null == m) m = this.gObj('middle-center'); //if different layout
	if (null == m) m = this.gObj('just-middle'); //if different layout
    if (null == m) m = this.gObj('just-middle'); //if different layout again
	if (null != l && null != m && null != r) {
		var maxH = l.offsetHeight;
		if(r.offsetHeight > maxH) maxH = r.offsetHeight;
		if(maxH > m.offsetHeight) m.style.height = (maxH + this.OFFSET_BODY_HEIGHT)+"px";
    }
    else if (null != l && null != m && null==r) {
		var maxH = l.offsetHeight;
		if(maxH > m.offsetHeight) m.style.height = (maxH + this.OFFSET_BODY_HEIGHT)+"px";
    }
}

KS_Util.prototype.init=function() {
    //this.fixFooter();
    if (this.IS_JAVASCRIPT_DEBUG) {
        this.gObj(this.DEBUG_CONSOLE).style.visibility="visible";
        this.gObj(this.DEBUG_CONSOLE).style.display="block";
    }
    //if (!this.isNull(gPageTitle)) this.setDocumentTitle(gPageTitle);
    this.doAggregateIncentiveEvents(aIncentiveArray);
    this.doFocusOnLoginBox();
    hasWindowLoaded = true;
}

KS_Util.prototype.getRadioValue = function(radioObj) {
	if(!radioObj)
		return "";
	var radioLength = radioObj.length;
	if(!radioLength || radioLength == undefined) 
		if(radioObj.checked)
			return radioObj.value;
		else
			return "";
	for (var i = 0; i < radioLength; i++) {
		if(radioObj[i].checked) {
			return radioObj[i].value;
		}
	}
	return null;
}

KS_Util.prototype.highlightElement = function (id, fps, duration, from, to) 
{
	Fat.fade_element(id,fps,duration,from,to);
}

/** Use this to add an event to an object unobtrusively
 *  @param - obj: Object to add event to (i.e. window)
 *  @param - evType: Event type (i.e. 'load')
 *  @param - fn:Function to be called when event occurs
 */
KS_Util.prototype.addEvent = function (obj, evType, fn){ 
    if (obj.addEventListener){ 
        obj.addEventListener(evType, fn, false); 
        return true; 
    } 
    else if (obj.attachEvent){ 
        var r = obj.attachEvent("on"+evType, fn); 
        return r; 
    } 
    else { 
        return false; 
    } 
}

/** Use this for displaying validation info to the user on the client side.
  * This function assumes that the form label and place for more information
  * are called inputIdLabel and inputIdHelp respectively.
  *
  * @param inputId: id of the input being evaluated
  * @param helpString: string to display for the user
  * @param show: boolean, show or hide the error and help string
  */
KS_Util.prototype.displayErrorInfo = function(inputId, helpString, show) {
    try {
        var helpString = helpString;
        var inputLabel = this.gObj(inputId+"Label"); //Main info label, will turn red
        var inputHelp = this.gObj(inputId+"Help"); //Place to put additional information in red
        var inputContainer = this.gObj(inputId+"Container"); //Place to put additional information in red
        if(show) {
                this.debug("error message to be displayed, input ID: " + inputId);
                if(inputLabel != null && inputLabel.className.indexOf("error") < 0) {
                        this.debug("Label to be set as error: "+inputLabel.id);
                        inputLabel.className = inputLabel.className + " error";
                }
                if(inputHelp != null) {
                        this.debug("Help content to be set as error: "+inputHelp.id);
                        inputHelp.className = inputHelp.className + " error";
                        inputHelp.innerHTML = helpString;
                }
		if(inputContainer != null) {
			this.debug("Changing container style: "+inputContainer.id);
			inputContainer.className = inputContainer.className + " error-container";
		}
        } else {
                this.debug("no errors, let's reinstate the element, input ID: " + inputId);
                if(inputLabel != null) {
                        inputLabel.className = inputLabel.className.replace("error", "");
                }
                if(inputHelp != null) {
                        inputHelp.className = inputHelp.className.replace("error", "");
                        inputHelp.innerHTML = "";
                }
                if(inputContainer != null) {
                        inputContainer.className = inputContainer.className.replace("error-container", "");
                }
        }
    } 
    catch(e) {
        this.debug(e.message);
    }
    return;
}


/**
 * Perform an asynchronous call to the server using the ygConn library
 * Requires ygConnect library to be included on page.  
 * @url : The url of the server side script where the action is to take place
 * @method: GET or POST. Default is GET.
 * @cF  : Callback Function - Called upon server side script completion
 * @argArr : An array of arguments to be passed to the callback function
 * @respIsXml : Boolean indicating a plain-text(false) or XML response(true).
 * @form : String indicating name of form to POST to server.  If none, set to null.
 */
KS_Util.prototype.ajaxCall = function (url, method, cF, argArr, respIsXml, form) {
	if(ygConn) {
		var obj = ygConn.getObject();
		var m = method;
		if(m == null || (m != "POST" && m!= "GET")) { m = "GET" };
		if(form != null && form.length > 0) {
			ygConn.http.setForm(form);
			m = "POST";
		}

		if(cF == null) {
			cF = this.defaultAjaxHandler;
		}
		ygConn.http.asyncRequest(obj, m, url, respIsXml, cF, argArr, null);
	}
}

/**
 * Default AJAX response handler.  Just inserts html into div identified in first parameter.
 * (This should probably never be used, but might be convenient in some cases.) 
 */
KS_Util.prototype.defaultAjaxHandler = function() {
	rsp  = arguments[0]; //Response text/html | or error
	tid  = arguments[1]; //Transaction id
	args = arguments[2]; //Arguments, if any, created during initial ajax call
		
	//Was there an error?  (true if arguments[1] and arguments[2] are null)
	if(tid == null && args == null) {
			return false;
	}
	 	
	//args[0] is the id of the element where rsp.responseText will be inserted into	
	if(args != null && args[0] != null) {
		dest = this.gObj(args[0]);
		if(dest != null) {
				dest.innerHTML = rsp.responseText;
		}
	}
}

KS_Util.prototype.evalJson = function(jsonString) {
	return eval('(' + jsonString + ')');
}

String.nl2br=function(pString){return pString.replace(/\n/g,'<br />\n');}

//escape UTF8
String.escape_utf8=function(pD){
	if(pD==''||pD==null)return '';pD=pD.toString();var bfr='';
	for(var i=0;i<pD.length;i++){
		var c=pD.charCodeAt(i),bs = new Array();
		if (c>0x10000){//4 bytes
			bs[0]=0xF0|((c&0x1C0000)>>>18);
			bs[1]=0x80|((c&0x3F000)>>>12);
			bs[2]=0x80|((c&0xFC0)>>>6);
			bs[3]=0x80|(c&0x3F);
		}else if(c > 0x800){//3 bytes
			bs[0]=0xE0|((c&0xF000)>>>12);
			bs[1]=0x80|((c&0xFC0)>>>6);
			bs[2]=0x80|(c&0x3F);
		}else if(c>0x80){//2 bytes
			bs[0]=0xC0|((c&0x7C0)>>>6);
			bs[1]=0x80|(c&0x3F);
		}else{//1 byte
            bs[0]=c;
        }
		for(var j=0;j<bs.length;j++) {
            var b=bs[j]; 
            var hex=nibble_to_hex((b&0xF0)>>>4)+nibble_to_hex(b & 0x0F); 
            bfr+='%'+hex;
        }
	}
	return bfr;
}

//trim whitespaces on the edges of the string
String.trim=function(s){while(s.substring(0,1)==' ')s=s.substring(1,s.length);while(s.substring(s.length-1,s.length)==' ')s=s.substring(0,s.length-1);return s;}

//find and replace
String.replace=function(find,replace){return this.split(find).join(replace);}

//escape for xml file
String.escapeForXML=function(){return this.replace('&','&amp;').replace('"','&quot;').replace('<','&lt;').replace('>','&gt;');}

//escape xml to non destructive html
String.escapeForDisplay=function(){return this.replace('<','&lt;');}

// Cross Browser selectionStart/selectionEnd
// Version 0.1
// Copyright (c) 2005 KOSEKI Kengo
// 
// This script is distributed under the MIT licence.
// http://www.opensource.org/licenses/mit-license.php

function Selection(textareaElement) {
    this.element = textareaElement;
}

Selection.prototype.create = function() {
    if (document.selection != null && this.element.selectionStart == null) {
        return this._ieGetSelection();
    } else {
        return this._mozillaGetSelection();
    }
}

Selection.prototype._mozillaGetSelection = function() {
    return { 
        start: this.element.selectionStart, 
        end: this.element.selectionEnd 
    };
}

Selection.prototype._ieGetSelection = function() {
    this.element.focus();

    var range = document.selection.createRange();
    var bookmark = range.getBookmark();

    var contents = this.element.value;
    var originalContents = contents;
    var marker = this._createSelectionMarker();
    while(contents.indexOf(marker) != -1) {
        marker = this._createSelectionMarker();
    }
    var selection = range.text;

    var parent = range.parentElement();
    if (parent == null || parent.type != "textarea") {
        return { start: 0, end: 0 };
    }
    range.text = marker + range.text + marker;
    contents = this.element.value;

    var result = {};
    result.start = contents.indexOf(marker);
    contents = contents.replace(marker, "");
    result.end = contents.indexOf(marker);

    this.element.value = originalContents;
    range.moveToBookmark(bookmark);
    range.select();

    return result;
}

Selection.prototype._createSelectionMarker = function() {
    return "##SELECTION_MARKER_" + Math.random() + "##";
}

function hexnib(d) { if(d<10) return d; else return String.fromCharCode(65+d-10); }

function hexbyte(d) { return "%"+hexnib((d&240)>>4)+""+hexnib(d&15);}

function hexcode(url) {
	var result="";
	var hex="";
	for(var i=0;i<url.length; i++) {
		var cc=url.charCodeAt(i);
		if (cc<128) {
			result+=hexbyte(cc);
		} else if((cc>127) && (cc<2048)) {
			result+=  hexbyte((cc>>6)|192)
				+ hexbyte((cc&63)|128);
		} else {
			result+=  hexbyte((cc>>12)|224)
				+ hexbyte(((cc>>6)&63)|128)
				+ hexbyte((cc&63)|128);
		}
	}
	return result;
}

YAHOO.search.answers.cache.setData('boaItemCount', 5);
YAHOO.search.answers.cache.setData('currBoaIndex', 0);
YAHOO.search.answers.cache.setData('boaTimerState', 1);
YAHOO.search.answers.cache.setData('boaAnimating', false);
function displayFeaturedItem(index, forward) {
	currBoaIndex = YAHOO.search.answers.cache.getData('currBoaIndex');
	animating = YAHOO.search.answers.cache.getData('boaAnimating');
	if(index != currBoaIndex && !animating) {
		YAHOO.search.answers.cache.setData('boaAnimating', true);
		if(forward == null) {
			forward = (index - currBoaIndex > 0);
		}

		boaContent = Util.gObj("boa-content");
		currItem = Util.gObj("fc-"+currBoaIndex);
		newItem = Util.gObj("fc-"+index);

		YAHOO.util.Dom.setStyle(newItem, 'position', 'absolute');

		startPos = 460;
		if(!forward) {
			startPos *= -1;
		}
		YAHOO.util.Dom.setStyle(newItem, 'left', startPos+'px');
		YAHOO.util.Dom.setStyle(newItem, 'display', 'block');

		if(boaContent && currItem && newItem) {

			var finishFade = function() {
				var el = this.getEl();
				YAHOO.util.Dom.setStyle(el, 'display', 'none');
				YAHOO.util.Dom.setStyle(el, 'opacity', 1);
				YAHOO.search.answers.cache.setData('boaAnimating', false);
			}

			YAHOO.util.Dom.setStyle(currItem, 'opacity', 1);
			YAHOO.util.Dom.setStyle(currItem, 'background-color', '#fff');
			var fadeAnim = new YAHOO.util.Anim(currItem, { opacity: { to: 0 }}, 0.6, YAHOO.util.Easing.easeOut);
			fadeAnim.onComplete.subscribe(finishFade); 
			fadeAnim.animate();
			var flyAnim = new YAHOO.util.Anim(newItem, { left: { from: startPos, to: 0 } }, 0.5, YAHOO.util.Easing.easeBoth); 
			flyAnim.animate(); 

			YAHOO.search.answers.cache.setData('currBoaIndex', index);
			itemCount = YAHOO.search.answers.cache.getData('boaItemCount');
			for(i = 0 ; i < itemCount ; i++) {
				p = Util.gObj("bp-"+i);
				if(i != index) {
					p.className = '';
				} else {
					p.className = 'active';
				}
			}
			updateBoaAttributes(index);
			resetBoaTimer();
		}
	}
}

function updateBoaAttributes(index) {
	var newTitle = Util.gObj("fc-title-"+index);
	if(newTitle) {
		var title = Util.gObj("boa-title");
		title.innerHTML = newTitle.value;
	}
}

function previousFeaturedItem() {
	currBoaIndex = YAHOO.search.answers.cache.getData('currBoaIndex');
	itemCount = YAHOO.search.answers.cache.getData('boaItemCount');
	if(currBoaIndex > 0) {
		displayFeaturedItem(currBoaIndex - 1, false);
	} else {
		displayFeaturedItem(itemCount - 1, false);
	}
}

function nextFeaturedItem() {
	currBoaIndex = YAHOO.search.answers.cache.getData('currBoaIndex');
	itemCount = YAHOO.search.answers.cache.getData('boaItemCount');
	if(currBoaIndex < itemCount - 1) {
		displayFeaturedItem(currBoaIndex + 1, true);
	} else {
		displayFeaturedItem(0, true);
	}
}

function startBoaTimer() {
	stopBoaTimer();
	timer = setTimeout("nextFeaturedItem()", 5000);
	YAHOO.search.answers.cache.setData('boaTimer', timer);
	YAHOO.search.answers.cache.setData('boaTimerState', 1);
}

function stopBoaTimer() {
	timer = YAHOO.search.answers.cache.getData('boaTimer');
	if(timer) {
		clearTimeout(timer);
	}
	YAHOO.search.answers.cache.setData('boaTimerState', 0);
}

function resetBoaTimer() {
	boaTimerState = YAHOO.search.answers.cache.getData('boaTimerState');
	if(boaTimerState) {
		stopBoaTimer();
		startBoaTimer();
	}
}

function toggleBoaTimer() {
	boaTimerState = YAHOO.search.answers.cache.getData('boaTimerState');
	button = Util.gObj('ctrl-pause');
	if(boaTimerState) {
		button.className = "play";
		stopBoaTimer();
	} else {
		button.className = "pause";
		startBoaTimer();
	}
}