/** library: master_switches.js ***********************************************
 * In case of an emergency with javascript based functionality, if the
 * functionality contains a kill switch it should be set in this file. Each
 * application's kill switch value(s) should be clearly documented.
 * @author joe whetzel
 * @minify true
 */

/* PLUCK ***
 * Turning Pluck off will turn off all Pluck functionality. Some SiteLife 
 * widgets, if implemented without the appropriate test, may continue to operate
 * if Pluck is responding to requests.
 * To turn Pluck off, set siteLife_master_switch_on to boolean false.
 */
if (typeof siteLife_master_switch_on === 'undefined') {
	var siteLife_master_switch_on = true;
}
// sitelife_is_on is meant for site-specific use and should not be reset here.
if (typeof sitelife_is_on === 'undefined') {
        var sitelife_is_on = true;
}
/* siteLifeConf.js ************************************************************* 
 * Define site-specific configuration settings for Pluck.                      
 * @minify true                                                               
 * Optional Values:                                                            
 * standardTZDhours: negative integer used to define the time zone, the app    
 *   defaults to eastern; common values:                                       
 *   eastern: -5                                                               
 *   central: -6                                                               
 *   mountain: -7                                                              
 *   pacific: -8                                                               
 *   alaska: -9                                                                
 * defaultDateFormat: string used to define a custom format for displaying dates 
 * mi_comment_sort_preference: comment sort order                              
 *   'TimeStampAscending'        == Oldest first                               
 *   'TimeStampDescending'       == Newest first                               
 *   'RecommendationsDescending' == Most-recommended first                     
 *   'RecommendationsAscending'  == Least-recommended first                    
 * mi_comments_per_page: integer from 3 to 10                                  
 */                                                                            
var sitelife_is_on = true;                                                    
var pluck_env = (location.host.match(/^(preview|dev)/))?'pluckdev':'pluck';
pluck_env += '.thesunnews.com';
var serverUrl = 'http://'+pluck_env+'/ver1.0/Direct/Process';                 
// optional variables **********************************                      
//document.standardTZDhours = -6;
//document.defaultDateFormat = '%B, %e %l:%M %p';
//var mi_comment_sort_preference = 'TimeStampDescending';
//var mi_comments_per_page = 10;
    //multi site enabled -- sid: pluckdev.thesunnews.com 

///<summary>constructor to create a new SiteLifeProxy</summary>
function SiteLifeProxy(url) {
    // User Configurable Properties - these can be set at any time

    // your apiKey, this value must be set!
    this.apiKey = null;

    // sniff the browser for custom behaviors
    this.__isExplorer = navigator.userAgent.toLowerCase().indexOf('msie') != -1;
    this.__isSafari = navigator.userAgent.toLowerCase().indexOf('safari') != -1;
    this.__isMac = navigator.platform.toLowerCase().indexOf('mac') != -1;
    this.__isMacIE = this.__isMac && this.__isExplorer;
    
    // if enabled, spit out debug information through alert()
    this.debug = false;
    
    // used to track the id of the handler expecting the results from the immediately preceeding method invocation
    // this is used only for testing purposes
    this.lastHandlerId = "";
    
    // Methods You can Overide
    //
    // OnSuccess(returnValue) - is passed the return value at the end of a successful call, default does nothing
    // OnError(msg) - is passed an error message if a problem occurs
    // OnDebug(msg) - is called when debugging is enabled
     
    this.__baseUrl = url;
    this.__sendInvokeCount = 0;
    
    this.__eventHandlers = new Object();
};

SiteLifeProxy.prototype.AddEventHandler = function (event_name, callback) {
	var eventList = this.__eventHandlers[event_name];
	if (!eventList){
		eventList = new Array();
		this.__eventHandlers[event_name] = eventList;
	}
	eventList.push(callback);
};

SiteLifeProxy.prototype.FireEvent = function (event_name) {
    var func;
    if(handlers = this.__eventHandlers[event_name]) {
        var A = new Array(); for (var i = 1; i <  this.FireEvent.arguments.length; i++){ A[i - 1] = this.FireEvent.arguments[i];}
        for(var x=0;x<handlers.length;x++){
			func = handlers[x];
			if (func.__Bound){
			   if (handlers.length == 1) return func();
			   func();
			}
			if (handlers.length == 1) return func.apply(this, A);
			func.apply(this, A);
    }
}
};

SiteLifeProxy.prototype.ScriptId = function() { return this.__scriptId = "_bb_script_" + this.__sendInvokeCount++; }

// Default error handler for the proxy object, simple alert
SiteLifeProxy.prototype.OnError = function(msg) {
   alert("OnError: " + msg);
}

// Default debug handler for the proxy object, simple alert
SiteLifeProxy.prototype.OnDebug = function(msg) {
    if (this.debug)
        alert("Debug: " + msg);
}

// fetch a named request parameter from the page URL
SiteLifeProxy.prototype.GetParameter = function(parameterName) {
    var key = parameterName + "=";
    var parameters = document.location.search.substring(1).split("&");
    for (var i = 0; i < parameters.length; i++)
    {
        if (parameters[i].indexOf(key) == 0)
            return parameters[i].substring(key.length);
    }
    return null;
};

// browser independent method to get elements by ID
SiteLifeProxy.prototype.GetElement = function(id) {
    this.OnDebug("GetElement " + id);
    if (document.getElementById)
        return document.getElementById(id);
    if (document.all)
        return document.all[id];
    this.OnError("No support for GetElement() in this browser");
    return null;
}

// browser independent method to get elements by tag name
SiteLifeProxy.prototype.GetTags = function(tagName) {
    this.OnDebug("GetTags " + tagName);
    if (document.getElementsByTagName)
        return document.getElementsByTagName(tagName);
    if (document.all)
       return document.tags(tagName);
    this.OnError("No support for GetTags() in this browser");
    return null;
}

SiteLifeProxy.prototype.Trim = function(s) {
	return s.replace(/^\s+|\s+$/g,"");

};

SiteLifeProxy.prototype.EscapeValue = function(s) {
    if (s == null) return null;
    return encodeURIComponent(s);
};

SiteLifeProxy.prototype.__ArrayValidation = function(s)
{
    if ((typeof s == 'undefined') || (s.length < 1))
    {
        return false;
    }
    return true;
}

SiteLifeProxy.prototype.__CheckErrorHandler = function(onError) {
    this.OnDebug("__CheckErrorHandler " + onError);
    if ((typeof onError == 'undefined') || (eval("window." + onError) == null))
    {
      return "gSiteLife.OnError";
    }
    return onError;
}
SiteLifeProxy.prototype.SetCookie = function SetCookie( name, value) {
    var today = new Date(); today.setTime( today.getTime() );
    
    var expires_date = new Date( today.getTime() + 126144000000 );
    
    document.cookie = name + "=" +escape( value ) +
    ";expires=" + expires_date.toGMTString() + 
    ";path=/" + ";domain=thesunnews.com" ;
}
// validate and fetch arguments, if the argument is missing and optional, we return an empty string        
SiteLifeProxy.prototype.__GetArgument = function(variableName, variableValue, isRequired, isArray) {
    this.OnDebug("__GetArgument " + variableName + "," + variableValue + "," + isRequired + "," + isArray);
    if (typeof variableValue == "undefined" || variableValue == null || variableValue == "")
    {
        if (isRequired)
        {
            this.OnError("Missing required parameter " + variableName);
            this.__isValid = false;
            return "";
        }
        else
            return "";
    }
    if (isRequired && isArray) 
    {
        if (!this.__ArrayValidation(variableValue)) 
        {
            this.OnError("Invalid array parameter " + variableName);
            this.__isValid = false;
            return "";
        }
    }
    return "&" + variableName + "=" + this.EscapeValue(variableValue);
};

SiteLifeProxy.prototype.__StripAnchorFromUrl = function(url) {
    var aIdx = url.indexOf("#");
    return aIdx == -1 ? url : url.substring(0, aIdx);
}

SiteLifeProxy.prototype.__SafeAppendUrlValue = function(url, key, value) {
    url += url.indexOf("?") != -1 ? "&" : "?";
    return url + key + "=" + value;
}

SiteLifeProxy.prototype.__AppendUrlValues = function (url)
{
	time = new Date();
    url += this.__GetArgument("plckNoCache", time.getTime(), false, false);
    url += this.__GetArgument("plckApiKey", this.apiKey, true, false);
                        url += this.__GetArgument("sid", gSiteLife.SID, false, false);
                
    return url;
}

SiteLifeProxy.prototype.ReloadPage = function(params) {
    var sSearch = window.location.search.substring(1);
    var sNVPs = sSearch.split('&');
    var newSearch = "";
    var anchorPoint = "";
    for(var k in params) {
        if(k == "extend") continue;
		if(k == "#") {
			anchorPoint = '#' + params[k];
			continue;
		}		
        if(newSearch == "") newSearch += "?"; else newSearch += "&";
        newSearch += k + '=' + params[k];
    }
    for (var i = 0; i < sNVPs.length; i++) {
        var kv = sNVPs[i].split('=');
        if(kv[0] && kv[0].indexOf('plck') != 0 && ! params[kv[0]]) {
            newSearch += "&" + sNVPs[i];        
        }
    }
            
    if(anchorPoint != ""){ 
        window.location.hash = anchorPoint;
    }
    window.location.search = newSearch;
}

function loadScript (url, callback) {
	var script = document.createElement('script');
	script.type = 'text/javascript';
	script.charset = 'utf-8';
	if (callback)
		script.onload = script.onreadystatechange = function() {
			if (script.readyState && script.readyState != 'loaded' && script.readyState != 'complete')
				return;
			script.onreadystatechange = script.onload = null;
			callback();
		};
	script.src = url;
	document.getElementsByTagName('head')[0].appendChild (script);
}

SiteLifeProxy.prototype.__Send = function(url, scriptToUse, callbackName, args) {
    this.OnDebug("_Send " + url);
    function gLoadScript(url, callbackName) {
      var script = document.createElement('script');
      script.setAttribute('type', 'text/javascript');
    	script.setAttribute('charset', 'utf-8');
    	script.setAttribute('src', url + (callbackName ? '&EVENT_ID=' + callbackName : ''));
    	document.getElementsByTagName('head')[0].appendChild (script);
    }
    function bind(_function, _this, _arguments) {
      var f = function() {
        _function.apply(_this, _arguments);
      };
      f['__Bound'] = true;
      return f;
    };
    var func;
    if ((typeof callbackName == 'string') && (func = this.__eventHandlers[callbackName]) && (typeof func == 'function') && !func['__Bound']) {
      this.__eventHandlers[callbackName] = bind(func, this, args);
    }
    
    //append our various parameters as necessary
    url = this.__AppendUrlValues(url);
    this.OnDebug("_Send (updated) " + url);
    // add the script node to the document
    if (document.createElement && ! this.__isMacIE) {
        gLoadScript(url, callbackName);
        return;
    }

    // could fall back to sync at this point, but will bust if the page is already loaded

    this.OnError("No support for async in this browser");
}

SiteLifeProxy.prototype.Logout = function(ScriptToUse, IsRestPage) {
    var plckRest = IsRestPage ? true : false;
    this.__Send(this.__baseUrl + '/Utility/Logout?plckRedirectUrl=' + escape(window.location.href) + '&plckRest=' + plckRest, ScriptToUse);
    return false;
}

SiteLifeProxy.prototype.AddLoadEvent = function(func) {
if(window.addEventListener){
 window.addEventListener("load", func, false);
}else{
 if(window.attachEvent){
   window.attachEvent("onload", func);
 }else{
   if(document.getElementById){
    var oldonload = window.onload;
    if (typeof window.onload != 'function') {
      window.onload = func;
    } else {
      window.onload = function() {
       if (oldonload) {
        oldonload();
       }
       func();
}}}}}}

SiteLifeProxy.prototype.AdInsertHelper = function() {
    for(var src in gSiteLife.__adsToInsert) {
        if(src == "extend") continue;
        var dest = gSiteLife.__adsToInsert[src];
        var parent = document.getElementById(dest);
		var newChild = document.getElementById(src);
		if( ! parent || ! newChild ) {continue; }
		parent.replaceChild( newChild, document.getElementById(dest + "Child"));
		newChild.style.display = "block"; parent.style.display = "block";
    }
}

SiteLifeProxy.prototype.InsertAds = function(source, destination) {
gSiteLife.__adsToInsert = new Object();
for(ii=0; ii< this.InsertAds.arguments.length; ii+=2) { gSiteLife.__adsToInsert[this.InsertAds.arguments[ii]] = this.InsertAds.arguments[ii+1];}
this.AddLoadEvent(gSiteLife.AdInsertHelper);
}

SiteLifeProxy.prototype.TitleTag = function() {
 var titleTag = document.getElementById("plckTitleTag");
 return titleTag ? titleTag.innerText || titleTag.textContent : null;
 }

SiteLifeProxy.prototype.WriteDiv = function(id, divClass) {
    var cssClass = divClass ? divClass : "";
    document.write('<div id="'+id+'" class="'+cssClass+'"></div>'); return id;
}

SiteLifeProxy.prototype.InnerHtmlWrite = function(elementId, innerContents ) {
    var el = document.createElement("div");
    try {
        if(document.location.href.indexOf("debug=true") > -1) {
            el.innerHTML += "<div style='border:1px solid red;'><span style='background-color:red; color:white; position:absolute; cursor:pointer; font-size:8pt;' onclick='DebugShowInnerHTML(\"${plckElementId}\",\"http://pluckdev.thesunnews.com/ver1.0/Proxies/Default.rails?&sid=pluckdev.thesunnews.com\");'>&nbsp;?&nbsp;</span><div>" + innerContents + "</div></div>";
        } else {
            el.innerHTML += innerContents;
            el.style.display = "inline";
        }
        var destDiv = document.getElementById(elementId);
        while (destDiv.childNodes.length >= 1) {
             destDiv.removeChild(destDiv.childNodes[0]);
        }
        
        destDiv.appendChild(el);
    } catch (error) {
        alert(elementId + " Error "  + error.number + ": " + error.description);
    }
}

SiteLifeProxy.prototype.SortTimeStampDescending = "TimeStampDescending";
SiteLifeProxy.prototype.SortTimeStampAscending = "TimeStampAscending";
SiteLifeProxy.prototype.SortRecommendationsDescending = "RecommendationsDescending";
SiteLifeProxy.prototype.SortRecommendationsAscending = "RecommendationsAscending";
SiteLifeProxy.prototype.SortRatingDescending = "RatingDescending";
SiteLifeProxy.prototype.SortRatingAscending = "RatingAscending";
SiteLifeProxy.prototype.SortAlphabeticalAscending = "AlphabeticalAscending";
SiteLifeProxy.prototype.SortAlphabeticalDescending = "AlphabeticalDescending";
SiteLifeProxy.prototype.KeyTypeExternalResource = "ExternalResource";
        



SiteLifeProxy.prototype.PersonaHeaderRequest = function(UserId) {
    var url = this.__baseUrl + '/Persona/PersonaHeader?plckElementId=personaHDest&plckUserId='+ UserId;
    this.__Send(url, "personaHeaderScript", 'persona:header', arguments);
}
SiteLifeProxy.prototype.PersonaHeader = function(UserId) {
    this.WriteDiv("personaHDest", "Persona_Main");
        this.PersonaHeaderRequest(UserId); 
}
SiteLifeProxy.prototype.PersonaHeaderInbox = function() {
	// if DAAPI proxy is not present, fail gracefully
	if (!document.getElementById('PrivateMessageInbox') || !window.RequestBatch || !window.PrivateMessageFolderList) {
		var pmContainer = document.getElementById('PersonaHeader_PrivateMessageContent');
		if (pmContainer) {
			pmContainer.style.display = 'none';
		}
		return;
	}

	var rb = new RequestBatch();
	rb.AddToRequest(new PrivateMessageFolderList());
	rb.BeginRequest(serverUrl,
		function(responseBatch) {
			var count = '';
			try {
				if (responseBatch && responseBatch.Messages && responseBatch.Messages.length && responseBatch.Messages[0].Message == 'ok') {
					var folders = responseBatch.Responses[0].PrivateMessageFolderList.FolderList;
					for (var i = 0; i < folders.length; i++) {
						var f = folders[i];
						if (f.FolderID == 'Inbox') { count = f.UnreadMessageCount; break; }
					}
				}
			} catch (e) {}
			var inboxStr = "Inbox ({0})";
			var idx = inboxStr.indexOf("{0}");
			if (inboxStr == '' || idx >= -1)
				inboxStr = inboxStr.substring(0, idx) + count + inboxStr.substring(idx+3);
			var inbox = document.getElementById('PrivateMessageInbox');
			inbox.innerHTML = inboxStr;
			if (count > 0) inbox.style.fontWeight = 'bold';
		});
}

SiteLifeProxy.prototype.Persona = function(UserId) {
    this.WriteDiv("personaDest", "Persona_Main");
    var action = this.GetParameter("plckPersonaPage");
    if(action && (typeof this[action] == 'function')) this[action](UserId);
             else this.PersonaHome(UserId);
    }
SiteLifeProxy.prototype.LoadPersonaPage = function(PageName, UserId) {
    var params = new Object(); params['plckPersonaPage'] = PageName; params['plckUserId'] = UserId;
            params['insiteUserId'] = UserId;
        for(ii=2; ii< this.LoadPersonaPage.arguments.length; ii+=2) { params[this.LoadPersonaPage.arguments[ii]] = this.LoadPersonaPage.arguments[ii+1];}
    this.ReloadPage(params);
    return false;
}

SiteLifeProxy.prototype.PersonaHome = function(UserId) {

    var me = this;
    this.AddEventHandler('persona:home:complete', function() { me.PopulateGroupsDiv(UserId, 1); });
    return this.PersonaSend('PersonaHome', 'personaDest', 'personaScript', UserId, null, 'persona:home:complete');
	  
}

