0

I am trying to get the index of child of its parent. For example:-

<div>
    <table>
        <tr id="rahul">
            <td> Hi this is ABC </td>
            <td> Hi this is XYZ </td>
        </tr>
    </table>
</div>

And my java script code is:-

<script>
    $(document).ready(function() {
        document.onmousedown = mouseDown;
        function mouseDown(e) {
            var element =  document.elementFromPoint(e.clientX,e.clientY);
            console.log("Clicked element is:" + element.tagName);
            var i=1;
            while (element.nextSibling != null) {
                element = element.nextSibling;
                console.log('Sibling No:' + (i++) + " " + element.tagName);
            }
        }
    });
</script>

When i click on "Hi this is ABC" according to me, it should print

Sibling No.1 TD

But actually It is printing

Clicked element is:TD jsoupTest.html:10
Sibling No:1 undefined jsoupTest.html:14
Sibling No:2 TD jsoupTest.html:14
Sibling No:3 undefined 

It arises a doubt why this is printing undefined as sibling of TD? And my idea is to find the no of siblings clicked element has and i can find out the total no of children its parent has. So now I can find the index of clicked element by subtracting no of siblings from total children of its parent.

Please tell me if there is any better alternative to get this.

3
  • As you're using jQuery (I'm inferring this from $(document).ready(...)), I've added the jQuery tag to your question -- as it will affect the answers pretty markedly. (E.g.: This is one line with jQuery, multiple lines without.) Commented Jun 14, 2012 at 11:14
  • You are getting undefined because between the td element nodes (and after the last one), there is a text node (containing the white space characters) and text nodes don't have a tag name. Use element.nodeName instead and you will see. Commented Jun 14, 2012 at 11:15
  • Since indices are normally given zero-based in javascript, you might be better to start with var i = 0. Commented Jun 14, 2012 at 11:18

2 Answers 2

2

If you want to know what index a child element is relative to its sibling elements, jQuery can do that for you via index (see further down if you want to consider non-element nodes):

$(document).ready(function() {
    document.onmousedown = mouseDown;
    function mouseDown(e) {
        var element =  document.elementFromPoint(e.clientX,e.clientY);
        console.log("Clicked element is:" + element.tagName);
        console.log("Index: " + $(element).index());
    }
});

Live example | source

Note that that only considered elements, and not other kinds of nodes (in particular, text nodes) that may be there. This is what you want probably about 90% of the time, possibly more. :-) If you really want to consider other node types, not just elements, use $.inArray(element, $(element).parent().contents()) rather than $(element).index(), e.g.:

$(document).ready(function() {
    document.onmousedown = mouseDown;
    function mouseDown(e) {
        var element =  document.elementFromPoint(e.clientX,e.clientY);
        console.log("Clicked element is:" + element.tagName);
        console.log("Index: " + $.inArray(element, $(element).parent().contents()));
        // ^--- this is the only line that changed
    }
});

Live copy | source


Side note: I'm fairly sure you can replace your line

var element =  document.elementFromPoint(e.clientX,e.clientY);

...with

var element =  e.target;

...as target will be the topmost element under the mouse when the button was pressed.

Sign up to request clarification or add additional context in comments.

3 Comments

$(element).index() suffices.
@FelixKling You should put that in its own answer.
Thanks T.J. Crowder once again for your super awesome answer :):)
1

First, you should use the click event instead of mousedown. Then, you should not use a on<event>-property but a proper way to add a listener, jQuery (which you already have loaded) offers a simple and cross-browser way.

Next, don't use document.elementFromPoint with the coordinates of the mouse event - just use the target property of the event.

$(document).on("click", function(e) {
     var element = e.target;
     ...
});

Then, your loop:

        var i=1;
        while (element.nextSibling != null) {
            element = element.nextSibling;
            console.log('Sibling No:' + (i++) + " " + element.tagName);
        }

This code prints all siblings that come after the element. This does not seem to be what you want. You want to count the siblings before it, right? Use .previousSibling then.

Also, it includes text nodes, logging undefined for their nodeName. To get around that, you can use [previous|next]ElementSibling.

...find out the total no of children its parent has

Oh, thats a much easier task:

element.parentNode.children.length;
// or even
element.parentNode.childElementCount;
// to include text nodes:
element.parentNode.childNodes.length;

1 Comment

I just came across this now and found out your answer was really cool..Surprised why I didn't upvote earlier..Thanks :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.