How to find deeply embedded children with jquery - javascript

I have a dom tree that looks like this:
<div class="specs>
<ul>
<li>
<a></a>
</li>
<li>
<a></a>
</li>
</div>
How would I use jquery to go through each anchor tag and add a target="_blank";
Adding classes is not an option. I'm using node with an api call off to a cms to pull in markdown and parse it into html.
What I have:
$('#specs-container.specs > ul > li').children('a').each(function () {
$(this).attr('target', '_blank');
});
Thanks!

You can write it like this:
$('.specs ul li a').attr('target', '_blank');
But don't forget to fix your HTML code (quotes and missing closing </ul> tag).
HTML should be like this:
<div class="specs">
<ul>
<li>
<a></a>
</li>
<li>
<a></a>
</li>
</ul>
</div>

There were a few issues with your code. Firstly, you were missing a closing " for your specs element in the HTML, next you were missing a closing </ul> at the end of your list, and finally your jQuery code was targeting an ID which does not exist in the HTML you provided.
$(function() {
$('.specs > ul > li').children('a').each(function () {
$(this).attr('target', '_blank');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="specs">
<ul>
<li>
<a>Test</a>
</li>
<li>
<a>Test 2</a>
</li>
</ul>
</div>

Related

Jquery combining text from parent li elements on click to get path

I am struggling with jquery a little. I have an unordered list that looks like this.
<ul>
<li class="folder">Folder: Test</li>
<ul>
<li class="folder">Folder: Archive</li>
<ul>
<li class="file">
<div class="filename">HelloWorld.docx</div>
<div class="size">11.79kiB</div>
<div class="date">2021-01-12 09:31:34</div>
</li>
<li class="file">
<div class="filename">HelloWorld1.docx</div>
<div class="size">12.79kiB</div>
<div class="date">2021-01-11 09:31:34</div>
</li>
</ul>
</ul>
</ul>
Which looks like this
Folder: Test
Folder : Archive
HelloWorld.docx
11.79kiB
2021-01-12 09:31:34
HelloWorld1.docx
12.79kiB
2021-01-11 09:31:34
When I click on any of the li's with the class of "file" I want to look back and work out what the path structure is by finding the parent li's that have the class "folder".
I have tried various combinations but cannot get it
This is what I am working with at the moment
$(document.body).on('click',"li.file",function (e) {
console.log("clicked");
$(this).parents("li.folder").each(function() {
console.log($(this).text());
});
});
Ultimately i want to get back a full path with the parent folder and the filename in a variable.
e.g. pathtofile = /Test/Archive/HelloWorld.docx
Here is a jsfiddle https://jsfiddle.net/e5d7bcyz/
Thanks
Before approaching your question you first need to correct the HTML. ul elements cannot be children of other ul elements. You need to wrap the ul within their associated li.
You will also need to wrap the folder names in another element, such as a span, in order for the text to be easily retrievable. This would be possible with your current HTML by trawling through text nodes, however that is messy code to write and very brittle. A simple HTML change is the best approach there.
Finally, you can loop through the parent li elements of the clicked .file and reverse their order to get the path in the right format. From there you can append the filename of the selected file. Try this:
$.fn.reverse = [].reverse;
$(document).on('click', "li.file", function(e) {
let $file = $(this);
let $path = $file.parent().parents('li').reverse();
let path = $path.map((i, el) => $(el).children('span').text().trim()).get();
path.push($file.children('.filename').text().trim());
console.log(path.join('/'));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="folder">
<span>Test</span>
<ul>
<li class="folder">
<span>Archive</span>
<ul>
<li class="file">
<div class="filename">HelloWorld.docs</div>
<div class="size">11.79kiB</div>
<div class="date">2021-01-12 09:31:34</div>
</li>
<li class="file">
<div class="filename">HelloWorld1.docs</div>
<div class="size">12.79kiB</div>
<div class="date">2021-01-11 09:31:34</div>
</li>
</ul>
</li>
</ul>
</li>
</ul>
Well, the LI you're looking for are not really the parents as they're not wrapping the current li.file element.
<ul>
<li class="folder">Folder: Archive</li> // You close the LI tag. So it's not a parent of the rest of the code.
<ul>
<li class="file">
Try to wrap the rest of the code with the LI tag:
<ul>
<li class="folder">Folder: Test
<ul>
<li class="folder">Folder: Archive
<ul>
<li class="file">
<div class="filename">HelloWorld.docx</div>
<div class="size">11.79kiB</div>
<div class="date">2021-01-12 09:31:34</div>
</li>
<li class="file">
<div class="filename">HelloWorld1.docx</div>
<div class="size">12.79kiB</div>
<div class="date">2021-01-11 09:31:34</div>
</li>
</ul>
</li> //closing the second parent: Folder: Archive
</ul>
</li> //closing the first parent: Folder: test
</ul>
As far as I know it's valid HTML code.
And then those li.folder elements would be actually parents.

How can I select the first specific inner element?

Here is my HTML?
<ul>
<li>
<a href="./link1">
<div>something</div>
<span>link</span>
</a>
</li>
</ul>
And this is my jQuery code:
$('li').on('click', function(){
var link = $(this).find('a').attr('href');
})
As you see, there is two <a> tags. And .find() refersh to both of them. While I just want to select the <a> which is right inside (one level) in the <li> tag. So expected result is ./link.
What alternative should I use instead of .find() ?
You can use the direct descendant selector.
$('li').on('click', function(){ var link = $(this).find('> a').attr('href'); })
Try with eq(0) .It will get the first a tag
Or
Do with first('a')
$(this).children().first('a').attr('href')
$('li').click(function(){
console.log($(this).children('a').eq(0).attr('href'))
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>click
<a href="./link1">
<div>something</div>
<span>link</span>
</a>
</li>
</ul>
Method 1: Using Jquery's children and first
$('#myList').on('click', function() {
var link = $('#myList').children('a').first();
console.log(link.attr('href'));
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<ul>
<li id="myList">
<a href="./link1">
<div>something</div>
<span>link</span>
</a>
</li>
</ul>
Method 2: Using the immediate children selector >
$('#myList').on('click', function() {
var link = $('li > a:first');
console.log(link.attr("href"));
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<ul>
<li id="myList">
<a href="./link1">
<div>something</div>
<span>link</span>
</a>
</li>
</ul>
the first specific element
What alternative should I use instead of .find() ?
$(this).find('a:first')
seems like only logical solution and easy to read by developer
Don't do so. How is the browser meant to know which link to follow? It'd be invalid HTML
I suggest you using this instead:
startmiddleend
As you can see start and end are linked to page1 but the middle points to page2.

jquery, move element to closest div

I want to move some span elements to closest div. I found the solution to my problem but it does not work for me. I have some Html code:
<ul>
<li>
<a><span>Some info</span></a>
</li>
<div class="cl1">...</div>
<li>
<a><span>Some info 2</span><a>
</li>
<div class="cl1">
...
</div>
...
</ul>
and to move <span> like this:
$('span').each(function () {
$(this).parent().parent().closest('.cl1').append(this);
})
but nothing happened. Any help would certainly be appreciated
you can't put a div in a ul, only li's.
your html has to be valid (a's, ul need to be closed)
Closest searches anscetors, not siblings.
since your markup is not valid as is, i'm not sure if you want the divs in the list or not. This example removes them from the lis, which breaks the list into two lists.
$('button').click(function() {
$('span').each(function() {
var $div = $(this).closest('ul').siblings('.cl1');
$(this).clone().appendTo($div);
$(this).remove();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>
<a><span>Some info</span></a>
</li>
</ul>
<div class="cl1">...</div>
<ul>
<li>
<a><span>Some info 2</span></a>
</li>
</ul>
<div class="cl1">...</div>
<button>Do Stuff</button>

get descent li anchor tag text using jquery

I have markup of ul and li. what I need to do is get text value from direct descentc li a text only. Expected result is a,b,c. fiddle
jquery
$(function(){
$('ul').first().find(' > li').each(function(){
alert($('a',this).text())
})
})
HTML
<ul>
<li><a>a</a>
<ul>
<li><a>a1</a></li>
<li><a>a2</a></li>
</ul>
</li>
<li><a>b</a></li>
<li><a>c</a></li>
</ul>
Use .children() instead which travels a single level down the DOM tree. Created a snippet for you:
$(function() {
$('ul').first().children('li').each(function() {
alert($(this).children('a').text())
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li><a>a</a>
<ul>
<li><a>a1</a>
</li>
<li><a>a2</a>
</li>
</ul>
</li>
<li><a>b</a>
</li>
<li><a>c</a>
</li>
</ul>

jQuery filter(this.hash) when not an <a> tag

<ul>
<li class="active"><a href="#block1">1<a/> </li>
<li><a href="#block2">2<a/> </li>
<li>3</li>
<ul>
<div id="block1">
Block1
</div>
<div id="block2">
Block2
</div>
$('ul li:has(a)').on('click', function(e){
$(this).closest('li').addClass('active').siblings('li').removeClass('active');
$('*[id^="block"]').hide();
.filter(this.hash).show(); //WRONG//
e.preventDefault();
});
ONLINE SAMPLE
I know this would be easy to make the jQuery to just click on a tag and .filter(this.hash).show(); ,
$('ul li a').on('click', function(){
$('*[id^="block"]').hide().filter(this.hash).show();
}
but I want to know & learn if there is another method to make this works. Thanks!
Your HTML is incorrect, which causes a lot of problems:
You are using <a/> instead of </a>.
You are using <ul> instead of </ul>.
You are using $('*[id^="tab"]').hide(); to try to hide the elements, but the identities are block1 are block2, not tab1 and tab2.
You are using closest("a") to try to find the link, but the link is inside the list item, not surrounding it.
Corrected HTML:
<ul>
<li class="active">1 </li>
<li>2 </li>
<li>3</li>
</ul>
<div id="block1">
Block1
</div>
<div id="block2">
Block2
</div>
Corrected Javascript:
$('*[id^="block"]').hide();
$('*[id^="block"]:first').show();
$('ul li:has(a)').on('click', function (e) {
$(this).addClass('active').siblings('li').removeClass('active');
$('*[id^="block"]').hide();
$($(this).find("a").attr('href')).show();
e.preventDefault();
});
Demo: http://jsfiddle.net/Y2TaT/2/

Categories

Resources