SiteLifeProxy.htmlEncode = function(str){
	// Fix HTML
	var ret = str;
	var div = document.createElement('div');
	var text = document.createTextNode(str);
	div.appendChild(text);
	ret = new String(div.innerHTML);				
	
	// The above doesn't take care of quotes.
	ret = ret.replace(/"/g, '&quot;');
	
	return ret;
};
			
SiteLifeProxy.prototype.PopulateGroupsDiv = function(UserId, OnPage) {
        // a utility function to compare two urls for purposes of determining site of origin
    var isFromThisSite = function(siteOfOrigin, currentHost) {
        // assume each url has periods in it
        var siteOfOriginDotIndex = siteOfOrigin.indexOf('.');
        var currentHostDotIndex = currentHost.indexOf('.')
        if (siteOfOriginDotIndex < 0 || currentHostDotIndex < 0) {
            return false;
        }
        else {
            return siteOfOrigin.slice(siteOfOriginDotIndex).toLowerCase() == currentHost.slice(currentHostDotIndex).toLowerCase();
        }
    }
        // check for DAAPI objects; if not there, fail gracefully
    if (window.RequestBatch && window.CommunityGroupMembershipPage && window.UserKey) {
        var requestBatch = new RequestBatch();
        requestBatch.AddToRequest(new CommunityGroupMembershipPage(new UserKey(UserId), 8, OnPage, "TimeStampAscending", "Member"));
        requestBatch.BeginRequest("http://pluckdev.thesunnews.com/ver1.0/Direct/Process", function(responseBatch) {   
            if (responseBatch.Responses.length > 0 && responseBatch.Responses[0].CommunityGroupMembershipPage) {
                // create the div that will house all this info
                var groupsDiv = document.createElement('div');
                groupsDiv.className = 'PersonaStyle_ItemContainer';
                var groupsContainer = document.getElementById('PersonaStyle_GroupsContainer');
                // Check groupsContainer is null because PersonaStyle_GroupContainer may be absent due to private persona files.
                if (groupsContainer != null) {
                    groupsContainer.appendChild(groupsDiv);
                        
                    var groupBaseUrl = "http://preview.thesunnews.com/groups/CommunityGroup.html";
                    var groupMembershipPage = responseBatch.Responses[0].CommunityGroupMembershipPage;
                    var groupsHtml = "<div class=\"PersonaStyle_SectionHead\">Groups</div>";
                    groupsHtml += "<div class=\"PersonaStyle_GroupList\">";
                    for (var index = 0; index < groupMembershipPage.CommunityGroupMemberships.length; index++) {
                        var currentGroup = groupMembershipPage.CommunityGroupMemberships[index].CommunityGroup;
                        // if current group is private and user is non-member, don't display
                        var display = true;
                        if (currentGroup.CommunityGroupVisibility == 'Private') {
                            display = (currentGroup.RequestingUsersMembershipTier != 'NonMember' && currentGroup.RequestingUsersMembershipTier != 'Banned');
                        }
                        if (display) {
                            var groupUrl = groupBaseUrl + "?slGroupKey=" + currentGroup.CommunityGroupKey.Key;
                                                            if (!isFromThisSite(currentGroup.SiteOfOrigin, window.location.host)) {
                                    groupsHtml += "<img height=\"50\" width=\"50\" title=\"" + SiteLifeProxy.htmlEncode(currentGroup.Title) + "\" src=\"" + currentGroup.AvatarImageUrl + "\" />";
                                }
                                else {
                                    groupsHtml += "<a href=\"" + groupUrl + "\"><img height=\"50\" width=\"50\" title=\"" + SiteLifeProxy.htmlEncode(currentGroup.Title) + "\" src=\"" + currentGroup.AvatarImageUrl + "\" /></a>";
                                }
                                                    }
                    }
                    //Pagination for Group List
                    groupsHtml += "<p><ul class=\"PersonaStyle_GroupListPagination\">";
                    
                    if (groupMembershipPage.OnPage > 1)                {
                        groupsHtml += "<li><a href='#PreviousGroup' onclick='gSiteLife.PopulateGroupsDiv(\"" + UserId + "\", " + (parseInt(groupMembershipPage.OnPage) - 1) + ");'>&lt;&lt;Previous</a></li>";
                    }
                    
                    if (groupMembershipPage.NumberOfCommunityGroupMemberships > (groupMembershipPage.NumberPerPage * groupMembershipPage.OnPage))                {
                        groupsHtml += "<li><a href='#NextGroup' onclick='gSiteLife.PopulateGroupsDiv(\"" + UserId + "\", " + (parseInt(groupMembershipPage.OnPage) + 1) + ");'>Next&gt&gt;</a></li>";
                    }
                    groupsHtml += "</p>";
                    
                    //End Pagination for Group List            
                    groupsHtml += "</ul><div class=\"PersonaStyle_GroupListClear\"></div>";                   
                    groupsHtml += "</div>";                   
                    groupsDiv.innerHTML = groupsHtml;
                    
                   
                    groupsContainer.appendChild(groupsDiv);
                }   
            }
        });
    }
    // fire any other events
    this.FireEvent('persona:home');
}

SiteLifeProxy.prototype.WatchItem = function(Controller,Method,WatchKey, targetDiv) {
    var url = this.__baseUrl + '/'+Controller+'/' + Method + '?' + 'plckWatchKey=' + WatchKey + '&plckElementId=' + targetDiv + '&plckWatchUrl=' + this.EscapeValue(window.location.href);
    this.__Send(url, "AddWatchScript");
    return false;
}
SiteLifeProxy.prototype.PersonaRemoveWatchItem= function(UserId, WatchKey, Div, View) {
   return this.PersonaSend('PersonaRemoveWatchItem', Div, 'personaScript', UserId, 'plckWatchView=' + View + '&plckWatchKey=' + WatchKey);
}
SiteLifeProxy.prototype.PersonaAddFriend= function(UserId) {
   return this.PersonaSend('PersonaAddFriend', 'personaHDest', 'personaScript', UserId);
}
SiteLifeProxy.prototype.PersonaRemoveFriend = function(UserId, Friend, Div, View, Expanded, confirmMsg) {
   if(!Expanded) Expanded = "false";
   if (confirm(confirmMsg) == true) {
    return this.PersonaSend('PersonaRemoveFriend', Div, 'personaScript', UserId, 'plckFriendView=' + View + '&plckFriend=' + Friend + '&plckExpanded=' + Expanded);
   }
   return false;
}
SiteLifeProxy.prototype.PersonaRemovePendingFriend = function(UserId, PendingFriend, Div, confirmMsg) {
   if (confirm(confirmMsg) == true) {
    return this.PersonaSend('PersonaRemovePendingFriend', Div, 'personaScript', UserId, 'plckPendingFriend=' + PendingFriend);
   }
   return false;
}
SiteLifeProxy.prototype.PersonaAddPendingFriend = function(UserId, PendingFriend, Div) {
    return this.PersonaSend('PersonaAddPendingFriend', Div, 'personaScript', UserId, 'plckPendingFriend=' + PendingFriend);
}
SiteLifeProxy.prototype.PersonaMessages = function(UserId) {
   var AdParams = this.GetParameter('plckCurrentPage') ? 'plckCurrentPage=' + this.GetParameter('plckCurrentPage') : "";
   var scrl = this.GetParameter('plckScrollToAnchor');  if(scrl){ if(AdParams) {AdParams +='&';} AdParams += 'plckScrollToAnchor=' + scrl;}
   if(this.GetParameter('plckMessageSubmitted')){if(AdParams) {AdParams +='&';} AdParams += 'plckMessageSubmitted=' + this.GetParameter('plckMessageSubmitted');}
   return this.PersonaSend('PersonaMessages', 'personaDest', 'personaScript', UserId, AdParams, 'persona:messages');
}
SiteLifeProxy.prototype.PersonaComments = function(UserId) {
   var AdParams = this.GetParameter('plckCurrentPage') ? 'plckCurrentPage=' + this.GetParameter('plckCurrentPage') : "";
   return this.PersonaSend('PersonaComments', 'personaDest', 'personaScript', UserId, AdParams, 'persona:comments');
}
SiteLifeProxy.prototype.PersonaBlog = function(UserId) {
   var AdParams = this.GetParameter('plckCurrentPage') ? 'plckCurrentPage=' + this.GetParameter('plckCurrentPage') : "";
   if(AdParams) {AdParams +='&';} AdParams += 'plckBlogId=' + UserId;
   var url = this.__baseUrl + '/PersonaBlog/PersonaBlog?plckElementId=personaDest&plckUserId='+ UserId + '&' + AdParams;
   this.__Send(url, 'personaScript', 'persona:blog', arguments);
   return false;
}
SiteLifeProxy.prototype.PersonaProfile = function(UserId) {
    return this.PersonaSend('PersonaProfile', 'personaDest', 'personaScript', UserId, null, 'persona:profile');
}
SiteLifeProxy.prototype.PersonaWatchListPaginate = function(UserId, pageNum) { 
    return this.PersonaPaginate('WatchList', pageNum, UserId);
}
SiteLifeProxy.prototype.PersonaFriendsPaginate = function(UserId, pageNum) { 
	var AdParam = "plckFullFriendsList=true";
    return this.PersonaPaginate('Friends', pageNum, UserId, AdParam);
}

SiteLifeProxy.prototype.PersonaFriendsExpand= function(UserId) { 
    var url = this.__baseUrl + '/Persona/PersonaFriends?plckFullFriendsList=true&plckFriendsPageNum=0&plckElementId=PersonaFriendsDest&plckUserId='+ UserId;
    this.__Send(url, 'PersonaFriendsScript');
    return false;
}
SiteLifeProxy.prototype.PersonaFriendsCollapse= function(UserId, pageNum) { 
    var url = this.__baseUrl + '/Persona/PersonaFriends?plckFullFriendsList=false&plckFriendsPageNum=0&plckElementId=PersonaFriendsDest&plckUserId='+ UserId;
    this.__Send(url, 'PersonaFriendsScript');
    return false;
}

SiteLifeProxy.prototype.PersonaPendingFriendsPaginate = function(UserId, pageNum) { 
    var AdParam = "plckPendingFriendsPageNum=" + pageNum;
    return this.PersonaPaginate('Friends', 0, UserId,AdParam);
}
SiteLifeProxy.prototype.PersonaMessagesPreviewPaginate = function(UserId, pageNum) { 
    return this.PersonaPaginate('MessagesPreview', pageNum, UserId);
}
SiteLifeProxy.prototype.PersonaMessageRemove = function(UserId, pageNum, MessageKey, confirmMsg) { 
   if (confirm(confirmMsg) == true) {
        return this.PersonaSend('PersonaRemoveMessage', 'personaDest', 'PersonaMessagesPageScript', UserId, 'plckCurrentPage='+ pageNum + '&plckMessageKey='+MessageKey);
   }
   return false;
}
SiteLifeProxy.prototype.PersonaSend = function(ApiName, DestDiv, ScriptName, UserId, AddParams, eventId){
    var url = this.__baseUrl + '/Persona/' + ApiName + '?plckElementId=' + DestDiv + '&plckUserId='+ UserId;
    if(AddParams) url += '&' + AddParams;
    this.__Send(url, ScriptName, eventId, arguments);
    return false;
}

SiteLifeProxy.prototype.PersonaPaginate = function(ApiName, PageNum, UserId, AddParams){
    var url = this.__baseUrl + '/Persona/Persona' + ApiName + '?plck' + ApiName + 'PageNum=' + PageNum + '&plckElementId=Persona' + ApiName + 'Dest&plckUserId='+ UserId;
    if(AddParams) url += '&' + AddParams;    
    this.__Send(url, 'Persona'+ ApiName + 'Script');
    return false;
}

SiteLifeProxy.prototype.PersonaPhotoSend = function(ApiName, DestDiv, ScriptName, UserId, AddParams, eventId){
    var url = this.__baseUrl + '/PersonaPhoto/' + ApiName + '?plckElementId=' + DestDiv + '&plckUserId='+ UserId;
    if(AddParams) url += '&' + AddParams;
    this.__Send(url, ScriptName, eventId, arguments);
    return false;
}

SiteLifeProxy.prototype.PersonaMostRecent = function(UserId, PhotoID, DestDiv) {
   return this.PersonaPhotoSend('PersonaMostRecent', DestDiv, 'personaScript', UserId,'plckPhotoID=' + PhotoID);
}

SiteLifeProxy.prototype.PersonaCommunityGroupsPaginate = function(UserId, PageNum){
	return this.PersonaPaginate('CommunityGroups', PageNum, UserId);
}

SiteLifeProxy.prototype.PersonaCreateGallery = function(UserId) {
     return this.PersonaPhotoSend('UserGalleryCreate', 'personaDestPhoto', 'personaScript', UserId);
}

SiteLifeProxy.prototype.PersonaEditGallery = function(UserId,GalleryID) {
     return this.PersonaPhotoSend('UserGalleryEdit', 'userGalleryDest', 'personaScript', UserId,'plckGalleryID=' + GalleryID);
}

SiteLifeProxy.prototype.PersonaUploadToUserGallery = function(GalleryId) {
    var url = this.__baseUrl + '/Photo/PhotoUpload?plckElementId=userGalleryDest&plckGalleryID='+ GalleryId;
    this.__Send(url);
    return false;
}

SiteLifeProxy.prototype.PersonaPhotos = function(UserId) {
     return this.PersonaPhotoSend('PersonaPhotos', 'personaDest', 'personaScript', UserId, null, 'persona:photos');
}
SiteLifeProxy.prototype.PersonaAllPhotos = function(UserId) {
     return this.PersonaPhotoSend('PersonaAllPhotos', 'personaDest', 'personaScript', UserId);
}

SiteLifeProxy.prototype.PersonaGalleryPhoto = function(UserId, plckFindCommentKey) {
	var findCommentKey = gSiteLife.ReadFindCommentKey(findCommentKey, "widget:personaGalleryPhoto");
	
    return this.PersonaPhotoSend('PersonaGalleryPhoto', 'personaDest', 'personaScript', UserId, 'plckFindCommentKey=' + findCommentKey, "widget:personaGalleryPhoto");
}
SiteLifeProxy.prototype.PersonaMyRecentPhotos = function(UserId,ElementId, PageNum) {
     return this.PersonaPhotoSend('PersonaMyRecentPhotos', ElementId, 'personaScript', UserId,'plckPageNum=' + PageNum);
}

SiteLifeProxy.prototype.PersonaGallery = function(UserId,GalleryId,PageNum) {
     if(!PageNum){
        PageNum = gSiteLife.GetParameter("plckPageNum") ? gSiteLife.GetParameter("plckPageNum") : 0;
     }
     if(!GalleryId) {
        GalleryId = gSiteLife.GetParameter("plckGalleryID");
     }
     return this.PersonaPhotoSend('PersonaGallery', 'personaDest', 'personaScript', UserId,'plckGalleryID='+ GalleryId + '&plckPageNum=' + PageNum);
}

SiteLifeProxy.prototype.UserGalleryList = function(UserId,ElementId, PageNum) {
     return this.PersonaPhotoSend('UserGalleryList', ElementId, 'personaScript', UserId,'plckPageNum=' + PageNum);
}
SiteLifeProxy.prototype.PersonaGallerySubmissions = function(UserId,ElementId, PageNum){
     return this.PersonaPhotoSend('PersonaGallerySubmissions', ElementId, 'personaScript', UserId,'plckPageNum=' + PageNum);
} 

SiteLifeProxy.prototype.PersonaGalleryPhoto = function(UserId, plckFindCommentKey) {
	var findCommentKey = gSiteLife.ReadFindCommentKey(findCommentKey, "widget:personaPhoto");
    
    var photoid = gSiteLife.GetParameter('plckPhotoID');
    return this.PersonaPhotoSend('PersonaGalleryPhoto', 'personaDest','personaScript', UserId,'&plckPhotoID=' +photoid + '&plckFindCommentKey=' +findCommentKey, "widget:personaPhoto");
}
SiteLifeProxy.prototype.PersonaRecentGalleryPhoto = function(UserId) {
    var photoid = gSiteLife.GetParameter('plckPhotoID');
    return this.PersonaPhotoSend('PersonaRecentGalleryPhoto', 'personaDest','personaScript', UserId,'&plckPhotoID=' +photoid);
}

SiteLifeProxy.prototype.LoadPersonaGalleryPage = function(UserId,GalleryID) {
    var params = new Object(); params['plckPersonaPage'] = 'PersonaGallery'; params['plckUserId'] = UserId; 
            params['insiteUserId'] = UserId;
        params['plckGalleryID'] = GalleryID;
    this.ReloadPage(params);
    return false;
}
SiteLifeProxy.prototype.LoadPersonaPhotoPage = function(UserId,PhotoID) {
    var params = new Object(); params['plckPersonaPage'] = 'PersonaGalleryPhoto'; params['plckUserId'] = UserId;
            params['insiteUserId'] = UserId;
        params['plckPhotoID'] = PhotoID;
    this.ReloadPage(params);
    return false;
}
SiteLifeProxy.prototype.LoadPersonaRecentPhotoPage = function(UserId,PhotoID) {
    var params = new Object(); params['plckPersonaPage'] = 'PersonaRecentGalleryPhoto'; params['plckUserId'] = UserId;
            params['insiteUserId'] = UserId;
        params['plckPhotoID'] = PhotoID;
    this.ReloadPage(params);
    return false;
}

var fbHelpDialogTimeout;
SiteLifeProxy.prototype.ShowFacebookHelpDialog = function(icon){
	var x = 0;
	var y = icon.clientHeight/2;

	do {
		x += icon.offsetLeft;
		y += icon.offsetTop;
	}
	while(icon = icon.offsetParent);

	var fb_div = document.getElementById("Persona_FacebookHelpDialog");
	
	fb_div.style.position = "absolute";
	fb_div.style.display = "block";
	
	// position div to the left of icon.
	var newX = x - fb_div.clientWidth;
	var newY = y - Math.floor(fb_div.clientHeight/2);
	
	fb_div.style.left = newX + "px";
	fb_div.style.top = newY + "px";

	return false;
}

SiteLifeProxy.prototype.HideFacebookHelpDialog = function(){
	var fb_div = document.getElementById("Persona_FacebookHelpDialog");
	fb_div.style.display = "none";
}

SiteLifeProxy.prototype.CopyRssUrlToClipboard = function(){	
	rssUrl = document.getElementById("rssUrl");
	copy(rssUrl);
	
	return false;
}

/* note: doesn't work with flash 10 */
function copy(inElement) {
  if (inElement.createTextRange) {
    var range = inElement.createTextRange();
    if (range)
      range.execCommand('Copy');
  } else {
    var flashcopier = 'flashcopier';
    if(!document.getElementById(flashcopier)) {
      var divholder = document.createElement('div');
      divholder.id = flashcopier;
      document.body.appendChild(divholder);
    }
    document.getElementById(flashcopier).innerHTML = '';
    var divinfo = '<embed src="' + gSiteLife.__baseUrl + '/Content/swf/clipboard.swf" FlashVars="clipboard='+encodeURIComponent(inElement.value)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';
    document.getElementById(flashcopier).innerHTML = divinfo;
  }
}

SiteLifeProxy.prototype.UpdateExternalUserId = function(ExternalSiteName, ExternalSiteUserId) {
	var adParam = this.BaseAdParam();
	adParam += "&externalSiteName=" + ExternalSiteName;
	adParam += "&externalSiteUserId=" + ExternalSiteUserId;
	return this.PersonaSend('UpdateExternalUserId', 'personaHDest', 'personaScript', adParam);
}






SiteLifeProxy.prototype.SolicitPhoto = function(galleryID) {
	var elementId = 'plcksolicit' + galleryID;
	this.WriteDiv(elementId);
    var url = this.__baseUrl + '/Photo/SolicitPhoto?plckElementId=' + elementId + '&plckGalleryID=' +galleryID;
    this.__Send(url);
    return false;
}

SiteLifeProxy.prototype.PhotoUpload = function() {
	var elementId = 'plcksubmit';
	this.WriteDiv(elementId);
    var galleryID = gSiteLife.GetParameter('plckGalleryID');

    var url = this.__baseUrl + '/Photo/PhotoUpload?plckElementId=' + elementId + '&plckGalleryID=' +galleryID;
    this.__Send(url);
    return false;
}

SiteLifeProxy.prototype.PublicGallery = function() {
    var elementId = 'plckgallery';
	this.WriteDiv(elementId);
	var galleryID = gSiteLife.GetParameter('plckGalleryID');
    var pageNum = gSiteLife.GetParameter('plckPageNum');
	
    var url = this.__baseUrl + '/Photo/PublicGallery?plckElementId=' + elementId + '&plckGalleryID=' +galleryID + '&plckPageNum=' +pageNum;
	this.__Send(url);
	return false;
}


SiteLifeProxy.prototype.GalleryPhoto = function() {
	var elementId = 'plckphoto';
	this.WriteDiv(elementId);
    var photoid = gSiteLife.GetParameter('plckPhotoID');
    var findCommentKey = gSiteLife.ReadFindCommentKey(null, "widget:galleryPhoto");

    var url = this.__baseUrl + '/Photo/GalleryPhoto?plckElementId=' + elementId + '&plckPhotoID=' +photoid + '&plckFindCommentKey=' + findCommentKey;
	this.__Send(url, null, "widget:galleryPhoto");
	return false;
}

SiteLifeProxy.prototype.PublicGalleries = function() {
	var elementId = 'plckgalleries';
	this.WriteDiv(elementId);
    var pageNum = gSiteLife.GetParameter('plckPageNum') ?  gSiteLife.GetParameter('plckPageNum') : "0";

    var url = this.__baseUrl + '/Photo/PublicGalleries?plckElementId=' + elementId + '&plckPageNum=' + pageNum;
    this.__Send(url);
    return false;
}

SiteLifeProxy.prototype.PhotoRecommend = function(targetid,recommendDiv,isGallery) {
    var url = this.__baseUrl + '/Photo/Recommend?plckElementId=' + recommendDiv + '&plckTargetid=' +targetid + '&plckIsGallery=' +isGallery ;
    this.__Send(url);
    return false;
}

//<script type="text/javascript">

//parentKeyType can be any gSiteLife.KeyType* value, but for including this widget on an article page the value is 
//typically gSiteLife.KeyTypeExternalResource
SiteLifeProxy.prototype.Comments = function(parentKeyType, parentKey, pageSize, sort, showTabs, tab, parentUrl, parentTitle, refreshPage, findCommentKey)
{
	return this.CommentsInternal(parentKeyType, parentKey, pageSize, sort, showTabs, tab, parentUrl, parentTitle, false, false, null, refreshPage, findCommentKey);
};

SiteLifeProxy.prototype.CommentsInput = function(parentKeyType, parentKey, redirectToUrl)
{    
    return this.CommentsInternal(parentKeyType, parentKey, null, "TimeStampDescending", null, null, null, null, true, false, redirectToUrl, false, null);
};

SiteLifeProxy.prototype.CommentsOutput = function(parentKeyType, parentKey, refreshPage, pageSize, sortOrder)
{
    sortOrder = sortOrder || "TimeStampDescending";
	return this.CommentsInternal(parentKeyType, parentKey, pageSize, sortOrder, null, null, null, null, false, true, null, refreshPage, null);
}

SiteLifeProxy.prototype.CommentsRefresh = function(parentKeyType, parentKey, pageSize, sortOrder)
{
    if (!parentKey || parentKey == "") throw "Must pass in value for parentKey!";
    return this.CommentsInternal(parentKeyType, parentKey, pageSize, sortOrder, null, null, null, null, false, false, null, true, null);
}

SiteLifeProxy.prototype.CommentsInternal = function(parentKeyType, parentKey, pageSize, sort, showTabs, tab, parentUrl, parentTitle, hideView, hideInput, redirectToUrl, refreshPage, findCommentKey)
{
    var divId = 'Comments_Container';
    if(this.numCommentsWidgets){ divId += this.numCommentsWidgets++; } else { this.numCommentsWidgets = 1; }
    
    document.write("<div id='" + divId + "'></div>");
    
    return this.GetComments(parentKeyType, parentKey, parentUrl, parentTitle, 0, pageSize, sort, showTabs, tab, hideView, hideInput, redirectToUrl, refreshPage, divId, findCommentKey);
}

SiteLifeProxy.prototype.ReadFindCommentKey = function(plckFindCommentKey, eventName){
	var findCommentKey = plckFindCommentKey || gSiteLife.GetParameter("plckFindCommentKey") || "";
    if(findCommentKey == "none"){
		findCommentKey = "";
    }
    
    if(findCommentKey != "" && eventName){
		this.AddEventHandler(eventName, function(){gSiteLife.ScrollToComment(findCommentKey)});
    }
    
    return findCommentKey;
}

SiteLifeProxy.prototype.GetComments = function(parentKeyType, parentKey, parentUrl, parentTitle, page, pageSize, sort, showTabs, tab, hideView, hideInput, redirectTo, refreshPage, divId, findCommentKey)
{
    parentKeyType = parentKeyType || "ExternalResource";
    parentUrl = parentUrl || gSiteLife.__StripAnchorFromUrl(window.location.href);
    parentUrl = gSiteLife.EscapeValue(parentUrl);
    parentKey = parentKey || gSiteLife.__StripAnchorFromUrl(window.location.href);
    parentTitle = parentTitle || gSiteLife.EscapeValue(gSiteLife.Trim(document.title));
    page = page || gSiteLife.GetParameter('plckCurrentPage') || 0;
    pageSize = pageSize || 10;
    sort = sort || "TimeStampAscending";
    showTabs = showTabs || false;
    tab = tab || "MostRecent";
    hideView = hideView || false;
    hideInput = hideInput || false;
    redirectTo =gSiteLife.EscapeValue(redirectTo) || "";
    refreshPage = refreshPage || false;
    findCommentKey = gSiteLife.ReadFindCommentKey(findCommentKey, "widget:comments");
    
    var url = this.__baseUrl + 
        '/Comment/GetPage.rails?plckTargetKeyType='+ parentKeyType + 
        '&plckTargetKey=' + escape(parentKey) + 
        "&plckCurrentPage=" + page + 
        "&plckItemsPerPage=" + pageSize + 
        "&plckSort=" + sort + 
        "&plckElementId=" + divId +
        "&plckTargetUrl=" + parentUrl +
        "&plckTargetTitle=" + parentTitle +
        "&plckHideView=" + hideView +
        "&plckHideInput=" + hideInput +
        "&plckRefreshPage=" + refreshPage +
        "&plckRedirectToUrl=" + redirectTo +
        "&plckFindCommentKey=" + findCommentKey;

    if (showTabs) {
        url = url + "&plckShowTabs=true&plckTab=" + tab;
    }
    this.__Send(url, null, "widget:comments");
    return false;
};

SiteLifeProxy.prototype.WaitForImages = function(callback){
	var allImgs = document.images;
	
}

SiteLifeProxy.prototype.ScrollToComment = function(commentKey){
		setTimeout(function(){
		window.location.hash = "#" + commentKey;
	}, 300);
}

SiteLifeProxy.prototype.Blog = function(BlogId) {
    this.WriteDiv("blogDest", "Persona_Main");
    var action = this.GetParameter("plckBlogPage");
    // If BlogId was not explicitly stated, grab it from the URL parameter...
    if(!BlogId){
		BlogId = this.GetParameter('plckBlogId');
    }
    
        
	if(action && action != "Blog" && (typeof this[action] == 'function')){
	 return this[action](BlogId);
	}else{
	   var AdParams = this.GetParameter('plckCurrentPage') ? 'plckCurrentPage=' + this.GetParameter('plckCurrentPage') : "";
	   return this.BlogSend('Blog', 'Blog', 'blogDest', 'blogScript', BlogId, AdParams);
	}
}
SiteLifeProxy.prototype.LoadBlogPage = function(PageName, BlogId) {
    var params = new Object(); params['plckBlogPage'] = PageName; params['plckBlogId'] = BlogId; 
    for(ii=2; ii< this.LoadBlogPage.arguments.length; ii+=2) { params[this.LoadBlogPage.arguments[ii]] = this.LoadBlogPage.arguments[ii+1];}
    this.ReloadPage(params);
    return false;
}

SiteLifeProxy.prototype.BlogViewEdit = function(blogId) {
   return this.BlogSend(null, 'BlogViewEdit', null, null, blogId);
}

SiteLifeProxy.prototype.BlogPostCreate = function(blogId) {
   return this.BlogSend(null, 'BlogPostCreate', null, null, blogId, 'plckRedirectUrl=' + this.GetParameter("plckRedirectUrl"));
}

SiteLifeProxy.prototype.BlogPendingComments = function(blogId, currentPage) {
   if( !currentPage) currentPage = 0;
   return this.BlogSend(null, 'BlogPendingComments', null, null, blogId, 'plckCurrentPage='+currentPage);
}

SiteLifeProxy.prototype.BlogSettings = function(blogId) {
   return this.BlogSend(null, 'BlogSettings', null, null, blogId);
}

SiteLifeProxy.prototype.BlogEditPost = function(blogId, controller, div, script, postId, selection, daysBack) {
	return this.BlogSend(controller, 'BlogPostEdit', div, script, blogId, 'plckPostId=' + postId + '&plckSelection=' + selection + '&plckDaysBack=' + daysBack + '&plckRedirectUrl=' + this.EscapeValue(window.location.href));
}

SiteLifeProxy.prototype.BlogRemovePost = function(blogId, controller, div, script, postId, selection, daysBack, confirmMsg) {
  if (confirm(confirmMsg) == true) {
    return this.BlogSend(controller, 'BlogRemovePost', div, script, blogId, 'plckPostId=' + postId + '&plckSelection=' + selection + '&plckDaysBack=' + daysBack );
  }
  return false;
}

SiteLifeProxy.prototype.BlogViewPost = function(blogId, postId, selection, daysBack) {
    if(!postId ) { postId = gSiteLife.GetParameter('plckPostId'); }
    var findCommentKey = gSiteLife.ReadFindCommentKey(null, "widget:blog");
	return this.BlogSend(null, 'BlogViewPost', null, null, blogId, 'plckPostId=' + postId + '&plckSelection=' + selection + '&plckDaysBack=' + daysBack + '&plckCommentSortOrder=' + this.GetParameter('plckCommentSortOrder') + '&plckFindCommentKey=' + findCommentKey);
}

SiteLifeProxy.prototype.BlogViewMonth = function(blogId, monthId) {
	if(!monthId ) { monthId = gSiteLife.GetParameter('plckMonthId'); }
	var AdParams = 'plckMonthId=' + monthId;
	AdParams += this.GetParameter('plckCurrentPage') ? '&plckCurrentPage=' + this.GetParameter('plckCurrentPage') : "";
	return this.BlogSend(null, 'BlogViewMonth', null, null, blogId,  AdParams);
}

SiteLifeProxy.prototype.AddBlogWatchItem= function(blogId, controller, script, Url, WatchKey) {
   return this.BlogSend(controller, 'AddBlogWatch', 'plckBlogWatchDiv', script, blogId, 'plckWatchKey=' + WatchKey + '&plckWatchUrl=' + this.EscapeValue(Url));
}
SiteLifeProxy.prototype.RemoveBlogWatchItem= function(blogId, controller, script, WatchKey) {
   return this.BlogSend(controller, 'RemoveBlogWatch', 'plckBlogWatchDiv', script, blogId, 'plckWatchKey=' + WatchKey);
}

SiteLifeProxy.prototype.BlogViewTag = function(blogId, tag) {
	if(!tag ) { tag = gSiteLife.GetParameter('plckTag'); }
	var AdParams = 'plckTag=' + tag;
	AdParams += this.GetParameter('plckCurrentPage') ? '&plckCurrentPage=' + this.GetParameter('plckCurrentPage') : "";
	return this.BlogSend(null, 'BlogViewTag', null, null, blogId, AdParams );
}

SiteLifeProxy.prototype.BlogRefreshViewEditList= function(blogId, controller, div, script, selection, daysBack) {
	return this.BlogSend(controller, 'BlogRefreshViewEditList', div, script, blogId, 'plckSelection=' + selection + '&plckDaysBack=' + daysBack  );
}

SiteLifeProxy.prototype.BlogSend = function(controller, apiName, destDiv, scriptName, blogId, addParams){
    if(!controller) controller = this.GetParameter('plckController') || "Blog";
    if(!destDiv) destDiv = this.GetParameter('plckElementId') || "blogDest";
    if(!scriptName) scriptName = this.GetParameter('plckScript') || "blogScript";
    var url = this.__baseUrl + '/' + controller + '/' + apiName + '?plckElementId=' + destDiv + '&plckBlogId=' + blogId + '&' + addParams;
    this.__Send(url, scriptName, 'widget:blog');
    return false;
}

SiteLifeProxy.prototype.Recommend = function(controller, itemId, recommendDiv) {
    var url = this.__baseUrl + '/' + controller + '/Recommend?plckElementId=' + recommendDiv + '&plckItemId=' +itemId;
    this.__Send(url);
    return false;
}
SiteLifeProxy.prototype.BlogSelectPendingComments = function(formId, checked) {   
    var form = document.getElementById(formId);
    for (i=0; i<form.elements.length; i++) {
        var input = form.elements[i];        
        input.checked = checked;
    }
}

SiteLifeProxy.prototype.Forums = function(numPerPage) {    
	this.WriteDiv("forumDest", "Forum_Main");
	
	var action = this.GetParameter("plckForumPage");
		
		
	var forumId = this.GetParameter('plckForumId');        
	if (forumId)
	{
		forumId = unescape(forumId);
		var i = forumId.indexOf('Forum:');
		forumId = forumId.substring(i).replace(':', '_');    
	}
	else
	{
		var discussionId = this.GetParameter('plckDiscussionId');
		if (discussionId)
		{                    
			discussionId = unescape(discussionId);
			var i = discussionId.indexOf('Forum:');
			var j = discussionId.indexOf('Discussion:');
			forumId = discussionId.substring(i, j).replace(':', '_');
		}
	}
    
	var categoryCurrentPage = this.GetParameter('plckCategoryCurrentPage');
	if(action && (typeof this[action] == 'function') && action != 'ForumCategories'){
		this[action]();
	}
	else {     
		if( numPerPage == null ){
			numPerPage = this.GetParameter('plckNumPerPage');
		}
		this.ForumCategories(numPerPage, categoryCurrentPage);
	}
}

SiteLifeProxy.prototype.SetupCallbacks = function(){
	var adParam = "";
    var showFirstUnread = this.GetParameter('plckShowFirstUnread'); 
    var findPostKey = this.GetParameter('plckFindPostKey');
    if(showFirstUnread != null){
		adParam += "&plckShowFirstUnread=" + showFirstUnread;
		this.AddEventHandler("widget:forums", function(){gSiteLife.DiscussionScrollToPost()});
    }
    if(findPostKey != null && findPostKey != ""){
		adParam += "&plckFindPostKey=" + findPostKey;
		this.AddEventHandler("widget:forums", function(){gSiteLife.DiscussionScrollToPost()});
    }
    var showLatestPost = this.GetParameter('plckShowLatestPost'); 
    if(showLatestPost != null){
		adParam += "&plckShowLatestPost=" + showLatestPost;
		this.AddEventHandler("widget:forums", function(){gSiteLife.DiscussionScrollToPost()});
    }
    
    this.AddEventHandler("widget:forums", function(){
		gSiteLife.DiscussionScanForUnread();

		// insert poll widget if the discussion is a poll		

		var me = this;
		var insertPoll = function(retryCount) {
			if (retryCount > 10) {
				return;
			}
			if (typeof(retryCount) === 'undefined') {
				retryCount = 0;
			}
			var pollWidgetDiv = document.getElementById('Discussion_Poll_Container');
			if (pollWidgetDiv) {
				var discussionKey = document.getElementById('DiscussionKeyContainer').value;
				slGetDiscussionPollOnKey = function() {
					return discussionKey;
				}
				window.slPollWidgetDiv = document.getElementById('Discussion_Poll');
				var pollInsertionScript = document.createElement('script');
				pollInsertionScript.type = 'text/javascript';
				pollInsertionScript.src = 'http://pluckdev.thesunnews.com/ver1.0/Forums/PollParams?plckDiscussionId=' + discussionKey;
				document.getElementsByTagName('head')[0].appendChild(pollInsertionScript);
			}
			else {
				setTimeout(function() {
					insertPoll(retryCount + 1);
				}, 100);
			}
		}
		insertPoll();

    	});
    
    return adParam;
}

SiteLifeProxy.prototype.ForumCategories = function(numPerPage, categoryCurrentPage) {
    var pageNum = this.GetParameter('plckCurrentPage'); if(pageNum == null) pageNum = 0;
    var urlPageInfoStr = '';
    urlPageInfoStr = '&plckNumPerPage=' + numPerPage;        
    urlPageInfoStr += '&plckCategoryCurrentPage=' + categoryCurrentPage;            
    return this.ForumSend("ForumCategories", "forumDest", "ForumMain", 'plckCurrentPage=' + pageNum + urlPageInfoStr);
}
SiteLifeProxy.prototype.Forum = function() {
    var forumId = this.GetParameter('plckForumId');
    var categoryPageNum = this.GetParameter('plckCategoryCurrentPage');
    if(categoryPageNum == null) { categoryPageNum = 0; }
    var discussionPageNum = this.GetParameter('plckCurrentPage');
    if (discussionPageNum == null) { discussionPageNum = 0; }
    var numPerPage = this.GetParameter('plckNumPerPage');
    var urlPageInfoStr = '';
    if( numPerPage != null ){
        urlPageInfoStr = '&plckNumPerPage=' + numPerPage;
    }
   return this.ForumSend('Forum', 'forumDest', 'ForumMain', 'plckForumId=' + forumId + '&plckCurrentPage=' + discussionPageNum + '&plckCategoryCurrentPage=' + categoryPageNum + urlPageInfoStr );
}
SiteLifeProxy.prototype.ForumDiscussion = function() {
    var dId = this.GetParameter("plckDiscussionId");
    var adParam = "plckDiscussionId=" + dId;
    var showLast = this.GetParameter("plckShowLastPage"); if(showLast) adParam += "&plckShowLastPage=true";
    var pageNum = this.GetParameter('plckCurrentPage'); if(pageNum == null) pageNum = 0;
	adParam += this.SetupCallbacks(); 
    adParam += "&plckCurrentPage=" + pageNum;
    adParam += "&plckCategoryCurrentPage=" + this.GetParameter('plckCategoryCurrentPage');   
    
    return this.ForumSend("ForumDiscussion", "forumDest", "ForumMain", adParam);
}

SiteLifeProxy.prototype.DiscussionScanForUnread = function(discussionKey){
	var postDatesContainer = document.getElementById("PostDateInfoContainer");
	if(!postDatesContainer){
		return;
	}
	
	this.postDates = eval(postDatesContainer.value);
	this.latestPost = new Date(document.getElementById("LastReadContainer").value);
	this.screenBottom = 0;
	if(discussionKey){
		this.discussionKey = discussionKey;
	}
	else if (document.getElementById('DiscussionKeyContainer')){
		this.discussionKey = document.getElementById('DiscussionKeyContainer').value;
	}
	
	this.checkForReadInterval = setInterval(function(){gSiteLife.DiscussionCheckForLatestPost();}, 1000);
}

SiteLifeProxy.prototype.DiscussionScrollToPost = function(){
	if(!document.getElementById("Discussion_ScrollToPostKey")){
		return false;
	}
	
	var postKey = document.getElementById("Discussion_ScrollToPostKey").value;
	var post = document.getElementById(postKey);
	
	if(!post){
		return false;
	}
	
	var postTop = 0;
	if(post.offsetParent){
		obj = post;
		do{
			postTop += obj.offsetTop;
		}
		while(obj = obj.offsetParent);
		window.scrollBy(0, postTop);
	}
}

SiteLifeProxy.prototype.IsPostOnScreen = function(screenBottom, postIndex){
	var postId = "readIndicator_" + this.postDates[postIndex].Key;
	var post = document.getElementById(postId);
	if(post){
		var postTop = 0;
		if(post.offsetParent){
			obj = post;
			do{
				postTop += obj.offsetTop;
			}
			while(obj = obj.offsetParent);
		}
		var postBottom = postTop + post.offsetHeight;
		
		if(postBottom < screenBottom){
			return true;
		}
	}
	
	return false;
}

SiteLifeProxy.prototype.DiscussionCheckForLatestPost = function(){
	var screenTop = 0;
	if (typeof(window.pageYOffset) !== 'undefined') {
		screenTop = window.pageYOffset;
	}
	else if (typeof(document.body.scrollTop) !== 'undefined') {
		screenTop = document.body.scrollTop;
	}
	else if (typeof(document.documentElement) !== 'undefined' && typeof(document.documentElement.scrollTop) !== 'undefined') {
		screenTop = document.documentElement.scrollTop;
	}
	
	var screenBottom = Math.pow(2,52); /*Supposing our browser can't get the height, we mark everything as read.*/
	if(window.innerHeight){
		screenBottom = screenTop + window.innerHeight;
	}
	else if(document.documentElement.clientHeight && document.documentElement.clientHeight != 0){
		screenBottom = screenTop + document.documentElement.clientHeight;
	}
	else if(document.body.clientHeight){
		screenBottom = screenTop + document.body.clientHeight;
	}
	
	/* Only update if we've scrolled down since last poll. */
	if(screenBottom <= this.screenBottom){
		return;
	}
	
	/* Just give up if there are no posts. */
	if(!this.postDates || this.postDates.length <= 0){
		clearInterval(this.checkForReadInterval);
		return;
	}
	
	/* If the last post is already marked read, don't bother polling. */
	if(this.postDates[(this.postDates.length - 1)].Timestamp <= this.latestPost){
		clearInterval(this.checkForReadInterval);
		return;
	}
	
	this.screenBottom = screenBottom;
	
	var latestKey = null;
	
	for(i=0; i < this.postDates.length; i++){
		if(this.IsPostOnScreen(screenBottom, i)){
			if(this.postDates[i].Timestamp >= this.latestPost){
				latestKey = this.postDates[i].Key;
				this.latestPost = this.postDates[i].Timestamp;
			}
		}
	}

	if(latestKey){
		this.ForumSetLastRead(this.discussionKey, latestKey);
	}
}

SiteLifeProxy.prototype.ForumCreateDiscussion = function() {
    var adParam = "plckRedirectUrl=" + this.GetParameter("plckRedirectUrl");
    var fId = this.GetParameter("plckForumId"); adParam += "&plckForumId=" + fId;
    var curView = this.GetParameter("plckCurrentView"); if(curView) adParam += "&plckCurrentView=" + curView;
    var curPage = this.GetParameter("plckCurrentPage"); if(curPage) adParam += "&plckCurrentPage=" + curPage;
    var dId = this.GetParameter("plckDiscussionId"); if(dId) adParam += "&plckDiscussionId=" + dId;
    adParam += "&plckCategoryCurrentPage=" + this.GetParameter('plckCategoryCurrentPage');    
    return this.ForumSend("ForumCreateDiscussion", "forumDest", "ForumMain", adParam);
}
SiteLifeProxy.prototype.ForumMain = function() {
    return this.ForumSend("ForumMain", "forumDest", "ForumMain");
}
SiteLifeProxy.prototype.ForumCreatePost = function() {
    var adParam = "plckDiscussionId=" + this.GetParameter("plckDiscussionId") + "&plckRedirectUrl=" + this.EscapeValue(window.location.href);
    var PostId = this.GetParameter("plckPostId"); if(PostId) adParam = adParam + "&plckPostId=" + PostId;
    var IsReply = this.GetParameter("plckIsReply"); if(IsReply) adParam = adParam + "&plckIsReply=" + IsReply;
    var curPage = this.GetParameter("plckCurrentPage"); if(curPage) adParam = adParam + "&plckCurrentPage=" + curPage;
    adParam += "&plckCategoryCurrentPage=" + this.GetParameter("plckCategoryCurrentPage"); 
    return this.ForumSend("ForumCreatePost", "forumDest", "ForumMain", adParam);
}
SiteLifeProxy.prototype.ForumEditPost = function() {
    var adParam = "plckDiscussionId=" + this.GetParameter("plckDiscussionId") + "&plckRedirectUrl=" + this.EscapeValue(window.location.href);
    var PostId = this.GetParameter("plckPostId"); if(PostId) adParam = adParam + "&plckPostId=" + PostId;
    var CurrPage = this.GetParameter("plckCurrentPage"); if(!CurrPage) CurrPage="0"; adParam = adParam + "&plckCurrentPage=" + CurrPage;
    adParam += "&plckCategoryCurrentPage=" + this.GetParameter('plckCategoryCurrentPage');    
    return this.ForumSend("ForumEditPost", "forumDest", "ForumMain", adParam);
}
SiteLifeProxy.prototype.ForumEditProfile = function() {
    return this.ForumSend("ForumEditProfile", "forumDest", "ForumMain", "plckRedirectUrl=" + this.EscapeValue(window.location.href));
}
SiteLifeProxy.prototype.ToggleExpand = function(imageId, tableId) {
  if (!this.collapsedCategories) {
    var cookie = document.cookie && document.cookie.match(/forumCatState=([^;]+)/); 
    cookie = (cookie ? cookie[1].replace(/^\s+|\s+$/g, '') : []); 
    this.collapsedCategories = (cookie.length ? unescape(cookie).split('|') : []);
  }
  var tableElem = document.getElementById(tableId), imgElem = document.getElementById(imageId),
      id = tableId.split(':')[1], cats = this.collapsedCategories, expire;
  if (tableElem.style.display == 'none') {
    tableElem.style.display = 'block';
    imgElem.src = this.__baseUrl + '/Content/images/forums/minus.gif';
    for (var i = 0, length = cats.length; i < length; i++) {
      if ((cats[i] == id) || (cats[i] === ''))
        cats.splice(i,1);
    }
  }
  else {
    tableElem.style.display = 'none';
    cats.push(id); 
    imgElem.src = this.__baseUrl + '/Content/images/forums/plus.gif';
  }
  this.SetCookie('forumCatState', cats.join('|'));
}

SiteLifeProxy.prototype.ForumSearch = function(suffix) {
    var searchText = document.getElementById('plckSearchText'+suffix).value;
    searchText = FixSearchString(searchText);
    var searchArea = document.getElementById('plckSearchArea'+suffix).value;
    this.LoadForumPage("ForumSearchPaginate", "plckSearchText", searchText, "plckSearchArea", searchArea, "plckCurrentPage", "0");
    return false;
}
SiteLifeProxy.prototype.ForumSearchKeyPress = function(event, suffix) {
    if(IsEnter(event)){return this.ForumSearch(suffix);}else{return true;}
}
SiteLifeProxy.prototype.ForumSearchPaginate = function() {	
    return this.ForumSend('ForumSearchPaginate', 'forumDest', 'ForumMain', 'plckSearchArea=' + this.GetParameter('plckSearchArea') + '&plckSearchText=' + this.GetParameter('plckSearchText') + '&plckCurrentPage=' + this.GetParameter('plckCurrentPage'));
}

SiteLifeProxy.prototype.ForumSpecificForumSearchKeyPress = function(event, suffix, forumId) {
    if(IsEnter(event)){return this.ForumSpecificForumSearch(suffix, forumId);}else{return true;}
}
SiteLifeProxy.prototype.ForumSpecificForumSearch = function(suffix, forumId) {
    var searchText = document.getElementById('plckSearchText'+suffix).value;
    searchText = FixSearchString(searchText);
    this.LoadForumPage("ForumSearchSpecificForumPaginate", "plckSearchText", searchText, "plckForumId", forumId, "plckCurrentPage", "0");
    return false;
}
SiteLifeProxy.prototype.ForumSearchSpecificForumPaginate = function(title) {	
    return this.ForumSend('ForumSearchSpecificForumPaginate', 'forumDest', 'ForumMain', 'plckForumId=' + this.GetParameter('plckForumId') + '&plckSearchText=' + this.GetParameter('plckSearchText') + '&plckCurrentPage=' + this.GetParameter('plckCurrentPage'));
}

SiteLifeProxy.prototype.LoadForumPage = function(PageName, paramName, paramVal) {
    var params = new Object(); 
    params['plckForumPage'] = PageName;
    for(ii=1; ii< this.LoadForumPage.arguments.length; ii+=2) { params[this.LoadForumPage.arguments[ii]] = this.LoadForumPage.arguments[ii+1];}
    this.ReloadPage(params);
    return false;
}

SiteLifeProxy.prototype.ForumSend = function(ApiName, DestDiv, ScriptName, AddParams){
    var url = this.__baseUrl + '/Forums/' + ApiName + '?plckElementId=' + DestDiv;
    if(AddParams) url += '&' + AddParams;
    var plckPostSort = this.GetParameter('plckPostSort');
    if (plckPostSort != null){
		url += "&plckPostSort=" + plckPostSort;
	}
    this.__Send(url, ScriptName, 'widget:forums', arguments);
    return false;
}

SiteLifeProxy.prototype.ForumDiscussionEdit = function(discussionId, curView, curPage) {
    return this.ForumSend('ForumDiscussionEdit', 'forumDest', 'ForumMain', 'plckDiscussionId=' + discussionId + '&plckCurrentView=' + curView + '&plckCurrentPage=' + curPage + '&plckRedirectUrl=' + this.EscapeValue(window.location.href));
}

SiteLifeProxy.prototype.ForumPostEdit = function(discussionId, postId, curView, curPage) {
    return this.ForumSend('ForumEditPost', 'forumDest', 'ForumMain', 'plckDiscussionId=' + discussionId + '&plckPostId=' + postId + '&plckCurrentView=' + curView + '&plckCurrentPage=' + curPage + '&plckRedirectUrl=' + this.EscapeValue(window.location.href));
}

SiteLifeProxy.prototype.ForumDiscussionToggleIsSticky = function(discussionId, curView, curPage) {
	return this.ForumSend('ForumDiscussionToggleIsSticky', 'forumDest', 'ForumMain', 'plckDiscussionId=' + discussionId + '&plckCurView=' + curView + '&plckCurrentPage=' + curPage);
}

SiteLifeProxy.prototype.ForumDiscussionToggleIsClosed = function(discussionId, curView, curPage) {
    return this.ForumSend('ForumDiscussionToggleIsClosed', 'forumDest', 'ForumMain', 'plckDiscussionId=' + discussionId + '&plckCurView=' + curView + '&plckCurrentPage=' + curPage );
}

SiteLifeProxy.prototype.ForumDiscussionDelete = function(discussionId, curPage, confirmMsg) {
  if (confirm(confirmMsg) == true) {
    return this.ForumSend('ForumDiscussionDelete', 'forumDest', 'ForumMain', 'plckDiscussionId=' + discussionId + '&plckCurrentPage=' + curPage );
  }
  else {
	return false;
  }
}

SiteLifeProxy.prototype.MoveDiscussion = function(discussionKey, toForum, curView, curPage) {
    return this.ForumSend('MoveDiscussion', 'forumDest', 'ForumMain', 'discussionKey=' + discussionKey + '&toForum=' + toForum + '&plckCurView=' + curView + '&plckCurrentPage=' + curPage );
}

SiteLifeProxy.prototype.ForumEdit = function(forumId, curPage) {
    return this.ForumSend('ForumEdit', 'forumDest', 'ForumMain', 'plckForumId=' + forumId + '&plckCurrentPage=' + curPage  );
}

SiteLifeProxy.prototype.ForumToggleIsClosed = function(forumId, curPage) {
    return this.ForumSend('ForumToggleIsClosed', 'forumDest', 'ForumMain', 'plckForumId=' + forumId + '&plckCurrentPage=' + curPage  );
}

SiteLifeProxy.prototype.ForumDelete = function(forumId, confirmMsg) {
  if (confirm(confirmMsg) == true) {
    return this.ForumSend('ForumDelete', 'forumDest', 'ForumMain', 'plckForumId=' + forumId );
  }
  else {
	return false;
  }
}

SiteLifeProxy.prototype.ForumPostDelete = function(postId, curPage, confirmMsg) {
  if (confirm(confirmMsg) == true) {
    return this.ForumSend('ForumPostDelete', 'forumDest', 'ForumMain', 'plckPostId=' + postId + '&plckCurPage=' + curPage);
  }
  else {
	return false;
  }
}

SiteLifeProxy.prototype.ForumBlockUser = function(postId, userId, value, curPage) {
    return this.ForumSend('ForumBlockUser', 'forumDest', 'ForumMain', 'plckPostId=' + postId + '&plckUserId=' + userId + '&plckValue=' + value + '&plckCurPage=' + curPage);
}

SiteLifeProxy.prototype.ForumMyDiscussionsPaginate = function(pageNum) {
    return this.ForumSend('ForumMyDiscussionsPaginate', 'ForumMyDiscussionsDiv', 'ForumMain', 'plckMyDiscussionsPage=' + pageNum);
}

SiteLifeProxy.prototype.ForumImage = function() {
    var adParam = "plckRedirectUrl=" + this.GetParameter("plckRedirectUrl");
    var pId = this.GetParameter("plckPhotoId"); adParam += "&plckPhotoId=" + pId;
    return this.ForumSend('ForumImage', 'forumDest', 'ForumMain', adParam);
}

SiteLifeProxy.prototype.BaseAdParam = function () {
    var adParam = "plckRedirectUrl=" + this.EscapeValue(window.location.href);
    var fId = this.GetParameter("plckForumId"); adParam += "&plckForumId=" + fId;
    var curView = this.GetParameter("plckCurrentView"); if(curView) adParam += "&plckCurrentView=" + curView;
    var curPage = this.GetParameter("plckCurrentPage"); if(curPage) adParam += "&plckCurrentPage=" + curPage;
    return adParam;
}

SiteLifeProxy.prototype.ForumJoinGroup = function() {
    var adParam = this.BaseAdParam();
    var dId = this.GetParameter("plckDiscussionId"); if(dId) adParam += "&plckDiscussionId=" + dId;
    return this.ForumSend("ForumJoinGroup", "forumDest", "ForumMain", adParam);
}

SiteLifeProxy.prototype.ForumLeaveGroup = function() {
    var adParam = this.BaseAdParam();
    var dId = this.GetParameter("plckDiscussionId"); if(dId) adParam += "&plckDiscussionId=" + dId;
    return this.ForumSend("ForumLeaveGroup", "forumDest", "ForumMain", adParam);
}

SiteLifeProxy.prototype.ForumGroupMemberList = function() {
    var adParam = this.BaseAdParam();
    return this.ForumSend("ForumGroupMemberList", "forumDest", "ForumMain", adParam);
}

SiteLifeProxy.prototype.ForumInviteUser = function() {
    var adParam = this.BaseAdParam();
    return this.ForumSend("ForumInviteUser", "forumDest", "ForumMain", adParam);
}

SiteLifeProxy.prototype.ForumGroupConfirm = function() {
    var adParam = this.BaseAdParam();
    var confirmType = this.GetParameter("plckConfirmType"); if (confirmType) adParam += "&plckConfirmType=" + confirmType;
    return this.ForumSend("ForumGroupConfirm", "forumDest", "ForumMain", adParam);
}

SiteLifeProxy.prototype.ForumSendInviteToUser = function(username, email) {
    var adParam = this.BaseAdParam();
    var username = this.GetParameter("plckUsername"); if (username) adParam += "&plckUsername=" + username;
    var email = this.GetParameter("plckUserEmail"); if (email) adParam += "&plckUserEmail" + email;
    return this.ForumSend("ForumSendInviteToUser", "forumDest", "ForumMain", adParam);
}

SiteLifeProxy.prototype.ForumAddEnemy = function(enemyKey) {
    var adParam = this.BaseAdParam();
    adParam += "&enemyKey=" + enemyKey;
    var dId = this.GetParameter("plckDiscussionId"); if(dId) adParam += "&plckDiscussionId=" + dId;
    return this.ForumSend("ForumAddEnemy", "forumDest", "ForumMain", adParam);
}

SiteLifeProxy.prototype.ForumRemoveEnemy = function(enemyKey) {
    var adParam = this.BaseAdParam();
    adParam += "&enemyKey=" + enemyKey;
    var dId = this.GetParameter("plckDiscussionId"); if(dId) adParam += "&plckDiscussionId=" + dId;
    return this.ForumSend("ForumRemoveEnemy", "forumDest", "ForumMain", adParam);
}

function slGetElementsByClassName(classname, node)  {
    if(!node) node = document.getElementsByTagName("body")[0];
    var a = [];
    var re = new RegExp('\\b' + classname + '\\b');
    var els = node.getElementsByTagName("*");
    for(var i=0,j=els.length; i<j; i++)
        if(re.test(els[i].className))a.push(els[i]);
    return a;
}

	function hideAllPostsFromUser(userKey){
	  var posts = slGetElementsByClassName("postVisibilityContainer_"+userKey, document);
	  var hiddenMessages = slGetElementsByClassName("postHiddenMessage_"+userKey, document);
	  
	  for(i=0; i < posts.length; i++){
	    posts[i].style.display = "none";
	    hiddenMessages[i].style.display = "block";
	  }
	  
	  gSiteLife.ForumAddEnemy(userKey);
	}
	
	function showAllPostsFromUser(userKey){
	  var posts = slGetElementsByClassName("postVisibilityContainer_"+userKey, document);
	  var hiddenMessages = slGetElementsByClassName("postHiddenMessage_"+userKey, document);
	  	  
	  for(i=0; i < posts.length; i++){
	    posts[i].style.display = "block";
	    hiddenMessages[i].style.display = "none";
	  }
	  
	  gSiteLife.ForumRemoveEnemy(userKey);
	}
	
SiteLifeProxy.prototype.ForumChangeSort = function(sortParamName, sortDirection) {
		var currentUrl = document.location.href;
		var newUrl;
		// replace the sort param in the url, if found
		var re = new RegExp("([?|&])" + sortParamName + "=.*?(&|$)","i");
		if (currentUrl.match(re)) {
			newUrl = currentUrl.replace(re, '$1' + sortParamName + "=" + sortDirection + '$2');
		}
		else {
			if(currentUrl.indexOf('?') >= 0){
				newUrl = currentUrl + '&' + sortParamName + "=" + sortDirection;
			}
			else{
				newUrl = currentUrl + '?' + sortParamName + "=" + sortDirection;
			}
		}
		document.location.href = newUrl;
}

SiteLifeProxy.prototype.ForumSetLastRead = function(discussionKey, postKey) {
    var adParam = this.BaseAdParam();
    adParam += "&discussionKey=" + discussionKey;
    if(postKey){
		adParam += "&postKey=" + postKey;
	}
    var ret = this.ForumSend("ForumSetLastRead", "forumDest", "ForumMain", adParam);
    
    if(!postKey){
		location.reload();
    }
    
    return ret;
} 

SiteLifeProxy.prototype.ForumDiscussionSubscribe = function(discussionKey, targetDiv) {
    var url = this.__baseUrl + '/Forums/ForumDiscussionSubscribe?' + 'plckDiscussionId=' + discussionKey + '&plckElementId=' + targetDiv;
    this.__Send(url, "ForumDiscussionSubscribe");
    return false;
}

SiteLifeProxy.prototype.ForumDiscussionUnSubscribe = function(discussionKey, targetDiv) {
    var url = this.__baseUrl + '/Forums/ForumDiscussionUnSubscribe?' + 'plckDiscussionId=' + discussionKey + '&plckElementId=' + targetDiv;
    this.__Send(url, "ForumDiscussionUnSubscribe");
    return false;
}


SiteLifeProxy.prototype.Recommend = function(keyType, targetKey, parentUrl) {
    keyType = keyType || "ExternalResource";
    targetKey = targetKey || gSiteLife.__StripAnchorFromUrl(window.location.href);
    parentUrl = parentUrl || window.location.href;
    targetKey = targetKey;
    var divId = "Recommend" + new Date().getTime();
    this.WriteDiv(divId, "Recommend");
    var url = this.__baseUrl + 
        '/Recommend/Recommend?plckElementId=' + divId + 
        '&plckTargetKey=' + gSiteLife.EscapeValue(targetKey) + 
        '&plckTargetKeyType=' + keyType +
        '&plckTargetUrl=' + gSiteLife.EscapeValue(parentUrl);
    this.__Send(url);
    return false;   
}

SiteLifeProxy.prototype.PostRecommendation = function(keyType, targetKey, recommendDiv, parentTitle, parentUrl) {
    parentUrl = parentUrl || window.location.href;
    var url = this.__baseUrl + 
        '/Recommend/PostRecommendation?plckElementId=' + recommendDiv + 
        '&plckTargetKey=' + gSiteLife.EscapeValue(targetKey) + 
        '&plckTargetKeyType=' + keyType +
        '&plckTargetUrl=' + gSiteLife.EscapeValue(parentUrl);
    if(parentTitle) url += '&plckParentTitle=' + gSiteLife.EscapeValue(parentTitle);
    
    this.__Send(url);
    return false;
}


SiteLifeProxy.prototype.RateItem = function (itemId, itemType, rating, targetDiv, parentTitle, parentUrl) {
    var url = this.__baseUrl + '/Rating/Rate?plckElementId=' + targetDiv + 
        '&plckTargetKey=' + gSiteLife.EscapeValue(itemId) + 
        '&plckTargetKeyType=' + itemType + 
        '&plckRating=' + rating +
        '&plckTargetUrl=' + gSiteLife.EscapeValue(parentUrl);
        if(parentTitle) url += '&plckParentTitle=' + parentTitle;
    this.__Send(url);
    return false;
}

SiteLifeProxy.prototype.Rating = function(itemType, itemId, parentUrl) {
    itemType = itemType || "ExternalResource";
    itemId = itemId || gSiteLife.__StripAnchorFromUrl(window.location.href);
    parentUrl = parentUrl || window.location.href;
    var divId = itemId + "_plckRateDiv_" + new Date().getTime() + Math.floor(Math.random()*1000);
    this.WriteDiv(divId, "Rating");
    var url = this.__baseUrl + '/Rating/GetRating?plckElementId=' + divId +
        '&plckTargetKey=' + gSiteLife.EscapeValue(itemId) + 
        '&plckTargetKeyType=' + itemType +
        '&plckTargetUrl=' + gSiteLife.EscapeValue(parentUrl);
    this.__Send(url);
    return false;   
}

SiteLifeProxy.prototype.RatingClickStar = function (index, targetKey, targetKeyType, targetDiv, parentTitle, parentUrl) {
    gSiteLife.RateItem(targetKey, targetKeyType, index, targetDiv, parentTitle, parentUrl);
    
}

SiteLifeProxy.prototype.RatingFillStar = function(index, targetKey, lbl) {
    var stars = document.getElementsByName(targetKey+"Stars");
    var label = document.getElementById(targetKey + "Rating-label");
    var selectedIndex = parseInt(document.getElementById(targetKey+"Rating-value").value);
    
    if (index < 0 && selectedIndex >= 0) index = selectedIndex;
    for(i=1; i <= stars.length; i++) {
        if (index > 0 && i <= index) {
            stars[i-1].src = this.__baseUrl + "/Content/images/icons/fullstar.gif";
        }else {
            stars[i-1].src = this.__baseUrl + "/Content/images/icons/emptystar.gif";
        }
    }
    label.innerHTML = lbl;
}

SiteLifeProxy.prototype.Review = function(parentKeyType, parentKey, reviewedTitle, reviewCategory, pageSize, sort, currentPage) {
    
    var divId = "Reviews_Container";
    this.WriteDiv(divId);
    return this.GetReviews(parentKeyType, parentKey, reviewedTitle, reviewCategory, pageSize, sort, currentPage);
}

SiteLifeProxy.prototype.ReviewClickStar = function (index, targetKey) {
    document.getElementById(targetKey+"Rating-value").value = index;
}

SiteLifeProxy.prototype.GetReviews = function(parentKeyType, parentKey, reviewedTitle, reviewCategory, pageSize, sort, currentPage) {
    parentKeyType = parentKeyType || "ExternalResource";
    parentKey = gSiteLife.EscapeValue(parentKey) || gSiteLife.EscapeValue(gSiteLife.__StripAnchorFromUrl(window.location.href));
    reviewedTitle = gSiteLife.EscapeValue(reviewedTitle) || gSiteLife.EscapeValue(document.title);
    reviewCategory = reviewCategory || "Uncategorized";
    pageSize = pageSize || 10;
    sort = sort || "TimeStampAscending";
    currentPage = currentPage || 0;
    var url = this.__baseUrl + '/Review/Reviews?plckElementId=Reviews_Container' +
        '&plckTargetKey=' + parentKey + 
        '&plckTargetKeyType=' + parentKeyType +
        '&plckReviewedTitle=' + reviewedTitle +
        '&plckReviewCategory=' + reviewCategory +
        '&plckSort=' + sort + 
        '&plckParentUrl=' + gSiteLife.EscapeValue(gSiteLife.__StripAnchorFromUrl(window.location.href)) + 
        '&plckParentTitle=' + gSiteLife.EscapeValue(document.title) +
        '&plckCurrentPage=' + currentPage +
        '&plckPageSize=' + pageSize;
    this.__Send(url);
    return false;   
}

SiteLifeProxy.prototype.SummaryArticlesMostCommented = function(count) {
 return this.SummaryPanel("SummaryArticlesMostCommented", count); 
} 
SiteLifeProxy.prototype.SummaryArticlesMostRecommended = function(count) {
 return this.SummaryPanel("SummaryArticlesMostRecommended", count); 
} 
SiteLifeProxy.prototype.SummaryPhotosRecentPhotosByTag = function(count, tagFilter, filterBySiteOfOrigin) {
 return this.SummaryPanel("SummaryPhotosRecentPhotosByTag", count, tagFilter, filterBySiteOfOrigin); 
} 
SiteLifeProxy.prototype.SummaryPhotosRecentUserPhotos = function(count, tagFilter, filterBySiteOfOrigin) {
 return this.SummaryPanel("SummaryPhotosRecentUserPhotos", count, tagFilter, filterBySiteOfOrigin);
} 
SiteLifeProxy.prototype.SummaryPhotosRecentPhotos = function(count, tagFilter, filterBySiteOfOrigin) {
 return this.SummaryPanel("SummaryPhotosRecentPhotos", count, tagFilter, filterBySiteOfOrigin); 
} 
SiteLifeProxy.prototype.SummaryPhotosMostRecommendedPhotos = function(count, filterBySiteOfOrigin) {
 return this.SummaryPanel("SummaryPhotosMostRecommendedPhotos", count, "", filterBySiteOfOrigin); 
} 
SiteLifeProxy.prototype.SummaryPhotosMostRecommendedUserPhotos = function(count, filterBySiteOfOrigin) {
 return this.SummaryPanel("SummaryPhotosMostRecommendedUserPhotos", count, "", filterBySiteOfOrigin); 
} 
SiteLifeProxy.prototype.SummaryPhotosMostRecommendedGalleries = function(count) {
 return this.SummaryPanel("SummaryPhotosMostRecommendedGalleries", count); 
} 
SiteLifeProxy.prototype.SummaryForumsRecentDiscussions = function(count, filterBySiteOfOrigin, parentIds) {
    var divId= "Summary_Container" + this.SID;
    if(this.numSummaryWidgets){ divId += this.numSummaryWidgets++; } else { this.numSummaryWidgets = 1; }
    this.WriteDiv(divId, divId);
    var methodName = "SummaryForumsRecentDiscussions";
    var tagFilter = "";
    return this.SummarySend(methodName, divId, divId + "Script", "plckCount", count, "plckTagFilter", tagFilter, "plckFilterBySiteOfOrigin", filterBySiteOfOrigin, "plckParentIds", parentIds);
} 
SiteLifeProxy.prototype.SummaryBlogsRecent = function(count, tagFilter) {
    return this.SummaryPanel("SummaryBlogsRecent", count, tagFilter);
}
SiteLifeProxy.prototype.SummaryBlogsRecentPostsByTag = function(count, tagFilter, filterBySiteOfOrigin) {
 return this.SummaryPanel("SummaryBlogsRecentPostsByTag", count, tagFilter, filterBySiteOfOrigin); 
} 
SiteLifeProxy.prototype.SummaryBlogsRecentPosts = function(count, tagFilter, filterBySiteOfOrigin) {
 return this.SummaryPanel("SummaryBlogsRecentPosts", count, tagFilter, filterBySiteOfOrigin); 
} 
SiteLifeProxy.prototype.SummaryBlogsMostRecommendedPosts = function(count, tagFilter, filterBySiteOfOrigin) {
    return this.SummaryPanel("SummaryBlogsMostRecommendedPosts", count, tagFilter, filterBySiteOfOrigin);
}
SiteLifeProxy.prototype.SummaryPersonaProfileRecent = function(count) {
    return this.SummaryPanel("SummaryPersonaProfileRecent", count);
}
SiteLifeProxy.prototype.SummaryPanel = function(methodName, count, tagFilter, filterBySiteOfOrigin) {
    var divId= "Summary_Container" + this.SID;
    if(this.numSummaryWidgets){ divId += this.numSummaryWidgets++; } else { this.numSummaryWidgets = 1; }
    this.WriteDiv(divId, divId);
    return this.SummarySend(methodName, divId, divId + "Script", "plckCount", count, "plckTagFilter", tagFilter, "plckFilterBySiteOfOrigin", filterBySiteOfOrigin);
}
SiteLifeProxy.prototype.SummarySend = function(ApiName, DestDiv, ScriptName) {
    var url = this.__baseUrl + '/Summary/' + ApiName + '?plckElementId=' + DestDiv;
    for(ii=3; ii< this.SummarySend.arguments.length; ii+=2) { if(this.SummarySend.arguments[ii+1]) { url += "&" + this.SummarySend.arguments[ii] + "=" + this.SummarySend.arguments[ii+1];} }
    this.__Send(url, ScriptName);
    return false;
}




var gSiteLife = new SiteLifeProxy("http://pluckdev.thesunnews.com/ver1.0");
gSiteLife.apiKey = "${APIKey}";
gSiteLife.SID = "pluckdev.thesunnews.com";



    // We need to return true here as our default behavior allowing normal link navigation
    gSiteLife.AddEventHandler('ExternalResourceLink', function() {return true;});

if(gSiteLife.GetParameter('plckPersonaPage') && gSiteLife.GetParameter('plckPersonaPage').indexOf('PersonaBlog') == 0) {
document.write("<link href=" + "'http://pluckdev.thesunnews.com/ver1.0/blog/BlogRss?plckBlogId=" + gSiteLife.GetParameter('insiteUserId') + "' title='" + gSiteLife.GetParameter('insiteUserId') + " Blog'" + "rel='alternate' type='application/rss+xml' />"); }
var numUploads = 1;
var maxUploads = 4;


function VerifyTOS() {
    if(!document.getElementById("plckTermsOfPhotoService").checked) {
        alert("Please agree to the terms of service before submitting.");
        return false;
    }
    return true;
}

// use to generate more photo submission divs
function AddAnotherPhoto(parentDivID,uploadButtonID, parentFrame){
    divNode = document.createElement('div');
    divNode.id = 'PhotoUpload' + ++numUploads;
    divNode.innerHTML = "<input type='file' name='image" + numUploads + "' value='Get' size=40/><br/><br/>"

    document.getElementById(parentDivID).appendChild(divNode);
    if(numUploads > maxUploads) document.getElementById(uploadButtonID).style.display = 'none';
    setTimeout(function(){autofitIframe(parentFrame, true);}, 100);
    return false;
}


// Returns the value of the radio button that is set in a group of buttons.
function getCheckedValue(radioObj) {
	var radioLength = radioObj.length;
	if(radioLength == undefined) {
		if(radioObj.checked) {
			return radioObj.value;
		}
		else {
			return "";
		}
	}
	for(var i = 0; i < radioLength; i++) {
		if(radioObj[i].checked) {
			return radioObj[i].value;
		}
	}
	return "";
}

// this trim was suggested by Tobias Hinnerup
String.prototype.trim = function() {
    return(this.replace(/^\s+/,'').replace(/\s+$/,''));
}

function IsEnter(e)  {
var kc = e.which;
if(kc == null) kc = e.keyCode;
if (e && kc == 13) return true;
return false;
}
function TrimEnd(ct, c) {
    while((ct.length > 0) && (ct.lastIndexOf(c) == (ct.length - 1))){
        if(ct.length > 1 ) {
            ct = ct.substring(0, ct.length - 1);
        }else{ 
            return "";
        }
    }
    return ct;
}
function FixSearchString(str) {
    var ct = str.replace(/[\%\&\/\<\>\\\|]+/g,"");
    ct = ct.replace(/[\.]{2,}/g, ".");
        
    ct = TrimEnd(ct,".");
    if( ct == "" ) return "";
    ct = TrimEnd(ct," ");
    if( ct == "") return "";

    ct = escape(ct);
    // JavaScript's built-in escape() skips plus signs, but we need them for Lucene
    ct = ct.replace(/\+/g, "%2B");
    return ct;
}

var nextGroupID = 1;

function autofitIframe(id, heightOnly){
    if(document.getElementById) {
        if(this.document.body.scrollHeight == 0 || ( !heightOnly && this.document.body.scrollWidth == 0)) {
            //Onload fired, DOM assembled, but scrollHeight/Width is zero. This should not be... Go to
            //sleep and try again
            setTimeout(function(){autofitIframe(id, heightOnly);}, 150);
            return;
        }
        window.parent.document.getElementById(id).style.height=this.document.body.scrollHeight+"px";
        if(!heightOnly)window.parent.document.getElementById(id).style.width=this.document.body.scrollWidth+"px";
    }
}

//Determines if the string being tested is a Url.
function isUrl(s) {
	var regexp = /(ftp|https?|file):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/
	return regexp.test(s);
}

function ValidateLogin() {
    function $(id) { return document.getElementById(id) };
    if($("plckUserName").value == '' && $("plckPassword").value == '') {
        alert("You must provide a UserName and Password");
        return false;
    }
    if($("plckUserName").value == '') {
        alert("You must provide a UserName");
        return false;
    }
    if($("plckPassword").value == '') {
        alert("You must provide a Password");
        return false;
    }
}   

function onSearchSubmit(qroupID) {
    if($(qroupID  + "_Search").value == '') {
        alert("You must provide some query text");
        return false;
    }    
}

function LimitLength(control, limitToLength) {
  var str = control.value;
  if(! str || str.length == 0) return false;
  
  var matches = str.match(/\r|\n/g);
  if(! matches) return false;
  
  var offSet = matches.length;
  if (str.length > (limitToLength + offSet)) {
    control.value = str.substring(0, limitToLength + offSet);
  }
  return false;
} 
/* this document is for visual dhtml features */
function mouseX(evt) {
    if (evt.pageX) return evt.pageX;
    else if (evt.clientX)
       return evt.clientX + (document.documentElement.scrollLeft ?
       document.documentElement.scrollLeft :
       document.body.scrollLeft);
    else return null;
}
function mouseY(evt) {
    if (evt.pageY) return evt.pageY;
    else if (evt.clientY)
       return evt.clientY + (document.documentElement.scrollTop ?
       document.documentElement.scrollTop :
       document.body.scrollTop);
    else return null;
}
function HideDiv(id){
    document.getElementById(id).style.display = "none";
}

function ShowDivAtMouse(evt, id) {
    posx = mouseX(evt) - 170;    
    posy = mouseY(evt);
    //normalize to make sure we at least appear on the screen
    if(posx < 0) posx = 10;
    if(posy < 0) posy = 10;
    
    document.getElementById(id).style.left = posx + "px";
	document.getElementById(id).style.top = posy + "px";
	document.getElementById(id).style.display = "block";
}
function ShowReportAbuse(evt, url, command) {
    var doc = document;
    doc.getElementById("ReportAbuse_Url").value = url; 
    doc.getElementById("ReportAbuse_Command").value = command;
    doc.getElementById("ReportAbuse_CommentText").value = "";
    doc.getElementById("ReportAbuse_Reason").selectedIndex = 0;
    ShowDivAtMouse(evt, "ReportAbuse_Menu");
    doc.getElementById('ReportAbuse_CommentText').focus();
}
function ReportAbuse() {
    var url = document.getElementById("ReportAbuse_Url").value; 
    var command = document.getElementById("ReportAbuse_Command").value;
    var text = document.getElementById("ReportAbuse_CommentText").value;
    var reason = document.getElementById("ReportAbuse_Reason").value;
    document.getElementById("ReportAbuse_Menu").style.display='none';
    var sendUrl = command+'&plckReason='+gSiteLife.EscapeValue(reason)+'&plckURL=' + gSiteLife.EscapeValue(url)
    if(text) sendUrl += "&plckAbuseDetail=" + gSiteLife.EscapeValue(text);
    gSiteLife.__Send(sendUrl);
}

function SiteLifeShowHide(id1, id2){
    document.getElementById(id1).style.display = "none";
    document.getElementById(id2).style.display = "block";
    return false;
}

function DebugShowInnerHTML(id, url) {
    var el = document.getElementById(id);
    var floatDiv = document.createElement("div");
      
    floatDiv.style.position = "absolute";    
    floatDiv.style.zIndex='1000';
    floatDiv.innerHTML = "<span style='background-color:red; color:white; cursor:pointer;' onclick='this.parentNode.parentNode.removeChild(this.parentNode);'>[close]</span>";    
    floatDiv.innerHTML += "<div style='background-color:black; color:white;'>" + url + "</div><textarea rows='20' cols='80'>" + el.childNodes[0].childNodes[1].innerHTML + "</textarea>";
    el.insertBefore(floatDiv, el.childNodes[0]);
}


function ToggleState() {
    function $(id) { return document.getElementById(id) };
    var radio1 = $("plckCommentApprovalEveryOne");
    var radio2 = $("plckCommentApprovalNoBody");
    var table = $("commentSettings"); 
    if(radio1.disabled  == true) {
        radio1.disabled  = false;
        radio2.disabled  = false;
        table.className = "";
    }
    else {
        radio1.disabled  = true;
        radio2.disabled  = true;
        table.className = "BlogSettings_Disabled";
    }
}

function getElementsByClassName(classname, node)  {
    if(!node) node = document.getElementsByTagName("body")[0];
    var a = [];
    var re = new RegExp('\\b' + classname + '\\b');
    var els = node.getElementsByTagName("*");
    for(var i=0,j=els.length; i<j; i++)
        if(re.test(els[i].className))a.push(els[i]);
    return a;
}


/*
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 2.6.0
*/
if(typeof YAHOO=="undefined"||!YAHOO){var YAHOO={};}YAHOO.namespace=function(){var A=arguments,E=null,C,B,D;for(C=0;C<A.length;C=C+1){D=A[C].split(".");E=YAHOO;for(B=(D[0]=="YAHOO")?1:0;B<D.length;B=B+1){E[D[B]]=E[D[B]]||{};E=E[D[B]];}}return E;};YAHOO.log=function(D,A,C){var B=YAHOO.widget.Logger;if(B&&B.log){return B.log(D,A,C);}else{return false;}};YAHOO.register=function(A,E,D){var I=YAHOO.env.modules;if(!I[A]){I[A]={versions:[],builds:[]};}var B=I[A],H=D.version,G=D.build,F=YAHOO.env.listeners;B.name=A;B.version=H;B.build=G;B.versions.push(H);B.builds.push(G);B.mainClass=E;for(var C=0;C<F.length;C=C+1){F[C](B);}if(E){E.VERSION=H;E.BUILD=G;}else{YAHOO.log("mainClass is undefined for module "+A,"warn");}};YAHOO.env=YAHOO.env||{modules:[],listeners:[]};YAHOO.env.getVersion=function(A){return YAHOO.env.modules[A]||null;};YAHOO.env.ua=function(){var C={ie:0,opera:0,gecko:0,webkit:0,mobile:null,air:0};var B=navigator.userAgent,A;if((/KHTML/).test(B)){C.webkit=1;}A=B.match(/AppleWebKit\/([^\s]*)/);if(A&&A[1]){C.webkit=parseFloat(A[1]);if(/ Mobile\//.test(B)){C.mobile="Apple";}else{A=B.match(/NokiaN[^\/]*/);if(A){C.mobile=A[0];}}A=B.match(/AdobeAIR\/([^\s]*)/);if(A){C.air=A[0];}}if(!C.webkit){A=B.match(/Opera[\s\/]([^\s]*)/);if(A&&A[1]){C.opera=parseFloat(A[1]);A=B.match(/Opera Mini[^;]*/);if(A){C.mobile=A[0];}}else{A=B.match(/MSIE\s([^;]*)/);if(A&&A[1]){C.ie=parseFloat(A[1]);}else{A=B.match(/Gecko\/([^\s]*)/);if(A){C.gecko=1;A=B.match(/rv:([^\s\)]*)/);if(A&&A[1]){C.gecko=parseFloat(A[1]);}}}}}return C;}();(function(){YAHOO.namespace("util","widget","example");if("undefined"!==typeof YAHOO_config){var B=YAHOO_config.listener,A=YAHOO.env.listeners,D=true,C;if(B){for(C=0;C<A.length;C=C+1){if(A[C]==B){D=false;break;}}if(D){A.push(B);}}}})();YAHOO.lang=YAHOO.lang||{};(function(){var A=YAHOO.lang,C=["toString","valueOf"],B={isArray:function(D){if(D){return A.isNumber(D.length)&&A.isFunction(D.splice);}return false;},isBoolean:function(D){return typeof D==="boolean";},isFunction:function(D){return typeof D==="function";},isNull:function(D){return D===null;},isNumber:function(D){return typeof D==="number"&&isFinite(D);},isObject:function(D){return(D&&(typeof D==="object"||A.isFunction(D)))||false;},isString:function(D){return typeof D==="string";},isUndefined:function(D){return typeof D==="undefined";},_IEEnumFix:(YAHOO.env.ua.ie)?function(F,E){for(var D=0;D<C.length;D=D+1){var H=C[D],G=E[H];if(A.isFunction(G)&&G!=Object.prototype[H]){F[H]=G;}}}:function(){},extend:function(H,I,G){if(!I||!H){throw new Error("extend failed, please check that "+"all dependencies are included.");}var E=function(){};E.prototype=I.prototype;H.prototype=new E();H.prototype.constructor=H;H.superclass=I.prototype;if(I.prototype.constructor==Object.prototype.constructor){I.prototype.constructor=I;}if(G){for(var D in G){if(A.hasOwnProperty(G,D)){H.prototype[D]=G[D];}}A._IEEnumFix(H.prototype,G);}},augmentObject:function(H,G){if(!G||!H){throw new Error("Absorb failed, verify dependencies.");}var D=arguments,F,I,E=D[2];if(E&&E!==true){for(F=2;F<D.length;F=F+1){H[D[F]]=G[D[F]];}}else{for(I in G){if(E||!(I in H)){H[I]=G[I];}}A._IEEnumFix(H,G);}},augmentProto:function(G,F){if(!F||!G){throw new Error("Augment failed, verify dependencies.");}var D=[G.prototype,F.prototype];for(var E=2;E<arguments.length;E=E+1){D.push(arguments[E]);}A.augmentObject.apply(this,D);},dump:function(D,I){var F,H,K=[],L="{...}",E="f(){...}",J=", ",G=" => ";if(!A.isObject(D)){return D+"";}else{if(D instanceof Date||("nodeType" in D&&"tagName" in D)){return D;}else{if(A.isFunction(D)){return E;}}}I=(A.isNumber(I))?I:3;if(A.isArray(D)){K.push("[");for(F=0,H=D.length;F<H;F=F+1){if(A.isObject(D[F])){K.push((I>0)?A.dump(D[F],I-1):L);}else{K.push(D[F]);}K.push(J);}if(K.length>1){K.pop();}K.push("]");}else{K.push("{");for(F in D){if(A.hasOwnProperty(D,F)){K.push(F+G);if(A.isObject(D[F])){K.push((I>0)?A.dump(D[F],I-1):L);}else{K.push(D[F]);}K.push(J);}}if(K.length>1){K.pop();}K.push("}");}return K.join("");},substitute:function(S,E,L){var I,H,G,O,P,R,N=[],F,J="dump",M=" ",D="{",Q="}";for(;;){I=S.lastIndexOf(D);if(I<0){break;}H=S.indexOf(Q,I);if(I+1>=H){break;}F=S.substring(I+1,H);O=F;R=null;G=O.indexOf(M);if(G>-1){R=O.substring(G+1);O=O.substring(0,G);}P=E[O];if(L){P=L(O,P,R);}if(A.isObject(P)){if(A.isArray(P)){P=A.dump(P,parseInt(R,10));}else{R=R||"";var K=R.indexOf(J);if(K>-1){R=R.substring(4);}if(P.toString===Object.prototype.toString||K>-1){P=A.dump(P,parseInt(R,10));}else{P=P.toString();}}}else{if(!A.isString(P)&&!A.isNumber(P)){P="~-"+N.length+"-~";N[N.length]=F;}}S=S.substring(0,I)+P+S.substring(H+1);}for(I=N.length-1;I>=0;I=I-1){S=S.replace(new RegExp("~-"+I+"-~"),"{"+N[I]+"}","g");}return S;},trim:function(D){try{return D.replace(/^\s+|\s+$/g,"");}catch(E){return D;}},merge:function(){var G={},E=arguments;for(var F=0,D=E.length;F<D;F=F+1){A.augmentObject(G,E[F],true);}return G;},later:function(K,E,L,G,H){K=K||0;E=E||{};var F=L,J=G,I,D;if(A.isString(L)){F=E[L];}if(!F){throw new TypeError("method undefined");}if(!A.isArray(J)){J=[G];}I=function(){F.apply(E,J);};D=(H)?setInterval(I,K):setTimeout(I,K);return{interval:H,cancel:function(){if(this.interval){clearInterval(D);}else{clearTimeout(D);}}};},isValue:function(D){return(A.isObject(D)||A.isString(D)||A.isNumber(D)||A.isBoolean(D));}};A.hasOwnProperty=(Object.prototype.hasOwnProperty)?function(D,E){return D&&D.hasOwnProperty(E);}:function(D,E){return !A.isUndefined(D[E])&&D.constructor.prototype[E]!==D[E];};B.augmentObject(A,B,true);YAHOO.util.Lang=A;A.augment=A.augmentProto;YAHOO.augment=A.augmentProto;YAHOO.extend=A.extend;})();YAHOO.register("yahoo",YAHOO,{version:"2.6.0",build:"1321"});/*
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 2.6.0
*/
YAHOO.lang.JSON=(function(){var l=YAHOO.lang,_UNICODE_EXCEPTIONS=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,_ESCAPES=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,_VALUES=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,_BRACKETS=/(?:^|:|,)(?:\s*\[)+/g,_INVALID=/^[\],:{}\s]*$/,_SPECIAL_CHARS=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,_CHARS={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};function _revive(data,reviver){var walk=function(o,key){var k,v,value=o[key];if(value&&typeof value==="object"){for(k in value){if(l.hasOwnProperty(value,k)){v=walk(value,k);if(v===undefined){delete value[k];}else{value[k]=v;}}}}return reviver.call(o,key,value);};return typeof reviver==="function"?walk({"":data},""):data;}function _char(c){if(!_CHARS[c]){_CHARS[c]="\\u"+("0000"+(+(c.charCodeAt(0))).toString(16)).slice(-4);}return _CHARS[c];}function _prepare(s){return s.replace(_UNICODE_EXCEPTIONS,_char);}function _isValid(str){return l.isString(str)&&_INVALID.test(str.replace(_ESCAPES,"@").replace(_VALUES,"]").replace(_BRACKETS,""));}function _string(s){return'"'+s.replace(_SPECIAL_CHARS,_char)+'"';}function _stringify(h,key,d,w,pstack){var o=typeof w==="function"?w.call(h,key,h[key]):h[key],i,len,j,k,v,isArray,a;if(o instanceof Date){o=l.JSON.dateToString(o);}else{if(o instanceof String||o instanceof Boolean||o instanceof Number){o=o.valueOf();}}switch(typeof o){case"string":return _string(o);case"number":return isFinite(o)?String(o):"null";case"boolean":return String(o);case"object":if(o===null){return"null";}for(i=pstack.length-1;i>=0;--i){if(pstack[i]===o){return"null";}}pstack[pstack.length]=o;a=[];isArray=l.isArray(o);if(d>0){if(isArray){for(i=o.length-1;i>=0;--i){a[i]=_stringify(o,i,d-1,w,pstack)||"null";}}else{j=0;if(l.isArray(w)){for(i=0,len=w.length;i<len;++i){k=w[i];v=_stringify(o,k,d-1,w,pstack);if(v){a[j++]=_string(k)+":"+v;}}}else{for(k in o){if(typeof k==="string"&&l.hasOwnProperty(o,k)){v=_stringify(o,k,d-1,w,pstack);if(v){a[j++]=_string(k)+":"+v;}}}}a.sort();}}pstack.pop();return isArray?"["+a.join(",")+"]":"{"+a.join(",")+"}";}return undefined;}return{isValid:function(s){return _isValid(_prepare(s));},parse:function(s,reviver){s=_prepare(s);if(_isValid(s)){return _revive(eval("("+s+")"),reviver);}throw new SyntaxError("parseJSON");},stringify:function(o,w,d){if(o!==undefined){if(l.isArray(w)){w=(function(a){var uniq=[],map={},v,i,j,len;for(i=0,j=0,len=a.length;i<len;++i){v=a[i];if(typeof v==="string"&&map[v]===undefined){uniq[(map[v]=j++)]=v;}}return uniq;})(w);}d=d>=0?d:1/0;return _stringify({"":o},"",d,w,[]);}return undefined;},dateToString:function(d){function _zeroPad(v){return v<10?"0"+v:v;}return d.getUTCFullYear()+"-"+_zeroPad(d.getUTCMonth()+1)+"-"+_zeroPad(d.getUTCDate())+"T"+_zeroPad(d.getUTCHours())+":"+_zeroPad(d.getUTCMinutes())+":"+_zeroPad(d.getUTCSeconds())+"Z";},stringToDate:function(str){if(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$/.test(str)){var d=new Date();d.setUTCFullYear(RegExp.$1,(RegExp.$2|0)-1,RegExp.$3);d.setUTCHours(RegExp.$4,RegExp.$5,RegExp.$6);return d;}return str;}};})();YAHOO.register("json",YAHOO.lang.JSON,{version:"2.6.0",build:"1321"});document.iframeLoaders = {};

iframe = function() { this.initialize.apply(this, arguments); };
iframe.prototype = {
	initialize: function(form, options,count){
		if (!options) options = {};
		this.form = form;
		this.uniqueId = count;
		document.iframeLoaders[this.uniqueId] = this;
		var url = form.action + '?jsonRequest=' + escape(form.elements[0].value); // change form submit to string; similar to changing form method to get
		var firstSlash = url.indexOf("/", url.indexOf("//")+2);
		this.transport = this.getTransport((firstSlash > 0) ? url.substring(0, firstSlash) : "");
		this.onComplete = options.onComplete || null;
		this.update = this.$(options.update) || null;
		this.updateMultiple = options.multiple || false;
		if (((navigator.vendor && (navigator.vendor.indexOf('Apple')) > -1) || window.opera) // safari and opera only
     && (/\/Direct\/Process(\?|$)/.test(form.action)) && form.elements && (form.elements.length == 1)) { // only change calls that contain 1 element and whose actions end with /Direct/Process
			var doc = this.transport.contentWindow || this.transport.contentDocument; // retrieve the document of the iframe
			if (url.length < 80000) { // allow fallback to normal submission (80k is the max length for urls in safari)
				if (doc.document) // make sure we have the document and not the window
					doc = doc.document;
				
				try { // if this fails, fallback to normal submission
					doc.location.replace(url); // use location.replace to overwrite elements in history 
					return;
				} catch (e) { };
			}
		}
		form.target= 'frame_'+this.uniqueId;
		form.setAttribute("target", 'frame_'+this.uniqueId); // in case the other one fails.
		form.submit();
	},

	onStateChange: function() {
		this.transport = this.$('frame_'+this.uniqueId);
		try {	 var doc = this.transport.contentDocument.body.innerHTML; this.transport.contentDocument.close(); }	// For NS6
		catch (e){ 
			try{ var doc = this.transport.contentWindow.document.body.innerHTML; this.transport.contentWindow.document.close(); } // For IE5.5 and IE6
			 catch (e){
				 try { var doc = this.transport.document.body.innerHTML; this.transport.document.body.close(); } // for IE5
					catch (e) {
						try	{ var doc = window.frames['frame_'+this.uniqueId].document.body.innerText; } // for really nasty browsers
						catch (e) { //alert(e); 
						} // forget it.
				 }
			}
		}
		this.transport.responseText = doc;
		if (this.onComplete) setTimeout(this.bind(function(){this.onComplete(this.transport);}, this), 10);
		if (this.update) setTimeout(this.bind(function(){this.update.innerHTML = this.transport.responseText;}, this), 10);
		if (this.updateMultiple){ setTimeout(this.bind(function(){ // JSON support!
				try	{ var hasscript = false; eval("var inputObject = "+this.transport.responseText);	// we're expecting a JSON object, eval it to inputObject
					for (var i in inputObject) { if (i == 'script') { hasscript = true; } // check if we passed some javascript along too
						else {if ( elm = this.$(i)) { elm.innerHTML = inputObject[i]; } else { 
						//alert("element "+i+" not found!"); 
						} } // if it's not script, update the corresponding div
					} if (hasscript) eval(inputObject['script']); // some on-the-fly-javascript exchanging support too
				} catch (e) { //alert('There was an error processing: '+this.transport.responseText); 
				} // in case of an error					
			}, this), 10);
		}	
	},

	getTransport: function(baseUrl) {
		var divElm = document.createElement('DIV'), frame;
		divElm.setAttribute('style', 'width: 0; height: 0; margin: 0; padding: 0; visibility: hidden; overflow: hidden');
		if (navigator.userAgent.indexOf('MSIE') > 0 && navigator.userAgent.indexOf('Opera') == -1) {// switch to the crappy solution for IE
			divElm.style.width = 0;
			divElm.style.height = 0;
			divElm.style.margin = 0;
			divElm.style.padding = 0;
			divElm.style.visibility = 'hidden';
			divElm.style.overflow = 'hidden';
			divElm.innerHTML = '<iframe name=\"frame_'+this.uniqueId+'\" id=\"frame_'+this.uniqueId+'\" src=\"' + baseUrl + '/ver1.0/Content/blank.html\" onload=\"setTimeout(function(){document.iframeLoaders['+this.uniqueId+'].onStateChange()},20);"></iframe>';
		} else {
			frame = document.createElement("iframe");
			frame.setAttribute("name", "frame_"+this.uniqueId);
			frame.setAttribute("id", "frame_"+this.uniqueId);
			frame.addEventListener("load", this.bind(function(){ this.onStateChange(); }, this), false);
			divElm.appendChild(frame);
		}
    (RequestBatch.container || document.body).appendChild(divElm);
		return frame;
	},
  
  bind: function(functionObject, referenceObject) {
    return function() {
      return functionObject.apply(referenceObject, arguments);
    }
  },
  
  '$': function(id) {
    return document.getElementById(id);
  }
};
if (typeof(RequestBatch) === 'undefined') {
    RequestBatch = function() {
      this.initialize.apply(this, arguments);
    };
    // for unique id
    var counter = 0;

    // how many requests are still pending?
    var pendingRequests = 0;

    function DirectAccessErrorHandler(msg,ex){
    //alert(msg);
    }
    (function() {

        function buildJsonpUrl(serverUrl, jsonString, callbackName) {
            var separator = serverUrl.indexOf('?') == -1 ? "?" : "&";
            // use Jsonp endpoint instead of Process
            serverUrl = serverUrl.replace('/Process', '/Jsonp');
            return serverUrl + separator + "r=" + encodeURIComponent(jsonString) + '&cb=' + callbackName;
        }

        function useJsonp(serverUrl, jsonString, callbackName) {
            // use Jsonp endpoint instead of Process
            serverUrl = buildJsonpUrl(serverUrl, jsonString, callbackName);
            var isIE = /*@cc_on!@*/false;
            if ((isIE && serverUrl.length < 2083) || (!isIE && serverUrl.length < 4000)) {
                return serverUrl;
            }
            return false;
        }

        // the core object to request batches
        RequestBatch.prototype = {
            initialize: function() {
                this.UniqueId = counter++;
                this.Requests = new Array()
            },

            HasTemplate: function() {
                return typeof (this["Template"]) != "undefined";
            },

            AddToRequest: function(requestThis) {
                this.Requests[this.Requests.length] = requestThis;
            },

            BeginRequest: function(serverUrl, callback) {
                pendingRequests++;

                if (!RequestBatch.callbacks) {
                    RequestBatch.callbacks = {};
                }

                // the cc_on comment below is important.. if you remove it, it will change the processing of the script
                // see http://msdn.microsoft.com/en-us/library/8ka90k2e(VS.85).aspx for details of conditional compilation
                var jsonString = YAHOO.lang.JSON.stringify(this), ie = /*@cc_on!@*/false;
                if (ie && !RequestBatch.container) { // forcibly take this route only for ie
                    var body = document.body, div;
                    RequestBatch.container = div = body.insertBefore(document.createElement('div'), body.firstChild);
                    div.style.height = div.style.width = div.style.margin = div.style.padding = 0;
                    div.style.visibility = div.style.overflow = 'hidden';
                    div.style.display = 'none';
                }
                // generate our callback function that will call their callback function via closure semantics
                var daapiCallbackName = 'daapiCallback' + this.UniqueId;
                var thisRequest = this;
                if (jsonpServerUrl = useJsonp(serverUrl, jsonString, 'RequestBatch.callbacks.' + daapiCallbackName)) {
                    // insert script node with callback function = daapiCallbackName
                    var jsonpScriptNode = document.createElement('script');
                    jsonpScriptNode.type = "text/javascript";
                    jsonpScriptNode.src = jsonpServerUrl;
                    var headElem = document.getElementsByTagName('head')[0];
                    RequestBatch.callbacks[daapiCallbackName] = (function(userCallback, headElem, scriptNode) {
                        return function(responses) {
                            if (thisRequest.HasTemplate()) {
                                userCallback(responses);
                            } else {
                                // clean up after ourselves
                                userCallback(responses.ResponseBatch);
                                userCallback = headElem = scriptNode = null;
                            }
                        }
                    })(callback, headElem, jsonpScriptNode);
                    headElem.appendChild(jsonpScriptNode);
                }
                else {
                    var form = generateForm(this.UniqueId, serverUrl, jsonString);
                    new iframe(form, { onComplete: function(request) { processResponse(callback, request, thisRequest.HasTemplate()); } }, this.UniqueId);
                }
                // in case they reuse the requestbatch
                this.UniqueId = counter++;
            }
        };
    })();
}

function generateForm(formId, serverUrl, inputVal) {
    // create the form
	var form = document.createElement("form");
	form.acceptCharset = "UTF-8";
	form.name = "f" + formId;
	form.id = "f" + formId;
	form.action = serverUrl;

	// create the input element on the form
	var inputElem = document.createElement("input");
	inputElem.name = "jsonRequest";
	inputElem.type = "hidden";
	inputElem.value = inputVal;
	form.appendChild(inputElem);

	// Firefox has a behavior on refresh that displays a popup confirming that is it reloading a form.
	// We work around this by attempting to perform a get action if the size is below a threshold, else
	// we will run as a post
	form.method = "post";
    if(navigator.userAgent.toLowerCase().indexOf('firefox') != -1) {
        var separator = serverUrl.indexOf('?') == -1 ? "?" : "&";
        var fullRequestURL = serverUrl + separator + "jsonRequest="+ escape(inputVal);
        if (fullRequestURL.length < 4000) {
            // we plan to perform a get, so we need to parse the sid out of the url and place it
            // inside the form
            var sidPos = serverUrl.indexOf('sid=');
            if (sidPos != -1) {
                var endPos = serverUrl.indexOf('&', sidPos);
                var sid = serverUrl.substring(sidPos + 'sid='.length, endPos == -1 ? serverUrl.length : endPos);
	            var sidInputElem = document.createElement("input");
	            sidInputElem.name = "sid";
	            sidInputElem.type = "hidden";
	            sidInputElem.value = sid;
	            form.appendChild(sidInputElem);
	            // remove the sid from the url
	            form.action = serverUrl.substring(0, sidPos-1);
            }
            form.method = "get";
        }
    }

	(RequestBatch.container || document.body).appendChild(form);
	return form;
}

function processResponse(callback, request, isTemplated)
{
    pendingRequests--;
    try {
        if (isTemplated) {
            callback(request.ResponseText);
        } else {
            var jsonResponse = unescape(request.responseText);
            jsonResponse = jsonResponse.replace(/\\\>/g, ">");
            var responseObject = YAHOO.lang.JSON.parse(jsonResponse);
            try {
                callback(responseObject.ResponseBatch);
            } catch (e) {
                DirectAccessErrorHandler("exception during client callback", e);
            }
        }
    } catch (e) {
        DirectAccessErrorHandler("exception during processResponse", e);
    }
}

function getPendingRequestCount()
{
    return pendingRequests;
}

// ------------------------------------------------------------------------------------
// This file contains all the request type objects for the SiteLife JSON Direct API.
// Create instances of these objects, place them in a RequestBatch, and send them off.
// ------------------------------------------------------------------------------------

(function() { // wrapped in a function to keep the Class variable out of the global scope
var Class = function() {
  return function() {
    this.initialize.apply(this, arguments);
  }
};
// Identify a user
UserKey = Class();
UserKey.prototype = {
   initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.UserKey = data;
   }
};
// Identify a comment
CommentKey = Class();
CommentKey.prototype = {
   initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.CommentKey = data;
   }
};
// Identify an article
ArticleKey = Class();
ArticleKey.prototype = {
   initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.ArticleKey = data;
   }
};

// Identify a persona message
PersonaMessageKey = Class();
PersonaMessageKey.prototype = {
   initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.PersonaMessageKey = data;
   }
};

// Identify a review
ReviewKey = Class();
ReviewKey.prototype = {
   initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.ReviewKey = data;
   }
};

// Identify a gallery
GalleryKey = Class();
GalleryKey.prototype = {
    initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.GalleryKey = data;
    }
};

