Shawn
Shawn

Reputation: 185

Novice/Beginner Javascript Request

HTML code:

<td>
<img src="../images/items/333.png"><br>
<b>Product One</b><br>
(2 in stock)<br>
<i>65 USD</i><br>
<form action="shopping.php?shop=1&amp;item=333&amp;price=65&amp;buy=conf&amp;type=" method="post">
<input name="" value="Buy this item" type="submit">
</form></td>

<td>
<img src="../images/items/444.png"><br>
<b>Product Two</b><br>
(4 in stock)<br>
<i>5 USD</i><br>
<form action="shopping.php?shop=1&amp;item=444&amp;price=5&amp;buy=conf&amp;type=" method="post">
<input name="" value="Buy" type="submit">
</form></td>

This is the html code on the page I'm working on, the html code cannot be altered.
There are several td tags on the page which contains the following information you see in the code above.



I would like to write a script that would do something like this:

if (document.body.innerHTML.indexOf("Product One") > -1) {
document.location = "shopping.php?shop=1&amp;item="+itemID+"&amp;price="+USD+"&amp;buy=conf&amp;type="
}

Search the body/td of the page for the "Product Name" specified in my script, and then if it's found, go to the url that contains variables that need to be extracted, itemID and USD.

itemID is extracted from the src of the image.png by taking the numbers. For example, the itemID of ../images/items/444.png is 444.

USD is extracted from the price defined between the italics tags. For example the extracted value for USD for<i>5 USD</i> would be 5.



Catch is

I would need a lot of if (document.body.innerHTML.indexOf("Name") > -1) {document.location = "shopping.php?shop=1&amp;item="+itemID+"&amp;price="+USD+"&amp;buy=conf&amp;type="} to cater to the large number of products I would specify. I might want to specify "Product One to Hundred" and "Sub-product A to Z"



Solution

Some ways I thought of to handle this (needs to be put into javascript code) is to:

  1. Put list of products I will specify into an array (something like) var list = new Array ("Product One","Product Two","Sub-Product A"); and have a function check the page for the presence of any product from this array that displays on the page.
  2. When the product is found, to get the itemID, isolate the numbers before .png and after /items/ from the image src of the product. And to get USD, get the value between the <i> </i> tags and only take the numerical values
  3. To do this I think nextSibling or previousSibing can be used, but I'm not too sure about that.
  4. Alternatively, to make it easier, there could be a function to immediately locate the form's action value and set the window.location since <form action="shopping.php?shop=1&amp;item=444&amp;price=5&amp;buy=conf&amp;type=" method="post">
  5. I've seen this done before using XPath?

Upvotes: 3

Views: 212

Answers (2)

Brock Adams
Brock Adams

Reputation: 93473

This is not difficult using jQuery -- especially if we extend it to search for case-insensitive, regular expressions.

The following script should work with the HTML structure from the question, if it is precisely accurate and not added by AJAX. Note the power that regular expressions give when targeting product descriptions.

You can see the underlying code at work at jsFiddle.

// ==UserScript==
// @name     _Auto-follow targeted product links.
// @include  http://YOUR_SERVER.COM/YOUR_PATH/*
// @require  http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// ==/UserScript==

var targetList  = [
    "Shoes, pumps",
    "Horse shoes",
    "(?:Red|Pink|Burgundy)\\s+shoes?"
];

/*--- Extend jQuery with a case-insensitive version of contains().
    Also allows regular expressions.
*/
jQuery.extend (
    jQuery.expr[':'].containsCI = function (a, i, m) {
        //--- The next is faster than jQuery(a).text()...
        var sText   = (a.textContent || a.innerText || "");     

        var zRegExp = new RegExp (m[3], 'i');

        return zRegExp.test (sText);
    }
);

$.each (targetList, function (index, value) { 
    var jqSelector          = 'td > b:containsCI("' + value + '")';
    var productFound        = $(jqSelector);
    if (productFound.length) {
        var matchingForm    = productFound.first ().nextAll ("form");
        if (matchingForm.length) {
            alert (productFound.text () );
            document.location   = matchingForm.attr ("action");
        }
    }
} );

Upvotes: 2

Tomalak
Tomalak

Reputation: 338198

Here is a solution that does not rely on external libraries like jQuery:

function findProducts(referenceList) {  
  var productsOnPage = {}, listMatches = {},
      tds = document.getElementsByTagName("TD"),
      bold, form, i, productName, productUrl;

  // build an index of products on the page (HTML scraping)
  for (i = 0; i < tds.length; i++) {
    bold = tds[i].getElementsByTagName("B")[0];
    form = tds[i].getElementsByTagName("FORM")[0];

    if (bold && form) {
      productName = bold.innerHTML.toLowerCase();
      productUrl  = form.action;

      productsOnPage[productName] = productUrl;
    }
  }

  // match reference list against all available products on the page
  for (i = 0; i < referenceList.length; i++) {
    productName = referenceList[i].toLowerCase();
    productUrl  = productsOnPage[productName];

    listMatches[productName] = productUrl;
  }

  return listMatches;
}

Call it:

var availableProducts = findProducts(["Product One","Product Two","Sub-Product A"]);

After that you'd have an object availableProducts that's looking like this:

{
  "product one": "shopping.php?shop=1&item=333&price=65&buy=conf&type=",
  "product two": "shopping.php?shop=1&item=444&price=5&buy=conf&type=",
  "sub-product a": undefined
}

Note that all keys are lower case to make string comparisons consistent. To look up a product you would use

function navigateIfAvailable(productName) {
  var url = availableProducts[productName.toLowerCase()];

  if (url) document.location = url;
}

Now

navigateIfAvailable("Product Two");

would go somewhere. Or not.

Upvotes: 1

Related Questions