jquery find element considering parent - javascript

How can I find an element considering parent node? Example:
<ul class="level-3">
<li class="item-1">1</li>
<li class="item-2">2</li>
<li class="item-3">3</li>
</ul>
var $ul = $('.ul');
console.log($ul.find('.item-1')) - // found - OK
if find
console.log($ul.find('.level-3')) - // not found - WHY ???

Assuming UL as element
You are not able to find it as level-3 is not the child of ul.
As per your current HTML, You need to use .filter()
Reduce the set of matched elements to those that match the selector or pass the function's test.
Code
var $ul = $('ul');
$ul.filter('.level-3')

You can use soma kind of jQuery functions to do this:
Closest: find the anchestor element matches the selector.
The .closest() method begins its search with the element itself before progressing up the DOM tree
Parents: walk the DOM tree looking for all parents that matches the selector.
is: check if the element match the selector.
$ul.closest(".level-3")

In your point you don't have ".level-3" class. For simply you can use jquery to do this.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("#btn1").click(function(){
alert($("ul").find('.item-3').text());
});
});
</script>
</head>
<body>
<ul class="level-3">
<li class="item-1">1</li>
<li class="item-2">2</li>
<li class="item-3">3</li>
</ul>
<button id="btn1">Show level 3 Text</button>
</body>
</html>

Related

jQuery target next `ul` element from `li` with class `active`

Cannot figure what I am doing wrong, as I get no errors. Essentially I want to target the very next ul element from the one and only li containing a class of active.
My HTML is:
<li id="abc"></li>
<li id="account" class="active">
<img class="menu-logo-symbol" src=" /img/app/logo-symbol.png">Your Account
<ul class="nav-pills nav-stacked sub-nav nav-list" style="display: none;">
<li id="account-details"></li>
......
</ul>
</li>
I have tried the following:
var checkElement = $('li.active').next('ul');
checkElement.slideDown('normal');
and
$('li.active').next('ul').show();
and also
$('li.active').next('ul').slideDown('normal');
Thanks
In jQuery, next() and prev() find siblings, or elements at the same depth in the DOM. In this case, since the ul is a child element of .active, you'd actually need to use the find() method like so: $('li.active').find('ul').first().show();
Using first() in combination with find() ensures that it'll only return that single ul element and not any others that may be nested deeper.
Done as follows:
$('.active ul:first').slideDown('normal');
I still do not understand why this did not work
$('li.active').next('ul').show();

Trouble using .closest function

