Clicking a button on a page using a Greasemonkey/userscript in Chrome

10,438

Note:

  1. jQuery .click() does not work reliably on click events that were not set via jQuery in the first place.

  2. You need to create the right kind of event; createEvent('Events') is not the way.

  3. As Jim Deville pointed out, the link pseudo-button was not being selected.

  4. You do not need jQuery for this (so far).

  5. Make sure that the "Refresh" control is loaded statically for the test code as shown in the question. If it's AJAXed in, the click attempt may fire too soon.

Putting that all together, the following code should work. But beware that some sites (like certain Google apps) use funky, state-sensitive designs -- which require a sequence of events.

var refreshBtn = document.querySelector (
    "div.serverguide-header-refresh-button div[type='reset'] a"
);
var clickEvent = document.createEvent ('MouseEvents');
clickEvent.initEvent ('click', true, true);
refreshBtn.dispatchEvent (clickEvent);
Share:
10,438
HittingSmoke
Author by

HittingSmoke

Updated on July 06, 2022

Comments

  • HittingSmoke
    HittingSmoke almost 2 years

    I'm going to be as absolutely verbose here as possible as I've run into a few solutions that didn't end up panning out. Please keep in mind that I don't know Javascript. I know basic HTML and CSS. I don't have any actual programming background but I'm trying to learn bit by bit by researching basic tasks like this. Please talk to me like I'm an idiot. Any lingo I throw around in this post I learned while researching this specific issue. I'm writing this userscript as a personal project and to share with some friends.

    What I'm trying to do.

    I'm trying to write a userscript for Chrome/Greasemonkey (Chrome is my target browser) that will click the Refresh button on the Battlefield 3 server browser. For those of you that don't know, Battlefield 3 uses a web site paired with a browser plugin for VOIP and actually launching the game via a server browser. The bulk of it seems to be fairly straight forward HTML arranged in tables.

    The idea is that when viewing the main page for a server that is full, the script will click the Refresh button every three seconds or so until the page reports an open spot on the server, then stop the refresh loop and click the join server button. I've already got the part of the script running that polls the server current and maximum players then assigns them to their own variables.

    At this point I'm trying to get a click to work in the console so I can actually put it to some use in my script and am having zero luck.

    The code I'm trying to manipulate.

    This is the div for the button that I'm trying to click pulled from the Chrome dev tools:

    <div class="serverguide-header-refresh-button alternate show"> 
    <div type="reset" class="common-button-medium-grey">
    <p style="position: relative;">
    <a href="/bf3/servers/show/c7088bdc-2806-4758-bf93-2106792b34d8/">Refresh </a>
    </p>
    </div>
    </div>
    

    (That link is not static. It's a link to a specific server page)

    What I've tried.

    To actually find the button I'm using getElementsByClassName. It doesn't have a unique ID but the class is unique to that element on this particular page so getElementsByClassName("serverguide-header-refresh-button")[0] is pulling the proper div each time. It's getting the script to perform any actual action on the button that's the problem.

    document.getElementsByClassName("serverguide-header-refresh-button")[0].click();
    

    I now realize this didn't work because it's not a conventional submit button. I don't understand the specifics of the standard here but I get that it doesn't support the .click() method.

    function addJQuery(callback) {
      var script = document.createElement("script");
      script.setAttribute("src", "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js");
      script.addEventListener('load', function() {
        var script = document.createElement("script");
        script.textContent = "(" + callback.toString() + ")();";
        document.body.appendChild(script);
      }, false);
      document.body.appendChild(script);
    }
    
    // the guts of this userscript
    function main() {
      unsafeWindow.jQuery('.serverguide-header-refresh-button')[0].click();
    }
    
    // load jQuery and execute the main function
    addJQuery(main);
    

    This is simply unsafeWindow.jQuery('.serverguide-header-refresh-button').click(); wrapped in some code to load jQuery for userscripts. It was a bit I picked up elsewhere but was told it would only work if jQuery was loaded on the page. I figured it was worth a try. This is one of those I have no idea what I'm doing shots in the dark and it didn't work. I tried the same thing below with another snippet of jQuery code I picked up:

    function addJQuery(callback) {
      var script = document.createElement("script");
      script.setAttribute("src", "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js");
      script.addEventListener('load', function() {
        var script = document.createElement("script");
        script.textContent = "(" + callback.toString() + ")();";
        document.body.appendChild(script);
      }, false);
      document.body.appendChild(script);
    }
    
    // the guts of this userscript
    function main() {
       var evObj = document.createEvent('Events');
          evObj.initEvent("click", true, false);
          document.getElementsByClassName('serverguide-header-refresh-button')[0].dispatchEvent(evObj);
    }
    
        // load jQuery and execute the main function
    addJQuery(main);
    

    Both of these return Undefined in the Chrome and Firebug consoles.

    So, would anyone be so kind as to help me create a bit of code for this script to press the Refresh button on this page?