w3schools example regarding jQuery callback function with index - javascript

In this example, a jQuery function is presented that when clicked, it prints out the old text and the new text of the element, plus the index of the current element. I'm pretty sure the index must increment (because new elements are being added). But upon testing the code, why is the index showing 0 all the time?
$("#btn1").click(function(){
$("#test1").text(function(i,origText){
return "Old text: " + origText + " New text: Hello world!
(index: " + i + ")";
});
});
$("#btn2").click(function(){
$("#test2").html(function(i,origText){
return "Old html: " + origText + " New html: Hello <b>world!</b>
(index: " + i + ")";
});
});

Have'nt you heard about w3fools.
I recommend you to follow jQuery official help.
function(index, text)
A function returning the text content to set. Receives the index position of the element in the set and the old text value as arguments.
The reason here index is always zero is it is only one p element so it always index 0. Lets say you have multiple li in list, on using index:
$( "ul li" ).text(function( index ) {
return "item number " + ( index + 1 );
});
will produce:
<ul>
<li>item number 1</li>
<li>item number 2</li>
<li>item number 3</li>
</ul>

Here is the same example re-written to explain index...
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("#btn1").click(function(){
$(".test1").text(function(i, origText){
return "Old text: " + origText + " New text: Hello world! (index: " + i + ")";
});
});
$("#btn2").click(function(){
$(".test1").html(function(i, origText){
return "Old html: " + origText + " New html: Hello <b>world!</b> (index: " + i + ")";
});
});
});
</script>
</head>
<body>
<p>This is a <b>bold</b> paragraph.</p>
<ul>
<li class="test1" >item number 1</li>
<li class="test1" >item number 2</li>
<li class="test1" >item number 3</li>
</ul>
<p class="test1">This is another <b>bold</b> paragraph.</p>
<button id="btn1">Show Old/New Text</button>
<button id="btn2">Show Old/New HTML</button>
</body>
</html>
I'm studying on W3schools right now and had the same question. Googling led me to this question and the answers are kind of cryptic. after fiddling with the code i found this and thought someone else might need a clearer answer.

Related

With .each() iterate through a list and create select options with the li's text

