Remove part of title of website via userscript

2020-04-18 09:24发布

问题:

I try to code a userscript that removes everything from the title of a website (flash browsergame) but the countdown that appears when starting an action.

I'm new to Javascript and need some help.

UPDATE

The regexp problem is solved but I still need some help getting this script to "monitor" the title so everytime it's changes by the game the script runs again.

The main title looks like this:

Shakes & Fidget - The Game (buffed buffed)

As soon as an action is started a countdown is added to the beginning so the title changes to

02:26 - Shakes & Fidget - The Game (buffed buffed)

I want the title to show the countdown only.

I searched the net and found different ways to do this but none of them works for me.

Here is what I currently have:

// ==UserScript==
// @name       Shakes & Fidget Buffed title shortener
// @namespace  http://släcker.de
// @version    0.1
// @description  Removes the page title of Shakes & Fidget to only display left time if it exists
// @include        *.sfgame.*
// @exclude        www.sfgame.*
// @exclude        sfgame.*
// @copyright  2013+, slaecker
// ==/UserScript==

var regex = [^0-9:]

function cleanTitle() { 
    var oldTitle = document.title; 
    var oldTitleRX = oldTitle.match(regex);
    document.title = oldTitle.replace(oldTitleRX,""); 
    return oldTitle; 
} 


cleanTitle()

The Javascript console shows errors concerning the regex. I tried to escape the characters but the errors are the same:

env: ERROR: Syntax error @ 'Shakes & Fidget Buffed title shortener'!
Unexpected token ^
SyntaxError: Unexpected token ^
    at Window.Function (<anonymous>)
    at L (eval at <anonymous> (eval at <anonymous> (chrome-extension://dhdgffkkebhmkfjojejmpbldmpobfkfo/content.js:51:21)), <anonymous>:156:21)
    at n (eval at <anonymous> (eval at <anonymous> (chrome-extension://dhdgffkkebhmkfjojejmpbldmpobfkfo/content.js:51:21)), <anonymous>:384:2)
    at R (eval at <anonymous> (eval at <anonymous> (chrome-extension://dhdgffkkebhmkfjojejmpbldmpobfkfo/content.js:51:21)), <anonymous>:388:86)
    at Q (eval at <anonymous> (eval at <anonymous> (chrome-extension://dhdgffkkebhmkfjojejmpbldmpobfkfo/content.js:51:21)), <anonymous>:194:40)
Uncaught SyntaxError: Unexpected token ^
L
n
R
Q

It has to be a regex match because the containing string "(buffed buffed)" changes (it shows the server name).

Another problem is that the script should "monitor" the title because it changes everytime a new action is started or finished but my script only runs once (tested it without regex).

Thanks in advance for your help,

slaecker

回答1:

For the regex, use:

document.title = document.title.replace (/[^0-9:]/g, "");

To detect title changes, use MutationObservers, a new HTML5 feature that is implemented in both Google Chrome and Firefox (The two main userscripts browsers).

This complete script will work:

// ==UserScript==
// @name        Shakes & Fidget Buffed title shortener
// @namespace   http://släcker.de
// @version     0.1
// @description  Removes the page title of Shakes & Fidget to only display left time if it exists
// @include     *.sfgame.*
// @exclude     www.sfgame.*
// @exclude     sfgame.*
// @copyright   2013+, slaecker, Stack Overflow
// @grant       GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/

var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
var myObserver       = new MutationObserver (titleChangeDetector);
var obsConfig        = {
    //-- Subtree needed.
    childList: true, characterData: true, subtree: true
};

myObserver.observe (document, obsConfig);

function titleChangeHandler () {
    this.weInitiatedChange      = this.weInitiatedChange || false;
    if (this.weInitiatedChange) {
        this.weInitiatedChange  = false;
        //-- No further action needed
    }
    else {
        this.weInitiatedChange  = true;
        document.title = document.title.replace (/[^0-9:]/g, "");
    }
}

function titleChangeDetector (mutationRecords) {

    mutationRecords.forEach ( function (mutation) {
        //-- Sensible, Firefox
        if (    mutation.type                       == "childList"
            &&  mutation.target.nodeName            == "TITLE"
        ) {
            titleChangeHandler ();
        }
        //-- WTF, Chrome
        else if (mutation.type                      == "characterData"
            &&  mutation.target.parentNode.nodeName == "TITLE"
        ) {
            titleChangeHandler ();
        }
    } );
}

//-- Probably best to wait for first title change, but uncomment the next line if desired.
//titleChangeHandler ();

If you are using some other browser (state that in the question), then fallback to using setInterval().



回答2:

You have a couple of problems with your regexp literal. It must be wrapped to /-es, it misses a multiplier without which it only matches one character and you need to make it global with the "g" modifier in order to match string parts at both sides of your numbers.

var regex = /[^0-9:]+/g;

function cleanTitle() { 
    document.title = document.title.replace(regex, ""); 
}


回答3:

It looks like your timer/counter has a definite format. Assuming that that the format is ##:##, you could form your RegEx thus:

var regex = /\d\d:\d\d/g;

This will then get the specific timer pattern (rather than any numbers and colons it finds at the beginning of the title).

Don't forget to wrap your regex statement in slashes. Using the g after the forward slash (as indicated above) will find other instances of timers in your title. If you know you only have the one, it might be best to take the g off the end.