How to aceess span directly using jQuery - javascript

I want to know how to get access of this [span class="myclass"] in below html structure..
<ul>
<li class="first">
<span class="myclass"></span>
<div class="xx">
<span></span>
........
</div>
<li >
<span class="myclass"></span>
<div class="xx">
<span></span>
........
</div>
</ul>
Here I need to write one function in [span class="myclass"], but i cant do it using $(".myclass") [I have few issues] I just want to directly access the span itself.How to do this..?
EDIT:the sln by phoenix is working fine..but lets say(just for my knowledge) the structure is
<li >
<span class="myclass"></span>
<div class="xx">
<li>
<span></span>
</li>
........
</div>
</ul>
so why the span inside 2 nd li(which is under div) is not getting the ref, is it bcoz they are not in the same level..if I need to access them do I need to do some thing like
enter code here
$("li").next(".xx").find(li span:first-child )..or something else is there?
Thanks.

$("li span.myclass")
EDIT: Okay then maybe with
$("li span:first") //EDIT: Don't do that. See below.
apparently :first stops after the first hit. So :first-child is the way to go.
which will select the first span in every li-element. But this can be tricky in case you have other li-elements with spans inside...
EDIT: If you can't use the class you already have, maybe assigning an additional class helps?
<span class="myclass newClass"></span>
...
var spans = $("li span.newClass");
EDIT:
As phoenix pointed out
$("li span:first-child")
returns a list with all span elements that are the first child of a li-element. I don't know if jQuery treats textnodes as child nodes. So if you have a space between <li> and <span>, this might be counted as the first-child. So check if you have any whitespace between your elements beside line breaks.

If span is the first child then you can use
first-child
selector
$("li span:first-child");

Related

Get <li> text number using jquery

i am trying to get li tag text value using js but i am not getting the expected output
i.e ("Pens").
I have added a code snippet.
Note - I cannot change html.
console.log(jQuery('#accordionItem li span').html());
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="accordionItem" class="filter_middle-stage2-list_wrapper">
<li style="font-weight: bold;">Pens<span>(1200)</span></li>
</div>
Any thoughts on this ?
Use the text method like below:
console.log($('#accordionItem li span').text());
from what I understand you want the text of the li without the text of the span.
So you can use the replace function to do it like so:
console.log($('#accordionItem li').text().replace($('#accordionItem li span').text(), ''));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="accordionItem" class="filter_middle-stage2-list_wrapper">
<li style="font-weight: bold;">Pens<span>(1200)</span></li>
</div>
if you want a more general solution that will get you just the text of the li without any of its children that would be a better solution:
console.log($('#accordionItem li').contents().get(0).nodeValue);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="accordionItem" class="filter_middle-stage2-list_wrapper">
<li style="font-weight: bold;">Pens<span>(1200)</span></li>
</div>
You seem to be selecting the <span> tag on your jQuery selector.
Although I'd suggest using the text method to achieve what you are looking for.
No jQuery needed.
Since you have an element with ID, you can access it directly, and get the node's text and simply remove any non-digit characters, and you'll be left with the numeral value you are after.
The benefit of this method is the irrelevance of the DOM structure - it will always work for that element (with that ID), but can be applied to any <li> element, regardless if it has a <span> child (or any other children)
console.log(
accordionItem.children[0].firstChild.textContent
)
<div id="accordionItem" class="filter_middle-stage2-list_wrapper">
<li style="font-weight: bold;">Pens<span>(1200)</span></li>
</div>

How to select the last child inside the tree using jQuery?

