/**
* community.js
*
/*
* GENERIC TOOLS
*
*/
function GenericTools () {
/**
* Convert newlines in a string to something that can be displayed in a browser.
*/
this.newlinesToHTML = function(text) {
var result = text.replace(/\r\n/g,"\n");
result = result.replace(/\n/g,"
\n");
return result;
}
/**
* Convert newlines in a string to something that can be displayed in a browser.
*/
this.htmlToNewlines = function(text) {
var result = text.replace(/<[bB][rR][ ]*\/+>/g,""); // we are betting that a newline was put after the BR anyway
return result;
}
/**
* Safe method for determining if a variable is available.
*/
this.isDefined = function(object, variable) {
return (typeof(eval(object)[variable]) != "undefined");
}
/**
* Gets the value of the specified cookie.
*
* name Name of the desired cookie.
*
* Returns a string containing value of specified cookie, or null if cookie does not exist.
*/
this.getCookie = function(name) {
var dc = document.cookie;// this returns/reads all cookies for the domain separated by a semicolon
var prefix = name + "=";// hd=
var begin = dc.indexOf("; " + prefix);// returns a -1 or whole number for position of "; hd"
if (begin == -1){ // "; hd" string does not exist - meaning that hd is the first cookie in the collection of cookies for the domain
begin = dc.indexOf(prefix); //begin is 0 since prefix ("hd") is at the 0 position
if (begin != 0) {return null;} //begin should be at index 0 - fail if not
} else {
begin += 2; // add 2 to current begin -- not sure why. perhaps this is useful if hd is not the first cookie for the domain
}
var end = document.cookie.indexOf(";", begin); // search the cookie collection for ";", start the search at begin
if (end == -1) { // end does not exist so there is only one cookie for the domain
end = dc.length; // only one cookie for the domain so the end is the length
}
return unescape(dc.substring(begin + prefix.length, end)); // return the values between the end of "hd=" and the end of the cookie
}
/**
* Gets the value of a specified query parameter.
*
* name Name of the value from the query string.
*
* Returns a string containing value of specified parameter, or null if it does not exist.
*/
this.getQueryParameter = function(name) {
// for now, piggyback on SiteLife's function for this.
return gSiteLife.GetParameter(name);
}
/**
*
*/
this.mouseX = function(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;
}
/**
*
*/
this.mouseY = function(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;
}
/**
*
*/
this.hideDiv = function(elementId) {
var el = document.getElementById(elementId);
if (el) {
el.style.display = "none";
}
}
/**
*
*/
this.showDivAtMouse = function(mouseEvent, elementId) {
var el = document.getElementById(elementId);
var posx = mouseX(mouseEvent) - 170;
var posy = mouseY(mouseEvent);
//normalize to make sure we at least appear on the screen
if (posx < 0) posx = 10;
if (posy < 0) posy = 10;
el.style.left = posx + "px";
el.style.top = posy + "px";
el.style.display = "block";
}
this.debug = function(s) {
if (SITELIFE_DEBUG && this.isDefined(window, "console")) {
console.log(s);
}
}
}
// Instantiate a tools object for use elsewhere.
var tools = new GenericTools();
function recommendArticle(key, count)
{
uniqueCommentKey = key;//update the global variable for the DAAPI response handler
recommendedCount = count;//update the global variable for the DAAPI response handler
var wp_RequestBatch = new RequestBatch();
var recommendRequest = new RecommendAction(new ArticleKey(key));
wp_RequestBatch.AddToRequest(recommendRequest);
// daapiServerUrl is from shared.js
wp_RequestBatch.BeginRequest(daapiServerUrl, recommendArticleActionHandler);
}
function recommendArticleActionHandler(responseBatch)
{
for (var i=0; i";
}
function charLimit(oSrc)
{
//need to verify getAttribute method on older browsers
var mlength = oSrc.getAttribute ? parseInt(oSrc.getAttribute("maxlength")) : "";
if (oSrc.getAttribute && oSrc.value.length > mlength)
{
oSrc.value = oSrc.value.substring(0, mlength);
}
}
function charCount(oSrc, charCountLabel)
{
var charCount = document.getElementById(charCountLabel);
var mlength = oSrc.getAttribute ? parseInt(oSrc.getAttribute("maxlength")) : "";
if (oSrc.getAttribute && oSrc.value.length > mlength)
{
oSrc.value = oSrc.value.substring(0, mlength);
}
if(charCount)
{
charCount.innerHTML = mlength - oSrc.value.length;
}
}
function clearReportAbuseForms()
{
var reportAbuseReasonForm = document.getElementById("ReportAbuse_Form");
reportAbuseReasonForm.reset();//reset is a clean, scalable way to handle the form clearing but will not reset the character counter
var charCount = document.getElementById("charCountDisplayRemoval");
charCount.innerHTML = "500"; //not ideal but need this element update because a form clear will not update the char count text
}
/***
***
*** SITELIFE INTEGRATION
***
***/
function SiteLifeIntegration () {
/**
** Load-time DAAPI tools
**/
this.doPageLoadDAAPI = function() {
if (this.pageLoadDAAPI_RequestBatch != null) {
this.pageLoadDAAPI_RequestBatch.BeginRequest(daapiServerUrl, new Function("respBatch", "sli.loadTimeCallBack(respBatch)"));
tools.debug("Begun Page Load DAAPI request to server with " + this.batchRequests.length + " requests");
}
}
/**
* Not really sure iof this is needed. But since there are places where we need to
* make a second call to the server, I thought I would make the second call distinct
* so that we can come back to it if we need to.
*/
this.doPageLoadSubsequentDAAPI = function() {
if (this.pageLoadDAAPI_RequestBatch != null) {
this.pageLoadDAAPI_RequestBatch.BeginRequest(daapiServerUrl, new Function("respBatch", "sli.loadTimeCallBack(respBatch)"));
tools.debug("Begun Subsequent Page Load DAAPI request to server with " + this.batchRequests.length + " requests");
}
}
this.pageLoadDAAPI_RequestBatch = null;
// Keep a handle on all of the things that we have asked for.
this.batchRequests = new Array();
// convenience function so th that batchRequest stays up-to-date.
this.addToPageLoadRequestBatch = function(request) {
this.pageLoadDAAPI_RequestBatch.AddToRequest(request);
this.batchRequests.push(request);
tools.debug("L132 batchRequests length now " + this.batchRequests.length);
}
this.clearPageLoadRequestBatch = function() {
this.pageLoadDAAPI_RequestBatch = new RequestBatch();
this.batchRequests.length = 0;
tools.debug("L137 batchRequests length now " + this.batchRequests.length);
}
this.setupPageLoadDAAPI = function() {
this.pageLoadDAAPI_RequestBatch = new RequestBatch();
}
this.loadTimeCallBack = function (responseBatch) { // old jClientCallBack()
if (SITELIFE_DEBUG) {
tools.debug("ResponseBatch Messages length is " + responseBatch.Messages.length);
for (var i = 0; i < responseBatch.Messages.length; i++) {
var serverMessage = responseBatch.Messages[i];
tools.debug("Server Message " + i + ": " + serverMessage.MessageTime + " -- " + serverMessage.Message);
}
for (var i = 0; i < responseBatch.Responses.length; i++) {
var response = responseBatch.Responses[i];
tools.debug("Response " + i + ": " + response);
}
}
//tools.showProps(responseBatch);
var tn = document.createTextNode("" + responseBatch.toSource());
var pre = document.createElement('pre','prid');
pre.appendChild(tn);
document.body.appendChild(pre);
for (var i = 0; i < responseBatch.Responses.length; i++) {
var response = responseBatch.Responses[i];
if (response.DiscoverArticlesAction != null) {
if (this.discoverArticlesHandler != null) {
this.discoverArticlesHandler(response.DiscoverArticlesAction);
} else {
tools.debug("No discoverArticlesHandler defined and response " + i + " is a DiscoverArticlesAction");
}
} else if (response.Article != null) {
if (this.articleHandler != null) {
this.articleHandler(response.Article);
} else {
tools.debug("No articleHandler defined and response " + i + " is an Article");
}
} else if (response.CommentPage != null) {
if (this.commentsPageHandler != null) {
//window.alert(response.CommentPage.Comments[0].Author.UserTier);
this.commentsPageHandler(response.CommentPage);
} else {
tools.debug("No commentsPageHandler defined and response " + i + " is a CommentPage");
}
}
}
}
/**
* DAAPI Action Handlers
*/
//this.reportAbuseActionHandler = null;
this.commentsPageHandler = null;
this.discoverArticlesHandler = null;
this.articleHandler = null;
this.commentActionHandler = function(responseBatch) {
if (responseBatch.Messages.length != 1) {
// ASSERT that we only are doing one thing here.
alert("SiteLife sent me back too many messages.");
for (var i = 0; i < responseBatch.Messages.length; i++) {
var serverMessage = responseBatch.Messages[i];
alert(serverMessage.MessageTime + ": " + serverMessage.Message);
}
return false;
}
var serverMessage = responseBatch.Messages[0];
var response = responseBatch.Responses[0];
tools.debug("Handling response from CommentAction"); // BOOKMARK!
//we need to do this stuff async
// check for errors.
for (var i = 0; i < responseBatch.Responses.length; i++) {
response = responseBatch.Responses[i];
if (response.CommentAction != null) {
alert("Ok, so I get a CommentAction back. response object " + i);
}
}
// empty out the box so that no one gets confused.
// ASSERT
document.getElementById("wp_comments_comment").value = "";
// go look at comments.
document.location.href = "/wp-dyn/comments/index.html?contentID=" + wp_article.id;
}
/**
** Form Handlers
**/
/**
* Handle comments left on articles. This method should be invoked by the form
* when it is ready to submit the comments to SiteLife.
*/
this.doArticleCommentAction = function() {
tools.debug("I am commenting on an article!");
var commentEl = document.getElementById("wp_comments_comment");
var commentActionButtonEl = document.getElementById("wp_comments_submit");
// ASSERT elements are present.
// stop user from doing this multiple times.
commentEl.disabled = true;
commentActionButtonEl.disabled = true;
var commentsRequestBatch = new RequestBatch();
var commentText = commentEl.value;
if (commentText != null) {
var finalCommentText = tools.newlinesToHTML(commentText);
//alert("yea: " + finalCommentText);
var theComment = new CommentAction(new ArticleKey(wp_article.id),
communityHostUrl + wp_article.path,
wp_article.headline,
finalCommentText);
tools.debug("Sending comment for article " + wp_article.id + " to SiteLife.");
commentsRequestBatch.AddToRequest(theComment);
// daapiServerUrl is from shared.js
commentsRequestBatch.BeginRequest(daapiServerUrl, new Function("respBatch", "sli.commentActionHandler(respBatch)"));
} else {
tools.debug("Something happened when trying to submit comments. Empty comment? REVISIT");
commentEl.disabled = false;
commentActionButtonEl.disabled = false;
}
}
this.debug = function(message) {
if (SITELIFE_DEBUG) {
var debugEl = document.getElementById("SiteLifeDebug");
if (debugEl != null) {
debugEl.innerHTML = debugEl.innerHTML + message + "\n";
} else {
window.alert(message);
}
}
}
}
// Instantiate a SiteLifeIntegration, if we need to.
var sli = null;
if (SITELIFE_ENABLED) {
sli = new SiteLifeIntegration();
}
/*
* Article
*/
function _Article() {
this.articleKey; // ArticleKey object
this.serverUrl = daapiServerUrl;
this.Article = null;
this.User = null;
this.CommentCountHandler;
this.updateArticleActionObj = null;
this.CallBack = function f() { };
this.Sections = null;
this.Categories = null;
this.UserTier = null;
this.Age = 7; // maximum days back to discover articles
this.ItemsToGet = 10; // number of items to return
/**
* Sets the handler for the response from the SiteLife servers
* DAAPI Processor. For reasons of scope, this has to be set once
* the object is instatiated and cannot be set within the object.
*
* callBack - a function that takes a DAAPI ResponseBatch object.
* Should always be set to the instantiated object of
* this class's ProcessResponse method.
*/
this.setCallBack = function (callBack) {
this.CallBack = callBack;
}
/**
* articleDetails - an UpdateArticleAction object.
*/
this.SetArticleDetails = function(articleDetails) {
// console.dir(articleDetails);
this.articleKey = new ArticleKey(articleDetails.UpdateArticleAction.UpdateArticle.ArticleKey.Key);
this.updateArticleActionObj = articleDetails;
}
this.SetDiscoverySections = function(sec) {
this.Sections = sec;
}
this.SetDiscoveryCategories = function(cat) {
this.Categories = cat;
}
this.SetDiscoveryUserTiers = function(contrib) {
this.UserTier= contrib;
}
this.SetDiscoveryActivities = function(act) {
this.Activity= act;
}
this.ProcessResponse = function(responseBatch) {
//tools.debug("ProcessResponse");
var bNeedToUpdate = false;
this.Article=null; //MSM:9/26/07
for (var i = 0; i < responseBatch.Responses.length; i++) {
var response = responseBatch.Responses[i];
// our request was good
if (response.Article != null) {
this.ParseArticle(response.Article);
// see if we need to run update article action
if (this.updateArticleActionObj != null) {
// since WPNI is using only Sections at this time we left out the Categories
if ((JSON.stringify(response.Article.Section) != JSON.stringify(this.updateArticleActionObj.UpdateArticleAction.Section.Section)) ||
//(JSON.stringify(response.Article.Categories.Name) != JSON.stringify(this.updateArticleActionObj.UpdateArticleAction.Categories.Categories)) ||
(response.Article.PageTitle != this.updateArticleActionObj.UpdateArticleAction.OnPageTitle) ||
(response.Article.PageUrl != this.updateArticleActionObj.UpdateArticleAction.OnPageUrl))
{
bNeedToUpdate = true;
}
}
} else if (response.User != null) {
this.User = response.User;
} else if (response.DiscoverArticlesAction != null) {
// reuses the 'this.Article.'
this.ParseArticle(response.DiscoverArticlesAction);
} else { // added these lines
bNeedToUpdate = true; // added these lines
} // added these lines
}
// if (this.Article) //MSM:9/26/07
this.CommentCountHandler(this.Article); // this is calling your Draw..Function with the Article set from ‘this.ParseArticle(response.Article)’ above.
// then when that is done, we send off the request to UpdateArticleAction if and only if we need to.
if (bNeedToUpdate == true) {
// RunUpdateArticleAction
var requestBatch = new RequestBatch();
// Always get teh current user!
if (this.updateArticleActionObj != null) {
requestBatch.AddToRequest(this.updateArticleActionObj);
requestBatch.BeginRequest(daapiServerUrl, this.CallBack);
}
}
}
this.ParseArticle = function(articleObj) {
this.Article = articleObj;
}
this.SetCommentCountHandler = function(handler) {
this.CommentCountHandler = handler;
}
this.SetDiscoveryHandler = function(handler) {
this.CommentCountHandler = handler;
}
this.CallServer = function() {
if (null == this.Article) {
// ASSERT: I better have an article id!
var requestBatch = new RequestBatch();
// console.dir(this.articleKey);
// Always get teh current user!
requestBatch.AddToRequest(this.articleKey);
requestBatch.AddToRequest(new UserKey());
if (this.updateArticleActionObj != null) {
// requestBatch.AddToRequest(this.updateArticleActionObj);
}
// console.dir(requestBatch);
requestBatch.BeginRequest(daapiServerUrl, this.CallBack);
}
}
this.Discover = function() {
// lets find some articles via discovery
var requestBatch = new RequestBatch();
var discoveryAction = new DiscoverArticlesAction(
this.Sections,
this.Categories,
this.UserTier,
this.Activity,
this.Age,
this.ItemsToGet);
requestBatch.AddToRequest(discoveryAction);
requestBatch.BeginRequest(daapiServerUrl, this.CallBack);
}
}
/*
* Comments:
* GetAllComments
* Given an ArticleID build an array of all the comments
*/
function _Comments() {
this.PERMALINK_QUERYSTRING_PARAM = "sl_cpl";
this.articlekey;
this.article = null; // the article that we are working with
this.batch = 1;
this.count = 0;
this.sortOrder = "TimeStampDescending";
this.serverUrl = "http://community.washingtonpost.com/ver1.0/Direct/Process";
this.theComments = new Array(); // array of comments
this.DesiredComments = 10; // number that want to be returned.
this.AbuseThreshhold = 3; // number of abuse counts to ignore the comments.
this.NumberOfComments = 0; // total number of comments for this article
this.User = null; // currently logged in user
this.CallBack = null; // callback function to call after comments are returned
this.CBCommentDisplay = null; // user callback function to draw the comments with the array of comments
this.CommentsPerPage = 20; // number of comment per paginated page (this has to be a multiple of 10)
this.OnPage =0; // on page what of pagination - pluck count in batches of 10
this.NumberPerPage=0; // number of comments per page - pluck count normally 10
this.PageNumber = 1; // 1 based page number of current pagination
this.FailureCallBack = null; // this is called when a comment fails (typically dirty work filter)
this.SuccessCallBack = null; // this is called whne a comment is successful (typically turning the page)
this.CmtCallBack = null; // comment callback, necessary to split since we want comments and entry on the same page
this.needCommentCount = false;
this.pageToGoTo = 0; //hack
// console.log("starting _Comments");
}
_Comments.prototype.SetSortOrder = function(sort) {
this.sortOrder = sort;
}
_Comments.prototype.SetCommentDisplay = function(func) {
this.CBCommentDisplay = func;
}
_Comments.prototype.SetReturnCount = function(count) {
this.DesiredComments = count;
}
_Comments.prototype.SetCallBack = function(ourCB) {
this.CallBack = ourCB;
}
_Comments.prototype.SetCmtCallBack = function(ourCB) {
this.CmtCallBack = ourCB;
}
// return the page number that we are currently requesting/viewing
// this is for pagination in the UI
_Comments.prototype.GetCurrentPageNumber = function() {
return (this.PageNumber);
}
_Comments.prototype.GetCurrentPermaPageNumber = function() {
// return (this.PageNumber);
return (this.GetPageCount()- this.PageNumber);
}
_Comments.prototype.SetSuccessCallBack = function(func) {
this.SuccessCallBack = func;
}
_Comments.prototype.SetFailureCallBack = function(func) {
this.FailureCallBack = func;
}
_Comments.prototype.GetComments = function(key) {
this.articlekey = key;
var qs = new _QueryString();
var page = qs.CommentPage();
tools.debug("starting page"+page);
tools.debug("starting page");
if (page) {
this.needCommentCount = true;
this.pageToGoTo = page;
this.GetAllComments(key);
this.ScrollToLink = "articleComment_"+qs.CommentKey();
} else {
this.GetAllComments(key);
}
return (true);
}
_Comments.prototype.GetCommentsPage = function(pageNumber) {
this.count = 0;
this.batch = ((parseInt(pageNumber)*parseInt(this.CommentsPerPage))/10); // divide by plucks batch number to get the right page
this.batch = parseInt(this.batch) -1; // subtract one because the pages are 1 based.
this.PageNumber = parseInt(pageNumber);
this.GetAllComments(this.articlekey);
this.theComments.length = 0;
}
_Comments.prototype.GetPageCount = function() {
return parseInt(1+parseInt(this.NumberOfComments)/this.CommentsPerPage);
}
_Comments.prototype.GetAllComments = function(key) {
// article is the unique identifier
var articleKey = new ArticleKey(key);
// allocate a new request batch to send to the pluck server
var requestBatch = new RequestBatch();
// We are interested in comments, lets get the comment page
var commentPage = new CommentPage(articleKey,10,this.batch,this.sortOrder);
requestBatch.AddToRequest(new UserKey());
requestBatch.AddToRequest(articleKey);
requestBatch.AddToRequest(commentPage);
requestBatch.BeginRequest(this.serverUrl, this.CallBack);
// save the articlekey for subsequent calls.
this.articlekey = key;
}
_Comments.prototype.GetMoreComments = function() {
this.GetAllComments(this.articlekey,this.PluckReturn);
}
_Comments.prototype.ParseCommentPage = function(cmtPage) {
// parse the comment page and build the comment list
tools.debug("ParseCommentPage");
this.NumberOfComments = cmtPage.NumberOfComments;
this.NumberPerPage = cmtPage.NumberPerPage;
this.OnPage = cmtPage.OnPage;
tools.debug("cmtPage.Comments.length : " + cmtPage.Comments.length);
for (var c=0;c < cmtPage.Comments.length; c++) {
// this check does the normal display stuff.
// showing the comments if they are valid (notBlocked,notAbusive,and equal to the number we want to see)
if ((cmtPage.Comments[c].Author.IsBlocked == "False") &&
(parseInt(cmtPage.Comments[c].AbuseReportCount) < this.AbuseThreshhold) &&
(this.count < this.DesiredComments)){
this.theComments[this.count]= cmtPage.Comments[c];
this.count ++ ;
}
else if ((cmtPage.Comments[c].Author.IsBlocked == "True") &&
// if this is a bozo'd user, show his comments
(parseInt(cmtPage.Comments[c].AbuseReportCount) < this.AbuseThreshhold) &&
(cmtPage.Comments[c].Author.UserKey.Key == this.User.UserKey.Key) &&
(this.count < this.DesiredComments)){
this.theComments[this.count]= cmtPage.Comments[c];
this.count ++ ;
}
}
}
_Comments.prototype.PluckReturn = function(responseBatch) {
// console.log("PluckReturn");
// console.dir(responseBatch);
for (var i = 0; i < responseBatch.Responses.length; i++) {
var response = responseBatch.Responses[i];
// Need to scrub this, because we are not always going to get an "ok" back now that we are also asking for a User.
//if(responseBatch.Messages[0].Message == 'ok') {
// our request was good
if (response.CommentPage != null) {
// we have a comment page/header
if (this.ParseCommentPage != null){
this.ParseCommentPage(response.CommentPage);
}
} else if (response.User != null) {
this.User = response.User;
} else if (response.Article != null) {
// we have an article page with summary information
this.parseArticle(response.Article);
}
//}
}
if (this.needCommentCount == false) {
if (this.count < this.DesiredComments &&
this.count < this.NumberOfComments &&
(parseInt(this.OnPage)*parseInt(this.NumberPerPage)) 1 ) {
document.getElementById(this.ScrollToLink).scrollIntoView(true);
this.ScrollToLink = "";
}
}
}
else {
// now we have the total comment count.. lets to get the right page
this.GetCommentsPage(this.GetPageCount()-this.pageToGoTo);
this.needCommentCount = false;
}
}
_Comments.prototype.parseArticle = function(articleObj) {
this.article = articleObj;
}
/**
* Returns the current page number from a view standpoint. If there
* are 20 comments per page, and we are looking at comments 41 - 60,
* then this will return 3.
*/
_Comments.prototype.xxxgetCurrentPageNumber = function () {
// This may bne the right answer... TBD with Matt.
return this.OnPage;
}
_Comments.prototype.GetCommentArray = function() {
return this.theComments;
}
// find the comment given the comment key
_Comments.prototype.RecommendedCount = function(key){
for (var c=0;c < this.theComments.length;c++) {
if (this.theComments[c].CommentKey.Key == key) {
return parseInt(this.theComments[c].NumberOfRecommendations);
}
}
return 0;
}
// find the comment given the comment key
_Comments.prototype.getFromLoadedCommentsByKey = function(key){
var theComment = null;
for (var c = 0; (theComment == null) && (c < this.theComments.length); c++) {
if (this.theComments[c].CommentKey.Key == key) {
theComment = this.theComments[c];
}
}
return theComment;
}
_Comments.prototype.Recommend = function(key,cb) {
//recommend this comment
var recKey=new CommentKey(key);
var requestBatch=new RequestBatch();
requestBatch.AddToRequest(new RecommendAction(recKey));
this.SiteLifeRequest(requestBatch,this.RecommendCallback);
if (cb) {
cb(key,this.RecommendedCount(key));
}
}
_Comments.prototype.RecommendCallback = function(response) {
//report this comment as recomended
if(response.Messages.length>0&&response.Messages[0].Message=="ok"){
}
else {
tools.debug("RecommendCallback Failed");
}
}
_Comments.prototype.ReportAbuse = function(key,reason,text,cb) {
//report this comment as abusive.
var recKey=new CommentKey(key);
var requestBatch=new RequestBatch();
requestBatch.AddToRequest(new ReportAbuseAction(recKey,reason,text));
this.SiteLifeRequest(requestBatch,this.AbuseCallback);
if (cb) {
cb(key);
}
}
_Comments.prototype.AbuseCallback = function(response) {
//report this comment as abusive.
if(response.Messages.length>0&&response.Messages[0].Message=="ok"){
}
else {
tools.debug("ReportAbuseCallback Failed");
}
}
_Comments.prototype.NumberOfComments = function(responseBatch) {
return (this.NumberOfComments);
}
_Comments.prototype.SiteLifeRequest = function(request,callback) {
request.BeginRequest(this.serverUrl,callback);
}
_Comments.prototype.Clean = function(cmt) {
var clean="";
if(cmt.length>0){
var clean=cmt.replace(//g,">");
clean=clean.replace(/\u2019/g,"’");
clean=clean.replace(/\u201C/g,"“");
clean=clean.replace(/\u201D/g,"”");
clean=clean.replace(/\r\n/g,"\n");
clean=clean.replace(/\n/g,"
\n");
}
return (clean);
}
_Comments.prototype.AddComment = function(key,cmt) {
var articleKey = new ArticleKey(key);
var pageUrl = document.location.href;
var pageTitle = document.title;
var cleancmt = this.Clean(cmt);
// create and send request
var requestBatch = new RequestBatch();
var commentAction = new CommentAction(articleKey, pageUrl, pageTitle, cleancmt);
requestBatch.AddToRequest(commentAction);
this.SiteLifeRequest(requestBatch, this.CmtCallBack);
}
_Comments.prototype.commentSubmitted = function(responseBatch) {
if (responseBatch.Messages[0].Message == 'ok') {
if(this.SuccessCallBack) {
this.SuccessCallBack();
}
else {
alert(responseBatch.Messages[0].Message);
}
}
else {
// need to check return codes for 'dirty word filter,etc'
if(this.FailureCallBack) {
this.FailureCallBack(responseBatch.Messages[0].Message);
}
else {
alert(responseBatch.Messages[0].Message);
}
}
}
_Comments.prototype.countChars = function(field,countfield, maxlimit){
if (document.getElementById(field).value.length > maxlimit) { // trim if too long
document.getElementById(field).value = document.getElementById(field).value.substring(0, maxlimit);
}
else {
document.getElementById(countfield).innerHTML = 0 + document.getElementById(field).value.length +"/"+maxlimit ;
}
}
/**
* Draws the link for a Staff Recomends button to the comment on the
* page at the designated element. The contents of elementId will be
* overwritten. At this time, the link will only show for Staff and
* Editor tier users.
*
* Unlike other functions that require a Display method to draw the
* button, this function writes straight to the DOM.
*
* currentComment - the DAAPI Comment object for the comment that we
* are currently working with.
* parentEl - the DOM element to put the function.
*/
_Comments.prototype.CommentStaffRecommendsButton = function (currentComment, parentEl) {
// get the menu that we need on the page.
this.writeStaffRecommendDialog(document.body);
if (this.User.UserTier == "Editor" || this.User.UserTier == "Staff") {
var linkEl = document.createElement("a");
linkEl.innerHTML = "Add as Staff Recommendation";
linkEl.onclick = function(event,Key) { cmt.openStaffRecommendsDialog(event || window.event, currentComment.CommentKey.Key ); };
// linkEl.onclick = function() { cmt.openStaffRecommendsDialog(event, currentComment.CommentKey.Key ); };
// linkEl.setAttribute("onclick", "cmt.openStaffRecommendsDialog(event, '" + currentComment.CommentKey.Key + "');");
linkEl.setAttribute("href", "javascript:void(0)");
parentEl.appendChild(linkEl);
}
}
/**
* Draws the link for a PermaLink to the comment on the page at the
* designated element. The contents of elementId will be overwritten.
* At this time, the link will only show for Staff and Editor tier
* users.
*
* Unlike other functions that require a Display method to draw the
* button, this function writes straight to the DOM.
*
* currentComment - the DAAPI Comment object for the comment that we
* are currently working with.
* parentEl - the DOM element to put the function.
*/
_Comments.prototype.CommentPermaLinkButton = function (currentComment, parentEl) {
if (this.User.UserTier == "Editor" || this.User.UserTier == "Staff") {
var linkEl = document.createElement("a");
linkEl.setAttribute("href", this.createPermaLink(currentComment.CommentKey.Key));
linkEl.innerHTML = "PermaLink";
parentEl.appendChild(linkEl);
}
}
/**
* Creates a URL to a comment. Assumes that the commentId passed is
* for a comment on hte current page. The format of the querystring
* value is:
*
* ":"
*
* commenId - the DAAPI Comment CommentKey.Key value. A text string.
*/
_Comments.prototype.createPermaLink = function (commentId) {
var pageURL = document.location.protocol
+ "//" + document.location.host
+ document.location.pathname + "?"
+ this.PERMALINK_QUERYSTRING_PARAM + "="
+ this.GetCurrentPermaPageNumber() + ":"
+ commentId;
var keyValuePairs = new Array();
if (document.location.search) {
keyValuePairs = document.location.search.substr(1).split("&")
}
for (var i = 0 ; i < keyValuePairs.length; i++) {
var eqLoc = keyValuePairs[i].indexOf("=");
if (eqLoc > 0) {
var key = keyValuePairs[i].substr(0, eqLoc);
if (key != this.PERMALINK_QUERYSTRING_PARAM) {
pageURL = pageURL + "&" + keyValuePairs[i];
}
}
}
return pageURL;
}
_Comments.prototype.openStaffRecommendsDialog = function(mouseEvent, commentKey) {
//alert("I want to tell you about " + mouseEvent);
//ShowDivAtMouse
//document.getElementById("ReportAbuse_Key").value = commentKey;
var formCommentKeyEl = document.getElementById("SLSR_Comment_Key");
var formCommentOrigTextEl = document.getElementById("SLSR_Comment_Orig_Text");
var formCommentOrigDateEl = document.getElementById("SLSR_Comment_Orig_Date");
var formCommentUserDisplayNameEl = document.getElementById("SLSR_Comment_Orig_User_DisplayName");
var formCommentUserKeyEl = document.getElementById("SLSR_Comment_Orig_User_Key");
var formCommentOrigPermaLinkEl = document.getElementById("SLSR_Comment_Orig_PermaLink");
var formArticleKeyEl = document.getElementById("SLSR_Article_Key");
var formArticleURLEl = document.getElementById("SLSR_Article_URL");
var formArticleTitleEl = document.getElementById("SLSR_Article_Title");
var formCommentTextEl = document.getElementById("SL_StaffRecommends_CommentText");
var formRecommendQueueEl = document.getElementById("SL_StaffRecommends_Queue");
var origComment = this.getFromLoadedCommentsByKey(commentKey);
formCommentKeyEl.value = commentKey;
formCommentOrigTextEl.value = origComment.CommentBody;
formCommentOrigDateEl.value = origComment.PostedAtTime;
formCommentUserDisplayNameEl.value = origComment.Author.DisplayName;
formCommentUserKeyEl.value = origComment.Author.UserKey.Key;
formCommentOrigPermaLinkEl.value = this.createPermaLink(commentKey);
//console.dir(this.article);
formArticleKeyEl.value = this.article.ArticleKey.Key;
formArticleURLEl.value = this.article.PageUrl;
formArticleTitleEl.value = this.article.PageTitle;
formCommentTextEl.innerHTML = tools.htmlToNewlines(origComment.CommentBody);
tools.showDivAtMouse(mouseEvent, "SL_StaffRecommends_Container");
}
/**
* Writes the hidden menu for Staff Recommends out to the page. This
* is safe to call multiple times.
*
* perentEl - the element of the DOM to hang the menu off of.
* document.body should be fine.
*/
_Comments.prototype.writeStaffRecommendDialog = function(parentEl) {
var alreadyThere = document.getElementById("SL_StaffRecommends_Container");
if (null === alreadyThere) {
tools.debug("Need to write SL_StaffRecommends_Container");
var cont = document.createElement("div");
cont.className = "SL_StaffRecommends_Container" ;
cont.id ="SL_StaffRecommends_Container";
cont.style.display = "none";
cont.style.left = "763px";
cont.style.top = "370px";
// cont.setAttribute("class", "SL_StaffRecommends_Container");
// cont.setAttribute("id", "SL_StaffRecommends_Container");
// cont.setAttribute("style", "display: none; left: 763px; top: 370px");
cont.innerHTML = "";
parentEl.appendChild(cont);
}
}
/**
* Sets all of the form variables/inputs used by the Staff Recommends
* dialog back to their normal state.
*/
_Comments.prototype.clearStaffRecommendForm = function() {
// REVISIT
var valsToClear = new Array("SLSR_Comment_Key",
"SLSR_Comment_Orig_Text",
"SLSR_Comment_Orig_Date",
"SLSR_Comment_Orig_User_DisplayName",
"SLSR_Comment_Orig_User_Key",
"SLSR_Comment_Orig_PermaLink",
"SLSR_Article_Key",
"SLSR_Article_URL",
"SLSR_Article_Title",
"SL_StaffRecommends_CommentText");
}
/**
* Actually do the work!
*/
_Comments.prototype.doStaffRecommend = function() {
// REVISIT
var form = document.getElementById("SL_StaffRecommends_Form");
var formCommentKeyEl = document.getElementById("SLSR_Comment_Key");
var formCommentOrigTextEl = document.getElementById("SLSR_Comment_Orig_Text");
var formCommentOrigDateEl = document.getElementById("SLSR_Comment_Orig_Date");
var formCommentUserDisplayNameEl = document.getElementById("SLSR_Comment_Orig_User_DisplayName");
var formCommentUserKeyEl = document.getElementById("SLSR_Comment_Orig_User_Key");
var formCommentOrigPermaLinkEl = document.getElementById("SLSR_Comment_Orig_PermaLink");
var formArticleKeyEl = document.getElementById("SLSR_Article_Key");
var formArticleURLEl = document.getElementById("SLSR_Article_URL");
var formArticleTitleEl = document.getElementById("SLSR_Article_Title");
var formCommentTextEl = document.getElementById("SL_StaffRecommends_CommentText");
var formQueue = document.getElementById("SL_StaffRecommends_Queue");
var sr = new _StaffRecommendation();
sr.recommendationBody = formCommentTextEl.innerHTML;
sr.commentKey = formCommentKeyEl.value;
sr.commentDate = formCommentOrigDateEl.value;
sr.commentUserDisplayName = formCommentUserDisplayNameEl.value;
sr.commentUserKey = formCommentUserKeyEl.value;
sr.commentPermaLink = formCommentOrigPermaLinkEl.value;
sr.articleKey = formArticleKeyEl.value;
sr.articleURL = formArticleURLEl.value;
sr.articleTitle = formArticleTitleEl.value;
sr.queueKey = formQueue.options[formQueue.selectedIndex].value
sr.submit();
tools.hideDiv("SL_StaffRecommends_Container");
}
/**** degugging ****/
_Comments.prototype.DumpComments = function() {
tools.debug("Dumpin Comments");
for (var c=0;c < this.theComments.length;c++) {
//if(console) {
// console.log(c + " : " + this.theComments[c].CommentBody.substring(0,50));
//}
}
}
function _QueryString() {
this.PERMALINK_QUERYSTRING_PARAM = "sl_cpl";
}
_QueryString.prototype.PageQuery = function(q) {
if(q.length > 1)
this.q = q.substring(1, q.length);
else
this.q = null;
this.keyValuePairs = new Array();
if(q) {
for(var i=0; i < this.q.split("&").length; i++) {
this.keyValuePairs[i] = this.q.split("&")[i];
}
}
this.getKeyValuePairs = function() { return this.keyValuePairs;
}
}
_QueryString.prototype.getValue = function(s) {
for(var j=0; j < this.keyValuePairs.length; j++) {
if(this.keyValuePairs[j].split("=")[0] == s)
return this.keyValuePairs[j].split("=")[1];
}
return '';
}
_QueryString.prototype.getParameters = function() {
var a = new Array(this.getLength());
for(var j=0; j < this.keyValuePairs.length; j++) {
a[j] = this.keyValuePairs[j].split("=")[0];
}
return a;
_QueryString.prototype.getLength = function() {
return this.keyValuePairs.length; }
}
_QueryString.prototype.parseDomainFromURL = function () {
var url = window.location.href.split("/");
var domainparts=url[4].split(".");
var domain = domainparts[parseInt(domainparts.length)-1] + "." + domainparts[parseInt(domainparts.length)];
parseDomainFromURL = domain;
return parseDomainFromURL;
}
_QueryString.prototype.queryString = function (key){
var page = this.PageQuery(window.location.search);
return unescape(this.getValue(key));
}
_QueryString.prototype.CommentKey = function(){
var page = this.PageQuery(window.location.search);
if (window.location.search.length == 0)
return page;
var page = this.PageQuery(window.location.search);
var commenttKey = this.getValue(this.PERMALINK_QUERYSTRING_PARAM);
return unescape(commenttKey.substring(commenttKey.indexOf(":")+1));
}
_QueryString.prototype.CommentPage = function(){
var page = this.PageQuery(window.location.search);
if (window.location.search.length == 0)
return page;
var page = this.PageQuery(window.location.search);
var commenttPage = this.getValue(this.PERMALINK_QUERYSTRING_PARAM);
return unescape(commenttPage.substring(0,commenttPage.indexOf(":")));
}
/***
***
***/
function _StaffRecommendation() {
this.recommendationBody = "";
this.commentKey = "";
this.commentDate = "";
this.commentUserDisplayName = "";
this.commentUserKey = "";
this.commentPermaLink = "";
this.articleKey = "";
this.articleURL = "";
this.articleTitle = "";
this.queueKey = "1";
/**
*
*/
this.submit = function() {
// create and send request
var requestBatch = new RequestBatch();
var reviewAction = new ReviewAction(new ArticleKey(this.getQueueName()), this.commentPermaLink, this.articleTitle, this.articleTitle, "5", this.recommendationBody, "----EDITOR RECOMMENDATION (ignore data below) ----", this.getEncapsulatedDataBlob());
// console.log("Here is our ReviewAction object...");
// console.dir(reviewAction);
requestBatch.AddToRequest(reviewAction);
requestBatch.BeginRequest(daapiServerUrl, __StaffRecommendationCallBack);
}
/**
*
*/
this.getQueueName = function() {
return "SL_StaffRecommendation_Queue_" + this.queueKey;
}
/**
*
*/
this.getDataBlob = function() {
// we need to create a serializable version of ourselves.
var StaffRecommendation = {};
StaffRecommendation.commentKey = this.commentKey;
StaffRecommendation.commentDate = this.commentDate;
StaffRecommendation.commentUserDisplayName = this.commentUserDisplayName;
StaffRecommendation.commentUserKey = this.commentUserKey;
StaffRecommendation.commentPermaLink = this.commentPermaLink;
StaffRecommendation.articleKey = this.articleKey;
StaffRecommendation.articleURL = this.articleURL;
StaffRecommendation.articleTitle = this.articleTitle;
// console.log("Here is our StaffRecommendation object...");
// console.dir(StaffRecommendation);
var strJSON = JSON.stringify(StaffRecommendation);
console.log(strJSON);
return(strJSON);
}
this.getEncapsulatedDataBlob = function() {
return (this.getDataBlob());
// can't wrap in comments as it all get stripped.
// return "JSON Data ";
}
}
/**
*
*/
function __StaffRecommendationCallBack(responseBatch) {
// console.dir(responseBatch);
//alert(responseBatch.Messages[0].Message);
if (responseBatch.Messages[0].Message == 'ok') {
alert('staff recommendation successfully submitted');
}
}
/*
* Comments:
* GetAllComments
* Given an ArticleID build an array of all the comments
*/
function _Reviews() {
this.articlekey;
this.article = null; // the article that we are working with
this.batch = 1;
this.count = 0;
this.sortOrder = "TimeStampDescending";
this.serverUrl = "http://community.washingtonpost.com/ver1.0/Direct/Process";
this.CallBack = null; // callback function to call after comments are returned
this.CBReviewDisplay = null; // user callback function to draw the comments with the array of comments
this.theReviews = null ;// = new Array();
}
_Reviews.prototype.SetSortOrder = function(sort) {
this.sortOrder = sort;
}
_Reviews.prototype.SetReviewDisplay = function(func) {
this.CBReviewDisplay = func;
}
_Reviews.prototype.SetCallBack = function(ourCB) {
this.CallBack = ourCB;
}
_Reviews.prototype.GetReviews = function(key) {
this.articlekey = key;
// article is the unique identifier
var articleKey = new ArticleKey(key);
// allocate a new request batch to send to the pluck server
var requestBatch = new RequestBatch();
// We are interested in comments, lets get the comment page
var reviewPage = new ReviewPage(articleKey,10,this.batch,this.sortOrder);
requestBatch.AddToRequest(reviewPage);
requestBatch.BeginRequest(this.serverUrl, this.CallBack);
// save the articlekey for subsequent calls.
this.articlekey = key;
}
_Reviews.prototype.ParseReviewsPage = function(revPage) {
// parse the comment page and build the comment list
tools.debug("ParseCommentPage");
tools.debug("revPage.Reviews.length : " + revPage.Reviews.length);
// for (var c=0;c < revPage.Reviews.length; c++) {
// this check does the normal display stuff.
// showing the comments if they are valid (notBlocked,notAbusive,and equal to the number we want to see)
this.theReviews = revPage;
// }
}
_Reviews.prototype.PluckReturn = function(responseBatch) {
console.log("PluckReturn");
console.dir(responseBatch);
for (var i = 0; i < responseBatch.Responses.length; i++) {
var response = responseBatch.Responses[i];
if (response.ReviewPage != null) {
// we have a comment page/header
if (this.ParseReviewsPage != null){
this.ParseReviewsPage(response.ReviewPage);
}
}
}
this.CBReviewDisplay(this.theReviews);
}
_Reviews.prototype.parseArticle = function(articleObj) {
this.article = articleObj;
}