Difference between revisions of "User:Void Singer/SL Forum Ignore"

From Second Life Wiki
Jump to navigation Jump to search
(condense the xpath (small speedup i think)...)
m (updated)
Line 15: Line 15:
// @name          SL Forum Ignore
// @name          SL Forum Ignore
// @namespace      Private
// @namespace      Private
// @description    Adds Ignore Links to User Posts on SL Forum Discussions/Questions (And Make Linden Names RED)
// @description    +Ignore Links on User Posts on SL Forum Discussions/Questions, +Make Linden Names RED, +OP Edit fix
// @include        https://blogs.secondlife.com/thread/*
// @include        https://blogs.secondlife.com/thread/*
// @include        https://blogs.secondlife.com/message/*
// @include        https://blogs.secondlife.com/message/*
// @match          https://blogs.secondlife.com/thread/*
// @match          https://blogs.secondlife.com/message/*
// @version        1.3
// @copyright      Void Singer 2009 [ https://wiki.secondlife.com/wiki/User:Void_Singer ] & BlindWanderer [ http://userscripts.org/users/4223 ]
// @license        CC-BY [ http://creativecommons.org/licenses/by/3.0 ]
// @licesne.ext    Free to copy, use, modify, distribute, or sell, with attribution.
// ==/UserScript==
// ==/UserScript==
 
   
  //-- Inject links, mark posts, and hide already ignored posts
/*//-- added match statements for compatibility with chromium 'content scripts' --//*/
function uSetupPage(){
/*//-- IE7pro unsupported: lacks CSS inheritance & getElementsByClassName      --//*/
var vColDivs, vObjDiv, vObjLink, vStrUserName, vStrLinkText, vStrPostStyle;
vColDivs = //-- grab the divs we need from the DOM, don't worry they ARE in page order
//-- compatibility replacements for Chrome4+, Opera10.5+, Safari4+, I hope
document.evaluate( "(//div[@class='jive-thread-post-body-container' or @class='jive-thread-reply-body-container' or @class='jive-username-link-wrapper'])",
if (typeof GM_addStyle  == 'undefined'){
document,
function GM_addStyle( vCss ){
null,
var vStyle = document.createElement( 'style' );
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
vStyle.textContent = vCss;
null );
document.getElementsByTagName( 'head' )[0].appendChild( vStyle );
//-- loop through the divs in order
}
for (var vIntCounter = 0; vIntCounter < vColDivs.snapshotLength; vIntCounter++){
} //-- "it's possible that *this* GM_ function is supported in chromium, but the others are not. can't find docs"
vObjDiv = vColDivs.snapshotItem( vIntCounter ); //-- grab first div, AKA user name
vStrUserName = vObjDiv.childNodes.item( 1 ).href; //-- unsafe, needs rewritten
//-- compatibility replacements for Chrome4+, Opera10.5+, Safari4+, I hope
vStrUserName = vStrUserName.substring( vStrUserName.lastIndexOf( "/" ) + 1 ); //-- grab the user name
if (typeof GM_setValue  == 'undefined'){
//-- native JSON and localStorage for GM_*Value replacement
if (vStrUserName.indexOf( "Linden" ) == -1){ //-- thou shalt not bite the hand that feeds you
GM_getValue = function( vKey, vDefault ){
if (GM_getValue( vStrUserName, 0 ) == 1){ //-- is this user already on ignore?
var vReturn = JSON.parse( window.localStorage.getItem( vKey ) );
//-- set ignore button text and blank post attributes
return ((vReturn == null)? vDefault: vReturn);
vStrLinkText = 'UnIgnore';
}
vStrPostStyle = 'display:none;';
}else{
GM_setValue = function( vKey, vValue ){
//-- set ignore button text attribute
window.localStorage.setItem( vKey, JSON.stringify( vValue ) );
vStrLinkText = 'Ignore';
}
vStrPostStyle = '';
}
GM_deleteValue = function( vKey ){
//-- create, watch, and insert ignore link after user name
window.localStorage.removeItem( vKey );
vObjLink = document.createElement( 'a' );
vObjLink.setAttribute( 'name', vStrUserName );
vObjLink.setAttribute( 'href', 'javascript:void( 0 );' );
vObjLink.setAttribute( 'style', 'color:orange;' );
vObjLink.setAttribute( 'onclick', "uIgnore( '" + vStrUserName + "');" );
vObjLink.textContent = vStrLinkText;
vObjLink.addEventListener( 'click', uPersist, true ); //-- this makes the magic work
vObjDiv.appendChild( document.createElement( 'br' ) );
vObjDiv.appendChild( vObjLink );
//-- jump to next div, AKA post body, insert name and style
vObjDiv = vColDivs.snapshotItem(++vIntCounter);
vObjDiv.setAttribute( 'name', vStrUserName + '.post' );
vObjDiv.setAttribute( 'style', vStrPostStyle );
}else{
vObjDiv.childNodes.item( 1 ).setAttribute( 'style', 'color:red' ); //-- unsafe, needs rewritten
vIntCounter++; //-- twas a Linden, skip the post body
}
}
}
}
}
 
  //-- create and insert script object into page to handle ignore status changes
  //-- function contributed by BlindWanderer
