Forceflow
Forceflow

Reputation: 37

My script will run in the console, but I can not get it to run in Greasemonkey

I'm about to rip my hair out with this. This code will execute just fine in the browser console, but it simply will not run with Greasemonkey or Tampermonkey. I've tried them both and I'm out of ideas as to what could be wrong.

ADDENDUM FOR CLARIFICATION: As this is written below, I don't receive any errors specific to the script or greaskmoney/tampermonkey. I have tried to use waitforKeyElements, but that didn't seem to make any difference. A simple alert will fire, so I'm sure that whatever the error is, it seems specific to the javascript.

For reference, I found the code here.

Thanks in advance.

// ==UserScript==
// @name            name
// @description     description
// @version         1
// @author          me
// @match           https://*.robertsspaceindustries.com/spectrum/community/SC/forum/*
// @icon            https://i.imgur.com/km9uoYJ.png
// ==/UserScript==

function hexToRgb(hex) {
  // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
  var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  hex = hex.replace(shorthandRegex, function(r, g, b) {
    return r + r + g + g + b + b;
  });

  var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result ? "rgb(" + [
    parseInt(result[1], 16),
    parseInt(result[2], 16),
    parseInt(result[3], 16)
  ].join(', ') + ")" : null;
}

// Function to change a color to another one
function colorChange(colorOld, colorNew, strict = false) {
  // If hex notation, convert to rgb
  if (colorOld.includes('#'))
    colorOld = hexToRgb(colorOld);
  // Loop through all elements styles
  [...document.getElementsByTagName('*')].forEach(elm => {
    let cStyle = getComputedStyle(elm);
    [...cStyle].forEach(prop => {
      // Escape if not a string
      if (typeof cStyle[prop] !== 'string') return;
      // Check if colorOld is in property
      if (cStyle[prop].includes(colorOld)){
        // If strict, colorOld is replaced only if it's the only value of the property
        if (!strict || cStyle[prop] === colorOld)
          elm.style[prop] = cStyle[prop].replace(colorOld, colorNew); // Replace color
      }
    })
  })
};

// function () {
//   colorChange('#182436', '#ff0000');
//   console.log('colorChange has run.');
// };

colorChange('#182436', '#ff0000');

Upvotes: 1

Views: 1046

Answers (2)

Human programmer
Human programmer

Reputation: 504

I had the same problem with Tampermonkey, but only on Chrome. In Firefox the script executes without problems. There are 2 reasons for this.
One is that it appears that below meta tag is required on Chrome, but not on Firefox and the script won't even start without it on Chrome:

// @run-at document-end

You can also change the document-end to for example document-start, if you want the script to be executed sooner.

Second reason why the script didn't execute was that I had to enable developer mode for extensions in the browser for some reason. Go to chrome://extensions/ and in top right corner enable "Developer mode".

Upvotes: 0

cssyphus
cssyphus

Reputation: 40106

The most common problem -- and what waitForKeyElements and/or MutationObserver solve -- is that the code is trying to run against elements that haven't yet been added to the page. (Remember we are talking microseconds here... the page is often still being rendered as the JavaScript is executing, and some elements might not be ready when the JavaScript expects them to be.) setTimeout, waitForKeyElements and MutationObserver are all ways to delay the JavaScript until the required elements are present.

You can test if waitForKeyElements or MutationObserver are the solution by just wrapping your code in a setTimeout() function.

// ==UserScript==
// @name            name
// @description     description
// @version         1
// @author          me
// @match           https://*.robertsspaceindustries.com/spectrum/community/SC/forum/*
// @icon            https://i.imgur.com/km9uoYJ.png
// ==/UserScript==

(function() {
    'use strict';

    setTimeout( () => {

        colorChange('#182436', '#ff0000');

    }, 10000);  //10-sec delay

})();

function hexToRgb(hex) {
    //etc (removed for brevity)
}

function colorChange(colorOld, colorNew, strict = false) {
    //etc (removed for brevity)
};

setTimeout is the old way to do this, but it still works and it is dead simple to implement. So, wrap your code in a 10 or 20 or 30 second setTimeout and if it runs, you know that waitForKeyElements or MutationObserver are the answer.

But if a 30 or 120 second setTimeout doesn't work, then it's not just a question of waiting for the right elements to be added to the page, there's more going on.

Upvotes: 1

Related Questions