Javascript - get child of child - javascript

How can I set the innner html of a span element in dom that is under li>a>?
<li class="first">
<a>
<span aria-hidden="true">1</span>
</a>
</li>
I have tried something like this, but nothing was written:
element[i].childNodes[1].children.innerHTML = number;

children is an HTMLCollection. innerHTML only applies to HTML elements. You need to find the HTML element in the children before using innerHTML.
It doesn't make a lot of sense to mix the use of childNodes and children. Use the former for more compatibility across browsers, use the latter for a simpler approach that lets you consider only element nodes.
var li = document.querySelector("li");
var number = 13;
li.children[0].children[0].innerHTML = number;
<ul>
<li class="first">
<a>
<span aria-hidden="true">1</span>
</a>
</li>
</ul>
Alternatively, you could just use querySelector:
var li = document.querySelector("li");
var number = 13;
li.querySelector("a").innerHTML = number;
<ul>
<li class="first">
<a>
<span aria-hidden="true">1</span>
</a>
</li>
</ul>

I recommend using jQuery (http://jquery.com)
and then use can simply do
$('li > a > span').html('THE INNER HTML HERE');
or
$('li > a').find('span').html('THE INNER HTML HERE');
you can use .first() to the result of find() function to get the first element

Related

Targeting the closest class in javascript

I'm just learning javascript and ran into a problem.
I'm trying to target the closest class and change the value, but I just keep getting Cannot read property 'innerText' of null at HTMLUListElement.
Is this not possible or is there another way I should look into?
Any help or guidance is appreciated.
<div id="someId">
<h2>Test</h2>
<ul>
<li>
<p class="amount">5</p>
<span class="name">My Name</span>
<button class="plus">Plus</button>
</li>
<li>
<p class="amount">10</p>
<span class="name">My Name 2</span>
<button class="plus">Plus</button>
</li>
<li>
<p class="amount">15</p>
<span class="name">My Name 3</span>
<button class="plus">Plus</button>
</li>
</ul>
const someList = document.querySelector('#someId ul');
someList.addEventListener('click', function(e) {
if (e.target.className === 'plus') {
let newValue = e.target.closest('.amount');
newValue.innerText += "5";
}
});
I've changed the .amount to lots of different things, p and li > p etc but no luck.
.closest() goes up the dom/xpath looking at ancestors. your p.amount is a sibling, not an ancestor, so nothing is returned from your .closest()
There is no single core js method for what you want to do. jQuery offers a function called .siblings() which is the closest to what you are intending to do, if you want to use it. But for pure javascript, the gist is to go up the dom/xpath tree and then back down.
There are different ways you can do it, depending on what selectors you want to be "anchors". #doodlemeister 's answer is one way to do it, but IMO it is not great because it may not be as flexible as you might like. It assumes going up to the first parent and then back down to the first child. IOW it expects your html structure to be exactly as you have it now.
A more flexible way is something like this:
const someList = document.querySelector('#someId ul');
someList.addEventListener('click', function(e) {
if (e.target.className === 'plus') {
let newValue = e.target.closest('li').querySelector('.amount');
newValue.innerText = +newValue.innerText + 5;
}
});
You can then adjust the .closest() selector if needed, and you use querySelector() to go back down the dom/xpath from there and target by your originally intended class.
.closest looks at ancestors, and .amount is not one. You can instead go to the .parentNode and then the .firstElementChild.
And I'd personally use .matches() instead of comparing the class name for exact equality.
someList.addEventListener('click', function(e) {
if (e.target.matches('.plus')) {
let newValue = e.target.parentNode.firstElementChild;
newValue.innerText += "5";
}
});
In javascript you can target the parent and select the matching child
const someList = document.querySelector('#someId ul');
someList.addEventListener('click', function(e) {
if (e.target.className === 'plus') {
let newValue = e.target.parentNode.querySelector('.amount').innerText += "5";
}
});
<div id="someId">
<h2>Test</h2>
<ul>
<li>
<p class="amount">5</p>
<span class="name">My Name</span>
<button class="plus">Plus</button>
</li>
<li>
<p class="amount">10</p>
<span class="name">My Name 2</span>
<button class="plus">Plus</button>
</li>
<li>
<p class="amount">15</p>
<span class="name">My Name 3</span>
<button class="plus">Plus</button>
</li>
</ul>
</div>

How to get span dynamic value inside li ul

My ASPX code looks like this:
<ul id="userlist">
<a class="s-test">
<li>
<span id="userlistspan" class="tt-User" value="1">Cardiologist</span>
<span id="userlistspan1" class="tt-Userss">SPECIALITY</span>
</li>
</a>
<a class="s-test">
<li>
<span id="userlistspan" class="tt-User" value="2">Cardio</span>
<span id="userlistspan1" class="tt-Userss">SPECIALITY</span>
</li>
</a>
</ul>
The jQuery I have tried is like this:
$('#userlist li #userlistspan').click(function () {
$('#txtSearch').val($(this).text());
})
//here am getting text like Cardio
How can I get value like value=2 from that span?
Your HTML is completely invalid for several reasons:
you cannot have an a element as a direct child of a ul. The li must be the child element.
You have duplicate id attributes when the id should be unique in same document, use classes to group elements instead.
span elements do not have a value attribute, if you want to store custom data with an element, use the data-* attribute.
the a element must have either an href or name attribute, however their use in this case seems redundant so you can remove them.
You need to fix all those issues first:
<ul id="userlist">
<li>
<span class="userlistspan tt-User" data-value="1">Cardiologist</span>
<span class="userlistspan1 tt-Userss">SPECIALITY</span>
</li>
<li>
<span class="userlistspan tt-User" data-value="2">Cardio</span>
<span class="userlistspan1 tt-Userss">SPECIALITY</span>
</li>
</ul>
From there you can attach the click handler to the .userlistspan class, and use the this keyword to reference the element which raised the event. You can then use the data() method to get the data-value, like this:
$('#userlist li .userlistspan').click(function() {
var $span = $(this);
$('#txtSearch').val($span.text());
var value = $span.data('value'); // = 1 or 2, depending on which element you clicked.
})

Find <li> tag by its child tag <a> href value

How to find Li tag which has a child tag by its Href value. By this I need to set class for that li tag.
My HTML
<div id="tabs" class="tab_wrapper">
<ul class="nav nav-tabs">
<li>Subject
</li>
<li>Contract
</li>
<li>Neighborhood
</li>
<li>Site
</li>
<li>Improvements
</li>
<li>Supplemental Data
</li>
</ul>
</div>
Css
.Active
{
color:red;
}
For example I have to set class "Active" for li tag which has href value "#tabNeighbourhood", so that li tag will be like
<li class="active">Neighborhood
</li>
Using :has() selector:
$('li:has(a[href="#tabNeighbourhood"])').addClass('active');
This will add class active to any LI containing anchor with specific href attribute.
Use .parent() :
$("ul.nav > li").removeClass("active"); // Clear all li's class attributes.
$("a[href='#tabNeighborhood']").parent().addClass("active"); // Add active to neighborhood.
$('li', '#tabs')
.filter(function() {
return !! $(this).find('a[href="#tabNeighbourhood"]').length;
})
.addClass('active');
I refer you to the official docs for explanation of the single parts.
Try Below Code
$(document).ready(function(){
$('body').find('a').each(function(){
if($(this).attr('href')=="#tabNeighbourhood"){
$(this).closest('li').addClass("Active");
}
});
});
Using your HTML structure you can use an immediate children selector >, has selector and a selector on href attribute.
Code:
$('#tabs>ul>li:has(a[href="#tabNeighbourhood"])').addClass('active');
Demo: http://jsfiddle.net/swvzot7f/
Try it by yourself. Here is an algorithm if you consider it too complex:
Search for needed <a> by attribute.
Select the parent of <a> that was found.
Add class to that parent.
Answer is pretty simple, so I do think it is much more important to show you the way of thinking instead of feeding with ready made-up solution.
EDIT
Just in case you fail I decided to add a solution too:
$( "a[href='NEEDED HREF TO SEARCH']" ).parent().addClass('active');
Another option, You can achieve by CSS alone:
a[href$='#tabNeighbourhood']
{
color:red;
}
Fiddle
JQuery method (using :has() selector):
$('ul li:has(a[href="#tabNeighbourhood"])').addClass('Active');
Fiddle
The following code (vanilla js :-) shows you how to add a class to an HTML element which ha specific href value. Just enter in the field the href value you want to search, it will add a class active, example try: #tabSubject or #tabImprovements. I hope it is what you need.
function setActive(){
var elm = document.getElementsByName('findElm')[0],
searchElm = elm.value,
targetStr = 'a[href*="' + searchElm + '"]',
target = document.querySelector(targetStr);
target.classList.add('Active');
}
.Active
{
color:red;
}
<div id="tabs" class="tab_wrapper">
<ul class="nav nav-tabs">
<li>Subject
</li>
<li>Contract
</li>
<li>Neighborhood
</li>
<li>Site
</li>
<li>Improvements
</li>
<li>Supplemental Data
</li>
</ul>
</div>
<input type="text" name="findElm" value="#tabImprovements"><br>
<input type="submit" value="Search" name="submit" onclick="setActive();">
css: Use the nth-child concept(Best Practice)
.tab_wrapper ul :nth-child(3) a {
color:red;
}

How to make selector that find class and data-id=X

<ul>
<li id="RadListBox1_i2" class="rlbItem ui-draggable">
<div class="ui-draggable ui-state-default" data-shortid="1007">
<em>ProductId: </em>
<span>110-01-070-10</span>
<br>
<em>ShortID: </em>
<span class="ShortID" data-shortid="1007">1007</span>
<br>
<em>Product Name: </em>
<span>Clearly Retro Style Colour Name Necklace</span>
<br>
<em>
</div>
</span>
</li>
<li id="RadListBox1_i3" class="rlbItem ui-draggable">
<li id="RadListBox1_i4" class="rlbItem ui-draggable">
</ul>
I need to build selector that find element that contains id=X and disable this item by .draggable('disable');
Some think like this:
find class y where data-shortid=X and make it
$("ul li").find(".ShortID").attr("data-shortid="+X+).draggable('disable');
Answer :
$("span.ShortID[data-shortid="+ShortId+"]").parents("li:first").draggable("disable");
You need to disable the li, not the span, so you need to find the parent:
$("span.ShortID[data-shortid=1007]").parents("li").draggable("disable");
$(".ShortID[data-shortid=1007]")
Above code will return you the element with class="ShortID" and attribute data-shortid="1007"When the element is picked, you can do anything you want with it.
Try this (jQuery Attribute Equals Selector):
$("ul li .ShortID[data-shortid='"+X+"']").draggable('disable');
Use this code:
$("ul li.ShortID[data-shortid="+X+"]").draggable('disable');
EDITED:
var obj = $("ul li span.ShortID");
var ids = obj.attr("data-shortid");
if(ids == X) {
obj.draggable('disable');
}
From JQuery documentation:
$( ",someclass[data-id='yourid']" ).dosomething();
$("ul li").find(".ShortID").attr("data-shortid="+X+).draggable('disable');
Would find all elements that have is inside a ul li that has a class .ShortID.
To grab a element by an attribute and value. You could do
$("div[data-shortid=" + x );
Beware that in your example you have to divs with the same ID.
http://api.jquery.com/attribute-equals-selector/
Btw. Keep using find to nest deeper as in your example, this will help on performence.

Cloning an element multiple times

I have a li element parented to a div with id holder. I need to clone the li multiple times, have all the clones parented to the holder div and change their data-ids. My hierarchy looks like this:
<div id="holder">
<li data-id=0 class="element">
//other nodes
</li>
</div>
How can I clone the li element and than change it's data-id so I get:
<div id="holder">
<li data-id=0 class="element">
//other nodes
</li>
<li data-id=1 class="element">
//other nodes
</li>
<li data-id=2 class="element">
//other nodes
</li>
<li data-id=3 class="element">
//other nodes
</li>
<li data-id=4 class="element">
//other nodes
</li>
<li data-id=5 class="element">
//other nodes
</li>
</div>
-- David
Just use clone and attr:
var holder, li, clone, counter;
holder = $("#holder");
li = holder.find("li:first");
counter;
for (counter = 1; counter <= 5; ++counter) {
clone = li.clone();
clone.attr("data-id", counter);
clone.appendTo(holder);
}
Here's a quick and dirty solution:
http://jsfiddle.net/Epzt9/7/
Also - and I'm surprised no-one else has mentioned this - your containing element for the list items should be a <ul>, not a <div> - <li> tags don't stand on their own, they should belong to a list.
Something along these lines should work:
var clone = $("#holder > li").last().clone();
clone.data("id", parseInt(clone.data("id"), 10) + 1);
$("#holder").append(clone);
It gets a reference to the last li child of #holder and clones that. It then adds 1 to the current value of the data-id attribute, and appends the clone back into #holder.
However, this won't actually change the value of the attribute on the element (if you inspected the DOM, clones would appear to have the same data-id value as the element from which they came). The new value is associated with the element, which is fine if you are using the jQuery data method to obtain this value later. If not, you would need to use attr instead of data to set the value.

Categories