function uInjectStatusHandler(){
function uHide( vPostNode ){
var vInject = document.createElement( 'script' );
vPostNode.className += ' ignored-user';
vInject.setAttribute( 'type', 'application/javascript' );
}
vInject.textContent =
//-- this injected scriplet function will parse all posts / ignore links to change them when switching modes
//-- function contributed by BlindWanderer
"\nuIgnore = function( vStrName ){" +
function uShow( vPostNode ){
"\n  var vColLinks, vColPosts, vStrLinkText, vStrPostStyle;" +
vPostNode.className = vPostNode.className.split( ' ' ).filter( function( v ){ return v != 'ignored-user';} ).join( ' ' );
"\n  vColLinks = document.getElementsByName( vStrName );" +          //-- collect all this names ignore links
"\n  vColPosts = document.getElementsByName( vStrName + '.post' );" + //-- collect all this names posts
"\n  vStrLinkText = vColLinks[0].textContent;" +                      //-- get action to preform from link text
"\n  if (vStrLinkText == 'Ignore'){" +                                //-- preset ignored attributes for links/posts
"\n    vStrLinkText = 'UnIgnore';" +
"\n    vStrPostStyle = 'display:none;';" +
"\n  }else{" +                                                        //-- preset unignored attributes for links/posts
"\n    vStrLinkText = 'Ignore';" +
"\n    vStrPostStyle = '';" +
"\n  }" +
"\n  for (var vIntCounter = vColLinks.length - 1; vIntCounter  > -1; vIntCounter --){" +                    //-- loop through and set attributes
"\n    vColLinks[vIntCounter].textContent = vStrLinkText;" +
"\n    vColPosts[vIntCounter].setAttribute( 'style', vStrPostStyle );" +
"\n  }" +
"\n}\n";
document.body.appendChild( vInject ); //-- inject scriptlet so it can run in the page context
}
}
 
  //-- magic to persist ignore settings, runs in sandbox context
  //-- function contributed by BlindWanderer, modifed by Void Singer
