/**
 *  @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! Hỏi & Đáp",
		version : "",
		locale : 'vn_VN',
		ua : navigator.userAgent.toLowerCase(),
		
		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();
		        }
		    }
		}()
	},
	HTML: {
		images : {
			img_green_busy : {
				src : "http://l.yimg.com/a/i/us/sch/gr2/greenbusy.gif",
				description : "Đang tải..."
			},
			img_small_grey_busy :{
			 src : "http://l.yimg.com/a/i/us/pim/dclient/img/md5/c8ad9845c9414424cb5854238af212b0_1.gif",
			 description : "Đang tải..." 
			}
		}
	},
	bookmarks : {
		save : function (title, url, myweburl) {
    		window.open(myweburl+'savebm?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;
		}
	},
	/* Profile restriction utilities */
	restrict : {
		request_handler : "/common/util/ks-urp-xhr-handler.php",
		
		ACTION_CONSTANT : "method",
		ACTION_HIDE_QNA : "hidePublicQnA",
		ACTION_SHOW_QNA : "showPublicQnA",
		ACTION_HIDE_CONTACTS : "hidePublicContacts",
		ACTION_SHOW_CONTACTS : "showPublicContacts",
		
		MSG_HIDE_QNA : "Nếu bạn mở tùy chọn này, các câu hỏi, câu trả lời và câu trả lời được đánh dấu sao sẽ không được hiển thị công khai trên trang Hồ Sơ Yahoo! Hỏi & Đáp.",
		MSG_SHOW_QNA : "Nếu bạn mở tùy chọn này, các câu hỏi, câu trả lời và câu trả lời được đánh dấu sao sẽ được hiển thị công khai trên trang Hồ Sơ Yahoo! Hỏi & Đáp.",
		MSG_HIDE_CONTACTS : "Nếu mở tùy chọn này, danh sách Liên Lạc của bạn sẽ không được hiển thị công khai trên trang Hồ sơ Yahoo! Hỏi & Đáp.",
		MSG_SHOW_CONTACTS : "Nếu mở tùy chọn này, danh sách Liên Lạc của bạn sẽ được hiển thị công khai trên trang Hồ sơ Yahoo! Hỏi & Đáp.",
	
        initToolTips : function(){
    		var tt3 = new YAHOO.widget.Tooltip("tt-invite", {context: 'profile-hide-qa', hidedelay: 1000 } );
	    	var tt4 = new YAHOO.widget.Tooltip("tt-invite", {context: 'profile-hide-contacts', hidedelay: 1000 } );
        },
		/*
		 * Setting the visibility of the QnA and Contacts/Fans section of the
		 * profile page on the public view.
		 */
		setHideQnA : function(doHide) {
			// var updateCheckboxState = function(wasChanged) { oAnswers.util.$('profile-hide-qa-cb').checked = (wasChanged ? doHide : !doHide); };
			return (doHide ?
				this.confirmShowHide(this.ACTION_HIDE_QNA, this.MSG_HIDE_QNA, 'profile-hide-qa-cb')
				:
				this.confirmShowHide(this.ACTION_SHOW_QNA, this.MSG_SHOW_QNA, 'profile-hide-qa-cb')
				);
		},
		
		setHideContacts : function(doHide) {
			// var updateCheckboxState = function(wasChanged) { alert(typeof(oAnswers.util.$('profile-hide-contacts-cb')) + " and " + (wasChanged ? doHide : !doHide)); oAnswers.util.$('profile-hide-contacts-cb').checked = (wasChanged ? doHide : !doHide); };
			return (doHide ?
				this.confirmShowHide(this.ACTION_HIDE_CONTACTS, this.MSG_HIDE_CONTACTS, 'profile-hide-contacts-cb')
				:
				this.confirmShowHide(this.ACTION_SHOW_CONTACTS, this.MSG_SHOW_CONTACTS, 'profile-hide-contacts-cb')
				);
		},
		
		updateCheckboxState : function(doHide, wasChanged, cbID) {
			oAnswers.util.$(cbID).checked = (wasChanged ? doHide : !doHide);
		},
		
		/* Show the dialogue to confirm the changes to the profile */
		confirmShowHide : function(method, _msg, cbID) {
			var _headerText = "Bạn có chắc không?";
			var doHide = (method == oAnswers.restrict.ACTION_HIDE_QNA || method == oAnswers.restrict.ACTION_HIDE_CONTACTS);
			var cfgButtons = [
				{
					text:"Ok",
					handler: function() {
						try {
							var _crumb = Util.gObj('crumb').value;
							var _uri = oAnswers.restrict.request_handler + "?" +
								oAnswers.restrict.ACTION_CONSTANT + "=" + method +
								"&curtime=" + (new Date().getTime().toString()) +
								"&.crumb=" + _crumb;
							var callback = { 
								success: function() { return true; },
								failure: function() { return true; },
								argument: []
							};
							oAnswers.util.Ajax.request(_uri, callback);
						} catch(e) {
							// Sending the hide command threw an error
						}
						oAnswers.restrict.updateCheckboxState(doHide, true, cbID);
						this.hide();
						this.destroy();
						return true;
					},
					isDefault:true
				},
				{
					text:"Hủy",
					handler: function() {
						oAnswers.restrict.updateCheckboxState(doHide, false, cbID);
						this.hide();
						this.destroy();
						return false;
					}
				}
				];
			/* Using a new dialog instance here because it is different than the oAnswers.dialog
			 * in that it has an Ok/Cancel button set.  The init function of oAnswers.dialog also
			 * doesn't let you override the buttons, it returns unless the instance property is
			 * null, so closures were keeping the button functionality the same between dialog's.
			 */
			restrictDialog = new YAHOO.widget.Dialog(
				"restrictDialogPanel",
				{ 
					modal:true, 
					visible:true, 
					width:"373px", 
					fixedcenter:true, 
					constraintoviewport:true, 
					draggable:false,
					close : false,
					underlay:'none'
				}
				);
			restrictDialog.cfg.queueProperty("buttons",cfgButtons);
			restrictDialog.setHeader(_headerText);
			restrictDialog.setBody(_msg);
			restrictDialog.render(document.body);
			restrictDialog.show();
		}
	},
	// relationships
	relationships : { 
		
		request_handler : "/common/util/ks-urp-xhr-handler.php",

		ACTION_ADD : "addFriend",
		ACTION_REMOVE : "removeFriend",
        ACTION_BLOCK : "blockUser",
        ACTION_UNBLOCK : "unBlockUser",
		ACTION_REMOVE_FANS : "removeFans",
		ACTION_CONSTANT : "method",
		ACTION_SUCCESS : "action_success",
		ACTION_ERROR : "action_error",	
		
		getRequestHandler : function() { return this.request_handler; },

		/**
		 * @description main response handler for URP Ajax requests
		 * @param response object from YUI connection manager
		 */
		handleResponse : function(response) {
			try {
            	var rsp = response.responseText;
            	var tid = response.tId;// transaction Id
            	var args = response.argument;
            	//if ((tid == null && args == null) || (response.status == 0))
            	var _kid = args[0]; //get the $kid
                var _action = args[1]; //what action had been performed
                var _nickname = args[2];
                if ("" == _nickname) _nickname = "Anh ấy/cố ấy";
                var _msg = "";
                var svar = rsp;
                var v = rsp.lastIndexOf('\n');
                if (v != -1) svar = rsp.substr(v+1);
		        var _headerText = oAnswers.dialog.writeStatusIconInHeader('yield',("Mạng của tôi"));
                switch (svar) { //toggle against the response text which is an error code (int)
                	case "0":
		                if (oAnswers.relationships.ACTION_ADD == _action) {
		                	_headerText = oAnswers.dialog.writeStatusIconInHeader('blueman',(_nickname + " đã thêm vào Danh bạ"));
		                	_msg = _nickname + " đã được thêm vào Danh bạ của bạn thành công";
		                	oAnswers.relationships.updateAddFriendFromList(_kid,_nickname);
		                }
		                else if (oAnswers.relationships.ACTION_REMOVE == _action) {
		                	_headerText = oAnswers.dialog.writeStatusIconInHeader('blueman',(_nickname + " đã xóa khỏi Danh bạ"));
		                	_msg = _nickname + " đã được xóa khỏi Danh bạ của bạn thành công";
		                	oAnswers.relationships.updateRemoveFriendFromList(_kid,_nickname);
		                }
                        else if (oAnswers.relationships.ACTION_BLOCK == _action) {
                            _str = _nickname + " đã được thêm vào danh sách \"Người Bị Chặn\"";
                            _headerText = oAnswers.dialog.writeStatusIconInHeader('block',(_str));
                            _msg = _nickname + " sẽ không thể thêm bạn vào danh sách Liên Lạc nữa.  " + _nickname + 
                                " sẽ không thể truy cập vào mục Hỏi & Đáp và Mạng Bạn bè trên trang Hồ Sơ công khai của bạn.";
		                	oAnswers.relationships.updateBlockUser(_kid,_nickname);
                        }
                        else if (oAnswers.relationships.ACTION_UNBLOCK == _action) {
                            _str = _nickname + " đã được xóa khỏi danh sách Người Bị Chặn";
                            _headerText = oAnswers.dialog.writeStatusIconInHeader('block',(_str));
                            _msg = _nickname + " bây giờ có thể thêm bạn vào danh sách Liên Lạc  " + _nickname +
                                " cũng có thể truy cập vào mục Hỏi & Đáp và Mạng Bạn bè trên trang Hồ Sơ công khai của bạn.";
		                	oAnswers.relationships.updateUnBlockUser(_kid,_nickname);
                        }
                		break;
                	case "-1":
	                	_headerText = oAnswers.dialog.writeStatusIconInHeader('yield',("Oops"));
                		_msg = "Rất tiếc, chúng tôi đã thực hiện sai một thao tác nào đó, vui lòng thử lại";
                		break;
                	case "-2":
	                	_headerText = oAnswers.dialog.writeStatusIconInHeader('yield',("Oops"));
                		_msg = "Rất tiếc, chúng tôi đã thực hiện sai một thao tác nào đó, vui lòng thử lại";
                		break;
                	case "-3": //limits to # of contacts (currently 200)
				        _headerText = oAnswers.dialog.writeStatusIconInHeader('yield',("Rất tiếc, bạn đã đạt mức giới hạn danh bạ của mình"));
                		_msg = "Bạn cần <a href=\"/my/contacts/connections/\">xóa bớt địa chỉ khỏi danh sách liên lạc của mình</a> để dành chỗ cho những người mới";
                		break;
                	case "-4":
                		_headerText = oAnswers.dialog.writeStatusIconInHeader('yield',("Không thể thêm vào Danh bạ của bạn"));
                        _msg = "Người này hiện không cho phép bất cứ ai thêm họ vào Danh bạ";
                		break;
                    case "-5":
                		_headerText = oAnswers.dialog.writeStatusIconInHeader('yield',("Không thể thêm vào Danh bạ của bạn"));
                        _msg = "Bạn không thể thêm chính mình làm bạn bè";
                        break;
                    case "-6": // removed the fans from a kpUser
                        doCheckMyEditPreviewFansRemoveResponse(true); //calls from /js/k-search-my.js
                        _headerText = oAnswers.dialog.writeStatusIconInHeader('blueman',("Chúng tôi đã xóa những Người hâm mộ của bạn"));
                        _msg = "Chúng tôi đã xóa những Người hâm mộ của bạn";
                        break;
                    case "-7": // error removing fans from a kpUser
                        doCheckMyEditPreviewFansRemoveResponse(false); //calls from /js/k-search-my.js
                        _headerText = oAnswers.dialog.writeStatusIconInHeader('yield',("Rất tiếc."));
                        _msg = "Hãy thử lại.";
                        break;
                    case "-9":
                		_headerText = oAnswers.dialog.writeStatusIconInHeader('yield',("Không thể thêm vào Danh bạ của bạn"));
                        _msg = "Hiện tại, bạn không thể thêm người này vào Danh Sách của bạn.";
                        break;
                    case "-11":
                		_headerText = oAnswers.dialog.writeStatusIconInHeader('yield',("Bạn đã đạt tới mức giới hạn những Người Bị Chặn."));
                        _msg = "Rất tiếc, bạn đã vượt quá mức chặn tối đa 200 người dùng. Bạn cần  <a href=\"/my/contacts/connections/\"> xóa bớt số người trong danh sách Người Bị Chặn của bạn trước khi có thể thêm vào người khác.";
                        break;
                	default:
	                	_headerText = oAnswers.dialog.writeStatusIconInHeader('yield',("Oops"));
                		_msg = "Rất tiếc, chúng tôi đã thực hiện sai một thao tác nào đó, vui lòng thử lại";
                		break;
                }
                if ("" != _msg) {
					var cfgButtons = [ { text:"OK", handler:oAnswers.dialog.cancel, isDefault:true } ];
   					oAnswers.dialog.init(cfgButtons,"");
					oAnswers.dialog.activate(_headerText, _msg);	
                }
                else {
                	//throw new Error("no set message");
                }
            }
            catch (e) {
                alert("failure: " + e.message);
            }
		},
		updateRemoveFriendFromList : function(pKid,pNickname) {
            oAnswers.relationships.updateWhoisCardInfo(pKid, pNickname, "0", "add", "");
            if ((location.href.indexOf('/my/')!=-1) && (location.href.indexOf('/my/profile')==-1)){
                // my profile page... either contacts or fans tab
                activeTab = oProfile.getActiveTab();
                if (activeTab.indexOf('fans')!=-1){
                    if (location.href.indexOf('/connections')==-1){
                        tabId = 'ks-user-profile-contacts-list';
                        oCache.setData(tabId + "_cache", null);
                    }

                    // either way, remove the blue man icon
                    _nameTitle_ele = Util.gObj('user-profile-nickname-link_'+ pKid);
                    if (null != _nameTitle_ele && "undefined" != _nameTitle_ele){
                        _nameTitle_ele.className = "";
                        if (_nameTitle_ele.innerHTML.indexOf('img')!=-1)
                            _nameTitle_ele.removeChild(_nameTitle_ele.childNodes[0]);
                    }
                }
                else {
                    if (location.href.indexOf('/connections')==-1){
                        tabId = 'ks-user-profile-contacts-list';
                        oCache.setData(tabId + "_cache", null);
                        dtpKid = oCache.getData('togglePeepsParamKid');
                        dtpPreview = oCache.getData('togglePeepsParamPreview');
                        setTimeout("oProfile.doTogglePeeps('" + tabId + "', '" + dtpKid + "', " + dtpPreview + ", true)", 10);
                        
                        tabId = 'ks-user-profile-fans-list';
                        oCache.setData(tabId + "_cache", null);
                    }
                    else {
                        // connections contacts page, just hide the contact and the remove link
                        _ele = Util.gObj('user-profile_' + pKid);
                        if (_ele) YAHOO.util.Dom.setStyle(_ele.parentNode.parentNode,'display','none');

                        _nameTitle_ele = Util.gObj('remove-contact-profile-'+ pKid);
                        if (null != _nameTitle_ele && "undefined" != _nameTitle_ele){
                            _nameTitle_ele.style.visibility = "hidden";
                        } 
                    }
                }
            }
            else {
                _nameTitle_ele = Util.gObj('user-profile-nickname-link_'+ pKid);
                if (null != _nameTitle_ele && "undefined" != _nameTitle_ele){
                    _nameTitle_ele.className = "";
                    if (_nameTitle_ele.innerHTML.indexOf('img')!=-1)
                        _nameTitle_ele.removeChild(_nameTitle_ele.childNodes[0]);
                }
            }
		},
		updateAddFriendFromList : function(pKid,pNickname) {
			try {
                oAnswers.relationships.updateWhoisCardInfo(pKid, pNickname, "1", "remove", "friend_question");

                // this adds the blue man icon next to the nickname anywhere
				_ele = Util.gObj('user-profile-nickname-link_' + pKid);
				if (null != _ele && "undefined" != _ele) {
					_ele.className = "friend_photo";
                    if (_ele.innerHTML.indexOf('img')==-1){
                        _img_elem = document.createElement('img');
                        _img_elem.setAttribute('src', "http://l.yimg.com/a/i/nt/ic/ut/bsc/bud12_1.gif");
                        _img_elem.setAttribute('alt', "Người này thuộc một trong các địa chỉ liên lạc của tôi");
                        _ele.insertBefore(_img_elem, _ele.childNodes[0]);
                    }
				}

	       
                if ((location.href.indexOf('/my/')!=-1) && (location.href.indexOf('/my/profile')==-1)){
                    // we're on the fans tab... only clear contact cache data if we have under 6 contacts
                    var tabId = 'ks-user-profile-contacts-list';
                    d = document.createElement('div');
                    d.innerHTML = oCache.getData(tabId + "_cache");
                    if (YAHOO.util.Dom.getElementsByClassName('rollover-profile-content', 'div', d).length < 6)
                        oCache.setData(tabId + '_cache', null);
                }
			}
			catch(e) {
				
			}
			finally {
				_ele = null; _nameTitle_ele = null;
			}
		},
        updateBlockUser : function(pKid, pNickname){
            oAnswers.relationships.updateWhoisCardInfo(pKid, pNickname, "2", "unBlock", "block_question");

            // if i am on *my* profile page [not connections page]
            if ((location.href.indexOf('/my/')!=-1) && (location.href.indexOf('/my/profile')==-1) && (location.href.indexOf('/connections')==-1)){
                // i just blocked, so i must be on the fans tab
                tabId = 'ks-user-profile-fans-list';
                oCache.setData(tabId + "_cache", null);
                dtpKid = oCache.getData('togglePeepsParamKid');
                dtpPreview = oCache.getData('togglePeepsParamPreview');
                setTimeout("oProfile.doTogglePeeps('" + tabId + "', '" + dtpKid + "', " + dtpPreview + ", true)", 10);

                // check to see if we should clear the blocked list cache or not
                tabId = 'ks-user-profile-blocked-list';
                d = document.createElement('div');
                d.innerHTML = oCache.getData(tabId + '_cache');
                if (YAHOO.util.Dom.getElementsByClassName('rollover-profile-content', 'div', d).length < 6)
                    oCache.setData(tabId + "_cache", null);
            }
            else if ((location.href.indexOf('/connections')!=-1) && (location.href.indexOf('show=')==-1)){
                // on my network page, if i blocked (must be on fans tab), just remove that fan
                _ele = Util.gObj('user-profile_' + pKid);
                if (_ele) YAHOO.util.Dom.setStyle(_ele.parentNode.parentNode,'display','none');
            }
            else {
                // anywhere else, just add the block symbol
				_ele = Util.gObj('user-profile-nickname-link_' + pKid);
                if (_ele && _ele != "undefined"){
                    _ele.className = "block_photo";
                    if (_ele.innerHTML.indexOf('img')==-1){
                        _img_elem = document.createElement('img');
                        _img_elem.setAttribute('src', "http://l.yimg.com/a/i/nt/ic/ut/bsc/blck12_1.gif");
                        _ele.insertBefore(_img_elem, _ele.childNodes[0]);
                    }
                }
            }
        },
        updateUnBlockUser : function(pKid, pNickname){
            oAnswers.relationships.updateWhoisCardInfo(pKid, pNickname, "0", "add", "");

            var activeTab = oProfile.getActiveTab();
            if (activeTab.indexOf('blocked')!=-1){
                tabId = 'ks-user-profile-blocked-list';
                // must be on my profile page
                if (location.href.indexOf('/connections')==-1){
                    dtpKid = oCache.getData('togglePeepsParamKid');
                    dtpPreview = oCache.getData('togglePeepsParamPreview');
                    setTimeout("oProfile.doTogglePeeps('" + tabId + "', '" + dtpKid + "', " + dtpPreview + ", true)", 10);
                }
                else {
                   // on connections page, just hide the guy and the link
                   _ele = Util.gObj('user-profile_' + pKid);
                   if (_ele) YAHOO.util.Dom.setStyle(_ele.parentNode.parentNode,'display','none');
                }
            }
            else {
                // just remove the block sign 
                _ele = Util.gObj('user-profile-nickname-link_' + pKid);
                if (null != _ele && "undefined" != _ele) {
                    _ele.className = "";
                    if (_ele.innerHTML.indexOf('img')!=-1)
                        _ele.removeChild(_ele.childNodes[0]);
                }
            }
        },
        updateWhoisCardInfo : function(pKid, pNickname, friendCode, peepsOp, titleClass){
            // id card related change
            var _ele = Util.gObj('member-is-friend_' + pKid);
            if (null != _ele && "undefined" != _ele) {
                _ele.innerHTML = friendCode;
            }

            // this is for the top whois card on the profile page
            var _profile_link = Util.gObj('add_remove_link-' + pKid);
            if (null != _profile_link && "undefined" != _profile_link){
                _profile_link.innerHTML = oAnswers.profile.doWritePeepsLink(peepsOp,pKid,pNickname);    
            }

            //on profile pages, let's add the blue man on the top whois card by the person's name
            var _nameTitle_ele = Util.gObj('user-profile-title-username-'+ pKid);
            if (null != _nameTitle_ele && "undefined" != _nameTitle_ele)
                _nameTitle_ele.className = titleClass;
        },
		// makes ajax request
		update : function(pUri,pCallback) {
            oAnswers.util.Ajax.request(pUri, pCallback);
       	},
       	removeFans : function() {
			try {
                var _crumb = Util.gObj('crumb').value;
                var _uri = this.request_handler + "?" + this.ACTION_CONSTANT + "=" + this.ACTION_REMOVE_FANS + "&.crumb=" + _crumb;
                var callback = {
                    success: oAnswers.relationships.handleResponse,
                    failure: oAnswers.relationships.handleResponse,
					argument: [null,this.ACTION_REMOVE_FANS,null]
                }
                var image_loading_url = oAnswers.HTML.images['img_small_grey_busy'].src;
				var _headerText = oAnswers.dialog.writeStatusIconInHeader('blueman',"Đang giải quyết ....");
				var _tmpStr  = "<img src=\"" + image_loading_url + "\" style=\"margin:3px 2px 0 0;\" border=\"0\">";
				    _tmpStr += "Đang xóa những Người hâm mộ, hãy đợi.";
				var _bodyText = _tmpStr;
				var cfgButtons = [ 
					//{ text:"Tiếp tục", handler:oAnswers.dialog.cancel },
	                //{ text:"Hủy", handler:function() {void(0);} } 
	            ];
	            oAnswers.dialog.init(cfgButtons,"");
				oAnswers.dialog.activate(_headerText, _bodyText);
                oAnswers.util.Ajax.request(_uri, callback);
			} 
			catch(e) { 
			    alert(e,true); 
			}
			finally {
			    //TODO?
			}
       	},
        addFriend : function(pKid) {
            pNickname = oProfile.getNickname(pKid);
			try {
                var _crumb = Util.gObj('crumb').value;
                var timestamp = "&curtime=" + (new Date().getTime().toString());
				var _uri = this.request_handler + "?" + this.ACTION_CONSTANT + "=" + this.ACTION_ADD +
					"&kid=" + pKid + timestamp + "&.crumb=" + _crumb;
				var callback = { 
					success: oAnswers.relationships.handleResponse,
                    failure: oAnswers.relationships.handleResponse,
        			argument: [pKid,this.ACTION_ADD,pNickname]    
	            }
            	oAnswers.util.Ajax.request(_uri, callback);				
			} 
			catch(e) {
				//alert("failure:" + e.message);
			}
		},
        blockUser : function(pKid) {
            pNickname = oProfile.getNickname(pKid);
			try {
                var _crumb = Util.gObj('crumb').value;
                var timestamp = "&curtime=" + (new Date().getTime().toString());
				var _uri = this.request_handler + "?" + this.ACTION_CONSTANT + "=" + this.ACTION_BLOCK +
					"&kid=" + pKid + timestamp + "&.crumb=" + _crumb;
				var callback = { 
					success: oAnswers.relationships.handleResponse,
                    failure: oAnswers.relationships.handleResponse,
        			argument: [pKid,this.ACTION_BLOCK,pNickname]    
	            }
            	oAnswers.util.Ajax.request(_uri, callback);				
			} 
			catch(e) {
				//alert("failure:" + e.message);
			}
		},
        unBlockUser : function(pKid){
            pNickname = oProfile.getNickname(pKid);
			try {
                var _crumb = Util.gObj('crumb').value;
                var timestamp = "&curtime=" + (new Date().getTime().toString());
				var _uri = this.request_handler + "?" + this.ACTION_CONSTANT + "=" + this.ACTION_UNBLOCK +
					"&kid=" + pKid + timestamp + "&.crumb=" + _crumb;
				var callback = { 
					success: oAnswers.relationships.handleResponse,
                    failure: oAnswers.relationships.handleResponse,
        			argument: [pKid,this.ACTION_UNBLOCK,pNickname]    
	            }
            	oAnswers.util.Ajax.request(_uri, callback);				
			} 
			catch(e) {
				//alert("failure:" + e.message);
			}
        },
		removeFriend : function(pKid, pNickname) {
		    if(!pNickname) {
                pNickname = oProfile.getNickname(pKid);
            }
			try {
                var _crumb = Util.gObj('crumb').value;
                var timestamp = "&curtime=" + (new Date().getTime().toString());
                var _uri = this.request_handler + "?" + this.ACTION_CONSTANT + "=" + this.ACTION_REMOVE +
                        "&kid=" + pKid + timestamp + "&.crumb=" + _crumb;
                var callback = {
                    success: oAnswers.relationships.handleResponse,
                    failure: oAnswers.relationships.handleResponse,
					argument: [pKid,this.ACTION_REMOVE,pNickname]
                }
                oAnswers.util.Ajax.request(_uri, callback);
			} 
			catch(e) { oAnswers.debug(e,true); }
			finally {
				oAnswers.profile.doCloseIdCard();
			}
		},
		handleRemoveCheck : function(pEle,pIsChecked) {
			var _ele = pEle;
			_ele.checked = pIsChecked;
			var _changed_flag_ele = Util.gObj('is_peeps_just_changed_allow_users_as_fans');
			if (null != _changed_flag_ele && "undefined" != _changed_flag_ele) {
			     _changed_flag_ele.value="y"; 
			}
			oAnswers.dialog.instance.hide();
		},
		handleRemovingFansDiscoverability : function(pEle) {
			var _ele = pEle;
			if (!_ele.checked) {
				var _headerText = oAnswers.dialog.writeStatusIconInHeader('yield',"Bạn chắc chắn không muốn người hâm mộ?");
				var _bodyText = "Khi bạn bỏ dấu chọn trong ô này, những người sử dụng Hỏi & Đáp khác sẽ không còn dễ dàng tìm thấy bạn và tác phẩm mới nhất của bạn trên Hỏi & Đáp.";
				var cfgButtons = [ 
					{ text:"Tiếp tục", handler:function() {oAnswers.relationships.handleRemoveCheck(_ele,false); var peepnotify = document.getElementById('is_peeps_allow_notifications'); if(peepnotify) peepnotify.checked = false; } }, 
	                { text:"Hủy", isDefault:true, handler:function() {oAnswers.relationships.handleRemoveCheck(_ele,true);} } 
	            ];
	            oAnswers.dialog.init(cfgButtons,"");
				oAnswers.dialog.activate(_headerText, _bodyText);
			}
		},
		countInvitees : 2,
		/*	@param pElementToAppendTo
		 *  @param pElementToClone
		 * */
        addInvitee : function(pElementToClone,pElementToAppendTo) {
        	try {
	            var _ele = Util.gObj(pElementToClone); //always clone the first one
	            var _clonedNode = _ele.cloneNode(true);
	                _clonedNode.id = "";
	                var _inputs = _clonedNode.getElementsByTagName('INPUT');
	                for (var _j=0; _j<_inputs.length; _j++) {
	                	_inputs[_j].value = "";
	                }
	            var _toAppend = Util.gObj(pElementToAppendTo);
	                _toAppend.appendChild(_clonedNode);
	            if (_inputs.length > 0) _inputs[0].focus();
        	}
        	catch (e) {
        		oAnswers.debug(e,true)	
        	}
        	finally {
        		_ele = null; _clonedNode = null; _toAppend= null;
        	}
        }
	/* END of .relationships */
	},
	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++) 
            {
                oAnswers.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 = ""; 
            	}
            }
            Util.gObj(pId).style.display = "block";
            Util.gObj(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;
        }
    },
    dialog : {
    	ELE_DIALOG    : { id: "dialog", type: null },
    	ELE_DIALOG_HD : { id: "dialog_heading", type:"DIV"  },
    	ELE_DIALOG_BD : { id: "dialog_content", type:"DIV"  },
        
        instance : null,
        getInstance : function(){
        	return this.instance;
        },
        
        submitCallback : function(obj) {
            var response = obj.responseText;
        },

        submitFailure : function(obj) {
            alert("Submission failed: " + obj.status);
        },
        
        /**
         *	@param: pCfgButtons (obj.literal)
         *  @param: pClassname (string): the className to set the dialog obj to inherit   
         */
        init : function(pCfgButtons,pClassname){
        	if (null != this.instance) return;
        	
			//the basics are set here to keep the look and feel consistent
            this.instance = new YAHOO.widget.Dialog(
                oAnswers.dialog.ELE_DIALOG['id'], 
                { 
                    modal:true, 
                    visible:true, 
                    width:"373px", 
                    fixedcenter:true, 
                    constraintoviewport:true, 
                    close:true,
                    draggable:false ,
                    underlay:'none'
                }
            );
            
            var handleCancel = function() { this.instance.cancel(); }
			
            this.instance.callback.success = this.submitCallback;
            this.instance.callback.failure = this.submitFailure;

            var listeners = new YAHOO.util.KeyListener(document, { keys : 27 }, 
                {fn:handleCancel,scope:this.dialog,correctScope:true} );
            
            this.instance.cfg.queueProperty("keylisteners", listeners);
            
			//let's set the buttons in the dialog
            if (null != pCfgButtons && "object" == typeof pCfgButtons) {
                this.instance.cfg.queueProperty("buttons",pCfgButtons);
            }
            
            this.instance.render();
        },
        destroy : function() {
        	oAnswers.dialog.instance = null;
        },
		cancel : function() {
			oAnswers.dialog.instance.hide();
		},
		writeStatusIconInHeader : function(pIcon,pStr) {
			var _style = "ico-blank";
			switch (pIcon) {
				case "blueman":
					_style = "ico-blue-buddy"
					break;
				case "star":
					_style = "ico-starred";
					break;
				case "yield":
					_style = "ico-yield";
					break;
                case "block":
                    _style = "ico-block";
                    break;
				default:
					break;
			}
			return '<span class="' + _style + '">' + pStr + '</span>'
			
		},
        activate : function(pHeading, pContent, pCfgButtons){
            pHeading = pHeading.replace(/&amp;/g, '&');
            pContent = pContent.replace(/&amp;/g, '&');
            oAnswers.dialog.instance.setHeader(pHeading);
            oAnswers.dialog.instance.setBody(pContent);  
            oAnswers.dialog.instance.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 + "')", 100);
                oCache.setData(name, timer);
            }
        },
        removeFromStarList : function(qid, crumb){
            var uri = "/common/util/ks-qa-xhr-handler.php" +
               "?method=removeFromStarredList&qid=" + qid + "&.crumb=" + crumb;
            var callback = { success: oAnswers.starflag.removeFromStarListResponse,
                             failure: oAnswers.starflag.removeFromStarListResponse,
                             argument: [qid] }
            oAnswers.util.Ajax.request(uri, callback);
        },
        removeFromStarListResponse : 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];
            // todo: "hide the question here... maybe?"
        },
        is_self_starred: false ,
        starToggle: function(qid, count, starred, module, crumb, xhrh){
           // artificial locking of this so multiple clicks don't fire
           if (oCache.getData('starToggle_' /*+ qid */) == 1) return;
           // okay, set it (also see getStarToggleResponse where it is removed)
           oCache.setData('starToggle_' /*+ qid */, 1);

           /* this block of code "fakes" the star by artificially
              incrememting/decrementing the count and by changing
              the resulting type of star seen */
           if(module == 2) {
				num_total_kids = starred ? count - 1 : count + 1;
               oAnswers.starflag.is_self_starred = !starred;
           }
           var _pfx = [ '' ];
           if (module < 2) _pfx = [ '', 'b' ];     
           else if (module != 2) _pfx = [ 'pq', 'pa', 'ps', 'pw' ];
           for (var _i=0; _i<_pfx.length; _i++){
              var star = Util.gObj("starflag_area-" + _pfx[_i] + qid);
              if (star){
                  var targetclass = (starred? "qstar2" : "qstar-starred2");
                  // var first = star.childNodes[1];
                  var first = star.getElementsByTagName('div');
                  if (module == 2) first = first[1];
                  else first = first[0];
                  var newclassname = first.className.split(' ')[0] + " " + targetclass;
                  first.className = newclassname;
                  first.title = "";
                  
                  /*
                  var node = first.getElementsByTagName('span')[0];
                  var current = node.innerHTML *= 1;
                  if (!starred) current += 1;
                  else current -= 1;
                  node.innerHTML = current;
                  */
              }
           }
           // if (starred) setTimeout("oAnswers.starflag.restoreHover('" + qid + "', " + module + ")", 1500);
           /*--------------------------------------------------------------*/
 
            var method = (starred? "unStarItem" : "starItem");

            var timestamp = "&curtime=" + (new Date().getTime().toString());
            var uri = xhrh +
               "?method=" + method + "&qid=" + qid + "&stars=" + count +
               "&p=" + module + "&.crumb=" + crumb + timestamp;
            var callback = { success: oAnswers.starflag.getStarToggleResponse,
                             failure: oAnswers.starflag.getStarToggleResponse,
                             argument: [qid, module, starred] }
            oAnswers.util.Ajax.request(uri, callback);
        },
        getStarToggleResponse : function(response){
            var args = response.argument;
            oAnswers.starflag.getGenericStarFlagResponse(response);

            var qid = args[0];
            // this is to "unlock" operations on this question
            oCache.setData('starToggle_' /* + qid */, 0);

            var module = args[1];
            if (module == 2){
                var starred = !args[2];
				//@TODO uncomment out saf_attach_pagination_events(0) call
		                //saf_attach_pagination_events(0);
				var starred_list_display = YAHOO.util.Dom.getStyle('saf-starrers-list-wrapper', 'display');
				saf_init();
				if(starred_list_display == 'block') {
					saf_goto_page(0);
					saf_starrers_toggle('on');
				}
	            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 module = args[1];
            var jsonText = (null != rsp)? rsp : "";
            var json = Util.evalJson(jsonText);
            var my = (location.href.indexOf('my/my')!=-1);

            if (json){
				//regardless of error states, always update the html with what is
				//returned from the server (i.e. to disable the starring if you're over your limit)
                var _pfx = [ '' ];
                if (module < 2) _pfx = [ '', 'b' ];     
                else if (module != 2) _pfx = [ 'pq', 'pa', 'ps', 'pw' ];
                var html = json["html"];

                for (var _i=0; _i<_pfx.length; _i++){
                    var star = Util.gObj("starflag_area-" + _pfx[_i] + qid);
                    if (star){
                        star.innerHTML = html;
                    }
                }

                // this hides the item when its unstarred from the star list
                if (my && (args[2] > 0) && (module > 2)){
                    var root = Util.gObj('starred-tab-content');
                    var elems = YAHOO.util.Dom.getElementsBy(function(e){ return e.id == 'q_row_' + qid; }, 'tr', root);
                    if (elems.length == 1){
                        elems[0].style.display = "none";
                        var more_count = Util.gObj('starred_list_more_count');
                        if (more_count){
                            var txt = more_count.innerHTML;
                            if (txt.indexOf('(')!=-1){
                                var rescnt = txt.substring(txt.indexOf('(')+1,txt.indexOf(')'));
                                var prefix = txt.substring(0, txt.indexOf('(')+1);
                                var postfix = txt.substring(txt.indexOf(')'));
                                rescnt = (rescnt * 1) - 1;
                                more_count.innerHTML = prefix + rescnt + postfix;
                            }
                        }
                    }
                } 

				//show the limit dialog
				if(json.error && json.error == "overlimit") {
					var cfgButtons = [ { text:"OK", handler:oAnswers.dialog.cancel } ];
   					oAnswers.dialog.init(cfgButtons,"");
					oAnswers.dialog.activate(json.error_heading, json.error_text);	
				}

				//display a success message on the question detail page underneath the action bar (if it's there)
				if(a = Util.gObj('messaging-area-' + qid)) {
					success_text = '';
					if(json.star_success_text) {
						success_text = json.star_success_text;
					}

					a.innerHTML = success_text;
					YAHOO.util.Event.addListener("saf-starrers-toggle-messaging", "click", saf_starrers_toggle_on_listener);
				}

                return true;
            } else {
			}
			
            return false;
        },
        restoreHover : function(qid, module){
            if (module < 2) _pfx = [ '', 'b' ]; 
            else if (module != 2) _pfx = [ 'pq', 'pa', 'ps', 'pw' ];
            else _pfx = [ '' ];

            for (var _i=0; _i<_pfx.length; _i++){
                var star = Util.gObj("starflag_area-" + _pfx[_i] + qid);
                if (star){
                  var child = star.getElementsByTagName('div');
                  if (module == 2) child = child[1];
                  else child = child[0];
                  if (child){
                      if (child.className.indexOf('qstar2') != -1)
                          child.className = child.className.substr(0, child.className.length-1);
                  }
                }
            }
        },
        justHideIt : function(qid, stars,module){
            var uri = "/common/util/ks-qa-xhr-handler.php" +
               "?method=hideItem&qid=" + qid + "&stars=" + stars + "&p=" + module;
            var callback = { success: oAnswers.starflag.justHideItResponse,
                             failure: oAnswers.starflag.justHideItResponse,
                             argument: [qid, module, -1] }
            oAnswers.util.Ajax.request(uri, callback);
        },
        justHideItResponse : function(response){
            var args = response.argument;
            oAnswers.starflag.getGenericStarFlagResponse(response);
            if (args != null){
                var module = args[1];
                if (module == 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 : {
		TIMEOUT_ONAVATAR_OVER_KEY : "ks-idcard-timeout-key",
		TIMEOUT_ONAVATAR_OVER     : 500,
		ELE_ID_CARD : { id:"ks-user-profile-peeps-proxy-idcard" },

		//is the person looking at him/herself 
		isViewingSelfProfile : function() {
			return (
				(Util.getKid()==Util.getRequestParameter('show')) || 
				location.href.toLowerCase().indexOf("/my/my") != -1 ||
				Util.getIsViewingSelf());
		},

		// 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;
        },
        doTogglePeeps : function(tabId, kid, preview, dontCacheCurrent){
            _prefix = "ks-user-profile-";
            _tabs = ['fans', 'contacts', 'blocked'];

            oCache.setData('togglePeepsParamKid', kid);
            oCache.setData('togglePeepsParamPreview', preview);
			
			/* tracking boolean to determine whether to reset the parent container's 
			 * height or to leave it set. Added as part of bug #1222223.
			 */
			var heightWasFixed = false;

            for (_i=0; _i<_tabs.length; _i++){
                _elem = Util.gObj(_prefix + _tabs[_i] + "-list-tab");
                if (_elem){
                    if (_elem.className == 'selected'){
                        if (!oCache.getData(_prefix + _tabs[_i] + '-list_kidarr'))
                            oCache.setData(_prefix + _tabs[_i] + '-list_kidarr', oAnswers.kidarr);
                        kiddata = oCache.getData('profile_kid_data');
                        if (kiddata != null)
                            oCache.setData('ks-user-profile-' + _tabs[_i] +
                                '-list_profile_kid_cache', kiddata);
                    }
					var oldClassName = _elem.className;
                    _elem.className = "";
                    _elem = Util.gObj(_prefix + _tabs[_i] + "-list");
					
					/* If we're updating the contact list then fix its height before */
					if(oldClassName == 'selected' && _prefix + _tabs[_i] + "-list" == tabId) {
						var elem = document.getElementById(_prefix + _tabs[_i] + "-list");
						var oldHeight = elem.offsetHeight;
						if(oldHeight > 0) {
							_elem.parentNode.style.height = (oldHeight - 10) + 'px';
							heightWasFixed = true;
						}
					}
					if(!heightWasFixed) _elem.parentNode.style.height = '';
					
                    _elem.style.display = "none";
                    if (_elem.innerHTML.indexOf('div')!=-1){
                        if (!dontCacheCurrent)
                            oCache.setData('ks-user-profile-' + _tabs[_i] + '-list_cache', _elem.innerHTML);
                        _elem.innerHTML = "";
                    }
                }
            }
            oCache.setData('profile_kid_data', null);

            list = Util.gObj(tabId);
            Util.gObj(tabId + '-tab').className = 'selected';
            list.style.display = "block";

            cached = oCache.getData(tabId + "_cache");
            if (cached){
                list.innerHTML = cached;
                cached_kid_data = oCache.getData(tabId + "_profile_kid_cache");
                if (cached_kid_data) oCache.setData('profile_kid_data', cached_kid_data);
                else oCache.setData('profile_kid_data', null);
                oAnswers.kidarr = oCache.getData(tabId + "_kidarr");
            }
            else {
                var loading_text = "Đang tải...";
                var image_loading_url = "http://l.yimg.com/a/i/us/sch/gr2/loading_greyarial.gif";
                list.innerHTML = "<img src=\"" + image_loading_url +
                    "\" alt=\"" + loading_text + "\">";

                var timestamp = "&curtime=" + (new Date().getTime().toString());
                var _ajax_url = "/my/contacts/connections/?action=ajax";
                if (kid) _ajax_url += "&show=" + kid;
                if (preview) _ajax_url += "&preview=true";

                if (tabId.indexOf("fans")!=-1) _ajax_url += "&link=fans";
                else if (tabId.indexOf("blocked")!=-1) _ajax_url += "&link=blocked";
                else _ajax_url += "&link=contacts";
                _ajax_url += timestamp;

                var callback = { success: oProfile.getPeepsListResponse,
                                 failure: oProfile.getPeepsListResponse,
                                 argument: [ list, kid, preview, tabId ] }
                 oAnswers.util.Ajax.request(_ajax_url, callback);
            }
        },
        getPeepsListResponse : function(response){
            var rsp = response.responseText;
            var tid = response.tId;
            var args = response.argument;

            var errstr = "Rất tiếc, đã xảy ra lỗi.";

            if ((tid == null && args == null) || (response.status == 0)){
                if (args != null) args[0].innerHTML = errstr;
                else {
                    // should not happen...
                }
            }

            var jsonText = (null != rsp)? rsp : "";
            var json = Util.evalJson(jsonText);

            var destinationTab = args[0];
            if (json && json['notloggedin'] && json['notloggedin']==1)
                location.href = json['loginurl'];
            if (json && !json.error)
                destinationTab.innerHTML = json['content'];
            var activeTab = args[3];
            oCache.setData(activeTab + '_kidarr', json['kidarr']);
            oCache.setData(activeTab + '_profile_kid_cache', null);

            if (activeTab.indexOf("blocked")!=-1){
                var tt5 = new YAHOO.widget.Tooltip("tt-invite", {context: 'profile-blocks-info', hidedelay: 1000 } );
            }

            oAnswers.kidarr = json['kidarr'];
        },
		doToggleProfileQAList : function(pId, kid) {
			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 = Util.gObj(_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 = Util.gObj(_profile_prefix + _tabs_array[_i] + "-tab");  
				if (elem){ elem.className = ""; }
			}
			Util.gObj(pId).style.display = "block";
			Util.gObj(pId + "-tab").className = "selected";

            if (pId == "ks-user-profile-starred"){
                var star_content = document.getElementById("starred-tab-content");
                var cached = oCache.getData('profile_starred_tab');
                if ((!cached) && (star_content.innerHTML.indexOf('div') == -1)){
                    var loading_text = "Đang tải...";
                    var image_loading_url = "http://l.yimg.com/a/i/us/sch/gr2/loading_greyarial.gif";
                    star_content.innerHTML = "<img src=\"" + image_loading_url +
                        "\" alt=\"" + loading_text + "\">";

                    var l = "";
                    var page = location.href;
                    if (page.indexOf('profile')==-1){
                        if (page.indexOf('&preview=true')==-1)
                            l = "&ptype=2";   // my profile
                        else l = "&ptype=1";  // preview my profile
                    }
                    else l = "&ptype=0";  // public profile

                    var timestamp = "&curtime=" + (new Date().getTime().toString());
                    var uri = "/common/util/ks-qa-xhr-handler.php" +
                       "?method=getStarredList&kid=" + kid + l + timestamp;
                    var callback = { success: oProfile.getStarredListResponse,
                                     failure: oProfile.getStarredListResponse,
                                     argument: [ star_content ] }
                    oAnswers.util.Ajax.request(uri, callback);
                }
                else if (!cached){
                   // do nothing, because this means it already has preloaded text in it
                }
                else {
                   star_content.innerHTML = cached;
                }
            }
            else {
                var star_content = document.getElementById("starred-tab-content");
                var cached = oCache.getData('profile_starred_tab');
                if ((cached) || (star_content.innerHTML.indexOf('div')!=-1)){
                    oCache.setData('profile_starred_tab', star_content.innerHTML);
                }
            }
			return false;
		},
        getNickname : function(kid){
            var elem = Util.gObj('member-nickname_' + kid);
            if (elem) return elem.innerHTML;
            elem = Util.gObj('user-profile-title-username-' + kid);
            if (elem && elem.firstChild) return elem.firstChild.nodeValue;
            else return "";
        },
        getActiveTab : function(){
            _prefix = "ks-user-profile-";
            _tabs = ['fans', 'contacts', 'blocked'];
            for (_i=0; _i<_tabs.length; _i++){
                tabname = _prefix + _tabs[_i] + "-list-tab";
                _elem = Util.gObj(tabname);
                if (_elem != null && _elem && _elem.className == 'selected')
                    return tabname;
            }
            return "";
        },
        getStarredListResponse : function(response){
            var rsp = response.responseText;
            var tid = response.tId;
            var args = response.argument;

            var errstr = "Rất tiếc, đã xảy ra lỗi.";

            if ((tid == null && args == null) || (response.status == 0)){
                if (args != null) args[0].innerHTML = errstr;
                else {
                    // should not happen...
                }
            }

            var jsonText = (null != rsp)? rsp : "";
            var json = Util.evalJson(jsonText);

            var star_content = args[0];
            if (json && !json.error){
                var result = json["starlist"];
                oCache.setData('profile_starred_tab', result);
                star_content.innerHTML = result;
            }
            else {
                star_content.innerHTML = errstr;
            }
        },
		// 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";
			}
		},
		is_fetch_user_data : false,
		isFetchingUserData : function() { return this.is_fetch_user_data; },
        /*	@description: called from /common/util/util.php -> doFormatAndWriteUserProfile()
         *  @param: pKid: Answers user Id
         *  @param: pIsVisible: whether to open or close the Id card
         * */
		onAvatarOver : function(pKid, pIsVisible) {
            var timer = oCache.getData('timer_before_avatar_over');
            if (!pIsVisible){
                if (timer){
                    clearTimeout(timer);
                    oCache.setData('timer_before_avatar_over', null);
                }
                oCache.setData('current_kid_for_avatar_over', null);
                oProfile.reallyOnAvatarOver(pKid, pIsVisible);
            }
            else {
                oCache.setData('current_kid_for_avatar_over', pKid);

                if (!timer){
	                var cached = oCache.getData('profile_kid_data');
                    timeout = cached? 500 : 200;
                    timer = setTimeout("oProfile.reallyOnAvatarOver('" + pKid + "', " + (pIsVisible? "true" : "false") + ")", timeout);
                    oCache.setData('timer_before_avatar_over', timer);
                }
            }
        },
        reallyOnAvatarOver : function(pKid, pIsVisible) {
            var _elem = Util.gObj('profile-info-' + pKid);
			var _proxy_elem = Util.gObj(oProfile.ELE_ID_CARD["id"]);
            try {
	            //should we display?
	            if (pIsVisible) {
                    _proxy_elem.innerHTML = "";
	                var cached = oCache.getData('profile_kid_data');
	                var best_answer_area = Util.gObj("member-answers-best_" + pKid);
	                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 && "undefined"!=cached){
	                    var cache = cached[pKid];
	                    if (cache && "undefined"!=cache) {
	                        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 = " " + percent + "%";
	                        ptweek.innerHTML = weekly;
	                        tpts.innerHTML = total_ans_cnt + "&nbsp;câu trả lời";
	                        best_answer_area.style.textAlign = 'left';
	                        best_answer_area.style.color = '#fff';
				            oProfile.doOpenIdCard('profile-info-' + pKid,true);
	                	}
	                }
	                else {
	                	
	                    var kids = oAnswers.kidarr;
	                    var uri = "/common/util/ks-qa-xhr-handler.php" + "?method=getKidData&kidarr=" + kids;
	
	                    var _tmpstr = "<img src=\"" + oAnswers.HTML.images['img_green_busy'].src + "\" alt=\""+oAnswers.HTML.images['img_green_busy'].description +"\">";
	                    best_answer_count.innerHTML = _tmpstr;
	                    best_answer_area.style.textAlign = 'center';
	                    best_answer_area.style.color = '#68ce12';
		                    
						if (!this.isFetchingUserData()) {
                			this.is_fetch_user_data = true;
		                    var callback = { success: oProfile.getKidsResponse,
		                                     failure: oProfile.getKidsResponse,
		                                     timeout: 7000,
		                                     argument: [pKid, best_answer_count, ptweek, tpts, best_answer_area] }
		
		                    oAnswers.util.Ajax.request(uri, callback);
	                	}
                        else oProfile.doHandleAvatarOver(true);  // reset timer if we tried to display while amidst another request
	                }
	            }
	            else {
                    // only set timer if its not already set
                    var cached = oCache.getData(oProfile.TIMEOUT_ONAVATAR_OVER_KEY);
                    if (cached == null)
    	            	oProfile.doHandleAvatarOver();
	            }
            } 
            catch(e) {
            }
            finally {
            	
            }
        },
        doWritePeepsLink : function(pAction,pKid,pNickname) {
			var _str = "";
			var _nickname = (null!=pNickname && ""!=pNickname) ? pNickname : "";
        	//user is a friend
        	if ("add"==pAction) {
        		_str = '<a class="add_link" href="javascript:void(0);" onclick="javascript:oAnswers.relationships.addFriend(\''+ pKid +'\');">Thêm vào Danh bạ</a>';
                if (oAnswers.blockUserEnabled == true)
                _str += '<a class="block_link" href="javascript:void(0);" onclick="javascript:oAnswers.relationships.blockUser(\'' + pKid + '\');">Chặn người này</a>';
        	}
        	//user is NOT a friend
        	else if ("remove"==pAction) {
        		_str = '<a href="javascript:void(0);" onclick="javascript:oAnswers.relationships.removeFriend(\''+ pKid +'\');">Xóa địa chỉ liên lạc</a>';
        	}
            else if ("unBlock"==pAction) {
        		_str = '<a href="javascript:void(0);" onclick="javascript:oAnswers.relationships.unBlockUser(\''+ pKid +'\');">Hủy chặn</a>';
            }
        	return _str;
        },
        /*	@description: "private" function handle display cards
         *  @param: pAppendToOlderSibling: element to set adjacent to
         *  @param: pIsVisible: whether to open or close the Id card
         * */
        doDisplayIdCard : function(pAppendToOlderSibling,pIsVisible) {
            try {
                if (pIsVisible) {
                	// force the timer cache to expire
                    oProfile.doHandleAvatarOver(true);
                    var _elem = Util.gObj(pAppendToOlderSibling);
                    var _proxy_elem = Util.gObj(oProfile.ELE_ID_CARD['id']);

                    var _xy = YAHOO.util.Dom.getXY(pAppendToOlderSibling);
                        _xy[1] = parseInt(_xy[1] - 1);
                    
                    YAHOO.util.Dom.setXY(_proxy_elem,_xy);
                    YAHOO.util.Event.purgeElement(_proxy_elem,true);
                    YAHOO.util.Event.addListener(_proxy_elem,"mouseout",function() { oProfile.doHandleAvatarOver() });
                    YAHOO.util.Event.addListener(_proxy_elem,"mouseover",function() { oProfile.doHandleAvatarOver(true); });
             
                    _proxy_elem.innerHTML = _elem.innerHTML;

                    // let's get all the proxy element's children
                    var _coll = _proxy_elem.getElementsByTagName("DIV");
                    var _coll_item = null;
                    for (var i = 0; i < _coll.length; i++) {
                        _coll_item = _coll[i];
                        if (_coll_item.id.toLowerCase().indexOf("is-friend") != -1) {

                            var _friend_status = _coll_item.innerHTML * 1;
						    if ((0 <= _friend_status) && 2 >= (_friend_status)) {
			                    var _action = (1==_friend_status) ? "remove" : (0==_friend_status)? "add" : "unBlock";
			                    //let's get the $kid
			                    var _prefix_is_friend = "member-is-friend_";
			                    var _kid = _coll_item.id.substring(_prefix_is_friend.length);
			                    
			                    var _nickname = null;
			                    var _nick_ele = Util.gObj('member-nickname-' + _kid);
			                    if (null != _nick_ele && "undefined" != _nick_ele) {
			                    	_nickname = _nick_ele.innerHTML;
			                    }
			                    else {
			                    	_nick_ele = Util.gObj('member-nickname_' + _kid);
			                    	if (null != _nick_ele && "undefined" != _nick_ele) {
			                    		_nickname = _nick_ele.innerHTML;			                    		
			                    	}
			                    }
			                    
			                    _coll_item.innerHTML = oProfile.doWritePeepsLink(_action,_kid,_nickname);
			                }
			                else if ("S" == _coll_item.innerHTML) {
			                	_coll_item.innerHTML="&nbsp;";
			                }
						    else {
						    	// this is default: the link redirects to a login page, while
						    	// the call to action looks like a regular link to ad contacts
			                    var _str = '<a class="add_link" href="' + _coll_item.innerHTML + '">Thêm vào Danh bạ</a>';
                                if (oAnswers.blockUserEnabled == true)
                                    _str += '<a class="block_link" href="' + _coll_item.innerHTML + '">Chặn người này</a>';
			                    _coll_item.innerHTML = _str;
						    }
						}
                        _coll_item.id = ""; //reset Ids to resolve unique key conflict
                        YAHOO.util.Event.purgeElement(_coll_item);
                        YAHOO.util.Event.addListener(_coll_item,"mouseover",
                        	function() { 
                        		oProfile.doHandleAvatarOver(true); 
                        	}
                        );
                    }
                    _proxy_elem.style.visibility = "visible";
                }
                // close Id card: let's clear timer cache
                else {
                    oProfile.doHandleAvatarOver(true);
                }
            }
            catch (e) {
                 oAnswers.debug("error: " + e);
            }
            finally {
            	_coll = null; _xy = null;
            }
        },
        /*	@description: public function to open the Id card
         *  @param: pAppendToOlderSibling: element to set adjacent to
         * */
        doOpenIdCard : function(pAppendToOlderSibling) {
        	try {
            	oProfile.doDisplayIdCard(pAppendToOlderSibling,true);
        	}
        	catch(e) {
        		oAnswers.debug("error: " + e);
        	}
        },
        /*	@description: public function to close the Id card
         * */
        doCloseIdCard : function() {
        	try {
            	var _proxy_elem = Util.gObj(oProfile.ELE_ID_CARD['id']);
            		_proxy_elem.style.left = "-500px"; //hide
            		_proxy_elem.style.visibility = "hidden";
        	}
        	catch(e) {
        		oAnswers.debug("error: " + e);
        	}
        },
        /*  @description: public function to close the Id card
         *  @param: pClearCache (optional): should we force to cache-clearing?
         * */
        doHandleAvatarOver : function(pClearCache){
            try {
                var cached = oCache.getData(oProfile.TIMEOUT_ONAVATAR_OVER_KEY);
                //if cache is set or brute force it
                if (cached || pClearCache) { 
                    oAnswers.debug("clearing cache for avatar");
                    window.clearTimeout(cached);
                    oCache.setData(oProfile.TIMEOUT_ONAVATAR_OVER_KEY,null);
                }
                else {
                    oAnswers.debug("setting cache for avatar");
                    oCache.setData(oProfile.TIMEOUT_ONAVATAR_OVER_KEY,
						window.setTimeout(
	                    	function() { 
	                    		oProfile.doCloseIdCard() 
	                    	}
	                    	,(document.getElementById('y-ks-header-user-profile') ? 350 : oProfile.TIMEOUT_ONAVATAR_OVER)
	                   	)
	                );
                }
            }
            catch(e) {
                oAnswers.debug("error: " + e);
            }
        },
        getKidsResponse : function(response) {
        	oAnswers.profile.is_fetch_user_data = false;
        	var errstr = oAnswers.translations['GENERAL_UI_ERROR'];
            var rsp = response.responseText;
            var tid = response.tId; //transaction Id
            var args = response.argument;
            if ((tid == null && args == null) || (response.status == 0)){
                if (args != null){
                    var errstr = "&nbsp;";
                    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 best_answer_area = args[4];

            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_area.style.textAlign = 'left';
                best_answer_area.style.color = '#fff';
                best_answer_count.innerHTML = (isNaN(percent)) ? "\"whoa!\"" : " " + percent + "%";
//                ptweek.innerHTML = weekly;
                tpts.innerHTML = (total_ans_cnt == 1) ? '1&nbsp;trả lời' : total_ans_cnt + "&nbsp;câu trả lời";

            }
            else {
                best_answer_count.innerHTML = errstr;
//                ptweek.innerHTML = errstr;
                tpts.innerHTML = errstr;
            }
            oCache.setData('profile_kid_data', json);

            // if we don't have a timer set, the mouse is still over the element, so display it

            var currentKid = oCache.getData('current_kid_for_avatar_over');
            if (currentKid != null){
                if (currentKid == kid)
                	oProfile.doDisplayIdCard('profile-info-' + kid,true);
                else oProfile.onAvatarOver(currentKid, true);
            }
        }
	},
	spellcheck : {
		/* spellcheck is set in another rosetta JS gile
		 */	
		SpellController : {},	
		data : {
			Speller : {
			
			}
		}		
	},
	util : {
		ERROR_NOTICE : { key : "8", value : "notice" },
		ERROR_INFO :   { key : "4", value : "info"   },
		ERROR_WARN :   { key : "2", value : "warn"   },
		ERROR_ERROR :  { key : "1", value : "error"  },
		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",	
			_INTL : "us",	
			init : function(pIntl,pNodeToAppendTo) {
				var _node_to_attach_to = pNodeToAppendTo || document.body;
				_INTL = pIntl || "us";
				if (_INTL == "br") {  
				var _aMenuItemData = [  
					{ text: "Yahoo! Tìm kiếm", config: { url:"javascript:void(0);" }, elementId : "option-yahoo-search", icoClassName : "ico-yahoo-cade" },
	                { text: "Wikipedia", config: { url:"javascript:void(0);" }, elementId : "option-wikipedia-search", icoClassName : "ico-wikipedia" }
				];
                                } else {
				var _aMenuItemData = [  
					{ text: "Yahoo! Tìm kiếm", 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);
				/* for br, swap out cade image if wikipedia search */
				if (_INTL == "br" && pClassName == "ico-wikipedia") {
					document.getElementById('cade-search-box').style.backgroundImage = "url(http://l.yimg.com/ao/i/uh/y7/hdr_srch_bck_1_3.gif)";
				}

				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;
				}
			}
		}, // oSearchOptionMenu
		setCursor : function(pStr) { document.body.style.cursor = pStr; },
		setDocumentTitle : function(pStr) { document.title = pStr; },
		isNull : function(pEle) {
		    return (null==pEle || "undefined"==pEle || ""==pEle);
		},
		isSet : function(v) { return (typeof(v)!="undefined"); },
		debug : function(pStr,pIsException) {
			YAHOO.search.answers.debug(pStr,pIsException);
		},
		$ : function() {
        	var elements=[]; var e = null;
   	    	for (var i=0; i < arguments.length; i++) {
            	e = arguments[i];
            	if ('string' == typeof e) e = document.getElementById(e);
            	if (arguments.length == 1) return e;
      			elements.push(e);
        	}
			return elements;
		},
		addressbook : {
			decorateContact : function(pName,pEmailAddress,pAlternate) {
				var _s = '<tr class="'+ ((pAlternate) ? "alternate" : "") + '"><td class="checkbox"><input type="checkbox" name="peeps-addressbook-contact-array" value="'+pName+'||'+pEmailAddress+'"></td><td class="peeps-addressbook-contact-name">'+pName+'</td><td>'+pEmailAddress+'</td></tr>';
				return _s;
			},
			hideContacts : function() {
				var _load_ele = Util.gObj('peeps-action-load-contacts');
				var _hide_ele = Util.gObj('peeps-action-hide-contacts');
				var _ele = Util.gObj('peeps-addressbook-container');
				_load_ele.style.display = "inline";
				_hide_ele.style.display = "none";
				_ele.style.display = "none";
			},
			loadContacts : function(pKey) {
				var _load_ele = Util.gObj('peeps-action-load-contacts');
				var _hide_ele = Util.gObj('peeps-action-hide-contacts');
				var _ele = Util.gObj('peeps-addressbook-container');
				_load_ele.style.display = "none";
				_hide_ele.style.display = "inline";
				_ele.style.display = "block";
				var _s = [];
				try {
					var _contacts = [];
					if (oAnswers.util.isSet(AC_allCanons) && null != AC_allCanons && "undefined" != AC_allCanons) {
						_contacts = AC_allCanons;
					}
				    var _t = oAnswers.util.rot13.transform(_contacts.toString());
				    	_contacts = null;
				    var _tarray = _t.split(',');
				    	_s.push('<table>');
				    var ll = _tarray.length;
				    if (ll > 0) {
					    var _i = 0;
					    var _alternate = false;
					    while(_i < ll) {
					          if (_tarray[_i+1]!="") {
					              _s.push(this.decorateContact(_tarray[_i].toString(),_tarray[_i+1].toString(),_alternate));
					          	  _alternate = !_alternate;
					          }
					          _i += 2;
					    }
				    }
				    else { // no one in a person's address book
				    	_s.push('<tr><td class="checkbox">&nbsp;</td><td colspan="2">Hiện bạn không có địa chỉ liên lạc nào trong Sổ địa chỉ Yahoo! của mình. Hãy tự mời các địa chỉ trên.</td></tr>');
				    }
				    _s.push('</table>');
					_tarray = null;
					return;
				} 
				catch(e) {
					_s.push('<table>');
				  	_s.push('<tr><td class="checkbox">&nbsp;</td><td colspan="2">Hiện bạn không có địa chỉ liên lạc nào trong Sổ địa chỉ Yahoo! của mình. Hãy tự mời các địa chỉ trên.</td></tr>');
				    _s.push('</table>');
				}
				finally {
				    Util.gObj('peeps-addressbook-data').innerHTML = _s.join('');
				    _s = null;						
				}
			}
		},
		forms : {
			toggleCheckboxFamily : function(pThisElement,pForm,pElementName) {
				var _isChecked = (pThisElement.checked);
				var _form = pForm;
				var _form_eles = _form.elements;
				var _form_eles_length = _form.elements.length;
				for (var _f=0; _f < _form_eles_length; _f++) {
					if (_form_eles[_f].name =  pElementName) {
						_form_eles[_f].checked = _isChecked;
					}
				}
			}
		},
		rot13 : {
			rot13map : null,
			
			// The problem is that JavaScript 1.0
			// does not provide a Char to Numeric value conversion
			// Thus we define a map.
			// Because there are 64K UniCode characters, this map does not cover all characters.
			
			rot13init : function() {
			  var map = [];
			  var s   = "abcdefghijklmnopqrstuvwxyz";
			  for (i=0; i<s.length; i++) map[s.charAt(i)] = s.charAt((i+13)%26);
			  for (i=0; i<s.length; i++) map[s.charAt(i).toUpperCase()] = s.charAt((i+13)%26).toUpperCase();
			  return map;
			},
			transform : function(a) {
			  if (!this.rot13map) this.rot13map=this.rot13init();
			  s = "";
			  for (i=0; i<a.length; i++) {
			      var b = a.charAt(i);			
			      s	+= (b>='A' && b<='Z' || b>='a' && b<='z' ? this.rot13map[b] : b);
			  }
			  return s;
			}
		},
		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,pIsException) {
		var _str = ((pIsException) ? "EXCEPTION: " : "") + pStr
        // this doesn't work either because its not about gecko, its only available on firebug...
		// if (console.log && oAnswers.application.ua.indexOf("gecko") != -1) console.log(_str)
		//if (Util) Util.debug(pStr,pLevel); // TODO: must be rewritten
	},
	eggs : {
		CONTRA_CODE_INIT : "rbaS"
	},
	translations: {
		GENERAL_UI_ERROR : "Rất tiếc, đã xảy ra lỗi.",
		SPELLCHECKER_ERROR : 'Rất tiếc, Trình kiểm tra chính tả đang gặp sự cố, hãy thử lại.'
	}
}


