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

From Second Life Wiki
Jump to navigation Jump to search
m (→‎Design: - reply)
Line 12: Line 12:


:The page layout on the Blogorums is... messy. and the wysiwyg editor loves to overuse &amp;nbsp; and there's lots of garbage spacing every... plus I forgot to convert childNodes to getElementByTagName since in both cases there's only 1 html element in the container, and it's an anchor. anyways, I'm rambling so I'll stop here <br/>-- '''[[User:Void_Singer|Void]]''' <sup><small>([[User_talk:Void_Singer|talk]]|[[Special:Contributions/Void_Singer|contribs]])</small></sup> 00:33, 14 February 2010 (UTC)
:The page layout on the Blogorums is... messy. and the wysiwyg editor loves to overuse &amp;nbsp; and there's lots of garbage spacing every... plus I forgot to convert childNodes to getElementByTagName since in both cases there's only 1 html element in the container, and it's an anchor. anyways, I'm rambling so I'll stop here <br/>-- '''[[User:Void_Singer|Void]]''' <sup><small>([[User_talk:Void_Singer|talk]]|[[Special:Contributions/Void_Singer|contribs]])</small></sup> 00:33, 14 February 2010 (UTC)
I tried to tweak it to be better... but it turned out to be easier to rewrite it from scratch. I redid just about everything with fuzzy xpath (I love "ancestor"). This final version is a lot similar than my previous version (which instead of mod'ing the post classes on the fly, it generated custom style elements on the fly; it did not scale). It looks like there is more CSS than code.
As to debugging JS in firefox, I recommend:
*[https://addons.mozilla.org/en-US/firefox/addon/11900 FireXPath] - XPath tab in Firebug, easier to use than XPather.
*[http://xpath.alephzarro.com/ XPather] - Has an excellent concise XPath help window.
<javascript>
// ==UserScript==
// @name          SL Forum Ignore
// @namespace      http://home.comcast.net/~mailerdaemon
// @description    Adds Ignore Links to User Posts on SL Forum Discussions/Questions (And Make Linden Names RED)
// @include        https://blogs.secondlife.com/thread/*
// @include        https://blogs.secondlife.com/message/*
// ==/UserScript==
var names = {};
GM_addStyle([
        ".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;}",
    ].join("\n"));
var box;
$Z("//div[@class='jive-thread-post-body' or @class='jive-thread-reply-body']", function(r,i){
        var linkwrapper = $X("./div[@class='jive-author']/div[@class='jive-username-link-wrapper']", r);
        var fullname = $X("./a", linkwrapper).textContent;
        var name = fullname.split(" ");
        if(name[1] != "Linden")
        {//this all could be made part of the original selector but... that would be ugly to say the least.
            var hidden = names[fullname] = Boolean(GM_getValue(fullname, false));
            r.parentNode.setAttribute("username", fullname);
           
            if(!box)
            {
                box = document.createElement("div");
                box.className = "GM-ignore-link-wrapper";
                {
                    var span = document.createElement("span");
                    span.appendChild(document.createTextNode("Ignore"));
                    span.className="ignore";
                    box.appendChild(span);
                }
                {
                    var span = document.createElement("span");
                    span.appendChild(document.createTextNode("Unignore"));
                    span.className="unignore";
                    box.appendChild(span);
                }
            }
            if(hidden)
                QuickHide(r.parentNode);
           
            var boxy = box.cloneNode(true);
            insertAfter(boxy, linkwrapper);
            boxy.addEventListener("click", toggleIgnore, false);
        }
    });
function QuickHide(r){ r.className = r.className + " ignored-user"; }
function QuickShow(r){ r.className = r.className.split(" ").filter(function(v){ return v != "ignored-user";}).join(" "); }
function toggleIgnore(event){
    var base = $X("./ancestor::div[@username]", event.currentTarget);
    var fullname = base.getAttribute("username");
    var hidden = names[fullname] = !names[fullname];
    if(hidden)
        GM_setValue(fullname, true);
    else
        GM_deleteValue(fullname);
    $Z("//div[@username='"+fullname+"']", hidden?QuickHide:QuickShow, base);
}
function insertAfter(insert, after){return after.parentNode.insertBefore(insert, after.nextSibling);}
function insertBefore(insert, before){return before.parentNode.insertBefore(insert, before);}
function $X(_xpath, node){//to search in a frame, you must traverse the .contentDocument or .contentWindow attribute.
    var doc = (node && (node.document || node.ownerDocument || node)) || document;
    return doc.evaluate(_xpath, node || doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0);
}
function $Y(_xpath, node){
    var doc = (node && (node.document || node.ownerDocument || node)) || document;
    return doc.evaluate(_xpath, node || doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
}
function $Z(_xpath, func, node){
    var doc = (node && (node.document || node.ownerDocument || node)) || document;
    var res = doc.evaluate(_xpath, node || doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    var args = Array.prototype.slice.call(arguments, 3);
    var i = 0;
    for (; i < res.snapshotLength; ++i)
        func.apply(func, [res.snapshotItem(i), i].concat(args));
    return i;
}
</javascript>
-- '''[[User:Strife_Onizuka|Strife]]''' <sup><small>([[User talk:Strife_Onizuka|talk]]|[[Special:Contributions/Strife_Onizuka|contribs]])</small></sup> 07:47, 14 February 2010 (UTC)

Revision as of 00:47, 14 February 2010

Design

I'm curious why you are injecting code, it seems to complicate things. You could put everything in the uPersist function (I'd rename the function). I'm a pretty experienced GM script writer and I wouldn't mind making the changes. If you haven't already, consider posting it on UserScripts.org (it's got version tracking and makes script installation easy, oh and it's free). -- Strife (talk|contribs) 18:51, 13 February 2010 (UTC)

P.S. The onclick attribute has fallen out of favor. addEventListener is the approved method of registering events.

originally I had been injecting the whole script, but didn't know about the changes to GM_*Value context or some of the newer methods (haven't played with javascript for awhile since I quite doing web work)... took me awhile to dig up a useful example for grabbing variables back to the sandbox context... current version is only beta while I make sure the features I have, work, then I'll rewrite for max efficiency...
There is a more recent version on userscripts [1] that adds jive version testing and wrappers the the GM_*Value functions for safe degrading to localStorage w/ JSON for Chrome/Opera/Safari/IE8 (although I'm not sure all the other methods will pass... I can't get a good idea what level of XPATH support they have, for instance). My understanding was that FF didn't have support for GM_* before v3 though? But that was just a matter of quick reading out of date resources...
Oh and I didn't know you could "or" the classes like that... nice, I was reading the MSDN for XPATH and must've missed it. (I also didn't realize we have javascript code wrappers on the wiki). I'd more than welcome input/suggestion/assistance on the script, I've got a few planned feature tweaks to make it nicer (listed on the new forum under beta testers), but some of them run in different directories on the new forum, so I haven't decided whether to make them separate scripts or not to cut down on page parsing...
The page layout on the Blogorums is... messy. and the wysiwyg editor loves to overuse &nbsp; and there's lots of garbage spacing every... plus I forgot to convert childNodes to getElementByTagName since in both cases there's only 1 html element in the container, and it's an anchor. anyways, I'm rambling so I'll stop here
-- Void (talk|contribs) 00:33, 14 February 2010 (UTC)

I tried to tweak it to be better... but it turned out to be easier to rewrite it from scratch. I redid just about everything with fuzzy xpath (I love "ancestor"). This final version is a lot similar than my previous version (which instead of mod'ing the post classes on the fly, it generated custom style elements on the fly; it did not scale). It looks like there is more CSS than code.

As to debugging JS in firefox, I recommend:

  • FireXPath - XPath tab in Firebug, easier to use than XPather.
  • XPather - Has an excellent concise XPath help window.

<javascript> // ==UserScript== // @name SL Forum Ignore // @namespace http://home.comcast.net/~mailerdaemon // @description Adds Ignore Links to User Posts on SL Forum Discussions/Questions (And Make Linden Names RED) // @include https://blogs.secondlife.com/thread/* // @include https://blogs.secondlife.com/message/* // ==/UserScript==

var names = {};

GM_addStyle([

       ".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;}",
   ].join("\n"));

var box;

$Z("//div[@class='jive-thread-post-body' or @class='jive-thread-reply-body']", function(r,i){

       var linkwrapper = $X("./div[@class='jive-author']/div[@class='jive-username-link-wrapper']", r);
       var fullname = $X("./a", linkwrapper).textContent;
       var name = fullname.split(" ");
       if(name[1] != "Linden")
       {//this all could be made part of the original selector but... that would be ugly to say the least.
           var hidden = names[fullname] = Boolean(GM_getValue(fullname, false));
           r.parentNode.setAttribute("username", fullname);
           
           if(!box)
           {
               box = document.createElement("div");
               box.className = "GM-ignore-link-wrapper";
               {
                   var span = document.createElement("span");
                   span.appendChild(document.createTextNode("Ignore"));
                   span.className="ignore";
                   box.appendChild(span);
               }
               {
                   var span = document.createElement("span");
                   span.appendChild(document.createTextNode("Unignore"));
                   span.className="unignore";
                   box.appendChild(span);
               }
           }
           if(hidden)
               QuickHide(r.parentNode);
           
           var boxy = box.cloneNode(true);
           insertAfter(boxy, linkwrapper);
           boxy.addEventListener("click", toggleIgnore, false);
       }
   });

function QuickHide(r){ r.className = r.className + " ignored-user"; } function QuickShow(r){ r.className = r.className.split(" ").filter(function(v){ return v != "ignored-user";}).join(" "); }

function toggleIgnore(event){

   var base = $X("./ancestor::div[@username]", event.currentTarget);
   var fullname = base.getAttribute("username");
   var hidden = names[fullname] = !names[fullname];
   if(hidden)
       GM_setValue(fullname, true);
   else
       GM_deleteValue(fullname);
   $Z("//div[@username='"+fullname+"']", hidden?QuickHide:QuickShow, base);

}

function insertAfter(insert, after){return after.parentNode.insertBefore(insert, after.nextSibling);} function insertBefore(insert, before){return before.parentNode.insertBefore(insert, before);}

function $X(_xpath, node){//to search in a frame, you must traverse the .contentDocument or .contentWindow attribute.

   var doc = (node && (node.document || node.ownerDocument || node)) || document;
   return doc.evaluate(_xpath, node || doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0);

} function $Y(_xpath, node){

   var doc = (node && (node.document || node.ownerDocument || node)) || document;
   return doc.evaluate(_xpath, node || doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

} function $Z(_xpath, func, node){

   var doc = (node && (node.document || node.ownerDocument || node)) || document;
   var res = doc.evaluate(_xpath, node || doc, null,	XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
   var args = Array.prototype.slice.call(arguments, 3);
   var i = 0;
   for (; i < res.snapshotLength; ++i)
       func.apply(func, [res.snapshotItem(i), i].concat(args));
   return i;

} </javascript>

-- Strife (talk|contribs) 07:47, 14 February 2010 (UTC)