Suppose I have such a structure:
<div id="content">
<div>
<span>
<b>
<i>
<u>
<span>Price</span>
</u>
</i>
</b>
</span>
</div>
</div>
In this case, the number of tags inside the div #content and which ones they don't know me. I only have access to the id content.
How do I get the selector to the latest span which contains the text Price?
p.s. lastChild method returns the last child within the selected selector, but not deeper!
Select all children of #content using * selector and use .filter() to filtering element. In callback filter elements hasn't any child.
$("#content *").filter(function(){
return $("*", this).length == 0;
});
// Or using ES6
$("#content *").filter((i,v) => $("*", v).length == 0);
var ele = $("#content *").filter((i,v) => $("*", v).length == 0);
console.log(ele[0].outerHTML);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="content">
<div>
<span>
<b>
<i>
<u>
<span>Price</span>
</u>
</i>
</b>
</span>
</div>
</div>
You can use .find():
https://api.jquery.com/find/
This will recursively look for your selector, so:
$('#content').find('span') will give you two spans, one for the first nested span and one for the second nested span. The downside is that if you have multiple spans you'll need to find the right one.
If you can put an identifier in the last one, say a class named 'target-class', than you know you'll find the right one:
$('#content').find('span.target-class');
First of all let's fix your syntax. You can't put an <span> directly within a <u>. You need a <li> node. Also you can't/shouldn't put block elements such as ul within inline elements (span, a, b, i...). And even <b> and <i> are not recommended, better use semantic markup such as <strong> or <em> instead.
Now your problem. I think you don't have to care about being the last node. If you know the text contained is "Price" you can look for it in the following way:
var selector = $('#content').find(":contains('Price')");
$(selector).addClass('highlighted');
.highlighted {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="content">
<div>
<u>
<li>
<span>Price</span>
</li>
</u>
</div>
</div>
If this solution does not fits your needs, to get the last node you have to get all of them an check if they have children or not. Once they don't, you've reached your target.
But I have to say that this is a solution you could have found in SO.
Select deepest child in jQuery
Jquery Way -
You could target all spans $() and target the latest span using slice() method.
$('#content span').slice(-1)[0];
Javascript way -
Find all spans using querySelectorAll(), You'd get a NodeArray, you can convert it to Array using Array.from() and slice() last item from it which is latest span.
Array.from(document.querySelectorAll('#content span')).slice(-1)[0]

Why does removeChild function behave differently with list items and i tag?

I have noticed that removeChild does NOT behave as it does with other elements such as list item. I am using the i tag for some icons from frontAwesome and want these items removed individually when a button is clicked.
Unfortunately, I can only remove each i tag element only if I use removeChild() function twice. (Weird!)
What's going on?
HTML:
<div id="myFonts">
<i>1</i>
<i>2</i>
<i>3</i>
<i>4</i>
<i>5</i>
</div>
Javascript:
function FunctionTwo() {
var font = document.getElementById("myFonts");
font.removeChild(font.childNodes[0]);
}
https://codepen.io/anon/pen/EeaYvL
EDIT
Note: It makes a difference if you use LineBreaks or not!
<ul id="myList">
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
Here, there are 6 child nodes. Apparently, the LineBreaks are also considered as child nodes!
<ul id="myList"><li>Coffee</li><li>Tea</li><li>Milk</li></ul>
Here, there are 3 child nodes. WEIRD - is this a bug?
From MDN,
childNodes includes all child nodes, including non-element nodes like
text and comment nodes. To get a collection of only elements, use
ParentNode.children instead.
Hence, in both the cases, the elements are being removed weirdly. You should update
from
font.removeChild(font.childNodes[0]);
to
font.removeChild(font.children[0]);
For tweaking, https://codepen.io/anon/pen/aazoLK
Also.. if you notice both of your code closely on your link...
Code for <ul id="myList">
<ul id="myList"><li>Coffee</li><li>Tea</li><li>Milk</li></ul>
We see no spaces between tags.
Whereas, Code for <div id="myFonts">
<div id="myFonts">
<i>1</i>
<i>2</i>
<i>3</i>
<i>4</i>
<i>5</i>
</div>
You see the empty spaces before the <i>? Those got added as a text node in the childNodes object of your div
<div id="myFonts">
<i>1</i>
</div>
You could have used exactly the same code that you have currently, if you had chosen to rather Not add spaces before the <i> tags.
For Eg. like this:
<div id="myFonts"><i>1</i><i>2</i><i>3</i><i>4</i><i>5</i></div>
Check modified HTML for div here:
CodePen

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 append a ul tag inside a P or span tag?

Run the following piece of jQuery:
$('body').append('<p><span><ul><li>test</li></ul></span></p>');
I would expect this:
<p>
<span>
<ul>
<li>test</li>
</ul>
</span>
</p>
However, the result is this:
<p>
<span></span>
</p>
<ul>
<li>test</li>
</ul>
Why does the ul tag break out of span and p? This is valid HTML markup.
* UPDATE *
The p tag seems to be the problem. If you run the following:
$('body').append('<span><ul><li>test</li></ul></span>');
then
<span>
<ul>
<li>test</li>
</ul>
</span>
will generate properly.
How to append a <ul> tag inside a <p> or <span>?
You can't, it's invalid. So what you're seeing is the browser trying to rearrange it to make it valid.
The content model of span elements (e.g., what they're allowed to have in them) is "phrasing content" (things like em and such). (Same for p elements.) ul elements are only valid where "flow content" (like paragraphs and divs) is expected.
To fix it, don't try to put a ul inside a span or a p. You could remove the span and the p and use a div, for instance:
$('body').append('<div><ul><li>test</li></ul></div>');
...or just use the ul directly without a wrapper around it.
Re your update:
If you add the following markup to an html document
...
And then open the page in your favorite browser, it will open correctly. Try it!
Sure — because the browser rearranges it. For instance, this snippet:
<p>
<span>
<ul>
<li>test</li>
</ul>
</span>
</p>
Is turned into this DOM by Chrome:
Note how the ul is not inside the p or span — it's exactly the result you said you were getting.
That said, browsers do a lot to try to tolerate invalid markup and structures. But using valid markup and structures is generally the way to go.
You're putting a block-level element inside an inline element. Also, you wouldn't normally put a list in a paragraph.
$('body').append('<div><ul><li>test</li></ul></div>');
As already explained, your markup is invalid HTML and won't be parsed as you expected.
However, you can still do it using DOM manipulations.
document.body
.appendChild(document.createElement('p'))
.appendChild(document.createElement('span'))
.appendChild(document.createElement('ul'))
.appendChild(document.createElement('li'))
.appendChild(document.createTextNode('test'))
Not recommended because it's semantically wrong, but it's possible.

Categories

Resources