function uPersist(){
function uToggleIgnore(){
if (this.textContent == "UnIgnore"){ //-- has the person been ignored?
//-- no ancestor support outside of xpath?
GM_setValue( this.name, 1 ); //-- store the name for future pages
var vName = this.getAttribute( 'username' );
if (this.name == "Void.Singer"){ //-- should probably remove this if statement..... Naaaaah =P
//-- ?is there really any savings to caching instead of a direct call to GM_getValue?
alert( "Well isn't that gratitude for ya\nYa know I wrote this ignore script... right?\n\n=p  thppppppt! " );
var vAction = (vIgnoreCache[vName] = !vIgnoreCache[vName])? uHide : uShow;
}
if (vIgnoreCache[vName]){
}else{
GM_setValue( vName, true );
if (GM_getValue( this.name ) == 1){ //-- delete names that aren't on ignore any more
}
GM_deleteValue( this.name );
else{
GM_deleteValue( vName );
}
var vSwaps = document.getElementsByClassName( vName );
var vCount = 0;
for (vCount; vCount < vSwaps.length; ++vCount){
vAction.apply( vAction, [vSwaps.item( vCount )] );
}
}
//-- adds styles, ignore toggles, and marks post containers
function uTweakPage(){
//-- use style to reduce load, contributed by BlindWanderer, modifed by Void Singer
GM_addStyle( [
'.GM-Fix-Thread-Edit {',
'  background: url( "../images/jive-icon-edit-16x16.gif" ) no-repeat scroll left center transparent;',
'  font-weight: bold;',
'  padding-left: 17px;',
'  margin-right: 0.5em;',
'  float: right;}',
'',
'.GM-ignore-link-wrapper { cursor:pointer; }',
'',
'.GM-ignore-link-wrapper .ignore { display:block;}',
'.GM-ignore-link-wrapper .unignore { display:none;}',
'.ignored-user .GM-ignore-link-wrapper .ignore {display:none;}',
'.ignored-user .GM-ignore-link-wrapper .unignore {display:block;}',
'',
'.ignored-user .jive-author { padding-top:0; padding-bottom:0; }',
'.ignored-user .jive-author-avatar-container { display:none!important; }',
'.ignored-user .jive-author-avatar-container { background-image: none !important; }',
'.ignored-user .jive-author > em { display:none; }',
'',
'.ignored-user .jive-thread-post-body-container { min-height:0; background-image: none !important; padding-bottom:8px; }',
'.ignored-user .jive-thread-post-subject { float: left; width:auto; }',
'.ignored-user .jive-thread-post-subject h2 { display:none; }',
'.ignored-user .jive-thread-post-message { display:none; }',
'.ignored-user .jive-thread-post-details { background-image: none !important; padding-top:0; margin-top:0; width:auto;}',
'.ignored-user .jive-thread-post-subject-content { background-image: none !important; padding-bottom:0; margin-bottom:0; }',
'.ignored-user .jive-thread-post-subject-content .jive-thread-post-reply { display:none; }',
'',
'.ignored-user .jive-thread-reply-body-container { min-height:0; padding-bottom:6px; }',
'.ignored-user .jive-thread-reply-subject { float: left; width:auto; padding-bottom:0!important;}',
'.ignored-user .jive-thread-reply-subject strong { display:none!important; }',
'.ignored-user .jive-thread-reply-message { display:none; }',
'.ignored-user .jive-content-controls { text-align:right; width:auto; padding-top:0; padding-bottom:0;}',
'',
'div[class$=".Linden"] div.jive-author div.jive-username-link-wrapper > a { color:#BB0000!important; }',
].join( '\n' ) );
//-- clone edit thread link to OP
var vGetOP  = document.getElementsByClassName( 'jive-thread-post-details' ).item( 0 );
var vGetEdit = document.getElementsByClassName( 'jive-link-edit' ).item( 0 );
if ((null != vGetEdit) && (null != vGetOP)){ //-- need to text both for flat paged views (edit still shows on follow-up pages)
var vCloneEdit = vGetEdit.cloneNode( true );
vGetOP.appendChild( vCloneEdit );
vCloneEdit.className = 'GM-Fix-Thread-Edit';
}
//-- create generic toggle for ignore buttons, contributed by BlindWanderer
var vToggleBox = document.createElement( 'div' );
vToggleBox.className = 'GM-ignore-link-wrapper';
{
var span = document.createElement( 'span' );
span.appendChild( document.createTextNode( 'Ignore' ) );
span.className = 'ignore';
vToggleBox.appendChild(span);
}
{
var span = document.createElement( 'span' );
span.appendChild( document.createTextNode( 'Unignore' ) );
span.className = 'unignore';
vToggleBox.appendChild(span);
}
function uInsertToggles( vPostNodes ){ //-- contributed by BlindWanderer, modifed by Void Singer
var vCount = 0;
//-- loop through posts
for (vCount; vCount < vPostNodes.length; ++vCount){
//-- get user profile link for position, and grab their system name
var vUserLink = vPostNodes.item( vCount ).getElementsByClassName( 'jive-username-link' ).item( 0 );
var vName = vUserLink.href.substring( vUserLink.href.lastIndexOf( '/' ) + 1 );
//-- tag post for ignore handling
vPostNodes.item( vCount ).parentNode.className += ' ' + vName; //-- changed to class vs custom attribute
if (vName.split( '.' ).slice( -1 )[0] != 'Linden'){
//-- check and ignore post if user already on ignore
//-- ?is there really any savings to caching instead of a direct call to GM_getValue?
var vIsIgnored = vIgnoreCache[vName] = GM_getValue( vName, false );
if (vIsIgnored){
uHide( vPostNodes.item( vCount ).parentNode );
}
//-- clone ignore toggle into user info box, and tie it the switch function
var vIgnoreToggle = vToggleBox.cloneNode( true );
//-- ?no ancestor support outside of xpath?
vIgnoreToggle.setAttribute( 'username', vName );
vUserLink.parentNode.insertBefore( vIgnoreToggle, vUserLink.nextSibling ); //--contributed by Blind Wanderer
vIgnoreToggle.addEventListener( 'click', uToggleIgnore, false );
}
}
}
}
}
//-- insert Toggle in OP
uInsertToggles( document.getElementsByClassName( 'jive-thread-post-body' ) );
//-- insert Toggle in replies
uInsertToggles( document.getElementsByClassName( 'jive-thread-reply-body' ) );
//-- not happy with the separate inserts for OP and reply, but it wasn't worth a custom function to grab both
}
}
 
