2

This is for a Google extension

I have an array of words that I try to match with existing words on a Twitter feed.

If a match is found, "exists" is printed in the console.

I'm trying to find the class name of the element that contains the specified words from my spoiled array.

I know it'll be a div because tweets are always put into divs but how do I find the class name in pure JavaScript?

//array with all the censor words 
var spoiled = ["terrible", "but", "pasta"];

//checks through every word of array and page
var result = spoiled.every(function(word) {
    return document.documentElement.innerText.indexOf(word) > -1;
});

// Checking page title
if (document.title.indexOf("Twitter") != -1) {

    //checks if every word of array is on page
    if (result) { 
        //if so do this

        console.log("exists");

    } else{
        console.log("not exist");
    }
}

The reason I need the class name is because my future plan is to place an image over the div that contains the words in my array.

Blue
  • 22,608
  • 7
  • 62
  • 92
  • 2
    *"The reason I need the class name is because my future plan is to place an image over the div that contains the words in my array."* How does placing an image over it have anything to do with getting the class? – T.J. Crowder Aug 07 '16 at 05:53
  • You should search when you wish to append image and on finding match, you can append/replace html. Storing class and appending class can have bad effects. – Rajesh Aug 07 '16 at 05:56
  • I mean I'm still figuring it out but without the class name I'd be placing an image over a random tweet instead of the one that contains words from the array. @T.J.Crowder – teresawithoutah Aug 07 '16 at 05:58
  • 1
    @teresawithoutah: You use the element itself, not a class. – T.J. Crowder Aug 07 '16 at 06:04

1 Answers1

2

The reason I need the class name is because my future plan is to place an image over the div that contains the words in my array.

It sounds like you want to get a reference to the div, not its class (but once you have a reference to it, you can get its class from .className if you really need it).

That means rather than using innerText, you'll need to walk the nodes in the document tree, which is quite straightforward. For this answer I posted a general-purpose "find matching nodes in the DOM" function that accepts a predicate function, so we can use it with a predicate tht checks the text nodes in the element for the words in the array.

You've used Array#every in your question, which will only return true if all the iterations returned a truthy value; below I've used Array#some to flag up having found any of them instead. Elements containing any of the words get a class added to them, highlight, which puts a yellow background behind them:

// The searcher function
function domFind(element, predicate, results = []) {
  if (!element.children) {
    throw new Error("Starting node must be an element or document");
  }
  if (predicate(element)) {
    results.push(element);
  }
  if (element.children && element.children.length) {
    [...element.children].forEach(child => {
      domFind(child, predicate, results);
    });
  }
  return results;
}
// Our words
let array = ["terrible", "but", "pasta"];
// Do our search with a predicate
let elements = domFind(document, element => {
  return Array.from(element.childNodes).some(n => {
    return n.nodeName.toLowerCase() != "script" &&
           n.nodeType == 3 &&
           array.some(word => n.nodeValue.indexOf(word) != -1);
  });
});
// We have the array of elements; add a class to them
elements.forEach(e => { e.classList.add("highlight"); });
.highlight {
  background-color: yellow;
}
<div>blah blah</div>
<div>this is terrible!</div>
<div>lorem ipsum</div>
<div>
  <div>
    <div>no fate but what we make</div>
  </div>
  <div>la la la</div>
  <div>mmmmmm pasta</div>
</div>
<div>foo</div>

Since this is for a Chrome extension, I've happily used ES2015 for the above.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875