.closest() returns undefined - javascript

I have the following list:
<div id="saved">
<ul class="list-group" style="display: block;">
<li class="marked list-group-item">box-shadow:<span class="marked_text">0px 0px rgb(200,200,200)</span>;<a class="pull-right multiple-shadows checkbox-active">Click</a>
</li>
</ul>
</div>
Now i want to store the text that is inside inside a variable.
I have written the following code:
$("body").on("click", "#saved ul li > a.multiple-shadows", function () {
$(this).toggleClass("checkbox-active");
var roll = $(this).closest("span").text();
console.log(roll);
});
The problem is that with .text() i get an empty value and with .html() i get undefined.Any ideas?

$.closest() gets the parent (https://api.jquery.com/closest/). What you need is $(this).siblings("span"). Also try to limit the number of selectors in jQuery. $('a.multiple-shadows') is more than enough.
EDIT: if you have more than one span siblings, to get the first one, use $(this).siblings("span").first()

closest finds the closest ancestor of an element. the span is a sibling of your a tag, so closest is correct to return undefined. your a is inside of an li, which is inside of a ul, which is inside of a div, so those are the only elements that closest will return anything for.

Since your span come before the a tag, you simple can use the .prev() function.
$(this).toggleClass("checkbox-active");
var roll = $(this).prev().text();
console.log(roll);
Fiddle: http://jsfiddle.net/hp9or7pf/

.closest "matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree" (https://api.jquery.com/closest/). Therefore, .closest will not match any siblings but ancestors. Instead, you can use .prev().
$("#saved").on("click", ".multiple-shadows",function(){
$(this).toggleClass("checkbox-active");
var roll=$(this).prev().text();
alert(roll);
});

Related

How do I know my position inside an li when interacting with an element inside that li?

I am dynamically appending to the main to-do "list" ul.
<li>
<div class="description">
<input class="descriptionInput" type="text">
</div>
</li>
How do I know I'm inside the 2nd li when performing an event on the description input? (trying to retrieve the text of the li the input is inside of)
I can't for the life of me figure out how to sort of select "backwards".
Would appreciate a few hints or terms to google.
Thanks!
Finding the LI element
the this value inside an event handler is the object on which the handler has been attached, whether by addEventListener or by assigning a function to an "onEventName" property/attribute. But if event handling is delegated, this may not be the object on which the event was fired.
the target property of theevent object is the object on which the event was fired. (srcElement is a proprietary and non standard alias of target.)
So if you are listening for an event fired on the input, e.g. "change", the li element is in the parent node chain, which you could code directly in a handler as
function (event) {
let li = event.target.parentNode.parentNode;
//... do stuff with li
which is brittle by assuming a particular element structure, or by searching the parent node chain:
function (event) {
let li;
for( li = event.target; li = li.parentNode;) {
if( li.tagName == "LI") {
break;
}
}
// process li ....
which finds the LI element or leaves li set to null.
Finding its position in the List
If the unordered or ordered element does not have its own id, you can find it in the parent node chain of the input element in similar fashion to finding the LI element above (i.e. by coding directly or searching).
The position of the LI element in the OL or UL list entries can be found by searching and matching it with an element in the children property of the OL/UL element.
Note that the node.children collection is live and should not be used while sorting LI elements by dynamically moving their positions around in the DOM.
You can use index() function for this.
If you are working with the input field under the list item. Then just select like this:
$("input.descriptionInput").parents("li").index();
I think it will work for you.
Your event should have a srcElement property, which contains the element from which the element originated. From there you can traverse through the DOM to get to the grand-parent element.
for example:
myElement.addEventListener('keyup',function(event){
let input=event.srcElement;
let div=input.parentElement;
let li=div.parentElement;
console.log(li.textContent);
//or just (event.srcElement.parentElement.parentElement.textContent)
})
Of course this only works if you're sure that the input will always be the grand-child of the li. If another element gets added for whatever reason, your code will break. It's safer to search for the element
I would just search for the element using a while loop.
let element=event.srcElement;
//while the element isn't an li, and it has a parentElement;
while(element.tagName !=='LI' && element.parentElement){
element=element.parentElement;
}
console.log(element) //should have found the first li ancestor
Try using .closest function to navigate to the nearest li and then use index() to determine the index. Also, since you are dynamically adding li, you might need to add change listener to the DOM.
<ul>
<li>
<div class="description">
<input class="descriptionInput" type="text">
</div>
</li>
<li>
<div class="description">
<input class="descriptionInput" type="text">
</div>
</li>
</ul>
<script>
$(document).on('change','ul li input.descriptionInput', function(){
var index = $(this).closest('li').index();
alert(index);
});
</script>
Example : https://jsfiddle.net/xpvt214o/874826/

using .eq closest to get upper div

I've tried using .closest, .parents and .eq to get this div selected on page load, and can not figure out why it is not working. My HTML is:
<div class="top">
<ul>
<li>
<div></div>
<ul class="first"></ul>
<div></div>
<ul class="first active">
<li><a class="current"></a></li>
</ul>
<ul class="first"></ul>
</li>
</ul>
So on page load I want the div above 'active' to change colors, but can't get it to work. I've tried:
$(document).ready(function () {
if ($('.current').is(':visible')){
$('.current').closest('div').addClass('active');
});
You have incorrect selector to target required div. You need to first traverse to parent ul element and then to its previous sibling div. Like this:
$('.current:visible').closest('ul').prev().addClass('active');
I think you are trying to select the prev sibling.
$('.current:visible').each(function(){
$(this).closest('ul').prev('div').addClass('active');
})
This should work:
$(document).ready(function () {
if ($('.current').is(':visible')){
$('.current').parents('.active').prev('div').addClass('active');
});
The div above .first.active in the source is a sibling, not a parent, hence why closest() doesn't work for you in the method you're using.
You can use closest() to get the parent ul, then prev() to get the div you require. Try this:
if ($('.current').is(':visible')) {
$('.current').closest('ul').prev('div').addClass('active');
});
.closest will look up the DOM tree to find the closest matching "parental" element. The div you are trying to get is actually a "sibling" of the <ul> so .closest won't find it.
So you would need to go up to the <ul>, then get the element "previous" to that.
$(document).ready(function () {
if ($('.current').is(':visible')){
$('.current').closest('ul').prev('div').addClass('active');
});

Is there a way to reach parent's sibling in jquery?

I have a button inside a div. When clicked, i will need to grab the length of a list that is a sibling to the parent container. maybe so even a grandparent container.
The gist of the code looks something like this below. (My actual code is actually nested deeper than this example. I would like to know how to target part a sibling of a parent or grandparents or even great great grandparent...)
HTML
<div>
<div class="button-parent">
<div class="button-containers">
<button>Click Here!</button>
</div>
</div>
<div class="list-container">
<ul class="lists">
<li>bar</li>
<li>bar</li>
<li>bar</li>
<li>bar</li>
<li>bar</li>
</ul>
</div>
</div>
jquery
$('button').parent('button-parent')
.closest('list-containers').length
.closest() finds the closest ancestor (parent), so it won't find your .list-container.
You can do this a few ways though...
Give your surrounding div a class and use .find() to locate your list if it is the only list in your parent div:
$('button').closest('.parent-div').find('.list-container');
Use next() if .list-container will always be the next item after .button-parent:
$('button').closest('.button-parent').next('.list-container');
You can use .siblings() if .list-container will always be on the same DOM level as .button-parent:
$('button').closest('.button-parent').siblings('.list-container');
From there you can fulfil the rest of your requirement to capture the length of the list by selecting all the li elements and counting them. If we use number 1 above as an example, it might look something like this:
const list = $('button').closest('.parent-div').find('.lists');
const items = list.children();
const count = items.length;
NOTE: The selection for list in this example targets ul.lists rather than .list-container, as this allows us to count using children(), which is much less intensive than find().
I suppose you can use Use parents([selector]) or closest([selector]) with siblings([selector])
parents() looks for ancestors, closest() be used as well if you want to select only the first going upward in the ancestry
siblings() select for siblings
you can pass them selectors or use eq()
one more things your jquery snippet doesn't seem to include . for class selector
Three methods that I tried and worked are
$('button').parents().eq(1).siblings('.list-container');
$('button').parents('.button-parent').siblings('.list-container');
$('button').closest('.button-parent').siblings('.list-container'));
Check out this jsfiddle, i have selected list-container using the three methods

Find element above another using jQuery

I'm trying to find the element using jQuery from the following html.
<ul class="gdl-toggle-box">
<li class="">
<h2 class="toggle-box-title"><span class="toggle-box-icon"></span>Volunteer Form</h2>
<div class="toggle-box-content" style="">
</div>
</li>
</ul>
What I'm looking to do is when the h2 is clicked find the li above the h2 add a class active to it. Tried a few different calls but no luck.
EDIT
The biggest issue is that there are multiple toggle boxes on a page so something like this works on pages with a single toggle but pages with multiple the result is they all open together.
var gdl_toggle_box = jQuery('ul.gdl-toggle-box');
gdl_toggle_box.find('li').each(function(){
jQuery(this).addClass('item');
});
gdl_toggle_box.find('li').not('.active').each(function(){
jQuery(this).children('.toggle-box-content').css('display', 'none');
});
gdl_toggle_box.find('h2').click(function(){
if( jQuery('.item').hasClass('active') ){
jQuery('.item').removeClass('active').children('.toggle-box-content').slideUp();
}else{
jQuery('.item').addClass('active').children('.toggle-box-content').slideDown();
}
});
You can use closest.
closest will match the first parent element that matches the selector traversing up the DOM tree.
Demo
$('h2.toggle-box-title').click(function(){
$(this).closest('li').addClass('active');
});
Try this.
$('h2.toggle-box-title').click(function(){
$(this).parent().addClass('newclass');
});
try this:
$('h2.toggle-box-title').click(function() {
$(this).parent('li').addClass('active');
});
On you click in the button you can use the event:
$("something").parent().find("h2.myClass");
// And if you want you can add class after you find you object
http://api.jquery.com/find/
Selecting an element's parent
In order to select an element parent, you can use the parent() function.
Try this:
$('h2.toggle-box-title').click(function() {
$(this).parent('li').addClass('active');
});
*to be more specific, you target the parent you would like to choose by specifying its selector
Check the jQuery API Documentation here
parent() - Get the parent of each element in the current set of matched elements,
optionally filtered by a selector.

how to get value of HTML from jquery or javascript

I want to select the following three values from the HTML file either by Jquery or Javascript.
class "class1" href value
class "class1" inner text value (PersonA in the example code)
class "Title" inner text value (Accountant in the example)
How can I select all the data of li node by node as? I am lost :(
<ol id="result-set">
<li id="v-0">
<div class="result-data">
..
<h2>
<a class="class1" href="">PersonA</a>
</h2>
<dl class="basic">
<dt>Title</dt>
<dd class="title">Accountant</dd>
....
</dl>
</div>
</li>
<li id="v-1">
...
</li>
.....
To get "PersonA": $('#v-0 h2 a').html();
To get href of that link: $('#v-0 h2 a').attr('href');
To get "Accountant": $('#v-0 dl dd').html();
You can modify the id ("v-0") at the start of the selector to choose a particular "row" of your data set.
With jQuery, you can do something like this:
$("#result-set li").each(function() {
var $currentLi = $(this),
$class1link = $currentLi.find("a.class1"),
class1href = $classAlink.attr("href"),
class1content = $classAlink.html();
// do something with values
});
The .each() method will process each li element. Within the callback to .each() the variable $currentLi is a jQuery object holding that li (set from $(this) where this is the li element itself). The .find() method is used to find the anchor element within the li and then its href and content are retrieved.
The "Accountant" you asked about is one item in a definition list, so you'd probably want to loop through that list with another .each() statement nested inside the one above.
You don't make it clear how you want to use the values, but this should get you started. For further details about the various jQuery methods I've mentioned check the jQuery API.
document.getElementById(Id).value
returns value of element with specific id. in jquery:
$("#id").val()
by class $(".yourClass").val()
to get attribute value use attr("attributeName") for example $(".class1").attr('href').
if you want to get text from specified element use .text() like $(".title").text() //will return Accountant.
You mean selecting them with a jQuery selector? That would be done like so:
$('.class1').attr('href') //class1 href, i persume you dont mean classA as it doesnt exist in your code
$('.class1').text(); //PersonA text using the same selector
$('.title').text(); //Accountant from the .title dd

Categories

Resources