// Identify a photo
PhotoKey = Class();
PhotoKey.prototype = {
    initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.PhotoKey = data;
    }
};

// Identify a video
VideoKey = Class();
VideoKey.prototype = {
    initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.VideoKey = data;
    }
};

// Identify a blog with this blog key
BlogKey = Class();
BlogKey.prototype = {
   initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.BlogKey = data;
   }
};

// Identify a blog post with this blog post key
BlogPostKey = Class();
BlogPostKey.prototype = {
   initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.BlogPostKey = data;
   }
};

// Identify a custom item with this CustomItemKey
CustomItemKey = Class();
CustomItemKey.prototype = {
   initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.CustomItemKey = data;
   }
};

// Identify a custom collection with this CustomCollectionKey
CustomCollectionKey = Class();
CustomCollectionKey.prototype = {
   initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.CustomCollectionKey = data;
   }
};


// Identify a Forum Category
ForumCategoryKey = Class();
ForumCategoryKey.prototype = {
    initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.ForumCategoryKey = data;
    }
};

// Identify a Forum
ForumKey = Class();
ForumKey.prototype = {
    initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.ForumKey = data;
    }
};

// Identify a forum discussion with this DiscussionKey 
DiscussionKey = Class();
DiscussionKey.prototype = {
   initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.DiscussionKey = data;
   }
};

