﻿if(!window.onerror){
	try{window.onerror = function(){try{return location.href.indexOf("stage") == -1 && location.href.indexOf("release") == -1 && location.href.indexOf("myspace") != -1;}catch(ex){} return true; }}catch(e){}
}

//----------------------------------------------------------
// Copyright (C) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------
// MicrosoftAjax.js
Sys.Res={'argumentInteger':'Value must be an integer.','scriptLoadMultipleCallbacks':'The script \'{0}\' contains multiple calls to Sys.Application.notifyScriptLoaded(). Only one is allowed.','invokeCalledTwice':'Cannot call invoke more than once.','webServiceFailed':'The server method \'{0}\' failed with the following error: {1}','argumentType':'Object cannot be converted to the required type.','argumentNull':'Value cannot be null.','controlCantSetId':'The id property can\'t be set on a control.','formatBadFormatSpecifier':'Format specifier was invalid.','webServiceFailedNoMsg':'The server method \'{0}\' failed.','argumentDomElement':'Value must be a DOM element.','invalidExecutorType':'Could not create a valid Sys.Net.WebRequestExecutor from: {0}.','cannotCallBeforeResponse':'Cannot call {0} when responseAvailable is false.','actualValue':'Actual value was {0}.','enumInvalidValue':'\'{0}\' is not a valid value for enum {1}.','scriptLoadFailed':'The script \'{0}\' could not be loaded.','parameterCount':'Parameter count mismatch.','cannotDeserializeEmptyString':'Cannot deserialize empty string.','formatInvalidString':'Input string was not in a correct format.','invalidTimeout':'Value must be greater than or equal to zero.','cannotAbortBeforeStart':'Cannot abort when executor has not started.','argument':'Value does not fall within the expected range.','cannotDeserializeInvalidJson':'Cannot deserialize. The data does not correspond to valid JSON.','invalidHttpVerb':'httpVerb cannot be set to an empty or null string.','nullWebRequest':'Cannot call executeRequest with a null webRequest.','eventHandlerInvalid':'Handler was not added through the Sys.UI.DomEvent.addHandler method.','cannotSerializeNonFiniteNumbers':'Cannot serialize non finite numbers.','argumentUndefined':'Value cannot be undefined.','webServiceInvalidReturnType':'The server method \'{0}\' returned an invalid type. Expected type: {1}','servicePathNotSet':'The path to the web service has not been set.','argumentTypeWithTypes':'Object of type \'{0}\' cannot be converted to type \'{1}\'.','cannotCallOnceStarted':'Cannot call {0} once started.','badBaseUrl1':'Base URL does not contain ://.','badBaseUrl2':'Base URL does not contain another /.','badBaseUrl3':'Cannot find last / in base URL.','setExecutorAfterActive':'Cannot set executor after it has become active.','paramName':'Parameter name: {0}','cannotCallOutsideHandler':'Cannot call {0} outside of a completed event handler.','format':'One of the identified items was in an invalid format.','assertFailedCaller':'Assertion Failed: {0}\r\nat {1}','argumentOutOfRange':'Specified argument was out of the range of valid values.','webServiceTimedOut':'The server method \'{0}\' timed out.','notImplemented':'The method or operation is not implemented.','assertFailed':'Assertion Failed: {0}','invalidOperation':'Operation is not valid due to the current state of the object.','breakIntoDebugger':'{0}\r\n\r\nBreak into debugger?'};
if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();
///////////////////////////////////////////////////////////////////////////
//  Comments for this code can be found in source control
//////////////////////////////////////////////////////////////////////////
Type.registerNamespace("MySpace");

_queryString=function(){
	var __pairs = window.location.search.substring(1).split("&");
	for(var i=0;i<__pairs.length;i++){
		var pos=__pairs[i].indexOf('=');
		if(pos>=0){
			var name=__pairs[i].substring(0,pos).toLowerCase();
			var value=escape(__pairs[i].substring(pos+1));
			this[name]=value;
		}
	}
}
var queryString=new _queryString();
var fuseaction = queryString['fuseaction'];
function QueryString(key){return queryString[key.toLowerCase()];}//only here for backward compatibility, use construct above

function generalizeDomain(){
	var domain = document.domain;
	if(domain[domain.length-1]===".")return;
	var domains = domain.split(".");
	var domainsLength = domains.length;
	if (domainsLength >= 2){document.domain = domains[domainsLength - 2] + "." + domains[domainsLength - 1];}
}
var supressFuseactions = {"blog.create":0,"blog.edit":1,"blog.commentreply":2,"blog.comment":3,"forums.post":4,"mail.compose":5,"mail.message":6, "mail.reply":7, "mail.forward":8};
if(typeof supressGeneralizeDomain==="undefined" && typeof supressFuseactions[fuseaction]==="undefined") generalizeDomain();


