משתמש:Mikimik/js/customizeWLRC.js

מתוך ויקיפדיה, האנציקלופדיה החופשית

הערה: לאחר הפרסום, ייתכן שיהיה צורך לנקות את זיכרון המטמון (cache) של הדפדפן כדי להבחין בשינויים.

  • פיירפוקס / ספארי: להחזיק את המקש Shift בעת לחיצה על טעינה מחדש (Reload) או ללחוץ על צירוף המקשים Ctrl-F5 או Ctrl-R (במחשב מק: ⌘-R).
  • גוגל כרום: ללחוץ על צירוף המקשים Ctrl-Shift-R (במחשב מק: ⌘-Shift-R).
  • אינטרנט אקספלורר / אדג': להחזיק את המקש Ctrl בעת לחיצה על רענן (Refresh) או ללחוץ על צירוף המקשים Ctrl-F5.
  • אופרה: ללחוץ על Ctrl-F5.
// original from [[w:en:User:js/watchlist.js]], changed and improved by [[user:Mikimik]]
var customizeWLRC = new function()        // --- wrapper object ---
{
var timePageLoaded = (getParamValue("loadtime") || new Date()) - 35000;  // add 35 seconds just in case
var content = null, point = null;
var mapNStoNum = new Array(), mapNumtoNS = new Array();
var listSortedBy = "time", alreadyAddedWatchLinks = false, alreadyMergedLists = false;
var hideLinesByType = new Array();
var patroller = null;                                     // can the user access the patrol system ?

var msg = {
    onlynew   : wgUserLanguage == "he" ? "שינויים חדשים בלבד" : "Only new changes",
    onlynew_t : wgUserLanguage == "he" ? "הצג שינויים שבוצעו מאז שדף זה נטען" : "Show changes since this page was loaded",

    sortBy            : wgUserLanguage == "he" ? "מיון לפי" : "Sort by",
    sortDone          : wgUserLanguage == "he" ? "הרשימה כבר ממוינת" : "List already sorted",
    sortByTime        : wgUserLanguage == "he" ? "זמן" : "time",
    sortByTime_t      : wgUserLanguage == "he" ? "מיין דפים לפי זמן" : "Sort titles by time",
    sortByGroupTime   : wgUserLanguage == "he" ? "קבוצות זמן" : "group time",
    sortByGroupTime_t : wgUserLanguage == "he" ? "מיין דפים לפי קבוצות זמן" : "Sort titles by group time",
    sortByPage        : wgUserLanguage == "he" ? "שם דף" : "page name",
    sortByPage_t      : wgUserLanguage == "he" ? "מיין דפים לפי שם הדף" : "Sort titles by title name",
    sortByUser        : wgUserLanguage == "he" ? "שם משתמש" : "user name",
    sortByUser_t      : wgUserLanguage == "he" ? "מיין דפים לפי שם המשתמש" : "Sort titles by user name",

    mergeChanges   : wgUserLanguage == "he" ? "מזג רשימות" : "Merge lists",
    mergeChanges_t : wgUserLanguage == "he" ? "מזג רשימות שינויים" : "Merge changes list",
    mergedListHead : wgUserLanguage == "he" ? "רשימה ממוזגת" : "Merged list",

    hideActions_t      : wgUserLanguage == "he" ? "הסתרת" : "Hide",
    nontopEdits      : wgUserLanguage == "he" ? "עריכות לא אחרונות" : "Non top edits",
    patrolledactions : wgUserLanguage == "he" ? "פעולות בדוקות" : "Patrolled actions",
    talkpageactions  : wgUserLanguage == "he" ? "דפי שיחה" : "Talk pages",
    logactions       : wgUserLanguage == "he" ? "פעולות יומן" : "Log actions",
    editactions      : wgUserLanguage == "he" ? "עריכות" : "Edits",

    watch             : wgUserLanguage == "he" ? "מעקב" : "Watch",
    unwatch           : wgUserLanguage == "he" ? "הפסקת מעקב" : "Unwatch",
    watchUnwatchTitle : wgUserLanguage == "he" ? "הוספת קישורי (+/x) למעקב/הפסקת מעקב מהיר" : "Add (+/x) for quick watch/unwatch links"
};

// mark lines in recent-changes and watch-list pages. written by [[User:Mikimik]]
function markLinesAndHistoryLinks()
{
    var lines = content.getElementsByTagName("LI");
    var pages = new Array(), grouptime = new Array();
    var logactionrx = new RegExp ( "^" + wgServer + "\\/wiki\\/" + encodeURIComponent(wgFormattedNamespaces[-1]) + ":" +
                                   ( wgContentLanguage == "he" ? encodeURIComponent("יומנים") : wgContentLanguage == "en" ? "Log" : "[^/:]+" ) +
                                   "\\/([a-z]+)$" );
// possible log actions:
//     * user related: block, newusers, rights, renameuser (rarely/not used: merge, gblblock, globalauth, gblrights)
//     * page related: upload, move, protect, delete, import (doesn't show on recent changes: patrol)
//     * log related:  delete (when details in a log action are hidden it's considered a delete action on the page "מיוחד:יומנים/<log name>")
//         because log related log actions are not interesting and quite uncommon they're treated as page related log actions with a hidden page name
//     * other:        abusefilter
    for ( var index = 0 ; index < lines.length ; index++ )
    {
        var logaction = "", pagetitle = "", username = "", patrolled = true;

        for ( var item = lines[index].firstChild ; item ; item = item.nextSibling )
            if ( item.nodeName == "A" )
                if ( /&action=history$/.test(item.href) )                 // in edit actions the history link can be first or second
                    item.className += " hist";                            // mark the history link
                 else if ( /\bmw-userlink\b/.test(item.className) )       // * no user link if user name was removed from the action
                          username = item.firstChild.nodeValue;           // * one user link in edits and most log actions
                                                                          // * keep the second of two user links in block actions
                                                                          //   and newusers actions where an existing user creates a new user
                  else if ( logactionrx.test(item.href) )
                           logaction = logaction || item.href.match(logactionrx)[1];     // get type of log action
                   else { if ( /^http:\/\/[^/]+\/(wiki\/[^&]+|w\/index.php\?title=[^&]+&(action=edit&redlink=1|rcid=\d+))$/.test(item.href) )
                              pagetitle = item.firstChild.nodeValue; }    // a page title exists in all edit actions and some log action,
                                                                          // unless it was removed
                                              // links not needed and thus not catched are: &diff / &redirect=no(&action=edit&redlink=1)?
             else if ( item.className )
                      if ( /\bunpatrolled\b/.test(item.className) ) patrolled = false;   // unpatrolled mark found
                       else if ( /\b(mw-watched|history-deleted)\b/.test(item.className) && item.getElementsByTagName("A")[0] )
                                pagetitle = item.getElementsByTagName("A")[0].firstChild.nodeValue;  // watched and/or deleted page - find link in
                                                                                             // <span>link</span> or <span><span>link</span></span>
        if ( !logaction )                                                          // page edit: pagetitle = page edited
        {
            if ( pages[pagetitle] ) lines[index].className += " nontopedit";       // mark the line as a non top edit
             else
            {
                pages[pagetitle] = true;                                           // first time this page appears
                lines[index].className += " topedit";                              // mark the line as a top edit
            }

            lines[index].className += " editaction " + ( patroller && patrolled ? "patrolledaction" : "unpatrolledaction" );
        }
         else if ( /^(block|newusers|rights|renameuser)$/.test(logaction) )        // user log action
        {
            if ( pagetitle )  // this only happens for rights and renameuser log actions or newusers where an existing user creates a new user
            {
                username = pagetitle.substring(pagetitle.indexOf(":")+1);          // fix user name
                pagetitle = "";                                                    // no page title is needed for a user log action
            }

            lines[index].className += " logaction userlogaction patrolledaction";  // mark as a patrolled user related log action
        }
         else                                                                      // page log action or some other log action
        {
            if ( !/^(upload|move|protect|delete|import)$/.test(logaction) ) pagetitle = "";  // remove the page title for non page log actions
                                                                 // now pagetitle is either empty or the page on which the log action acted on
            lines[index].className += " logaction pagelogaction patrolledaction";  // mark as a patrolled page related log action
        }

        var ns = pagetitle ? getNSNum(pagetitle) : -1;     // get the page namespace, or use special namespace for:
                                                           // * user related log action
                                                           // * page related log action with a hidden page name (possibly a log related log action)
        lines[index].namespace = ns;                                               // keep the namespace in the line so other scripts can use it
        lines[index].pagetitle = pagetitle;                                        // keep the pagetitle in the line so other scripts can use it
        if ( pagetitle && ns % 2 ) lines[index].className +=  " talkpageaction";   // mark talk page actions

        var sortableName = zeroes(pagetitle && ns % 2 ? ns : ns+1, true) + "\x01" + (ns > 0 ? pagetitle.substring(pagetitle.indexOf(":")+1) : pagetitle);
        if ( !grouptime[sortableName] ) grouptime[sortableName] = pagetitle ? (index+1)*10000 : 1;

        lines[index].sortkey = new Array();
        lines[index].sortkey["time"] = index;
        lines[index].sortkey["page"] = sortableName + "\x01" + zeroes(index);
        lines[index].sortkey["user"] = username + "\x01" + lines[index].sortkey["page"];
        lines[index].sortkey["grouptime"] = grouptime[sortableName] + index;
    }

    return index;
}

function markSortLink ( action )                       // action = mark (true) / unmark (false)
{
    if ( document.getElementById("sortby" + listSortedBy + "Link") )
        document.getElementById("sortby" + listSortedBy + "Link").style.fontWeight = action ? "bold" : "normal";
}

this.sortChangesList = function ( sortby, forcesort )                           //  sortkey = "page", "user", "time" or other
{
 try {
    if ( listSortedBy == sortby && !forcesort ) return alert ( msg.sortDone );  // alert if already sorted by this sort key
    markSortLink ( false );

    var DayTitles = content.getElementsByTagName("H4");
    for ( var d = 0 ; d < DayTitles.length ; d++ )                           // sort every day separately
    {
        var listWrapper = DayTitles[d].nextSibling;                          // find UL after the day title
        while ( listWrapper && listWrapper.nodeName != "H4" && listWrapper.nodeName != "UL" ) listWrapper = listWrapper.nextSibling;
        if ( !listWrapper || listWrapper.nodeName != "UL" || !listWrapper.getElementsByTagName("LI")[1] ) continue;

        var unSortedLines = listWrapper.getElementsByTagName("LI");          // get the unsorted lines from the list wrapper
        var items = new Array();

        for ( var i = 0 ; i < unSortedLines.length ; i++ )                                           // copy the unsorted lines to a sortable list
            items.push ( { sortkey : unSortedLines[i].sortkey[sortby], line : unSortedLines[i] } );  // with the appropriate sortkey

        items.sort ( function(a,b) {                                         // sort items
                         if ( a.sortkey > b.sortkey ) return 1;
                         if ( a.sortkey < b.sortkey ) return -1;
                         return 0;                               } );

        for ( var i in items )                                               // sort lines in HTML by moving each line
            items[i].line.parentNode.appendChild ( items[i].line );          // to the bottom of the list, according to the sorted list
    }

    listSortedBy = sortby;
    markSortLink ( true );
  }
 catch ( e )
  {
    return;
  }
}

function onlyNewEntries()
{
    var url = window.location.href.split("#")[0].replace(/&loadtime=\d+/,"");
    if ( /[?&]days=/.test(url) ) url = url.replace ( /([?&]days=)[^&]*/, "$1" + ((new Date() - timePageLoaded) / (1000 * 3600 * 24)) );
     else url = url + ( url.indexOf("?") == -1 ? "?" : "&" ) + "days=" + ((new Date() - timePageLoaded) / (1000 * 3600 * 24));
    this.href = url + ( /[?&]sortWLRC=page(&|$)/.test(url) ? "" : "&sortWLRC=page" ) + "&loadtime=" + new Date().getTime();
    return true;
}

this.mergeChangesLists = function()
{
    if ( alreadyMergedLists ) return;
    alreadyMergedLists = true;
    if ( document.getElementById("wlrcMergeLink") ) document.getElementById("wlrcMergeLink").style.fontWeight = "bold";

    var DayTitles = content.getElementsByTagName("H4");
    if ( DayTitles.length <= 1 || !content.getElementsByTagName("LI")[0] )  // there are no lines, no lists or just one list - nothing to merge
    {
        if ( DayTitles[0] ) DayTitles[0].id = "mergedListTitle";            // mark the first day title, if it exists
        return;
    }

    var mergedList = null;                                                 // --> the inner-most wrapper of the merged list
    var outerWrapper = null;                                               // --> the outer-most wrapper of the merged list
    var archetypeList = content.getElementsByTagName("LI")[0].parentNode;  // use the direct parent of the first line as the archetype list

    do {
        var struct = archetypeList.cloneNode(false);                       // copy the structure of the archetype list

        if ( outerWrapper ) struct.appendChild ( outerWrapper );           // if there's an internal structure - attach it
         else mergedList = struct;                                         // else - this is the inner-most wrapper

        outerWrapper = struct;                                             // struct is the new outer-most wrapper
        archetypeList = archetypeList.parentNode;                          // go up the tree
    }
    while ( outerWrapper.tagName != "UL" );                                // until the outer-most UL wrapper is found

    DayTitles[0].parentNode.insertBefore ( outerWrapper, DayTitles[0] );   // insert the outer wrapper of the merged list before the first day title

    for ( var d = 0 ; d < DayTitles.length ; d++ )
    {
        var list = DayTitles[d].nextSibling;                               // find UL after the day title
        while ( list && list.nodeName != "H4" && list.nodeName != "UL" ) list = list.nextSibling;
        if ( !list || list.nodeName != "UL" ) continue;

        var date = DayTitles[d].firstChild.nodeValue.replace(/ *\d+$/,"");                 // get the date, without the year
        for ( var item = list.getElementsByTagName("LI")[0] ; item ; item = next )
        {
            var next = item.nextSibling;
            if ( item.nodeName == "LI" )
            {
                for ( var t = item.firstChild ; t ; t = t.nextSibling )
                    if ( t.nodeName == "#text" && /\d\d:\d\d/.test(t.nodeValue) )          // find "00:00" text in line
                    {
                        t.nodeValue = t.nodeValue.replace(/(\d\d:\d\d)/,date + " $1");     // add list's date before the line's time
                        break;
                    }
                mergedList.appendChild ( item );                                           // move the line to the merged list
            }
        }

        list.parentNode.removeChild ( list );                                              // remove the empty list
    }

    date += " - " + DayTitles[0].firstChild.nodeValue.replace(/ *\d+$/,"");      // "last date - first date"

    for ( var d = DayTitles.length - 1 ; d >= 0 ; d-- ) DayTitles[d].parentNode.removeChild ( DayTitles[d] );  // remove original day titles

    var mergedTitle = document.createElement("H4");                              // create the merged list title
    mergedTitle.id = "mergedListTitle";
    mergedTitle.appendChild ( document.createTextNode(msg.mergedListHead + ": " + date) );
    outerWrapper.parentNode.insertBefore ( mergedTitle, outerWrapper );          // insert merged list title before the merged list wrapper

    if ( listSortedBy != "time" ) this.sortChangesList ( listSortedBy, true );   // resort list, if needed
}

this.toggleFilter = function ( id, className, action )
{
    hideLinesByType["."+className] = action;

    var show = "", hide = "";
    for ( var c in hideLinesByType )
        if ( hideLinesByType[c] ) show += (show ? "," : "") + c;
                             else hide += (hide ? "," : "") + c;

    appendCSS ( ( show ? show + "{ display:list-item; }" : "" ) + ( hide ? hide + "{ display:none; }" : "" ) );

    var link = document.getElementById(id);
    link.href = link.href.replace ( /,[01]\)/, action ? ",0)" : ",1)" );
    link.style.textDecoration = action ? "none" : "line-through";
}

