-1

I have an HTML form with a simple JavaScript function that is meant to send the user to a different link based on the option selected.

<form>
<select name="deliveryType">
    <option value="123">Item 1</option>
    <option value="456">Item 2</option>
    <option value="789">Item 3</option>
</select>
<p><a href="javascript:void(0);" onClick="javascript:addToCart(this);">Submit</a>
<script>
    function addToCart(t) {
    var dT = t.parentNode.parentNode.childNodes[1].value;
    alert(dT);
    // location.href = "http://linkprefix.com/?variable=" + dT;
}</script>
</form>

It works as expected. The variable dT returns the value of the selected option.

However, if there is no line break between <form> and <select>, dT returns undefined. But then if I change childNodes[1] to childNodes[0] it then works again. I don't know why this would happen. I thought parentNode and childNode were based on HTML elements and the text within them, not line breaks between elements. If I had to guess, the line break is being counted as a text node, but that makes no sense to me. Is that what's happening? Is there a better way to do this?

user1934286
  • 1,732
  • 3
  • 23
  • 42
  • 1
    use `children[0]` - it will work regardless of whitespace - `children` does not include text nodes – Jaromanda X Aug 20 '17 at 07:23
  • _"the line break is being counted as a text node, but that makes no sense to me"_ - [white-space: pre;](https://developer.mozilla.org/en/docs/Web/CSS/white-space) - When you set this style, it break the lines not only on `
    ` but also by `\n` ( newline characters), so that can be one reason for this to make sencse and keep newlines as Text note inside the `childNodes` array
    – Alon Eitan Aug 20 '17 at 17:18
  • @AlonEitan Yes, that makes sense. My confusion was mostly that I assumed that text nodes only existed in elements that can actually contain them validly. I understand now that it was misguided. Using `children` instead of `childNodes` is what I am looking for. – user1934286 Aug 22 '17 at 18:50

2 Answers2

6

That's because in HTML, whitespace inside elements is considered as text, and text is considered as nodes (see w3schools). So by adding a line break, you are adding a node, which is why the <select> node is accessible through childNodes[1]. If there are no line breaks, then the <select> node is accessible through childNodes[0].

Andrew Bedford
  • 176
  • 1
  • 7
  • 4
    or as `children[0]` regardless of text nodes - of course, usual "internet exploder behaves differently" caveat for IE 8 or less – Jaromanda X Aug 20 '17 at 07:24
  • 1
    @JaromandaX Make sure to note that Netscape Navigator also behaves differently. –  Aug 20 '17 at 17:23
  • yeah, except nobody uses it, people do still use IE8! – Jaromanda X Aug 20 '17 at 21:16
  • Thank you for the explanation, but it is unfortunately not a solution. @Jaromanda offered a fix in his comment, which I've verified and added in an answer. – user1934286 Aug 21 '17 at 13:25
-1

As suggested in a comment, changing childNodes[1] to children[0] makes the function work regardless of any linebreaks or spaces between elements. See the updated fiddle.

childNodes apparently counts all text nodes, while children doesn't. Also, linebreaks count as a text node, which makes sense in the strictest interpretation of "text", but wasn't immediately obvious to me.

user1934286
  • 1,732
  • 3
  • 23
  • 42