if(typeof(console) === 'undefined') {
var console = {log: function () { return; }};
}
var PluckUtils = {
FB_TEMPLATE_ID: '115444719406',
/**
* Grab the portion of the URL after 'content/' and before '?' or '#' to use
as the article key for Pluck.
*/
generateArticleKey: function() {
var re = new RegExp('content/([^?#]*)');
var match = re.exec(document.location);
return match ? match[1] : 'ERROR';
},
/**
* Constructor for an object that fetches and stores the information for the
currently logged in user if user info hasn't been bassed to it. The 'userLoaded'
event is triggered on the document when the request has finished.
*/
User: function (userData) {
var self = this;
var loaded = false;
var loadCallbacks = [];
this.onLoad = function (func) {
if(loaded) {
func();
} else {
loadCallbacks.push(func);
}
};
this.fireLoadEvent = function () {
loaded = true;
$.each(loadCallbacks, function (index, func) { func(); });
};
this.isLoggedIn = function () {
return !(self.UserTier === 'Anonymous');
};
this.setCanComment = function () {
if(!self.isLoggedIn()) {
$('#comment-form').find(':input').attr('disabled', true);
if(self.hasAccount()) {
$('#comment-username-required').show();
} else {
$('#comment-login-required').show();
}
}
};
this.hasAccount = function () {
return /CN_UR_EMAIL=/.test(document.cookie);
};
function init() {
for(prop in userData) {
if(userData.hasOwnProperty(prop)) {
self[prop] = userData[prop];
}
}
self.fireLoadEvent();
}
function storeRequest(responseBatch) {
userData = responseBatch.Responses[0].User;
init();
}
if(userData) {
init();
} else {
var userRequest = new RequestBatch();
userRequest.AddToRequest(new UserKey());
userRequest.BeginRequest(serverUrl, storeRequest);
}
},
/**
* Initializes the comment widget and loads the first page. If currentUser isn't
* given, the user data will be loaded along with the first page.
*/
CommentsWidget: function (perPage, currentUser) {
var self = this;
this.perPage = perPage;
this.user = currentUser;
this.currentPage = 0;
this.totalComments = 0;
var kinds = {'CommentPage': 'page', 'User': 'user'};
var loaded = {user: self.user, page: false};
var loadCallbacks = {user: [], page: []};
this.onLoad = function (func, kind) {
var kind = kind || 'page';
loadCallbacks[kind].push(func);
if(loaded[kind]) {
func(self[kind]);
}
};
this.fireLoadEvent = function (kind, data) {
if(kind === 'page') {
$('#comments-spinner').hide();
}
if(kind === 'user') {
data = new PluckUtils.User(data);
}
self[kind] = data;
$.each(loadCallbacks[kind], function (index, func) { func(data); });
loadCallbacks[kind] = [];
loaded[kind] = true;
};
this.addUserRequest = function (requestBatch) {
if(!self.user) {
loaded.user = false;
self.onLoad(function (user) { user.setCanComment(); }, 'user');
requestBatch.AddToRequest(new UserKey());
}
};
this.fetchPermalinkedComment = function (href) {
href = href ? href : document.URL;
var match = /#comment-(.+)$/.exec(href);
if(!match) {
return false;
}
self.perPage = 1;
$('#comments').empty();
$("#comments-spinner").show();
var requestBatch = new RequestBatch();
var articleKey = new ArticleKey(PluckUtils.generateArticleKey());
var commentKey = new CommentKey(match[1]);
requestBatch.AddToRequest(new CommentPage(articleKey, self.perPage, 1,
"TimeStampDescending", commentKey));
self.addUserRequest(requestBatch);
loaded.page = false;
self.onLoad(self.renderPermalinkedComment);
requestBatch.BeginRequest(serverUrl, self.processResponse);
return true;
};
this.fetchNextPage = function () {
if(self.perPage == 1) {
// Hide the permalinked comment, reset perPage, and show the first page.
$('#comments').empty();
self.perPage = perPage;
self.currentPage = 0;
}
$("#comments-spinner").show();
self.currentPage++;
var requestBatch = new RequestBatch();
var articleKey = new ArticleKey(PluckUtils.generateArticleKey());
requestBatch.AddToRequest(new CommentPage(articleKey, self.perPage,
self.currentPage, "TimeStampDescending"));
self.addUserRequest(requestBatch);
loaded.page = false;
self.onLoad(self.renderPage);
requestBatch.BeginRequest(serverUrl, self.processResponse);
};
this.processResponse = function (responseBatch) {
var data = {};
$.each(responseBatch.Responses, function (index, response) {
$.each(response, function (name, item) {
data[kinds[name]] = item;
});
});
// Fire user loaded event first because the comments require user data.
$.each(['user', 'page'], function (i, kind) {
if(data[kind]) {
self.fireLoadEvent(kind, data[kind]);
}
});
};
/**
* Build the HTML for a comment, attach the appropriate events, and return the
element in a jQuery object.
*/
this.renderComment = function (comment, timePreposition) {
if(typeof(timePreposition) === 'undefined') {
timePreposition = 'on';
}
var author = comment.Author;
var viewerWroteComment = (self.user.isLoggedIn() && (self.user.UserKey.Key === author.UserKey.Key));
if((author.IsBlocked === 'True') && !viewerWroteComment) {
return null;
}
var $comment = $('#comment-prototype').clone();
$comment.attr('id', comment.commentKey ? 'comment-' + comment.CommentKey.Key
: '');
$comment.show();
$comment.find('.commenter img').attr('src', author.AvatarPhotoUrl);
var nameParams = ('?newspaperUserId=' + author.UserKey.Key +
'&plckUserId=' + author.UserKey.Key);
var $nameLink = $comment.find('.comment-byline a');
$nameLink.attr('href', $nameLink.attr('href') + nameParams);
$nameLink.text(author.DisplayName);
$comment.find('.comment-body').html(comment.CommentBody);
$comment.find('.comment-time').text(timePreposition + ' ' +
comment.PostedAtTime);
if(comment.CommentKey) {
$comment.find('.comment-permalink')
.attr('href', '#comment-' + comment.CommentKey.Key)
.click(function (evnt) {
self.fetchPermalinkedComment($(evnt.target).attr('href'));
});
} else {
$comment.find('.comment-permalink').hide();
}
if(viewerWroteComment) {
$comment.find('.comment-abuse').hide();
} else {
var doReportAbuse = function () {
var $abuseForm = $comment.find('form.abuse-form');
var reason = $abuseForm.find('[name=reason]').val();
var name = $abuseForm.find('[name=name]').val();
var email = $abuseForm.find('[name=email]').val();
if(email && name && reason) {
var request = new RequestBatch();
var extraInfo = name + ' - ' + email;
request.AddToRequest(new ReportAbuseAction(
{'CommentKey': comment.CommentKey}, reason, extraInfo));
request.BeginRequest(serverUrl, function(responseBatch) {
if(responseBatch.Messages[0].Message == 'ok') {
$abuseForm.replaceWith('
' +
'Abuse Report Submitted.
');
}
});
} else {
$abuseForm.find('.abuse-error').text('All fields are required. Please fill out missing fields and resubmit.');
}
};
$comment.find('.abuse-submit').click(doReportAbuse);
$comment.find('.abuse-link').click(function () {
$comment.find('.comment-abuse').toggleClass('expanded');
});
}
return $comment;
};
this.renderPermalinkedComment = function (page) {
// Permalinked comments should always be shown, so ignore blocks.
page.Comments[0].Author.isBlocked = 'False';
self.renderPage(page);
window.scrollTo(0, $('#comments-wrapper').offset().top);
};
this.renderPage = function (page) {
$('#comments-spinner').hide();
self.comments = page.Comments;
self.totalComments = page.NumberOfComments;
var $commentsPage = $('');
$.each(self.comments, function(index, comment) {
if(typeof(parseInt(index)) !== 'number') {
// The Comments object is an array with other properties. Ignore
// those.
return;
}
var $comment = self.renderComment(comment);
if($comment) {
$commentsPage.append($comment);
}
});
$('#comments').append($commentsPage);
self.updateShowMore();
};
this.updateShowMore = function() {
if(self.perPage == 1) {
// We're showing a permalink.
$('#show-more-comments').text('Show all comments').show();
return;
}
var start = (self.currentPage * self.perPage) + 1;
if(start > self.totalComments) {
$('#show-more-comments').hide();
return;
}
var end = start + self.perPage - 1;
end = end > self.totalComments ? self.totalComments : end;
$('#show-more-comments')
.text('Show ' + start + ' - ' + end + ' of ' + self.totalComments +
' comments')
.show();
};
this.postComment = function() {
if(!self.user.isLoggedIn()) return;
var commentBody = $("#comment-form [name=body]").val();
if(commentBody == '') {
$('#comment-error').text("You can't submit a blank comment.");
return;
}
var articleKey = new ArticleKey(PluckUtils.generateArticleKey());
var commentAction = new CommentAction(articleKey, document.location.href,
document.title, commentBody);
var requestBatch = new RequestBatch();
requestBatch.AddToRequest(commentAction);
requestBatch.BeginRequest(serverUrl, function (responseBatch) {
self.commentSubmitted(responseBatch, commentBody);
});
// Popup blocker workaround
if($('#twitter-post-checkbox').attr('checked')) {
self.twitterWindow = window.open('http://alt.coxnewsweb.com/statesman/twitter-popup.html', 'twitterLoginWindow', 'toolbar=0,status=0,width=800,height=600');
window.focus();
}
};
this.commentSubmitted = function(responseBatch, commentBody) {
var message = responseBatch.Messages[0].Message;
if(message === 'ok') {
var comment = {
'Author': self.user,
'CommentBody': commentBody,
'PostedAtTime': 'now'
};
var $comment = self.renderComment(comment, 'just');
$comment.hide();
$comment.prependTo('#comments');
$('#comment-form [name=body]').val('');
$('#comment-error').html('');
$comment.fadeIn('normal', function () {
self.shareComment(commentBody, $comment, {
facebook: $('#facebook-post-checkbox').attr('checked'),
twitter: $('#twitter-post-checkbox').attr('checked')
});
});
} else {
$('#comment-error').text(message);
}
};
this.shareComment = function (commentBody, $comment, shareOn) {
if(!(shareOn.facebook || shareOn.twitter)) {
return;
}
// Get the posted comment so we have its CommentKey.
var requestBatch = new RequestBatch();
var articleKey = new ArticleKey(PluckUtils.generateArticleKey());
requestBatch.AddToRequest(new CommentPage(articleKey, 15,
1, "TimeStampDescending"));
function share(comment) {
if(shareOn.facebook) {
self.sendCommentToFacebook(commentBody, $comment, comment);
}
if(shareOn.twitter) {
self.sendCommentToTwitter(commentBody, $comment, comment);
}
}
loaded.page = false;
self.onLoad(function (page) {
var shared = false;
$.each(page.Comments, function (index, comment) {
if(comment.Author.UserKey.Key === self.user.UserKey.Key) {
// The first comment by the same author is probably the comment
// that was just written.
share(comment);
shared = true;
return false;
}
});
if(!shared) {
share(null);
}
});
requestBatch.BeginRequest(serverUrl, self.processResponse);
};
function getShareURL(ref, comment) {
var url = new String(document.URL).split('#')[0];
var domainExp = new RegExp('^(https?://)(.*?)(.statesman.com/.*)$');
var match = domainExp.exec(url);
if(match && (match[2] == 'template' || match[2] == 'test')) {
url = match[1] + 'www' + match[3];
}
url = url.replace(/UrAuth=.*(&|$)/, '');
url = url.replace(/\?$/, '');
url += url.indexOf('?') == -1 ? '?' : '&';
if(ref) {
url += 'ext_ref=comment-' + ref;
}
return comment ? url + '#comment-' + comment.CommentKey.Key : url;
}
this.sendCommentToFacebook = function (commentBody, $comment, comment) {
var title = $('#story_content h1:first').text();
var excerpt = $('#story_content span.byline').closest('p').next('p').text();
slFB.init(function () {
// This is supposed to be set via a Pluck setting, but doing it this way
// makes it easier for us to change things. If something breaks, this
// might be why.
slFB.Templates.ArticleComment = PluckUtils.FB_TEMPLATE_ID;
$comment.find('.facebook-loader').show();
var afterSend = function () {
$comment.find('.facebook-loader .spinner').replaceWith('');
};
var url = getShareURL('facebook', comment);
slFB.submitArticleComment(title, url, excerpt, commentBody, [],
afterSend);
});
};
this.sendCommentToTwitter = function (commentBody, $comment, comment) {
$comment.find('.twitter-loader').show();
var afterSend = function () {
$comment.find('.twitter-loader .spinner').replaceWith('');
};
var actuallySend = function () {
slTwitter.sendMessage(commentBody, getShareURL('twitter', comment),
'{0} @statesman {1}', afterSend);
};
slTwitter.checkConnected(function (connected) {
var $select = $('#twitter-login-method');
var login = true;
if($select.size()) {
login = $select.find(':selected').val() === 're-login';
}
if(login || !connected) {
if(self.twitterWindow) {
window.blur();
self.twitterWindow.focus();
}
slTwitter.login(function (username) {
if(username) {
actuallySend();
}
});
} else {
actuallySend();
// No twitter page will ever be loaded, so we need to close the
// window we opened manually.
if(self.twitterWindow) {
self.twitterWindow.close();
}
}
});
};
this.twitterInit = function () {
slTwitter.checkConnected(function (connected, username) {
if(username) {
var $dropdown = $('')
.attr('id', 'twitter-login-method')
.append($('').attr('value', 'use-login')
.attr('selected', true)
.text('@' + username))
.append($('').attr('value', 're-login')
.text('someone else'));
$('#social-post-options').addClass('with-usernames');
$('label[for=twitter-post-checkbox]')
.append(' as ')
.after($dropdown);
// Center options together.
var leftOffset = $('#twitter-post-checkbox').offset().left -
$('#facebook-post-checkbox').offset().left;
$('#facebook-post-checkbox').closest('span').children().css({
left: leftOffset,
position: 'relative'
});
}
});
}
// Attach events
$('#show-more-comments').click(self.fetchNextPage);
$('a.sendback-link').each(function () {
var oldHref = $(this).attr('href');
$(this).attr('href', oldHref + encodeURIComponent(window.parent.window.location.href));
});
if(!self.fetchPermalinkedComment()) {
self.fetchNextPage();
}
self.twitterInit();
}
};