// Stop using TextFilterWBR! 
// use MySpace.Util.InjectWBR, MySpace.Util.ApplyWBRtoElements and MySpace.Util.ApplyWBRtoElement
function TextFilterWBR(){
    var regex = new RegExp(/[^\s]{3}/mgi);
    var hs = this.match(/(<.*?>|&[#0-9a-zA-Z]{1,5};)/mgi);
    var o=[];
    var offset = 0;
    if(hs){
        for(var i = 0 ; i < hs.length; i++){
            o.push(this.substring(offset, offset = (this.indexOf(hs[i],offset))).replace(regex, "$&<wbr/>"));
            o.push(this.substring(offset, offset += hs[i].length));
        }
    }
    if(offset<this.length) 
        o.push(this.substring(offset,this.length).replace(regex, "$&<wbr/>"));
    
    return o.join("");
}
String.prototype.call = function(f,c){
    return f.call(this,c);
}
MySpace.Util=function(){throw "Cannot instantiate static class.";};
MySpace.Util.applyWBRToElements = function(elements,options){
	/// <param name="elements" type="Array" elementType="DomElement"></param>
	/// <param name="frequency" type="Number" integer="true" optional="true"></param>
	/// <param name="regex" type="RegExp" optional="true"></param>
	for(var i=0;i<elements.length;i++)
		MySpace.Util.applyWBRToElement(elements[i],options);
}
MySpace.Util.applyWBRToElement=function(element,options){
	/// <param name="elements" type="Array" elementType="DomElement"></param>
	/// <param name="options" type="Object" optional="true">
	///  options can include:
	///   frequency: number of non-whitespace chars to break after (defaults to 20)
	///   breakCharsRegex: regex for additional places where a break can be added after (defaults to all punctuation chars)
	/// </param>
	if(MySpace.Application.keyDisabled("CommonWordBreaker")){ return; }
	
	options=options || {};
	var frequency=options.frequency || 20;
	var breakCharsRegex=options.breakCharsRegex || MySpace.Util.applyWBRToElement._breakCharsRegex;
	var wrapChar=MySpace.Util.applyWBRToElement._wrapChar;
	var longWordRegex=new RegExp("\\S{"+frequency+",}", "g");
	var unbrokenCharsRegex=new RegExp("[^"+wrapChar+"]{"+frequency+"}(?!"+wrapChar+")", "g");	// 20 non-zwsp chars, not followed by a zwsp
	var replaceValue=MySpace.Util.applyWBRToElement._replaceValue;
	var bigChunkRegex=new RegExp("\\S{"+frequency+"}(?!$)", "g");	// 20 non-whitespace chars, not at the end of the string
	
	_r(element);
	function _r(e){
		if(!e || !e.childNodes)return;
		
		for(var i=0;i<e.childNodes.length;i++){
			var el=e.childNodes[i];
			if(/(STYLE|SCRIPT)/.test(el.nodeName)){ continue; }
			
			if(el.nodeType===3){
				if(Sys.Browser.agent===Sys.Browser.Safari){
                //check if the browser version is 3 or later
                    if (Sys.Browser.version > 522.12){
					//Safari doesn't support WBR well, so use zero-width space even though
					//it breaks copy-and-paste
					if(!MySpace.Util.applyWBRToElement._replaceFunctionSupported){ return; }

					el.nodeValue=el.nodeValue.replace(longWordRegex, function(word){
						return word.replace(breakCharsRegex, replaceValue).replace(unbrokenCharsRegex, replaceValue);
                        
					});
                    }else { return; }
				}else{
					//Keep splitting the text node and inserting a WBR every 20 chars, or
					//whenever punctuation is found
					var match;
					while(match=bigChunkRegex.exec(el.nodeValue)){
						var splitIdx=match.index+frequency;
						
						breakCharsRegex.lastIndex=match.index;
						var breakMatch=breakCharsRegex.exec(el.nodeValue);
						if(breakMatch && breakMatch.index<match.index+frequency){
							splitIdx=breakMatch.index+1;
						}

						var parent=el.parentNode;
						el=el.splitText(splitIdx);
						parent.insertBefore(document.createElement("wbr"), el);
						bigChunkRegex.lastIndex=0;
						
						// Advance past the newly created text node and WBR node
						i += 2;
					}
				}
			}
			else _r(el);
		}
	}
}
MySpace.Util.applyWBRToElement._breakCharsRegex=/[-!@#$%&*()_=+\[{\]}\\|;:'",.<>\/?`~^]/g;
MySpace.Util.applyWBRToElement._wrapChar="\u200B";	// zero-width space
MySpace.Util.applyWBRToElement._replaceValue="$&"+MySpace.Util.applyWBRToElement._wrapChar;
//Test for old Safari's (before 2.0.4) that don't support passing a function to String.replace
MySpace.Util.applyWBRToElement._replaceFunctionSupported=("x".replace(/./, function(){return "y";}) === "y");

Function.createPartial=function(scope, method /*, ...*/){
	var pre=[];
	for(var i=2;i<arguments.length;i++){ pre.push(arguments[i]); }
	var named=typeof method=="string";
	return function(){
		var f=named ? (scope || window)[method] : method;
		var args=pre.concat([]);
		for(var i=0;i<arguments.length;i++){ args.push(arguments[i]); }
		return f && f.apply(scope || window, args);
	};
};


var checkflag = "false";
function checkUncheckAll(f){
	if (checkflag == "false"){
		for (var i=0;i<f.length;i++)
			f[i].checked = true;
		f.checked = true;
		checkflag = "true";
	}else {
		for (var i=0; i < f.length; i++)
			f[i].checked = false;
		f.checked = false;
		checkflag = "false";
	}
}

function openWin( windowURL, windowName, windowFeatures ) {
	return window.open( windowURL, windowName, windowFeatures ) ;
}


function get_url() { //el=str, case_sensitive=bool
	var rs="i";
	var urls = document.URL;
	urls = urls.replace(/'/g,"");

	var el = "friendID";
	var re = new RegExp( "\\?[\\w\\W]*"+ el +"=([^\\&\\?#]*)", rs);
	var arr = re.exec(urls);
	if(!arr){
		elg = "groupID";
		var red = new RegExp( "\\?[\\w\\W]*"+ elg +"=([^\\&\\?#]*)", rs);
		arr = red.exec(urls);
	}
	if(arr && arr.length>1)return arr[1];
	else{
		var expr = /\/([\w]*)$/i;
		arr = expr.exec(urls);
			if(arr && arr.length>1) {
				return arr[1].toLowerCase(); }
			else {
				return ''; }
	}
}


function BrowserDetect() {
	var ua = navigator.userAgent.toLowerCase();

	this.isGecko	   = (ua.indexOf('gecko') != -1 && ua.indexOf('safari') == -1);
	this.isSafari	  = (ua.indexOf('safari') != - 1);
	this.isIE		  = (ua.indexOf('msie') != -1 && (ua.indexOf('webtv') == -1) );

	this.versionMinor = parseFloat(navigator.appVersion);

	if (this.isGecko) {
		this.versionMinor = parseFloat( ua.substring( ua.indexOf('/', ua.indexOf('gecko/') + 6) + 1 ) );
	}
	else if (this.isIE && this.versionMinor >= 4) {
		this.versionMinor = parseFloat( ua.substring( ua.indexOf('msie ') + 5 ) );
	}
	else if (this.isSafari) {
		this.versionMinor = parseFloat( ua.substring( ua.lastIndexOf('safari/') + 7 ) );
	}

	this.versionMajor = parseInt(this.versionMinor, 10);

	this.isWin	= (ua.indexOf('win') != -1);
	this.isMac	= (ua.indexOf('mac') != -1);

	this.isIE6x = (this.isIE && this.versionMajor == 6);
	this.isIE6up = (this.isIE && this.versionMajor >= 6);
}
var browser = new BrowserDetect();


// start MySpace Profile ShortCut
var profile_AddToFriends = '';
var profile_BlockUser='';  
        
        function shortCut(ddl)
	    {   if(ddl == null){return;}
	        if(!ddl.selectedIndex && !(ddl.selectedIndex > 0))
	        {   return; }
	        var selectedVal = ddl.options[ddl.selectedIndex].value.toLowerCase();
            var sTargetUrl  = '';                      
            var sFriendID   = MySpace.ClientContext.DisplayFriendId;
            var myToken     = MySpace.ClientContext.MyToken;
            var USERID_TOM  = 6221;
		    
		    
            switch(selectedVal)
            {   case 'sendmessage':
                    if(sFriendID == USERID_TOM)
                        sTargetUrl = 'http://collect.myspace.com/index.cfm?fuseaction=profile.mailTom&MyToken=' + myToken;
                    else
                        sTargetUrl = 'http://messaging.myspace.com/index.cfm?fuseaction=mail.message&friendID=' + sFriendID + '&MyToken=' + myToken;
                    break;                
                case 'forwardtofriend':
                    sTargetUrl = 'http://messaging.myspace.com/index.cfm?fuseaction=mail.forward&f=forwardprofile&friendID=' + sFriendID;

                    break;
                
                case 'addtofriends':
                    if(profile_AddToFriends.length>0)
                        sTargetUrl = profile_AddToFriends;
                    else
                        sTargetUrl = 'http://collect.myspace.com/index.cfm?fuseaction=invite.addfriend_verify&friendID=' + sFriendID + '&MyToken=' + myToken;
                    break;
                
                case 'addtofavorites':
                    sTargetUrl = 'http://collect.myspace.com/index.cfm?fuseaction=user.addToFavorite&public=0&friendID=' + sFriendID;

                    break;
                
                case 'blockuser':
                    if (confirm(profile_BlockUser))
                        sTargetUrl = 'http://collect.myspace.com/index.cfm?fuseaction=block.blockUser&userID=' + sFriendID;
                    else
                        return;
                    break;
                
                case 'addtogroup':
                    sTargetUrl = 'http://groups.myspace.com/index.cfm?fuseaction=groups.addtogroup&friendID=' + sFriendID;
                    break;
                
                case 'rankuser':
                    sTargetUrl = 'http://collect.myspace.com/index.cfm?fuseaction=RateImage.UserRating&UserID=' + sFriendID;
                    break;
                
                case 'instantmessage':
                    shortCut_InstantMsg();
                    return;
                    break;
                
                default:
            } 
	        //alert(selectedVal + '\n' + sTargetUrl);
		location.href = sTargetUrl;
        }
// end MySpace Profile ShortCut


// start MySpace IM code
function getIMwin(h,w) {
	var getIMurl = "http://www.myspace.com/Modules/IM/Pages/GetIM.aspx";
	var getIMh = h;
	var getIMw = w;
	var getIMleft = (screen.availwidth-w)/2;
	var getIMtop =(screen.availheight-h)/2;
	window.open(getIMurl,null,'height='+getIMh+',width='+getIMw+',left='+getIMleft+',top='+getIMtop+',status=no,toolbar=no,menubar=no,location=no');
}

function gotIM(){
	try{if (document.cookie && document.cookie.indexOf('imyspaceim') != -1)return true;}catch(err){}
	try{new ActiveXObject("MySpaceIMX.MySpaceIMPlugin.1");return true;}catch(err){}
	try{if(navigator.mimeTypes && navigator.mimeTypes.length>0)if(navigator.mimeTypes["application/myspaceim"])return true;}catch(err){}
	return false
}

function IsMySpaceIMInstalled(){IsMySpaceIMInstalledById(get_url());}
function IsMySpaceIMInstalledById(fid){
	if(gotIM())window.location.href='myim:sendIM?uID=0&cID='+fid;
	else getIMwin(475,600);
}
// end MySpace IM code

Type.registerNamespace("MySpace");
MySpace._Application = function() { MySpace._Application.initializeBase(this); }
MySpace._Application.prototype = { 
    Culture : {IPCulture:0, PreferredCulture:1},
	_list : {},
	_intMaintenanceConfigs : null,
	_maintenanceConfigs : null,
	isDOMLoaded : false,		
	add_DOMloaded : function(handler) {
		Array.add(this._getEvent("domloaded"), handler);
	},
	intlFeatureDisabled : function(key, culture, cultureType) {
	    if (!MySpace.ClientIntMaintenanceConfigs) MySpace.ClientIntMaintenanceConfigs = {};
	    	        
	    if (MySpace.ClientIntMaintenanceConfigs[key.toLowerCase()]) {
            var feature = MySpace.ClientIntMaintenanceConfigs[key.toLowerCase()];
            
            return this._checkFeatureDisabled(feature, culture, cultureType);
	    }
	    else
	        return false;
	},
	intlSubFeatureDisabled : function(featureKey, subFeatureKey, culture, cultureType) {
	    if (!MySpace.ClientIntMaintenanceConfigs) MySpace.ClientIntMaintenanceConfigs = {};
	    	        
	     if (MySpace.ClientIntMaintenanceConfigs[featureKey.toLowerCase()]) {
	        var feature = MySpace.ClientIntMaintenanceConfigs[featureKey.toLowerCase()];
	        
	        if (!this._checkFeatureDisabled(feature, culture, cultureType)) {
	            if (feature.subfeatures[subFeatureKey.toLowerCase()]) {
	                return this._checkFeatureDisabled(feature.subfeatures[subFeatureKey.toLowerCase()], culture, cultureType);
	            }
	            else
	                return false;
            }
            else
                return true;
	     }
	     else 
	        return false;
	},
	keyDisabled : function(key) {
        if (!MySpace.ClientMaintenanceConfigs) MySpace.ClientMaintenanceConfigs = {};
      
		if (MySpace.ClientMaintenanceConfigs[key.toLowerCase()] < 1)
			return true;
		else
			return false;	
	},
	remove_DOMloaded : function(handler) {
		var evt = this._getEvent("domloaded");
		if (!evt) return;
		Array.remove(evt, handler);
	},
	_checkFeatureDisabled : function(feature, culture, cultureType) {
	    if (feature.enabled) {
	        if (cultureType == MySpace.Application.Culture.PreferredCulture) {
                if (feature.excPrefCltr.length == 0 && feature.allPrefCltr.length == 0)
                    return false;
                
                if (Array.contains(feature.excPrefCltr, culture))
                    return true;
                   
                if (feature.allPrefCltr.length == 0 || Array.contains(feature.allPrefCltr, culture))
                    return false;
                else
                    return true;
            } else if (cultureType == MySpace.Application.Culture.IPCulture) {
                if (feature.excIPCltr.length == 0 && feature.allIPCltr.length == 0)
                    return false;
                    
                if (Array.contains(feature.excIPCltr, culture))
                    return true;
                    
                if (feature.allIPCltr.length == 0 || Array.contains(feature.allIPCltr, culture))
                    return false;
                else
                    return true;
            }
        }
        else 
            return true;
        
        return !feature.enabled;
	},
	_getEvent : function(id, create) {
		if (!this._list[id])
			this._list[id] = [];
		return this._list[id];
	},
	_raiseDOMloaded : function() {
	    this.isDOMLoaded=true;
	    
		var evt = this._getEvent("domloaded");
		if (!evt || (evt.length === 0)) return null;
		evt = Array.clone(evt);
		if (!evt._handler) {
			evt._handler = function(source, args) {
				for (var i = 0, l = evt.length; i < l; i++) {
					evt[i](source, args);
				}
			};
		}
		var h = evt._handler;
		if (h)
			h(this, null);
		var handler = this.get_events().getHandler('DOMloaded');
		if(handler) {
			var eventArgs = new Sys.EventArgs();
			handler(this, eventArgs);
		}
	}
}
MySpace._Application.registerClass('MySpace._Application', Sys.Component);
MySpace.Application = new MySpace._Application();

MySpace.Util.parseNameValuePair=function(nameValuePair, delimiter, modifier){
	/// <param name="nameValuePair" type="String"></param>
	/// <param name="delimiter" type="Regex"></param>
	/// <param name="modifier" type="Function" mayBeNull="true" optional="true"></param>
	/// <returns type="Object"></returns>
	if(!delimiter) delimiter="=";
	if(!nameValuePair || nameValuePair[0]===delimiter) return null;
	var nameValueObject;
	var pos=nameValuePair.search(delimiter);
	if(pos>0){
		nameValueObject={
			name:nameValuePair.substring(0,pos),
			value:nameValuePair.substring(pos+1)
		}
	}
	else nameValueObject={name:nameValuePair,value:""};

	if(modifier) nameValueObject=modifier(nameValueObject);
	return nameValueObject;
}
MySpace.Util.parseNameValuePairs=function(nameValuePairs, pairDelimiter, nameValueDelimiter, nameValueModifier){
	/// <param name="nameValuePairs" type="String"></param>
	/// <param name="pairDelimiter" type="Regex"></param>
	/// <param name="nameValueDelimiter" type="Regex"></param>
	/// <param name="modifier" type="Function" mayBeNull="true" optional="true"></param>
	/// <returns type="Object"></returns>
	var _collection=null,nameValuePair=null;
	var _pairs = nameValuePairs.split(pairDelimiter);
	for(var i=0;i<_pairs.length;i++){
		nameValuePair=MySpace.Util.parseNameValuePair(_pairs[i],nameValueDelimiter,nameValueModifier);
		if(!nameValuePair) continue;
		if(!_collection) _collection={};
		_collection[nameValuePair.name]=nameValuePair.value;
	}
	return _collection;
}

MySpace.Cookie=function(name, rawValue){
	/// <param name="name" type="String"></param>
	/// <param name="rawValue" type="String"></param>
	this._name = name;
	this._rawValue = rawValue;
	this._value = unescape(rawValue);
	this._values = MySpace.Util.parseNameValuePairs(rawValue,"&",null,this._modifier);
}
MySpace.Cookie.prototype={
	get_name:function(){return this._name;},
	get_value:function(){return this._value;},
	get_values:function(){return this._values;},

	_modifier:function(nameValueObject){
		if(!nameValueObject.value) return null;
		nameValueObject.value=unescape(nameValueObject.value);
		return nameValueObject;
	},
	toString:function(){
		/// <returns type="String"></returns>
		var valuesArray=[];
		var values=this.get_values();
		if(!values) return this.get_value();
		for(var i in values)
			valuesArray[valuesArray.length] = i+"="+escape(values[i]);
		return valuesArray.join("&");
	}
}
MySpace.Cookie.registerClass('MySpace.Cookie');

MySpace._Cookies=function(){
	var nvc = MySpace.Util.parseNameValuePairs(document.cookie,/\s?;\s?/,null);
	for(var name in nvc)
		this[name] = new MySpace.Cookie(name, nvc[name]);
}
MySpace._Cookies.prototype={
	save:function(cookie,domain,expires){
		/// <param name="cookie" type="MySpace.Cookie"></param>
		/// <param name="domain" type="String"></param>
		/// <param name="expires" type="Date"></param>
		var value=cookie.toString();
		var parts=[cookie.get_name()+"="+value];
		if(domain){
			if(domain!=="localhost" && domain.charAt(0)!==".")
				throw Error.invalidOperation("domain must start with '.'");
			parts[1]="domain="+domain;
		}
		if(expires)parts[parts.length]="expires="+expires.toGMTString();
		parts[parts.length]="path=/";
		document.cookie = parts.join("; "); 
		MySpace.Cookies=new MySpace._Cookies();
	},
	remove:function(cookieName, domain){
		/// <param name="cookieName" type="String"></param>
		this.save(new MySpace.Cookie(cookieName,""),domain,new Date().addDays(-1));
	}
}
MySpace._Cookies.registerClass('MySpace._Cookies');
MySpace.Cookies=new MySpace._Cookies();

Type.registerNamespace("MySpace.UI");

///////////////////////
// NEW GLOBAL HEADER //
///////////////////////
var msglobalnav = {

    $$: function(el, tag) { return el.getElementsByTagName(tag) },
    menuItems: [],
    isIntlFooterOn: false,
    searchTypesOn: 0,
    searchTimer: null,
    searchFramer: null,

    loadStrings: function(defs) {
        for (var classKey in defs) {
            if (!MySpaceRes[classKey]) { MySpaceRes[classKey] = {}; }

            for (var resourceKey in defs[classKey]) {
                MySpaceRes[classKey][resourceKey] = defs[classKey][resourceKey];
            }
        }
    },

    initNavigation: function() {
        var leftUL = $get("leftNav");
        var rightUL = $get("rightNav");
        var leftItems = leftUL.hasChildNodes ? leftUL.childNodes : [];
        var rightItems = rightUL.hasChildNodes ? rightUL.childNodes : [];
        var sheet = document.styleSheets[0];


        for (var i = 0; i < leftItems.length; i++)
            if (leftItems[i].nodeName === "LI" && leftItems[i].className.indexOf("dropDown") > -1) this.menuItems.push(leftItems[i]);
        for (var i = 0; i < rightItems.length; i++)
            if (rightItems[i].nodeName === "LI" && rightItems[i].className.indexOf("dropDown") > -1) this.menuItems.push(rightItems[i]);

        for (var i = 0; i < this.menuItems.length; i++) {
            var mi = this.menuItems[i];
            var subItems = this.$$(mi, "LI");
            var ul = this.$$(mi, "UL")[0];
            if (subItems.length > 0) {
                var min = 140;
                for (var j = 0; j < subItems.length; j++) { if (min < subItems[j].offsetWidth) { min = subItems[j].offsetWidth; } }
                if (this.$$(mi, "IFRAME")[0]) {
                    var currentId = (mi.id) ? mi.id : "";
                    sheet.addRule('div#topnav li#' + currentId + ' li', '{width:' + min + 'px;}');
                    sheet.addRule('div#topnav li#' + currentId + ' iframe', '{width:' + (min + 2) + 'px; height:' + ul.offsetHeight + 'px;}');
                }
            }
        }
    },

    addIE6Events: function() {

        for (var i = 0; i < this.menuItems.length; i++) {
            var mi = this.menuItems[i];
            var subItems = this.$$(mi, "LI");
            if (subItems.length > 0) {
                if (this.$$(mi, "IFRAME")[0]) {
                    mi.onmouseover = function() { this.className += (this.className.indexOf("hover") > -1) ? "" : " hover"; }
                    mi.onmouseout = function() { this.className = this.className.replace(" hover", ""); event.cancelBubble = true; }
                }
            }
        }
    },
    
    applyAlphaImageLoader : function(id, url, method) {
        var el = document.getElementById(id);
        if (el == null) return;
        var img = new Image();
        img.src = url;
        el.style.backgroundImage = 'none';
        $addHandler(window, 'load', function() {
            el.style.filter = 'progid:DXImagetransform.Microsoft.AlphaImageLoader(enabled="true", src="' + url + '", sizingMethod="' + method + '");';
        });
    },

    openSearchTypes: function(arg) {

        var isHeader = (arg.toLowerCase() === 'header');
        var searchMenuListBox = 'srchMenuListBox_' + arg;
        var searchList = $get(searchMenuListBox);
        if (searchList == null) return;

        searchList.className += (searchList.className.indexOf(' open') > -1) ? '' : ' open';
        var pos = Sys.UI.DomElement.getLocation(searchList);
        if (isHeader) {
            if (this.searchFramer == null) { this.searchFramer = this.$$(searchList, "IFRAME")[0]; }
            if (this.searchFramer) {
                this.searchFramer.style.width = searchList.offsetWidth + 'px';
                this.searchFramer.style.height = searchList.offsetHeight + 'px';
            }
        }
        window.clearTimeout(this.searchTimer);
        this.searchTimer = null;
    },

    hideSearchTypes: function(arg) {
        var x = this;
        this.searchTimer = setTimeout(function() {

            var searchMenuListBox = 'srchMenuListBox_' + arg;
            var searchList = $get(searchMenuListBox);
            if (searchList == null) return;

            searchList.className = '';
            if (x.searchFramer == null) { x.searchFramer = x.$$(searchList, "IFRAME")[0]; }

            x.searchTimer = null;
        }, 500);
    },

    switchSearchTypeTo: function(v, searchType) {
        var _after = '<small>&#9660;</small>';
        var types;
        var searchText = 'search_t_' + searchType;
        var searchTypeValue = 'searchTypeValue_' + searchType;
        var srchMenuListBox = 'srchMenuListBox_' + searchType;
        var typeName = v + '_' + searchType;
        if ($get(searchText)) $get(searchText).value = v;
        if ($get(typeName))
            if ($get(searchTypeValue)) $get(searchTypeValue).innerHTML = $get(typeName).innerHTML + _after;

        if ($get(srchMenuListBox)) $get(srchMenuListBox).className = '';

        window.clearTimeout(this.searchTimer);
        this.searchTimer = null;
    },

    srchMenuList: function(isOn, searchType) {
        var x = this;
        if (isOn) {
            window.clearTimeout(this.searchTimer);
            this.searchTimer = null;
        }
        else {
            this.searchTimer = setTimeout(function() {

                var srchMenuListBox = 'srchMenuListBox_' + searchType;
                if ($get(srchMenuListBox)) $get(srchMenuListBox).className = '';
                x.searchTimer = null;
            }, 500);
        }
    },

    searchLocation: function(url, fuseaction, type, qry) {
        var fuseAction = $get(fuseaction);
        var typeElement = $get(type);
        var qryElement = $get(qry);
        if (qryElement.value.length > 0) {
            window.location = url + fuseAction.name + "=" + fuseAction.value + "&" + typeElement.name + "=" + typeElement.value
								+ "&" + qryElement.name + "=" + qryElement.value + '&submit=Search';
        }
        return false;
    },

    toggleInternationalLinks: function() {
        var internationalLinks = $get('internationalLinks');
        var intlLink = $get('intlLink');
        if (this.isIntlFooterOn) {
            internationalLinks.style.left = "-100000px";
        }
        else {
            var pos = Sys.UI.DomElement.getLocation(intlLink);
            internationalLinks.style.top = (-internationalLinks.offsetHeight) + 'px';
            internationalLinks.style.left = (pos.x - (internationalLinks.offsetWidth / 2) + (intlLink.offsetWidth / 2)) + 'px';
        }        
        this.isIntlFooterOn = !this.isIntlFooterOn;
    },

    initializeProfileSearchMenu: function(defaultVal) {

        if (!defaultVal) return;

        if (MySpace.ClientContext.FunctionalContext) {
            if (MySpace.ClientContext.FunctionalContext === "UserViewProfile") {
                if (MySpace.ClientContext.ProfileType === "Band") {
                    switchSearchTypeTo('Music', 'Header');
                }
            }
        }
    },
    
    
    // BACKWARDS COMPATIBILITY (V1,Ad Profiles ONLY)
	framer : null,
    menuTopOffset : (Sys.Browser.agent === Sys.Browser.InternetExplorer) ? -3 : 0,
    menuLeftOffset : (Sys.Browser.agent === Sys.Browser.InternetExplorer) ? -3 : 0,
    linkOffset : (Sys.Browser.agent === Sys.Browser.InternetExplorer && document.compatMode == "BackCompat") ? 0 : -15,
    timerOut : null,
    menuOutTime : 250,
    currentItemId : null,
    
    toggle : function(id, show) {
        if (show) {
            var subNavDropDown = this.getSubNav(id);
            //cancel the time
            if (this.timerOut) {
                clearTimeout(this.timerOut);
                this.timerOut = null;
            }

            //turn off previous					
            if (this.currentItemId != null) {
                var current = this.getItems(this.currentItemId);
                current.parent.className = '';
                this.framer.style.left = '-100000px';
                current.child.style.left = '-100000px';
                this.currentItemId = null;
            }
            //turn-on new one
            subNavDropDown.child.style.left = subNavDropDown.childLeft
            subNavDropDown.child.style.top = subNavDropDown.childTop
            subNavDropDown.parent.className = 'open';

            if (this.framer == null) { this.framer = document.getElementById('framer'); }
            
            this.framer.style.left = subNavDropDown.childLeft;
            this.framer.style.top = subNavDropDown.childTop;
            this.framer.style.width = subNavDropDown.child.offsetWidth + 'px';
            this.framer.style.height = subNavDropDown.child.offsetHeight + 'px';
            this.framer.style.zIndex = subNavDropDown.child.style.zIndex + 1;
            this.framer.style.display = 'block';
            this.currentItemId = id;
        }
        else {
            this.timerOut = setTimeout(function(){msglobalnav.hideDropDown(id);}, this.menuOutTime);
        }
    },    
    
    getSubNav : function(id) {
        var items = this.getItems(id);
        var subNavDropDown = {};
        subNavDropDown.parent = items.parent;
        subNavDropDown.child = items.child;
        if (!items.parent.resized){
			this.fixedSub(subNavDropDown.child, subNavDropDown.parent);
			items.parent.resized = true;
		}
        var pos = Sys.UI.DomElement.getLocation(items.parent);
		subNavDropDown.childLeft = pos.x + 'px';
        subNavDropDown.childTop = (pos.y + items.parent.offsetHeight) + 'px';
        return subNavDropDown;
    },
    
    getItems : function(id) { 
		return { 'child': document.getElementById('subNav' + id), 'parent': document.getElementById('nav' + id) };
    },
    
    fixedSub : function(sub, parent) {
        //FIX FOR UHP
        var d = document.getElementById('userdisplay');
        var uhpOffset = 0;
        if (d && d.className === 'module' && d.tagName === 'DIV') { uhpOffset = 1; }

        var items = sub.getElementsByTagName('LI');

        var max = 140;
        for (var i = 0; i < items.length; i++) {
            if (max < items[i].offsetWidth) { max = items[i].offsetWidth; }
        }
        
        if (max < parent.offsetWidth) max = parent.offsetWidth;
        sub.style.width = max + 'px';

        for (var i = 0; i < items.length; i++) {
            items[i].style.width = max + 'px';
            items[i].getElementsByTagName('A')[0].style.width = (max + this.linkOffset + uhpOffset) + 'px';
        }
    },
    
    hideDropDown : function(id) {
        var subNavDropDown = this.getItems(id);
        subNavDropDown.parent.className = '';
        this.framer.style.left = '-100000px';
        this.framer.style.display = 'none';
        subNavDropDown.child.style.left = '-100000px';
        this.timerOut = null;
        this.currentItemId = null;
    },
    
    subToggle : function(id, show) {
        if (show) {
            if (this.timerOut) {
                clearTimeout(this.timerOut);
                this.timerOut = null;
            }
        }
        else {
            this.timerOut = setTimeout(function(){msglobalnav.hideDropDown(id);}, this.menuOutTime);
        }
    }
    
};



MySpace.UI.DefaultTextboxBehavior=function(e){
	MySpace.UI.DefaultTextboxBehavior.initializeBase(this, [e]);
	
	this._defaultValue="";
};
MySpace.UI.DefaultTextboxBehavior.prototype={
	initialize:function(){
		MySpace.UI.DefaultTextboxBehavior.callBaseMethod(this, "initialize");

		var e=this.get_element();
		
		this.set_value(e.value);
		
		this._focusHandler=Function.createDelegate(this, this._onFocus);
		$addHandler(e, "focus", this._focusHandler);
		this._blurHandler=Function.createDelegate(this, this._onBlur);
		$addHandler(e, "blur", this._blurHandler);
	},
	
	dispose:function(){
		$removeHandler(this.get_element(), "focus", this._focusHandler);
		$removeHandler(this.get_element(), "blur", this._blurHandler);
		MySpace.UI.DefaultTextboxBehavior.callBaseMethod(this, "dispose");
	},
	
	_onFocus:function(e){
		if(this.get_element().value==this._defaultValue){
			this.get_element().value="";
			this._updateClass();
		}
	},
	_onBlur:function(e){
		if(!this.get_element().value){
			this.get_element().value=this._defaultValue;
			this._updateClass();
		}
	},
	
	_updateClass:function(){
		var e=this.get_element();
		if(e.value==this._defaultValue){
			Sys.UI.DomElement.addCssClass(e, "msDefaultTextbox");
		}
		else{
			Sys.UI.DomElement.removeCssClass(e, "msDefaultTextbox");
		}
	},
	
	get_defaultValue:function(){ return this._defaultValue; },
	set_defaultValue:function(val){
		if(this.get_element().value==this._defaultValue){
			this.get_element().value=val;
		}
		this._defaultValue=val;
	},
	
	get_value:function(){
		if(this.get_element().value==this._defaultValue){
			return "";
		}
		else{
			return this.get_element().value;
		}	
	},
	set_value:function(val){
		this.get_element().value=val || this._defaultValue;
		this._updateClass();
	}
};
MySpace.UI.DefaultTextboxBehavior.registerClass("MySpace.UI.DefaultTextboxBehavior", Sys.UI.Behavior);


MySpace.UI.ProfileImageLink={
	counter:0,
	images:[],
	
	onLoad:function(img,evt){
		if(!(img && img.tagName.toLowerCase()=="img")){
			img=evt.target || evt.srcElement;
		}
		
		if(String(img.src).indexOf(".")>0 && img.getAttribute("thsrc")){
			var i=this.counter++;
			this.images[i]={image:img, bgLoader:new Image()};
			this.images[i].bgLoader.onload=Function.createPartial(MySpace.UI.ProfileImageLink, "onBgLoad", i);
			this.images[i].bgLoader.onerror=Function.createPartial(MySpace.UI.ProfileImageLink, "onBgError", i);
			this.images[i].bgLoader.src=img.getAttribute("thsrc");
		}
		
		img.onload = null;
	},
	
	onBgLoad:function(i){
		var bgLoader=this.images[i].bgLoader,
			image=this.images[i].image,
			maxWidth=parseInt(image.getAttribute("MaxWidth")),
			maxHeight=parseInt(image.getAttribute("MaxHeight"));
		
		if(bgLoader.height>bgLoader.width){
			image.style.height=maxHeight+"px";
			image.style.maxHeight=maxHeight+"px"; // Needed for Firefox2
			image.style.width=(bgLoader.width*maxHeight/bgLoader.height)+"px";
		}
		else{
			var imgHeight=bgLoader.height*maxWidth/bgLoader.width;
			image.style.height=imgHeight+"px";
			image.style.width=maxWidth+"px";
			var fixHeight=(maxHeight - imgHeight ) / 2;
			if(fixHeight*2 < maxWidth){
				image.style.paddingTop=image.style.paddingBottom=fixHeight + "px";
			}
		}        

		image.setAttribute("alsrc",image.getAttribute("thsrc"));
		image.setAttribute("thsrc","")        
		image.src=image.getAttribute("alsrc");       
		bgLoader.onload = null;
	},
	
	onBgError:function(i){
		UseNoPicImage(this.images[i].image);
	}
};


//
// MySpace.Timer component
//

MySpace.Timer=function(){
	MySpace.Timer.initializeBase(this);
	this._interval=1000;
	this._enabled=false;
	this._timer=null
};
MySpace.Timer.prototype={
	get_interval:function(){
		return this._interval
	},
	set_interval:function(a){
		if(this._interval!==a){
			this._interval=a;
			this.raisePropertyChanged("interval");
			if(!this.get_isUpdating()&&this._timer!==null)this.restartTimer()
		}
	},
	get_enabled:function(){
		return this._enabled
	},
	set_enabled:function(a){
		if(a!==this.get_enabled()){
			this._enabled=a;
			this.raisePropertyChanged("enabled");
			if(!this.get_isUpdating())if(a)this._startTimer();
			else this._stopTimer()
		}
	},
	add_tick:function(a){
		this.get_events().addHandler("tick",a)
	},
	remove_tick:function(a){
		this.get_events().removeHandler("tick",a)
	},
	dispose:function(){
		this.set_enabled(false);
		this._stopTimer();
		MySpace.Timer.callBaseMethod(this,"dispose")
	},
	updated:function(){
		MySpace.Timer.callBaseMethod(this,"updated");
		if(this._enabled)this.restartTimer()
	},
	_timerCallback:function(){
		var a=this.get_events().getHandler("tick");
		if(a)a(this,Sys.EventArgs.Empty)
	},
	restartTimer:function(){
		this._stopTimer();
		this._startTimer()
	},
	_startTimer:function(){
		this._timer=window.setInterval(Function.createDelegate(this,this._timerCallback),this._interval)
	},
	_stopTimer:function(){
		window.clearInterval(this._timer);
		this._timer=null
	}
};
MySpace.Timer.registerClass("MySpace.Timer",Sys.Component);



//
// MySpace.UI.PopupBehavior
//

MySpace.UI.PopupBehavior=function(element){
	/// <summary>
	/// The PopupBehavior is used to show/hide an element at a position
	/// relative to another element
	/// </summary>
	/// <param name="element" type="Sys.UI.DomElement" mayBeNull="false" domElement="true">
	/// The DOM element the behavior is associated with
	/// </param>
	MySpace.UI.PopupBehavior.initializeBase(this, [element]);

	this._x=0;
	this._y=0;
	this._positioningMode=MySpace.UI.PositioningMode.Absolute;
	this._parentElement=null;
	this._parentElementID=null;
	this._moveHandler=null;
	this._firstPopup=true;	
	this._originalParent=null;
	this._visible=false;
	this._hideOnDocumentClick=false;
	
	this._onShow=null;
	this._onShowEndedHandler=null;
	this._onHide=null;
	this._onHideEndedHandler=null;
}
MySpace.UI.PopupBehavior.prototype={
	initialize:function(){
		/// <summary>
		/// Initialize the PopupBehavior
		/// </summary>
		MySpace.UI.PopupBehavior.callBaseMethod(this, 'initialize');
		
		this._hidePopup();
		this.get_element().style.position="absolute";
		
		// Create handlers for the animation ended events
		this._onShowEndedHandler=Function.createDelegate(this, this._onShowEnded);
		this._onHideEndedHandler=Function.createDelegate(this, this._onHideEnded);
		
		$addHandler(document.body, "mousedown", Function.createDelegate(this, this._onDocumentClick));
	},
	
	dispose:function(){
		/// <summary>
		/// Dispose the PopupBehavior
		/// </summary>
	
		var element=this.get_element();
		if(element){
			if(this._visible){
				this.hide();
			}
			if(this._originalParent){
				element.parentNode.removeChild(element);
				this._originalParent.appendChild(element);
				this._originalParent=null;
			}
			
			// Remove expando properties
			element._hideWindowedElementsIFrame=null;
		}
		this._parentElement=null;

		// Remove the animation ended events and wipe the animations
		// (we don't need to dispose them because that will happen
		// automatically in our base dispose)
		if(this._onShow && this._onShowEndedHandler){
			this._onShow.remove_ended(this._onShowEndedHandler);
		}
		this._onShowEndedHandler=null;
		this._onShow=null;
		if(this._onHide && this._onHideEndedHandler){
			this._onHide.remove_ended(this._onHideEndedHandler);
		}
		this._onHideEndedHandler=null;
		this._onHide=null;
		
		MySpace.UI.PopupBehavior.callBaseMethod(this, 'dispose');
	},
	
	show:function(){
		/// <summary>
		/// Show the popup
		/// </summary>
		
		// Ignore requests to hide multiple times
		if(this._visible){
			return;
		}
		
		var eventArgs=new Sys.CancelEventArgs();
		this.raiseShowing(eventArgs);
		if(eventArgs.get_cancel()){
			return;
		}
		
		// Either show the popup or play an animation that does
		// (note: even if we're animating, we still show and position
		// the popup before hiding it again and playing the animation
		// which makes the animation much simpler)
		this._visible=true;
		var element=this.get_element();
		element.style.visibility="visible";
		this.setupPopup();
		if(this._onShow){
			element.style.visibility="hidden";
			this.onShow();
		} else {
			this.raiseShown(Sys.EventArgs.Empty);
		}
	},
	
	hide:function(){
		/// <summary>
		/// Hide the popup
		/// </summary>
		
		// Ignore requests to hide multiple times
		if(!this._visible){
			return;
		}
		
		var eventArgs=new Sys.CancelEventArgs();
		this.raiseHiding(eventArgs);
		if(eventArgs.get_cancel()){
			return;
		}

		// Either hide the popup or play an animation that does
		this._visible=false;
		if(this._onHide){
			this.onHide();
		} else {
			this._hidePopup();
			this._hideCleanup();
		}
	},
	
	getBounds:function(){
		/// <summary>
		/// Get the expected bounds of the popup relative to its parent
		/// </summary>
		/// <returns type="Sys.UI.Bounds" mayBeNull="false">
		/// Bounds of the popup relative to its parent
		/// </returns>
		/// <remarks>
		/// The actual final position can only be calculated after it is
		/// initially set and we can verify it doesn't bleed off the edge
		/// of the screen.
		/// </remarks>
	
		var element=this.get_element();
		
		// offsetParent (doc element if absolutely positioned or no offsetparent available)
		var offsetParent=element.offsetParent;
		if(!offsetParent || (offsetParent==document.documentElement)){ offsetParent=document.body; }
		
		// diff=difference in position between element's offsetParent and the element we will attach popup to.
		// this is basically so we can position the popup in the right spot even though it may not be absolutely positioned
		var diff;
		var parentBounds;
		if(this._parentElement){
			// we will be positioning the element against the assigned parent
			parentBounds=Sys.UI.DomElement.getBounds(this._parentElement);
			
			var offsetParentLocation=Sys.UI.DomElement.getLocation(offsetParent);
			diff={x: parentBounds.x - offsetParentLocation.x, y:parentBounds.y - offsetParentLocation.y};
		} else {
			// we will be positioning the element against the offset parent by default, since no parent element given
			parentBounds=Sys.UI.DomElement.getBounds(offsetParent);
			diff={x:0, y:0};
		}

		// width/height of the element, needed for calculations that involve width like centering
		var width=element.offsetWidth - (element.clientLeft ? element.clientLeft * 2:0);
		var height=element.offsetHeight - (element.clientTop ? element.clientTop * 2:0);

		// Setting the width causes the element to grow by border+passing every
		// time.  But not setting it causes strange behavior in safari. Just set it once.
		if(this._firstpopup){
			element.style.width=width + "px";
			this._firstpopup=false;
		}
		
		var position;
		switch (this._positioningMode){
			case MySpace.UI.PositioningMode.Center:
				position={
					x: Math.round(parentBounds.width / 2 - width / 2),
					y: Math.round(parentBounds.height / 2 - height / 2)
				};
				break;
			case MySpace.UI.PositioningMode.BottomLeft:
				position={
					x: 0,
					y: parentBounds.height
				};
				break;
			case MySpace.UI.PositioningMode.BottomRight:
				position={
					x: parentBounds.width - width,
					y: parentBounds.height
				};
				break;
			case MySpace.UI.PositioningMode.TopLeft:
				position={
					x: 0,
					y: -element.offsetHeight
				};
				break;
			case MySpace.UI.PositioningMode.TopRight:
				position={
					x: parentBounds.width - width,
					y: -element.offsetHeight
				};
				break;
			case MySpace.UI.PositioningMode.Right:
				position={
					x: parentBounds.width,
					y: 0
				};
				break; 
			case MySpace.UI.PositioningMode.Left:
				position={
					x: -element.offsetWidth,
					y: 0
				};
				break;				   
			default:
				position={x: 0, y: 0};
		}
		position.x += this._x + diff.x;
		position.y += this._y + diff.y;
		
		
		return new Sys.UI.Bounds(position.x, position.y, width, height);
	},

	adjustPopupPosition:function(bounds){
		/// <summary>
		/// Adjust the position of the popup after it's originally bet set
		/// to make sure that it's visible on the page.
		/// </summary>
		/// <param name="bounds" type="Sys.UI.Bounds" mayBeNull="true" optional="true">
		/// Original bounds of the parent element
		/// </param>

		var element=this.get_element();
		if(!bounds){
			bounds=this.getBounds();
		}
		
		// Get the new bounds now that we've shown the popup
		var newPosition=Sys.UI.DomElement.getBounds(element);
		var updateNeeded=false;

		if(newPosition.x < 0){
			bounds.x -= newPosition.x;
			updateNeeded=true;
		}
		if(newPosition.y < 0){
			bounds.y -= newPosition.y;
			updateNeeded=true;
		}

		// If the popup was off the screen, reposition it
		if(updateNeeded){
			Sys.UI.DomElement.setLocation(element, bounds.x, bounds.y);
		}
	},
	
	addBackgroundIFrame:function(){
		/// <summary>
		/// Add an empty IFRAME behind the popup (for IE6 only) so that SELECT, etc., won't
		/// show through the popup.
		/// </summary>
	
		// Get the child frame
		var element=this.get_element();
		if((Sys.Browser.agent === Sys.Browser.InternetExplorer) && (Sys.Browser.version < 7)){
			var childFrame=element._hideWindowedElementsIFrame;
			
			// Create the child frame if it wasn't found
			if(!childFrame){
				childFrame=document.createElement("iframe");
				childFrame.src="javascript:'<html></html>';";
				childFrame.style.position="absolute";
				childFrame.style.display="none";
				childFrame.scrolling="no";
				childFrame.frameBorder="0";
				childFrame.tabIndex="-1";
				childFrame.style.filter="progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)";
				element.parentNode.insertBefore(childFrame, element);
				element._hideWindowedElementsIFrame=childFrame;
				this._moveHandler=Function.createDelegate(this, this._onMove);
				Sys.UI.DomEvent.addHandler(element, "move", this._moveHandler);
			}
			
			// Position the frame exactly behind the element
			childFrame.style.width=element.offsetWidth+"px";
			childFrame.style.height=element.offsetHeight+"px";
			childFrame.style.display=element.style.display;
			if(element.currentStyle && element.currentStyle.zIndex){
				childFrame.style.zIndex=element.currentStyle.zIndex;
			}
			else if(element.style.zIndex){
				childFrame.style.zIndex=element.style.zIndex;
			}
		}
	},
	
	setupPopup:function(){
		/// <summary>
		/// Position the popup relative to its parent
		/// </summary>
		
		var element=this.get_element();
		var bounds=this.getBounds();
		Sys.UI.DomElement.setLocation(element, bounds.x, bounds.y);

		// Tweak the position, set the zIndex, and add the background iframe in IE6
		this.adjustPopupPosition(bounds);
		element.zIndex=1000;
		this.addBackgroundIFrame();
	},
	
	_hidePopup:function(){
		/// <summary>
		/// Internal hide implementation
		/// </summary>
		
		var element=this.get_element();
		element.style.visibility="hidden";
		if(element.originalWidth){
			element.style.width=element.originalWidth + "px";
			element.originalWidth=null;
		}
	},
	
	_hideCleanup:function(){
		/// <summary>
		/// Perform cleanup after hiding the element
		/// </summary>
	
		var element=this.get_element();
		
		// Remove the tracking handler
		if(this._moveHandler){
			Sys.UI.DomEvent.removeHandler(element, "move", this._moveHandler);
			this._moveHandler=null;
		}
		
		// Hide the child frame
		if(Sys.Browser.agent === Sys.Browser.InternetExplorer){
			var childFrame=element._hideWindowedElementsIFrame;
			if(childFrame){
				childFrame.style.display="none";
			}
		}
		
		this.raiseHidden(Sys.EventArgs.Empty);
	},
	
	_onDocumentClick:function(e){
		if(!this._hideOnDocumentClick || !this._visible){ return; }
		
		for(var node=e.target; node; node=node.parentNode){
			if(node==this.get_element()){
				return;
			}
		}
		
		this.hide();
	},
	
	_onMove:function(){
		/// <summary>
		/// Track the popup's movements so the hidden IFrame (IE6 only) can
		/// be moved along with it
		/// </summary>
		
		var element=this.get_element();
		if(element._hideWindowedElementsIFrame){
			element.parentNode.insertBefore(element._hideWindowedElementsIFrame, element);
			element._hideWindowedElementsIFrame.style.top=element.style.top;
			element._hideWindowedElementsIFrame.style.left=element.style.left;
		}
	},
	
	get_onShow:function(){
		/// <value type="MySpace.UI.Effects.Animation" mayBeNull="true">
		/// Animation to play when the popup is shown
		/// </value>
		return this._onShow;
	},
	set_onShow:function(value){
		this._onShow=value;
		if(value){
			value.set_target(this.get_element());
			value.add_ended(this._onShowEndedHandler);
		}
	},
	onShow:function(){
		/// <summary>
		/// Play the OnShow animation
		/// </summary>
		/// <returns />
		if(this._onShow){
			if(this._onHide){
				this._onHide.stop();
			}
			this._onShow.play();
		}
	},
	_onShowEnded:function(){
		/// <summary>
		/// Handler for the OnShow Animation's Ended event
		/// </summary>
		
		// Make sure the popup is where it belongs
		this.adjustPopupPosition();
		this.addBackgroundIFrame();
		
		this.raiseShown(Sys.EventArgs.Empty);
	},
	
	get_onHide:function(){
		/// <value type="MySpace.UI.Effects.Animation" mayBeNull="true">
		/// Animation to play when the popup is hidden
		/// </value>
		return this._onHide;
	},
	set_onHide:function(value){
		this._onHide=value;
		if(value){
			value.set_target(this.get_element());
			value.add_ended(this._onHideEndedHandler);
		}
	},
	onHide:function(){
		/// <summary>
		/// Play the OnHide animation
		/// </summary>
		/// <returns />
		if(this._onHide){
			if(this._onShow){
				this._onShow.stop();
			}
			this._onHide.play();
		}
	},
	_onHideEnded:function(){
		/// <summary>
		/// Handler for the OnHide Animation's Ended event
		/// </summary>
		
		this._hideCleanup();
	},
	
	get_parentElement:function(){
		/// <value type="Sys.UI.DomElement" domElement="true">
		/// Parent dom element.
		/// </value>
		
		if(!this._parentElement && this._parentElementID){
			this.set_parentElement($get(this._parentElementID));
		}		
		return this._parentElement;
	},
	set_parentElement:function(element){
		this._parentElement=element;
	},
	
	get_parentElementID:function(){
		/// <value type="String">
		/// Parent dom element.
		/// </value>
		
		if(this._parentElement){
			return this._parentElement.id
		}
		return this._parentElementID;
	},
	set_parentElementID:function(elementID){
		this._parentElementID=elementID;
		if(this.get_isInitialized()){
			this.set_parentElement($get(elementID));
		}
	},
		
	get_positioningMode:function(){
		/// <value type="MySpace.UI.PositioningMode">
		/// Positioning mode.
		/// </value>
		return this._positioningMode;
	},
	set_positioningMode:function(mode){
		this._positioningMode=mode;
	},
	
	get_x:function(){
		/// <value type="Number">
		/// X coordinate.
		/// </value>
		return this._x;
	},
	set_x:function(value){
		if(value != this._x){
			this._x=value;
			
			// Reposition the popup if it's already showing
			if(this._visible){
				this.setupPopup();
			}
		}
	},
	
	get_y:function(){
		/// <value type="Number">
		/// Y coordinate.
		/// </value>
		return this._y;
	},
	set_y:function(value){
		if(value != this._y){
			this._y=value;
			
			// Reposition the popup if it's already showing
			if(this._visible){
				this.setupPopup();
			}
		}
	},
	
	get_visible:function(){
		/// <value type="Boolean" mayBeNull="false">
		/// Whether or not the popup is currently visible
		/// </value>
		return this._visible;
	},
	
	get_hideOnDocumentClick:function(){ return this._hideOnDocumentClick; },
	set_hideOnDocumentClick:function(value){ this._hideOnDocumentClick=value; },
	
	add_showing:function(handler){
		/// <summary>
		/// Add an event handler for the showing event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().addHandler('showing', handler);
	},
	remove_showing:function(handler){
		/// <summary>
		/// Remove an event handler from the showing event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().removeHandler('showing', handler);
	},
	raiseShowing:function(eventArgs){
		/// <summary>
		/// Raise the showing event
		/// </summary>
		/// <param name="eventArgs" type="Sys.CancelEventArgs" mayBeNull="false">
		/// Event arguments for the showing event
		/// </param>
		/// <returns />
		
		var handler=this.get_events().getHandler('showing');
		if(handler){
			handler(this, eventArgs);
		}
	},
	
	add_shown:function(handler){
		/// <summary>
		/// Add an event handler for the shown event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().addHandler('shown', handler);
	},
	remove_shown:function(handler){
		/// <summary>
		/// Remove an event handler from the shown event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().removeHandler('shown', handler);
	},
	raiseShown:function(eventArgs){
		/// <summary>
		/// Raise the shown event
		/// </summary>
		/// <param name="eventArgs" type="Sys.EventArgs" mayBeNull="false">
		/// Event arguments for the shown event
		/// </param>
		/// <returns />
		
		var handler=this.get_events().getHandler('shown');
		if(handler){
			handler(this, eventArgs);
		}
	},	
	
	add_hiding:function(handler){
		/// <summary>
		/// Add an event handler for the hiding event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().addHandler('hiding', handler);
	},
	remove_hiding:function(handler){
		/// <summary>
		/// Remove an event handler from the hiding event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().removeHandler('hiding', handler);
	},
	raiseHiding:function(eventArgs){
		/// <summary>
		/// Raise the hiding event
		/// </summary>
		/// <param name="eventArgs" type="Sys.CancelEventArgs" mayBeNull="false">
		/// Event arguments for the hiding event
		/// </param>
		/// <returns />
		
		var handler=this.get_events().getHandler('hiding');
		if(handler){
			handler(this, eventArgs);
		}
	},
	
	add_hidden:function(handler){
		/// <summary>
		/// Add an event handler for the hidden event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().addHandler('hidden', handler);
	},
	remove_hidden:function(handler){
		/// <summary>
		/// Remove an event handler from the hidden event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().removeHandler('hidden', handler);
	},
	raiseHidden:function(eventArgs){
		/// <summary>
		/// Raise the hidden event
		/// </summary>
		/// <param name="eventArgs" type="Sys.EventArgs" mayBeNull="false">
		/// Event arguments for the hidden event
		/// </param>
		/// <returns />
		
		var handler=this.get_events().getHandler('hidden');
		if(handler){
			handler(this, eventArgs);
		}
	}
}
MySpace.UI.PopupBehavior.registerClass('MySpace.UI.PopupBehavior', Sys.UI.Behavior);


MySpace.UI.PositioningMode=function(){
	/// <summary>
	/// Positioning mode describing how the popup should be positioned
	/// relative to its specified parent
	/// </summary>
	/// <field name="Absolute" type="Number" integer="true" />
	/// <field name="Center" type="Number" integer="true" />
	/// <field name="BottomLeft" type="Number" integer="true" />
	/// <field name="BottomRight" type="Number" integer="true" />
	/// <field name="TopLeft" type="Number" integer="true" />
	/// <field name="TopRight" type="Number" integer="true" />
	/// <field name="Right" type="Number" integer="true" />
	/// <field name="Left" type="Number" integer="true" />
	throw Error.invalidOperation();
}
MySpace.UI.PositioningMode.prototype={
	Absolute: 0,
	Center: 1,
	BottomLeft: 2,
	BottomRight: 3,
	TopLeft: 4,
	TopRight: 5,
	Right: 6,
	Left: 7
}
MySpace.UI.PositioningMode.registerEnum('MySpace.UI.PositioningMode');




//
// AutoComplete
//

MySpace.UI.AutoCompleteBehavior=function(element){
	/// <summary>
	/// This behavior can be attached to a textbox to enable auto-complete/auto-suggest scenarios.
	/// </summary>
	/// <param name="element" type="Sys.UI.DomElement" DomElement="true" mayBeNull="false">
	/// DOM Element the behavior is associated with
	/// </param>
	/// <returns />
	MySpace.UI.AutoCompleteBehavior.initializeBase(this, [element]);
	
	// Path to the web service, or null if a page method
	this._servicePath=null;
	
	// Name of the web method
	this._serviceMethod=null;
	
	// User/page specific context provided to the web method
	this._contextKey=null;
	
	// Whether or not the the user/page specific context should be used
	this._useContextKey=false;
	this._minimumPrefixLength=3;
	this._completionItems=null;
	this._completionInterval=1000;
	this._completionListWrapperID=null;	
	this._completionListElementID=null;
	this._completionListAlwaysVisible=false;
	this._currentPrefix=null;
	this._selectIndex=-1;
	this._enableCaching=true;
	this._flyoutHasFocus=false;
	this._textBoxHasFocus=false;
	this._completionListCssClass=null;
	this._completionListItemCssClass=null;
	this._completionListFixedHeight=null;
	this._completionListMaxHeight=200;
	this._completionListWidth=null;
	this._lazyLoadPlaceholderHeight=null;
	this._groupHeaderCssClass=null;
	this._highlightedItemCssClass=null;
	this._delimiterCharacters=null;
	this._firstRowSelected=false;
	this._showOnlyCurrentWordInCompletionListItem=false;
	this._webRequest=null;  
};

MySpace.UI.AutoCompleteBehavior.prototype={
	initialize: function(){
		/// <summary>
		/// Initializes the autocomplete behavior.
		/// </summary>
		/// <returns />
		MySpace.UI.AutoCompleteBehavior.callBaseMethod(this, 'initialize');
		
		this._popupBehaviorHiddenHandler=Function.createDelegate(this, this._popupHidden);
		this._tickHandler=Function.createDelegate(this, this._onTimerTick);
		this._focusHandler=Function.createDelegate(this, this._onGotFocus);
		this._blurHandler=Function.createDelegate(this, this._onLostFocus);
		this._keyDownHandler=Function.createDelegate(this, this._onKeyDown);
		this._mouseDownHandler=Function.createDelegate(this, this._onListMouseDown);
		this._mouseUpHandler=Function.createDelegate(this, this._onListMouseUp);
		this._mouseOverHandler=Function.createDelegate(this, this._onListMouseOver);
		this._completionListBlurHandler=Function.createDelegate(this, this._onCompletionListBlur);
		this._completionListScrollHandler=Function.createDelegate(this, this._drawMissingItems);
		this._bodyClickHandler=Function.createDelegate(this, this._onBodyClick);
		
		this._timer=new MySpace.Timer();
		this._timer.set_interval(this._completionInterval);
		this._timer.add_tick(this._tickHandler);
		
		var element=this.get_element();
		this.initializeTextBox(element);
		
		if(this._completionListElementID !== null){
			this._completionListElement=$get(this._completionListElementID);
		}
		if(this._completionListElement == null){
			this._completionListElement=document.createElement('div');
			this._completionListElement.id=this.get_id() + '_completionListElem';
			element.parentNode.insertBefore(this._completionListElement, element.nextSibling);
		}
		if(this._completionListWrapperID){
			this._completionListWrapper=$get(this._completionListWrapperID);
		}
		else{
			this._completionListWrapper=this._completionListElement;
		}
		this.initializeCompletionList();
		
		if(this._completionListAlwaysVisible){
			// List starts out visible, so we need to show data right away
			this._onTimerTick();
		}
		else{
			this._popupBehavior=$create(MySpace.UI.PopupBehavior, 
					{ 'id':this.get_id()+'PopupBehavior', 'parentElement':element, "positioningMode": MySpace.UI.PositioningMode.BottomLeft }, null, null, this._completionListWrapper);
			this._popupBehavior.add_hidden(this._popupBehaviorHiddenHandler);
		
			// Create the animations (if they were set before initialize was called)
			if(this._onShow){
				this._popupBehavior.set_onShow(this._onShow);
			}
			if(this._onHide){
				this._popupBehavior.set_onHide(this._onHide);
			}
		}
	},
	
	dispose: function(){
		/// <summary>
		/// Disposes the autocomplete behavior
		/// </summary>
		/// <returns />
	   
		if(this._popupBehavior){
			if(this._popupBehaviorHiddenHandler){
				this._popupBehavior.remove_hidden(this._popupBehaviorHiddenHandler);
			}
			this._popupBehavior.dispose();
			this._popupBehavior=null;
		}
		if(this._timer){		
			this._timer.dispose();
			this._timer=null;
		}

		var element=this.get_element();
		if(element){
			$removeHandler(element, "focus", this._focusHandler);
			$removeHandler(element, "blur", this._blurHandler);
			$removeHandler(element, "keydown", this._keyDownHandler);
			$removeHandler(this._completionListElement, 'blur', this._completionListBlurHandler);
			$removeHandler(this._completionListElement, 'scroll', this._completionListScrollHandler);
			$removeHandler(this._completionListElement, 'mousedown', this._mouseDownHandler);
			$removeHandler(this._completionListElement, 'mouseup', this._mouseUpHandler);
			$removeHandler(this._completionListElement, 'mouseover', this._mouseOverHandler);
		}
		if(this._bodyClickHandler){
			$removeHandler(document.body, 'click', this._bodyClickHandler);
			this._bodyClickHandler=null;
		}
		
		this._popupBehaviorHiddenHandler=null;
		this._tickHandler=null;
		this._focusHandler=null;
		this._blurHandler=null;
		this._keyDownHandler=null;
		this._completionListBlurHandler=null;
		this._mouseDownHandler=null;
		this._mouseUpHandler=null;
		this._mouseOverHandler=null;
		
		MySpace.UI.AutoCompleteBehavior.callBaseMethod(this, 'dispose');
	},
	
	initializeTextBox: function(element){
		/// <summary>
		/// Initializes the textbox
		/// </summary>
		/// <param name="element" type="Sys.UI.DomElement" DomElement="true" mayBeNull="false" />
		/// <returns />	
		element.autocomplete="off";
		element.setAttribute("autocomplete", "off");
		$addHandler(element, "focus", this._focusHandler);		
		$addHandler(element, "blur", this._blurHandler);
		$addHandler(element, "keydown", this._keyDownHandler);
	},
	
	initializeCompletionList: function(){
		/// <summary>
		/// Initializes the autocomplete list element
		/// </summary>
		/// <param name="element" type="Sys.UI.DomElement" DomElement="true" mayBeNull="false" />
		/// <returns />		
		
		var element=this._completionListElement;
		var wrapper=this._completionListWrapper;
		var completionListStyle=element.style;
		
		if(this._completionListCssClass){
			Sys.UI.DomElement.addCssClass(element, this._completionListCssClass);
		}
		else{
			completionListStyle.textAlign='left';
			completionListStyle.overflow='auto';
			completionListStyle.overflowX='hidden';
			completionListStyle.cursor='default';
			completionListStyle.padding='0px';
			completionListStyle.margin='0px! important';
			if(Sys.Browser.agent === Sys.Browser.Safari){
				completionListStyle.border='solid 1px gray';	
				completionListStyle.backgroundColor='white';
				completionListStyle.color='black';			
			}
			else{
				completionListStyle.border='solid 1px buttonshadow';			
				completionListStyle.backgroundColor='window';
				completionListStyle.color='windowtext';
			}
			if(!this._completionListAlwaysVisible){
				wrapper.style.visibility='hidden';
			}
		}
		if(this._completionListFixedHeight){
			completionListStyle.height=this._completionListFixedHeight+"px";
		}
		$addHandler(element, "mousedown", this._mouseDownHandler);
		$addHandler(element, "mouseup", this._mouseUpHandler);
		$addHandler(element, "mouseover", this._mouseOverHandler);
		$addHandler(element, "blur", this._completionListBlurHandler); 
		$addHandler(element, "scroll", this._completionListScrollHandler);  
		$addHandler(document.body, 'click', this._bodyClickHandler);
	},
	
	_currentCompletionWord: function(){
		var elementValue=this.get_value();
		var word=elementValue;
		
		if(this.get_isMultiWord()){
			var startIndex=this._getCurrentWordStartIndex();
			var endIndex=this._getCurrentWordEndIndex(startIndex);
			
			if(endIndex <= startIndex){
				word=elementValue.substring(startIndex);
			} else{
				word=elementValue.substring(startIndex, endIndex);
			}
		}
		
		return word;
	},
	
	_getCursorIndex: function(){
		return this.get_element().selectionStart;
	},
	
	_getCurrentWordStartIndex: function(){
		var elementText=this.get_value().substring(0,this._getCursorIndex());
		
		var index=0;
		var lastIndex=-1;
		
		for(var i=0; i < this._delimiterCharacters.length; ++i){
			var curIndex=elementText.lastIndexOf(this._delimiterCharacters.charAt(i));
			if(curIndex > lastIndex){
				lastIndex=curIndex;
			}
		}	
		
		index=lastIndex;
		if(index >= this._getCursorIndex()){
			index=0;
		}
		
		return index < 0 ? 0:index + 1;	
	},
	
	_getCurrentWordEndIndex: function(wordStartIndex){
		var elementValue=this.get_value();
		var elementText=elementValue.substring(wordStartIndex);
		var index=0;
		
		for(var i=0; i < this._delimiterCharacters.length; ++i){
			var curIndex=elementText.indexOf(this._delimiterCharacters.charAt(i));
			if(curIndex > 0 && (curIndex < index || index == 0)){
				index=curIndex;
			}
		}
			   
		return index <= 0 ? elementValue.length:index + wordStartIndex;
	},
	
	get_isMultiWord:function(){
		/// <value type="Boolean" mayBeNull="false">
		/// Whether the behavior is currently in multi-word mode
		/// </value>
		return (this._delimiterCharacters != null) && (this._delimiterCharacters != '');
	},
	
	_getTextWithInsertedWord: function(wordToInsert){
		var text=wordToInsert;
		var replaceIndex=0;
		var originalText=this.get_value();
		
		if(this.get_isMultiWord()){
			var startIndex=this._getCurrentWordStartIndex();
			var endIndex=this._getCurrentWordEndIndex(startIndex);
			var prefix='';
			var suffix='';
			
			if(startIndex > 0){
				prefix=originalText.substring(0, startIndex);
			}
			if(endIndex > startIndex){
				suffix=originalText.substring(endIndex);
			}
			
			text=prefix + wordToInsert + suffix;
		}
		
		return text;
	},
	
	_hideCompletionList: function(){
		/// <summary>
		/// Hides the autocomplete flyout list
		/// </summary>
		/// <returns />
		
		if(!(this._popupBehavior && this._popupBehavior.get_visible())){
			return;
		}
		
		var eventArgs=new Sys.CancelEventArgs();
		this.raiseHiding(eventArgs);
		if(eventArgs.get_cancel()){
			return;
		}

		// Actually hide the popup
		this.hidePopup();
	},
	
	showPopup:function(){
		/// <summary>
		/// Show the completion list popup
		/// </summary>
		/// <remarks>
		/// If you cancel the showing event, you should still call
		/// showPopup to ensure consistency of the internal state
		/// </remarks>
		if(this._popupBehavior){
			this._popupBehavior.show();
			this.raiseShown(Sys.EventArgs.Empty);
		}
	},
	
	hidePopup:function(){
		/// <summary>
		/// Hide the completion list popup
		/// </summary>
		/// <remarks>
		/// If you cancel the hiding event, you should still
		/// call hidePopup to ensure consistency of the internal
		/// state
		/// </remarks>

		if(this._popupBehavior){
			this._popupBehavior.hide();
		}
		else{
			this._popupHidden();
		}
	},
	
	_popupHidden:function(){
		/// <summary>
		/// Clean up the completion list popup after it has been hidden
		/// </summary>
	
		this._completionListElement.innerHTML='';
		this._selectIndex=-1;
		this._flyoutHasFocus=false;
		
		this.raiseHidden(Sys.EventArgs.Empty);
	},
	
	_highlightItem: function(item){
		/// <summary>
		/// Highlights the specified item
		/// </summary>
		/// <param name="item" type="Sys.UI.DomElement" DomElement="true" mayBeNull="false" />
		/// <returns />
		
		var children=this._completionListElement.childNodes;

		// Unselect any previously highlighted item
		for(var i=0; i < children.length; i++){
			var child=children[i];
			if(child._highlighted){
				child._highlighted=false;
				if(this._completionListItemCssClass){
					Sys.UI.DomElement.removeCssClass(child, this._highlightedItemCssClass);
					Sys.UI.DomElement.addCssClass(child, this._completionListItemCssClass);
				}
				else{
					if(Sys.Browser.agent === Sys.Browser.Safari){
						child.style.backgroundColor='white';
						child.style.color='black';
					}
					else{
						child.style.backgroundColor='window';
						child.style.color='windowtext';
					}
				}
				this.raiseItemOut(new MySpace.UI.AutoCompleteItemEventArgs(child, child.firstChild.nodeValue, child._value));
			}
		}
		
		// Highlight the new item
		if(this._highlightedItemCssClass){
			Sys.UI.DomElement.removeCssClass(item, this._completionListItemCssClass);
			Sys.UI.DomElement.addCssClass(item, this._highlightedItemCssClass);
		}
		else{
			if(Sys.Browser.agent === Sys.Browser.Safari){
				item.style.backgroundColor='lemonchiffon';
			}
			else{
				item.style.backgroundColor='highlight';
				item.style.color='highlighttext';
			}
			
		}
		item._highlighted=true;
		if(!item._isPlaceholder){
			this.raiseItemOver(new MySpace.UI.AutoCompleteItemEventArgs(item, item.firstChild.nodeValue, item._value));
		}
	},

	_onBodyClick:function(ev){
		var tgt=ev.target;
		while(tgt){
			if(tgt==this._completionListWrapper){
				return;
			}
			tgt=tgt.parentNode;
		}
		this._onCompletionListBlur(ev);
	},
	
	_onCompletionListBlur: function(ev){
		/// <summary>
		/// Handler for the blur event on the autocomplete flyout.
		/// </summary>
		/// <param name="ev" type="Sys.UI.DomEvent" DomElement="false" mayBeNull="false" />
		/// <returns />	
		this._hideCompletionList();
	},
	
	_getCompletionItem:function(node){
		/// <summary>
		/// Finds the list item that the node descends from, if any
		/// </summary>
		/// <returns />
		/// <param name="node" type="Sys.UI.DomElement" DomElement="true" mayBeNull="false" />
		while(node){
			if(node.parentNode==this._completionListElement && !node._isGroupHeader){
				return node;
			}
			node=node.parentNode;
		}
	},
	
	_onListMouseDown: function(ev){
		/// <summary>
		/// Handler for the mousedown event on the autocomplete flyout.
		/// </summary>
		/// <param name="ev" type="Sys.UI.DomEvent" DomElement="false" mayBeNull="false" />
		/// <returns />	
		var item=this._getCompletionItem(ev.target); 
		if(item){
			this._setText(item);
			this._flyoutHasFocus=false;
			ev.stopPropagation();
		}
		else{ // focus is still on the flyout and we do not want to hide it
			this._flyoutHasFocus=true;
		}
	},
	
	_onListMouseUp: function(ev){
		/// <summary>
		/// Handler for the mouseup event on the autocomplete flyout.
		/// </summary>
		/// <param name="ev" type="Sys.UI.DomEvent" DomElement="false" mayBeNull="false" />
		/// <returns />	
		if(!this._flyoutHasFocus){
			try{
				this.get_element().focus();
			}catch(e){} // IE throws if the input box has been hidden
		}
	},
	
	_onListMouseOver: function(ev){
		/// <summary>
		/// Handler for the mouseover event on the autocomplete flyout.
		/// </summary>
		/// <param name="ev" type="Sys.UI.DomEvent" DomElement="false" mayBeNull="false" />
		/// <returns />	  
		var item=ev.target;
		if(item !== this._completionListElement){
			item=this._getCompletionItem(item);
			if(item){
				this._highlightItem(item);
				this._selectIndex=Array.indexOf(item.parentNode.childNodes, item);
			}
		}
	},

	_onGotFocus: function(ev){
		/// <summary>
		/// Handler for textbox focus event.
		/// </summary>
		/// <param name="ev" type="Sys.UI.DomEvent" DomElement="false" mayBeNull="false" />
		/// <returns />	  
		this._textBoxHasFocus=true;
		if(this._flyoutHasFocus){
			// hide the flyout now that the focus is back on the textbox
			this._hideCompletionList();		  
		}
		if((this._minimumPrefixLength == 0) && (!this.get_value())){
			this._timer.set_enabled(true); 
			// only start the timer if the minimumprefixlength is 0
			// since we would like to retrieve results even if
			// the user has not entered any text and the textbox is empty.
		}
	},
	
	_onKeyDown: function(ev){
		/// <summary>
		/// Handler for the textbox keydown event.
		/// </summary>
		/// <param name="ev" type="Sys.UI.DomEvent" DomElement="false" mayBeNull="false" />
		/// <returns />	  
		this._timer.set_enabled(false); 
		// the last key press occured so we need to "reset" the timer.
		var k=ev.keyCode ? ev.keyCode:ev.rawEvent.keyCode;
		if(k === Sys.UI.Key.esc){
			this._hideCompletionList();
			ev.preventDefault();
			ev.stopPropagation();
		}
		else if(k === Sys.UI.Key.up){
			var newIndex=this._getAdjacentItemIndex(this._selectIndex, -1);
			if(newIndex >= 0){
				this._selectIndex=newIndex;
				this._handleScroll(this._completionListElement.childNodes[newIndex], newIndex);
				this._highlightItem(this._completionListElement.childNodes[newIndex]);
				ev.stopPropagation();	 
				ev.preventDefault();
			}
		}
		else if(k === Sys.UI.Key.down){
			var newIndex=this._getAdjacentItemIndex(this._selectIndex, 1);	
			if(newIndex < this._completionListElement.childNodes.length){
				this._selectIndex=newIndex;
				this._handleScroll(this._completionListElement.childNodes[newIndex], newIndex);
				this._highlightItem(this._completionListElement.childNodes[newIndex]);			  
				ev.stopPropagation();				
				ev.preventDefault();
			}
		}
		else if(k === Sys.UI.Key.enter){
			if(this._selectIndex !== -1){
				this._setText(this._completionListElement.childNodes[this._selectIndex]);
				ev.preventDefault();
				ev.stopPropagation();
			} else{
				// close the popup
				this.hidePopup();
			}
		}
		else if(k === Sys.UI.Key.tab){
			if(this._selectIndex !== -1){
				this._setText(this._completionListElement.childNodes[this._selectIndex]);
			}
		}
		else{
			this._timer.set_enabled(true);
			// start the timer to retrieve results since now it is an actual key
		}
	},
	
	_getAdjacentItemIndex:function(index, offset){
		var childNodes=this._completionListElement.childNodes;
		
		do{
			index+=offset;
		}while(index>=0 && index<childNodes.length && childNodes[index]._isGroupHeader);
		
		return index;
	},
	
	_handleScroll:function(element, index){
		/// <summary>
		/// Method to determine if an item is in view or not
		/// </summary>
		/// <returns />
		/// <param name="element" type="Sys.UI.DomElement" DomElement="true" mayBeNull="false" />
		/// <param name="index" type="Number" DomElement="false" mayBeNull="true" />		
		var flyout=this._completionListElement,
			elemHeight=element.offsetHeight || 0,
			isAbsolute=element.offsetParent==flyout,
			offsetStart=isAbsolute ? 0 : flyout.offsetTop;
		
		var scrollDown=element.offsetTop-offsetStart+elemHeight-flyout.scrollTop-flyout.offsetHeight;
		if(scrollDown>0){ flyout.scrollTop += scrollDown; }
		
		var scrollUp=flyout.scrollTop-element.offsetTop+offsetStart;
		if(scrollUp>0){ flyout.scrollTop -= scrollUp; }
	},
	
	_handleFlyoutFocus:function(){
		/// <summary>
		/// Method to handle flyout focus if textbox loses focus.
		/// </summary>
		/// <returns />   
		if(!this._textBoxHasFocus){ 
			if(!this._flyoutHasFocus){
				if(this._webRequest){
					// abort the web service call if we are losing focus. no sense having it delay future web requests.
					this._webRequest.get_executor().abort();
					this._webRequest=null;
				}
				// the textbox lost focus and the flyout does not have it
				this._hideCompletionList();
			} else{
				// keep the flyout around otherwise
			}
		}
	},	 
	
	_onLostFocus: function(){
		/// <summary>
		/// Handler textbox blur event.
		/// </summary>
		/// <returns />	 
		this._textBoxHasFocus=false;   
		this._timer.set_enabled(false);
		/* the rest of the onblur handling will be done in
		this method after a minor delay to ensure we do not close the flyout 
		if a user clicks on its scroll bars for example */  
		window.setTimeout(Function.createDelegate(this, this._handleFlyoutFocus), 500);
	},  
	
	_onMethodComplete: function(result, context){
		/// <summary>
		/// Handler invoked when the webservice call is completed.
		/// </summary>
		/// <param name="result" type="Object" DomElement="false" mayBeNull="true" />
		/// <param name="context" type="String" DomElement="false" mayBeNull="true" />		
		/// <returns /> 
		this._webRequest=null; // clear out our saved WebRequest object	
		this._update(context, result, /* cacheResults */ true);
	},
	
	_onMethodFailed: function(err, response, context){
		/// <summary>
		/// Handler invoked when the webservice call fails, currently a noop
		/// </summary>
		/// <param name="err" type="Object" DomElement="false" mayBeNull="true" />		
		/// <param name="result" type="Object" DomElement="false" mayBeNull="true" />
		/// <param name="context" type="String" DomElement="false" mayBeNull="true" />
		/// <returns />	 
		// clear out our saved WebRequest object
		this._webRequest=null; 
	},
	
	_onTimerTick: function(sender, eventArgs){
		/// <summary>
		/// Handler invoked when a timer tick occurs
		/// </summary>
		/// <param name="sender" type="Object" mayBeNull="true"/>
		/// <param name="eventArgs" type="Sys.EventArgs" mayBeNull="true" />		
		/// <returns />
		
		// turn off the timer until another key is pressed.
		this._timer.set_enabled(false);
		
		var text=this._currentCompletionWord();
		
		if(text.trim().length < this._minimumPrefixLength){
			this._currentPrefix=null;
			this._update('', null, /* cacheResults */ false);
			return;
		}
		
		var isShowing=(!this._popupBehavior || this._popupBehavior.get_visible());
		// there is new content in the textbox or the textbox is empty but the min prefix length is 0
	   if((this._currentPrefix !== text || !isShowing) || ((text == "") && (this._minimumPrefixLength == 0))){
			this._currentPrefix=text;
			if((text != "") && this._cache && this._cache[text]){
				this._update(text, this._cache[text], /* cacheResults */ false);
				return;
			}
			// Raise the populating event and optionally cancel the web service invocation
			var eventArgs=new Sys.CancelEventArgs();
			this.raisePopulating(eventArgs);
			if(eventArgs.get_cancel()){
				return;
			}
			
			this._fetchCompletionItems(text);
		}
	},
	
	_fetchCompletionItems:function(prefixText){
		if(this._servicePath && this._serviceMethod){
			// Create the service parameters and optionally add the context parameter
			// (thereby determining which method signature we're expecting...)
			var params={ prefixText:this._currentPrefix };
			if(this._useContextKey){
				params.contextKey=this._contextKey;
			}
			
			if(this._webRequest){
				// abort the previous web service call if we 
				// are issuing a new one and the previous one is 
				// active.
				this._webRequest.get_executor().abort();
				this._webRequest=null;
			}
			// Invoke the web service
			this._webRequest=Sys.Net.WebServiceProxy.invoke(this.get_servicePath(), this.get_serviceMethod(), false, params,
										Function.createDelegate(this, this._onMethodComplete),
										Function.createDelegate(this, this._onMethodFailed),
										prefixText);
		}
		else{
			var matches=this.getCompletionItems(prefixText);
			if(matches){
				this._update(prefixText, matches);
			}
		}
	},
	
	getCompletionItems:function(prefixText){
		prefixText=prefixText.toLowerCase();
		var matches=[];
		
		for(var i=0;i<this._completionItems.length;i++){
			var item=this._completionItems[i];
			if((item.text || item).toLowerCase().startsWith(prefixText)){
				matches.push(this._completionItems[i]);
			}
		}
	
		return matches;
	},
	
	_setText: function(item){
		/// <summary>
		/// Method to set the selected autocomplete option on the textbox
		/// </summary>
		/// <param name="item" type="Sys.UI.DomElement" DomElement="true" mayBeNull="true">
		/// Item to select
		/// </param>
		/// <returns />
		
		var text=null;
		if(item){
			text=item._text || (item.firstChild ? item.firstChild.nodeValue : null);
		}
		this._timer.set_enabled(false);

		var newText=this._showOnlyCurrentWordInCompletionListItem ? this._getTextWithInsertedWord(text):text;
		this.set_value(newText, true);

		this.raiseItemSelected(new MySpace.UI.AutoCompleteItemEventArgs(item, text, item ? item._value:null));

		this._currentPrefix=this._currentCompletionWord();
		this._hideCompletionList();
	},
	
	_update: function(prefixText, completionItems, cacheResults){
		/// <summary>
		/// Method to update the status of the autocomplete behavior
		/// </summary>
		/// <param name="prefixText" type="String" DomElement="false" mayBeNull="true" />
		/// <param name="completionItems" type="Object" DomElement="false" mayBeNull="true" />
		/// <param name="cacheResults" type="Object" DomElement="false" mayBeNull="true" />
		/// <returns />	   
		if(cacheResults && this.get_enableCaching()){
			if(!this._cache){
				this._cache={};
			}
			this._cache[prefixText]=completionItems;
		}
		
		this._currentCompletionItems=completionItems;
		
		// If the target control loses focus or 
		// if the value in textbox has changed before the webservice returned
		// completion items we don't need to show popup 
		if((!this._completionListAlwaysVisible && !this._textBoxHasFocus) || (prefixText != this._currentCompletionWord())){
			this._hideCompletionList();
			return;
		}  
		
		if(this._completionListAlwaysVisible || (completionItems && completionItems.length)){
			this._completionListElement.innerHTML='';
			this._selectIndex=-1;
			var _firstChild=null, text=null, value=null, itemElement=null, placeholderHeight=this._lazyLoadPlaceholderHeight;
			
			for(var i=0; i < completionItems.length; i++){
				if(completionItems[i] && completionItems[i].groupHeader){
					itemElement=this.createGroupHeader(completionItems[i]);
				}
				else if(placeholderHeight){
					itemElement=document.createElement("div");
					itemElement.style.height=placeholderHeight+"px";
					itemElement._isPlaceholder=true;
				}
				else{
					itemElement=this.createCompletionItem(completionItems[i]);
					
					// set the first child if it is null
					if(_firstChild == null){
						_firstChild=itemElement;
					}
				}

				this._completionListElement.appendChild(itemElement);
			}
			var elementBounds=Sys.UI.DomElement.getBounds(this.get_element());		
			this._completionListElement.style.width=(this.get_completionListWidth() || Math.max(1, elementBounds.width - 2)) + 'px';
			
			this.raisePopulated(Sys.EventArgs.Empty);
			
			var eventArgs=new Sys.CancelEventArgs();
			this.raiseShowing(eventArgs);
			if(!eventArgs.get_cancel()){
				if(!this._completionListFixedHeight){
					this._completionListElement.style.height="1px";
				}
				this.showPopup();
				
				if(!this._completionListFixedHeight){
					// Cap its size at the max height
					this._completionListElement.style.height="";
					if(this._completionListElement.offsetHeight > this._completionListMaxHeight){
						this._completionListElement.style.height=this._completionListMaxHeight+"px";
					}
				}
				this._completionListElement.scrollTop=0;
				
				// Check if the first Row is to be selected by default and if yes highlight it and updated selectIndex.
				if(this._firstRowSelected && (_firstChild != null)){
					this._highlightItem( _firstChild );
					this._selectIndex=0;
				}
				
				this._drawMissingItems();
			}			
		} else{
			this._hideCompletionList();
		}
	},
	
	_drawMissingItems:function(){
		var list=this._completionListElement,
			isAbsolute=list.childNodes[0] && (list.childNodes[0].offsetParent==list),
			offsetStart=isAbsolute ? 0 : list.offsetTop,
			yStart=offsetStart+list.scrollTop-4*this._lazyLoadPlaceholderHeight,
			yEnd=yStart+list.offsetHeight+8*this._lazyLoadPlaceholderHeight,
			childNodesLength=list.childNodes.length,
			el=null;
			
		for(var i=0;i<childNodesLength;i++){			
			el=list.childNodes[i];
			
			if(el.offsetTop < yStart){ continue; }
			if(el.offsetTop > yEnd){ break; }
			
			if(el._isPlaceholder){
				var newEl=this.createCompletionItem(this._currentCompletionItems[i]);
				list.replaceChild(newEl, el);
				
				if(this._selectIndex==-1 && this._firstRowSelected){
					this._highlightItem(newEl);
					this._selectIndex=i;
				}
			}
		}
	},
	
	createCompletionItem:function(item){
		// Create the item				
		var itemElement=document.createElement('div');
		var text, value;
		
		// Get the text/value for the item
		if(item && item.text){
			// Use the text and value pair returned from the web service
			text=item.text;
			value=item.value;
		} else{
			// If the web service only returned a regular string, use it for
			// both the text and the value
			text=item;
			value=item; 
		} 

		// Set the text/value for the item
		// ShowOnlyCurrentWordInCompletionListItem support
		var optionText=this._showOnlyCurrentWordInCompletionListItem ? text: this._getTextWithInsertedWord(text);
		itemElement.appendChild(document.createTextNode(optionText));
		itemElement._value=value;
		
		if(this._completionListItemCssClass){
			Sys.UI.DomElement.addCssClass(itemElement, this._completionListItemCssClass);
		}
		else{
			var itemElementStyle=itemElement.style;
			itemElementStyle.padding='0px';
			itemElementStyle.textAlign='left';
			itemElementStyle.textOverflow='ellipsis';
			itemElementStyle.cursor='pointer';
			// workaround for safari since normal colors do not
			// show well there.
			if(Sys.Browser.agent === Sys.Browser.Safari){
				itemElementStyle.backgroundColor='white';
				itemElementStyle.color='black';
			} else{
				itemElementStyle.backgroundColor='window';
				itemElementStyle.color='windowtext';
			}
		}	
		
		return itemElement;
	},
	
	createGroupHeader:function(item){
		var itemElement=document.createElement("div");
		itemElement.appendChild(document.createTextNode(item.groupHeader));
		itemElement._isGroupHeader=true;
		
		if(this._groupHeaderCssClass){
			Sys.UI.DomElement.addCssClass(itemElement, this._groupHeaderCssClass);
		}
		else{
			var itemElementStyle=itemElement.style;
			itemElementStyle.fontWeight='bold';
			itemElementStyle.fontStyle='italic';
		}
		
		return itemElement;
	},
	
	get_value:function(){
		var el=this.get_element();
		var b=Sys.UI.Behavior.getBehaviorByName(el, "DefaultTextboxBehavior");
		return b ? b.get_value() : el.value;
	},
	set_value:function(val, noUpdate){
		var el=this.get_element();
		var b=Sys.UI.Behavior.getBehaviorByName(el, "DefaultTextboxBehavior");
		if(b){
			b.set_value(val);
		}
		else{
			el.value=val || "";
		}
		if(!noUpdate){
			this._onTimerTick();	// Force an update of the completion list		
		}
	},
	
	get_onShow:function(){
		/// <value type="String" mayBeNull="true">
		/// Generic OnShow Animation's JSON definition
		/// </value>
		return this._popupBehavior ? this._popupBehavior.get_onShow():this._onShow;
	},
	set_onShow:function(value){
		if(this._popupBehavior){
			this._popupBehavior.set_onShow(value)
		} else{
			this._onShow=value;
		}
	},
	onShow:function(){
		/// <summary>
		/// Play the OnShow animation
		/// </summary>
		/// <returns />
		if(this._popupBehavior){
			this._popupBehavior.onShow();
		}
	},
		
	get_onHide:function(){
		/// <value type="String" mayBeNull="true">
		/// Generic OnHide Animation's JSON definition
		/// </value>
		return this._popupBehavior ? this._popupBehavior.get_onHide():this._onHide;
	},
	set_onHide:function(value){
		if(this._popupBehavior){
			this._popupBehavior.set_onHide(value)
		} else{
			this._onHide=value;
		}
	},
	onHide:function(){
		/// <summary>
		/// Play the OnHide animation
		/// </summary>
		/// <returns />
		if(this._popupBehavior){
			this._popupBehavior.onHide();
		}
	},
	
	get_visible:function(){
		return this._popupBehavior && this._popupBehavior.get_visible(); 
	},
	
	get_completionItems:function(){
		return this._completionItems;
	},
	set_completionItems:function(value){
		this._completionItems=value;
	},
	
	get_completionInterval: function(){
		/// <value type="Number" integer="true" maybeNull="true">
		/// Auto completion timer interval in milliseconds.
		/// </value>
		return this._completionInterval;
	},
	set_completionInterval: function(value){
		this._completionInterval=value;
	},
	
	get_completionList: function(){
		/// <value type="Sys.UI.DomElement" domElement="true" maybeNull="true">
		/// List dom element.
		/// </value>
		return this._completionListElement;
	},
	set_completionList: function(value){
		this._completionListElement=value;
	},
	
	get_minimumPrefixLength: function(){
		/// <value type="Number" integer="true" maybeNull="true">
		/// Minimum text prefix length required to call the webservice.
		/// </value>
		return this._minimumPrefixLength;
	},
	set_minimumPrefixLength: function(value){
		this._minimumPrefixLength=value;
	},
	
	get_serviceMethod: function(){
		/// <value type="String" maybeNull="false">
		/// Web service method.
		/// </value>
		return this._serviceMethod;
	},
	set_serviceMethod: function(value){
		this._serviceMethod=value;
	},
	
	get_servicePath: function(){
		/// <value type="String" maybeNull="true">
		/// Web service url.
		/// </value>
		return this._servicePath;
	},
	set_servicePath: function(value){
		this._servicePath=value;
	},
	
	get_contextKey:function(){
		/// <value type="String" mayBeNull="true">
		/// User/page specific context provided to an optional overload of the
		/// web method described by ServiceMethod/ServicePath.  If the context
		/// key is used, it should have the same signature with an additional
		/// parameter named contextKey of type string.
		/// </value>
		return this._contextKey;
	},
	set_contextKey:function(value){
		this._contextKey=value;
		this.set_useContextKey(true);
	},
	
	get_useContextKey:function(){
		/// <value type="Boolean">
		/// Whether or not the ContextKey property should be used.  This will be
		/// automatically enabled if the ContextKey property is ever set
		/// (on either the client or the server).  If the context key is used,
		/// it should have the same signature with an additional parameter
		/// named contextKey of type string.
		/// </value>
		return this._useContextKey;
	},
	set_useContextKey:function(value){
		this._useContextKey=value;
	},
	
	get_enableCaching: function(){
		/// <value type="Boolean" maybeNull="true">
		/// Get or sets whether suggestions retrieved from the webservice
		/// should be cached.
		/// </value>
		return this._enableCaching;
	},
	set_enableCaching: function(value){
		this._enableCaching=value;
	},
	
	get_completionListWrapperID:function(){
		return this._completionListWrapperID;
	},
	set_completionListWrapperID:function(value){
		this._completionListWrapperID=value;
	},
	
	get_completionListElementID: function(){
		/// <value type="String" maybeNull="true">
		/// ID of the completion div element.
		/// </value>
		return this._completionListElementID;
	},
	set_completionListElementID: function(value){
		this._completionListElementID=value;
	},  
	
	get_completionListAlwaysVisible:function(){
		return this._completionListAlwaysVisible;
	},
	set_completionListAlwaysVisible:function(value){
		this._completionListAlwaysVisible=value;
	},
	
	get_completionListCssClass:function(){
		/// <value type="String" maybeNull="true">
		/// Css class name that will be used to style the completion list element.
		/// </value>
		return this._completionListCssClass;
	},
	set_completionListCssClass:function(value){
		this._completionListCssClass=value;	
	},   
	
	get_completionListItemCssClass:function(){
		/// <value type="String" maybeNull="true">
		/// Css class name that will be used to style an item in the completion list.
		/// </value>
		return this._completionListItemCssClass;
	},
	set_completionListItemCssClass:function(value){
		this._completionListItemCssClass=value;	
	},
	
	get_completionListFixedHeight:function(){
		/// <value type="Number" maybeNull="true">
		/// Height in pixels of the completion list.  If not specified, the list will grow or
		/// shrink to fit the displayed items (subject to completionListMaxHeight).
		/// </value>
		return this._completionListFixedHeight;
	},
	set_completionListFixedHeight:function(value){
		this._completionListFixedHeight=value;
	},
	
	get_completionListMaxHeight:function(){
		/// <value type="Number" maybeNull="true">
		/// Maximum height in pixels of the completion list.  Has no effect if
		/// a completionListFixedHeight is specified. Default is 200.
		/// </value>
		return this._completionListMaxHeight;
	},
	set_completionListMaxHeight:function(value){
		this._completionListMaxHeight=value;
	},
	
	get_completionListWidth:function(){
		return this._completionListWidth;
	},
	set_completionListWidth:function(value){
		this._completionListWidth=value;
	},

	get_lazyLoadPlaceholderHeight:function(){
		return this._lazyLoadPlaceholderHeight;
	},
	set_lazyLoadPlaceholderHeight:function(value){
		this._lazyLoadPlaceholderHeight=value;
	},
	
	get_groupHeaderCssClass:function(){
		return this._groupHeaderCssClass;
	},
	set_groupHeaderCssClass:function(value){
		this._groupHeaderCssClass=value;
	},
	
	get_highlightedItemCssClass:function(){
		/// <value type="String" maybeNull="true">
		/// Css class name that will be used to style a highlighted item in the list.
		/// </value>
		return this._highlightedItemCssClass;
	},
	set_highlightedItemCssClass:function(value){
		this._highlightedItemCssClass=value;
	},
	
	get_delimiterCharacters: function(){
		/// <value type="String">
		/// Gets or sets the character(s) used to seperate words for autocomplete.
		/// </value>
		return this._delimiterCharacters;
	},
	set_delimiterCharacters: function(value){
		this._delimiterCharacters=value;
	},
	
	get_firstRowSelected:function(){
		/// <value type="Boolean" maybeNull="true">
		/// Flag to determine if the first option in the flyout is selected or not. 
		/// </value>
		return this._firstRowSelected;
	},
	set_firstRowSelected:function(value){
		this._firstRowSelected=value;
	},
	
	get_showOnlyCurrentWordInCompletionListItem:function(){
		/// <value type="Boolean">
		/// If Delimiter characters are specified and showOnlyCurrentWordInCompletionListItem is 
		/// set to true, then the completion list displays suggestions just for the current word, 
		/// otherwise, it displays the whole string that will show up in the TextBox if that
		/// item is selected, which is the current default.
		/// </value>
		return this._showOnlyCurrentWordInCompletionListItem;
	},
	set_showOnlyCurrentWordInCompletionListItem:function(value){
		this._showOnlyCurrentWordInCompletionListItem=value;
	},

	add_populating:function(handler){
		/// <summary>
		/// Add an event handler for the populating event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().addHandler('populating', handler);
	},
	remove_populating:function(handler){
		/// <summary>
		/// Remove an event handler from the populating event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().removeHandler('populating', handler);
	},
	raisePopulating:function(eventArgs){
		/// <summary>
		/// Raise the populating event
		/// </summary>
		/// <param name="eventArgs" type="Sys.CancelEventArgs" mayBeNull="false">
		/// Event arguments for the populating event
		/// </param>
		/// <returns />
		/// <remarks>
		/// The populating event can be used to provide custom data to AutoComplete
		/// instead of using a web service.  Just cancel the event (using the
		/// CancelEventArgs) and pass your own data to the _update method.
		/// </remarks>
		
		var handler=this.get_events().getHandler('populating');
		if(handler){
			handler(this, eventArgs);
		}
	},
	
	add_populated:function(handler){
		/// <summary>
		/// Add an event handler for the populated event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().addHandler('populated', handler);
	},
	remove_populated:function(handler){
		/// <summary>
		/// Remove an event handler from the populated event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().removeHandler('populated', handler);
	},
	raisePopulated:function(eventArgs){
		/// <summary>
		/// Raise the populated event
		/// </summary>
		/// <param name="eventArgs" type="Sys.EventArgs" mayBeNull="false">
		/// Event arguments for the populated event
		/// </param>
		/// <returns />
		
		var handler=this.get_events().getHandler('populated');
		if(handler){
			handler(this, eventArgs);
		}
	},
	
	add_showing:function(handler){
		/// <summary>
		/// Add an event handler for the showing event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().addHandler('showing', handler);
	},
	remove_showing:function(handler){
		/// <summary>
		/// Remove an event handler from the showing event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().removeHandler('showing', handler);
	},
	raiseShowing:function(eventArgs){
		/// <summary>
		/// Raise the showing event
		/// </summary>
		/// <param name="eventArgs" type="Sys.CancelEventArgs" mayBeNull="false">
		/// Event arguments for the showing event
		/// </param>
		/// <returns />
		
		var handler=this.get_events().getHandler('showing');
		if(handler){
			handler(this, eventArgs);
		}
	},
	
	add_shown:function(handler){
		/// <summary>
		/// Add an event handler for the shown event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().addHandler('shown', handler);
	},
	remove_shown:function(handler){
		/// <summary>
		/// Remove an event handler from the shown event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().removeHandler('shown', handler);
	},
	raiseShown:function(eventArgs){
		/// <summary>
		/// Raise the shown event
		/// </summary>
		/// <param name="eventArgs" type="Sys.EventArgs" mayBeNull="false">
		/// Event arguments for the shown event
		/// </param>
		/// <returns />
		
		var handler=this.get_events().getHandler('shown');
		if(handler){
			handler(this, eventArgs);
		}
	},
	
	add_hiding:function(handler){
		/// <summary>
		/// Add an event handler for the hiding event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().addHandler('hiding', handler);
	},
	remove_hiding:function(handler){
		/// <summary>
		/// Remove an event handler from the hiding event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().removeHandler('hiding', handler);
	},
	raiseHiding:function(eventArgs){
		/// <summary>
		/// Raise the hiding event
		/// </summary>
		/// <param name="eventArgs" type="Sys.CancelEventArgs" mayBeNull="false">
		/// Event arguments for the hiding event
		/// </param>
		/// <returns />
		
		var handler=this.get_events().getHandler('hiding');
		if(handler){
			handler(this, eventArgs);
		}
	},
	
	add_hidden:function(handler){
		/// <summary>
		/// Add an event handler for the hidden event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().addHandler('hidden', handler);
	},
	remove_hidden:function(handler){
		/// <summary>
		/// Remove an event handler from the hidden event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().removeHandler('hidden', handler);
	},
	raiseHidden:function(eventArgs){
		/// <summary>
		/// Raise the hidden event
		/// </summary>
		/// <param name="eventArgs" type="Sys.EventArgs" mayBeNull="false">
		/// Event arguments for the hidden event
		/// </param>
		/// <returns />
		
		var handler=this.get_events().getHandler('hidden');
		if(handler){
			handler(this, eventArgs);
		}
	},
	
	add_itemSelected:function(handler){
		/// <summary>
		/// Add an event handler for the itemSelected event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().addHandler('itemSelected', handler);
	},
	remove_itemSelected:function(handler){
		/// <summary>
		/// Remove an event handler from the itemSelected event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().removeHandler('itemSelected', handler);
	},
	raiseItemSelected:function(eventArgs){
		/// <summary>
		/// Raise the itemSelected event
		/// </summary>
		/// <param name="eventArgs" type="MySpace.UI.AutoCompleteItemEventArgs" mayBeNull="false">
		/// Event arguments for the itemSelected event
		/// </param>
		/// <returns />
		
		var handler=this.get_events().getHandler('itemSelected');
		if(handler){
			handler(this, eventArgs);
		}
	},
	
	add_itemOver:function(handler){
		/// <summary>
		/// Add an event handler for the itemOver event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().addHandler('itemOver', handler);
	},
	remove_itemOver:function(handler){
		/// <summary>
		/// Remove an event handler from the itemOver event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().removeHandler('itemOver', handler);
	},
	raiseItemOver:function(eventArgs){
		/// <summary>
		/// Raise the itemOver event
		/// </summary>
		/// <param name="eventArgs" type="MySpace.UI.AutoCompleteItemEventArgs" mayBeNull="false">
		/// Event arguments for the itemOver event
		/// </param>
		/// <returns />
		
		var handler=this.get_events().getHandler('itemOver');
		if(handler){
			handler(this, eventArgs);
		}
	},
	
	add_itemOut:function(handler){
		/// <summary>
		/// Add an event handler for the itemOut event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().addHandler('itemOut', handler);
	},
	remove_itemOut:function(handler){
		/// <summary>
		/// Remove an event handler from the itemOut event
		/// </summary>
		/// <param name="handler" type="Function" mayBeNull="false">
		/// Event handler
		/// </param>
		/// <returns />
		this.get_events().removeHandler('itemOut', handler);
	},
	raiseItemOut:function(eventArgs){
		/// <summary>
		/// Raise the itemOut event
		/// </summary>
		/// <param name="eventArgs" type="MySpace.UI.AutoCompleteItemEventArgs" mayBeNull="false">
		/// Event arguments for the itemOut event
		/// </param>
		/// <returns />
		
		var handler=this.get_events().getHandler('itemOut');
		if(handler){
			handler(this, eventArgs);
		}
	}
}
MySpace.UI.AutoCompleteBehavior.registerClass('MySpace.UI.AutoCompleteBehavior', Sys.UI.Behavior);


MySpace.UI.AutoCompleteItemEventArgs=function(item, text, value){
	/// <summary>
	/// Event arguments used when the itemSelected event is raised
	/// </summary>
	/// <param name="item" type="Sys.UI.DomElement" DomElement="true" mayBeNull="true">
	/// Item
	/// </param>
	/// <param name="text" type="String" mayBeNull="true">
	/// Text of the item
	/// </param>
	/// <param name="value" type="String" mayBeNull="true" optional="true">
	/// Value of the item different from text if specifically returned by the webservice
	/// as autocomplete json text/value item(using AutoComplete.CreateAutoCompleteItem); otherwise same as text.
	/// </param>
	MySpace.UI.AutoCompleteItemEventArgs.initializeBase(this);
	
	this._item=item;
	this._text=text;
	this._value=(value !== undefined) ? value:null;
}
MySpace.UI.AutoCompleteItemEventArgs.prototype={
	get_item:function(){
		/// <value type="Sys.UI.DomElement" DomElement="true" mayBeNull="true">
		/// Item
		/// </value>
		return this._item;
	},
	set_item:function(value){
		this._item=value;
	},
	
	get_text:function(){
		/// <value type="String" maybeNull="true">
		/// Text of the item
		/// </value>
		return this._text;
	},
	set_text:function(value){
		this._text=value;
	},
	
	get_value:function(){
		/// <value type="String" maybeNull="true">
		/// Value of the item different from text if specifically returned by the webservice
		/// as autocomplete json text/value item(using AutoComplete.CreateAutoCompleteItem); otherwise same as text.
		/// </value>
		return this._value;
	},
	set_value:function(value){
		this._value=value;
	}
}
MySpace.UI.AutoCompleteItemEventArgs.registerClass('MySpace.UI.AutoCompleteItemEventArgs', Sys.EventArgs);


MySpace.UI.ComboBoxBehavior=function(element){
	MySpace.UI.ComboBoxBehavior.initializeBase(this, [element]);
	
	this._lazyLoadPlaceholderHeight=13;
};
MySpace.UI.ComboBoxBehavior.prototype={
	initialize:function(){
		MySpace.UI.ComboBoxBehavior.callBaseMethod(this, 'initialize');
	
		var el=this.get_element();
		Sys.UI.DomElement.addCssClass(el, "msComboBox");
		
		var arrow=this._arrowNode=document.createElement("img");
		arrow.src="http://x.myspacecdn.com/modules/common/static/img/spacer.gif";
		arrow.className="msComboBoxArrow";
		arrow.style.height=(el.offsetHeight-2)+"px";
		$addHandler(arrow, "click", Function.createDelegate(this, this._toggleComboBoxList));
		
		// CSS hack is needed on Safari but not Chrome
		if(navigator.userAgent.indexOf("Safari") != -1 && navigator.userAgent.indexOf("Chrome") == -1){
			Sys.UI.DomElement.addCssClass(arrow, "msComboBoxArrowSafari");
		}
		
		if(el.nextSibling){
			el.parentNode.insertBefore(arrow, el.nextSibling);
		}
		else{
			el.parentNode.appendChild(arrow);
		}
	},
	
	_toggleComboBoxList:function(ev){
		if(this._popupBehavior && this._popupBehavior.get_visible()){
			this.hidePopup();
		}
		else{
			this._textBoxHasFocus=true;
			this._showingFullList=true;
			this._fetchCompletionItems("");
			this._showingFullList=false;
		}
		
		ev.stopPropagation();
	},
	
	_onKeyDown:function(ev){
		var k=ev.keyCode ? ev.keyCode:ev.rawEvent.keyCode;
		if(k==Sys.UI.Key.down && this._popupBehavior && !this._popupBehavior.get_visible()){
			this._toggleComboBoxList(ev);
		}
		else{
			MySpace.UI.ComboBoxBehavior.callBaseMethod(this, "_onKeyDown", arguments);
		}
	},
	
	_currentCompletionWord:function(){
		if(this._showingFullList){
			return "";
		}
		else{
			return MySpace.UI.ComboBoxBehavior.callBaseMethod(this, "_currentCompletionWord");
		}
	},
	
	get_completionListWidth:function(){
		var elementBounds=Sys.UI.DomElement.getBounds(this.get_element());		
		return elementBounds.width + this._arrowNode.offsetWidth - 2;
	}
};
MySpace.UI.ComboBoxBehavior.registerClass("MySpace.UI.ComboBoxBehavior", MySpace.UI.AutoCompleteBehavior);



//
// JsonpWebServiceProxy class
//

Type.registerNamespace("MySpace.Net");
MySpace.Net.JsonpWebServiceProxy = function() {};
MySpace.Net.JsonpWebServiceProxy.registerClass("MySpace.Net.JsonpWebServiceProxy");

MySpace.Net.JsonpWebServiceProxy.invoke=function(url, params, onSuccess, onFailure, jsonpParam, context, timeout){
	params[jsonpParam || "jsonp"]="MySpace.Net.JsonpWebServiceProxy._handlers["+(++this._counter)+"]";
	
	var count=this._counter;
	this._handlers[count]=function(res){
		MySpace.Net.JsonpWebServiceProxy._handle(el, count, res, onSuccess, onFailure, context);
	};
	
	var pairs=[];
	for(var key in params){
		pairs.push(encodeURIComponent(key)+"="+encodeURIComponent(params[key]));
	}
	url=url+(url.indexOf("?")==-1 ? "?" : "&")+pairs.join("&");
	
	var el=document.createElement("script");
	el.type="text/javascript";
	el.src=url;

	var errorHandler=function(){
		if(MySpace.Net.JsonpWebServiceProxy._handlers[count] != Function.emptyFunction){
			MySpace.Net.JsonpWebServiceProxy._handle(el, count, {}.x, onSuccess, onFailure, context);
		}
	};
	$addHandler(el, "error", errorHandler);
	setTimeout(errorHandler, timeout || 30000);
	
	document.getElementsByTagName("head")[0].appendChild(el);
};
MySpace.Net.JsonpWebServiceProxy._handle=function(el, counter, result, onSuccess, onFailure, context){
	for(var i=0;i<this._deadScripts.length;i++){
		var node=this._deadScripts[i];
		node.parentNode.removeChild(node);
	}
	this._deadScripts=[];
	
	$clearHandlers(el);
	this._handlers[counter]=Function.emptyFunction;
	this._deadScripts.push(el);
		
	if(typeof result != "undefined"){
		if(onSuccess){ onSuccess(result, context); }
	}
	else{
		if(onFailure){ onFailure(context); }
	}
};
MySpace.Net.JsonpWebServiceProxy._counter=0;
MySpace.Net.JsonpWebServiceProxy._handlers=[];
MySpace.Net.JsonpWebServiceProxy._deadScripts=[];


//
// Status/mood control
//

MySpace.UI.HeaderStatusMood=function(e){
	MySpace.UI.HeaderStatusMood.initializeBase(this, [e]);
};
MySpace.UI.HeaderStatusMood.init=function(){
	if(!MySpace.UI.HeaderStatusMood._instance){
		MySpace.UI.HeaderStatusMood._instance=$create(MySpace.UI.HeaderStatusMood, null, null, null, $get('headerStatusMood'));
	}
};
MySpace.UI.HeaderStatusMood.prototype={
	initialize:function(){
		MySpace.UI.HeaderStatusMood.callBaseMethod(this, 'initialize');

		var e=this.get_element();
		var status=e.getAttribute("status");
		var mood=e.getAttribute("mood");
		var moodUrl=e.getAttribute("moodUrl") || this._spacerUrl;
		var thmUrl=e.getAttribute("thmUrl");
		var time=e.getAttribute("time");

		var html="";		
		
		if(thmUrl){
			html="<a id='hsmThumb' href='"+e.getAttribute("homeUrl")+"'>"+
						"<img src='"+thmUrl+"' id='hsmMyImage' alt='' height='28' style='visibility:hidden;' onload='if(this.offsetWidth>32)this.height=Math.round(30*30/this.offsetWidth);this.style.marginTop=((32-this.offsetHeight)/2)+\"px\";this.onload=null;this.style.visibility=\"\"' />"+
				  "</a>";
		}
		
		html+="<div id='hsmMain'"+(status ? "" : " style='visibility:hidden;'")+">"+
					"<div id='hsmStatusLine'>"+
						"<span class='hsmLabel'>"+MySpaceRes.Status.lblStatus+"</span> "+
						"<span id='hsmUserName' style='display:"+(status==MySpaceRes.Status.none ? "none" : "inline")+"'>"+e.getAttribute("userName")+"</span> "+
						"<span id='hsmStatus'>"+status+"</span>"+
						(time ? " &nbsp; <span id='hsmTimestamp'>"+time+"</span>" : "")+
					"</div>"+
					"<div>"+
						"<span class='hsmLabel'>"+MySpaceRes.Status.Mood+"</span> "+
						"<span id='hsmMoodName'>"+(mood || "")+"</span>"+
						"&nbsp;<img src='"+moodUrl+"' id='hsmMoodImage' alt='' /> "+
						"<span class='hsmParen'>(</span>"+
						"<a href='#' id='hsmUpdateLink'>"+MySpaceRes.UserPage.Update+"</a>"+
						"<span class='hsmParen'>)</span>"+
					"</div>"+
				"</div>";
						
		e.innerHTML=html;
		
		this.webServiceURL=e.getAttribute("webServiceURL");
		this.hash=e.getAttribute("hash");
		
		this._mainNode=$get("hsmMain");
		this._updateLink=$get("hsmUpdateLink");
		this._userNameNode=$get("hsmUserName");
		this._statusNode=$get("hsmStatus");
		this._statusLine=$get("hsmStatusLine");
		this._timestampNode=$get("hsmTimestamp");
		this._moodNameNode=$get("hsmMoodName");
		this._moodImage=$get("hsmMoodImage");
		
		this._truncate=!Sys.UI.DomElement.containsCssClass(e, "hsmNoTruncate");
		
		this._addHandler(this._updateLink, "click", "_showUpdateDialog");
		
		if(status){
			this._currentStatus=this._getText(this._statusNode);
			this._currentMood=this._getText(this._moodNameNode);
			this._truncateStatus();
			
			this._saveStatusInCookie({
				status: status,
				moodName: mood,
				moodPictureURL: moodUrl
			});
		}
		else if(this._getStatusFromCookie()){
			this._onSaveSuccess(this._getStatusFromCookie());
		}
		else{
			this._call("GetMoodStatus", {}, "_onSaveSuccess");
		}
	},
	
	_spacerUrl:"http://x.myspacecdn.com/modules/common/static/img/spacer.gif",
	
	dispose:function(){
		for(var i=0;i<this._handlers.length;i++){
			$removeHandler.apply(window,this._handlers[i]);
		}

		MySpace.UI.HeaderStatusMood.callBaseMethod(this, 'dispose');
	},
	
	_call:function(action, args, onSuccess, onFailure){
		args.action=action;
		args.hash=this.hash;
		MySpace.Net.JsonpWebServiceProxy.invoke(this.webServiceURL, args,
			onSuccess ? Function.createDelegate(this, this[onSuccess]): null,
			onFailure ? Function.createDelegate(this, this[onFailure]): null);
	},
	
	_cancelEvent:function(e){
		if(e){
			var evt=new Sys.UI.DomEvent(e);
			e.preventDefault();
			e.stopPropagation();
		}
	},
	
	_addHandler:function(el, type, methodName){
		var hdlr=Function.createDelegate(this, this[methodName]);
		$addHandler(el, type, hdlr);
		
		if(!this._handlers){ this._handlers=[]; }
		this._handlers.push([el,type,hdlr]);
	},
	
	_getText:function(node){
		if(node && node.childNodes[0]){
			return node.childNodes[0].nodeValue;
		}
		return null;
	},
	
	_getStatusFromCookie:function(){
		var cookie=MySpace.Cookies[this._cookieName];
		if(!cookie){return null;}
		
		var vals=cookie.get_values();
		if(!("StatusUid" in vals)){return null;}
		
		if(vals.StatusUid != MySpaceClientContext.UserId){return null;}
		
		return {status: vals.Status, moodName: vals.MoodName, moodPictureURL: vals.MoodImg};
	},
	_saveStatusInCookie:function(vals){
		var cookie=MySpace.Cookies[this._cookieName] || new MySpace.Cookie(this._cookieName, "");
		var cookieVals=cookie.get_values() || (cookie._values={});
		
		if(vals.status){ cookieVals.Status=vals.status; }
		cookieVals.StatusUid=MySpaceClientContext.UserId;
		if(vals.moodName){ cookieVals.MoodName=vals.moodName; }
		if(vals.moodPictureURL){ cookieVals.MoodImg=vals.moodPictureURL; }
		
		MySpace.Cookies.save(cookie,".myspace.com");
	},
	_cookieName:"MSSession",
			
	_showUpdateDialog:function(e){
		this._cancelEvent(e);
		
		if(!this._updateDialog){ this._createUpdateDialog(); }
		
		this._statusInput.value=this._currentStatus;
		this._moodInput.value=this._currentMood;
		this._setSmileyUrl(this._moodImage.src || this._spacerUrl);
	
		this._updateDialog.style.display="block";
		
		this._statusInput.focus();
	},
	
	_createUpdateDialog:function(){
		var dlg=this._updateDialog=document.createElement("div");
		dlg.id="hsmUpdateDialog";
		this.get_element().appendChild(dlg);
		
		dlg.innerHTML=
			'<table>' +
			'	<tr>' +
			'		<td class="hsmLabel">' + MySpaceRes.Status.lblStatus + '</td>' +
			'		<td>' +
			'			<input id="hsmStatusInput" maxlength="160" tabindex="500">' +
			'			<a href="#" id="hsmClearLink">' + MySpaceRes.Status.Clear + '</a>' +
			'		</td>' +
			'	</tr>' +
			'	<tr>' +
			'		<td class="hsmLabel">' + MySpaceRes.Status.Mood + '</td>' +
			'		<td valign="middle">' +
			'			<div id="hsmMoodWrapper">' +
			'				<input id="hsmMoodInput" tabindex="501" maxlength="16">' +
			'			</div>' +
			'			<div id="hsmSmileyWrapper" tabindex="502">' +
			'				<img src="' + this._spacerUrl + '" id="hsmUpdateMoodImage">' +
			'				<img id="hsmSmileyArrow" src="' + this._spacerUrl + '">' +
			'			</div>' +
			'			<div id="hsmSmileyPalette"></div>' +
			'		</td>' +
			'	</tr>' +
			'	<tr>' +
			'		<td></td>' +
			'		<td>' +
			'			<div id="hsmCancelBtn" class="hsmButton" tabindex="504">' +
							MySpaceRes.HomeDisplay.Cancel +
			'				<div class="hsmButtonRight"></div>' +
			'			</div>' +
			'			<div id="hsmDoneBtn" class="hsmButton" tabindex="503">' +
							MySpaceRes.Status.Done +
			'				<div class="hsmButtonRight"></div>' +
			'			</div>' +
			'		</td>' +
			'	</tr>' +
			'</table>';
			
		this._statusInput=$get("hsmStatusInput");
		this._moodInput=$get("hsmMoodInput");
		this._updateMoodImage=$get("hsmUpdateMoodImage");
		this._smileyArrow=$get("hsmSmileyArrow");
		this._smileyPalette=$get("hsmSmileyPalette");
		this._doneBtn=$get("hsmDoneBtn");
		
		// IE quirks mode - inputs don't size properly unless we set the height
		if(Sys.Browser.agent == Sys.Browser.InternetExplorer && document.compatMode == "BackCompat"){
			this._statusInput.style.height=this._moodInput.style.height="22px";
		}
		
		this._addHandler($get("hsmClearLink"), "click", "_clearStatus");
		this._addHandler(this._doneBtn, "click", "_saveStatus");
		this._addHandler($get("hsmCancelBtn"), "click", "_closeDialog");
		this._addHandler(this._statusInput, "focus", "_onFocusInput");
		this._addHandler(this._moodInput, "focus", "_onFocusInput");
		this._addHandler($get("hsmSmileyWrapper"), "click", "_showSmileyPalette");
		this._addHandler(this._smileyPalette, "click", "_onClickSmiley");
		this._addHandler(this._smileyPalette, "blur", "_hideSmileyPalette");
		this._addHandler(this._updateDialog, "keydown", "_enterKeyHandler");
		this._addHandler(document, "keypress", "_escKeyHandler");
		
		this._moodComboBox=$create(MySpace.UI.ComboBoxBehavior, {
			minimumPrefixLength:1,
			completionItems:[this._currentMood],
			completionInterval:500
		}, {
			itemSelected:Function.createDelegate(this, this._onMoodSelected)
		}, null, this._moodInput);
		
		this._smileyPopupBehavior=$create(MySpace.UI.PopupBehavior, {
			parentElement:$get("hsmSmileyWrapper"),
			positioningMode:MySpace.UI.PositioningMode.BottomLeft,
			hideOnDocumentClick:true,
			x:-1, y:-2
		}, null, null, this._smileyPalette);
		
		this._call("GetMoodList", {}, "_populateMoodList");
	},
	
	_populateMoodList:function(result){
		var smileys={};
		var items=[];
		
		this._addSmiley(this._spacerUrl);
		
		for(var i=0;i<result.length;i++){
			var mood=result[i];
			
			items.push({text:mood.name, value:mood});
			
			if(mood.smiley && !(mood.smiley in smileys)){
				smileys[mood.smiley]=true;
				this._addSmiley(mood.smiley);
			}
		}
		
		this._moodComboBox.set_completionItems(items);
	},
	_addSmiley:function(url){
		var img=document.createElement("img");
		img.src=this._spacerUrl;
		img.style.backgroundImage="url('"+url+"')";
		img.url=url;
		this._smileyPalette.appendChild(img);
		
		if(this._smileyPalette.getElementsByTagName("img").length % 7 == 0){
			this._smileyPalette.appendChild(document.createElement("br"));
		}
	},
	_onMoodSelected:function(sender, args){
		this._setSmileyUrl(args.get_value().smiley || this._spacerUrl);
	},
	
	_clearStatus:function(e){
		this._cancelEvent(e);
		this._statusInput.value=MySpaceRes.Status.none;
	},
	
	_onFocusInput:function(e){
		var inp=e.target;
		setTimeout(function(){
			inp.select();
		}, 50);
	},
	
	_showSmileyPalette:function(e){
		this._smileyPopupBehavior.show();
		this._smileyPalette.focus();
	},
	_hideSmileyPalette:function(e){
		this._smileyPopupBehavior.hide();
	},
	_onClickSmiley:function(e){
		var img=e.target;
		if(img.tagName.toLowerCase()!="img"){ return; }
		
		this._hideSmileyPalette();
		this._setSmileyUrl(img.url);
	},
	_setSmileyUrl:function(url){
		this._currentSmileyUrl=url;
		this._updateMoodImage.style.backgroundImage="url('"+url+"')";
	},
	
	_enterKeyHandler:function(e){
		if(!this._moodComboBox.get_visible() && e.keyCode==13){ // enter
			if(e.target==this._cancelBtn){ this._closeDialog(e); }
			else{ this._saveStatus(e); }
		}
	},
	_escKeyHandler:function(e){
		if(e.charCode==27 && this._updateDialog && this._updateDialog.style.display!="none"){
			this._closeDialog(e);
		}
	},
	
	_saveStatus:function(e){
		this._cancelEvent(e);
		
		if(this._saveInProgress){ return; }
		
		var args={
			status:this._statusInput.value,
			mood:this._moodInput.value,
			smiley:this._currentSmileyUrl
		};
		
		this._doneBtn.childNodes[0].nodeValue=MySpaceRes.Common.PleaseWait;
		
		this._call("SaveCustomMoodStatus", args, "_onSaveSuccess", "_onSaveError");
		this._saveInProgress=true;
	},
	
	_onSaveSuccess:function(result){
		this._onSaveComplete();
		
		this._saveStatusInCookie(result);
		
		if(!result.status || result.status=="null" || result.status=="undefined"){
			result.status=MySpaceRes.Status.none;
		}
		
		this._statusNode.innerHTML=result.status;
		if(this._timestampNode){ this._timestampNode.innerHTML=result.timestamp; }
		this._moodNameNode.innerHTML=result.moodName;
		this._moodImage.src=result.moodPictureURL;
		
		this._userNameNode.style.display=(result.status==MySpaceRes.Status.none)?"none":"inline";
		
		this._currentMood=this._getText(this._moodNameNode);
		this._currentStatus=this._getText(this._statusNode);
		this._truncateStatus();
		
		this._mainNode.style.visibility="visible";
		
		//hide the module tip if any
		var moduletip=$get("mtStatusMood");
		if (moduletip){
		    moduletip.style.display="none";
		}
		
		this._closeDialog();
	},
	_onSaveError:function(){
		this._onSaveComplete();
		var msg=$get("hsmErrorText").innerHTML.replace(/<br.*>/gi, "\n");
		alert(msg);
	},
	_onSaveComplete:function(){
		this._saveInProgress=false;
		if(this._doneBtn){ this._doneBtn.childNodes[0].nodeValue=MySpaceRes.Status.Done; }
	},
	
	_truncateStatus:function(){
		if(!this._truncate){
			MySpace.Util.applyWBRToElement(this._statusLine);
			return;
		}
		
		if(this._statusLine.scrollWidth > this._statusLine.offsetWidth){
			this._statusLine.title=this._getText(this._userNameNode)+" "+this._currentStatus;
		}
		else{
			this._statusLine.title="";
		}
		
		if(Sys.Browser.agent!=Sys.Browser.Firefox){ return; }	// IE/Safari support text-overflow
		
		for(var i=this._currentStatus.length;i>=0;i--){
			if(this._statusLine.scrollWidth <= this._statusLine.offsetWidth) { break; }
			
			this._statusNode.childNodes[0].nodeValue=this._currentStatus.substring(0,i) + "\u2026"; // ellipsis
		}
	},
	
	_closeDialog:function(e){
		this._cancelEvent(e);
		if(this._updateDialog){
			this._moodComboBox.hidePopup();
			this._updateDialog.style.display="none";
		}
	}
};
MySpace.UI.HeaderStatusMood.registerClass('MySpace.UI.HeaderStatusMood', Sys.UI.Behavior);
