';
//default comments
var defaultcomments = [
{ Name: "Answers just to say Thanks!", Description: 'Please don\'t add "thanks" as answers. Invest some time in the site and you will gain sufficient privileges to upvote answers you like, which is the $SITENAME$ way of saying thank you.' },
{ Name: "Nothing but a URL (and isn't spam)", Description: 'Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference.' },
{ Name: "Requests to OP for further information", Description: 'This is really a comment, not an answer. With a bit more rep, you will be able to post comments. For the moment I\'ve added the comment for you, and I\'m flagging this post for deletion.' },
{ Name: "OP using an answer for further information", Description: 'Please use the Post answer button only for actual answers. You should modify your original question to add additional information.' },
{ Name: "OP adding a new question as an answer", Description: 'If you have another question, please ask it by clicking the Ask Question button.' },
{ Name: "Another user adding a 'Me too!'", Description: 'If you have a NEW question, please ask it by clicking the Ask Question button. If you have sufficient reputation, you may upvote the question. Alternatively, "star" it as a favorite and you will be notified of any new answers.' },
];
var weekday_name = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
var minute = 60, hour = 3600, day = 86400, sixdays = 518400, week = 604800, month = 2592000, year = 31536000;
//Wrap local storage access so that we avoid collisions with other scripts
function GetStorage(key) { return localStorage[prefix + key]; }
function SetStorage(key, val) { localStorage[prefix + key] = val; }
function RemoveStorage(key) { localStorage.removeItem(prefix + key); }
function ClearStorage(startsWith) {
for(var i = localStorage.length - 1; i >= 0; i--) {
var key = localStorage.key(i);
if(key.indexOf(prefix + startsWith) == 0) localStorage.removeItem(key);
}
}
//Calculate and format datespan for "Member since/for"
function datespan(date) {
var now = new Date() / 1000;
var then = new Date(date * 1000);
var today = new Date().setHours(0, 0, 0) / 1000;
var nowseconds = now - today;
var elapsedSeconds = now - date;
var strout = "";
if(elapsedSeconds < nowseconds) strout = "since today";
else if(elapsedSeconds < day + nowseconds) strout = "since yesterday";
else if(elapsedSeconds < sixdays) strout = "since " + weekday_name[then.getDay()];
else if(elapsedSeconds > year) {
strout = "for " + Math.round((elapsedSeconds) / year) + " years";
if(((elapsedSeconds) % year) > month) strout += ", " + Math.round(((elapsedSeconds) % year) / month) + " months";
}
else if(elapsedSeconds > month) {
strout = "for " + Math.round((elapsedSeconds) / month) + " months";
if(((elapsedSeconds) % month) > week) strout += ", " + Math.round(((elapsedSeconds) % month) / week) + " weeks";
}
else {
strout = "for " + Math.round((elapsedSeconds) / week) + " weeks";
}
return strout;
}
//Calculate and format datespan for "Last seen"
function lastseen(date) {
var now = new Date() / 1000;
var today = new Date().setHours(0, 0, 0) / 1000;
var nowseconds = now - today;
var elapsedSeconds = now - date;
if(elapsedSeconds < minute) return (Math.round(elapsedSeconds) + " seconds ago");
if(elapsedSeconds < hour) return (Math.round((elapsedSeconds) / minute) + " minutes ago");
if(elapsedSeconds < nowseconds) return (Math.round((elapsedSeconds) / hour) + " hours ago");
if(elapsedSeconds < day + nowseconds) return ("yesterday");
var then = new Date(date * 1000);
if(elapsedSeconds < sixdays) return ("on " + weekday_name[then.getDay()]);
return then.toDateString();
}
//Format reputation string
function repNumber(r) {
if(r < 1E4) return r;
else if(r < 1E5) {
var d = Math.floor(Math.round(r / 100) / 10);
r = Math.round((r - d * 1E3) / 100);
return d + (r > 0 ? "." + r : "") + "k"
}
else return Math.round(r / 1E3) + "k"
}
//Get userId for post
function getUserId(el) {
// a bit complicated, but we have to avoid edits (:last), not trip on CW questions (:not([id])), and not bubble
// out of post scope for deleted users (first()).
var userlink = el.parents('div').find('.post-signature:last').first().find('.user-details > a:not([id])');
if(userlink.length) return userlink.attr('href').split('/')[2];
return "[NULL]";
}
function isNewUser(date) {
return (new Date() / 1000) - date < week
}
function getOP() {
var userlink = $('#question').find('.owner').find('.user-details > a:not([id])');
if(userlink.length) return userlink.text();
var user = $('#question').find('.owner').find('.user-details'); //for deleted users
if(user.length) return user.text();
return "[NULL]";
}
//Ajax to Stack Exchange api to get basic user info, and paste into userinfo element
//http://soapi.info/code/js/stable/soapi-explore-beta.htm
function getUserInfo(userid, container) {
var userinfo = container.find('#userinfo');
if(isNaN(userid)) {
userinfo.fadeOutAndRemove();
return;
}
$.ajax({
type: "GET",
url: 'http://api.stackexchange.com/2.2/users/' + userid + '?site=' + siteurl + '&jsonp=?',
dataType: "jsonp",
timeout: 2000,
success: function (data) {
if(data['items'].length > 0) {
var user = data['items'][0];
if(isNewUser(user['creation_date'])) {
showGreeting = true;
container.find('.action-desc').prepend(greeting);
}
username = user['display_name'];
var usertype = user['user_type'].charAt(0).toUpperCase() + user['user_type'].slice(1);
var html = usertype + ' user ' + username + ', \
member ' + datespan(user['creation_date']) + ', \
last seen ' + lastseen(user['last_access_date']) + ', \
reputation ' + repNumber(user['reputation']) + '';
userinfo.html(html.replace(/ +/g, ' '));
}
else userinfo.fadeOutAndRemove();
},
error: function () { userinfo.fadeOutAndRemove(); }
});
}
//Show textarea in front of popup to import/export all comments (for other sites or for posting somewhere)
function ImportExport(popup) {
var tohide = popup.find('#main');
var div = $('
');
//Painful, but shortest way I've found to position div over the tohide element
div.css({ position: 'absolute', left: tohide.position().left, top: tohide.position().top,
width: tohide.css('width'), height: tohide.css('height'), background: 'white'
});
var txt = '';
for(var i = 0; i < GetStorage("commentcount"); i++) {
var name = GetStorage('name-' + i);
var desc = GetStorage('desc-' + i);
txt += '###' + name + '\n' + htmlToMarkDown(desc) + '\n\n'; //the leading ### makes prettier if pasting to markdown, and differentiates names from descriptions
}
div.find('textarea').width('100%').height('95%').val(txt);
div.find('.jsonp').click(function () {
var txt = 'callback(\n[\n';
for(var i = 0; i < GetStorage("commentcount"); i++) {
txt += '{ "name": "' + GetStorage('name-' + i) + '", "description": "' + GetStorage('desc-' + i).replace(/"/g, '\\"') + '"},\n\n';
}
div.find('textarea').val(txt + ']\n)');
div.find('a:lt(2)').remove(); div.find('.lsep:lt(2)').remove();
});
div.find('.cancel').click(function () { div.fadeOutAndRemove(); });
div.find('.save').click(function () { DoImport(div.find('textarea').val()); WriteComments(popup); div.fadeOutAndRemove(); });
popup.append(div);
}
//Import complete text into comments
function DoImport(text) {
//clear out any existing stuff
ClearStorage("name-"); ClearStorage("desc-");
var arr = text.split('\n');
var nameIndex = 0, descIndex = 0;
for(var i = 0; i < arr.length; i++) {
var line = $.trim(arr[i]);
if(line.indexOf('#') == 0) {
var name = line.replace(/^#+/g, '');
SetStorage('name-' + nameIndex, name);
nameIndex++;
}
else if(line.length > 0) {
var desc = markDownToHtml(line);
SetStorage('desc-' + descIndex, Tag(desc));
descIndex++;
}
}
//This is de-normalised, but I don't care.
SetStorage("commentcount", Math.min(nameIndex, descIndex));
}
function htmlToMarkDown(html) {
markdown = html.replace(/(.+?)<\/a>/g, '[$2]($1)').replace(/&/g, '&');
return markdown.replace(/(.+?)<\/em>/g, '*$1*').replace(/(.+?)<\/strong>/g, '**$1**');
}
function markDownToHtml(markdown) {
html = markdown.replace(/\[([^\]]+)\]\((.+?)\)/g, '$1');
return html.replace(/\*\*(.+?)\*\*/g, '$1').replace(/\*([^`]+?)\*/g, '$1');
}
function UnTag(text) {
return text.replace(/\$SITENAME\$/g, sitename).replace(/\$SITEURL\$/g, siteurl)
}
function Tag(html) {
//put tags back in
var regname = new RegExp(sitename, "g"), regurl = new RegExp('http://' + siteurl, "g");
return html.replace(regname, '$SITENAME$').replace(regurl, 'http://$SITEURL$');
}
//Replace contents of element with a textarea (containing markdown of contents), and save/cancel buttons
function ToEditable(el) {
var backup = el.html();
var html = Tag(el.html().replace(greeting, '')); //remove greeting before editing..
if(html.indexOf('