20

I expect the following code to alert "out"

<input type=text onfocus="alert(this.nextSibling.id)" />
<output id="out">this is output</output>

But it alerts undefined WHY?

moroccan_dev
  • 310
  • 1
  • 2
  • 11

4 Answers4

22

nextSibling selects the very next sibling node of the element. The very next node can also be a textNode which doesn't have an id property, hence you get the undefined value. As the other answer suggests you could use the nextElementSibling property which refers to the next sibling node that has nodeType of 1 (i.e. an Element object) or remove the hidden characters between the elements.

Note that IE8 doesn't support the nextElementSibling property.

Ram
  • 143,282
  • 16
  • 168
  • 197
  • but in my code there is no nodes between the inout element and output and i don't see ant hidden characters – moroccan_dev Nov 15 '14 at 12:29
  • @moroccan_dev Please check this fiddle, and open the console to see the logged node. http://jsfiddle.net/khcxjta5/ – Ram Nov 15 '14 at 12:31
  • 2
    @moroccan_dev hidden characters are something that you can't see since they are hidden. In this case, they're the newline characters. – cychoi Nov 15 '14 at 12:36
11

Try this:

alert(this.nextElementSibling.id);

NOTE: The nextSibling property returns the node immediately following the specified node, in the same tree level.

The nextElementSibling read-only property returns the element immediately following the specified one in its parent's children list, or null if the specified element is the last one in the list.

Shijin TR
  • 7,516
  • 10
  • 55
  • 122
Johan Karlsson
  • 6,419
  • 1
  • 19
  • 28
5

Why you have this problem

nextSibling selects the next sibling node of the element. In your case you have a text node as a next node because you have a new line between your element nodes. Each text node between element nodes will be selected as next node and this nodes don't have an id property.

To prevent this we can use 2 ways:

Solution 1:

We delete a new lines, all of whitespaces, comment nodes or other text nodes and then we can use nextSibling:

<input type="button" value="get next sibling value" onclick="console.log(this.nextSibling.value)"><input type="text" value="txt 1">

Solution 2:

We use instead of nextSibling the nextElementSibling property:

<input type="button" value="get next sibling value" onclick="console.log(this.nextElementSibling.value)">
<input type="text" value="txt 1">

The nextElementSibling property returns the element immediately following the specified one in its parent's children list, or null if the specified element is the last one in the list.

In the case if some browser like IE8 doesn't support the nextElementSibling property we can use a polyfill (it should be placed before your code):

if(!('nextElementSibling' in document.documentElement))
{
    Object.defineProperty(Element.prototype, 'nextElementSibling',
    {
        get: function()
        {
            var e = this.nextSibling;
            while (e && e.nodeType !== 1)
                e = e.nextSibling;

            return e;
        }
    });
}

Relevant links:

Bharata
  • 13,509
  • 6
  • 36
  • 50
-1

Assuming that you can use jQuery

Note that this.nextSibling might not work in IE specifically

The jQuery alternative for this.nextSibling is $(this).next()

Community
  • 1
  • 1
Zameer Ansari
  • 28,977
  • 24
  • 140
  • 219
  • 7
    Why would you post a jQuery answer to a question that asks explicitly for a JavaScript answer and, nowhere, suggests that jQuery is either being used or is an option? Especially after eighteen months (as I write this)? – David Thomas Jul 18 '16 at 12:32
  • @DavidThomas , i totally agree , i know its old but i hate when i ask question about JavaScript and someone suggest a Prefabricated library , i mean how we can learn JavaScript if we being lazy and use the already-made scripts everytime , we can suggest others to use jQuery if they dont want to learn the true javascript. – The Doctor Feb 17 '18 at 12:42