Eric J.
Eric J.

Reputation: 150138

GreaseMonkey jQuery Script only Affects One Element

My company uses a web-based product whose UI requires us to click more than 200 checkboxes for some use cases. We have requested an "uncheck all" feature, but it is apparently not forthcoming.

I tried to write a simple GreaseMonkey script to solve the problem:

$('img').click(function() {
    $('input.HideQuestion:checked').each(function() {
        $(this).click();
    });
});

(There's one image, our logo, on the page that I use as a click target)

The trouble is, each time I click the image, only one (of the ~270) checkboxes is affected. Each additional click affects the next checkbox.

I can see that the website makes an Ajax call each time a checkbox is checked, but the response body of that Ajax call is empty so I presume they are just updating state on the server rather than replacing part of the page.

Why might only one checkbox end up getting unchecked?

When I use the alternative approach

$(this).prop("checked", true);

All checkboxes are visually unchecked, but the Ajax calls do not happen and server state is never updated. Additionally, when I check any checkboxes, all checkboxes are reverted to the pre-GreaseMonkey state.

UPDATE

I tried both of the following suggested by @BrockAdams to intercept the Ajax call. Neither alert() is being called.

Override XMLHttpRequest.prototype.open https://stackoverflow.com/a/7778218/141172

(function() {
    var proxied = window.XMLHttpRequest.prototype.open;
    window.XMLHttpRequest.prototype.open = function() {
        alert('A-ha! Open!');
        return proxied.apply(this, [].slice.call(arguments));
    };
})();

Intercept the target page's AJAX using .ajaxSuccess()
https://stackoverflow.com/a/8252726/141172

// Also tried: unsafeWindow.$('body').ajaxSuccess (
$('body').ajaxSuccess ( 
        function (event, requestData)
        {
            alert('A-ha.  Success!');
        }
    );  

Upvotes: 1

Views: 254

Answers (2)

Brock Adams
Brock Adams

Reputation: 93533

We really need to see the target page's JS code for this. But, it sounds like the target page is waiting for an AJAX response and then setting internal states. It also may be overwriting the local state with a state maintained by the server.

If that's true, then you need to wait for a server response after every uncheck, or perhaps the target page's javascript might provide a better solution.

Pending more details from you (especially whether the target page uses jQuery for this particular AJAX), here is a general approach that should work:

  1. Use $('input.HideQuestion:checked').each() to populate a jQuery queue.

  2. Intercept the target page's AJAX using .ajaxSuccess() if possible. Or by overriding XMLHttpRequest.prototype.open, if it isn't.

  3. On each successful AJAX completion, dequeue the next item, if any, remaining in the queue from step 1.

    Setup the dequeue function to uncheck its matching checkbox.

Upvotes: 2

Ram
Ram

Reputation: 144699

Try this:

$('img').click(function() {
    $('input[type="checkbox"]:checked').prop('checked', false)
});

Upvotes: 0

Related Questions