", s, ""].join('');
return sret;
}
function CommentAuthorHTML(ourCIndex,authindex,bIsRealName)
{
var sclass = ClassnameFrAuthor(authindex);
var sAuthname = Authname(authindex)
var sSpanUs = AsSpanOfClassAndTitle(sclass,'',sAuthname);
var sSpanForRealName = (bIsRealName)? AsSpanOfClassAndTitle('arealname','(real name)','*'): '';
var sSpanForLabel = AsSpanOfClassAndTitle('labeling','',LabelFrAuthor(authindex,false));
var sUs =
[
"",
sSpanForLabel
].join('');
return sUs;
}
// ---------------------
function CreateFillAttachDoemallNode(irechots,iauthhots)
{
var doemallNode = CreateNodeOfClass('div', 'TBVDoemallBtns');
var shotsCSV = irechots.join(',');
var sDaHotRecs = (irechots.length==0)? '' :
NewButtonStr('TBVrechotsonly',
// 'Click to shrink all except these (' + shotsCSV + ')',
'Recs only',
'expandtheseonly([' + shotsCSV + ']);'
);
shotsCSV = iauthhots.join(',');
var sDaHotAuths = (iauthhots.length==0)? '' :
NewButtonStr('TBViauthhotsonly',
'Experts only',
// 'Click to shrink all except these (' + shotsCSV + ')',
'expandtheseonly([' + shotsCSV + ']);'
);
doemallNode.innerHTML = [ "Resize comments:
",
NewButtonStr('TBVbtnupcbodyall','Enlarge All','cbresizeall(1);' ),
NewButtonStr('TBVbtnupcbodyall','ReInit All','cbrestoresizeall();' ),
NewButtonStr('TBVbtndncbodyall','Shrink All','cbresizeall(0);' ),
sDaHotRecs,
sDaHotAuths
].join(' ');
var parNode = document.getElementById('comments');
parNode.appendChild(doemallNode);
parNode.appendChild(CreateNodeOfClass('div', 'TBVclearfloats'));
}
function LinkToAnchorStr(slabel, sid)
{
if (slabel.length && sid.length)
return "" + slabel + "";
else return '';
}
function CreatePagenavNode()
{
var jumpnode = CreateNodeOfClass('div', 'TBVToAnchors');
jumpnode.innerHTML = [
"Jump to...",
LinkToAnchorStr('pagetop', 'blog_content'),
LinkToAnchorStr('commentstop', 'blog_comments'),
LinkToAnchorStr('commentform', 'respond')
].join(' ');
jumpnode.setAttribute('style','float:right;');
return jumpnode;
}
function CreateAndFillDEControlsNode(ourCIndex,oktoshowrecs,authnamelc)
{
var dcnode = CreateNodeOfClassAndId('div', 'TBVCommentBtns',ourCIndex);
var tmpnode = CreateNodeOfClass('div', '');
tmpnode.setAttribute('style','float:left;');
var stitle = 'Compose a reply to ' + ReCapped(authnamelc);
var sliid = LiIdStrFrIndex(ourCIndex);
var sreplyaction = "Reply2Comment( %d,'" + sliid + "','" + stitle + "');";
// GM_log(sreplyaction);
tmpnode.innerHTML = [
NewButtonStr('TBVbtnreplyto%d','Reply',sreplyaction),
].join('').replace(/%d/mg,ourCIndex);;
dcnode.appendChild(tmpnode);
var aiwnode = CreateNodeOfClass('div', 'TBVcbodyresizebtns'); // alice in wonderland toggle
aiwnode.innerHTML = [
NewButtonStr('TBVbtnupcbody%d','Enlarge','cbresize(%d,1);'),
NewButtonStr('TBVbtndncbody%d','Shrink','cbresize(%d,0);')
].join('').replace(/%d/mg,ourCIndex);
dcnode.appendChild(aiwnode);
if (oktoshowrecs) {
var rnode = CreateNodeOfClass('div', 'TBVdorecbtns');
rnode.innerHTML = ([
NewButtonStr('TBVbtnunrec%d','Unrec','increcstatus(%d,-1);'),
NewButtonStr('TBVbtnrec%d','REC','increcstatus(%d,1);')
].join("\n")).replace(/%d/mg,ourCIndex);
dcnode.appendChild(rnode);
}
dcnode.appendChild(CreatePagenavNode());
dcnode.appendChild(CreateNodeOfClass('div', 'TBVclearfloats'));
return dcnode;
}
function CreateAndFillThreadingNode(ourCIndex,bRealName)
{
var ourcom = comTbl[ourCIndex];
if (!ourcom)
return null;
var tnode = CreateNodeOfClass('div', 'TBVthreading');
var sBegatIcon = AsSpanOfClassAndTitle('TBVbegaticon', '... called forth a reply by...',"->");
// rming this, since it breaks even when it shouldn't.
var sNewlineSpan = ''; AsSpanOfClassAndId('','TBVbreakwpast'+ourCIndex, "
");
var sAncestors = (ourcom.upstrs.length==0)? '' :
AsSpanOfClassAndTitle('TBVreplyingto','(reply to previous comments)',
AsNamesSpan(LinkstrsForCArr(ourcom.upstrs).join(', ')) + sBegatIcon);
if (sAncestors!='') {
sAncestors += sNewlineSpan; // rm if shrinking
}
var sDescendants = (ourcom.dnstrs.length==0)? '' :
AsSpanOfClassAndTitle('TBVrepliedtoby','replies to this comment:',
sBegatIcon + AsNamesSpan(LinkstrsForCArr(ourcom.dnstrs).join(', ')));
var sUs = CommentAuthorHTML(ourCIndex,ourcom.authindex,bRealName);
tnode.innerHTML = [ ' ', sAncestors, sUs, sDescendants].join(" ");
return tnode;
}
// ---------------------
function iconCountStr(n)
{
var s='******************************************************************';
return (n>40)? n : s.slice(0,n);
}
function AsRecSpan(sclass,siconclass,stitle,shtmls)
{
var nrecs = shtmls.length;
var ret = (nrecs==0)? '' :
[
"\n",
AsSpanOfClassAndTitle(siconclass, '', iconCountStr(nrecs)),
' ',
stitle,
' ',
AsNamesSpan(shtmls.join(', ')),
"
\n" ].join('');
// GM_log(ret);
return ret;
}
// ---------
function CreateAndFillRatersNode(ourCIndex)
{
var ourcom = comTbl[ourCIndex];
if (!ourcom || (!ourcom.reccers.length && !ourcom.unreccers.length))
return null;
var rnode = CreateNodeOfClass('div', 'TBVraters');
rnode.setAttribute('id', 'TBVrating'+ourCIndex);
rnode.innerHTML =
AsRecSpan('recs','TBVrecicon','Recommended by',
LinkstrsForCArr(ourcom.reccers))
+ AsRecSpan('unrecs','TBVunrecicon','thumbs down by',
LinkstrsForCArr(ourcom.unreccers));
return rnode;
}
// -----------------------------------------------------
function CreateAndFillMetaNode(sid, hmeta)
{
var mNode = CreateNodeOfClass("span", "TBVmeta");
mNode.setAttribute('style', "display:none");
mNode.setAttribute('id', sid);
mNode.innerHTML = HashToStr(hmeta);
return mNode;
}
// --------------
function CreateAndFillNodeOfClassFrHash(snodetype, sclass,slabel, ahash)
{
return CreateNodeOfClassAndFillWithText(snodetype, sclass,StrFrHash(slabel, ahash));
}
// --------------
function CreateAndFillTBVSettingsNode(sid)
{
var sAddenda = (!gbItsDED)? '\n(fyi, the filter/label/shrink settings shouldnt be relevant on this blog.)' : [
"\nI said 'most'; alas as of v3.0, the only way you can change the ",
"'precategorized authors' lists is to hand-edit them in the script. ",
"\n(to hand edit: Tools - Greasemonkey - ManageUserScripts, then",
"select '" + gsScriptname + "' and hit Edit;",
"the lists are up near the top. Once you've saved your edits (and beware of quotation marks!) the script will run with your changes, until you uninstall it and reinstall the same or another version. ))"
].join(' ');
var smostof = (!gbItsDED)? '' : "_most_ of the";
var sInstructionsToModify = [
"You can **edit**",
smostof,
gsScriptname,
" settings from Firefox's Tools - Greasemonkey - UserScriptCommands. ",
"\n (then refresh the page! otherwise it probably runs with the old settings.) ",
sAddenda
].join(' ');
var retnode = CreateNodeOfClass('div', sid);
var sdatanode = "TBVSettingsData";
var showhidenode = CreateNodeOfClass('div', 'showhidebtns');
showhidenode.innerHTML = [
NewButtonStr('show' + sdatanode,
'Show my ' + gsScriptname + ' Settings',
"showIt('" + sdatanode + "',true);"),
NewButtonStr('hide' + sdatanode,
'Hide',
"showIt('" + sdatanode + "',false);" , true)
].join('');
showhidenode.setAttribute('style',"background:#CFC;"); // diff from tbv's default css
var datanode = CreateNodeOfClassAndId('div', sdatanode,'');
datanode.appendChild(document.createTextNode(sInstructionsToModify));
datanode.appendChild(CreateAndFillNodeOfClassFrHash('div','TBVSettings',
"Script settings",TBVSettings));
datanode.appendChild(document.createElement('p')); // spacing
// lists of known authors, by category
if (gbItsDED) {
datanode.appendChild(CreateAndFillNodeOfClassFrHash('div','TBVKnownAuths',
"Known (Categorized) commenters", authnamesByClassTbl));
}
datanode.style.display = 'none';
showhidenode.appendChild(datanode);
retnode.appendChild(showhidenode);
return retnode;
}
// --------------
function GoogleSearchURLFrName(sname)
{
return "http://www.google.com/search?hl=en&q=%22"
+ sname.replace(/\s+/g, "+")
+ "%22+site%3A"
+ gsBlogname
+ ".blogs.nytimes.com";
}
// --------------
function BlogGoogleLink4Name(sname,sinner)
{
return [
"",
sinner,
""
].join('');
}
// --------------
function CreateAndFillAuthorlistNode() // which goes above comments
{
var mNode = CreateNodeOfClassAndId("span", "TBVAuthList",'');
authlinksArr = [];
for (var iauth in authTbl) {
var carr = NumSortArr(authTbl[iauth].comments);
// if (iauth==28) GM_log(carr.join('-'));
if (carr.length) {
var sclass = ClassnameFrAuthor(iauth);
var snamelc =authTbl[iauth].namelc;
authlinksArr.push(
[
"",
snamelc, // not BlogGoogleLink4Name(snamelc),
"#" ,
MiniLinkstrsForCArr(carr).join(','), // 1 per comment by this auth
'(',
BlogGoogleLink4Name(snamelc,'G'),
')'
].join('')
);
}
}
mNode.innerHTML = (!authlinksArr.length)? '' : '
' + authlinksArr.sort().join(' ');
// GM_log(mNode.innerHTML);
return mNode;
}
// -----------------------------------------------------
// in development, alas. Can't get the button over to the right!
// ----------------
function HideEndIfLongComment(cNode,ourCIndex)
{
var sinner = cNode.innerHTML;
var ntotal = sinner.length;
if (ntotal < 2000) return;
if (gsBlogHostname.length && sinner.indexOf('[' + gsBlogHostname)>=0) {
// bloghost responded; dont truncate visible comment
return;
}
var nmaxvis=700;
var nkids = cNode.childNodes.length -1; // p cite
// var zelast = cNode.lastNode; // p-cite, most likely
var i=0;
var imore=nkids+1;
for (i=n=0; iInvestigators: NASA Officials ‘Mischaracterized’ and Limited Flow of Findings on Climate
// for #comments, this:
//
function MinOf(a,b)
{
return (a' + ncomments + ')';
archNode.appendChild(document.createElement('br'));
archNode.appendChild(plink);
}
}
function AsList(sarr)
{
return (!sarr.length)? '' : "";
}
function AddRecentPostsToSidebar(sOurURL,num)
{
var recentsNode = CreateNodeOfClassAndId('div','TBVrecent','');
var sidediv = document.getElementById('blog_sidebar');
sidediv.insertBefore(recentsNode, sidediv.firstChild);
FillRecentPostsNode(sOurURL,recentsNode); // here a miracle occurs
var sstyle = 'background:#CFC; opacity:.85;';
recentsNode.setAttribute('style',sstyle);
}
function WeAreTheFrontPage(sURL)
{
var stmp = sURL.replace(/.*blogs.nytimes.com\//,'').replace(/[\#\?].*/,''); // anything left?
return (trimmed(stmp).length==0);
}
// -------------------------------------------------------------------------------------
// Once the page has loaded, we can start here...
// --------------------------------------------------
window.addEventListener("load", function(e) {
var commentsdiv = document.getElementById('add_comments');
var sOurURL = window.location.href.toString();
var bRunOnThisPage = false;
if (!commentsdiv) {
if (WeAreTheFrontPage(sOurURL)) {
var bAssembleRecentPosts = sOurURL.match(/\?TBVrecent=(\d*)/);
if (bAssembleRecentPosts) {
var num = RegExp.$1;
if (num>0) {
GM_log("'" + sOurURL + "' is front page - add archives");
bRunOnThisPage = true;
AddSomePageNavLinksEtc(true);
AddRecentPostsToSidebar(sOurURL.replace(/\?.*/,''),num); // rm the 'options' crap from our url
}
}
}
if (!bRunOnThisPage) {
GM_log("'" + sOurURL + "' not a page for " + gsScriptname + " (it has no comments section and archives werent requested)");
}
return;
}
GM_log(gsScriptname + " is running, on " + sOurURL);
var ouranchorIdent = OurURLAnchorIdent(); // i.e. '#comment-66113' or ''
InitDataTbls(gbFilterMode);
// likely it's faster to modify it, if we don't have to update the display as we go along:
commentsdiv.style.display = 'none';
SetTBVStyles();
AddClientJS();
ModifyCommentForm();
AddSomePageNavLinksEtc(false);
var citeNodes = xpath("//cite");
var lastindex = 0;
// get #comments (some of which might be gaps?? how is this handled?
var sofarNode = document.getElementById('comments'); // 'n comments so far'
var numcommentsSoFar = parseInt(sofarNode.innerHTML.replace(/\s.*/,''));
// ------------------------------------
// First pass, init the Comment tbl with just indexes & authnames
// ------------------------------------
var ncomments = citeNodes.snapshotLength;
for (var iC = 0; iC < ncomments; ++iC) {
var citeNode = citeNodes.snapshotItem(iC); // cite (author)
var gpNode = citeNode.parentNode.parentNode; // div class=comment
var liNode = gpNode.parentNode; // id="comment-44976"
var sliid = liNode.getAttribute('id'); // visitor-usable links will use this id
var ourCIndex = CommentIndexFrCiteNode(citeNode); // start at 1.
var authnamelc = SafeAuthnameFrCiteNode(citeNode).toLowerCase();
if (!ourCIndex) {
GM_log("error- cindex is 0");
}
AddCommentToTbl(ourCIndex,sliid,authnamelc)
}
var iauthhots = []; // comments by hot authors
var irechots = []; // comments with hot recommends
// ------------------------------------
// Next pass, populate the comments tbl etc
// (in reverse order, so recs/ratings for the comment will already be known)
// ------------------------------------
for (var iC = ncomments-1; iC >=0; iC--) {
var citeNode = citeNodes.snapshotItem(iC); // cite (author)
var gpNode = citeNode.parentNode.parentNode; // div class=comment
var liNode = gpNode.parentNode; // id="comment-44976"
var indexNode = IndexNodeFrCiteNode(citeNode);
var ourCIndex = CommentIndexFrIndexNode(indexNode);
var sliid = liNode.getAttribute('id'); // true permalinks will use this id - 'ourCIndex' will change if an earlier comment gets deleted.
var iauth = AuthorFrComment(ourCIndex);
var authnamelc = AuthnameLC(iauth);
indexNode.setAttribute('id','index' + ourCIndex); // so we can link via cindex to the comment
if (AuthorIsHot(iauth)) {
iauthhots.push(ourCIndex);
}
if (RecsOfThisCommentAreHot(ourCIndex)) {
irechots.push(ourCIndex);
}
var isTrusted = AuthorIsTrusted(iauth);
var isDistrusted = isTrusted? false : AuthorIsDistrusted(iauth);
gpNode.setAttribute('id','TBVcbody'+ourCIndex); // for expand/contract
var ourTBVHash = []; // this comment's TBV-related info if any, from w/in the squaretags
var sTBV = TBVStuffFrText(gpNode.innerHTML);
if (ourCIndex==993) { GM_log("stbv=" + sTBV); } // debug crap
var ourTBVrecstr ='';
if (sTBV && sTBV.length>0) {
// this is very hackish since I don't know how to neatly 'enclose' it on the fly.
ourTBVrecstr = TBVIrecStrFrText(sTBV);
if (ourCIndex==993) { GM_log("ourTBVrecstr=" + ourTBVrecstr); }
var spanstr = AsSpanOfClassAndId('shrinkme', 'tbvinfo'+ ourCIndex,
sTBV.replace(/I recommend.*\./,''));
if (ourCIndex==993) { GM_log("spanstr=" + spanstr); }
ourTBVHash = HashFrStr(TBVHashStrFrText(sTBV));
// ReportHash('#' + ourCIndex + "'s TBVHash", ourTBVHash);
// ReportHash('#' + ourCIndex + "'s TBVHash", ourTBVHash);
var reccsv = ourTBVHash['r'];
var unreccsv = ourTBVHash['u'];
if (OKToRec(isTrusted)) {
DigestRecsAndUnrecs(ourCIndex,reccsv,unreccsv);
}
if (ourTBVrecstr.length) {
ourTBVrecstr = [
'',
Firstname(authnamelc),
' recommends ',
ourTBVrecstr,
''
].join('');
// if (ourCIndex==993) { GM_log("ourTBVrecstr=" + ourTBVrecstr); }
}
// gpNode.innerHTML = ourTBVrecstr + WithAllTBVStuffRemoved(gpNode.innerHTML) + spanstr;
if (ourCIndex==993) {
GM_log("gpNode.innerHTML=" + gpNode.innerHTML);
GM_log("notbvstuff=" + WithAllTBVStuffRemoved(gpNode.innerHTML));
}
gpNode.innerHTML = WithAllTBVStuffRemoved(gpNode.innerHTML) + spanstr;
}
var metahash={}; // stuff that clientjs will need access to
metahash['linkstr'] = LinkstrForCIndex(ourCIndex); // stash it where clientjs can easily find it
metahash['sliid'] = sliid; // "comment-44976"
metahash['auth'] = iauth;
metahash['authname'] = authnamelc;
var bodyvisible = 1;
if (gbShrinkDistrusted || OKToShowRecs()) {
if (isDistrusted || IsUnreccedByNTrustedUsers(ourCIndex,2)) {
gpNode.style.fontSize='2pt';
bodyvisible = 0;
}
}
metahash['origvis'] = bodyvisible; // to be accessed as TBVMetaVal('origvis')
var sinnerHTML = gpNode.innerHTML;
// fix "reply to comment" format outliers
if (authnamelc=='david b. benson') {
sinnerHTML =sinnerHTML.replace(/\((\d+)\) /mg,"\#$1 ");
}
sinnerHTML = sinnerHTML.replace(/#\s*/mg,'#');
// MarkBlogHostResponses
if (gsBlogHostname.length) {
var re = new RegExp('(\\[' + gsBlogHostname + '.*?\\])','mg')
sinnerHTML=sinnerHTML.replace(re, "$1");
}
gpNode.innerHTML = sinnerHTML;
var maxrepliesby1comment = 5;
var ancestralCIndexes = ArrOfMaxSizeFrCSV(pullCSVRepliesFromComment(gpNode,authnamelc),maxrepliesby1comment);
// needed to do this -before- we get linkified
// pull who(s) we're replying to, out of our comment
AddIndexAsReplierToComments(ourCIndex,ancestralCIndexes);
// linkify in-comment comment#s _IFF_ they aren't already linkified:
var re = /<\/a>/;
// look for e.g #32 plus the closing-tag that follows it, if any
sinnerHTML = sinnerHTML.replace(/#\d+(?:<\/.*?>)?/mg, function(smatch) {
if (re.test(smatch)) {
return smatch; // it's followed by , so dont change it
} else {
var thecindex = parseInt(smatch.replace(/[^\d]/g,''));
if (thecindex>0 && thecindex < ourCIndex) {
return SimplyLinkified(thecindex) + smatch.replace(/#\d+/,''); // the end tag, if any
} else { return smatch };
}
});
gpNode.innerHTML = ourTBVrecstr + sinnerHTML;
// per-comment buttons
var xrefNode = CreateNodeOfClassAndId('div','TBVxref',ourCIndex);
var oktoshowrecs = OKToShowRecs();
var dcNode = CreateAndFillDEControlsNode(ourCIndex,oktoshowrecs, authnamelc);
if (dcNode) {
xrefNode.appendChild(dcNode);
}
var bRealName = ourTBVHash['rn']=='y';
var thNode = CreateAndFillThreadingNode(ourCIndex,bRealName);
if (thNode) {
xrefNode.appendChild(thNode);
}
// stash this-comment's-info for later use by clientside js
var metaNode = CreateAndFillMetaNode('TBVmeta' + ourCIndex,metahash);
xrefNode.appendChild(metaNode);
var cmetaNode = CreateNodeOfClassAndId('div','commentmeta',ourCIndex);
cmetaNode.appendChild(xrefNode);
for (var inode=3; inode>=0; --inode) { // move 1st 3 comment nodes to under it
cmetaNode.insertBefore(liNode.removeChild(liNode.childNodes[inode]), cmetaNode.firstChild);
}
if (oktoshowrecs) {
var recstatnode = CreateNodeOfClassAndId('span','TBVrecstatus',ourCIndex);
recstatnode.innerHTML = '';
cmetaNode.appendChild(recstatnode);
var rNode = CreateAndFillRatersNode(ourCIndex);
if (rNode) {
cmetaNode.appendChild(rNode);
}
}
cmetaNode.appendChild(CreateNodeOfClass('div', 'TBVclearfloats'));
liNode.insertBefore(cmetaNode, gpNode);
document.getElementById('TBVbtnupcbody'+ourCIndex).style.display = (bodyvisible)? 'none' : 'block';
document.getElementById('TBVbtndncbody'+ourCIndex).style.display = (bodyvisible)? 'block' :'none';
HideEndIfLongComment(gpNode,ourCIndex);
}
// stash whole-page-level info for later use by clientside js
var metahashall={}; // stuff that clientjs will need access to
metahashall['numcomments'] = numcommentsSoFar;
var metaNodeAll = CreateAndFillMetaNode('TBVmetaall',metahashall);
if (metahashall['numcomments']>0) {
var showhidenode = CreateNodeOfClass('div', 'showhidebtns');
showhidenode.innerHTML = [
NewButtonStr('showTBVAuthList','Show who has commented',"showIt('TBVAuthList',true);"),
NewButtonStr('hideTBVAuthList','Hide',"showIt('TBVAuthList',false);", true)
].join('');
var authlistnode = CreateAndFillAuthorlistNode();
authlistnode.style.display='none';
showhidenode.appendChild(authlistnode);
sofarNode.appendChild(showhidenode);
FillInClassOfAllRecLinks(); // ...once we know everything.
CreateFillAttachDoemallNode(irechots.reverse(),iauthhots.reverse()); // likewise - btns to resize everything
}
sofarNode.parentNode.appendChild(metaNodeAll);
var tbvSettingsNode= CreateAndFillTBVSettingsNode('viewTBVSettings'); // view preferences
sofarNode.parentNode.insertBefore(tbvSettingsNode,sofarNode);
if (ouranchorIdent.length) {
// GM_log('at end, jump to ' + ouranchorIdent);
window.location.href = ouranchorIdent;
}
// scriptstatusdiv.style.display = 'none';
commentsdiv.style.display = 'block';
}, false);
// -------------------------------------------------------------------