/*
 *  @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 : "Không có gợi ý nào",
		NO_MORE_MISSPELLINGS : "Không có lỗi chính tả nào khác",
		NO_MISSPELLINGS : "Không tìm thấy lỗi chính tả nào",
		SPELL_DISABLED : "Đã tắt chính tả, click Tiếp tục để tiếp tục",
		
		// 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 : "Đổi thành:",
		SUGGESTION_LABEL: "Các gợi ý:",        
        
        // Command Labels
		DONE_COMMAND : "Hoàn tất",
		CHANGE_COMMAND : "Thay đổi",
		IGNORE_COMMAND : "Bỏ qua",
		CLOSE_COMMAND : "Thân",
		RESUME_COMMAND : "Tiếp tục",		
		CHANGE_ONE_ITEM_COMMAND : "Đổi từ này",
		CHANGE_ALL_ITEM_COMMAND : "Đổi mọi sự kiện",
		IGNORE_ONE_ITEM_COMMAND : "Bỏ qua từ này",
		IGNORE_ALL_ITEM_COMMAND : "Bỏ qua mọi sự kiện",
		
		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://l.yimg.com/a/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 (YAHOO.search.answers.locale == 'th_TH' ||
            YAHOO.search.answers.locale == 'th' ||
            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="Hãy kiểm tra chính tả trước khi gửi!" ';
        s += ' onclick="SpellController.start(\'' + pInputField + '\',document.' + pForm + ',' + isUsingIframe +'); return false;" ';
        // s += ' onfocus="javascript:this.blur();"
        s += '>';
        s += '<span style="font-size:88%;">Kiểm tra chính tả</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(
        '',
'Bạn có 100 điểm để bắt đầu',
'Cảm ơn bạn đã truy cập! (1 điểm)',
'Bạn đã đặt một câu hỏi (-5 điểm)',
'Đặt câu hỏi ẩn danh',
'Bỏ qua câu hỏi của tôi',
'Bạn đã chọn một câu trả lời hay nhất(3 điểm)',
'Bạn đã trả lời một câu hỏi (2 điểm)',
'Xóa câu trả lời',
'Câu trả lời của bạn được chọn là câu hay nhất! (10 điểm)',
'Bạn đã bình chọn một câu trả lời nhất (1 điểm)',
'Bạn đã đánh giá một câu trả lời hay nhất (1 điểm)',
'Được đánh giá xuất sắc!',
'Đóng góp danh dự',
'Vi phạm trong câu hỏi',
'Vi phạm khi trả lời',
'Vi phạm trong bình luận',
'Câu trả lời hay nhất bị cho là vi phạm',
'Những điều nhảm nhí khác',
'Dấu hiệu đồng ý cho câu trả lời hay nhất của bạn! (1 điểm)',
'Bạn đã chọn để mời bình chọn',
'Các giải thưởng tối đa cho câu trả lời được đánh giá là tích cực',
'Số sự kiện sẽ lưu vào nhật ký mỗi người dùng',
'',
'Câu hỏi của bạn không có câu trả lời hay nhất (5 điểm)',
'',
'',
'',
'',
'',
'Câu trả lời đã được phục hồi',
'',
'Câu hỏi đã được phục hồi',
'Khiếu nại bị từ chối'
    );
}

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()+ ' trước)</em><br/>';
    s += ("0"!=pObj.getQid()) ? '<p align="right"><a href="/question/index?qid='+pObj.getQid() +'">Xem câu hỏi</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>Bạn/đã kiếm được ' +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>Một số <a href="' + tmpUrl + '">các câu hỏi của bạn</a> cần sự quan tâm!</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">Bạn/đã kiếm được <strong>'+c_login.toString() +'</strong> số điểm nhờ đăng nhập!</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) {
		f.action='/search/search_advance';
		f.submit();
		l.href='#';
		return false;
	}
}

function doCheckMessageForPreview(pForm) {
	var error = false;
	var subject = String.trim(pForm.subject.value);
    
   	if (subject.length == 0) {
   		helpString = "Bạn phải nhập một chủ đề";
   		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 = "Bạn phải nhập một nickname với tối đa 32 ký tự";
    		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;
}
var _hasAttemptedToRemoveFans = false;
function doCheckMyEditPreviewForWrite(pForm) {
    var _ele = Util.gObj('is_peeps_allow_users_as_fans');
    var _ele_checked = Util.gObj('is_peeps_just_changed_allow_users_as_fans');
    if (null != _ele && "undefined" != _ele && 
        null != _ele_checked && "undefined" != _ele_checked && 'y' === _ele_checked.value &&
        !_hasAttemptedToRemoveFans) {
        if ("INPUT" == _ele.tagName && "n"==_ele.value) {
            _hasAttemptedToRemoveFans = true;
            setTimeout(function(){oAnswers.relationships.removeFans();},100);
            return false;
        } 
    }
    return true;
}
function doCheckMyEditPreviewFansRemoveResponse(pHasRemovedAllFans) {
    if (pHasRemovedAllFans) {
        setTimeout(function(){document.forms["my_edit_preview"].submit();},1000);
    }
    else {
        _hasAttemptedToRemoveFans = false;    
    }
}

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 = "Hãy nhập một địa chỉ email hợp lệ";
			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 = "Hãy chọn một địa chỉ email";
		Util.displayErrorInfo("email", helpString, true);
    	hasError = true;
    }
    else {
		Util.displayErrorInfo("email", "", false);
        hasError = false;
	}
    return !hasError;
}

function expandConsumptionAnswer(id) {
	Util.gObj("more-"+id).style.display = "none";
	Util.gObj("more-text-"+id).style.display = "inline";
}

function contractConsumptionAnswer(id) {
	Util.gObj("more-"+id).style.display = "inline";
	Util.gObj("more-text-"+id).style.display = "none";
}

function fetchContactListImages() {
	//use this cache item to make sure we only start doing this once
	fetched = YAHOO.search.answers.cache.getData('cl-fetched');

	if(!fetched || fetched == undefined) {
		YAHOO.search.answers.cache.setData('cl-fetched', true);
		f = Util.gObj('cl-form');
		for(i=0; i < f.elements['cl-photos'].length; i++){
		    v = f.elements['cl-photos'][i].value.split('||');
			kid = v[0];
			photoUrl = v[1];
			Util.gObj('cl-img-'+kid).src = photoUrl;
		}
	}  
}

/** 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 = "Bạn cần nhập một câu hỏi.<br/><br/>";
        helpString2 = "Câu hỏi của bạn phải dài ít nhất 10 ký tự.<br/><br/>";

	capsHelp = "Vui lòng đừng VIẾT HOA TẤT CẢ.  Điều đó là bất lịch sự.";

        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 = "Hãy chọn một nhóm<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 = "Hãy chọn một nhóm phụ dưới: " + 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 = "Hãy chọn một nhóm<br/><br/><br/><br/>";
    
        if (!selectedCatID) {
            Util.displayErrorInfo("menu", helpString, true);
            error = true;
        } else {
            if (cA[selectedCatID]) {
                    if (selectedMenuName != "menu_2") {
                        //alert("Hãy chọn một nhóm phụ dưới: " + getPath());
                        helpString2 = "Hãy chọn một nhóm phụ dưới: " + 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('Số từ trong nội dung bổ sung đã vượt quá giới hạn');
        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("Bạn có chắc nhắn muốn câu trả lời hay nhất được bình chọn bằng phiếu bầu?\n (Cuộc bình chọn sẽ được mở trong 5 ngày.)");
    //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("Bạn có chắc chắn muốn gia hạn thời gian hiệu lực cho câu hỏi không?\n (Bạn chỉ có thể gia hạn một lần để thêm 5 ngày.)");
    //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("Bạn có chắn chắn muốn xóa câu hỏi này không?\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("Bạn chắc chắn? Bạn sẽ không thể gửi câu trả lời khác cho câu hỏi này.\n\nĐể sửa câu trả lời hiện tại :\n1. Nhấp vào \"Hủy\".\n2. Vào câu trả lời của bạn và nhấp vào đường dẫn \"Sửa\" bên dưới.");
    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("Bạn có chắn chắn muốn gửi phản hồi không?");
    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) ? "Ẩn các bình luận" : "Thêm/Xem các bình luận (" + 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("Vui lòng xếp hạng câu trả lời");
    else {
        //var flag = window.confirm("Bạn có chắc không?");
        //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('Hãy chọn một nhóm cho câu hỏi của bạn');
        return false;
    }
    */
    var helpString="";;
    var inputStr = String.trim(pForm.textfield.value);
    var strlength= inputStr.length;
    if (strlength == 0) {
        //alert('Hãy nhập bình luận của bạn'); 
	    helpString = "Hãy nhập bình luận hợp lệ";
        Util.displayErrorInfo("titleComments", helpString, true);
        return false;
    }
    if (strlength > iMaxLength ) {
        //alert('Số từ trong nội dung bình luận đã vượt quá giới hạn'); 
	    helpString = "Hãy giới hạn bình luận của bạn trong 300 ký tự.";
        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("Bạn chắn chắn muốn xóa ý kiến của mình?");
    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('Hãy chọn loại vi phạm.');
	} else {
		if( pForm.pmesg.value == ''  ) {
            alert('Hãy nhập những gì bạn muốn báo cáo'); 
		}
        else {
            return true;
        }
	}
    return false;
}
*/

