get nearby sibling in javascript
Asked Answered
C

5

20

I have a certain DIV structure with an anchor tag in between somewhere. On click of the link, I need to fetch the value of another span element within the parent div and do something, (say, alert it).

The html is like this :

...
<div id="div1">
  ...
  <span>This is reqd</span>
  ...
  <a href="#">Click Me </a>
  ...
</div>
...

The entire div is repeated many times in the page. When I click on the a I want to alert "This is reqd".

Can the HTML be searched like this?

Conserve answered 23/1, 2013 at 10:47 Comment(2)
is there any fiddle available ?Ropable
@Riju I don't have a fiddle.. And there is only one HIDDEN span element in the parent DIV. forgot to mention thatConserve
R
9

For a single span element, it should be pretty easy,. Just call a myFunction(this) on click of the link and manipulate the DOM like this :

function myFunction(currObj){
var parentofSelected = currObj.parentNode; // gives the parent DIV

var children = parentofSelected.childNodes;
for (var i=0; i < children.length; i++) {
    if (children[i].tagName = "span") {
        myValue= children[i].value;
        break;
    }
}
alert(myValue); // just to test

 } // end function

Hope this works. It did for me !!

Ropable answered 23/1, 2013 at 10:58 Comment(3)
thanks... exactly what I was looing for. worked in an instant !!Conserve
document.getElementsByTagName('span')[0] instead of that for loop. also, .value is not a valid way to access a span.Vandalism
could have, should have, would have !Superman
S
4

Since the <span> is not the immediate sibling of that <a>, we can't invoke .previousSibling or .previousElementSibling. Best solution might be to get the parent and query for the <span>

document.getElementById( 'div1' ).getElementsByTagName( 'a' )[ 0 ].addEventListener('click', function() {
    alert( this.parentNode.getElementsByTagName( 'span' )[ 0 ].textContent );
}, false);

Demo: http://jsfiddle.net/cEBnD/

Superman answered 23/1, 2013 at 10:49 Comment(2)
Pretty much the same as I answered, but not downvoted into oblivion for no apparent reason. Not to mention accessing the spans in a valid way, and no need to load a library. +1. Hrmpf, StackOverflow...Vandalism
If you use addEventListener and textContent, you can as well go for querySelector :P jsfiddle.net/Ralt/cEBnD/1Catwalk
D
2

Update: Solutions with and without jQuery

This answer got so many downvotes for showing an example with jQuery that I decided to add more examples with vanilla JavaScript so that anyone could choose whether to use jQuery or not.

Generally, you can use .previousSibling in vanilla JavaScript, see:

and you can use .prev() in jQuery, see:

But keep in mind that those may not work in more complicated cases when you don't know the exact structure of your entire DOM.

Here are few examples of achieving that goal both using jQuery and with vanilla JavaScript, for simple cases with fixed DOM structure and for more complicated cases using classes.

Without classes

For the most simple DOM structures you might get away with putting event listeners on all links and relying on the implicit knowledge of the DOM, but this may not work for more complex situations - for those see the examples with classes below.

With jQuery:

$('a').click(function () {
  alert( $(this).prev().text() );
  return false;
});

See DEMO.

Without jQuery:

document.querySelectorAll('a').forEach(link => {
  link.addEventListener('click', () => {
    alert(link.previousSibling.previousSibling.innerText);
  });
});

Note that the previousSibling has to be used twice, because the empty text node that is between tha span and link would be used otherwise.

See DEMO.

Using classes

If the span is not immediately preceding your a element then you may also want to do it a little bit differently, also adding some classes to make sure that your code doesn't break any other links on the page:

With jQuery:

$('a.link').click(function () {
  alert( $(this).parent().find('span.text').text() );
  return false;
});

See DEMO.

Without jQuery:

document.querySelectorAll('a.link').forEach(link => {
  link.addEventListener('click', () => {
    alert(link.parentNode.querySelector('span.text').innerText);
  });
});

See DEMO.

The above code will bind click handlers to every a element with class "link" which will alert a text contained by its sibling span element with a class "text". (Of course the class names should be more descriptive than that.)

Drake answered 23/1, 2013 at 10:55 Comment(4)
Don't bring a shotgun to a fencing match. OP didn't ask for jQuery, didn't tag the question with jQuery, and jQuery is just inefficient compared to normal JS. Yes, it's shorter code, but that's the only advantage.Vandalism
@Vandalism jQuery is JavaScript and the question didn't mention any prejudice against any particular technology. This is a solution that solves the problem described in the question (unlike yours).Drake
jQuery is a library. It's a extra file to load, way more code to run, and doesn't help anyone to learn JS. Basics first, then libraries. Especially on simple matters such as this. I mean, loading a library for 3 lines of code?Vandalism
@Vandalism If you post a solution that doesn't use jQuery and works for a general case without polluting the DOM with useless IDs that only add needless complexity to the markup generating templates and works across different browsers then we might have something to argue about.Drake
C
2
<html>
<body>
    <div id="div1">
        <span>This is required</span>
        <a href="#" onclick="myclick(this.parentNode)">Click Me</a>
    </div>
</body>
<script>
    function myclick(x){
        var y = x.querySelector("span").innerHTML;
        alert(y)
    }
</script>
</html>

insted of span you can also give class name eg.,

<span class="classname">This is required</span>
x.querySelector(".classname").innerHTML
Capacitance answered 16/11, 2019 at 4:6 Comment(0)
L
-1

Using jQuery:

$('#innerId').siblings()
Langtry answered 26/4, 2017 at 10:25 Comment(1)
The OP didn't ask for a jquery solution. Loading a massive external library to find the siblings is massive overkill.Humber

© 2022 - 2024 — McMap. All rights reserved.