在AJAX驱动的站点上select并激活正确的控件

所以,我试图在每次访问任何nike.com运动鞋页面(没有HTML链接)的时候,它会自动挑选我的鞋子尺寸,将其添加到购物车,并检查出我。

我目前正在尝试使用这个脚本(下面),但每次去运动鞋页面,它不会正确添加我想要的鞋子尺寸,但只是直接结账,没有在我的购物车。

我被告知我需要将代码与实际的页面HTML相匹配,但是我不知道该怎么做。 请帮忙。

// ==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); } 

链接到“目标页面”
目标HTML的快照 (如果目标页面被Nike删除或更改)

我希望能够简单地概述如何使用Greasemonkey / Tampermonkey来编写这些页面和动作脚本。

步骤是:

  1. 仔细记下你手动做了什么。 特别注意由页面的javascript添加/更改的元素,以及所需的步骤顺序(如果有的话)。

  2. 使用Firebug和/或Firefox的检查员和/或Chrome的开发人员工具 ,确定所有您将阅读或操作的元素的CSS / jQueryselect器。 使用Firebug特别容易。

  3. 使用jQuery来操作静态HTML。 使用waitForKeyElements来处理由javascript(AJAX)添加或更改的节点。 使用Greasemonkey API (Tampermonkey也支持,部分受Chrome用户脚本支持)可以执行任何跨域页面调用,或者在页面加载之间存储跨页面集合之间的任何值。



具体例子:

  1. 对于OP的目标页面 ,OP想要:(a)自动select鞋子尺寸,(b)将鞋子添加到购物车,以及(c)点击结账button。

    这需要等待和/或点击五(5)个页面元素,如下所示:

    设置大小

    查看

  2. 使用Firebug(或类似的工具),我们获得关键节点的HTML结构。 例如, SIZE下拉菜单有这样的HTML:

     <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> 

    链接实际上引发了一个mousedown事件,而不是点击。

    Firebug给我们提供了一个CSSpath:

     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 

    我们可以削减到:

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

    对于一个合理的select器来说,这个select器很可能在页面变化不大的情况下继续存在,不太可能在不需要的页面/

    ~~~~~~~~~~~~~
    请注意,Firebug还可以帮助我们了解哪些事件与什么有关,在确定我们需要触发哪些事件时至关重要。 例如,对于那个节点,我看到:

    Events for key first node

    该链接没有href ,也没有听click事件。 在这种情况下,我们必须触发mousedown (或keydown )。

    ~~~~~~~~~~~~~
    对其他4个关键节点使用类似的过程,我们获得了以下CSS / jQueryselect器:

     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. 最后,我们使用waitForKeyElements将所需的事件发送到关键节点,并按照正确的操作顺序进行sorting。

结果完整的工作脚本是:

 // ==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); }