Question

This script assists in a checkout process at an online store. All is working correctly, except the need to refresh the page to get the program to run initially.

I wonder if it is a cache problem because it works on other products that have been previously viewed. I also tried tinkering with the @run-at to no avail. I'm using the Scriptish extension and it is a standalone .js file.

// ==UserScript==
// @id             proper-id
// @name           proper-name
// @version        1.0
// @namespace      
// @description    
// @include        proper-url-here
// @include about:blank
// @run-at window-load
// ==/UserScript==

for (var i=0; i<document.getElementsByName("skuAndSize")[0].length; i++){
    if(document.getElementsByName("skuAndSize")[0].options[i].text == 11) {
        document.getElementsByName("skuAndSize")[0].selectedIndex = i;
    }
}
document.getElementsByClassName("button-container add-to-cart")[0].click();

Why does this userscript only run on refresh?

Was it helpful?

Solution

This is a classic problem with pages that change their content via AJAX.
@run-at has no effect because the targeted content is loaded long after the window load event. And, "new" pages are really complete rewrites via AJAX -- until you refresh the page, at least.

Change the script to @run-at document-end (or omit the line) and then, depending on the target page and how you are using it, it may be enough to fire off of hashchange as shown on "I have to refresh the page for my Greasemonkey script to run?" or as shown on this other answer.

The go to tool is waitForKeyElementsMore info, however. Your script might be as simple as:

// ==UserScript==
// @name     _YOUR_SCRIPT_NAME
// @include  http://YOUR_SERVER.COM/YOUR_PATH/*
// @require  http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js
// @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
// ==/UserScript==

waitForKeyElements ("[name='skuAndSize']", setSizeIndex);
waitForKeyElements (".button-container.add-to-cart", clickAddToCart);

function setSizeIndex (jNode) {
    var node    = jNode[0];
    for (var J = node.options.length - 1;  J >= 0;  --J) {
        if (node.options[J].text == "11") {
            node.selectedIndex = J;
            break;
        }
    }
}

function clickAddToCart (jNode) {
    var clickEvent  = document.createEvent ('MouseEvents');
    clickEvent.initEvent ('click', true, true);
    jNode[0].dispatchEvent (clickEvent);
}


See, also, "Choosing and activating the right controls on an AJAX-driven site".

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top