17

So, I am trying to make it where every time I visit any nike.com sneaker page (without the HTML link), it automatically picks my shoe size, adds it to the cart, and checks out for me.

I am currently trying to use this script (below), but every time I go to the sneaker page, it does not properly add the shoe size I want, but just goes straight to checkout with nothing in my cart.

I'm told that I need to match the code to the actual page HTML, but I don't know how to do that. Please help.

// ==UserScript==
// @name     _Nike auto-buy(!!!) script
// @include  http://*/*
// @require  http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant    GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/

var okayToClickAddtoCart = false;

//-- Assumes that size is a standard <option> tag or similar...
waitForKeyElements (".selectBox-label[value='10']", selectShoeSize);

function selectShoeSize (jNode) {
    jNode.prop ('selected', true);

    okayToClickAddtoCart = true;
}


waitForKeyElements (".add-to-cart.nike-button", clickAddToCart);

function clickAddToCart (jNode) {
    if ( ! okayToClickAddtoCart) {
        return true;    //-- Don't click yet.
    }

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


waitForKeyElements (".checkout-button", clickCheckoutButton);

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


Link to the "target page"
Snapshot of the target HTML (in case the target page is removed or changed by Nike)

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
Nite
  • 268
  • 1
  • 4
  • 12
  • `.selectBox-label[value='10']` is a jQuery selector. It apparently does not match the HTML of the actual page. Disable the script, Browse to the page, Save the page from Firefox (**Ctrl** + **S**) as "Targetpage.htm", then upload that file (`Targetpage.htm`) to http://pastebin.com/ and link to the pastebin from your question. Then we can help you tune your jQuery selector(s). – Brock Adams Feb 24 '13 at 03:23
  • Here is the targetpage, http://pastebin.com/6M7cMw40 – Nite Feb 24 '13 at 03:31
  • Here is the test page (targetpage) http://store.nike.com/us/en_us/?l=shop,pdp,ctr-inline/cid-1/pid-656545/pgid-656543 – Nite Feb 24 '13 at 03:54
  • Okay, thank you I very much appreciate it. So, once you have figured out the code will it work on any Nike sneaker page, or just that one? As I want it to work on every nike.com sneaker page without knowing the pre-defined HTML link(s). – Nite Feb 24 '13 at 04:00
  • It should work on every shoe page with the same basic HTML. Also, note that SO is not a script writing service. But I noticed that there wasn't any one question I could point a beginner to to explain the process for this kind of page. – Brock Adams Feb 24 '13 at 04:03
  • I know that, it's just that I didn't know where to start, but I really honestly do appreciate you helping me with this! If you have a Paypal I can donate to, I will gladly do so. – Nite Feb 24 '13 at 04:06
  • Have you figured out how to do it? Sorry, if I am a bother. I just want to know the progress of it. Thanks once again! – Nite Feb 24 '13 at 10:03
  • Awesome. Okay, sounds good to me. I appreciate you doing this even though you don't have to. – Nite Feb 24 '13 at 10:13

1 Answers1

31

Rather than just alter the script from the question, I hope to make a quick outline of how to script these kinds of pages and actions with Greasemonkey/Tampermonkey.

The steps are:

  1. Take careful note of what you do manually. Take special note of elements added/altered by the page's javascript, and the needed sequence of steps, if any.

  2. Using Firebug, and/or Firefox's inspector, and/or Chrome's Developer tools, determine CSS/jQuery selector's for all of the elements you will read or manipulate. This is especially easy to do using Firebug.

  3. Use jQuery to manipulate static HTML. Use waitForKeyElements to handle nodes added or changed by javascript (AJAX). Use the Greasemonkey API -- which is also supported by Tampermonkey and partially supported by Chrome userscripts -- to do any cross-domain page calls, or to store any values between page loads for cross-domain sets of pages.



Specific example:

  1. For the OP's target pages, the OP wants to: (a) automatically select the shoe size, (b) add the shoes to the shopping cart, and (c) click the checkout button.

    This requires waiting for, and/or clicking on, five (5) page elements like so:

    Set the size

    Check out


  2. Using Firebug (or similar tool) we obtain the HTML structure for the key nodes. For example, the SIZE dropdown has HTML like this:

    <div class="size-quantity">
        <span class="sizeDropdown selectBox-open">
            ...
            <label class="dropdown-label selectBox-label-showing">SIZE</label>
            ...
            <a class="selectBox size-dropdown mediumSelect footwear selectBox-dropdown" ...>
                ...
            </a>
        </span>
    </div>
    

    Where the link actually fires off a mousedown event, not a click.

    Firebug gives us a CSS path of:

    html.js body div#body div#body-wrapper.fullheight div#body-liner.clear div#content div#pdp.footwear div#product-container.clear div.pdp-buying-tools-container div.pdp-box div.buying-tools-container div#PDPBuyingTools.buying-tools-gadget form.add-to-cart-form div.product-selections div.size-quantity span.sizeDropdown a.selectBox
    

    Which we can pare down to:

    div.footwear form.add-to-cart-form span.sizeDropdown a.size-dropdown
    

    for a reasonable selector that's likely to survive trivial page changes and unlikely to trigger on unwanted pages/products.

    ~~~~~~~~~~~~~
    Note that Firebug also helps us see what events are attached to what, which is crucial when determining what we need to trigger. For example, for that node, I see:

    Events for key first node

    That link has no href, nor does it listen for click events. In this case, we must trigger a mousedown (or keydown).

    ~~~~~~~~~~~~~
    Using a similar process for the other 4 key nodes, we obtain CSS/jQuery selectors of:

    Node 1:     div.footwear form.add-to-cart-form span.sizeDropdown a.size-dropdown
    
    Node 2:     ul.selectBox-dropdown-menu li a:contains('10')
                (But this will need an additional check)
    
    Node 3:     div.footwear form.add-to-cart-form span.sizeDropdown a.selectBox span.selectBox-label:contains('(10)')
    
    Node 4:     div.footwear form.add-to-cart-form div.product-selections div.add-to-cart
    
    Node 5:     div.mini-cart div.cart-item-data a.checkout-button:visible
    


  3. Finally, we use waitForKeyElements to send the required events to the key nodes and to sequence through the proper order of operations.

The resulting, complete, working script is:

// ==UserScript==
// @name     _Nike auto-buy shoes(!!!) script
// @include  http://store.nike.com/*
// @include  https://store.nike.com/*
// @require  http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant    GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/

var targetShoeSize  = "10";

//-- STEP 1:    Activate size drop-down.
waitForKeyElements (
    "div.footwear form.add-to-cart-form span.sizeDropdown a.size-dropdown",
    activateSizeDropdown
);
function activateSizeDropdown (jNode) {
    triggerMouseEvent (jNode[0], "mousedown");

    //-- Setup step 2.
    waitForKeyElements (
        "ul.selectBox-dropdown-menu li a:contains('" + targetShoeSize + "'):visible",
        selectDesiredShoeSize
    );
}

//-- STEP 2:    Select desired shoe size.
function selectDesiredShoeSize (jNode) {
    /*-- Because the selector for this node is vulnerable to false positives,
        we need an additional check here.
    */
    if ($.trim (jNode.text () ) === targetShoeSize) {
        //-- This node needs a triplex event
        triggerMouseEvent (jNode[0], "mouseover");
        triggerMouseEvent (jNode[0], "mousedown");
        triggerMouseEvent (jNode[0], "mouseup");

        //-- Setup steps 3 and 4.
        waitForKeyElements (
            "div.footwear form.add-to-cart-form span.sizeDropdown a.selectBox "
            + "span.selectBox-label:contains('(" + targetShoeSize + ")')",
            waitForShoeSizeDisplayAndAddToCart
        );
    }
}

//-- STEPS 3 and 4: Wait for shoe size display and add to cart.
function waitForShoeSizeDisplayAndAddToCart (jNode) {
    var addToCartButton = $(
        "div.footwear form.add-to-cart-form div.product-selections div.add-to-cart"
    );
    triggerMouseEvent (addToCartButton[0], "click");

    //-- Setup step 5.
    waitForKeyElements (
        "div.mini-cart div.cart-item-data a.checkout-button:visible",
        clickTheCheckoutButton
    );
}

//-- STEP 5:    Click the checkout button.
function clickTheCheckoutButton (jNode) {
    triggerMouseEvent (jNode[0], "click");

    //-- All done.  The checkout page should load.
}

function triggerMouseEvent (node, eventType) {
    var clickEvent = document.createEvent('MouseEvents');
    clickEvent.initEvent (eventType, true, true);
    node.dispatchEvent (clickEvent);
}
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • 1
    Brock you're awesome, it works flawlessly! Again, if you have Paypal, I would love to donate to you! – Nite Feb 24 '13 at 18:11
  • 3
    You're welcome. You can donate [to Adblock Plus](https://addons.mozilla.org/en-US/firefox/addon/adblock-plus/?src=userprofile#contribution) or [to the *Electronic Frontier Foundation* (EFF)](https://supporters.eff.org/donate) in my name if you wish. The Adblock guy is also a generous and knowledgeable instructor of extension development. – Brock Adams Feb 24 '13 at 23:13