// Identify a Forum Post
ForumPostKey = Class();
ForumPostKey.prototype = {
    initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.ForumPostKey = data;
    }
};

// Identify an Event
EventKey = Class();
EventKey.prototype = {
    initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.EventKey = data;
    }
};

// Identify an Event
EventSetKey = Class();
EventSetKey.prototype = {
    initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.EventSetKey = data;
    }
};

// Identify a Community Group
CommunityGroupKey = Class();
CommunityGroupKey.prototype = {
    initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.CommunityGroupKey = data;
    }
};

// Identify a CommunityGroup Membership
CommunityGroupMembershipKey = Class();
CommunityGroupMembershipKey.prototype = {
    initialize: function(communityGroupKey, userKey) {
        var data = new Object();
        data.CommunityGroupKey = communityGroupKey;
        data.UserKey = userKey;
        this.CommunityGroupMembershipKey = data;
    }
};


// Identify a CommunityGroup Invitation
CommunityGroupInvitationKey = Class();
CommunityGroupInvitationKey.prototype = {
    initialize: function(communityGroupKey, userKey) {
        var data = new Object();
        data.CommunityGroupKey = communityGroupKey;
        data.UserKey = userKey;
        this.CommunityGroupInvitationKey = data;
    }
};

// Identify a CommunityGroup Registrant
CommunityGroupRegistrantKey = Class();
CommunityGroupRegistrantKey.prototype = {
    initialize: function(communityGroupKey, userKey) {
        var data = new Object();
        data.CommunityGroupKey = communityGroupKey;
        data.UserKey = userKey;
        this.CommunityGroupRegistrantKey = data;
    }
};

// Identify a CommunityGroup Banned User
CommunityGroupBannedUserKey = Class();
CommunityGroupBannedUserKey.prototype = {
    initialize: function(communityGroupKey, userKey) {
        var data = new Object();
        data.CommunityGroupKey = communityGroupKey;
        data.UserKey = userKey;
        this.CommunityGroupBannedUserKey = data;
    }
};

PollKey = Class();
PollKey.prototype = {
    initialize: function(pollKey) {
        var data = new Object();
        data.Key = pollKey;
        this.PollKey = data;
    }
}

// Points/Badging
BadgeFamilyKey = Class();
BadgeFamilyKey.prototype = {
    initialize: function(badgeFamilyKey) {
        var data = new Object();
        data.Key = badgeFamilyKey;
        this.BadgeFamilyKey = data;
    }
}

LeaderboardKey = Class();
LeaderboardKey.prototype = {
    initialize: function(leaderboardKey) {
        var data = new Object();
        data.Key = leaderboardKey;
        this.LeaderboardKey = data;
    }
}

// Wrapper to request a comment page
CommentPage = Class();
CommentPage.prototype = {
   initialize: function(articleKey, numberPerPage, onPage, sort, findCommentKey) {
        var data = new Object();
        data.ArticleKey = articleKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.Sort = sort;
        data.FindCommentKey = findCommentKey;
        this.CommentPage = data;
   }
};

// Wrapper to request a persona message page
PersonaMessagePage = Class();
PersonaMessagePage.prototype = {
   initialize: function(userKey, numberPerPage, onPage, sort) {
        var data = new Object();
        data.UserKey = userKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.Sort = sort;
        this.PersonaMessagePage = data;
   }
};

// Wrapper to request a review page
ReviewPage = Class();
ReviewPage.prototype = {
   initialize: function(articleKey, numberPerPage, onPage,sort) {
        var data = new Object();
        data.ArticleKey = articleKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.Sort = sort;
        this.ReviewPage = data;
   }
};

// wrapper to request a page of reviews by user
UserReviewPage = Class();
UserReviewPage.prototype = {
    initialize: function(userKey, numberPerPage, onPage, sort) {
        var data = new Object();
        data.UserKey = userKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.Sort = sort;
        this.UserReviewPage = data;
    }
};