function doCheckAnswerQuestionFormSubmit(pFrom) {
    inputStr = String.trim(pFrom.textarea2.value);
    if(pFrom.textarea2.value == 0) {
	    var helpString = "Phải, bạn rất vui tính, giờ thì hãy nhập một giải đáp thực. (Tối thiểu 20 ký tự)";
        Util.displayErrorInfo("titleAnswer", helpString, true);
        //alert("Hãy nhập trả lời của bạn.");
        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 = "Bạn phải nhập ít nhất 10 ký tự";
        Util.displayErrorInfo("details", helpString, true);
        err = true;
    }
    if (strlength > MaxLen ) {
        alert('Số từ trong nội dung bổ sung đã vượt quá giới hạn');
        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 = "Đang lưu...";
	}

	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 = "+ Thêm vào Danh sách theo dõi";
			
		if(!add) { newText = "Xóa khỏi Danh sách theo dõi"; }

		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 = "Rất tiếc, đã xảy ra lỗi.";
		}		
	}

	return false;
}

function doCheckAbuseReportForm(pForm) {
	var hasErr=false;
	if ("" == pForm.reason.options[pForm.reason.options.selectedIndex].value) {
		var helpString = "Hãy chọn một nhóm";
		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 = "Vui lòng mô tả trường hợp vi phạm này";
	   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 = "Vui lòng xếp hạng câu trả lời";
            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 = "Hãy nhập một bình luận";
            Util.displayErrorInfo("moreComments", helpString, true);
            hasErr=true;
        }
        else if ( strlength > 300 ) {
            var helpString = "Bình luận của bạn có quá nhiều ký tự";
            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 = 'Nhập một địa chỉ email';
            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 = 'Số ký tự trong mục các địa chỉ email đã vượt quá giới hạn';
           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 = 'Hãy thêm tin nhắn của bạn';
           Util.displayErrorInfo("pmesg", helpString, true);
           hasErr = true;
       } else {
           Util.displayErrorInfo("pmesg", "", false);
       }
       */
       
       if (strlength > MaxLen ) {
           helpString = 'Số ký tự trong tin nhắn của bạn đã vượt quá giới hạn';
           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 = 'Hãy nhập một địa chỉ email';
    		   err = true;
    		}
    		var invalidChars = '\/\'\\ ":?!()[]\{\}^|';
    		for (i=0; i<invalidChars.length; i++) {
    		   if ((addr.indexOf(invalidChars.charAt(i),0) > -1) || (addr.charCodeAt(i)>127)) {
    			  errString = 'Hãy nhập một địa chỉ email hợp lệ';
    			  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 = 'Hãy nhập một địa chỉ email hợp lệ';
    		    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();
			*/
			answerHiddenDesc = Util.gObj("hide-desc-"+targetName);
			if(answerHiddenDesc && rating == -1) {
				setTimeout("hideAnswer('"+targetName+"');", 1200);

				answerHiddenDescO = Util.gObj("hide-desc-o-"+targetName);
				answerHiddenDesc.innerHTML = "Bạn đã đánh giá thấp câu trả lời này:";
				answerHiddenDescO.innerHTML = "Bạn đã đánh giá thấp câu trả lời này:";
			}

			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="Đang lưu..." src="http://l.yimg.com/a/i/us/saving_vn.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 = "Bạn đã đánh giá thấp câu trả lời này:";
		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()", 500); });

    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()", 500); });
    }

//    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;
	}
}


