0

Question

How do you select text node values identified with a specific attribute (background color #00FF00)?

As I'm new to javascript, I'm not sure how to do the first step:

  1. use the js dom to select the node with 00FF00
  2. split the string with " " as the separator
  3. loop through and add each split[2] with +=
  4. write the sum (240+80+600) to html

Code

<!DOCTYPE html>
<html>
<head>

<script>
window.onload = function() {
    var data  = document.getElementsByTagName('span');
    document.write(data);
};
</script>

</head>
<body>
<div class="box">
<span class="highlight">Dave collected 700 items.</span>
</div>
<div class="box">
<span class="highlight" style="background-color:#00FF00;">Bob collected 240 items.</span>
</div>
<div class="box">
<span class="highlight" style="background-color:#00FF00;">Bob collected 80 items.</span>
</div>
<div class="box">
<span class="highlight" style="background-color:#00FF00;">Bob collected 600 items.</span>
</div>
</body>
</html> 


var els = document.querySelectorAll('span.highlight');
var len = els.length;
//console.log(len); //returns 4
var total = 0;
for (var i=0; i < len; i++) {
    if (els[i].style.backgroundColor.toLowerCase() === 'rgb(0, 255, 0)') {
    var txt = els[i].innerHTML;

    //split txt into array
    split = txt.split(" ");
    total += parseInt(split[2]);
    }
}
console.log(total);
rrrfusco
  • 1,057
  • 3
  • 18
  • 44
  • 2
    Selecting by color is not the easiest thing in the world to do, and it's sort-of a weird thing to do. – Pointy Aug 13 '13 at 15:08
  • Yes. you can use some class to refer your filter. – Deepak Biswal Aug 13 '13 at 15:09
  • maybe if you will explain what are you trying to do we can help you more... just saying i want to do this... and cant get it right means that you want us to solve your problem. not that this bad, but at least give us something to work with. – Liran Aug 13 '13 at 15:15
  • [Don't use `document.write`](http://stackoverflow.com/questions/802854/why-is-document-write-considered-a-bad-practice) – Bergi Aug 13 '13 at 15:23
  • I think you want to select the summed items by `split[0]=="Bob"` rather than selecting the spans by color. – Bergi Aug 13 '13 at 15:25
  • May I ask why you selected this answer? It's way less efficient than mine for many reasons. It's reading styles from the DOM which is slower than accessing the `style` property on the object and it's trying to match the whole style definition, which is slower than simply looking up the style.backgroundColor property. It's also not enforcing good practices, by having multiple `var` statements and relying on `!=` instead of `!==` (doesnt change anything here however). – plalx Aug 14 '13 at 14:24
  • @plalx, post a link to some benchmark or reference. – rrrfusco Aug 14 '13 at 14:28
  • @rrrfusco Looks like I am wrong afterall. The result is surprising http://jsperf.com/colorselector – plalx Aug 14 '13 at 15:02
  • Both answers were similar. Geoff's answer seemed the simpler choice. The number of nodes on the page is small. – rrrfusco Aug 14 '13 at 15:33
  • @rrrfusco I'm still curious about why using `getAttribute` and then indexOf is that much faster than accessing `style.backgroundColor` directly. – plalx Aug 14 '13 at 15:47
  • @Liran I'm trying to dynamically add numbers from html that are fed by long polling. – rrrfusco Aug 27 '13 at 01:53
  • @plalx http://www.javascriptturnsmeon.com/the-new-document-queryselectorall-method-and-the-gotchas-with-it/ – rrrfusco Sep 21 '13 at 22:42

2 Answers2

2

Unless you are trying to scrape the content of another site and have no control over the HTML structure, I would recommend adding an additionnal class or an attribute to these that would ease the selection of these nodes.

However, you could do it like:

var els = document.querySelectorAll('span.highlight'),
    i = 0,
    len = els.length;

for (; i < len; i++) {
    if (els[i].style.backgroundColor.toLowerCase() === '#00ff00') {
        //code
    }
}
plalx
  • 39,329
  • 5
  • 63
  • 83
  • @rrrfusco I doubt it would. Perhaps by using a regex rather than querying the DOM, but what would be faster is select by class or any other attribute set directly on the element. If you could add an additionnal class to the elements, that would be great. – plalx Aug 14 '13 at 15:51
  • @rrrfusco, Change `=== '#00FF00'` for `=== '#00ff00'`. It's case-sensitive. – plalx Aug 27 '13 at 02:02
  • @rrrfusco Hum, somehow `backgroundColor` returns a value in `rgb()` format in this case. I would have to read more about it, but here's the working example http://jsfiddle.net/qUp2J/ – plalx Aug 27 '13 at 02:22
  • @rrrfusco, Well aren't you generating this markup and adding new nodes? The simplest solution would be to put that code inside a function and call that function everytime new nodes gets added. – plalx Aug 27 '13 at 11:53
  • @rrrfusco, Well since you are scraping data, I believe that you are performing async requests to gather that site's content at specific intervals? You just have to re-run the code everytime you are fetching the site's content... no? – plalx Aug 27 '13 at 19:08
  • I think this code will sum the current loaded page. I'd like to add new values to previous found values. – rrrfusco Aug 27 '13 at 19:25
  • @rrrfusco, I will need a concrete example on how you are gathering the other's site HTML. Please setup a jsfiddle example or update your answer with additionnal relevant code. – plalx Aug 27 '13 at 20:18
  • New question. http://stackoverflow.com/questions/18458228/add-numbers-from-dynamic-site-with-new-page-load – rrrfusco Aug 29 '13 at 05:01
1

As previously mentioned, it's probably best to use a class definition. But if you must select by color, the following code should do it for you.

var data = document.getElementsByTagName('span');
var len = data.length;
for(var i = 0; i < len; ++i){
    var styles = data[i].getAttribute('style');
    if(styles.indexOf('background-color:#00FF00') != -1){
        //Do something
    }
}
Geoffrey Ochsner
  • 215
  • 2
  • 14