// Wrapper of types a gallery can contain
MediaType = Class();
MediaType.prototype = {
    initialize: function(name) {
        var data = new Object();
        data.Name = name;
        this.MediaType = data;
    }
};
// Wrapper to request a page of public galleries
PublicGalleryPage = Class();
PublicGalleryPage.prototype = {
    initialize: function(numberPerPage, onPage, mediaType) {
        var data = new Object();
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.MediaType = mediaType;
        this.PublicGalleryPage = data;
    }
};
// Wrapper to request a page of user galleries
UserGalleryPage = Class();
UserGalleryPage.prototype = {
    initialize: function(userKey, numberPerPage, onPage, mediaType) {
        var data = new Object();
        data.UserKey = userKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.MediaType = mediaType;
        this.UserGalleryPage = data;
    }
};
// Wrapper to request a page of photos
PhotoPage = Class();
PhotoPage.prototype = {
    initialize: function(galleryKey, numberPerPage, onPage, sort) {
        var data = new Object();
        data.GalleryKey = galleryKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.Sort = sort;
        this.PhotoPage = data;
    }
};
// Wrapper to request a page of videos
VideoPage = Class();
VideoPage.prototype = {
    initialize: function(galleryKey, numberPerPage, onPage, sort) {
        var data = new Object();
        data.GalleryKey = galleryKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.Sort = sort;
        this.VideoPage = data;
    }
};
// Wrapper to request a comment action
CommentAction = Class();
CommentAction.prototype = {
   initialize: function(commentOnKey, onPageUrl, onPageTitle, commentBody) {
        var data = new Object();
        data.CommentOnKey = commentOnKey;
        data.OnPageUrl = onPageUrl;
        data.OnPageTitle = onPageTitle;
        data.CommentBody = commentBody;
        this.CommentAction = data;
   }
};
// Wrapper to request a review action
ReviewAction = Class();
ReviewAction.prototype = {
   initialize: function(reviewOnThisKey, onPageUrl, onPageTitle, 
                        reviewTitle, reviewRating, reviewBody, reviewPros, reviewCons) {
        var data = new Object();
        data.ReviewOnKey = reviewOnThisKey;
        data.OnPageUrl = onPageUrl;
        data.OnPageTitle = onPageTitle;
        data.ReviewTitle = reviewTitle;
        data.ReviewRating = reviewRating;
        data.ReviewBody = reviewBody;
        data.ReviewPros = reviewPros;
        data.ReviewCons = reviewCons;
        this.ReviewAction = data;
   }
};
// Wrapper to request a recommend action
RecommendAction = Class();
RecommendAction.prototype = {
   initialize: function(recommendThisKey, articleTitle) {
        var data = new Object();
        data.RecommendThisKey = recommendThisKey;
        if(articleTitle){
			data.OnPageTitle = articleTitle;
		}
		
        this.RecommendAction = data;
   }
};
// Wrapper to request a rate action
RateAction = Class();
RateAction.prototype = {
   initialize: function(rateThisKey, rating) {
        var data = new Object();
        data.RateThisKey = rateThisKey;
        data.Rating = rating;
        this.RateAction = data;
   }
};

// Permanently delete a gallery, video or photo
DeleteContentAction = Class();
DeleteContentAction.prototype = {
   initialize: function(deleteThisContent) {
        var data = new Object();
        data.DeleteThisContent = deleteThisContent;
        this.DeleteContentAction = data;
   }
};

// Email from the SiteLife system
EmailContentAction = Class();
EmailContentAction.prototype = {
   initialize: function(toAddress, subject, body) {
        var data = new Object();
        data.ToAddress = toAddress;
        data.Subject = subject;
        data.Body = body;
        this.EmailContentAction = data;
   }
};

// Email from the SiteLife system with user key as target
EmailContentWithUserIDAction = Class();
EmailContentWithUserIDAction.prototype = {
   initialize: function(toUserKey, subject, body) {
        var data = new Object();
        data.UserKey = toUserKey;
        data.Subject = subject;
        data.Body = body;
        this.EmailContentWithUserIDAction = data;
   }
};

// Wrapper to request a report abuse action
ReportAbuseAction = Class();
ReportAbuseAction.prototype = {
   initialize: function(reportThisKey, abuseReason, abuseDescription) {
        var data = new Object();
        data.ReportThisKey = reportThisKey;
        data.AbuseReason = abuseReason;
        data.AbuseDescription = abuseDescription;
        this.ReportAbuseAction = data;
   }
};
// Category used for discovery
Category = Class();
Category.prototype = {
   initialize: function(name) {
        var data = new Object();
        data.Name = name;
        this.Category = data;
   }
};
// Section used for discovery
Section = Class();
Section.prototype = {
    initialize: function(name) {
        var data = new Object();
        data.Name = name;
        this.Section = data;
    }
};
// Update or create an article
UpdateArticleAction = Class();
UpdateArticleAction.prototype = {
   initialize: function(updateArticle, onPageUrl, onPageTitle, section,categories) {
        var data = new Object();
        data.UpdateArticle = updateArticle;
        data.OnPageUrl = onPageUrl;
        data.OnPageTitle = onPageTitle;
        data.Section = section;
        data.Categories = categories;
        this.UpdateArticleAction = data;
   }
};
// Update or create a gallery
UpdateGalleryAction = Class();
UpdateGalleryAction.prototype = {
    initialize: function(updateGallery, galleryType, mediaType, title, description, tags, section, galleryPromo) {
        var data = new Object();
        data.UpdateGallery = updateGallery;
        data.GalleryType = galleryType;
        data.MediaType = mediaType;
        data.Title = title;
        data.Description = description;
        data.Tags = tags;
        data.Section = section;
        data.GalleryPromo = galleryPromo;
        this.UpdateGalleryAction = data;
    }
};
// Update or create a photo
UpdatePhotoAction = Class();
UpdatePhotoAction.prototype = {
    initialize: function(updatePhoto, title, description, tags, section) {
        var data = new Object();
        data.UpdatePhoto = updatePhoto;
        data.Title = title;
        data.Description = description;
        data.Tags = tags;
        data.Section = section;
        this.UpdatePhotoAction = data;
    }
};
// Update or create a video
UpdateVideoAction = Class();
UpdateVideoAction.prototype = {
    initialize: function(updateVideo, title, description, tags, section) {
        var data = new Object();
        data.UpdateVideo = updateVideo;
        data.Title = title;
        data.Description = description;
        data.Tags = tags;
        data.Section = section;
        this.UpdateVideoAction = data;
    }
};
// 
GalleryType = Class();
GalleryType.prototype = {
    initialize: function(name) {
        var data = new Object();
        data.Name = name;
        this.GalleryType = data;
    }
};
// GalleryPromo used for setting promotional text for public galleries
GalleryPromo = Class();
GalleryPromo.prototype = {
    initialize: function(title, body, photoKey) {
        var data = new Object();
        data.Title = title;
        data.Body = body;
        data.PhotoKey = photoKey;
        this.GalleryPromo = data;
    }
};
// UserTier used for discovery
UserTier = Class();
UserTier.prototype = {
    initialize: function(name) {
        var data = new Object();
        data.Name = name;
        this.UserTier = data;
    }
};
// MembershipTier used for community groups
MembershipTier = Class();
MembershipTier.prototype = {
    initialize: function(name) {
        var data = new Object();
        data.Name = name;
        this.MembershipTier = data;
    }
};
// Activity used for discovery
Activity = Class();
Activity.prototype = {
    initialize: function(name) {
        var data = new Object();
        data.Name = name;
        this.Activity = data;
    }
};
// Discovery on articles
DiscoverArticlesAction = Class();
DiscoverArticlesAction.prototype = {
   initialize: function(searchSections,searchCategories,limitToContributors,activity,age,maximumNumberOfDiscoveries) {
        var data = new Object();
        data.SearchSections = searchSections;
        data.SearchCategories = searchCategories;
        data.LimitToContributors = limitToContributors;
        data.Activity = activity;
        data.Age = age;
        data.MaximumNumberOfDiscoveries = maximumNumberOfDiscoveries;

        this.DiscoverArticlesAction = data;
   }
};

// Action used to add a friend
AddFriendAction = Class();
AddFriendAction.prototype = {
    initialize: function(friendUserKey) {
        var data = new Object();
        data.FriendUserKey = friendUserKey;
        this.AddFriendAction = data;
    }
};

// Action used to add a message
AddPersonaMessageAction = Class();
AddPersonaMessageAction.prototype = {
    initialize: function(toUserKey, body) {
        var data = new Object();
        data.ToUserKey = toUserKey;
        data.Body = body;
        this.AddPersonaMessageAction = data;
    }
};

// Action used to remove a message
RemovePersonaMessageAction = Class();
RemovePersonaMessageAction.prototype = {
    initialize: function(personaMessageKey) {
        var data = new Object();
        data.PersonaMessageKey = personaMessageKey;
        this.RemovePersonaMessageAction = data;
    }
};

// Action used to approve a friend
ApproveFriendAction = Class();
ApproveFriendAction.prototype = {
    initialize: function(friendUserKey, isApproved) {
        var data = new Object();
        data.FriendUserKey = friendUserKey;
        data.IsApproved = isApproved;
        this.ApproveFriendAction = data;
    }
};

// Action used to remove a friend
RemoveFriendAction = Class();
RemoveFriendAction.prototype = {
    initialize: function(friendUserKey) {
        var data = new Object();
        data.FriendUserKey = friendUserKey;
        this.RemoveFriendAction = data;
    }
};

// Action used to add an enemy
AddEnemyAction = Class();
AddEnemyAction.prototype = {
    initialize: function(enemyUserKey) {
        var data = new Object();
        data.EnemyUserKey = enemyUserKey;
        this.AddEnemyAction = data;
    }
};

// Action used to remove an enemy
RemoveEnemyAction = Class();
RemoveEnemyAction.prototype = {
    initialize: function(enemyUserKey) {
        var data = new Object();
        data.EnemyUserKey = enemyUserKey;
        this.RemoveEnemyAction = data;
    }
};

// Wrapper to request a friend page
FriendPage = Class();
FriendPage.prototype = {
   initialize: function(userKey, numberPerPage, onPage, isPendingList, filterKey, filterValue) {
        var data = new Object();
        data.UserKey = userKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.IsPendingList = isPendingList;
        data.FilterKey = filterKey;
        data.FilterValue = filterValue;
        this.FriendPage = data;
   }
};

// Wrapper to request if a given user key is a friend of the user specified by the second parameter
// if the userKey parameter is not specified, the currently logged-in user is used
IsFriend = Class();
IsFriend.prototype = {
   initialize: function(friendUserKey, userKey) {
        var data = new Object();
        data.FriendUserKey = friendUserKey;
        data.UserKey = userKey;
        this.IsFriend = data;
   }
};
												
// Wrapper to request a friend page
EnemyPage = Class();
EnemyPage.prototype = {
   initialize: function(userKey, numberPerPage, onPage, sort) {
        var data = new Object();
        data.UserKey = userKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.Sort = sort;
        this.EnemyPage = data;
   }
};
												
// Discovery on content
DiscoverContentAction = Class();
DiscoverContentAction.prototype = {
   initialize: function(searchSections,searchCategories,limitToContributors,activity,contentType,age,maximumNumberOfDiscoveries, filterBySiteOfOrigin, parentKeys) {
        var data = new Object();
        data.SearchSections = searchSections;
        data.SearchCategories = searchCategories;
        data.LimitToContributors = limitToContributors;
        data.Activity = activity;
        data.ContentType = contentType;
        data.Age = age;
        data.MaximumNumberOfDiscoveries = maximumNumberOfDiscoveries;
        data.FilterBySiteOfOrigin = filterBySiteOfOrigin;
        if(parentKeys){
			data.ParentKeys = parentKeys;
		}	
        this.DiscoverContentAction = data;
   }
};

// Content type for discovery
ContentType = Class();
ContentType.prototype = {
    initialize: function(name) {
        var data = new Object();
        data.Name = name;
        this.ContentType = data;
    }
};
												
UpdateUserProfileAction = Class();
UpdateUserProfileAction.prototype = {
   initialize: function(   userKey, 
                            aboutMe, 
                            location,
                            signature,
                            dateOfBirth, 
                            sex, 
                            personaPrivacyMode, 
                            commentsTabVisible, 
                            photosTabVisible, 
                            messagesOpenToEveryone, 
                            isEmailNotificationsEnabled, 
                            selectedStyleId, 
                            customAnswers, 
                            extendedProfile) {
                            
        var data = new Object();
        data.UserKey = userKey;
        data.AboutMe = aboutMe;
        data.Location = location;
        data.Signature = signature;
        data.DateOfBirth = dateOfBirth;
        data.Sex = sex;
		data.PersonaPrivacyMode = personaPrivacyMode;
		data.CommentsTabVisible = commentsTabVisible;
		data.PhotosTabVisible = photosTabVisible;
		data.MessagesOpenToEveryone = messagesOpenToEveryone;
		data.IsEmailNotificationsEnabled = isEmailNotificationsEnabled;
		data.SelectedStyleId = selectedStyleId;
		data.CustomAnswers = customAnswers;
		data.ExtendedProfile = extendedProfile;        
        this.UpdateUserProfileAction = data;
   }
};

UpdateUserBlockedSettingAction = Class();
UpdateUserBlockedSettingAction.prototype = {
    initialize: function( userKey, isBlocked ){
        var data = new Object;
        data.UserKey = userKey;
        data.IsBlocked = isBlocked;
        this.UpdateUserBlockedSettingAction = data;
    }    
};

SearchAction = Class();
SearchAction.prototype = {
   initialize: function(searchType, searchString, numberPerPage, onPage ) {
        var data = new Object();
        data.SearchType = searchType;
        data.SearchString = searchString;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        this.SearchAction = data;
   }
};

// Wrapper to request a watch item page
WatchItemPage = Class();
WatchItemPage.prototype = {
   initialize: function(userKey, numberPerPage, onPage) {
        var data = new Object();
        data.UserKey = userKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        this.WatchItemPage = data;
   }
};

// Wrapper to add a watch item
AddWatchItemAction = Class();
AddWatchItemAction.prototype = {
   initialize: function(userKey, watchTargetKey, title, url ) {
        var data = new Object();
        data.UserKey = userKey;
        data.WatchTargetKey = watchTargetKey;
        data.WatchItemTitle = title;
        data.WatchItemUrl = url;
        this.AddWatchItemAction = data;
   }
};

// Wrapper to delete a watch item
DeleteWatchItemAction = Class();
DeleteWatchItemAction.prototype = {
   initialize: function(userKey, watchTargetKey) {
        var data = new Object();
        data.UserKey = userKey;
        data.WatchTargetKey = watchTargetKey;
        this.DeleteWatchItemAction = data;
   }
};

// Wrapper to request a blog post page
BlogPostPage = Class();
BlogPostPage.prototype = {
   initialize: function(blogKey, numberPerPage, onPage, sort, blogPostState, restrictToOwner, includeFuturePosts) {
        var data = new Object();
        data.BlogKey = blogKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.Sort = sort;
        data.BlogPostState = blogPostState;
        if ((typeof(restrictToOwner) == 'undefined') || (restrictToOwner == null)) {
            // Default to false for backwards compatibility
            restrictToOwner = false;
        }
        data.RestrictToOwner = restrictToOwner.toString();
        if ((typeof(includeFuturePosts) == 'undefined') || (includeFuturePosts == null)) {
            // Default to false for backwards compatibility
            includeFuturePosts = false;
        }
        data.IncludeFuturePosts = includeFuturePosts.toString();
        this.BlogPostPage = data;
   }
};

// Wrapper to request a blog post page by Tag
BlogPostsByTagPage = Class();
BlogPostsByTagPage.prototype = {
   initialize: function(blogKey, tag, numberPerPage, onPage, sort) {
        var data = new Object();
        data.BlogKey = blogKey;
        data.Tag = tag;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.Sort = sort;
        this.BlogPostsByTagPage = data;
   }
};


// Wrapper to request a blog post archive count
BlogPostArchiveCount = Class();
BlogPostArchiveCount.prototype = {
   initialize: function(blogKey) {
        var data = new Object();
        data.BlogKey = blogKey;
        this.BlogPostArchiveCount = data;
   }
};


// Wrapper to request a blog post archive content page
BlogPostArchiveContentPage = Class();
BlogPostArchiveContentPage .prototype = {
   initialize: function(blogKey, month, numberPerPage, onPage, sort) {
        var data = new Object();
        data.BlogKey = blogKey;
        data.Month = month;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.Sort = sort;
        this.BlogPostArchiveContentPage = data;
   }
};


// Wrapper to request a user comment page
UserCommentPage = Class();
UserCommentPage.prototype = {
   initialize: function(userKey, numberPerPage, onPage, sort, commentsOnly) {
        var data = new Object();
        data.UserKey = userKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.Sort = sort;
        data.CommentsOnly = commentsOnly;
        this.UserCommentPage = data;
   }
};


// Wrapper to request blog tag 
RecentBlogTag = Class();
RecentBlogTag.prototype = {
   initialize: function(blogKey) {
        var data = new Object();
        data.BlogKey = blogKey;
        this.RecentBlogTag = data;
   }
};


// Wrapper to request recent user photo page
RecentUserPhotoPage = Class();
RecentUserPhotoPage.prototype = {
   initialize: function(userKey, numberPerPage, onPage) {
        var data = new Object();
        data.UserKey = userKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        this.RecentUserPhotoPage = data;
   }
};

// Wrapper to request recent user video page
RecentUserVideoPage = Class();
RecentUserVideoPage .prototype = {
   initialize: function(userKey, numberPerPage, onPage) {
        var data = new Object();
        data.UserKey = userKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        this.RecentUserVideoPage  = data;
   }
};


// Wrapper to request recent public gallery page
RecentPublicGalleryPage = Class();
RecentPublicGalleryPage .prototype = {
   initialize: function(userKey, numberPerPage, onPage) {
        var data = new Object();
        data.UserKey = userKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        this.RecentPublicGalleryPage  = data;
   }
};
    
    
// Wrapper to request recent user activity page
RecentUserActivity = Class();
RecentUserActivity .prototype = {
   initialize: function(userKey) {
        var data = new Object();
        data.UserKey = userKey;
       this.RecentUserActivity  = data;
   }
};

  
// Wrapper to request page of user media submission counts
UserMediaSubmissionsCountPage = Class();
UserMediaSubmissionsCountPage .prototype = {
    initialize: function(userKey, mediaType, numberPerPage, onPage) {
        var data = new Object();
        data.UserKey = userKey;
        data.MediaType = mediaType;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        this.UserMediaSubmissionsCountPage = data;
    }
};


// Wrapper to request recent forum discussion page
RecentForumDiscussionPage = Class();
RecentForumDiscussionPage .prototype = {
   initialize: function(userKey, numberPerPage, onPage) {
        var data = new Object();
        data.UserKey = userKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        this.RecentForumDiscussionPage = data;
   }
};

    
// Wrapper to request user group forum page
UserGroupForumPage = Class();
UserGroupForumPage .prototype = {
   initialize: function(userKey, numberPerPage, onPage, sort) {
        var data = new Object();
        data.UserKey = userKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.Sort = sort;
        this.UserGroupForumPage = data;
   }
};

// The blogRollEntry used in UpdateBlogAction
BlogRollEntry = Class();
BlogRollEntry.prototype = {
   initialize: function(name, url) {
        var data = new Object();
        data.Name = name;
        data.Url = url;
        this.BlogRollEntry = data;
   }
};

// Bookmark used in UpdateCommunityGroupAction
Bookmark = Class();
Bookmark.prototype = {
    initialize: function(title, link) {
        var data = new Object();
        data.Title = title;
        data.Link = link;
        this.Bookmark = data;
   }
};

// CommunityGroupVisibility used in UpdateCommunityGroupAction
CommunityGroupVisibility = Class();
CommunityGroupVisibility.prototype = {
    initialize: function(name) {
        var data = new Object();
        data.Name = name;
        this.CommunityGroupVisibility = data;
    }
};

// Update or create a blog
UpdateBlogAction = Class();
UpdateBlogAction.prototype = {
   initialize: function(updateBlog, title, tagline, blogRollEntries, blogType) {
        var data = new Object();
        data.BlogKey = updateBlog;
        data.Title = title;
        data.Tagline = tagline;
        data.BlogRollEntries = blogRollEntries;
        data.BlogType = blogType;
        this.UpdateBlogAction = data;
   }
};

// Update or create a blog post, key can be either a post key (update case)
// or a blog key (create case)
UpdateBlogPostAction = Class();
UpdateBlogPostAction.prototype = {
   initialize: function(key, title, body, tags, publishDate, published) {
        var data = new Object();
        data.TargetThis = key;
        data.Title = title;
        data.Body = body;
        data.Tags = tags;
        data.Date = publishDate;
        data.Published = published;
        this.UpdateBlogPostAction = data;
   }
};

// Identify a forum discussion with this DiscussionKey 
DiscussionKey = Class();
DiscussionKey.prototype = {
   initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.DiscussionKey = data;
   }
};

// Identify a custom item with this CustomItemKey
CustomItemKey = Class();
CustomItemKey.prototype = {
   initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.CustomItemKey = data;
   }
};

// Identify a custom collection with this CustomCollectionKey
CustomCollectionKey = Class();
CustomCollectionKey.prototype = {
   initialize: function(key) {
        var data = new Object();
        data.Key = key;
        this.CustomCollectionKey = data;
   }
};

// Update or create a custom item in storage
UpdateCustomItemAction = Class();
UpdateCustomItemAction.prototype = {
   initialize: function(customItemKey, name, mimeType, displayText, content, includeInRecentActivity) {
        var data = new Object();
        data.CustomItemKey = customItemKey;
        data.Name = name;
        data.MimeType = mimeType;
        data.DisplayText = displayText;
        data.Content = content;
        if ((typeof(includeInRecentActivity) == 'undefined') || (includeInRecentActivity == null)) {
            // Default to true for backwards compatibility
            includeInRecentActivity = true;
        }
        data.IncludeInRecentActivity = includeInRecentActivity
        this.UpdateCustomItemAction = data;
   }
};

// Add a new custom collection to storage
AddCustomCollectionAction = Class();
AddCustomCollectionAction.prototype = {
   initialize: function(customCollectionKey, customCollectionName) {
        var data = new Object();
        data.CustomCollectionKey = customCollectionKey;
        data.CustomCollectionName = customCollectionName;
        this.AddCustomCollectionAction = data;
   }
};

// Insert an item into a custom collection
InsertIntoCollectionAction = Class();
InsertIntoCollectionAction.prototype = {
   initialize: function(customCollectionKey, insertThisKey, position) {
        var data = new Object();
        data.CustomCollectionKey = customCollectionKey;
        data.InsertThisKey = insertThisKey;
        data.Position = position;
        this.InsertIntoCollectionAction = data;
   }
};

// Remove an item from a custom collection (position can be null to specify to remove all occurrences of item)
RemoveFromCollectionAction = Class();
RemoveFromCollectionAction.prototype = {
   initialize: function(customCollectionKey, removeThisKey, position) {
        var data = new Object();
        data.CustomCollectionKey = customCollectionKey;
        data.RemoveThisKey = removeThisKey;
        data.Position = position;
        this.RemoveFromCollectionAction = data;
   }
};

// Get a page of items out of a custom collection
CustomCollectionPage = Class();
CustomCollectionPage.prototype = {
   initialize: function(customCollectionKey, numberPerPage, onPage, sort) {
        var data = new Object();
        data.CustomCollectionKey = customCollectionKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.Sort = sort;
        this.CustomCollectionPage = data;
   }
};


// Get a page of items out of a custom collection
EditorMessageRequest = Class();
EditorMessageRequest.prototype = {
   initialize: function() {
      this.EditorMessageRequest = new Object();
   }
};

// Retrieve a user's tags for the given content type
UserTags = Class();
UserTags.prototype = {
   initialize: function(userKey, contentType) {
      var data = new Object();
      data.UserKey = userKey;
      data.ContentType = contentType;
      this.UserTags = data;
   }
};


// Get an item's ContentPolicy
GetContentPolicyAction = Class();
GetContentPolicyAction.prototype = {
    initialize: function(targetKey, userTier, action) {
        var data = new Object();
        data.TargetKey = targetKey;
        data.UserTier = userTier;
        data.ContentPolicyActionType = action;
        this.GetContentPolicyAction = data;
    }
}

// Set an item's ContentPolicy
SetContentPolicyAction = Class();
SetContentPolicyAction.prototype = {
    initialize: function(targetKey, userTier, action, policy) {
        var data = new Object();
        data.TargetKey = targetKey;
        data.UserTier = userTier;
        data.ContentPolicyActionType = action;
        data.ContentPolicy = policy;
        this.SetContentPolicyAction = data;
    }
}

ContentPolicy = Class();
ContentPolicy.prototype = {
    initialize: function(name) {
        var data = new Object();
        data.Name = name;
        this.ContentPolicy = data;
    }
};

ContentPolicyActionType = Class();
ContentPolicyActionType.prototype = {
    initialize: function(name) {
        var data = new Object();
        data.Name = name;
        this.ContentPolicyActionType = data;
    }
};

// Updates a Forum's meta data
UpdateForumAction = Class();
UpdateForumAction.prototype = {
    initialize: function(forumKey, title, description) {
        var data = new Object();
        data.ForumKey = forumKey;
        data.Title = title;
        data.Description = description;
        this.UpdateForumAction = data;
    }
};

//Adds/Updates a Forum Discussion's meta data. If the key is a ForumKey, it will be added as a new Discussion.
//If the key is a ForumDiscussionKey, the existing forum discussion will be updated.
UpdateForumDiscussionAction = Class();
UpdateForumDiscussionAction.prototype = {
    initialize: function(key, title, body, isQuestion, isPoll) {
        var data = new Object();
        data.TargetThis = key;
        data.Title = title;
        data.Body = body;
        data.IsQuestion = typeof(isQuestion) == 'string' ? isQuestion : (isQuestion ? "true" : "false");
        data.IsPoll = typeof(isPoll) == 'string' ? isPoll : (isPoll ? "true" : "false");
        this.UpdateForumDiscussionAction = data;
    }
};

//Adds/Updates a Forum Post's meta data. If the key is a ForumDiscussionKey, it will be added as a new Post.
//If the key is a ForumPostKey, the existing forum post will be updated.
UpdateForumPostAction = Class();
UpdateForumPostAction.prototype = {
    initialize: function(key, title, body, isQuestion) {
        var data = new Object();
        data.TargetThis = key;
        data.Title = title;
        data.Body = body;
        data.IsQuestion = isQuestion;
        this.UpdateForumPostAction = data;
    }
};

//Updates a Forum Discussion's Sticky flag
ForumToggleDiscussionStickyAction = Class();
ForumToggleDiscussionStickyAction.prototype = {
    initialize: function(discussionKey) {
        var data = new Object();
        data.DiscussionKey = discussionKey;
        this.ForumToggleDiscussionStickyAction = data;
    }
};

//Opens/Closes a Forum Discussion
ForumToggleDiscussionClosedAction = Class();
ForumToggleDiscussionClosedAction.prototype = {
    initialize: function(discussionKey) {
        var data = new Object();
        data.DiscussionKey = discussionKey;
        this.ForumToggleDiscussionClosedAction = data;
    }
};

//Retrieves a paginated list of Discussions for a particular Forum
ForumDiscussionsPage = Class();
ForumDiscussionsPage.prototype = {
    initialize: function(forumKey, numberPerPage, oneBasedOnPage, sort) {
        var data = new Object();
        data.ForumKey = forumKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = oneBasedOnPage;
        data.Sort = sort;
        this.ForumDiscussionsPage = data;
    }
};

//Retrieves a paginated list of Posts for a particular Forum
ForumPostsPage = Class();
ForumPostsPage.prototype = {
    initialize: function(forumDiscussionKey, numberPerPage, oneBasedOnPage, sort, findPostKey) {
        var data = new Object();
        data.DiscussionKey = forumDiscussionKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = oneBasedOnPage;
        data.Sort = sort;
        data.FindPostKey = findPostKey;
        this.ForumPostsPage = data;
    }
};

//Retrieves a paginated list of forums for a particular category
ForumCategoriesPage = Class();
ForumCategoriesPage.prototype = {
    initialize: function(numberPerPage, oneBasedOnPage) {
        var data = new Object();
        data.NumberPerPage = numberPerPage;
        data.OnPage = oneBasedOnPage;
        this.ForumCategoriesPage = data;
    }
};

//Retrieves a paginated list of forums for a particular category
ForumsPage = Class();
ForumsPage.prototype = {
    initialize: function(categoryKey, numberPerPage, oneBasedOnPage, sort) {
        var data = new Object();
        data.ForumCategoryKey = categoryKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = oneBasedOnPage;
        data.Sort = sort;
        this.ForumsPage = data;
    }
};

ForumSearchAction = Class();
ForumSearchAction.prototype = {
    initialize: function(searchKey, searchString, numberPerPage, onPage) {
        var data = new Object();
        data.TargetThis = searchKey;
        data.SearchString = searchString;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        this.ForumSearchAction = data;
    }
};

// Retrieves a paginated list of community groups
CommunityGroupPage = Class();
CommunityGroupPage.prototype = {
    initialize: function(numberPerPage, oneBasedOnPage, sort, section) {
        var data = new Object();
        data.NumberPerPage = numberPerPage;
        data.OnPage = oneBasedOnPage;
        data.Sort = sort;
        if ((typeof(section) == 'undefined') || (section == null)) {
            // Default section to All
            section = new Section("All");
        }
        data.Section = section;
        this.CommunityGroupPage = data;
    }
};

// Retrieves a paginated list of community groups
CommunityGroupMembership = Class();
CommunityGroupMembership.prototype = {
    initialize: function(groupKey, userKey) {
        var data = new Object();
        data.CommunityGroupKey = groupKey;
        data.UserKey = userKey;
        this.CommunityGroupMembership = data;
    }
};


// Retrieves a paginated list of community groups
CommunityGroupMembershipPage = Class();
CommunityGroupMembershipPage.prototype = {
    initialize: function(key, numberPerPage, oneBasedOnPage, sort, membershipFilter) {
        var data = new Object();
        data.Key = key;
        data.NumberPerPage = numberPerPage;
        data.OnPage = oneBasedOnPage;
        data.Sort = sort;
        data.MembershipFilter = membershipFilter;
        this.CommunityGroupMembershipPage = data;
    }
};

// Retrieves a paginated list of registrants
CommunityGroupRegistrantPage = Class();
CommunityGroupRegistrantPage.prototype = {
    initialize: function(key, numberPerPage, oneBasedOnPage, sort) {
        var data = new Object();
        data.CommunityGroupKey = key;
        data.NumberPerPage = numberPerPage;
        data.OnPage = oneBasedOnPage;
        data.Sort = sort;
        this.CommunityGroupRegistrantPage = data;
    }
};

// Retrieves a paginated list of banned users
CommunityGroupBannedUserPage = Class();
CommunityGroupBannedUserPage.prototype = {
    initialize: function(key, numberPerPage, oneBasedOnPage, sort) {
        var data = new Object();
        data.CommunityGroupKey = key;
        data.NumberPerPage = numberPerPage;
        data.OnPage = oneBasedOnPage;
        data.Sort = sort;
        this.CommunityGroupBannedUserPage = data;
    }
};

// Retrieves a paginated list of invited users
CommunityGroupInvitedUserPage = Class();
CommunityGroupInvitedUserPage.prototype = {
    initialize: function(key, numberPerPage, oneBasedOnPage, sort) {
        var data = new Object();
        data.CommunityGroupKey = key;
        data.NumberPerPage = numberPerPage;
        data.OnPage = oneBasedOnPage;
        data.Sort = sort;
        this.CommunityGroupInvitedUserPage = data;
    }
};



// Creates a new or updates an existing community group
UpdateCommunityGroupAction = Class();
UpdateCommunityGroupAction.prototype = {
    initialize: function(key, title, description, categories, visibility, bookmarks, section, photoKey) {
        var data = new Object();
        data.CommunityGroupKey = key;
        data.Title = title;
        data.Description = description;
        data.Categories = categories;
        data.Visibility = visibility,
        data.Bookmarks = bookmarks;        
        data.Section = section;
        data.PhotoKey = photoKey;
        this.UpdateCommunityGroupAction = data;
    }
};

// Updates an existing commnity group's bookmarks
UpdateCommunityGroupBookmarksAction = Class();
UpdateCommunityGroupBookmarksAction.prototype = {
    initialize: function(key, bookmarks) {
        var data = new Object();
        data.CommunityGroupKey = key;
        data.Bookmarks = bookmarks;        
        this.UpdateCommunityGroupBookmarksAction = data;
    }
};

// Creates or updates a user's membership in a group, with options to ban the user from the group.
UpdateCommunityGroupMembershipAction = Class();
UpdateCommunityGroupMembershipAction.prototype = {
    initialize: function(communityGroupKey, userKey, membershipTier, isBanned, banMessage) {
        var data = new Object();
        data.CommunityGroupKey = communityGroupKey;
        data.UserKey = userKey;
        data.MembershipTier = membershipTier;
        data.IsBanned = isBanned;
        data.BanMessage = banMessage;
        this.UpdateCommunityGroupMembershipAction = data;
    }
};