I'm trying to iterate through a list, get the text of it's items and create and then inside a select, create an option with each of the list items
text, but I just get the last one.
$(".categories ul li a").each(function(i){
console.log($(this).text());
$(".filters-select").html("<option value=." + $(this).text() + ">" + $(this).text() + "</option>" );
})
Why does the console log works and outputs the 4 items that I have, but it's not creating 4 option tags and just one?
The HTML structure looks like this:
<li class="categories">Categorías
<ul>
<li class="cat-item cat-item-4">novedades
</li>
<li class="cat-item cat-item-2">Nueva
</li>
<li class="cat-item cat-item-5">Otros
</li>
<li class="cat-item cat-item-1">Sin categoría
</li>
</ul></li>
You should use .append() and not .html() since html will override everytime its called.
$(".filters-select").append("<option value=." + $(this).text() + ">" + $(this).text() + "</option>");
Demo
$(".categories ul li a").each(function(i) {
console.log($(this).text());
$(".filters-select").append("<option value=." + $(this).text() + ">" + $(this).text() + "</option>");
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<li class="categories">Categorías
<ul>
<li class="cat-item cat-item-4">novedades
</li>
<li class="cat-item cat-item-2">Nueva
</li>
<li class="cat-item cat-item-5">Otros
</li>
<li class="cat-item cat-item-1">Sin categoría
</li>
</ul>
</li>
<select class="filters-select"></select>
If you use html() this is what happen for EACH loop:
You get the data you want
You create your option
You change the HTML of ".filter-select" by the current option
So each loop you delete the previous.
This is an other solution than using append() you can use I think:
var option_content = ""; // I create an empty var
$(".categories ul li a").each(function(i){
option_content += "<option value=." + $(this).text() + ">" + $(this).text() + "</option>";
});
$(".filters-select").html(option_content);
You build your data for each loop, then you add it in your "filter-select" element.
Hope it helps

Jquery - Filtering cascaded list based on class (Seprate list and nested list)

This is my sample HTML trying achieve some filtering logic for business functionality. We have a Complex structure HTML and i just hard coded some sample HTML to make some example out of it
<ol class="list_1">
<li class="page_1">one</li>
<li class="page_1">two</li>
<li><span class="ing_page_1">three
</span><ol class="list_2">
<li class="page_1">sub 1</li>
<li class="page__1">sub 2</li>
<li class="page__2">sub 3</li>
</ol>
</li>
<li class="page_2">four</li>
<li class="page_2">five</li>
</ol>
Am trying to Filter the list to get below results(DOM Elements).
Query to get DOM elements as results so i can add some attribute for each list
List 1 and its pages(List 1 - One, Two , Three , Four , Five)
List 2 and its pages(List 2 - Sub 1,Sub 2 , Sub 3)
Class 'ing_page_1' also belongs to page 1 but when i have nested structure i have some special class created with ing_ to process some other logic and it is a constant
have added my fiddle(https://jsfiddle.net/pjagana/ubk8ngha/6/) with console statements as my filter always result in sub list as well. Any help would be helpful
You must iterate through all immediate child lis and remove non span (or attr*=ing_page) then get the text.
Maybe you can try this:
function getList(parent) {
var temp = parent + " and its pages (" + parent + " - ";
$("." + parent + ' > li').each(function() { // Find all immediate li children
// Create a clone
var $clone = $(this).clone();
// remove non-span elements and remove them so only span elements would be left (you can replace this with ':not([class&=ing_page])' or something similar if needed)
$clone.find(':not(span)').remove();
// clean the text
temp += $.trim($clone.text().replace(/\s{2,}/gim, " "));
if ($(this).is(':not(:last-child)'))
temp += ", ";
});
return temp + ")";
}
console.log(getList('list_1') + "\n" + getList('list_2'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ol class="list_1">
<li class="page_1">one</li>
<li class="page_1">two</li>
<li>
<span class="ing_page_1">three</span>
<ol class="list_2">
<li class="page_1">sub 1</li>
<li class="page__1">sub 2</li>
<li class="page__2">sub 3</li>
</ol>
</li>
<li class="page_2">four</li>
<li class="page_2">five</li>
</ol>

Appending an element with an ID that matches a class

I found a couple of other questions that were similar but I'm still not getting the needed result.
So I have a list:
<ul>
<li class="class1"></li>
<li class="class2"></li>
<li class="class3"></li>
<li class="class4"></li>
<li class="class5"></li>
</ul>
And then I have a set of dynamically-generated spans with IDs that match those classes.
<span id="class1"></span>
<span id="class2"></span>
<span id="class3"></span>
<span id="class4"></span>
<span id="class5"></span>
I need to append each of those spans to their matched list item. So .class1 to #class1. I figured there would be something easy like:
$(this).find('#' + this.className).appendTo(this);
Any suggestions?
$("li[class^='class']").on("click", function(){
$("#"+ this.className).appendTo(this);
});
jsBin demo
NOTE: your code will break as soon you add another class to your element:
<li class="class2 something"></li>
cause than you'll be erroneously searching for an ID element called #class2 something.
You'd better go using data-* attributes instead of class names.
$("[data-get]").on("click", function(){
$("#class"+ this.dataset.get).appendTo(this);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li data-get="1" class="class">1</li>
<li data-get="2" class="class">2</li>
<li data-get="3" class="class">3</li>
<li data-get="4" class="class">4</li>
<li data-get="5" class="class">5</li>
</ul>
<span id="class1">s1</span>
<span id="class2">s2</span>
<span id="class3">s3</span>
<span id="class4">s4</span>
<span id="class5">s5</span>
My solution, if I understood correctly:
$(function() {
$("span[id^='class']").each(function() {
var liObj = $("li[class='" + this.id + "']");
if (liObj.length == 1) {
$(this).appendTo(liObj);
}
});
}
Sorry for not posting all of my code. It didn't seem necessary. The answer is:
$( '#' + this.className ).appendTo('.' + this.className);
I knew it was something stupidly simple. Thanks for everyone who responded!

Count the number of <div> elements inside <li>

I need to know how many <div> elements are in each <li>. So something like that:
<ul>
<li>
<div> Some image 1 </div>
<div> Some image 2 </div>
<div> Some image 3 </div>
</li>
<li>
<div> Some image 4 </div>
<div> Some image 5 </div>
</li>
<li>
<div> Some image 6 </div>
<div> Some image 7 </div>
<div> Some image 8 </div>
<div> Some image 9 </div>
</li>
</ul>
The output of the function:
First <li> has 3 <div>
Second <li> has 2 <div>
Third <li> has 4 <div>
var lengths = $('li').map(function(){
return $(this).find('div').length;
}).get();
Live DEMO
Comments:
// Make an array when the input for every iteration is a <li>
$('li').map(
// Every element in the array is the amount <div>s inside the current <li>
return $(this).find('div').length;
// Produce the arry.
.get();
If you want to produce something similar to what you want easily:
$('li').each(function() {
var length = $(this).find('div').length;
$('<div> ' + length + ' li has ' + length + 'divs </div>').appendTo('#output');
});​
Live DEMO
Output:
3 li has 3divs
2 li has 2divs
4 li has 4divs
Given a jQuery object representing your <li>, item, you can find out the number of <div>s that it contains just by doing:
item.find('div').length
But if you'd like a function with that exact output, you'll need a number → English library. Or, if you'll have exactly three, get your <ul> as list and do this:
var items = list.find('li');
'First <li> has ' + items.eq(0).find('div').length + ' <div>';
'Second <li> has ' + items.eq(1).find('div').length + ' <div>';
'Third <li> has ' + items.eq(2).find('div').length + ' <div>';
$('li').each(function() {
console.log($('div', this).length);
});​
jsFiddle example.
$('li').each(function(i){
console.log('<li> ' + i + ' has ' + $(this).children('div').length + 'divs');
});

Appending wrapped elements doesn't include wrapper

I am trying understand why the .wrap() function in my basic table of contents function isn't working. The function filters headers from a textarea and places them in an iframe, and the basic part works. But whereas my desired output is this:
<ul>
<li class="toc_h2">This is an h2</li>
<li class="toc_h3">This is an h3</li>
<li class="toc_h1">This is an h1</li>
</ul>
What I am actually getting is this:
<ul>
<h2>This is an h2</h2>
<h3>This is an h3</h3>
<h1>This is an h1</h1>
</ul>
How can I fix this/what am I misunderstanding? The code is here and at http://jsfiddle.net/supertrue/JgWxJ/
headers.each(function(i) {
$(this).wrap('<li class="toc_' + this.nodeName.toLowerCase() + '"></li>').appendTo(toc);
});
You can change this:
$(this).wrap('<li class="toc_' + this.nodeName.toLowerCase() + '"></li>').appendTo(toc);
to this:
$('<li class="toc_' + this.nodeName.toLowerCase() + '"></li>').html(this).appendTo(toc);
Here's your fiddle: http://jsfiddle.net/JgWxJ/7/
Alternatively, you could just add .parent() before appending:
$(this).wrap('<li class="toc_' + this.nodeName.toLowerCase() + '"></li>').parent().appendTo(toc);
...and here's the fiddle: http://jsfiddle.net/JgWxJ/10/

Categories