var saf_get_starrers_list_description = function() {
	if(num_total_kids != undefined && num_total_kids == 0) {
		return("");
	} else if(num_total_kids != undefined && num_total_kids == 1) {
		return("Nhấp vào tên để xem các câu hỏi khác mà người dùng này đã đánh dấu sao.");
	} else if(num_total_kids != undefined && num_total_kids > 0) {
		return("Nhấp vào các tên để xem các câu hỏi khác mà những người dùng này đã đánh dấu sao.");
	} else {
		return false;
	}
};

//handle singular, plural and zero message here:
var saf_get_starrers_list_title = function() {
	if(num_total_kids != undefined && num_total_kids == 0) {
		return("Hãy là người đầu tiên đánh dấu câu hỏi là thật tuyệt!");
	} else if(num_total_kids != undefined && num_total_kids == 1) {
		return("\$num_total_kids người dùng nghĩ rằng câu hỏi này thật tuyệt!".replace(/\$num_total_kids/, num_total_kids));
	} else if(num_total_kids != undefined && num_total_kids > 0) {
		return("\$num_total_kids người dùng nghĩ rằng câu hỏi này thật tuyệt!".replace(/\$num_total_kids/, num_total_kids));
	} else {
		return false;
	}
};

var saf_starrers_response_success = function(o) {
	var response_json = o.responseText;
	eval( 'var arr_response = ' + response_json + ';' );
	if(arr_response['displayed_page'] != undefined) {
		current_starrer_page = parseInt(arr_response['displayed_page']);
	}
	if(arr_response['total_pages'] != undefined) {
		num_total_starrer_pages = parseInt(arr_response['total_pages']);
	}
	if(arr_response['self_star_html'] != undefined) {
		self_star_html = arr_response['self_star_html'];
	}
	if(arr_response['first_starrer_kid'] != undefined) {
		first_starrer_kid = arr_response['first_starrer_kid'];
	}
	
	var response_contains_first_page = false;
	if(arr_response['pages'] != undefined) {
		var arr_response_pages = arr_response['pages'];
		for(var index in arr_response_pages) {
			var page_contents = arr_response_pages[index];
			arr_starrers_pages[index] = page_contents;
			if(index == 0) {
				response_contains_first_page = true;
			}
		}
	}


	if(num_total_kids == 0) {
		document.getElementById('saf-starrers-container').innerHTML = '';
	}else if(arr_starrers_pages[current_starrer_page] != undefined) {
		document.getElementById('saf-starrers-container').innerHTML = arr_starrers_pages[current_starrer_page];
		saf_attach_pagination_events(current_starrer_page);
	}

    if (num_total_kids == 0 || arr_starrers_pages[current_starrer_page] != undefined){
        var title = saf_get_starrers_list_title();
		var description = saf_get_starrers_list_description();
		if(title !== false) {
			document.getElementById('saf-starrers-list-h1').innerHTML = title;
		}
		if(description !== false) {
			document.getElementById('saf-starrers-list-p').innerHTML = description;
		}
    }
	
};