uInjectStatusHandler(); //-- inject status changer
//-- ?is there really any savings to caching instead of a direct call to GM_getValue?
uSetupPage(); //-- format the page
var vIgnoreCache = {}; //-- contributed by BlindWanderer
 
/*//--                          License Text                          --//*/
//-- jive version checking
/*//  Free to copy, use, modify, distribute, or sell, with attribution.   //*/
if (document.getElementsByClassName( 'jiveVersion' ).item( 0 ).textContent.indexOf( '80211' ) != -1){
/*//    (C)2009 (CC-BY) [ http://creativecommons.org/licenses/by/3.0 ]    //*/
uTweakPage();
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
}</javascript>
/*//  All usages must contain a plain text copy of the previous 2 lines.  //*/
/*//--                                                                  --//*/
</javascript>
:[[User:Void_Singer/Programs#Return_to_Void_Singers_user_page|Return to top]]
:[[User:Void_Singer/Programs#Return_to_Void_Singers_user_page|Return to top]]
}}
}}

Revision as of 20:41, 21 February 2010

SL Forum Ignore

Features:

  • requires FireFox 2.0
  • requires Greasemonkey some-version-or-another

User Script

<javascript>// ==UserScript== // @name SL Forum Ignore // @namespace Private // @description +Ignore Links on User Posts on SL Forum Discussions/Questions, +Make Linden Names RED, +OP Edit fix // @include https://blogs.secondlife.com/thread/* // @include https://blogs.secondlife.com/message/* // @match https://blogs.secondlife.com/thread/* // @match https://blogs.secondlife.com/message/* // @version 1.3 // @copyright Void Singer 2009 [ https://wiki.secondlife.com/wiki/User:Void_Singer ] & BlindWanderer [ http://userscripts.org/users/4223 ] // @license CC-BY [ http://creativecommons.org/licenses/by/3.0 ] // @licesne.ext Free to copy, use, modify, distribute, or sell, with attribution. // ==/UserScript==

