Here's how the HTML markup looks like
<ul>
<li>red</li>
<li>green</li>
<li>
<ul>
<li>banana</li>
<li>pineapple</li>
<li>peanut</li>
</ul>
</li>
<li>blue</li>
<li>
<ul>
<li>sun</li>
<li>mars</li>
<li>earth</li>
</ul>
</li>
<li>orange</li>
</ul>
how do I count direct children (<li>) in this list? (items containing red,green,blue,orange) ?
Try this:
$('ul > li').length;
'ul > li' selector point only first level of children i.e direct children for all ul.
or
$('ul').children().length;
If your code is string variable like
var html = '<ul><li>.....';
Then
$('ul > li', $(html)).length;
NOTE: Above code will find all li
To find only first level of li use:
$('ul:not(li > ul)').children().length;
You can also use:
$('ul:not(li > ul) > li').length
For html variable string:
$(html).children('ul > li').length;
var ul = document.querySelector('ul');
var count = 0;
for (var ch = ul.firstChild; ch; ch = ch.nextSibling)
if (ch instanceof HTMLLIElement) count++;
Use this:
$("ul > li").length
Other way:
$("ul").children().length
In JQuery documentation you can also find size() method to get the number of elements. However, it is better to use length, since it is simply faster.
The first ul element can be taken by :first selector. Another way is to set the concrete <ul> element ID, and address it with #element_id selector.
DEMO: http://jsfiddle.net/xDYn9/
Related
I have a ul as navigation with a few li elements.
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
Although I got the same amount of div elements, that I can target with .scrollTo( "number of div" ), starting by 0. I could do it on my own this way:
$("ul li:nth-child(1)").on('click', function(){
sliderInstance.goTo(0);
});
$("ul li:nth-child(2)").on('click', function(){
sliderInstance.goTo(1);
});
$("ul li:nth-child(3)").on('click', function(){
sliderInstance.goTo(2);
});
$("ul li:nth-child(4)").on('click', function(){
sliderInstance.goTo(3);
});
But that seems to be neither smart nor efficient. Imagen I have about twenty div and li elements. Is there a good tweak combining .size(), .length() or something else I am not aware of?
Just for diversity:
var $li = $('ul li').on('click', function (event) {
sliderInstance.goTo($li.index(this));
})
i would use onclick event
<ul id="navigation">
<li onclick="scrollTo('#yourTargetAnchor1')"></li>
<li onclick="scrollTo('#yourTargetAnchor2')"></li>
<li onclick="scrollTo('#yourTargetAnchor3')"></li>
<li onclick="scrollTo('#yourTargetAnchor4')"></li>
</ul>
you can also generate it, but in most cases a hardcoded navigation is not too bad. to generate it i would do like this:
var navArr = $('#navigation').children().length;
for (var i = 0; i < navArr; i++) {
$('#navigation').children()[i].click(function(){
scrollTo('#yourTargerAnchor'+i);}}
not tested but should do the job. hope i could help ;)
I am trying to find all top li from html .I have this mark up
<ul class="chapters">
<li>
tc_1
</li>
<li>
tc_2<ul>
<li>tc_1_1</li>
<li>tc_1_2</li>
<li>tc_1_3</li>
</ul>
</li>
<li>
tc_3
</li>
</ul>
Expected Answer: tc_1 ,tc_2,tc_3
I tried like that actually I inspect and write my code on console .
I tried like that $('li') and I get null
Then I put a class attribute "chapters" on ul then try like this
$(".chapters") again and I got null.
how to achieve this ?
You could iterate through the childNodes of the topmost li elements and filter their first textNode:
var textArray = $(".chapters > li").map(function() {
var nodes = this.childNodes, len = nodes.length;
for ( var i = 0; i < len; i++ ) {
if ( nodes[i].nodeType === 3 && $.trim(nodes[i].nodeValue).length ) {
return $.trim(nodes[i].nodeValue);
}
}
}).get();
console.log(textArray.join());
Here is a demo.
$('.chapters > li').each(function(){
alert($(this) .clone()
.children()
.remove()
.end()
.text());
});
JSFIDDLE
for more explanation you can read http://viralpatel.net/blogs/jquery-get-text-element-without-child-element/
This locates the ul, takes its immediate children (each of the lis), then removes any subchildren, .end(), to return to the lis, and .text() to get the contents.
$("ul").clone().children().children().remove().end().text()
This returns
"tc_1
tc_2
tc_3"
because of the line breaks and whitespace in between.
$(".chapters li").text()
should work.
I know there are dozens of similar topics but I am so dumb I can't learn anything from it.
Other words: My code is just mean and doesn't work with any fixes published online. ;)
My HTML:
<ul id="main_menu">
<li class="menu-item">Link 1</li>
<li class="menu-item">Link 2</li>
<li class="menu-item">Link 3</li>
<li class="menu-item">Link 4</li>
</ul>
and how the LI should look after JS does its magic:
...
<span data-title="Link 1">Link 1</span>
...
JS/JQ mission:
add class="roll-link" to every A
add SPAN right after A tag
add data-title="xxx" attribute to SPAN with A value (text exactly the same as the A)
close SPAN tag before A closing tag
My JS try:
var menuLis = document.querySelectorAll("ul.main_menu li"); //It's an Array right?
for(var i=0; i<menuLis.length; i++) {
this.nextChild.setAttribute('class', 'rollink');
var span = document.createElement('span');
this.nextChild.nextSibling.insertBefore(span); //Auto-closing </span> may be an issue...
span.setAttribute('data-title', hrefvalue[i]); //but how to get value?
}
It may be total crap but I have completely no experience in JS/JQ, only had few hours of basic training online...
Thanks for reading and even bigger thanks for trying to help.
Greets!
it should be as simple using jQuery(because you tagged it with jQuery)
jQuery(function ($) {
$('#main_menu li a').addClass('roll-link').wrapInner(function () {
return $('<span />', {
'data-title': $.trim($(this).html())
});
})
})
Demo: Fiddle
See
selectors
addClass()
wrapInner()
dom ready
To make your code work, first the main_menu is an id, not a class so you need to use id selector, then try
var as = document.querySelectorAll("#main_menu li a");
for (var i = 0; i < as.length; i++) {
as[i].className = 'rollink';
var span = document.createElement('span');
span.setAttribute('data-title', as[i].innerHTML);
span.appendChild(as[i].firstChild);
as[i].appendChild(span)
}
Demo: Fiddle
$('#main_menu > li > a').each(function () {
var text = $(this).addClass('roll-link').contents().first();
text.wrap($('<span>').attr('data-title', text.text()));
});
DEMO: http://jsfiddle.net/Bw723/
Here is your solution with pure Javascript.
//get the li elements
var menuLis = document.getElementById("main_menu").getElementsByTagName('li');
for(var i=0; i<menuLis.length; i++) {
menuLis[i].firstChild.setAttribute('class', 'rollink');
var span = document.createElement('span');
span.setAttribute('data-title', menuLis[i].innerHTML);
//If you want to get href of a then use this one.
//span.setAttribute('data-title', menuLis[i].href);
//appending the span into a
menuLis[i].firstChild.appendChild(span);
}
DEMO
I'm trying to insert a new div after the second list item. But I also want to close the </ol> before it and open a new <ol> right after it.
This:
<ol>
<li>test 1</li>
<li>test 2</li>
<li>test 3</li>
<li>test 4</li>
</ol>
Should become this:
<ol>
<li>test 1</li>
<li>test 2</li>
</ol>
<div>NEW DIV</div>
<ol>
<li>test 3</li>
<li>test 4</li>
</ol>
jQuery:
var el = $('ol li:eq(1)');
el.after('<div>NEW DIV</div>');
Here's my demo: http://jsfiddle.net/5hhr2/
Is there any way to do this with jQuery?
I already tried to do after('</ol><div>NEW DIV</div><ol>) but that obviously does not work, as it has been discussed here: Using .after() to add html closing and open tags.
Try
var $lis = $('ol li');
$lis.filter(':lt(2)').unwrap().wrapAll('<ol/>').closest('ol').after('<div>NEW DIV</div>');
$lis.filter(':gt(1)').wrapAll('<ol/>');
Fiddle
If you want to chain all of them then:
var $lis = $('ol li');
$lis.filter(':lt(2)') //get all the li's with index less than 2 i.e your number
.unwrap() //unwrap it
.wrapAll('<ol/>') //wrap them in ol
.closest('ol').after('<div>NEW DIV</div>').end().end() //append div next to the ol and go back in the chain to the first list of li's
.filter(':gt(1)') //filter to get remaining items
.wrapAll('<ol/>'); //wrap them all in a new ol
Fiddle
var $oldOL = $("ol"),
$newOL = $("<div><ol></ol><div>NEW DIV</div><ol></ol></div>");
$newOL.children().eq(0).append($oldOL.children().slice(0, 2)).end().eq(2).append($oldOL.children().slice(0, 2));
$oldOL.replaceWith($newOL.children());
Here is a demo: http://jsfiddle.net/5hhr2/9/
The idea is to create a new set of lists with a div between them and replace the old list with the new HTML structure. The numbers on the ordered list restart now since there are two <ol /> elements.
var el = $('ol li');
var elSize = el.length;
var html = '<ol>';
el.each(function(i){
if(i > 0 && i % 2 == 0 && i < elSize) {
html += '</ol><div>NEW DIV</div><ol>';
}
html += '<li>' + $(this).text() + '</li>';
});
html += '</ol>';
$('body').html(html);
jsfiddle
You need to create two lists and insert the new div between them. Here's one of the many ways to do thin by adding the new list before and after the original, then replacing the original with new div:
var list = $('ol'),
newList = $('<ol />'),
items = list.children(),
items1 = items.slice(0,2),
items2 = items.slice(2),
newDiv = $('<div>NEW DIV</div>');
list
.before( newList.clone().append( items1 ) )
.after( newList.clone().append( items2 ))
.replaceWith( newDiv );
http://jsfiddle.net/5hhr2/12/
Or, even better! Create a new list, append it after the original, and move a part of list items to it. Then append the new div after the original list.
var list = $('ol'),
newList = $('<ol />'),
items = list.children(),
newDiv = $('<div>NEW DIV</div>');
list.after(
newList.append(
items.slice(2).remove()
))
.after( newDiv );
http://jsfiddle.net/5hhr2/15/
Try this, this will be help you, It is easy to understand, here i'm doing first find second item of the list the add div on it using append method..
$('ol li').eq(1).append('<div>New Div</div>');
Fiddle Here
I have 3 Columns of ULs each a Dynamic UL container that can have anywhere from 0-9 LI containers (eventually more). All my LI elements have an attribute "rel" which I am trying to ultimately find that attribute and use it for something else on all LI elements within that parent DIV. I do eventually want to find more based on each but for not the very least the rel.. Any Ideas how I can achieve that with jQuery? Example:
<ul id="column1">
<li rel="1">Info</li>
<li rel="2">Info</li>
<li rel="3">Info</li>
</ul>
<ul id="column2">
<li rel="4">Info</li>
<li rel="5">Info</li>
<li rel="6">Info</li>
</ul>
<ul id="column3">
<li rel="7">Info</li>
<li rel="8">Info</li>
<li rel="9">Info</li>
</ul>
these elements are all sortable as well. So when I get a list of them I want to also keep them in the order they were found from top to bottom of each column.
I have tried find(), parent(), and similar, maybe I am approaching it wrong. But its still worth mentioning to help come up with an idea
Are you thinking about something like this?
$('ul li').each(function(i)
{
$(this).attr('rel'); // This is your rel value
});
var column1RelArray = [];
$('#column1 li').each(function(){
column1RelArray.push($(this).attr('rel'));
});
or fp style
var column1RelArray = $('#column1 li').map(function(){
return $(this).attr('rel');
});
html
<ul class="answerList" id="oneAnswer">
<li class="answer" value="false">info1</li>
<li class="answer" value="false">info2</li>
<li class="answer" value="false">info3</li>
</ul>
Get index,text,value
js
$('#oneAnswer li').each(function (i) {
var index = $(this).index();
var text = $(this).text();
var value = $(this).attr('value');
alert('Index is: ' + index + ' and text is ' + text + ' and Value ' + value);
});
$('li[rel=7]').siblings().andSelf();
// or:
$('li[rel=7]').parent().children();
Now that you added that comment explaining that you want to "form an array of rels per column", you should do this:
var rels = [];
$('ul').each(function() {
var localRels = [];
$(this).find('li').each(function(){
localRels.push( $(this).attr('rel') );
});
rels.push(localRels);
});