var saf_attach_pagination_events = function (page_num) {
	YAHOO.util.Event.purgeElement('ctrl-prev');
	YAHOO.util.Event.purgeElement('ctrl-next');
	var prev_page = page_num - 1;
	var next_page = page_num + 1;
	if(current_starrer_page != 0) {
		YAHOO.util.Event.addListener("ctrl-prev", "click", saf_goto_page_listener, {goto_page: prev_page});
	} else {
		YAHOO.util.Dom.setStyle('ctrl-prev', 'background-image', 'url("'+prev_arrow_disabled+'")');
		YAHOO.util.Event.addListener("ctrl-prev", "click", function(e) {YAHOO.util.Event.stopEvent(e);return false;} );
	}
	if(current_starrer_page != num_total_starrer_pages - 1) {
		YAHOO.util.Event.addListener("ctrl-next", "click", saf_goto_page_listener, {goto_page: next_page});
	} else {
		YAHOO.util.Dom.setStyle('ctrl-next', 'background-image', 'url("'+next_arrow_disabled+'")');
		YAHOO.util.Event.addListener("ctrl-next", "click", function(e) {YAHOO.util.Event.stopEvent(e);return false;} );
	}


	//Always keep the current person on the first spot on the first page
	elem_self_icon = document.getElementById('saf_lst-'+saf_user_kid);
	//elem_first_icon = document.getElementById('saf_lst-'+first_starrer_kid);
	elem_first_icon = first_starrer_kid == undefined ? document.getElementById('saf_placeholder') : document.getElementById('saf_lst-'+first_starrer_kid);
	if(oAnswers.starflag.is_self_starred == true) {
		if(page_num == 0) {
			if(elem_self_icon == undefined) {
				if(elem_first_icon != undefined) {
					html_aux_self_starred_swap = elem_first_icon.innerHTML;
					elem_first_icon.innerHTML = self_star_html;
				}
			} else { // elem_self_icon != undefined
				if(elem_first_icon != undefined) {
					html_aux_self_starred_swap = elem_first_icon.innerHTML;
					elem_first_icon.innerHTML = self_star_html;
					elem_self_icon.innerHTML = html_aux_self_starred_swap;
				}
			}
		}

		if(page_num > 0) {
			//remove them if they exist on any page, because we stuck them in the first spot already
			if(elem_self_icon != undefined) {
				elem_self_icon.innerHTML = html_aux_self_starred_swap;
			}
		}
	}

	return true;
};