// --- watch/unwatch from watch list and recent changes ---

var watchLinks = new Array();
var inProgress = null, timeoutID = null;

this.addWatchLinks = function()
{
    if ( alreadyAddedWatchLinks ) return;
    alreadyAddedWatchLinks = true;
    if ( document.getElementById("wlrcAddWatchLinks") ) document.getElementById("wlrcAddWatchLinks").style.fontWeight = "bold";

    var histLinks = content.getElementsByClassName("hist");

    for ( var i = 0 ; i < histLinks.length ; i++ )
    {
        var link = document.createElement("A");
        link.appendChild ( document.createTextNode("?") );
        link.onclick = ajaxWatchUnwatch;
        watchLinks.push ( link );

        var point = histLinks[i].nextSibling.nextSibling;
        point.parentNode.insertBefore ( document.createTextNode(' ('), point );
        point.parentNode.insertBefore ( link, point );
        point.parentNode.insertBefore ( document.createTextNode(') \u200F'), point );

        if ( wgCanonicalSpecialPageName == "Recentchanges" ) setWatchLinkLook ( link, !link.parentNode.getElementsByClassName("mw-watched")[0] );
         else setWatchLinkLook ( link, false );
    }
}

function ajaxWatchUnwatch ( e )
{
    if ( inProgress ) return false;

    e = e || event;
    var targ = e.target || e.srcElement;
    inProgress = targ.parentNode.pagetitle;
    timeoutID = setTimeout ( function() { inProgress = null; }, 10000 );

    targ.replaceChild ( document.createTextNode("..."), targ.firstChild );

//    sajax_do_call ( "wfAjaxWatch", [ inProgress, targ.state ? "w" : "u" ], processWatchResponse );   // use ajax to ask server to watch/unwatch
    $.get( wgScriptPath+'/api.php?action=watch&format=json&title='+encodeURIComponent(inProgress)+( targ.state ? '' : '&unwatch' ),
           {}, processWatchResponse,'json');
    return false;
}