// Enables a user to request membership in a community group or an admin to invite a non-member.
RequestCommunityGroupMembershipAction = Class();
RequestCommunityGroupMembershipAction.prototype = {
    initialize: function(communityGroupKey, userKey, message) {
        var data = new Object();
        data.CommunityGroupKey = communityGroupKey;
        data.UserKey = userKey;
        data.Message = message;
        this.RequestCommunityGroupMembershipAction = data;
    }
};

//Retrieves a paginated list of Events for a particular EventSetKey
EventsPage = Class();
EventsPage.prototype = {
    initialize: function(eventSetKey, startDate, endDate,numberPerPage, oneBasedOnPage, sort) {
        var data = new Object();
        data.EventSetKey = eventSetKey;
        data.StartDate = startDate;
        data.EndDate = endDate;
        data.NumberPerPage = numberPerPage;
        data.OnPage = oneBasedOnPage;
        data.Sort = sort;
        this.EventsPage = data;
    }
};

// Update or creates an Event, key can be either an EventKey (update case)
// or an EventSetKey (create case)
UpdateEventAction = Class();
UpdateEventAction.prototype = {
    initialize: function(key, title, description, location, bookmarkName, bookmarkUrl, startDate, endDate, utcOffset) {
        var data = new Object();
        data.TargetThis = key;
        data.Title = title;
        data.Description = description;
        data.Location = location;
        data.BookmarkName = bookmarkName;
        data.BookmarkUrl = bookmarkUrl;
        data.StartDate = startDate;
        data.EndDate = endDate;
        data.UtcOffset = utcOffset;
        this.UpdateEventAction = data;
    }
};


// Retrieve a paginated list of recent group activities
RecentMiniFeedActivity = Class();
RecentMiniFeedActivity.prototype = {
    initialize: function(communityGroupKey, onPage, numberPerPage) {
        var data = new Object();
        data.CommunityGroupKey = communityGroupKey;
        data.OnPage = onPage;
        data.NumberPerPage = numberPerPage
        this.RecentMiniFeedActivity = data;
    }
}

//Retrieve a list of Most Active Users in a CommunityGroup
CommunityGroupMostActiveMembers = Class();
CommunityGroupMostActiveMembers.prototype = {
    initialize: function(communityGroupKey, age, maximumNumberOfMembers) {
        var data = new Object();
        data.CommunityGroupKey = communityGroupKey;
        data.Age = age;
        data.MaximumNumberOfMembers = maximumNumberOfMembers
        this.CommunityGroupMostActiveMembers = data;
    }
}

// perform a search for content within a specific community group
CommunityGroupSearchAction = Class();
CommunityGroupSearchAction.prototype = {
    initialize: function(communityGroupKey, searchType, searchString, numberPerPage, onPage) {
        var data = new Object();
        data.CommunityGroupKey = communityGroupKey;
        data.SearchType = searchType;
        data.SearchString = searchString;
        data.OnPage = onPage;
        data.NumberPerPage = numberPerPage;
        this.CommunityGroupSearchAction = data;
    }
}

// perform a search for content within a specific community group
RequestDeleteCommunityGroupAction = Class();
RequestDeleteCommunityGroupAction.prototype = {
    initialize: function(communityGroupKey, deleteReason) {
        var data = new Object();
        data.CommunityGroupKey = communityGroupKey;
        data.DeleteReason = deleteReason;
        this.RequestDeleteCommunityGroupAction = data;
    }
}

CommunityGroupRecentForumDiscussions = Class();
CommunityGroupRecentForumDiscussions.prototype = {
    initialize: function(communityGroupKey, age, maximumNumberOfDiscussions) {
        var data = new Object();
        data.CommunityGroupKey = communityGroupKey;
        data.Age = age;
        data.MaximumNumberOfDiscussions = maximumNumberOfDiscussions;
        this.CommunityGroupRecentForumDiscussions = data;
    }
}


SystemTimeInfo = Class();
SystemTimeInfo.prototype = {
    initialize: function(){
        var data = new Object();
        this.SystemTimeInfo = data;
    }
}

PrivateMessageFolderList = Class();
PrivateMessageFolderList.prototype = {
    initialize: function(){
        var data = new Object();
        this.PrivateMessageFolderList = data;
    }
}


PrivateMessage = Class();
PrivateMessage.prototype = {
    initialize: function(folderID, messageID){
        var data = new Object();
        data.FolderID = folderID;
        data.MessageID = messageID;
        this.PrivateMessage = data;
    }
}

PrivateMessagePage = Class();
PrivateMessagePage.prototype = {
    initialize: function(folderID, numberPerPage, onPage, messageReadState){
        var data = new Object();
        data.FolderID = folderID;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.MessageReadState = messageReadState;
        this.PrivateMessagePage = data;
    }
}

PrivateMessageSendAction = Class();
PrivateMessageSendAction.prototype = {
    initialize: function(subject, body, recipientList){
        var data = new Object();
        data.Subject = subject;
        data.Body = body;
        data.RecipientList = recipientList;
        this.PrivateMessageSendAction = data;
    }
}

PrivateMessageMoveMessageAction = Class();
PrivateMessageMoveMessageAction.prototype = {
    initialize: function(sourceFolderID, destinationFolderID, messageIDList){
        var data = new Object();
        data.SourceFolderID = sourceFolderID;
        data.DestinationFolderID = destinationFolderID;
        data.MessageIDList = messageIDList;
        this.PrivateMessageMoveMessageAction = data;
    }
}

PrivateMessageDeleteMessageAction = Class();
PrivateMessageDeleteMessageAction.prototype = {
    initialize: function(sourceFolderID, messageIDList){
        var data = new Object();
        data.SourceFolderID = sourceFolderID;
        data.MessageIDList = messageIDList;
        this.PrivateMessageDeleteMessageAction = data;
    }
}

PrivateMessageEmptyTrashAction = Class();
PrivateMessageEmptyTrashAction.prototype = {
    initialize: function(){
        var data = new Object();
        this.PrivateMessageEmptyTrashAction = data;
    }
}


PrivateMessageCreateFolderAction = Class();
PrivateMessageCreateFolderAction.prototype = {
    initialize: function(){
        var data = new Object();
        data.FolderID = "Inbox";
        this.PrivateMessageCreateFolderAction = data;
    }
}

FirstUnreadPost = Class();
FirstUnreadPost.prototype = {
	initialize: function(discussionKey, numberPerPage, sort){
		var data = new Object();
		data.DiscussionKey = discussionKey;
        data.NumberPerPage = numberPerPage;
        data.Sort = sort;
        this.FirstUnreadPost = data;
	}
}

LatestPost = Class();
LatestPost.prototype = {
	initialize: function(discussionKey, numberPerPage, sort){
		var data = new Object();
		data.DiscussionKey = discussionKey;
        data.NumberPerPage = numberPerPage;
        data.Sort = sort;
        this.LatestPost = data;
	}
}

UpdateDiscussionLastReadAction = Class();
UpdateDiscussionLastReadAction.prototype = {
	initialize: function(discussionKey, postKey, forceUpdate){
		var data = new Object();
		data.DiscussionKey = discussionKey;
		if(postKey){
			data.ForumPostKey = postKey;
		}
		if(forceUpdate){
			data.ForceUpdate = true;
		}
		else{
			data.ForceUpdate = false;
		}
		this.UpdateDiscussionLastReadAction = data;
	}
}

UpdateExternalUserIdAction = Class();
UpdateExternalUserIdAction.prototype = {
	initialize: function(externalSiteName, externalSiteUserId, forUser){
		var data = new Object();
		data.ExternalSiteName = externalSiteName;
		data.ExternalSiteUserId = externalSiteUserId;
		data.ForUser = forUser;
		this.UpdateExternalUserIdAction = data;
	}
}

UpdateSubscriptionAction = Class();
UpdateSubscriptionAction.prototype = {
    initialize: function(discussionKey, subscribe){
        var data = new Object();
        data.DiscussionKey = discussionKey;
        data.Subscribe = subscribe;
        this.UpdateSubscriptionAction = data;
    }
}

UpdatePollAction = Class();
UpdatePollAction.prototype = {
    initialize: function(pollOnKey, question, answers) {
        var data = new Object();
        data.PollOnKey = pollOnKey;
        data.Question = question;
        data.Answers = answers;
        this.UpdatePollAction = data;
    }
}

TogglePollIsClosedAction = Class();
TogglePollIsClosedAction.prototype = {
    initialize: function(pollKey) {
        var data = new Object();
        data.ToggleThisPoll = pollKey;
        this.TogglePollIsClosedAction = data;
    }
}

PostPollAnswerAction = Class();
PostPollAnswerAction.prototype = {
    initialize: function(pollToAnswer, indexOfAnswer) {
        var data = new Object();
        data.PollToAnswer = pollToAnswer;
        data.IndexOfAnswer = indexOfAnswer;
        this.PostPollAnswerAction = data;
    }
}

PollPage = Class();
PollPage.prototype = {
    initialize: function(pollOnKey, numberPerPage, onPage, sort) {
        var data = new Object();
        data.PollOnKey = pollOnKey;
        data.NumberPerPage = numberPerPage;
        data.OnPage = onPage;
        data.Sort = sort;
        this.PollPage = data;
    }
}

CheckFilteredWords = Class();
CheckFilteredWords.prototype = {
    initialize: function(keyValueDictionary) { // key is the string ID, value is the string to be checked - formatted like { "key1":"string1", "key2":"string2" }.
        var data = new Object();
        data.WordDictionary = keyValueDictionary;
        this.CheckFilteredWords = data;
    }
}

//Points&Badging
AwardPointsAction = Class();
AwardPointsAction.prototype = {
    initialize: function(userKey, points, currencyType) { 
        var data = new Object();
        data.UserKey = userKey;
        data.Points = points;
        data.CurrencyType = currencyType;
        this.AwardPointsAction = data;
    }
}

BadgeFamily = Class();
BadgeFamily.prototype = {
    initialize: function(badgeFamilyKey) { 
        var data = new Object();
        data.BadgeFamilyKey = badgeFamilyKey;
        this.BadgeFamily = data;
    }
}

BadgeFamilies = Class();
BadgeFamilies.prototype = {
    initialize: function() { 
        var data = new Object();        
        this.BadgeFamilies = data;
    }
}

BadgingEventAction = Class();
BadgingEventAction.prototype = {
    initialize: function(activityName, activityTags, userTags) { 
        var data = new Object();
        data.ActivityName = activityName;
        data.ActivityTags = activityTags
        data.UserTags = userTags;
        this.BadgingEventAction = data;
    }
}

GrantBadgeAction = Class();
GrantBadgeAction.prototype = {
    initialize: function(userKey, badgeFamilyKey, badgeKey) { 
        var data = new Object();
        data.UserKey = userKey;
        data.BadgeFamilyKey = badgeFamilyKey
        data.BadgeKey = badgeKey;
        this.GrantBadgeAction = data;
    }
}

Leaderboard = Class();
Leaderboard.prototype = {
    initialize: function(leaderboardKey) { 
        var data = new Object();
        data.LeaderboardKey = leaderboardKey;
        this.Leaderboard = data;
    }
}

Leaderboards = Class();
Leaderboards.prototype = {
    initialize: function() { 
        var data = new Object();        
        this.Leaderboards = data;
    }
}

LeaderboardRankingsPage = Class();
LeaderboardRankingsPage.prototype = {
    initialize: function(leaderboardKey, oneBasedOnPage) { 
        var data = new Object();
        data.LeaderboardKey = leaderboardKey;
        data.OnPage = oneBasedOnPage;
        this.LeaderboardRankingsPage = data;
    }
}

RevokeBadgeAction = Class();
RevokeBadgeAction.prototype = {
    initialize: function(userKey, badgeFamilyKey, badgeKey) { 
        var data = new Object();
        data.UserKey = userKey;
        data.BadgeFamilyKey = badgeFamilyKey
        data.BadgeKey = badgeKey;
        this.RevokeBadgeAction = data;
    }
}

PointsAndBadgingRuleValidationAction = Class();
PointsAndBadgingRuleValidationAction.prototype = {
    initialize: function(rules) { 
        var data = new Object();
        data.Rules = rules;
        this.PointsAndBadgingRuleValidationAction = data;
    }
}

AbuseItemPage = Class();
AbuseItemPage.prototype = {
	initialize: function(numberPerPage, onPage, section, maxReportsPerItem){
		var data = new Object();
		data.NumberPerPage = numberPerPage;
		data.OnPage = onPage;
		data.Section = section;
		data.MaxReportsPerItem = maxReportsPerItem;
		this.AbuseItemPage = data;
	}
}

AbuseItem = Class();
AbuseItem.prototype =  {
	initialize: function(targetKey){
		var data = new Object();
		data.TargetKey = targetKey;
		this.AbuseItem = data;
	}
}

ClearAbuseAction = Class();
ClearAbuseAction.prototype =  {
	initialize: function(targetKey){
		var data = new Object();
		data.TargetKey = targetKey;
		this.ClearAbuseAction = data;
	}
}

SetCommentBlockingStateAction = Class();
SetCommentBlockingStateAction.prototype = {
	initialize: function(commentKey, blockingState){
		var data = new Object();
		data.CommentKey = commentKey;
		data.CommentBlockingState = blockingState;
		this.SetCommentBlockingStateAction = data;
	}
}
	
})();
/** MI_SiteLife.js *************************************************************
 * @fileoverview MI modifications to the gSiteLife object.
 *
 * <p>These mods apply for simple widget functionality and this file should be
 * included immediately after the scripts included from Pluck.</p>
 *
 * <p>Everything should be namespaced into the gSiteLife.mi object.</p>
 *
 * @author Joe Whetzel
 * @namespace gSiteLife.mi
 * @minify true
 */

gSiteLife.mi = {};

// variable setting the default location to return to after submitting a
// comment, the argument identifies to Omniture that a Pluck comment has been
// submitted.
//The qwxq variable is filled with a random value to force page reload upon multiple submissions
var urlTS = new Date();
gSiteLife.mi.commenting = {
	submitReturnAddress: 'http://' + location.host + location.pathname + "?mi_pluck_action=comment_submitted&qwxq="+Math.floor(Math.random()*10000)+urlTS.getMilliseconds()+"#Comments_Container"
};

/**
 * Returns boolean true or false indicating whether or not the current user is 
 * logged in. Status is determined via agreement by both Pluck and Insite, 
 * meaning if either doesn't recognize you as logged in you're not.
 * To determine this function checks the availability of the Pluck HD or AT
 * cookie, and the Insite *_user_auth cookie.
 * For efficiency, if the variable isn't set the results will be stored in 
 * gSiteLife.mi.loggedIn for future reference.
 * @type Boolean
 * @return Whether or not the current user is logged in or not.
 */
gSiteLife.mi.userLoggedIn = function() {
	if (this.loggedIn === undefined) {
		var cookies=document.cookie.split(';');
		var insiteCrumb = false;
		var pluckCrumb = false;
		for (var i=cookies.length-1; i>=0; i--) {
			if (cookies[i].match(/^\s*AT=/) || cookies[i].match(/^\s*HD=/)) { pluckCrumb=true; }
			else if (cookies[i].match(/_user_auth=/)) { insiteCrumb=true; }
		}
		this.loggedIn = (insiteCrumb && pluckCrumb);
	}
	return this.loggedIn;
};
/** MI_SiteLife.js ^ ******************************************************** *//** nyxMain.js *****************************************************************
 * @fileOverview
 * Nyx is not just the goddess of the night, she's also a mini-library of DAAPI reference gadgets.
 * 
 * This file includes scripts used throughout Nyx; defines:
 * <li>(if needed) console -- a safety wrapper for Firebug-type logging calls</li>
 * 
 * Everything (except console) is namespaced into the global object NYX.
 * 
 * @author Glen Ford (glenford [at] yahoo.com)
 * @namespace NYX
 * @minify true
 */

//create the wrapper object for the namespace (with version number and other key defaults)
var NYX = {
	version: "0.6"
};

/* goof-proof calls to the console -- IMMEDIATE EXECUTION HERE
 * Defines a console object (with "empty" methods) as needed; allows code in any browser to
 * call Firebug console methods without error. Doesn't overwrite existing console so as to not
 * interfere with Safari's console. The Firebug methods array should be maintained in sync with
 * the actual Firebug console.
 * 
 * TODO: this could be enhanced to make dir do something meaningful in the Safari console
 */
NYX.fixConsole = function() {
	if (typeof window.console != "object") {window.console = {};}
	if (window.console.isNyxxed) {/*already fixed*/}
	else {
		var firebugMethods = ["log","debug","info","warn","error","assert","dir","dirxml",
			"trace","group","groupEnd","time","timeEnd","profile","profileEnd","count"];
		for (var methodIdx = 0; methodIdx < firebugMethods.length; methodIdx++) {
			var methodName = firebugMethods[methodIdx];
			if (typeof window.console[methodName] != "function") {window.console[methodName] = function(){};}
		}
	}
	//add our tracking flag
	window.console.isNyxxed = true;
};
NYX.fixConsole();


//now let's report the version (totally optional)
console.info("Nyx library loaded, version " + NYX.version);



//the cache is a hash for object instances to store "globals" without affecting the window namespace
NYX.cache = {};




/* this apparently fixes the horrid IE Operation Aborted error pretty simply;
 * based on a trick by Diego Perini -- http://javascript.nwbox.com/IEContentLoaded/
 * (it's an object instance in order to handle objects parameters sent to the action function)
 */
NYX.ieSafeExecution = function() {
	//store this in a closure, in case we do asynchronous operation
	var This = this;
	
	//a setting
	this.timeoutLength = 200;	//millis
	
	//the first argument must be the function to call; any remaining arguments get passed to that function
	if (typeof arguments[0] != "function") {
		throw("First parameter to NYX.ieSafeExecution is required and must be a function");
	} else {
		this.functionToCall = arguments[0];
	}
	
	this.execute = function() {
		//on the first call, we need to cache the arguments
		if (typeof This.arguments == "undefined") {This.arguments = arguments;}
		
		if ( typeof document.body.attachEvent == "object" && (document.readyState != "loaded" && document.readyState != "complete") ) {
			//document.title += "[IE]"; //for visual debugging
			if (typeof console == "object") {console.log("in the IE block");}
			try {
				//document.title += "^trying^"; //for visual debugging
				document.documentElement.doScroll("left");
				This.functionToCall.apply(This.functionToCall, This.arguments);
			} catch(error) {
				setTimeout(This.execute, This.timeoutLength);
			}
		} else {
			if (typeof console == "object") {console.log("executing immediately");}
			This.functionToCall.apply(This.functionToCall, This.arguments);
		}
	};
};


//NYX utilities
NYX.util = {};

NYX.util.makePuid = function(optExtraDigits, optBase) {
	/* returns a string based on the current time and a pseudorandom number that is 
	 * _probably_ unique... not quite a GUID, but pretty secure
	 * pass a larger number for optExtraDigits for more security
	 * optBase controls how the number gets converted -- a higher number results in a smaller string
	 */
	var timeSeed, rnd, puid;
	if (typeof optExtraDigits != "number") {optExtraDigits = 5;}
	if (typeof optBase != "number") {optBase = 32;}
	timeSeed = ( new Date().valueOf() ) - Date.parse("1/1/2008");
	rnd = Math.random().toString().substr(2, optExtraDigits); //expects Math.random to return x.YYY...
	puid = parseInt(timeSeed + "" + rnd).toString(optBase);
	
	return puid;
};

NYX.util.querystring = {
	/**
	 * @return {String} the value of the specified querystring parameter;
	 * 					null if the variable isn't defined
	 * @param {String} name				Name of the QS variable
	 */
	get: function(name) {
		var key = name + "=";
		var nameValuePairs = document.location.search.substring(1).split("&");
		for (var pairIdx = 0; pairIdx < nameValuePairs.length; pairIdx++) {
			if ( nameValuePairs[pairIdx].indexOf(key) === 0 ) {
				return nameValuePairs[pairIdx].substring(key.length);
			}
		}
		return null;
	}
	,
	/**
	 * Sets or adds the specified querystring parameter. Returns the querystring with a 
	 * leading "?" even if it didn't have one before.
	 * 
	 * <p><i>Notes:</i>
	 * 	If the parameter exists, it <b>must</b> have the trailing equals sign, even if the value is empty.
	 * 	Names are case sensitive.
	 * </p>
	 * 
	 * @return {String} <code>location.search</code> or the optional querystring argument
	 * 					with the given parameter set to the value passed.
	 * @param {String} name				Name of the QS variable
	 * @param {String} value			Value to set
	 * @param {String} [optExistingQS]	QS to use (defaults to location.search)
	 */
	set: function(name, value, optExistingQS) {
		//get the qs to work with 
		var qs;
		if (typeof optExistingQS != "string") {
			qs = location.search;
		} else {
			qs = optExistingQS;
		}
		var theReturn = qs;
		
		if (typeof value == "undefined") {value = "";}
		
		//escape the name-value pair
		var nvp = encodeURI(name + "=" + value);
		
		if (qs === "") {
			theReturn = nvp;
		} else if ( !NYX.util.string.contains(qs, name) ) {
			theReturn = qs + "&" + nvp;
		} else {
			//use a regex to replace the variable
			var regex = new RegExp("(" + name + "=[^&^]*)", "gi");
			
			//this test also loads the global RegExp object
			var qsm = qs.match(regex);
			if ( qsm !== null ) {
				theReturn = qs.replace(qsm, nvp);
			}
		}
		
		if ( !NYX.util.string.startsWith(theReturn, "?") ) {theReturn = "?" + theReturn;}
		return theReturn;
	}
};

NYX.util.obj = {
	/** 
	 * Mimics the Java <code>extends</code> keyword.
	 * Copies all members (properties and methods) from the parent into the target.
	 * <p>In addition to inheritance, it's useful for copying "parameter bags" (JSON objects) into an instance.</p>
	 * <p>To override members, change them after the <code>extendObj</code> call.</p>
	 * @param {Object} targetClass	The child class to modify.
	 * @param {Object} parentClass	The class to extend from.
	 */
	extend: function(targetClass, parentClass) {
		for (var member in parentClass) {
			targetClass[member] = parentClass[member];
		}
		return targetClass;
	}
};

NYX.util.array = {
	contains: function(theArray, match) {
		if (theArray.length) {
			for (var idx = 0; idx < theArray.length; idx++) {
				if (theArray[idx] == match) {
					return true;
				}
			}
		}
		return false;	//if we get here, there's no match
	}
};

NYX.util.string = {
	/**
	 * Checks source for presence of match. Source is converted to a string as needed,
	 * but that doesn't guarantee this will work for arrays. The caller must manipulate arrays as needed
	 * if using this function to check for an element.
	 * 
	 * @return {Boolean} true if the string contains match
	 * 
	 * @param {String} source	string to search through
	 * @param {String} match	string to search for
	 * @param {Boolean} [optIgnoreCase]	if true, case is ignored
	 */
	contains: function(source, match, optIgnoreCase) {
		if (optIgnoreCase) {
			source = source.toLowerCase();
			match  = match.toLowerCase();
		}
		return (source.indexOf(match) > -1);
	}
	,
	/**
	 * @return {String} this string with all occurrences of the substring replaced
	 * @param {String} source	string to search through
	 * @param {String} match		The sub-string to kill
	 * @param {String} replacement	
	 */
	replaceAll: function(source, match, replacement) {
		// in js regular expressions the $ character paired with some others represents
		// a special replacement pattern, so we replace $ with a custom pattern
		// after everything is done replacing we then go back and replace our custom
		// pattern with the desired $
		replacement = replacement.replace(/\$/g, 'tom MI.dollar sawyer');
		while ( this.contains(source, match) ) {
			source = source.replace(match, replacement);
		}
		source = source.replace(/tom MI\.dollar sawyer/g,'$');
		return source;
	}
	,
	/**
	 * @return {String} A 0-length string for nulls/undefined argument; else the argument as a string.
	 */
	ensure: function(arg) {
		//converts arg to a string even if it is null, etc.
		if (typeof arg == "string") {return arg;}
		if (arg === null || typeof arg == "undefined") {return "";}
		return arg.toString();
	}
	,
	/** Replaces leading and trailing whitespace. */
	trim: function(stringToTrim) {
		stringToTrim = this.ensure(stringToTrim);
		return stringToTrim.replace(/(^\s+|\s+$)/g, "");
	}
	,
	/** @return {Boolean} true if the string passed is 0-length or only whitespace */
	isBlank: function(source) {
		return (this.trim(source) === "");
	}
	,
	/** 
	 * @return {Boolean} true if the string starts with the fragment passed (case-sensitive)
	 * @param {String} source	string to search through
	 * @param {String} match	Fragment to look for
	 * @param {Boolean} [optIgnoreCase]	if true, case is ignored
	 */
	startsWith: function(source, match, optIgnoreCase) {
		return ( source.substring(0, match.length) == match );
	}
	,
	/** 
	 * @return {Boolean} true if the string ends with the fragment passed (case-sensitive)
	 * @param {String} source	string to search through
	 * @param {String} match	Fragment to look for
	 * @param {Boolean} [optIgnoreCase]	if true, case is ignored
	 */
	endsWith: function(source, match, optIgnoreCase) {
		if (optIgnoreCase) {
			source = source.toLowerCase();
			match  = match.toLowerCase();
		}
		return ( source.substring(source.length - match.length) == match );
	}
};

NYX.util.dom = {
	/**
	 * Returns an array of <b>direct</b> child elements that have the given 
	 * CSS class. (This is based on Prototype, but their way causes weird bugs in IE.)
	 * 
	 * @return {DOM:Element[]} Returns an empty array if nothing found.
	 * @param {String} 		className to match
	 * @param {DOM:Element}	[optElem]	if not passed, <code>document.body</code> is used
	 */
	getElementsByClass: function(className, optElem) {
		var theReturn = [];
		if (typeof optElem == "undefined") {var elem = document.body;}
		
		var children = elem.getElementsByTagName("*");
		for (var childIdx = 0; childIdx < children.length; childIdx++) {
			var child = children[childIdx];
			if ( typeof child.className == "string" && this.elemHasClass(child, className) ) {
				theReturn.push(child);
			}
		}
		return theReturn;
	},
	/**
	 * @return {Boolean} True if the DOM element has the CSS class applied to it.
	 * @param {DOM:Element}	elem		
	 * @param {String} 		className	
	 */
	elemHasClass: function(elem, className) {
		var currentClasses = elem.className.toLowerCase().split(/\s+/g);
		return NYX.util.array.contains( currentClasses, className.toLowerCase() );
	}
};

//constructors
NYX.TemplateTool = { //"ABSTRACT" superclass!
	//template part names -- internal use, but can be overridden
	DOM_TARGET_SUFFIX:  "dynamicContent",
	DOM_WAITMSG_SUFFIX: "waitMsg",
	
	//classes for item coloring (see below)
	ALT_CLASS_2: "nyx2",
	ALT_CLASS_3: "nyx3",
	
	getElem: function(idSuffix) {
		return document.getElementById(this.idRoot + "_" + idSuffix);
	}
	,
	getIndexedElem: function(idSuffix, index) {
		return document.getElementById(this.idRoot + "_" + idSuffix + "_" + index);
	}
	,
	showElem: function(idSuffix) {
		var elem = this.getElem(idSuffix);
		if (elem !== null) {elem.style.display = "";}
	}
	,
	flattenDaapiItem: function(daapiItem) {
		var flatData = {};
		for (var child in daapiItem) {
			if (daapiItem[child] === null) {
				flatData[child] = null;
			} else if (typeof daapiItem[child] != "object") {
				//scalar value
				flatData[child] = daapiItem[child];
			} else {
				//non-scalar, so recurse
				if (typeof daapiItem[child].join == "function" && typeof daapiItem[child].length == "number") {
					//we're going to assume it's an array and just assign it
					flatData[child] = daapiItem[child];
				} else {
					//we have an object, so recurse one level and set members that haven't already been set
					for (var grandchild in daapiItem[child]) {
						if (typeof flatData[grandchild] == "undefined") {flatData[grandchild] = daapiItem[child][grandchild];}
					}
				}
			}
		}
		return flatData;
	}
	,
	processTemplate: function(dataObj, template) {
		//finds template variables in the template passed and replaces them *if* the dataObj has a matching defined member
		
		var regex, template, matches, matchIdx, theMatch, varName;
		regex = /\@Nyx\.[^\@]+\@/g;
		
		matches = template.match(regex);
		if (matches !== null) {
			for (matchIdx = 0; matchIdx < matches.length; matchIdx++) {
				theMatch = matches[matchIdx];
				
				//varName = theMatch.substring( theMatch.indexOf(".") + 1 , theMatch.lastIndexOf("@") );
				varName = theMatch.substring(5, theMatch.length - 1);
				
				if (typeof dataObj[varName] != "undefined") {
					template = NYX.util.string.replaceAll(template, theMatch, dataObj[varName]);
				}
			}
		}
		
		return template;
	}
	,
	applyAltClasses: function(itemIndex, template) {
		/* edits the HTML passed in template to apply alternate-row class names on an every-other and every-third basis
		 * 
		 * IMPORTANT -- itemIndex is expected to be 0-based
		 */
		//template must contain Nyx.AlternateClass variable
		var className, templateVariable;
		templateVariable = "@Nyx.AlternateClass@";
		if (template.indexOf(templateVariable) > -1) {
			className = " ";
			if ( (itemIndex + 1) % 2 === 0 ) {
				//every-other style
				className += this.ALT_CLASS_2 + " ";
			}
			if ( (itemIndex + 1) % 3 === 0 ) {
				//every-third style
				className += this.ALT_CLASS_3 + " ";
			}
			template = NYX.util.string.replaceAll(template, templateVariable, className);
		}
		return template;
	}
	,
	showTarget: function(domTarget) {
		//hide the wait message
		var waitingMsgElem = this.getElem(this.DOM_WAITMSG_SUFFIX);
		if (waitingMsgElem !== null) {
			waitingMsgElem.style.display = "none";
		}
		
		//show the target element
		if (domTarget !== null) {
			domTarget.style.display = "";
		}
	}
};

/**
 * MI added functions, these should probably be corraled into an object
 */
function requestPluckUserAvatar() {
	// create a request batch  
	var requestBatch = new RequestBatch();

	// add the userKey to the request
	var currentUser = retrieveSSOCookieUserId();
	if (currentUser !=='' && currentUser !='undefined') {
		currentUser = hex_md5(currentUser);
	}
	var userKey = new UserKey(currentUser);
	requestBatch.AddToRequest(userKey); 

	// initiate the request. The response will be passed to the renderUserAvatar() method.  
	requestBatch.BeginRequest(serverUrl, renderUserAvatar);
}
// writes the user data into a <img> tag on the page
function renderUserAvatar(responseBatch) {
	var user = retrieveSSOCookieUserId();
console.log('user = '+ retrieveSSOCookieUserId());
	if (user === null) {
		// ignore response
	} else {
		// get the user object out of the response  
		var user = responseBatch.Responses[0].User;
	//	document.getElementById("avatar").src = user.AvatarPhotoUrl;
		var avatar = document.createElement('a');
		avatar.href = '/personas?plckUserId='+user.UserKey.Key+'&insiteUserId='+user.UserKey.Key;
		var genericAvatar = document.getElementById("avatar");
		var newImg = genericAvatar.cloneNode();
		newImg.src = user.AvatarPhotoUrl;
		avatar.appendChild(newImg);
		genericAvatar.replaceChild(avatar,genericAvatar);
	}
}
/** nyxMain.js ^ **************************************************************/
/** nyxPersona.js **************************************************************
 * @fileOverview
 * Tools related to persona (DAAPI User object) output.
 * 
 * @author Glen Ford (glenford [at] yahoo.com)
 * @namespace NYX
 * @minify true
 */