var saf_toggle_self_star = function (starOn) {
	if(starOn == true) {
		self_starred = starOn;
	} else if(starOn == false) {
		self_starred = starOn;
	} else {
		return false; // error
	}
	return true; // success
};

var saf_starrers_callback = {
	success: saf_starrers_response_success,
	failure: function(o) {},
	timeout: 5000
};

var saf_goto_page_listener = function(e, obj) {
	if(obj['goto_page'] != undefined) {
		saf_goto_page(obj['goto_page']);
	}
	YAHOO.util.Event.stopEvent(e);
};

var saf_goto_page = function(num_goto_page) {
	if(arr_starrers_pages[num_goto_page] == undefined) {
		document.getElementById("saf-starrers-container").innerHTML = html_starrers_container_loading;
		var sUrl = '/common/util/ks-saf-xhr-handler.php?page='+num_goto_page+'&pages='+NUM_STARRER_PAGES_PER_REQUEST+'&qid='+page_qid+'&num_total_kids='+num_total_kids; //page is the shown page, pages is the number of pages we should retrieve on this request
		YAHOO.util.Connect.asyncRequest('GET', sUrl, saf_starrers_callback, null);
	} else {
		document.getElementById('saf-starrers-container').innerHTML = arr_starrers_pages[num_goto_page];
		current_starrer_page = num_goto_page;
		saf_attach_pagination_events(current_starrer_page);
	}
};