/*//-- added match statements for compatibility with chromium 'content scripts' --//*/ /*//-- IE7pro unsupported: lacks CSS inheritance & getElementsByClassName --//*/

//-- compatibility replacements for Chrome4+, Opera10.5+, Safari4+, I hope

if (typeof GM_addStyle == 'undefined'){ function GM_addStyle( vCss ){ var vStyle = document.createElement( 'style' ); vStyle.textContent = vCss; document.getElementsByTagName( 'head' )[0].appendChild( vStyle ); } } //-- "it's possible that *this* GM_ function is supported in chromium, but the others are not. can't find docs"

//-- compatibility replacements for Chrome4+, Opera10.5+, Safari4+, I hope

if (typeof GM_setValue == 'undefined'){ //-- native JSON and localStorage for GM_*Value replacement GM_getValue = function( vKey, vDefault ){ var vReturn = JSON.parse( window.localStorage.getItem( vKey ) ); return ((vReturn == null)? vDefault: vReturn); }

GM_setValue = function( vKey, vValue ){ window.localStorage.setItem( vKey, JSON.stringify( vValue ) ); }

GM_deleteValue = function( vKey ){ window.localStorage.removeItem( vKey ); } }

//-- function contributed by BlindWanderer

function uHide( vPostNode ){ vPostNode.className += ' ignored-user'; }

//-- function contributed by BlindWanderer

function uShow( vPostNode ){ vPostNode.className = vPostNode.className.split( ' ' ).filter( function( v ){ return v != 'ignored-user';} ).join( ' ' ); }

//-- function contributed by BlindWanderer, modifed by Void Singer