NYX.CurrentUser = function(idRoot) {
	//do some inheritance
	NYX.util.obj.extend(this, NYX.TemplateTool);
	
	//required, but don't necessarily have to be set in the constructor call
	this.idRoot = idRoot;
	this.userTemplate  = "";	//for a logged-in user
	this.guestTemplate = "";	//for a guest user
	
	this.prepareData = function(user) {
		//cleans up a data item; override this as needed to add/subtract post-processing of the flattened data object
		
		//"flatten" 
		var dataObj = this.flattenDaapiItem(user);
		
		return dataObj;
	};
	
	this.writeGui = function(user) {
		//console.dir(user); return false;
		
		var flatUser, targetElem;
		flatUser = this.prepareData(user);
		targetElem = this.getElem(this.DOM_TARGET_SUFFIX);

		if (targetElem !== null) {
			//process the GUI
			this.initGui(targetElem);
			if (user.UserTier.toLowerCase() == "anonymous" || gSiteLife.mi.userLoggedIn() === false) {
				targetElem.innerHTML = this.processTemplate(flatUser, this.guestTemplate);
			} else {
				//logged-in user
				targetElem.innerHTML = this.processTemplate(flatUser, this.userTemplate);
			}
			this.finishGui(targetElem);

			//show the content and hide the wait message/spinner
			this.showTarget(targetElem);
		}
	};
	
	//these methods are empty; they are called during the GUI-writing process to let you add effects/features, and have access to all the instance members
	this.initGui = function(domTarget) {
		//override this method as needed to add your own GUI customizations
		return true;
	};
	this.finishGui = function(domTarget) {
		//override this method as needed to add your own GUI customizations
		return true;
	};
};
/** nyxPersona.js ^ ***********************************************************//* Date.js ****************************************************************
 * Extends the native Date object.
 * @minify true
 * @author Joe Whetzel
 **************************************************************************** */

/* Returns the name of the day.
 */
Date.prototype.getDayString = function(){
  switch (this.getDay()) {
    case 0:
      return 'Sunday';
    case 1:
      return 'Monday';
    case 2:
      return 'Tuesday';
    case 3:
      return 'Wednesday';
    case 4:
      return 'Thursday';
    case 5:
      return 'Friday';
    case 6:
      return 'Saturday';
  }
};

/* Returns the name of the Month. By default the string is returned as a three
 * letter abbreviation. Providing the optional argument will return the full 
 * name of the month. The argument may be any value that equates to true.
 */
Date.prototype.getMonthString = function(full){
  switch (this.getMonth()) {
    case 0:
      return (full)?'January':'Jan';
    case 1:
      return (full)?'February':'Feb';
    case 2:
      return (full)?'March':'Mar';
    case 3:
      return (full)?'April':'Apr';
    case 4:
      return 'May';
    case 5:
      return (full)?'June':'Jun';
    case 6:
      return (full)?'July':'Jul';
    case 7:
      return (full)?'August':'Aug';
    case 8:
      return (full)?'September':'Sep';
    case 9:
      return (full)?'October':'Oct';
    case 10:
      return (full)?'November':'Nov';
    case 11:
      return (full)?'December':'Dec';
  }
};

/* Spanish equvalent to Date.getDayString, also available as Date.obtenerDia.
 */
Date.prototype.spanishDay = function(){
  switch (this.getDay()) {
    case 0:
      return 'domingo';
    case 1:
      return 'lunes';
    case 2:
      return 'martes';
    case 3:
      return 'mi&eacute;rcoles';
    case 4:
      return 'jueves';
    case 5:
      return 'viernes';
    case 6:
      return 's&aacute;bado';
  }
};
Date.prototype.obtenerDia = Date.prototype.spanishDay;

/* Spanish equvalent to Date.getMonthString, also available as Date.obtenerMes.
 */
Date.prototype.spanishMonth = function(full){
  switch (this.getMonth()) {
    case 0:
      return (full)?'enero':'ene';
    case 1:
      return (full)?'febrero':'feb';
    case 2:
      return (full)?'marzo':'mar';
    case 3:
      return (full)?'abril':'abr';
    case 4:
      return (full)?'mayo':'may';
    case 5:
      return (full)?'junio':'jun';
    case 6:
      return (full)?'julio':'jul';
    case 7:
      return (full)?'augusto':'aug';
    case 8:
      return (full)?'septiembre':'sep';
    case 9:
      return (full)?'octubre':'oct';
    case 10:
      return (full)?'noviembre':'nov';
    case 11:
      return (full)?'deciembre':'dec';
  }
};
Date.prototype.obtenerMes = Date.prototype.spanishMonth;

/* This method allows you to define the format of the date string returned.
 * The format string consists of zero or more conversion specifications and 
 * ordinary characters. All ordinary characters are copied directly into the 
 * returned string. A conversion specification consists of a percent sign "%" 
 * and one other character. The conversion specification is based on, but not a 
 * direct copy of, the conversion specification used by the unix date command.
 * %A full weekday name; i.e. "Monday"
 * %a abbreviated weekday name; i.e. "Mon"
 * %B full month name; i.e. "June"
 * %b abbreviated month name; i.e. "Jun"
 * %c time and date; i.e. "Mon Jun 18 09:46:17 2007"; same as "%aÊ%bÊ%dÊ%H:%M:%SÊ%Y"
 * %D month, day and year with leading zeros; i.e. "06/18/07"; same as "%m/%d/%y"
 * %d two digit day of the month, 01-31
 * %E day of the month, 1st-31st; i.e. "18th"
 * %e day of the month, 1-31
 * %F Year-Month-Day; i.e. "2007-06-18"; same as "%Y-%m/%d"
 * %H hour from 24-hour clock as two digit number, 00-23
 * %I hour from 12-hour clock as two digit number, 01-12
 * %k hour from 24-hour clock, 0-23
 * %l hour from 12-hour clock, 1-12
 * %M minutes as two digit number, 00-59
 * %m month as two digit number, 01-12
 * %O Spanish weekday name; i.e. "lunes"
 * %o abbreviated spanish weekday name; i.e. "lun"
 * %p "AM" or "PM"
 * %Q spanish month name; i.e. "junio"
 * %q abbreviated spanish month name; i.e. "jun"
 * %R hours and minutes separated by colon, uses leading zeros and 24 hour clock; i.e. "09:00" and "21:05"; same as "%H:%M"
 * %r hours:minutes:seconds AM/PM using 12-hour clock and leading zeros; i.e. "09:05:00 AM"; same as "%I:%M:%SÊ%p"
 * %S seconds with leading zeros, 00-59
 * %s seconds since epoch, unix time
 * %T hours:minutes:seconds using 24-hour clock; i.e. "13:04:07"; same as "%H:%M:%S"
 * %u day of the week as a number 1-7, Monday = 1
 * %v i.e. "18-Jun-2007"; same as "%d-%b-%Y"
 * %w day of the week as a number 0-6, Sunday = 0
 * %Y four digit year; i.e. "2007"
 * %y two digit year; i.e. "07"
 */
Date.prototype.toFormattedString = function (f) {
	var a,b;
	var d0 = (this.getDate() < 10) ? '0'+this.getDate() : this.getDate();
	var h0 = (this.getHours() < 10) ? '0'+this.getHours() : this.getHours();
	var m0 = (this.getMinutes() < 10) ? '0'+this.getMinutes() : this.getMinutes();
	var s0 = (this.getSeconds() < 10) ? '0'+this.getSeconds() : this.getSeconds();
	var mo0 = this.getMonth() +1;
	mo0 = (mo0 < 10) ? '0'+mo0 : mo0;
	f = f.replace(/%%/g,'%');
	f = f.replace(/%A/g,this.getDayString());
	f = f.replace(/%a/g,this.getDayString().substring(0,3));
	f = f.replace(/%B/g,this.getMonthString(true));
	f = f.replace(/%b/g,this.getMonthString());
	f = f.replace(/%c/g,this.getDayString().substring(0,3) + ' ' +
											this.getMonthString() + ' ' +
											d0 + ' ' + h0 + ':' + m0 + ':' + s0 + ' ' +
											this.getFullYear() );
	a = this.getFullYear()+'';
	a = a.substring(2);
	f = f.replace(/%D/g,mo0+'/'+d0+'/'+a);
	f = f.replace(/%d/g,d0);
	a = this.getDate();
	switch(a) {
		case 1 :
		case 21 :
		case 31 :
			a = a+'st';
			break;
		case 3 :
		case 23 :
			a = a+'rd';
			break;
		default :
			a = a+'th';
	}
	f = f.replace(/%E/g,a);
	f = f.replace(/%e/g,this.getDate());
	f = f.replace(/%F/g,this.getFullYear() +'-'+ mo0 +'-'+ d0);
	f = f.replace(/%H/g,h0);
	a = (this.getHours() > 12) ? this.getHours() -12 : this.getHours();
	f = f.replace(/%I/g,(a < 10) ? '0'+a : a);
	f = f.replace(/%k/g,this.getHours());
	f = f.replace(/%l/g,(this.getHours() > 12) ? this.getHours() -12 : this.getHours());
	f = f.replace(/%M/g,m0);
	f = f.replace(/%m/g,mo0);
	f = f.replace(/%O/g,this.spanishDay());
	f = f.replace(/%o/g,this.spanishDay().substring(0,3));
	f = f.replace(/%p/g,(this.getHours() > 11) ? 'PM' : 'AM');
	f = f.replace(/%Q/g,this.spanishMonth(true));
	f = f.replace(/%q/g,this.spanishMonth().substring(0,3));
	f = f.replace(/%R/g,h0+':'+m0);
	a = (this.getHours() > 12) ? this.getHours() -12 : this.getHours();
	a = (a < 10) ? '0'+a : a;
	b = (this.getHours() > 11) ? 'PM' : 'AM';
	f = f.replace(/%r/g,a +':'+ m0 +':'+ s0 +' '+ b);
	f = f.replace(/%S/g,s0);
	f = f.replace(/%s/g,Date.parse(this)/1000);
	f = f.replace(/%T/g,h0+':'+m0+':'+s0);
	f = f.replace(/%u/g,(this.getDay() === 0) ? 7 : this.getDay());
	f = f.replace(/%v/g,this.getDate()+'-'+this.getMonthString()+'-'+this.getFullYear());
	f = f.replace(/%w/g,this.getDay());
	f = f.replace(/%X/g,this.toLocaleTimeString());
	f = f.replace(/%Y/g,this.getFullYear());
	a = this.getFullYear()+'';
	f = f.replace(/%y/g,a.substring(2));
	return f;
};






/* Date.js ^ ---------------------------------------------------------------- */
/** nyxPager.js ****************************************************************
 * @fileOverview
 * Objects for navigating among pages on any paginated lists; 
 * in SiteLife, these include galleries or comments.
 * 
 * @author Glen Ford (glenford [at] yahoo.com)
 * @namespace NYX
 * @minify true
 */

NYX.Pager = function(paramBag) {
	//creates a GUI for navigation between pages on *any* paginated list (incl. DAAPI page objects)
	
	/* paramBag REQUIRED members:
	 *   .domTargetElem
	 *   .pageLength
	 *   .totalItems
	 *   .template
	 * OPTIONAL: any other property that can be set
	 */
	
	//do some inheritance
	NYX.util.obj.extend(this, NYX.TemplateTool);
	
	//CSS classes
	this.CSS_CLASS_PAGELINKS   = "paginationNavLinks";
	this.CSS_CLASS_CDTRANSPORT = "paginationTransport";
	this.CSS_CLASS_SELECT      = "paginationDropDown";
	
	//these determine whether controls are shown even when no navigation is possible
	this.alwaysShowJumpNav   = false;	//jump nav includes page links & drop down
	this.alwaysShowTransport = true;
	
	this.linkLimit = 10; //limits the number of direct-to-page links displayed (ignored if that element isn't in the template)
	
	//inherit from the paramter bag (copy properties)
	NYX.util.obj.extend(this, paramBag);
	
	//querystring variable name
	this.pageVarName = "pageNum";
	
	this.transportMaker = null;	//tool for writing CD-type transport controls; will be defaulted at run-time if needed
	this.dropDownMaker  = null;	//tool for writing drop-down control; will be defaulted at run-time if needed
	
	this.getPageCount = function() {
		var count = Math.ceil(this.totalItems / this.pageLength);
		return count;
	};
	
	//do some calculations to set current state parameters
	this.currentPage = NYX.util.querystring.get(this.pageVarName);
	if (this.currentPage === null || this.currentPage < 1) {this.currentPage = 1;}
	
	//action methods ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *****
	this.writeGui = function() {
		//clean up the link limit since it might be a string, which will cause concatenation instead of addition (thanks JavaScript!)
		this.linkLimit = Math.abs(this.linkLimit);
		
		//get the current page count
		this.pageCount = this.getPageCount();
		
		//add properties to this instance for template replacement (actual controls, etc)
		//calculate numbers for "Showing X-Y of T items" type display
		this.firstItem = (this.currentPage - 1) * this.pageLength + 1;
		this.lastItem  = this.firstItem + (this.pageLength - 1);
		if (this.lastItem > this.totalItems) {this.lastItem = this.totalItems;}
		
		//jump nav
		//if ( this.pageCount > 1 || this.alwaysShowJumpNav ) {
		if ( NYX.util.string.contains(this.template, "pageLinks") ) {
			this.pageLinks = this.getPageLinks();
		}
		if ( NYX.util.string.contains(this.template, "pageDropDown") ) {
			this.pageDropDown = this.getDropDownCtrl();
		}
		
		//CD-player-like controls
		//if ( thisthis.firstItem.getPageCount() > 1 || this.alwaysShowTransport ) {
		if ( NYX.util.string.contains(this.template, "cdTransport") ) {
			this.cdTransport = this.getTransportCtrl();
		}
		
		//do template replacements
		this.domTargetElem.innerHTML = this.processTemplate(this, this.template);
	};
	
	this.getPageLinks = function() {
		//returns HTML of direct-to-page links
		
		//start the HTML with wrappers
		var wrapper = document.createElement("ins"); //arbitrary wrapper for collecting the HTML -- not returned
		var innerWrapper = document.createElement("span"); //for CSS classing -- *will* be returned
		innerWrapper.className = this.CSS_CLASS_PAGELINKS;
		wrapper.appendChild(innerWrapper);
		
		//calculate the range of page links to display; assume the user wants to go forward moreso that backward
		var actualLinkLimit = (this.pageCount < this.linkLimit) ? this.pageCount : this.linkLimit;
		var startPage = this.currentPage - Math.floor(this.linkLimit / 3) - 1;
		if (startPage + actualLinkLimit > this.pageCount) {startPage = this.pageCount - actualLinkLimit + 1;}
		if (startPage < 1) {startPage = 1;}
		
		//create the links
		for (var linkCount = 0; linkCount < actualLinkLimit; linkCount++) {
			var jumpNum = linkCount + startPage;
			var tag;
			if (jumpNum != this.currentPage) {
				tag = document.createElement("a");
				tag.href = NYX.util.querystring.set(this.pageVarName, jumpNum);
				tag.href = tag.href.replace(/mi_pluck_action=[^&]*&*/i,''); // removes pre-existing mi_pluck_action argument
				tag.href += '&mi_pluck_action=page_nav#Comments_Container';
			} else {
				tag = document.createElement("span");
			}
			tag.innerHTML = jumpNum;
			innerWrapper.appendChild(tag);
		}
		
		return wrapper.innerHTML;
	};
	
	this.getTransportCtrl = function() {
		if ( !( this.pageCount > 1 || this.alwaysShowTransport) ) {return "";}
		if (this.transportMaker === null) {this.transportMaker = new NYX.TextCDButtons(this);}
		return this.transportMaker.getHTML();
	};
	
	this.getDropDownCtrl = function() {
		if ( !( this.pageCount > 1 || this.alwaysShowJumpNav) ) {return "";}
		if (this.dropDownMaker === null) {this.dropDownMaker = new NYX.PageSelect(this);}
		return this.dropDownMaker.getHTML();
	};
};







//child objects start here ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *****
NYX.TextCDButtons = function(parent) {
	//character-based "CD transport buttons" for page navigation
	this.parent = parent;
	
	/* constants for the symbols to use 
	 * -- choose carefully, as global search-and-replace may be used by child classes
	 * (recommendation: always use entities or other multi-character strings, or rare characters)
	 */
	this.SYM_FIRST = "&laquo;"  ;
	this.SYM_PREV  = "&lt;"     ;
	this.SYM_NEXT  = "&gt;"     ;
	this.SYM_LAST  = "&raquo;"  ;
	
	this.getHTML = function() {
		//wrapper to collect HTML
		var wrapper = document.createElement("ins");
		//inner wrapper for styling
		var innerWrapper = document.createElement("span"); //for CSS classing -- *will* be returned
		innerWrapper.className = this.parent.CSS_CLASS_CDTRANSPORT;
		wrapper.appendChild(innerWrapper);
		
		//link: << (first)
		var tag;
		if (this.parent.currentPage > 1) {
			tag = document.createElement("a");
			tag.href = NYX.util.querystring.set(this.parent.pageVarName, 1);
		} else {
			tag = document.createElement("span");
		}
		tag.innerHTML = this.SYM_FIRST;
		innerWrapper.appendChild(tag);
		
		//link: < (prev)
		if (this.parent.currentPage > 1) {
			tag = document.createElement("a");
			tag.href = NYX.util.querystring.set(this.parent.pageVarName, this.parent.currentPage - 1);
		} else {
			tag = document.createElement("span");
		}
		tag.innerHTML = this.SYM_PREV;
		innerWrapper.appendChild(tag);
		
		//link: > (next)
		if (this.parent.currentPage < this.parent.pageCount) {
			tag = document.createElement("a");
			tag.href = NYX.util.querystring.set(this.parent.pageVarName, this.parent.currentPage + 1);
		} else {
			tag = document.createElement("span");
		}
		tag.innerHTML = this.SYM_NEXT;
		innerWrapper.appendChild(tag);
		
		//link: >> (last)
		if (this.parent.currentPage < this.parent.pageCount) {
			tag = document.createElement("a");
			tag.href = NYX.util.querystring.set(this.parent.pageVarName, this.parent.pageCount);
		} else {
			tag = document.createElement("span");
		}
		tag.innerHTML = this.SYM_LAST;
		innerWrapper.appendChild(tag);
		
		return wrapper.innerHTML;
	};
};

NYX.PrevNextLinks = function(parent, paramBag) {
	//textual "CD transport buttons" for page navigation
	this.parent = parent;
	
	//constants for the text
	this.JOINER = "&nbsp;";
	this.TEXT_FIRST = "First";
	this.TEXT_PREV  = "Prev";
	this.TEXT_NEXT  = "Next";
	this.TEXT_LAST  = "Last";
	
	//param bag can override constants; also can pass in killSymbols to affect the display
	if (typeof paramBag == "object") {NYX.util.obj.extend(this, paramBag);}
	
	//utilize the existing class and do surgery on it
	NYX.util.obj.extend( this, new NYX.TextCDButtons(this.parent) );
	
	//override symbol constants
	if (this.killSymbols) {
		this.SYM_FIRST = this.TEXT_FIRST;
		this.SYM_PREV  = this.TEXT_PREV;
		this.SYM_NEXT  = this.TEXT_NEXT;
		this.SYM_LAST  = this.TEXT_LAST;
	} else {
		this.SYM_FIRST += this.JOINER + this.TEXT_FIRST;
		this.SYM_PREV  += this.JOINER + this.TEXT_PREV;
		this.SYM_NEXT  += this.JOINER + this.TEXT_NEXT;
		this.SYM_LAST  += this.JOINER + this.TEXT_LAST;
	}
};



NYX.PageSelect = function(parent) {
	//basic SELECT box for direct-page navigation
	this.parent = parent;
	
	//top item text
	this.DEFAULT_OPTION_TEXT = "Jump to:";
	
	this.getHTML = function() {
		//wrapper to collect HTML
		var wrapper = document.createElement("ins");
		
		var ctrl = document.createElement("select"); //for CSS classing -- *will* be returned
		ctrl.className = this.parent.CSS_CLASS_SELECT;
		
		//add the default option
		var option = document.createElement("option");
		option.innerHTML = this.DEFAULT_OPTION_TEXT;
		ctrl.appendChild(option);
		
		for (var pageIdx = 1; pageIdx <= this.parent.pageCount; pageIdx++) {
			option = document.createElement("option");
			//option.value = pageIdx;
			option.innerHTML = pageIdx;
			ctrl.appendChild(option);
		}
		
		wrapper.appendChild(ctrl);
		
		//add the onchange event to the SELECT -- the cheap way
		var eventCode = "if (this.selectedIndex != " + this.parent.currentPage + " && this.selectedIndex > 0) " +
			"location.search = NYX.util.querystring.set(pageVarName, this.selectedIndex);" +
			"else this.selectedIndex = 0;"; 
		eventCode = eventCode.replace("pageVarName", '"' + this.parent.pageVarName + '"');
		wrapper.innerHTML = wrapper.innerHTML.replace("<select", "<select onchange='" + eventCode + "' ");
		
		return wrapper.innerHTML;
	};
};
/** nyxPager.js ^ *************************************************************//** nyxReactions.js ************************************************************
 * @fileOverview
 * Objects that do DAAPI comment input and output.
 * The Nyx main library MUST be loaded before this script.
 * 
 * @author Glen Ford (glenford [at] yahoo.com)
 * @namespace NYX
 * @minify true
 */

//TODO: lots of room for improvement, e.g. handling class names, white-box code duplication, etc.

NYX.cache.userIsLoggedIn = false; //a semi-global variable for use in reaction widgets to determine when to display non-anonymous elements