var saf_starrers_toggle_on_listener = function(e) {
	saf_goto_page(0);
	saf_starrers_toggle('on');
	YAHOO.util.Event.stopEvent(e);
};

var saf_starrers_toggle_off_listener = function(e) {
	saf_starrers_toggle('off');
	YAHOO.util.Event.stopEvent(e);
};

var saf_starrers_toggle = function(type) {
	if(type == 'off') {
		document.getElementById('saf-starrers-toggle-div').innerHTML = html_toggle_hiding;
		YAHOO.util.Dom.setStyle('saf-starrers-list-wrapper', 'display', 'none');
		var new_toggle_listener = saf_starrers_toggle_on_listener;
	} else {
		document.getElementById('saf-starrers-toggle-div').innerHTML = html_toggle_showing;
		YAHOO.util.Dom.setStyle('saf-starrers-list-wrapper', 'display', 'block');
		var new_toggle_listener = saf_starrers_toggle_off_listener;
	}
	YAHOO.util.Event.purgeElement('saf-starrers-toggle-a');
	YAHOO.util.Event.purgeElement('saf-starrers-toggle-img-a');
	YAHOO.util.Event.addListener("saf-starrers-toggle-a", "click", new_toggle_listener);
	YAHOO.util.Event.addListener("saf-starrers-toggle-img-a", "click", new_toggle_listener);
};

var saf_init = function() {
	saf_reset();
	html_starrers_container_loading = document.getElementById("saf-starrers-container").innerHTML;
	YAHOO.util.Event.addListener("saf-starrers-toggle-button", "click", saf_starrers_toggle_off_listener);
	saf_starrers_toggle('off');
};
/** 
 *  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 = "Chúng tôi tìm thấy các câu hỏi tương tự: ";
var NO_RESULTS_FOUND_MESSAGE = "Không tìm thấy câu hỏi tương tự ";
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&bolding=true";
                	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://bookmarks.yahoo.com/toolbar/savebm?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+'savebm?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,pURL,pIsViewingSelf){
    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.REQUEST_URI = pURL;
    this.DATATYPE_OBJECT="object";
    this.OFFSET_BODY_HEIGHT=100;
    this.EXCEPTION_STRING="EXCEPTION";
    this.isViewingSelf = pIsViewingSelf||false;
    
    this.IS_JAVASCRIPT_DEBUG=pIsDebug||false;
    this.DEBUG_CONSOLE='y-ks-error-log';
    this.DISPLAY_WIDGET_STAR='<img src="http://l.yimg.com/a/i/us/sch/gr/pointsstar.gif" border="0" alt="star"/>';
    this.DISPLAY_WIDGET_ALERT='http://l.yimg.com/a/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(
        '',
'Bạn có 100 điểm để bắt đầu',
'Cảm ơn bạn đã truy cập! (1 điểm)',
'Bạn đã đặt một câu hỏi (-5 điểm)',
'Đặt câu hỏi ẩn danh',
'Bỏ qua câu hỏi của tôi',
'Bạn đã chọn một câu trả lời hay nhất(3 điểm)',
'Bạn đã trả lời một câu hỏi (2 điểm)',
'Xóa câu trả lời',
'Câu trả lời của bạn được chọn là câu hay nhất! (10 điểm)',
'Bạn đã bình chọn một câu trả lời nhất (1 điểm)',
'Bạn đã đánh giá một câu trả lời hay nhất (1 điểm)',
'Được đánh giá xuất sắc!',
'Đóng góp danh dự',
'Vi phạm trong câu hỏi',
'Vi phạm khi trả lời',
'Vi phạm trong bình luận',
'Câu trả lời hay nhất bị cho là vi phạm',
'Những điều nhảm nhí khác',
'Dấu hiệu đồng ý cho câu trả lời hay nhất của bạn! (1 điểm)',
'Bạn đã chọn để mời bình chọn',
'Các giải thưởng tối đa cho câu trả lời được đánh giá là tích cực',
'Số sự kiện sẽ lưu vào nhật ký mỗi người dùng',
'',
'Câu hỏi của bạn không có câu trả lời hay nhất (5 điểm)',
'',
'',
'',
'',
'',
'Câu trả lời đã được phục hồi',
'',
'Câu hỏi đã được phục hồi',
'Khiếu nại bị từ chối'
    );
}
KS_Util.prototype.getKid = function() {
	return this.kid;	
}
KS_Util.prototype.getRequestParameter =function(parameterName) {
	var queryString = window.top.location.search.substring(1)
	// Add "=" to the parameter name (i.e. parameterName=value)
	var parameterName = parameterName + "=";
	if ( queryString.length > 0 ) {
		// Find the beginning of the string
		var begin = queryString.indexOf ( parameterName );
		var end;
		// If the parameter name is not found, skip it, otherwise return the value
		if ( begin != -1 ) {
			// Add the length (integer) to the beginning
			begin += parameterName.length;
			// Multiple parameters are separated by the "&" sign
			end = queryString.indexOf ( "&" , begin );
			if ( end == -1 ) {
				end = queryString.length
			}
			// Return the string
			return unescape(queryString.substring(begin,end));
		}
		// Return "null" if no parameter has been found
		return null;
	}
}

KS_Util.prototype.getIsViewingSelf = function() {
	return this.isViewingSelf;	
}

KS_Util.prototype.setIsViewingSelf = function(pBool) {
	this.isViewingSelf = pBool;	
}

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="">Thông báo</span>';
	else if (pPt == 0) s +='<span style="">Thông báo</span>';
	else if (pPt > 0) s +='<span style="color:#52be0a">Cảm ơn!</span>';
	else s +='<span style="">Thông báo</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">Chào <a href="/my/my">' + this.nick + '</a>! Kiểm tra <a href="/my/my?link=question&more=y">các câu hỏi</a> của bạn để tìm câu trả lời nhất</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://l.yimg.com/a/i/us/sch/gr2/medal.gif" vspace="12" style="border:none;" alt="award medal" /></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>Một số <a href="' + tmpUrl + '">câu hỏi của bạn</a> cần được quan tâm!</strong></span></td>';
        }
        else {
	       	s += '<td style="width:60px; height:50px; vertical-align:middle; text-align:center;"><img src="http://l.yimg.com/a/i/us/sch/gr2/medal.gif" vspace="12" style="border:none;" alt="award medal" /></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) ? "điểm" : "số điểm";
				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 += "Bạn đã ghi được <strong>"+ count +"</strong> điểm!";
                	s +=' </span>';//need the space for aesthetic reasons
                } else {
					s += '<strong style="margin-top:12px; font-size:115%;">Thông báo</strong><br/>';
					var _num = (count * -1);
                	s += "Bạn bị trừ <strong>" + _num + "</strong> điểm!";
                	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">Hãy cho tôi biết thêm</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();
    if(this.getKid() != undefined) {
        this.initMCE();
    }
    hasWindowLoaded = true;
}


/**
 * Initialize mini consumption environment (if applicable, based on the current URI)
 */