function processWatchResponse ( response )
{
    if ( timeoutID ) clearTimeout ( timeoutID );

    response=response.watch;
    if (response.watched!==undefined) var state = false;
     else if(response.unwatched!==undefined) var state = true;
     else return;                                                     // unrecognized response

    var name = inProgress, name2 = inProgress;
    var ns = getNSNum ( name2 );                                      // find the full name of "other page":
    if ( ns > 0 ) name2 = name2.substring(name2.indexOf(":")+1);      // remove old prefix
    if ( ns % 2 ) ns--;                                               // switch to "other" namespace
             else ns++;
    if ( ns > 0 ) name2 = getNSTitle(ns) + ":" + name2;               // add new prefix

    for ( var i in watchLinks )                                       // mark lines that are either name or name2
        if ( watchLinks[i].parentNode.pagetitle == name || watchLinks[i].parentNode.pagetitle == name2 )
        {
            setWatchLinkLook ( watchLinks[i], state );

            var item = watchLinks[i].nextSibling;
            while ( !item.tagName || ( item.tagName != "A" && !item.getElementsByTagName("A")[0] ) ) item = item.nextSibling;
            if ( wgCanonicalSpecialPageName == "Recentchanges" ) item.style.fontWeight = state ? "normal" : "bold";
             else item.style.textDecoration = state ? "line-through" : "none";
        }

    inProgress = null;
}