NYX.CommentOutput = function(idRoot, itemTemplate) {
	//do some inheritance
	NYX.util.obj.extend(this, NYX.TemplateTool);
	
	//required, but don't necessarily have to be set in the constructor call
	this.idRoot = idRoot;
	if (typeof itemTemplate == "string") {this.template = itemTemplate;}
	else {this.template = "@Nyx.PageTitle@";}
	
	//optional Pager
	this.pager = null;
	
	//internal use
	this.comments = [];
	this.DOM_TARGET_SUFFIX_COUNT  = "count";
	this.DOM_TARGET_SUFFIX_SORT   = "sort";
	this.DOM_TARGET_SUFFIX_HEADER = "header";
	
	this.prepareData = function(commentObj) {
		/* "flattens" the comment objects selectively by coping values in the User child 
		 * object one level up with "Author" as a prefix on the new variable name; thus,
		 * template variables like AuthorDisplayName can be used
		 * IMPORTANT: actually modifies commentObj as well as returns it
		 */
		
		for (var i in commentObj.Author) {
			commentObj["Author" + i] = commentObj.Author[i];
		}
		
		//add custom items
		commentObj.AuthorKey = commentObj.Author.UserKey.Key;
		commentObj.CommentIDKey = commentObj.CommentKey.Key;
		commentObj.CommentIDKey = commentObj.CommentIDKey.replace(/CommentKey\:/, "");
		commentObj.FilteredAuthorName = commentObj.AuthorDisplayName;
		commentObj.FilteredAuthorName = commentObj.FilteredAuthorName.replace(/\\/g, "\\\\");
		commentObj.FilteredAuthorName = commentObj.FilteredAuthorName.replace(/\'/g, "\\\'");
		commentObj.FilteredAuthorName = commentObj.FilteredAuthorName.replace(/\"/g, "\\\"");//name escaped for js
		commentObj.CommentBody = commentObj.CommentBody.replace(/\r*\n/g, "<br>");//bugfix - make newlines visible
		
		commentObj.repliedToText = "";//what they were replying to
		commentObj.replyAnswerText = commentObj.CommentBody;//what they replied, or just the comment if not a reply
		if(commentObj.CommentBody.search(/("*Replying to \S+? \(\d+\/\d+\/\d+ \d+\:\d+\:\d+ \w\w\)\:.+?".+"\:)\s*(<br>)*/) != -1){
			commentObj.repliedToText = commentObj.CommentBody;
			//commentObj.repliedToText = commentObj.repliedToText.replace(/("*Replying to \S+? \(\d+\/\d+\/\d+ \d+\:\d+\:\d+ \w\w\)\:.+?".+"\:)\s*(<br>)*.*/, "$1");
			commentObj.repliedToText = commentObj.repliedToText.replace(/("*Replying to \S+? \(\d+\/\d+\/\d+ \d+\:\d+\:\d+ \w\w\)\:.+?".+"\:)\s*(<br>)*.*/, "<div class=\"commentRepliedInner\">$1</div>");
			commentObj.replyAnswerText = commentObj.replyAnswerText.replace(/("*Replying to \S+? \(\d+\/\d+\/\d+ \d+\:\d+\:\d+ \w\w\)\:.+?".+"\:)\s*(<br>)*/, "");
		}	

		return commentObj;
	};
	
	this.writeGui = function(daapiResponse) {
		/* this method expects the daapiResponse to be a valid 
		 * DAAPI CommentPage array (or something with the same interface)
		 */
		//console.group("CommentOutput.writeGui");console.dir(daapiResponse);console.groupEnd(); return false;
		this.comments = daapiResponse.Comments;
		this.commentCount = Math.abs(daapiResponse.NumberOfComments);
		
		var commentData, itemIdx, html, targetElem;
		targetElem = this.getElem(this.DOM_TARGET_SUFFIX);

		if (targetElem !== null) {
			this.initGui();
			// if the site hasn't set standardTZDhours we assume eastern time zone
			// modifier is the number of miliseconds difference between central time and local time
			document.standardTZDhours = (document.standardTZDhours) ? document.standardTZDhours : -5;
			document.defaultDateFormat = (document.defaultDateFormat) ? document.defaultDateFormat : '%m/%d/%Y %r';
			var modifier = (6 + document.standardTZDhours) * 3600000, pluckDate, modTest = (Date.prototype.toFormattedString && (document.standardTZDhours !== -6 || document.defaultDateFormat != '%m/%d/%Y %r')) ? 1 : 0;
			var abuseMsg = 'This comment has been hidden and is pending site review. Click here if you wish to view.';
			for (itemIdx = 0; itemIdx < this.comments.length; itemIdx++) {
				if (this.comments[itemIdx].Author.IsBlocked === 'False' || NYX.cache.DisplayName == this.comments[itemIdx].Author.DisplayName) {
					if (modTest === 1) {
						// formatting comment time stamp
						pluckDate = new Date(this.comments[itemIdx].PostedAtTime);
						this.comments[itemIdx].PostedAtTime = pluckDate.toFormattedString(document.defaultDateFormat);
					}
					//get processable data
					commentData = this.prepareData(this.comments[itemIdx]);
				
					//do the template replacements for this item and append the HTML to the content target
					html = this.processTemplate(commentData, this.template);
					if (this.comments[itemIdx].AbuseReportCount > 2){
						html = html.replace(/<p([^>]*)>/ig, '<p$1 style="display:none;">');
						html = html.replace(/(div class=["']*pluckComOptions["']* style=["']*)/i, '$1display:none; ');
						html = html.replace(/<p /i, '<p class="abuseMsg" style="cursor:pointer;">'+abuseMsg+'<'+'/p><p ');
					}
				
					//apply the alternate row classes
					html = this.applyAltClasses(itemIdx, html);
			
					//handle GUI for recommendations and abuse reporting
					html = this.showRecommends(html, commentData, itemIdx);
					html = this.showAbuse(html, commentData, itemIdx);
				
					//call the customizable method to do more replacements
					html = this.customizeItem(commentData, html, targetElem, itemIdx);
				
					targetElem.innerHTML += html;
				}
			}
		
			//handle pagination etc.
			this.showCommentCount();
			this.setPageSort();
			this.setPaginationCtrl();
		
			this.finishGui();
		
			//show the content and hide the wait message/spinner
			this.showTarget(targetElem);
		
			//also show the associated header element, if it exists
			this.showElem(this.DOM_TARGET_SUFFIX_HEADER);
			$('.abuseMsg').click(
				function (e) {
					$(e.target).parent().children('p').show('fast');
					$(e.target).hide('fast');
					$(e.target).parent().children('.pluckComOptions').show('fast');
					return false;
				}
			);
		}
	};
	
	//additional methods to show the comment count etc.;
	//these follow strict naming conventions (less flexible than much of Nyx)
	this.showCommentCount = function() {
		var targetElem = this.getElem(this.DOM_TARGET_SUFFIX_COUNT);
		if (targetElem !== null) {
			var domain = (typeof mi != 'undefined' && typeof mi.media_domain != 'undefined') ? mi.media_domain : '';
			targetElem.innerHTML = "Comment" + ( this.commentCount == 1 ? "" : "s" ) + ": <img src='"+ domain +"/static/images/pluck/comment.gif' /> " + this.commentCount;
		}
	};
	this.setPageSort = function() {
		var targetElem = this.getElem(this.DOM_TARGET_SUFFIX_SORT);
		//targetElem should be a SELECT and NYX.cache["commentSort"] should exist
		if ( targetElem !== null && typeof NYX.cache.commentSort == "string" ) {
			targetElem.value = NYX.cache.commentSort;
		}
	};
	this.setPaginationCtrl = function() {
		if (this.pager !== null) {
			this.pager.totalItems = this.commentCount;
			this.pager.writeGui();
		}
	};
	
	//methods for GUI elements that allow user reactions; these create and link to new objects that do the work
	//TODO: important! these need to be encapsulated into another class so they can apply to other outputs (such as Personas) without white-box duplication
	//TODO: they're also very white-box when compared with one another
	this.showRecommends = function(template, dataObj, itemIdx) {
		var recIdRoot, link, countElem, wrapper, reactionTool, alreadyDone, html, clickEventHtml;
		
		alreadyDone = (dataObj.CurrentUserHasRecommended.toLowerCase() == "true");
		
		//extend this object's ID root to work for the recommendation GUI elements
		recIdRoot = this.idRoot + "_rec_" + itemIdx;
		
		//create and cache the object that does the reporting
		reactionTool = new NYX.Recommender(recIdRoot, "Comment", dataObj.CommentKey.Key);
		reactionTool.alreadyDone = alreadyDone;
		NYX.cache[recIdRoot + "_recommender"] = reactionTool;
		
		//create the link that does the action
		if (alreadyDone) {
			link = document.createElement("span");
			link.innerHTML = reactionTool.stateStrings.done;
			link.className = " " + reactionTool.classNames.done;
		} else {
			link = document.createElement("a");
			link.href = "#";
			link.innerHTML = reactionTool.stateStrings.notDone;
			link.className = " " + reactionTool.classNames.notDone;
		}
		//link.className += " nyxAbuseReport";
		link.id = recIdRoot + "_link";
		
		//create a container for the count
		countElem = document.createElement("span");
		countElem.className = "nyxRecCount ";
		countElem.id = recIdRoot + "_recCount";
		countElem.innerHTML = "&nbsp;(" + dataObj.NumberOfRecommendations + ")";
		
		//create a throwaway wrapper so we can get the inner HTML
		wrapper = document.createElement("ins");
		wrapper.appendChild(link);
		wrapper.appendChild(countElem);
		
		//this awkward crar is needed to get the event to work in Firefox
		clickEventHtml = "NYX.cache['" + recIdRoot + "_recommender'].recommend()";
		html = wrapper.innerHTML;
		html = html.replace('href="#"', 'href="javascript: void(0)" onclick="' + clickEventHtml + '"');
		
		template = template.replace("@Nyx.Recommender@", html);
		
		return template;
	};
	
	this.showAbuse = function(template, dataObj, itemIdx) {
		var abuseIdRoot, link, img, wrapper, reactionTool, alreadyReported, html, clickEventHtml;
		
	// show "report abuse" link only if user is logged in
	//if ((gSiteLife.mi.userLoggedIn())){
		alreadyReported = (dataObj.CurrentUserHasReportedAbuse.toLowerCase() == "true");
		
		//extend this object's ID root to work for the abuse GUI elements
		abuseIdRoot = this.idRoot + "_abuse_" + itemIdx;
		
		//create and cache the object that does the reporting
		reactionTool = new NYX.AbuseReporter(abuseIdRoot, "Comment", dataObj.CommentKey.Key);
		reactionTool.alreadyDone = alreadyReported;
		NYX.cache[abuseIdRoot + "_reporter"] = reactionTool;
		
		//create the link that shows the abuse report form
		if (alreadyReported) {
			link = document.createElement("span");
			link.innerHTML = reactionTool.stateStrings.done;
		} else {
			link = document.createElement("a");
			//link.href = "javascript: NYX.cache['" + abuseIdRoot + "_reporter'].positionAndShowForm(this)";
			link.href = "#";
			//link.onclick = "NYX.cache['" + abuseIdRoot + "_reporter'].positionAndShowForm(event)";
			link.innerHTML = reactionTool.stateStrings.notDone;
		}
		link.className = "nyxAbuseReport";
		link.id = abuseIdRoot + "_link";
		
		//create the image that shows state
		img = document.createElement("img");
		img.className = "nyxAbuseReport";
		img.id = abuseIdRoot + "_img";
		
		//TODO: this is duplicated in the reporter class
		if (alreadyReported) {
			img.src = NYX.cache.iconRoot + "/icon_" + reactionTool.imageNames.done + ".gif";
			img.className += " " + reactionTool.classNames.done;
		} else {
			img.src = NYX.cache.iconRoot + "/icon_" + reactionTool.imageNames.notDone + ".gif";
			img.className += " " + reactionTool.classNames.notDone;
		}
		
		//create a throwaway wrapper so we can get the inner HTML
		wrapper = document.createElement("ins");
		wrapper.appendChild(img);
		wrapper.appendChild(link);
		
		//this awkward crar is needed to get the event to work in Firefox
		clickEventHtml = "NYX.cache['" + abuseIdRoot + "_reporter'].positionAndShowForm(event)";
		html = wrapper.innerHTML;
		html = html.replace('href="#"', 'href="javascript: void(0)" onclick="' + clickEventHtml + '"');
	//} else {
	//	html = "";
	//}
		
		template = template.replace("@Nyx.AbuseReporter@", html);
		
		return template;
	};
	
	//these methods are empty; they are called during the GUI-writing process to let you add effects/features, and have access to all the instance members
	this.initGui = function() {
		//override this method as needed to add your own GUI customizations
		return true;
	};
	this.finishGui = function() {
		//override this method as needed to add your own GUI customizations
		return true;
	};
	this.customizeItem = function(dataObj, itemHtml, domElemThisWritesTo, itemIndex) {
		//override this method as needed to add your own GUI customizations
		return itemHtml;	//IMPORTANT: always return the itemHtml (processed or otherwise)
	};
};



//abstract superclass for reaction controls
NYX.Reactor = {
	This: this,
	msg_saveError: "Sorry, an unexpected error occurred. Please try your action again.",
	form: null,
	
	//INTERNAL -- probably should not be set except through setDoneState()
	alreadyDone: false,
	
	getForm: function() {
		if (this.form === null) {this.form = document.getElementById(this.FORM_ID);}
		return this.form;
	}
	,
	showForm: function() {
		//shows it and sets an expando to point to this object also
		var form = this.getForm();
		form.style.display = "block";
		form.reporter = this;
	}
	,
	hideForm: function() {
		this.form.style.display = "none";
	}
	,
	positionAndShowForm: function(theEvent) {
		ShowDivAtMouse(theEvent, this.FORM_ID);	//using the standard SiteLife function here
		this.showForm();
	}
};



//recommendations
NYX.Recommender = function(guiIdRoot, itemType, itemId) {
	//closure for async callback
	var This = this;
	
	//inherit shared reaction props & methods
	NYX.util.obj.extend(this, NYX.Reactor);
	
	this.guiIdRoot = guiIdRoot;
	this.keyType = itemType;
	this.itemId = itemId;
	
	//messages that can be customized
	this.stateStrings = {
		notDone: "Recommend",
		done:    "Recommended"
	};
	
	//filename (no path or extension) for the images on the SiteLife server that indicate state
	this.classNames = {
		//standard SiteLife class names
		notDone: "SiteLife_Recommend",
		done:   "SiteLife_Recommended"
	};
	
	this.recommend = function() {
		if (!this.alreadyDone) {
			var requestBatch, daapiAction, theKey;
			
			//create the key object for the appropriate type
			theKey = eval('new ' + this.keyType + 'Key("' + this.itemId + '")');
			
			//do the report
			requestBatch = new RequestBatch();
			daapiAction = new RecommendAction(theKey);
			requestBatch.AddToRequest(daapiAction);
			requestBatch.BeginRequest(NYX.cache.daapiProcessUrl, this.callback);
		}
	};
	
	this.callback = function(responseBatch) {
		//if the response was good, change the link state for feedback; else show error message and show the form again
		if (responseBatch.Messages[0].Message.toLowerCase() == "ok") {
			This.setDoneState();
		} else {
			alert(This.msg_saveError);
			console.dir(responseBatch);
		}
	};
	
	this.setDoneState = function() {
		//sets the link text and class and increments the recommendation number
		this.alreadyDone = true;
		
		var anchorTag, countTag, currentCount;
		anchorTag = document.getElementById(this.guiIdRoot + "_link");
		anchorTag.className = anchorTag.className.replace(this.classNames.notDone, this.classNames.done);	//TODO: here's where a better routine for class names would help (NYX.util)
		anchorTag.innerHTML = this.stateStrings.done;
		
		countTag = document.getElementById(this.guiIdRoot + "_recCount");
		currentCount = Math.abs(countTag.innerHTML.substring(countTag.innerHTML.length - 2, countTag.innerHTML.length - 1));
		countTag.innerHTML = "&nbsp;("+ ++currentCount +")"; //TODO: whitebox here too, and it's easy to get out-of-sync
	};
};



//abuse reporting
NYX.AbuseReporter = function(guiIdRoot, itemType, itemId) {
	//closure for async callback
	var This = this;
	
	//inherit shared reaction props & methods
	NYX.util.obj.extend(this, NYX.Reactor);
	
	this.guiIdRoot = guiIdRoot;
	this.keyType = itemType;
	this.itemId = itemId;
	
	//messages that can be customized
	this.msg_saveError = "Sorry, an unexpected error occurred. Please try your abuse report again.";
	this.stateStrings = {
		notDone: "Report abuse",
		done:    "Abuse reported"
	};
	
	//the ID of the tandard form is meant to be a constant, but can be overridden as needed
	this.FORM_ID = "nyxAbuseRptForm";
	
	//filename (no path or extension) for the images on the SiteLife server that indicate state
	this.imageNames = {
		//based on standard SiteLife image names
		notDone: "alert",
		done:   "accept"
	};
	this.classNames = {
		notDone: "reportable",
		done:   "reported"
	};
	
	this.report = function() {
		if (!this.alreadyDone) {
			var requestBatch, daapiAction, theKey;
			
			//create the key object for the appropriate type
			theKey = eval('new ' + this.keyType + 'Key("' + this.itemId + '")');
			
			//do the report
			requestBatch = new RequestBatch();
			daapiAction = new ReportAbuseAction( theKey, 
				document.getElementById(this.FORM_ID + "_reason").value, 
				document.getElementById(this.FORM_ID + "_comment").value
			);
			requestBatch.AddToRequest(daapiAction);
			requestBatch.BeginRequest(NYX.cache.daapiProcessUrl, this.callback);
			
			//hide the form
			this.hideForm();
		}
	};
	
	//this can't belong to the parent class
	this.callback = function(responseBatch) {
		//if the response was good, change the link state for feedback; else show error message and show the form again
		if (responseBatch.Messages[0].Message.toLowerCase() == "ok") {
			This.setDoneState();
		} else {
			alert(This.msg_saveError);
			This.positionAndShowForm();
			console.dir(responseBatch);
		}
	};
	
	this.setDoneState = function() {
		//sets the image and link text as well as the internal state to indicate the user has previously reported
		this.alreadyDone = true;
		
		var imgTag, anchorTag;
		imgTag = document.getElementById(this.guiIdRoot + "_img");
		imgTag.src = imgTag.src.replace(this.imageNames.notDone, this.imageNames.done);
		imgTag.className = imgTag.className.replace(this.classNames.notDone, this.classNames.done);
		anchorTag = document.getElementById(this.guiIdRoot + "_link");
		anchorTag.innerHTML = this.stateStrings.done;
	};
};


function colorReplies(retryNum)
{
	var changed = false;
	$(".pluckCommentBody").attr("innerHTML", function (){
		if(isReply(this.innerHTML)){
			changed = true;
			return this.innerHTML.replace(/("*Replying to \S+? \(\d+\/\d+\/\d+ \d+\:\d+\:\d+ \w\w\)\:.+?".+"\:)\s*(<br>)*/, "<table border=0 class=\"pluckReplyTable\"><tr><td class=\"pluckReplyInComment\">$1<"+"/td><"+"/tr><"+"/table>");//this works in ie and ff - why not use divs? because of a bug in ie
		}
		else{return this.innerHTML;}
	});
	if(!(changed) && retryNum > 0){
		retryNum--;
		setTimeout( "colorReplies("+retryNum+")" , 2000);//check back every 2 seconds, if this has loaded, change it
	}
}


//returns true if it appears that the comment is a reply, based on regex of comment text
function isReply(commentText)
{
	if(commentText.search(/Replying to \S+? \(\d+\/\d+\/\d+ \d+\:\d+\:\d+ \w\w\)\:/) == -1){return false;}
	return true;
}

//hides the reply to comment link if user is not logged in
function hideReplyNotLoggedIn()
{
	if (!(gSiteLife.mi.userLoggedIn())){
		$(".Discussion_PostReply").css("display", "none");
	}
}

//shows the reply to comment link if user is logged  in
function showReplyLoggedIn()
{
	if (gSiteLife.mi.userLoggedIn()){
		$(".Discussion_PostReply").css("display", "inline");
	}
}

//starts the reply process when user clicks on reply to  comment link
//Parameters: pluck  generated  comment id, name of person writing original comment, time of origianl comment, character limit on reply
function commentReply(commentID, replyToName, origTime,truncateTo)
{
	var replyText = "Replying to "+replyToName +" ("+origTime + "):<br>";
	var fromText = $("#"+commentID).html();
	fromText =  fromText.replace(/[\r\n]/g, "");
	fromText =  fromText.replace(/<div class="commentRepliedInner">Replying to.+?M\):<br>"/i, "");
	fromText =  fromText.replace(/":<\/div>/i, "");

	if(fromText.length > truncateTo){
		var spaceIndex = fromText.lastIndexOf(' ',truncateTo);
		if(spaceIndex < fromText.lastIndexOf("\n",truncateTo)){spaceIndex = fromText.lastIndexOf("\n",truncateTo);}
		fromText = fromText.substring(0,spaceIndex) + "...";
	}
	replyText += "\"" + fromText + "\":<br>";
	
	var fromTextCR = fromText.replace(/<br>/gi,"\n");
	var matches = fromTextCR.match(/\r|\n/g);

	if(! matches){NYX.cache.commentReplyLength = fromTextCR.length;}
	else{NYX.cache.commentReplyLength = fromTextCR.length - matches.length;}//determine length of commment, not counting cr's
	NYX.cache.max_comment_length = NYX.cache.init_max_comment_length - NYX.cache.commentReplyLength;
	
	var commentMsg = document.getElementById('commentTopMsg');
	commentMsg.innerHTML = "<br><a id=\"link_back_from_reply\" href=\"#commentlink"+commentID+"\" onclick=\"cancelCommentReply()\" class=\"cancelReplyLink\">Cancel Reply</a>";

	commentMsg.innerHTML += "<br>";

	var commentTarget = document.getElementById('commentTopReply');
	commentTarget.innerHTML = replyText;
	
	var commentTextArea = document.getElementById('commentBody');
	commentTextArea.focus();
	checkCommentLength(document.getElementById("commentBody"));

	return false;
}

//cancels the reply
function cancelCommentReply()
{
	var commentMsg = document.getElementById('commentTopMsg');
	commentMsg.innerHTML = "";
	var commentTarget = document.getElementById('commentTopReply');
	commentTarget.innerHTML = "";
	NYX.cache.commentReplyLength = 0;
	NYX.cache.max_comment_length = NYX.cache.init_max_comment_length;
	checkCommentLength(document.getElementById("commentBody"));
}

//add the comment being replied to into the comment at time of submit
function addReplyToComment()
{
	var replyToComment = document.getElementById('commentTopReply');
	var replyToText = replyToComment.innerHTML;
	if(replyToText !== ""){
		replyToText = replyToText.replace(/[\r\n]/g,"");
		replyToText = replyToText.replace(/<br>/gi,"\n");
		replyToText = replyToText.replace(/<span.+?>/i,"");
		replyToText = replyToText.replace(/<\/span>/i,"");
		replyToText = replyToText.replace(/<\/*table.*?>/gi,"");
		replyToText = replyToText.replace(/<\/*tr.*?>/gi,"");
		replyToText = replyToText.replace(/<\/*td.*?>/gi,"");
		replyToText = replyToText.replace(/<\/*td.*?>/gi,"");
		replyToText = replyToText.replace(/<\/*tbody.*?>/gi,"");
		replyToText = replyToText.replace(/<\/*div.*?>/gi,"");
		
		var matches = replyToText.match(/\r|\n/g);
		if(! matches){NYX.cache.commentReplyLength = replyToText.length;}
		else{NYX.cache.commentReplyLength = replyToText.length - matches.length;}//determine length of commment, not counting cr's
		NYX.cache.max_comment_length = NYX.cache.init_max_comment_length - NYX.cache.commentReplyLength;

		var commentTarget = document.getElementById('commentBody');
		var commentText = $("#commentBody").html();
		if(commentText === null){commentText = "";}
		if(typeof(commentTarget.value)!="undefined"){
			if(commentTarget.value !== "" && commentTarget.value !== null){commentText = commentTarget.value;}
		}

		commentText = replyToText + commentText;
		commentTarget.innerText = commentText;
		commentTarget.textContent = commentText;
		commentTarget.value = commentText;
	}
	return true;
}

//remove any reply-related text that  has been added to a comment
function stripReplyText()
{
	var commentTarget = document.getElementById('commentBody');
	var commentText = $("#commentBody").html();
	if(commentText === null){commentText = "";}
	if(typeof(commentTarget.value)!="undefined"){
		if(commentTarget.value !== "" && commentTarget.value !== null){commentText = commentTarget.value;}
	}
	
	if(isReply(commentText)){
		commentText = commentText.replace(/\r?\n/g, "#zxyqj");//get around browser multiline limitation
		commentText = commentText.replace(/Replying to \S+? \(\d+\/\d+\/\d+ \d+\:\d+\:\d+ \w\w\)\:.+?".+?"\:(#zxyqj)*/, "");
		commentText = commentText.replace(/\#zxyqj/g, "\n");
	}

	commentTarget.innerText = commentText;//multiple methods to account for  browser incompatibility
	commentTarget.textContent = commentText;
	commentTarget.value = commentText;
}

function commentReplyInit()
{
	showReplyLoggedIn();
	colorReplies(20);
}
/** nyxReactions.js ^ *********************************************************/
/** nyxComment.js **************************************************************
 * @minify true
 */
NYX.cache.daapiProcessUrl = serverUrl;
var d=document.domain.split('.');
d=d[d.length - 2]+'.'+d[d.length - 1];
NYX.cache.domain = d;
switch(d) {
	case 'charlotteobserver.com':
	case 'macon.com':
	case 'bradenton.com':
	case 'sunherald.com':
		if (typeof thisArticlePubDate != 'undefined' && thisArticlePubDate) {
			var pubDate = new Date(thisArticlePubDate), fixDate = new Date('September 11, 2008 12:00 PM');
			thisArticleId = (pubDate.getTime() > fixDate.getTime()) ? d + '_' + thisArticleId : thisArticleId;
		}
		break;    
	case 'thesunnews.com':
		thisArticleId = 'myrtlebeachonline.com_' + thisArticleId;
		break;    
	default:
		thisArticleId = d + '_' + thisArticleId;
}
thisArticleUrl = thisArticleUrl.replace(/\/v-[^\/]+/,'');
var thisArticleKey = new ArticleKey(thisArticleId);
var commentsPerPage = (typeof mi_comments_per_page == 'undefined' || mi_comments_per_page > 10) ? 10 : (mi_comments_per_page < 3) ? 3 : mi_comments_per_page;
var numOfRecommends = 0;
//pull the current page number from the querystring (defaults to 1)
var currentCommentPage = NYX.util.querystring.get("pageNum");
if (currentCommentPage === null) {currentCommentPage = 1;}

//get the sort criteria for comment output from the querystring (defaults as needed);
//stored in the Nyx cache so that object instances can access it too (like a global)
var qsParamForSorting = "commentSort";
NYX.cache.commentSort = NYX.util.querystring.get(qsParamForSorting);
if (NYX.cache.commentSort === null)
{
	if (typeof mi_comment_sort_preference != 'undefined') {
		switch ( mi_comment_sort_preference ) {
			case 'TimeStampAscending':
			case 'TimeStampDescending':
			case 'RecommendationsDescending':
			case 'RecommendationsAscending':
				NYX.cache.commentSort = mi_comment_sort_preference;
				break;
			default:
				NYX.cache.commentSort = 'TimeStampDescending';
		}
	} else { NYX.cache.commentSort = 'TimeStampDescending'; }
}


//function to change the sort
function sortComments(criterion) {
	//alter the existing querystring
	var newQuerystring = NYX.util.querystring.set(qsParamForSorting, criterion, location.search);
	
	//reset to the first page of the comments -- you can remove this as needed
	newQuerystring = NYX.util.querystring.set("pageNum", 1, newQuerystring);
	
	//do the navigation
	location.search = newQuerystring;
}

//callback manager
function daapiCallback(responseBatch) {
	//log the response -- for whatever reason (some scope issue), we have to re-fix the Safari console on async callbacks
	NYX.fixConsole();
	console.dir(responseBatch);
	
	myGadgetAva.writeGui(responseBatch.Responses[0].User);
	NYX.cache.DisplayName = responseBatch.Responses[0].User.DisplayName;
	var respIdx;
	if (!responseBatch.Responses[1].Article) {
		var articlePath = thisArticleUrl.replace(/^(http:\/\/)?[^\.]*\.*[^\.]+\.[^\/]+(\/.*)$/,'$2');
		var origin = NYX.cache.iconRoot.replace(/^http:\/\/([^\/]+)\/.*/,'$1');
		responseBatch.Responses[2] = responseBatch.Responses[1];
		responseBatch.Responses[1] = {
			'Article':{
				'ArticleKey':new ArticleKey(thisArticleId),
				'Categories':[],
				'Comments':{'NumberOfComments':0},
				'PageTitle':thisArticleTitle,
				'PageUrl':'http://' + location.hostname + articlePath,
				'Ratings':{
					'AverageRating':'0',
					'CurrentUserRating':'0',
					'NumberOfRatings':'0'
				},
				'Recommendations':{
					'CurrentUserHasRecommended':'False',
					'NumberOfRecommendations':'0'
				},
				'Reviews':{'NumberOfReviews':'0'},
				'Section':{'Name':thisArticleSection},
				'SiteOfOrigin':origin
			}
		};
	}
	if(responseBatch.Responses[1].Article.Recommendations.NumberOfRecommendations){
		numOfRecommends=responseBatch.Responses[1].Article.Recommendations.NumberOfRecommendations;
		var recDiv=document.getElementById('recommendation');
		var comCount=document.getElementById('commentsCount');
		if (recDiv && comCount) {
			comCount.innerHTML = responseBatch.Responses[2].CommentPage.NumberOfComments;
			if(responseBatch.Responses[1].Article.Recommendations.CurrentUserHasRecommended == "False"){
				recDiv.innerHTML = "<a href='#none' onClick='artRecommend();'><img src='"+NYX.cache.iconRoot+"arrow_up_rec.gif' /> Recommend</a> ("+responseBatch.Responses[1].Article.Recommendations.NumberOfRecommendations+")";
			}else{
				recDiv.innerHTML = "<img src='"+NYX.cache.iconRoot+"icon_accept.gif' /> Recommended ("+responseBatch.Responses[1].Article.Recommendations.NumberOfRecommendations+")";   
			}
		}
	}
	//loop over the responses -- here's where you can add your custom callback code as needed
	for (respIdx = 0; respIdx < responseBatch.Responses.length; respIdx++) {
		var thisResponse = responseBatch.Responses[respIdx];
		if (typeof thisResponse.User == "object") {
			//set the "global" flag to indicate whether the user is logged in
			if (thisResponse.User.UserTier.toLowerCase() != "anonymous") {NYX.cache.userIsLoggedIn = true;}
		} else if (typeof thisResponse.CommentPage == "object") {
			//pass the comment page to the appropriate Nyx gadget
			outputGadget.writeGui(thisResponse.CommentPage);
		}
	}
}

//create a gadget for handling the avatar
var myGadgetAva = new NYX.CurrentUser("AvatarOutput");
//create a daapi batch
var requestBatch = new RequestBatch();

//get the current user to see if they're logged in (you can use the response in other ways if you like)
requestBatch.AddToRequest( new UserKey() );
requestBatch.AddToRequest(thisArticleKey);
//FOR DEMO PURPOSES ONLY!... make sure the article exists
//var articlePath = thisArticleUrl.replace(/^(http:\/\/)?[^\.]*\.*[^\.]+\.[^\/]+(\/.*)$/,'$2');
//requestBatch.AddToRequest( new UpdateArticleAction(thisArticleKey, 'http://' + location.hostname + articlePath, thisArticleTitle , new     Section(thisArticleSection), [new Category(thisArticleCatagory)] ) );

//request the article for reaction counts, and the current comment page
//unneeded: requestBatch.AddToRequest(thisArticleKey);
requestBatch.AddToRequest( new CommentPage(thisArticleKey, commentsPerPage, currentCommentPage, NYX.cache.commentSort) );

function artRecommend(){
	requestBatch = new RequestBatch(); 
	var articlePath = thisArticleUrl.replace(/^(http:\/\/)?[^\.]*\.*[^\.]+\.[^\/]+(\/.*)$/,'$2');
	requestBatch.AddToRequest( new UpdateArticleAction(thisArticleKey, 'http://' + location.hostname + articlePath, thisArticleTitle , new     Section(thisArticleSection), [new Category(thisArticleCatagory)] ) );
	requestBatch.AddToRequest(new RecommendAction(thisArticleKey));
	requestBatch.BeginRequest(serverUrl, RecommendSubmitted);
}
function RecommendSubmitted(responseBatch) {
	if (responseBatch.Messages[0].Message == 'ok') {
		//alert('Item successfully recommended.')
		document.getElementById('recommendation').innerHTML="<img src='"+NYX.cache.iconRoot+"icon_accept.gif' /> Recommended ("+ ++numOfRecommends +")";
	} else {
		alert(responseBatch.Messages[0].Message);
	}
}









NYX.CommentInput = function(idRoot, articleKey) {
	this.idRoot = idRoot;
	this.MAX_COMMENT_LENGTH = 1000;	//needs to match the SiteLife server config!
	NYX.cache.max_comment_length = this.MAX_COMMENT_LENGTH;
	NYX.cache.init_max_comment_length = this.MAX_COMMENT_LENGTH;
	NYX.cache.commentReplyLength = 0;//SCC added
	this.getTrueMaxLength = function() {
		return this.MAX_COMMENT_LENGTH - 5;
	};
	this.makeHTML = function() {
		//builds the form and returns its HTML
		NYX.cache.articlePath = thisArticleUrl.replace(/^(http:\/\/)?[^\.]*\.*[^\.]+\.[^\/]+(\/.*)$/,'$2');
		var theForm = document.createElement("form");
		theForm.id = idRoot + "_inputForm";
		theForm.action = "#";
		theForm.method='post';
		theForm.style.display='inline';
		var addHeading = document.createElement("div");
		if (gSiteLife.mi.userLoggedIn()) {
			addHeading.className='Comments_AddHeading';
			addHeading.appendChild(document.createTextNode('Add a comment '));
			var elmRef=addHeading.appendChild(document.createElement('span'));
			elmRef.className='Comments_MaxLengthText';
			elmRef.appendChild(document.createTextNode('(max '+this.MAX_COMMENT_LENGTH+' characters)'));
		} else {
			addHeading.className='SiteLife_Login';
			addHeading.id='SiteLife_Login';
			addHeading.appendChild(document.createTextNode('You must be logged in to leave a comment. '));
			elmRef=addHeading.appendChild(document.createElement('a'));
			elmRef.href='/static/insite/login.html?goto='+window.location.href;
			elmRef.appendChild(document.createTextNode('Login'));
			addHeading.appendChild(document.createTextNode(' | '));
			elmRef=addHeading.appendChild(elmRef.cloneNode(false));
			elmRef.href='/reg-bin/int.cgi?mode=register&goto='+window.location.href;
			elmRef.appendChild(document.createTextNode('Register'));
		}
		$(addHeading).prepend('<div class="Sitelife_PluckLogo"><a target="_blank" href="http://www.pluck.com"><img src="http://pluck.'+document.domain+'/ver1.0/Content/images/poweredbypluck.gif" style="border: 0px none ;"/></a></div>');
		elmRef=addHeading.appendChild(elmRef.cloneNode(false));
		elmRef.id='CommentError';
		elmRef.className='Comments_Error';
		//for commenting reply:
		var commentTopMsg = addHeading.appendChild(document.createElement('span'));
		commentTopMsg.id='commentTopMsg';
		commentTopMsg.className='commentTop_Msg';
		var commentTopReply = addHeading.appendChild(document.createElement('span'));
		commentTopReply.id='commentTopReply';
		commentTopReply.className='commentTop_Reply';
		
		theForm.appendChild(addHeading);
		var addTextArea = addHeading.cloneNode(false);
		addTextArea.className='Comments_AddTextarea';
		addTextArea.id='';
		var textArea = addTextArea.appendChild(document.createElement("textarea"));
		textArea.id = 'commentBody';
		$(textArea).bind('keyup',function(){ checkCommentLength(document.getElementById("commentBody")); });
		textArea.disabled = (gSiteLife.mi.userLoggedIn()) ? false : 'true';
		var filterMsg = addTextArea.appendChild(addHeading.cloneNode(false));
		filterMsg.className='SiteLife_Filtered';
		filterMsg.id='';
		theForm.appendChild(addTextArea);
		var commentsSubmit = addTextArea.cloneNode(false);
		commentsSubmit.className='Comments_Submit';
		commentsSubmit.id='';
		var theButton = document.createElement("input");
		theButton.type="submit";
		theButton.value = "Submit";
		theButton.id="comment_submit_button";
		theButton.disabled = (gSiteLife.mi.userLoggedIn()) ? false : 'true';
		commentsSubmit.appendChild(theButton);
		theForm.appendChild(commentsSubmit);
		$(theForm).bind('submit',this.submit);
		$('#Comments_Container').prepend(theForm);
	};
	this.submit = function() {
		if (document.getElementById("commentBody").value.trim() === "") {
			document.getElementById("CommentError").innerHTML = " * Please provide a comment.";
			return false;
		} else {
			addReplyToComment();
			$('.Comments_Submit input[type=submit]').attr({disabled:true});
			checkCommentLength(document.getElementById("commentBody"));
			var pageUrl = 'http://' + location.hostname + NYX.cache.articlePath;
			requestBatch = new RequestBatch(); 
			requestBatch.AddToRequest(new CommentAction(thisArticleKey,pageUrl,thisArticleTitle,document.getElementById('commentBody').value));
			requestBatch.AddToRequest( new UpdateArticleAction(thisArticleKey, 'http://' + location.hostname + NYX.cache.articlePath, thisArticleTitle , new     Section(thisArticleSection), [new Category(thisArticleCatagory)] ) );
			requestBatch.BeginRequest(serverUrl, commentSubmitted); 

		}
		return false;
	};
};
checkCommentLength = function(textbox) {
	//call in the onkeyup event handler; truncates the comment when max length is exceeded
	//TODO: goldplating -- handle formatting like *bold* and _italic_
	//alert(textbox == event);
	//var textbox = theEvent.target;
//	var maxLength = this.getTrueMaxLength();
	if (textbox.value.length > NYX.cache.max_comment_length) {
		//TODO: goldplating -- add gui effect
		textbox.value = textbox.value.substring(0, NYX.cache.max_comment_length);
		document.getElementById("CommentError").innerHTML = " * Your comment has been truncated to meet the character limit.";
	} else {
		document.getElementById("CommentError").innerHTML = "";
	}
};

commentSubmitted = function(responseBatch) {
	//we have to re-fix the console on asynchronous callbacks (for Safari)
	NYX.fixConsole();
	if (responseBatch.Messages[0].Message == "ok") {
		location = gSiteLife.mi.commenting.submitReturnAddress;
	} else if (responseBatch.Messages[0].Message.match('not permitted by our language filter')) {
		var obscenities = responseBatch.Messages[0].Message.replace(/^.+for example: ([^\)]+).+$/,'$1');
		commentErrorProcess('Please edit or remove the following word(s), then resubmit your comments: '+obscenities+'.',true);
	} else if (responseBatch.Messages[0].Message.match('rapid posting of multiple comments')) {//SCC - added following section:
		commentErrorProcess('We restrict the rapid posting of comments.  Please wait 15 seconds before submitting again.',true);
	} else {
		$('.comWrapper .SiteLife_Filtered').empty().append((typeof CommentTechProbMsg != 'undefined') ? CommentTechProbMsg : 'Commenting is currently experiencing temporary technical difficulties. We value your input, please try submitting your comment later. We apologize for the inconvenience.');
	}
};
//disply an  error message 'errorMsg', submitOK=true => enable submit button, else disable it
commentErrorProcess = function(errorMsg, submitOK){
	stripReplyText();//SCC comment  reply
	$('.comWrapper .SiteLife_Filtered').empty().append(errorMsg);
	if(submitOK){$('.Comments_Submit input[type=submit]').attr({disabled:false});}
};

NYX.commentingInit = function() {
	if (sitelife_is_on && siteLife_master_switch_on) {
		$(document).ready(
			function(){
				document.domain = NYX.cache.domain;
				var commentInput = new NYX.CommentInput('commenting');
				commentInput.makeHTML();
				commentTempl = (document.getElementById("commentOutputTemplate")) ? document.getElementById("commentOutputTemplate").innerHTML : '';
				window.outputGadget = new NYX.CommentOutput("nyxComments",commentTempl);
				window.outputGadget.pager = new NYX.Pager( {
					pageLength: commentsPerPage,
					template: "More comments on this story: @Nyx.pageLinks@",
					domTargetElem: document.getElementById("nyxComments_pager"),
					linkLimit: 10
				} );
				myGadgetAva.userTemplate  = (document.getElementById("userTemplate")) ? document.getElementById("userTemplate").innerHTML : '';
				myGadgetAva.guestTemplate = (document.getElementById("anonTemplate")) ? document.getElementById("anonTemplate").innerHTML : '';
				function pluckCallToAction() {requestBatch.BeginRequest(serverUrl, daapiCallback);}
				new NYX.ieSafeExecution(pluckCallToAction).execute();
			});
	}
};
/** nyxComment.js ^ ********************************************************* */