I'm trying to make a sidebar menu for a dashboard. I want to implement this with .closest as it will fit with my code right. Here is a simple example of what I'm trying to do: https://jsfiddle.net/eu8kjzh4/10/
Why isn't the closest span's (and the only span in this case) text being replaced with a '-'? In my code, I have
$('.' + Key).closest( '.' + Key ).css("color", "#000");
This code works just fine, but the one in the jsfiddle does not.
closest traverses up the DOM and is used for nested elements.
In your markup, your div is not a descendant of your span, not even a sibling.
You have
1. To retrieve the previous sibling (the first li after the body)
2. And find the span inside the li
$(document).ready(function() {
$(".sub").prev().find('span').text('-');
});
Also, in your fiddle, you forgot to include jQuery.
Here is a working code : https://jsfiddle.net/qwc6pepr/1/
Incorrect function: .closest( selector ) Returns: jQuery
Description: For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree
What you want is the prev which finds the first sibling prior to the element
$(document).ready(function() {
$('.sub').prev('li').find('span').text('-');
});
From jQuery documentation
Given a jQuery object that represents a set of DOM elements, the .closest() method searches through these elements and their ancestors in the DOM tree and constructs a new jQuery object from the matching elements
Your span is neither a Parent Element of your div.sub in the DOM, nor matches with the $(".sub") rule.
The only way to make your jQuery code work with your HTML structure :
$("#plusMinus1").text("-");
Or modify your HTML structure to match with the .closest() method requierements
Fiddle
When you go to the parent you'll end up in the body. From there you can find the span.
$(document).ready(function() {
$(".sub").parent().find("span").text("-");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<body>
<li>
<a class="selected" href="#" onclick="return false;">Dashboard 1 <span id="plusMinus1">+</span></a>
</li>
<div class="sub">
<ul>
<li><a id="s1" href="">Test A</a>
</li>
<li><a id="s2" href="">Test B</a>
</li>
<li><a id="s3" href="">Test C</a>
</li>
</ul>
</div>
</body>

How to permanently remove an element from a jQuery object

here is the problem.
I have code like this where I get all li elements into a jQuery collection and then I remove last item from DOM. But I don't know how to also remove an element from a jQuery collection?
Now it's something like this:
console.log(myList);
['li.item', 'li.item', 'li.item']
I need to pop last item and get something like this:
console.log(myList);
['li.item', 'li.item']
var myList = $('.item');
console.log(myList);
myList.last().remove();
console.log(myList);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="item">Item</li>
<li class="item">Item</li>
<li class="item">Item</li>
<ul>
To remove an element in the jQuery object, you can use .splice().
To remove the last element :
myList.splice(-1);
To remove the first element :
myList.splice(0, 1);
It is important to know that the returned value is an HTMLElement. If you wanna do something with it, you need to convert it into a jQuery element again.
Unfortunatly, jQuery doesnt have pop or shift by default. But you can easily create those methods with that :
$.fn.pop = function(){
return $(this.splice(-1));
}
$.fn.shift = function(){
return $(this.splice(0,1));
}
Then call:
myList.pop();
myList.shift();
If you want to remove in the DOM and in the object, you can chain the remove function :
myList.pop().remove();
myList.shift().remove();
$(myList.splice(0, 1)).remove();
$(myList.splice(-1)).remove();
The problem is that $.fn.remove doesn't update collection elements and length property after it removes elements from DOM. As the result collection becomes desynchronized with actual DOM. What you can do however is to use combination of jQuery's remove method and native javascript pop or splice. It can be pretty concise:
$([].pop.call(myList)).remove();
Check the demo below.
var myList = $('.item');
alert(myList.length);
$([].pop.call(myList)).remove()
alert(myList.length);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="item">Item 1</li>
<li class="item">Item 2</li>
<li class="item">Item 3</li>
<ul>
You can use .slice to select a specific cached item from the jQuery object, but it is little tricky to update the original cached element. I used .not function to filter out the removed element from the cached selector.
Explanation:
//read as numbered for better understanding
myList = myList.not( // 3. Use .not to remove the Last element from the
// cached selector
myList.slice(-1) // 1. Select Last element using .slice(-1)
.remove() // 2. Remove Last element
);
var myList = $('.item');
console.log(myList);
myList = myList.not(myList.slice(-1).remove());
console.log(myList.css('color', 'red'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="item">Item 1</li>
<li class="item">Item 2</li>
<li class="item">Item 3</li>
<ul>

Inserting HTML into tag using JavaScript

I'm having a problem with JavaScript/jQuery at the moment where I'm trying to access the element inside the h4 element in my code. I'm doing this because I would like to dynamically display to the user how many guides are available in each "h4" section. For the PC section, it should display "4 reviews available" and for the Xbox One section, it should display "3 reviews available". However, both say " reviews available", and I'm assuming it's because I'm not using the jQuery functions properly. Here's the HTML code:
<h4><li class="console">PC (<span class="number"></span> reviews available)</li></h4>
<div class="gameList">
<ul>
<li class="game">Guide #1</li>
<li class="game">Guide #2</li>
<li class="game">Guide #3</li>
<li class="game">Guide #4</li>
</ul>
</div>
<h4><li class="console">Xbox One (<span class="number"></span> reviews available)</li></h4>
<div class="gameList">
<ul>
<li class="game">Guide #1</li>
<li class="game">Guide #2</li>
<li class="game">Guide #3</li>
</ul>
</div>
And here's the jQuery/JavaScript code:
$("h4").each(function() {
var node = $(this).children().children(); // gets node that has "number" class
var count = $(this).next().children().children().length; // gets number of li tags
node.innerHTML = count;
});
I tested whether or not it's properly getting the correct node and count by using the alert function for JavaScript, but for some reason, node.innerHTML = count won't display the contents of "content" properly in the element. Rather, it just displays a blank. Does anyone know why?
Its a jquery object not a DOM one..use this...
node.html(count);
node is a jQuery object here. It does not have "innerHTML". Instead you can use one of these:
node.html(count);
node.get(0).innerHTML = count;
node.get(0) will give you first DOM object from jQuery one.
A good practice is to prefix or suffix all jQuery objects with $ (e.g. $node), so that you will always know if a variable is meant to be a jQuery object.
use find() lot more cleaner and readable
$("h4").each(function() {
var $this=$(this);
var node = $this.find('.number');
var count = $this.next().find('li').length; // gets number of li tags
node.text(count); //or html()
});
and you have come invalid HTML li in h4 make sure you change that
working fiddle here
Do not use .children().children().
Only one .children() would do.
$(this).children('.game');
Also innerHTML is plain javascript. use .html(value) as node is JQuery Object.
$("h4").each(function() {
var node = $(this).children('.number');
var count = $(this).next().children('li').length;
node.html(count);
});
Reference to JQuery APIs:
.html()
.children()
$("h4").each(function() {
var $spanNumber = $('.console .number', this),
gameListCount = $(this).next().find('ul li').size();
$spanNumber.text(gameListCount)
});
You may use this also,
$("h4").each(function() {
var node = $(this).find('.number');
var count = $(this).next().find('.game').length;
node.html(count);
});

.prevUntil not working as expected

what am I doing wrong in this code..
I should get the class name of the previous sibling using this code.. but I am getting undefined..where am I going wrong
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JprevUntil</title>
<script type="text/javascript" src="jquery-1.7.1.min.js"></script>
<script>
$('.clickme').live('click',function(){
alert($(this).prevUntil('li.lick').className);
});
</script>
</head>
<body>
<div>
<p id="hello">Hello World</p>
<li class="lick">hello i am li</li>
heello i am a
<p class="clickme">click</p>
</div>
</body>
</html>
you can use siblings() and attr() method, prevUnti is not what you want:
Get all preceding siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object.
$('.clickme').live('click',function(){
alert($(this).siblings('li').attr('class'));
});
className is a javascipt core element property and cannot be used with jQuery objects, if you want to use className you can try this:
$('.clickme').on('click',function() { // you can use on(). live() is deprecated
alert($(this).siblings('li')[0].className);
});
From the prevUntil api documentation
*Get all preceding siblings of each element up to but not including the element matched by the selector, DOM node, or jQuery object.*
You are expecting the prevUntil to stop at the li.lick but it is not included.
You can see live in this jsfiddle
Do this way:-
Refer LIVE DEMO
HTML:
<div>
<li class="lick2">hello i am li 2</li>
<p id="hello">Hello World</p>
<li class="lick">hello i am li</li>
heello i am a
<p class="clickme">click</p>
<li class="lick1">hello i am li 2</li>
</div>​
JS:
$('.clickme').one('click',function(){
alert($(this).prevAll('li').attr('class'));
});​
OUTPUT:
lick
Look what the jQuery documentation says about this:
Get all preceding siblings of each element up to but not including the
element matched by the selector, DOM node, or jQuery object.
Your element is NOT included thats why you don't get what you want.
You could try the following:
$('.clickme').live('click',function(){
alert($(this).prevAll('li.lick').get(0).className);
});
UPDATE:
Seems like what you want to achieve (getting the closest preceding sibling) can be done with that code (code taken from here):
$('.clickme').live('click',function(){
alert($(this).prevAll('li.lick:first').attr('class'));
});
FIDDLE
It's because you get a JQuery wrapped object, try :
$('.clickme').live('click',function(){
alert($(this).prev('li.lick')[0].className);
});
If you inspect your code for
$(this).prevUntil('li.lick')
You have :
-->$(this).prevUntil('li.lick'): e.fn.e.init[1]
0: HTMLAnchorElement
context: HTMLParagraphElement
length: 1
prevObject: e.fn.e.init[1]
selector: ".prevUntil(li.lick)"
__proto__: Object[0]
Your HTMLAnchorElement is a DOM object, it's here that you can retrieve your className property.

Categories

Resources