1

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!');
        }
    );  
Community
  • 1
  • 1
Eric J.
  • 147,927
  • 63
  • 340
  • 553
  • _All checkboxes are visually unchecked_ You are setting the checked property to `true`, this checks all of the checkboxes,it doesn't uncheck them. – Ram Aug 24 '12 at 00:35
  • @undefined: Yes I know. Wanted to mention that I also tried (but discarded) that approach. – Eric J. Aug 24 '12 at 00:45
  • This is a better approach than triggering click event more that 200 times. – Ram Aug 24 '12 at 00:49
  • I assume only the **last** checkbox is getting unchecked? This is a case that could really use an analysis of the target page's JS. Is it using jQuery to do the AJAX? Save a complete page to disk, zip it and post it to pastebin or similar. – Brock Adams Aug 24 '12 at 00:58
  • Important tangent: Don't add "mystery meat" controls, even if it's just for your own use (and assuming nothing clandestine is going on). Go ahead and add an "uncheck all" button. Don't add unrelated click handlers to the only (for now) image on the page! The headscratch you save, may be your own. – Brock Adams Aug 24 '12 at 01:37
  • @BrockAdams: Good point. This is my first GreaseMonkey script so I used the IMG tag to just get it working. – Eric J. Aug 24 '12 at 01:56

2 Answers2

2

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.

Community
  • 1
  • 1
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • Unfortunately the app in question is proprietary. Your approach sounds interesting. However, I cannot seem to implement 2. Posted my three attempts. Do you see a problem with the cod? – Eric J. Aug 24 '12 at 02:23
  • `unsafeWindow.$('body').ajaxSuccess()` would work, but only if the target page used jQuery (and normally) for its AJAX. Does it? ... The `XMLHttpRequest.prototype.open` method is not the way I do it, but it *should* work (untested), **IF, and only if**, you inject the override code into the target page. Also, for your purposes, you would need to listen for `status` `200` from the response. – Brock Adams Aug 24 '12 at 02:33
  • See http://stackoverflow.com/a/6805461/ for one implementation of the generic AJAX-intercept approach, from Greasemonkey. – Brock Adams Aug 24 '12 at 02:39
0

Try this:

$('img').click(function() {
    $('input[type="checkbox"]:checked').prop('checked', false)
});
Ram
  • 143,282
  • 16
  • 168
  • 197
  • Unfortunately that doesn't "stick", as in the page has some state that gets reset after I click any checkbox. Plus, the UI design is such that the page only refreshes when a checkbox is checked/unchecked (yuck). There is not "refresh" button. Clicking the browser refresh button restores the check state that is stored server side. – Eric J. Aug 24 '12 at 01:59