function setWatchLinkLook ( link, state )
{
    link.replaceChild ( document.createTextNode(state ? "+" : "x"), link.firstChild );
                                                                                         // set non-Ajax watch/unwatch url
    link.href = wgScript + "?action=" + ( state ? "watch" : "unwatch" ) + "&title=" + encodeTextToWikiURL ( link.parentNode.pagetitle );
    link.title = state ? msg.watch : msg.unwatch;
    link.state = state;
}

// --- general functions

var linkGroupStatus = 0, linkGroupStartText;

function startLinkGroup ( text )
{
    linkGroupStatus = 1;
    linkGroupStartText = document.createTextNode(" | < " + text + ": ");
}

function endLinkGroup()
{
    if ( linkGroupStatus == 2 ) point.parentNode.insertBefore ( document.createTextNode(" >"), point );
    linkGroupStatus = 0;
}

function addLink ( id, url, text, title )
{
    var link = document.createElement("a");
    link.id = id;
    link.href = url;
    link.appendChild ( document.createTextNode(text) );
    link.title = title ? title : text;

    if ( linkGroupStatus != 1 ) point.parentNode.insertBefore ( document.createTextNode(linkGroupStatus ? ", " : " | "), point );
     else
    {
        linkGroupStatus = 2;
        point.parentNode.insertBefore ( linkGroupStartText, point );
    }
    point.parentNode.insertBefore ( link, point );
    return link;
}

