jQuery each array index append to div - javascript

I'm trying to append the values of array I've made into another div but when I append the array value its appending all the values of the array not just the one I've added(by click), any suggestions would be great, thanks in advance!
HTML
<div id="products">
<ul>
<li><p>Lorem 1</p><button class="target">Add</button></li>
<li><p>Lorem 2</p><button class="target">Add</button></li>
</ul>
</div>
<div id="cart">
<ul>
</ul>
</div>
jQuery
$(document).ready(function(){
var array = Array();
$(".target").click(function() {
array.push($(this).siblings('p').text());
$.each(array, function(index, value) {
$("#cart ul").append("<li>"+value+"</li>");
});
});
});
When I click Add on say the first button its displays
Lorem 1
but when I then click the add on the second button it displays
Lorem 1
Lorem 1
Lorem 2

You are adding the items to the array, which makes sense if you want to keep a list of added items, but then you are looping through the array when adding items to the list, which will make it add all items to the items already existing there.
You can just add the last item:
array.push($(this).siblings('p').text());
$("#cart ul").append("<li>" + array[array.length - 1] + "</li>");
or you can clear the list before adding the items:
array.push($(this).siblings('p').text());
$("#cart ul").empty();
$.each(array, function(index, value) {
$("#cart ul").append("<li>" + value + "</li>");
});

Because you loop on each element of the array, so you get all your elements.
Try without the $.each in your click function, it will be better.

If you want to only add one value when the selector $(".target") is clicked, you should do something like
// assuming you want the last value in the array.
var value = array[array.length-1]; // could also do $(this).siblings('p').text()
$("#cart ul").append("<li>"+value+"</li>");
It seems like you might not even need your array, (unless it is being used by some other functions as well).

LIVE DEMO
$(function(){
var array = [];
$(".target").click(function() {
array.push( $(this).siblings('p').text() );
$("#cart ul").append("<li>"+ array[array.length -1] +"</li>");
});
});

Related

Filtering through an array to match the text (jQuery / Javascript)