function uToggleIgnore(){ //-- no ancestor support outside of xpath? var vName = this.getAttribute( 'username' ); //-- ?is there really any savings to caching instead of a direct call to GM_getValue? var vAction = (vIgnoreCache[vName] = !vIgnoreCache[vName])? uHide : uShow; if (vIgnoreCache[vName]){ GM_setValue( vName, true ); } else{ GM_deleteValue( vName ); } var vSwaps = document.getElementsByClassName( vName ); var vCount = 0; for (vCount; vCount < vSwaps.length; ++vCount){ vAction.apply( vAction, [vSwaps.item( vCount )] ); } }

//-- adds styles, ignore toggles, and marks post containers function uTweakPage(){ //-- use style to reduce load, contributed by BlindWanderer, modifed by Void Singer GM_addStyle( [ '.GM-Fix-Thread-Edit {', ' background: url( "../images/jive-icon-edit-16x16.gif" ) no-repeat scroll left center transparent;', ' font-weight: bold;', ' padding-left: 17px;', ' margin-right: 0.5em;', ' float: right;}', , '.GM-ignore-link-wrapper { cursor:pointer; }', , '.GM-ignore-link-wrapper .ignore { display:block;}', '.GM-ignore-link-wrapper .unignore { display:none;}', '.ignored-user .GM-ignore-link-wrapper .ignore {display:none;}', '.ignored-user .GM-ignore-link-wrapper .unignore {display:block;}', , '.ignored-user .jive-author { padding-top:0; padding-bottom:0; }', '.ignored-user .jive-author-avatar-container { display:none!important; }', '.ignored-user .jive-author-avatar-container { background-image: none !important; }', '.ignored-user .jive-author > em { display:none; }', , '.ignored-user .jive-thread-post-body-container { min-height:0; background-image: none !important; padding-bottom:8px; }', '.ignored-user .jive-thread-post-subject { float: left; width:auto; }', '.ignored-user .jive-thread-post-subject h2 { display:none; }', '.ignored-user .jive-thread-post-message { display:none; }', '.ignored-user .jive-thread-post-details { background-image: none !important; padding-top:0; margin-top:0; width:auto;}', '.ignored-user .jive-thread-post-subject-content { background-image: none !important; padding-bottom:0; margin-bottom:0; }', '.ignored-user .jive-thread-post-subject-content .jive-thread-post-reply { display:none; }', , '.ignored-user .jive-thread-reply-body-container { min-height:0; padding-bottom:6px; }', '.ignored-user .jive-thread-reply-subject { float: left; width:auto; padding-bottom:0!important;}', '.ignored-user .jive-thread-reply-subject strong { display:none!important; }', '.ignored-user .jive-thread-reply-message { display:none; }', '.ignored-user .jive-content-controls { text-align:right; width:auto; padding-top:0; padding-bottom:0;}', , 'div[class$=".Linden"] div.jive-author div.jive-username-link-wrapper > a { color:#BB0000!important; }', ].join( '\n' ) );

//-- clone edit thread link to OP var vGetOP = document.getElementsByClassName( 'jive-thread-post-details' ).item( 0 ); var vGetEdit = document.getElementsByClassName( 'jive-link-edit' ).item( 0 ); if ((null != vGetEdit) && (null != vGetOP)){ //-- need to text both for flat paged views (edit still shows on follow-up pages) var vCloneEdit = vGetEdit.cloneNode( true ); vGetOP.appendChild( vCloneEdit ); vCloneEdit.className = 'GM-Fix-Thread-Edit'; }

//-- create generic toggle for ignore buttons, contributed by BlindWanderer var vToggleBox = document.createElement( 'div' ); vToggleBox.className = 'GM-ignore-link-wrapper'; { var span = document.createElement( 'span' ); span.appendChild( document.createTextNode( 'Ignore' ) ); span.className = 'ignore'; vToggleBox.appendChild(span); } { var span = document.createElement( 'span' ); span.appendChild( document.createTextNode( 'Unignore' ) ); span.className = 'unignore'; vToggleBox.appendChild(span); }

function uInsertToggles( vPostNodes ){ //-- contributed by BlindWanderer, modifed by Void Singer var vCount = 0; //-- loop through posts for (vCount; vCount < vPostNodes.length; ++vCount){ //-- get user profile link for position, and grab their system name var vUserLink = vPostNodes.item( vCount ).getElementsByClassName( 'jive-username-link' ).item( 0 ); var vName = vUserLink.href.substring( vUserLink.href.lastIndexOf( '/' ) + 1 ); //-- tag post for ignore handling vPostNodes.item( vCount ).parentNode.className += ' ' + vName; //-- changed to class vs custom attribute if (vName.split( '.' ).slice( -1 )[0] != 'Linden'){ //-- check and ignore post if user already on ignore //-- ?is there really any savings to caching instead of a direct call to GM_getValue? var vIsIgnored = vIgnoreCache[vName] = GM_getValue( vName, false ); if (vIsIgnored){ uHide( vPostNodes.item( vCount ).parentNode ); } //-- clone ignore toggle into user info box, and tie it the switch function var vIgnoreToggle = vToggleBox.cloneNode( true ); //-- ?no ancestor support outside of xpath? vIgnoreToggle.setAttribute( 'username', vName ); vUserLink.parentNode.insertBefore( vIgnoreToggle, vUserLink.nextSibling ); //--contributed by Blind Wanderer vIgnoreToggle.addEventListener( 'click', uToggleIgnore, false ); } } } //-- insert Toggle in OP uInsertToggles( document.getElementsByClassName( 'jive-thread-post-body' ) ); //-- insert Toggle in replies uInsertToggles( document.getElementsByClassName( 'jive-thread-reply-body' ) ); //-- not happy with the separate inserts for OP and reply, but it wasn't worth a custom function to grab both }

//-- ?is there really any savings to caching instead of a direct call to GM_getValue? var vIgnoreCache = {}; //-- contributed by BlindWanderer

//-- jive version checking if (document.getElementsByClassName( 'jiveVersion' ).item( 0 ).textContent.indexOf( '80211' ) != -1){ uTweakPage(); }</javascript>

Return to top