KS_Util.prototype.initMCE = function() {
	var in_hp = in_my = false;
	var aux_clean_URI = this.REQUEST_URI.replace(/;.*$/, '').replace(/\?.*$/, '');
	if( ( in_hp = (aux_clean_URI.search(/^(\/|\/index)$/) != -1) ) ||
	    ( in_my = (aux_clean_URI.search(/^(\/my\/my)$/) != -1) ) ) {
		this.MCEPageType = in_hp ? 'h' : 'm';
		if(!this.gObj('mce-js').innerHTML.replace(/^\s*/, '').replace(/\s*$/, '')) {
			YAHOO.util.Connect.asyncRequest('GET', '/common/util/ks-pref-xhr-handler.php?pt='+this.MCEPageType+'&rand='+this.getKid()+'+'+Math.round(Math.random()*1000), {
        success: this.successMCE,
        failure: this.failureMCE,
        scope: this
});
		} else {
			var embedded_json = unescape(this.gObj('mce-js').innerHTML);
			this.gObj('mce-js').innerHTML=''; // so as to avoid showing gibberish
			this.successMCE( {responseText: unescape(embedded_json) } );
		}
	}
}


KS_Util.prototype.successMCE = function(o) {
	var e_mc_div = this.gObj('mini-consumption');
	eval('var handler_nfo = ' + o.responseText);
	if(
	   handler_nfo['mhs'] != undefined &&
	   handler_nfo['mms'] != undefined &&
	   handler_nfo['mhe'] != undefined) {
		if(this.MCEPageType == 'm') {
			YAHOO.util.Dom.addClass(this.gObj('mini-consumption'), 'no-contacts');
		}
		
		this.MCEShowHP = handler_nfo['mhs'];
		this.MCEShowMy = handler_nfo['mms'];

        if(this.MCEShowHP != 1 && this.MCEShowHP != 0) this.MCEShowHP = 1;
        if(this.MCEShowMy != 1 && this.MCEShowMy != 0) this.MCEShowMy = 1;

		this.MCEEnable = handler_nfo['mhe'];
		this.HTML = handler_nfo['HTML'];
		this.MCENewItems = handler_nfo['ni'];
		this.MCEFriendsCount = handler_nfo['fc'];
		var unsignedUrl = '/common/util/ks-pref-xhr-handler.php';
		this.showUrl = handler_nfo.showUrl != undefined ? handler_nfo.showUrl : unsignedUrl;
		this.hideUrl = handler_nfo.hideUrl != undefined ? handler_nfo.hideUrl : unsignedUrl;
		this.closeUrl = handler_nfo.closeUrl != undefined ? handler_nfo.closeUrl : unsignedUrl;
		this.ceUrl = handler_nfo.ceUrl != undefined ? handler_nfo.ceUrl : '/my/contacts/from/';
		if(this.MCEPageType == 'm' || this.MCEEnable || this.MCEFriendsCount) {
			var init_cmd = undefined;
            if(this.HTML) e_mc_div.innerHTML = this.HTML;
			//YAHOO.util.Event.on('mini-c-no_friends-close', 'click', this.closeMCEListener, this, true);
			YAHOO.util.Event.on('mini-c-ctrl-a', 'click', this.toggleMCEListener, this, true);
			if(this.MCEPageType == 'm') {
				init_cmd = this.MCEShowMy == 0 ? 'init_close' : 'init_open';
			} else {
				init_cmd = this.MCEShowHP == 0 ? 'init_close' : 'init_open';
			}
			this.toggleMCE( {action: init_cmd} );
		}
	}
}

KS_Util.prototype.failureMCE = function(o) {

}

KS_Util.prototype.successSaveMCE = function(o) {
	// o.responseText should be "OK"
	this.debug('success handler got responseText:"'+o.responseText+'"');
}

KS_Util.prototype.failureSaveMCE = function(o) {

}

KS_Util.prototype.toggleMCE = function(o_data) {
	if(o_data.action == "h_close" && this.MCEPageType == 'h') {
		YAHOO.util.Connect.asyncRequest('GET', this.closeUrl+'?pt='+this.MCEPageType+'&p=mhe&v=0'+'&rand='+this.getKid()+'+'+Math.round(Math.random()*1000), {
        success: this.successSaveMCE,
        failure: this.failureSaveMCE,
        scope: this
});
	} else {
		var pref_name;
		var pref_value;
		if(o_data.action == "toggle") {
			pref_name = this.MCEPageType == 'h' ? 'mhs' : 'mms';
			var action = YAHOO.util.Dom.hasClass('mini-c-ctrl', 'hide') ? 'close' : 'open';
		} else if(o_data.action == "init_close") {
			var action = 'close';
		} else {
			var action = 'open';
		}
		var h3 = document.getElementById('mini-c').getElementsByTagName('h3')[0];
		var xhr_url;
		if(action == 'close') {
			YAHOO.util.Dom.replaceClass('mini-c-ctrl', 'hide', 'show');
			xhr_url = this.hideUrl;
			if(this.gObj('mini-c-ctrl-a') != null) {
				this.gObj('mini-c-ctrl-a').innerHTML = 'Hiển thị';
			}
			YAHOO.util.Dom.setStyle('mini-c-body', 'display', 'none');
			pref_value = 0;
			if(h3 != null) {
				if(this.MCENewItems == 0) {
					h3.innerHTML = '<span class="yks-beta"><a href="'+this.ceUrl+'">Hỏi & Đáp trong Mạng của tôi</a></span>' + ' <span class="white-space-pre">(Không có gì mới)</span>';
				} else {
					h3.innerHTML = '<span class="yks-beta"><a href="'+this.ceUrl+'">Hỏi & Đáp trong Mạng của tôi</a></span>' + ' <span class="white-space-pre">( <img class="mce_new" src="http://l.yimg.com/a/i/nt/ic/ut/bsc/new12_1.gif" alt="new"> Các mục mới)</span>';
				}
			}
		} else { // action == 'open'
			YAHOO.util.Dom.replaceClass('mini-c-ctrl', 'show', 'hide');
			xhr_url = this.showUrl;
			if(this.gObj('mini-c-ctrl-a') != null) {
				this.gObj('mini-c-ctrl-a').innerHTML = 'Ẩn';
			}
			YAHOO.util.Dom.setStyle('mini-c-body', 'display', 'block');
			pref_value = 1;
			if(h3 != null) {
				h3.innerHTML = '<span class="yks-beta"><a href="'+this.ceUrl+'">Hỏi & Đáp trong Mạng của tôi</a></span>';
			}
		}
                var els =  YAHOO.util.Dom.getElementsByClassName( 'tt-invite-listener' , 'img');
                var tts =  new YAHOO.widget.Tooltip("tt-invite", {context:els, autodismissdelay: 99999 } );
                
                // this probably shouldn't be here but, theres not reall any other hooks, when migrating create tooltips as a seperate module
                if (document.getElementById("tt-total-points-listener"))
                {
                  var tts =  new YAHOO.widget.Tooltip("tt-total-points", {context: 'tt-total-points-listener', autodismissdelay: 99999 } );
                }
                
		var tt = new YAHOO.widget.Tooltip("tt-invite", {context: 'mini-c-qm', autodismissdelay: 99999 } );
		var tt2 = new YAHOO.widget.Tooltip("tt-invite-contants", {context: 'mini-c-qm2', autodismissdelay: 99999 } );
//		var tt3 = new YAHOO.widget.Tooltip("tt-invite", {context: 'profile-hide-qa', autodismissdelay: 99999 } );
//		var tt4 = new YAHOO.widget.Tooltip("tt-invite", {context: 'profile-hide-contacts', autodismissdelay: 99999 } );
		
		if( pref_name != undefined  ) {
			YAHOO.util.Connect.asyncRequest('GET', xhr_url+'?pt='+this.MCEPageType+'&p='+pref_name+'&v='+pref_value+'&rand='+this.getKid()+'+'+Math.round(Math.random()*1000), {
        success: this.successSaveMCE,
        failure: this.failureSaveMCE,
        scope: this
});
		}
	}
}

KS_Util.prototype.toggleMCEListener = function(e) {
	this.toggleMCE( {action: "toggle"} );
	YAHOO.util.Event.stopEvent(e);
}

KS_Util.prototype.closeMCEListener = function(e) {
	this.toggleMCE( {action: "h_close"} );
	YAHOO.util.Event.stopEvent(e);
}

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;
}

function hideMiniC() {
    ctrl = Util.gObj('mini-c-ctrl');
    ctrl.className = "show";
    ctrl.innerHTML = "<a href=\"\" onclick=\"showMiniC(); return false;\">Hiển thị</a>";

	body = Util.gObj('mini-c-body');
	//var anim = new YAHOO.util.Anim(body, { opacity: {to: 0} }, 1, YAHOO.util.Easing.bounceOut);
	body.style.display = "none";
}

function showMiniC() {
    ctrl = Util.gObj('mini-c-ctrl');
    ctrl.className = "hide";
    ctrl.innerHTML = "<a href=\"\" onclick=\"hideMiniC(); return false;\">Ẩn</a>";

	body = Util.gObj('mini-c-body');
	body.style.display = "block";
	//var anim = new YAHOO.util.Anim(body, { opacity: { to: 1 } }, 1, YAHOO.util.Easing.bounceOut);
}

//Form Help to prevent empty searches in top nav
function validSearch(form) {
 var prodInput = YAHOO.util.Dom.get('psearch');
 //var searchMessage = YAHOO.util.Dom.get('searchMessage');
  if (prodInput.value == "") {
    prodInput.value = "Hãy nhập một từ tìm kiếm tại đây"
		prodInput.select();
	return (false);
     }
	if (prodInput.value == "Hãy nhập một từ tìm kiếm tại đây") {
    prodInput.value = "Hãy nhập một từ tìm kiếm tại đây"
		prodInput.select();
	return (false);
     }
  return (true);
  }
  
  // basic toggle function. send it an id that you want to switch from display none to block and vice versa
  //this assumes the target already has display:block or none specified. it won't work if it hasn't been declared.
function toggle(targetId){
  if (document.getElementById){
  	target = YAHOO.util.Dom.get(targetId);
		if (target.style.display == "none" ) {
  			target.style.display = "block";
  		} else {
  			target.style.display = "none";
  		}
	}
}

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()", 10000);
	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();
	}
}