function getNSNum ( title )        // returns namespace number matching the title
{
    var pos = title.indexOf(":");
    return pos != -1 && mapNStoNum[title.substring(0,pos)] ? mapNStoNum[title.substring(0,pos)] : 0;
}

function getNSTitle ( ns )         // returns namespace name matching the number
{
    return mapNumtoNS[ns];
}

function getTitleFromURL ( url )   // gets "title=" part from a link
{
     var ma = url.match ( /[?&]title=([^&]+)/ );
     return ma ? decodeURIComponent(ma[1]).replace(/_/g," ") : "";
}

function zeroes ( num, twoDigits )           // 0 <= num <= 9999
{
    if ( twoDigits ) return num < 10 ? "0" + num : num.toString();   // 5 -> "05"
     else return "000".concat(num).substr(num.toString().length-1);  // 5 -> "0005"
}

this.init = function initCustomizeWLRC()
{
 try {
    if ( document.getElementsByClassName("mw-enhanced-rc")[0] ) return;    // don't work with enhanced last changes or enhanced watch list

    content = document.getElementById("bodyContent");
    var nsSelectList = document.getElementById("namespace");
    if ( !content || !nsSelectList ) return;

//--- init variables and constants ---
    patroller = content.getElementsByClassName("unpatrolled")[0];          // for a patroller, the legend includes an unpatrolled mark

    mapNumtoNS[0] = "";
    for ( var i = 2 ; i < nsSelectList.options.length ; i++ )
    {
        mapNStoNum[nsSelectList.options[i].text] = i - 1;
        mapNumtoNS[i - 1] = nsSelectList.options[i].text;
    }

    point = nsSelectList.form.parentNode.firstChild;                            // find insertion point:
    while ( point && point.nodeName != "A" ) point = point.nextSibling;         // find first link
    while ( point && point.nodeName != "BR" ) point = point.nextSibling;        // find the next breakline
    if ( !point ) throw ( "cannot find insertion point." );

//--- add an "only new" link to RC/WL ---
    var link = addLink ( "listOnlyNew", "javascript:void()", msg.onlynew, msg.onlynew_t );   // create "only new" link
    if ( wgCanonicalSpecialPageName == "Watchlist" )                                         // in WatchList page:
    {
        link.onclick = onlyNewEntries;                                                       // function will react to mouse click and
        link.onmousedown = onlyNewEntries;                                                   // to middle click
    }
     else                                                                                    // in LastChanges page:
    {
         for ( var item = point.parentNode.lastChild ; item ; item = item.previousSibling )  // find "display changes from" link
             if ( item.nodeName == "A" && item.href.indexOf("&from=") != -1 )
             {
                 link.href = item.href;                                                      // and copy it
                 break;
             }
                                                                                             // delete the link and the text line
         while ( item.previousSibling.nodeName != "BR" ) item.parentNode.removeChild ( item.previousSibling );
         item.parentNode.removeChild ( item.previousSibling )
         item.parentNode.removeChild ( item );
    }

//--- scan lines and mark them by type + mark history links. exit if there are no lines ---
    linesNum = markLinesAndHistoryLinks();
    if ( linesNum == 0 ) return;

//--- change RC/WL options and links, add new links, write CSS info ---
    addLink ( "wlrcAddWatchLinks", "javascript:customizeWLRC.addWatchLinks()", "x", msg.watchUnwatchTitle );    // watch/unwatch links

    if ( linesNum == 1 ) return;

    startLinkGroup ( msg.sortBy );
    addLink ( "sortbytimeLink", "javascript:customizeWLRC.sortChangesList('time')", msg.sortByTime, msg.sortByTime_t );
    addLink ( "sortbygrouptimeLink", "javascript:customizeWLRC.sortChangesList('grouptime')", msg.sortByGroupTime, msg.sortByGroupTime_t );
    addLink ( "sortbypageLink", "javascript:customizeWLRC.sortChangesList('page')", msg.sortByPage, msg.sortByPage_t );
    addLink ( "sortbyuserLink", "javascript:customizeWLRC.sortChangesList('user')", msg.sortByUser, msg.sortByUser_t );
    endLinkGroup();
    markSortLink ( true );

    if ( !getParamValue("patrolMode") && content.getElementsByTagName("H4").length > 1 )
        addLink ( "wlrcMergeLink", "javascript:customizeWLRC.mergeChangesLists()", msg.mergeChanges, msg.mergeChanges_t );

    startLinkGroup ( msg.hideActions_t );

    if ( content.getElementsByClassName("nontopedit")[0] )
        addLink ( "wlrcFilterNontop", "javascript:customizeWLRC.toggleFilter('wlrcFilterNontop','nontopedit',0)", msg.nontopEdits );

    if ( patroller && !getParamValue("patrolMode") && content.getElementsByClassName("patrolledaction")[0] && content.getElementsByClassName("unpatrolledaction")[0] )
        addLink ( "wlrcFilterPatrolled", "javascript:customizeWLRC.toggleFilter('wlrcFilterPatrolled','patrolledaction',0)", msg.patrolledactions );

    if ( content.getElementsByClassName("talkpageaction")[0] )
        addLink ( "wlrcFilterTalkPage", "javascript:customizeWLRC.toggleFilter('wlrcFilterTalkPage','talkpageaction',0)", msg.talkpageactions );

    if ( !getParamValue("patrolMode") && content.getElementsByClassName("editaction")[0] && content.getElementsByClassName("logaction")[0] )
    {
        addLink ( "wlrcFilterLogAction", "javascript:customizeWLRC.toggleFilter('wlrcFilterLogAction','logaction',0)", msg.logactions );
        addLink ( "wlrcFilterEditAction", "javascript:customizeWLRC.toggleFilter('wlrcFilterEditAction','editaction',0)", msg.editactions );
    }

    endLinkGroup();

    appendCSS (".topedit .hist { font-weight:bold; } .nontopedit .hist { margin-left:2px; margin-right:2px; }");

//--- sort the lists, if needed ---
    if ( getParamValue("sortWLRC") ) customizeWLRC.sortChangesList ( getParamValue("sortWLRC") );
  }
 catch(e)
  {
    return;        // lets just ignore what's happened
  }
}
} // --- end of customizeWLRC wrapper object ---

if ( wgCanonicalSpecialPageName == "Recentchanges" || wgCanonicalSpecialPageName == "Watchlist" ) $( customizeWLRC.init );



if ( mw.config.get('wgCanonicalSpecialPageName') === 'Watchlist' ) $( function() { $('strong.mw-watched').children().unwrap(); } );