0

I have the following HTML data on a website which I am trying to manipulate using an extension in Google Chrome:

<div id="lvl-2">
        <div class="loading" style="display: none;"><div class="loading-text"><div class="nowloading">Loading…</div>
        <div class="content">
            <div class="dirs">
                <form class="search">
                    <input type="text">
                </form>
                <div class="dirs-list"></div>
            </div> <!-- dirs -->
        <div class="tunes"><table>
            <tbody>
            <tr></tr>
            ...
            <tr></tr>
            </tbody></table>
            </div>
            </div>

I am using the following code to get the table element somehow:

var div1 = document.getElementById("lvl-2");
var divChild1 = div1.children;
var divChild2 = divChild1[1].children;
var tables = divChild2[1].children;

But on executing the line where the tables variable is assigned, I am getting this error:

Cannot read property 'children' of undefined.

I am not sure why am I getting this error, as second child of the divChild2 variable should contain the table as a child. What do you suggest I should do? Ultimately, my aim is to randomize all the rows in the table. If there is another way I can do that, I would welcome it.

P.S. 1: I am a Javascript noob, I think it is abundantly clear.

P.S. 2: Apologies for the weird HTML. I had to remove a lot of useless tags in between the relevant tags. Otherwise the HTML would have gotten huge.

Parag Goel
  • 123
  • 2
  • 14

2 Answers2

0

Your HTML is invalid, you are not closing the .loading div and some others. So your DOM is absolutely not the way you expect it to be.

That is why all those stupid people always tell you to indent your code properly. Might be easier to catch problems like this. Validation is also a good way to find problems like this.

This is how your HTML looks after running it through a beautifier (which you could do too before asking a question next time):

<div id="lvl-2">
  <div class="loading" style="display: none;">
    <div class="loading-text">
      <div class="nowloading">
        Loading…
      </div>
      <div class="content">
        <div class="dirs">
          <form class="search">
            <input type="text">
          </form>
          <div class="dirs-list">
          </div>
        </div>

        <!-- dirs -->
        <div class="tunes">
          <table>
            <tbody>
              <tr>
              </tr>
              <tr>
              </tr>
            </tbody>
          </table>
        </div>
      </div>

Obviously this is not what you expected. I fixed it for you:

<div id="lvl-2">
  <div class="loading" style="display: none;">
    <div class="loading-text">
      <div class="nowloading">
        Loading…
      </div>
    </div>
  </div>
  <div class="content">
    <div class="dirs">
      <form class="search">
        <input type="text">
      </form>
      <div class="dirs-list">
      </div>
    </div>

    <!-- dirs -->
    <div class="tunes">
      <table>
        <tbody>
          <tr>
          </tr>
          <tr>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</div>

And with the fixed HTML, your code works.

kapa
  • 77,694
  • 21
  • 158
  • 175
  • Thanks for the beautifier advice, will surely remember it in the future. But the thing is, the tags are incomplete because I am accessing a web page, and hence I had to strip out a lot of unneeded tags. That resulted in this ugly HTML that you see. Apologies for that. – Parag Goel Feb 19 '14 at 19:39
  • I was trying this code in Google Chrome, and I was getting this error. But when I try the same code in Firefox, the code works smooth as butter. Why is that? – Parag Goel Feb 19 '14 at 19:41
  • Certain browsers are more tolerant about certain types of messy html. As I proved with my jsfiddle, http://jsfiddle.net/qJRkk/1/ , your js code works fine. I tried it in Chrome. Validate your html. Use inspector to check dom tree. Without seeing your real html, you cannot expect me to help. – kapa Feb 19 '14 at 20:31
  • I am actually accessing the web app at http://droptun.es/app. When I load the table with mp3 files, that is when I run the javascript code. – Parag Goel Feb 19 '14 at 21:46
  • @ParagGoel 404 Not Found. Do what I advised, and I am almost certain it will be resolved. Have you validated your HTML? – kapa Feb 20 '14 at 09:52
  • I will, but I can't access it right now, since the web app is currently down. Will post any update when it comes back up. – Parag Goel Feb 20 '14 at 17:10
0

In your webpage, there are other elements that you don't know. Each text (including line breaks, tabs and spaces) between tags is a TextNode, which is a Node in the DOM document.

var div1 = document.getElementById("lvl-2");

// divChild1 is a TextNode representing the line break and the tab
// between <div id="lvl-2"> and <div class="loading"
var divChild1 = div1.children;

// A textNode doesn't have a children attribute, so divChild2 is undefined
var divChild2 = divChild1[1].children;

// Error
var tables = divChild2[1].children;

To solve it, you can try using "firstElementChild" and "nextElementSibling", that only refers to "true" Nodes (assuming you try to get the "tunes" div. I haven't tested it but it should work) :

var div1 = document.getElementById("lvl-2");
var divChild1 = div1.firstElementChild;
var divChild2 = divChild1.nextElementSibling;
var tables = divChild2.nextElementSibling;
Sebastien C.
  • 4,649
  • 1
  • 21
  • 32
  • Wrong, `Element.children` will not include text nodes, what you are talking about is `Node.childNodes`. See http://stackoverflow.com/questions/7935689/what-is-the-difference-between-children-and-childnodes-in-javascript – kapa Feb 19 '14 at 12:30
  • You're right. My mistake. But the second part should still work. – Sebastien C. Feb 19 '14 at 12:34
  • If what I wrote in my answer is right, your code will not be better than what the OP already has. – kapa Feb 19 '14 at 15:00