I have an unordered list called $myList. Every time a string ($entry) is entered into an input, I want to run through the list to see if that string is already in the list. If it is, I want to remove the list item that contains the matching string. Either way, the new string gets added and becomes a new list item.
Here's the most recent thing I tried:
$myList.text().filter($entry).remove();
$myList.append($entry);
It doesn't like that I'm doing .text().filter(), but none of the other things I've tried have worked either.
What's a simple way to accomplish this?
The filter method should act on the list items, not on the text() value, since it is one of the list items you might need to remove. The filter method needs a function as argument. That function should determine whether or not the text() value of the iterated item is the entry text. Then the remove will work:
$('li', $myList).filter(function () {
return $(this).text() == entry;
}).remove();
$('button').click(function () {
var entry = $('input').val();
var $myList = $('ul');
$('li', $myList).filter(function () {
return $(this).text() == entry;
}).remove();
$('<li>').text(entry).appendTo($myList); // add item at end of list
$('input').val(''); // clear input
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input><button>Add</button>
<ul></ul>
$myList.find("li").filter(function() { // for each list item
return $(this).text() === $entry; // pick those who have the text equal to $entry
}).remove(); // remove them
$("<li></li>").text($entry) // create a new list item
.appendTo($myList); // add it to $myList
I used the .each function; it iterates through all the items inside the selector. I didn't use .filter, because I though .each would provide a more intuitive programming experience, as you both want to check if something exists and remove it if it does and append that same item to another list.
$myList = $("#myList");
$entry = $("#entry");
$newList = $("#newList");
$entry.on('input', function () {
entryText = $entry.val();
$myList.find("li").each(function () {
if ($(this).html() == entryText) {
$("<li>")
.append($(this).html())
.appendTo($newList);
$(this).remove();
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Let's filter some tags<br />
<ul id="myList">
<li>css</li>
<li>js</li>
<li>so</li>
<li>sass</li>
<li>haml</li>
</ul>
<input type="text" id="entry" />
<ul id="newList">
</ul>

Delete DOM elements throught loop

I am trying to create a loop which is reponsible to delete DOM elements (one or severals lines into an HTML table) :
<tr class="entireLine><input type="checkbox"></tr>
<tr class="entireLine><input type="checkbox" checked></tr>
<tr class="entireLine><input type="checkbox" checked></tr>
JS
for (var i=0; i<$(".entireLine").length; i++){
// Get the current line of the table
var currentLine = $(".entireLine")[i];
// Get the checkbox in the DOM element
var checkbox = $(currentLine).find("input[type=checkbox]");
// Check the state of the checkbox. If checked, remove the line.
if ( $(checkbox).is(":checked") ) {
$(currentLine).remove();
}
}
This code works fine only when there is one line selected. From 2 lines selected, the second line is not deleted because the index (i) is not good after the first remove.
Where is my mistake ?
You can just find tr with checked checkboxes
$(".entireLine").has('input[type=checkbox]:checked').remove()
In your loop the problem is the expression $(".entireLine").length is evaluated in each iteration, it will reduce the length if item was removed in the previous iteration but the value of i is not reduced so there will be some leftout items
.has()
:checked
Use a jquery each:
$(".entireLine").each(function( index ) {
if ($(this).find("input[type=checkbox]").is(":checked")) {
$(this).remove();
}
});
And correct your HTML, it's not <tr class="entireLine> but <tr class="entireLine"> (You forget the closing ")
Reverse your thinking - instead of looping through all the rows to find selected items, find the selected items then remove their rows:
$(":checkbox:selected").each(function() {
$(this).closest("tr").remove();
});
I would do something like this, instead of doing the for loop. This will find all the checkboxes, and do a $.each and if they are checked, it will remove them. I put checkboxes in its own var for debugging purposes.
var checkboxes = $('input[type=checkbox]');
checkboxes.each(function(){
var $checkbox = $(this);
if ( $checkbox.is(":checked") ) {
$checkbox.remove();
}
})

Get content of 2 classes within 1 class

I have HTML like
<a href="/blabla" class="matchupLink">
<span class="teams"> USA</span>
<span class="teams">Brazil</span>
</a>
I want to get the HTML of the elements with class 'teams' within class 'matchupLink'
I tried
$('.matchupLink').each(function (index, obj) {
var teams = $(this).find('.teams');
console.log(teams.html())
});
But that only returns the first instance of the .teams class within each .matchupLink class. So here it only returns USA and not Brazil.
I want to calculate how many characters both teams class have within each matchupLink class. Because then if characterCount >=20, I want to display ellipses.
What should I be doing?
Thanks
You can combine selectors with the classes
$('.matchupLink .teams')
This will return you an array of objects with the class "teams".
UPDATE
Here's a fiddle that prints to the console the length
$('.matchupLink .teams').each(function(index, item){
var $item = $(item);
var teamNameLength = $item.html().length;
console.log($item.html() + ' length is: ' + $item.html().length);
// if ($item.html().length >= 20){
// ::do logic for ellipses::
// }
});
**note the USA prints out a value of 4 because you have a space before in your example.
UPDATE 2
Fiddle alerting the length of both teams
To get the length of both teams, create a variable outside of the loop and increment it appropriately.
var lengthOfBothTeams = 0;
$('.matchupLink .teams').each(function(index, item){
lengthOfBothTeams += $(item).html().length;
});
alert('Length of both team names is: ' + lengthOfBothTeams);
console.log will work on the first match in the set in your example
you should loop over the teams and not the matches
$('.matchupLink .teams').each(function () {
console.log($(this).html())
});
html() only returns the HTML content of the first matched element in the jQuery object. Use each() to iterate over the element and display their HTML content.
$('.matchupLink .teams').each(function (index, obj) {
console.log($(this).html());
});

Refreshing the order of an ordered list, after appending a list item

jsFiddle example
I'm attempting to use an ol to display several, dynamic, list items. Upon appending a list item using jQuery, I'd have hoped that the browser would've refreshed the ordered list, however it doesn't appear to be.
<ol>
<li value="1">First</li>
<li value="2">Second</li>
<li value="4">Forth</li>
</ol>
After appending <li value="3">Third</li>, the resulting order is:
// First
// Second
// Forth
// Third <-
Do I need to trigger a re-order, or is the order only calculated upon rendering the page / adding the list DOM element?
Note: I'm using Chrome 28.0.1500.95m
Firstly, note that value is not a valid attribute of li, so your code is invalid. You should use a data attribute for any non-standard attributes you require, the you need to write a sorter function. Try this:
$('#addThird').one('click', function() {
$('ol').append('<li data-value="3">Third</li>');
sortItems();
});
var sortItems = function() {
var $items = $('ol li');
$items.sort(function(a, b) {
var keyA = $(a).data('value');
var keyB = $(b).data('value');
return (keyA > keyB) ? 1 : 0;
});
$.each($items, function(index, row){
$('ol').append(row);
});
}
Updated fiddle
This sorts by the data-value attribute of the element, but that can be amended as required.

jQuery return only <li> element text

I have added an .on() function to my dynamically added list elements with jQuery. The problem I'm facing is that the button that triggers the click lives inside the dynamically added li elements and therefore
$(this).parent().text()
returns the text from the li element as well as the button's text.
See the following fiddle: http://jsfiddle.net/TL5TR/
How can I get around this problem and only display the li text (without the button text)? Would I have to rework my code in a way that button will be placed outside the li tag?
Update
Before I accept one of these answers -- all of them which are working by the way, so thank you, can you also explain to me what are the pros/cons of using one method or the other - i.e. textNode vs span tag.
I think the easiest solution would be to add span around your text:
$('#list').append("<li><span>" + item + "</span><button class='clickme'>Click me</button></li>");
And then:
$(this).siblings("span").text()
If the textNode is the previous sibling of the clicked button you can use previousSibling property.
$("#list").on('click', 'button', function() {
alert(this.previousSibling.nodeValue);
});
http://jsfiddle.net/cZk8H/
var array = ["First", "Second", "Third"];
$.each(array, function(index, item) {
$('#list').append("<li><span>" + item + "</span> <button class='clickme'>Click me</button></li>");
});
$("#list").on('click', 'button', function() {
alert($(this).parent().find("span").text());
});
put the text in a span tag
http://jsfiddle.net/TL5TR/2/
Try Adding text wrapped in a span. And you should easily address the sibling's value, later:
var array = ["First", "Second", "Third"];
$.each(array, function(index, item) {
$('#list').append("<li><span>" + item + "</span><button class='clickme'>Click me</button></li>");
});
$("#list").on('click', 'button', function() {
alert($(this).siblings().text());
});
http://jsfiddle.net/TL5TR/1/
PROS (of using span) : Better Management of text inside the li. You actually refer to the content enclosed in the span always....
PROS(of not using span) : Lesser tags in the HTML that you need to take care of. Although in this case I would say it's more of a micro management to think about it.
Or instead of separating it out, you could just do this:
var array = ["First", "Second", "Third"];
$.each(array, function(index, item) {
$("<li>" + item + " <button class='clickme'>Click me</button></li>")
.appendTo('#list')
.on('click', function() { alert(item); });
});
Unless of course you are adding these some other way. Then I would use one of the other suggested answers.
You can clone the element and remove the children elements:
$(this).parent().clone().children().remove().end().text()

Categories