I want to add an event listener to my unordered list elements with jQuery. When one of the list elements are clicked another unordered list is checked whether it has the clicked element from the former list, more correctly the clone of it, a list element with same text. If the latter list has it nothing happens, however if it does not have it, a copy of it is added to this latter unordered list.
I try to achieve it with each() but cannot manage to success the conditional append() and the case of starting with an empty selecteds list.
I need the latter list, selecteds, be empty once.
How can this be achieved?
$("ul#list li").on("click", function(event) {
var t = $(event.target).text();
if ($("ul#selecteds li").length == 0) {
$("ul#selecteds").append("<li></li>");
}
$("ul#selecteds li").each(function(index) {
var s = $(this).text();
if (s !== t) {
console.log("he");
$(event.target).clone().appendTo($("ul#selecteds"));
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="selecteds">
</ul>
<ul id="list">
<li>asdf</li>
<li>qwer</li>
<li>zxcv</li>
</ul>
You have the right idea, but you can't add a clone every time an element in the "selected" list doesn't match.
Also, you don't need to say e.g. ul#selecteds - ids are unique, and sufficient on their own.
$("#list li").on("click", function(event) {
var t = $(this).text(); // the clicked text
var exists = false; // is it already selected?
$('#selecteds li').each(function() {
if ($(this).text() == t) {
exists = true; // found a match
return false; // stop looking
}
});
// no match? add one
if (! exists) {
$('<li>').text(t).appendTo('#selecteds');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="selecteds">
</ul>
<ul id="list">
<li>asdf</li>
<li>qwer</li>
<li>zxcv</li>
</ul>
Related
I am creating a To-Do list with the ability to remove specific items from the list. I am currently trying to use 'localStorage' to essentially save the list on page refresh. However, when I delete an item from the list, the 'localStorage' does not work as intended and instead removes the first item in the array when you next load the page.
JS & jQuery:
$(document).ready(function () {
$(document).on('click', '.delete-task', function () { // We use 'on' as the element is dynamically added
console.log("'Delete' button pressed");
var foo = $(this).closest('li');
console.log(foo);
$(this).closest('li').fadeOut(250, function() {
arr.splice(foo, 1);
$(this).remove(); // Dynamically remove the DOM element from the list
localStorage.setItem('items', JSON.stringify(arr));
console.log(arr);
console.log(localStorage.getItem('items'));
});
});
});
If interested, the HTML format of an item within the 'ul' list looks similar to this:
<li><span class="text-task">5</span><span class="delete-task">x</span></li>
I am expecting the selected item from the list to be removed and store within the localStorage correctly when you next load the page.
Update:
As #Slim pointed out, 'foo' is a JS object and not an index.
My question is, how do I find the index of the specified item (the 'li') within the 'arr' array?
You could try to find the parent of foo using .parent() ( https://api.jquery.com/parent/ ) and then find the index of given li by using .index() ( https://api.jquery.com/index/ )
...
var index = foo.parent().index( foo );
arr.splice(index, 1);
...
Also, you should try to cache jQuery object. Calling multiple times $(this) is calculating the same thing multiple times.
For example:
...
var $self = $(this)
var foo = $self.closest('li');
console.log(foo);
$self.closest('li').fadeOut(250, function() {
...
Also, good idea is to name variables containing jQuery objects starting with $ - it's quite a common pattern.
simulate this
<ul id="list">
<li data-id="1" >Coffee <span class="delete-task">x</span></li>
<li data-id="2" >Tea <span class="delete-task">x</span></li>
<li data-id="3" >Milk <span class="delete-task">x</span></li>
</ul>
use id value here
$(document).on('click', '.delete-task', function () {
var id = $(this).parents('li').attr('data-id');
for (var k in arr) {
if (typeof arr[k] !== 'function') {
if (arr[k].id == id) {
//your codes
break;
}
}
}
});
I also recommend you use : https://github.com/localForage/localForage
I am working on the two ul lists. What I need is if someone click on the list item in list1, it will check if the 2nd list contains the clicked element or not. If it does not contain the element then copy it else just return.
What I have done so far is I am moving the elements successfully between the list but if I apply a check on it everything stops working.
Here is the link of jsfiddle.
$().ready(function() {
var classHighlight = 'highlight';
var $thumbs = $('ul li').on("click", function(e) {
//e.preventDefault();
debugger;
$thumbs.removeClass(classHighlight);
$(this).addClass(classHighlight);
});
$('#select1').on("dblclick", "li", function() {
//if($("#select2").has($(this))
//return;
//else
$(this).clone().appendTo('#select2').removeClass('highlight');
});
$('#select2').on("dblclick", "li", function() {
$(this).remove();
});
$('#add').click(function() {
$('#select1.highlight').clone().appendTo('#select2').removeClass(classHighlight);
});
$('#remove').click(function() {
$('#select2.highlight').remove();
});
});
If you un comment the above lines in code everything stop working.
Can any one please help me with this?
Thanks
Try this check:
var check = function(li) {
return $("#select2 li").filter(function(i, li2) {
return $(li2).text() == $(li).text();
}).length > 0;
};
Demo
As you're using clone(), you can't compare the new cloned element using is() or has() with the orignal one, because it is a new element, it isn't the same, as stated in clone's docs:
Create a deep copy of the set of matched elements
So it's a copy.
You have a missing paren.
This if($("#select2").has($(this)) should be this if($("#select2").has($(this))).
Also you can just pass this: if($("#select2").has(this))
And you have to check length: if($("#select2").has(this).length)
I'm trying to loop over a list in my html with a .each() loop, and removing any elements with matching ids.
<ul>
<li id="0" class="liRem">zero</li>
<li id="1" class="liRem">one</li>
<li id="2" class="liRem">two</li>
<li id="3" class="liRem">three </li>
<li id="4" class="liRem">four </li></ul>
And the jquery:
var output = [1, 3];
$(document).ready(function () {
$("ul li").each(function () {
if(this.id in output) {
$(this).remove();
};
});
});
However, instead of removing the specified li element, it just removes the next 'first' one on the page.
Also, I can't change the fact that I'm using an array, and the list is the only one on the html document. I'm new to jquery, so any advice would be greatly appreciated
Javascript doesn't have the functionality "value in array". This is used for for loops to loop over each element of an object.
Instead you should use either JQuerys inArray method or array.indexOf(value) > -1.
Additionally the Ids are strings, while your array contains numbers.
This works:
var output = ["1", "3"];
$(document).ready(function () {
$("ul li").each(function () {
if(output.indexOf(this.id) > -1) {
$(this).remove();
};
});
});
https://jsfiddle.net/07atsh5o/
try this script using jquery inArray and get the id using jquery .attr('id')
<script type="text/javascript">
$(document).ready(function () {
var output = ["1", "3"];
$("ul li").each(function () {
if($.inArray($(this).attr('id'), output) !== -1){
$(this).remove();
};
});
});
</script>
Too bad JavaScript doesn't have a nice function to simply check if an array contains a certain element. Nevertheless you could make one yourself by using this snippet:
Array.prototype.contains = function (search) {
for (key in this) {
if (this[key] == search) {
return true;
}
}
return false;
}
This function wil check whether your array will contain the given value or not and returns true or false. You can use it like so:
output.contains($(this).attr('id'));
Please also note my usage of retrieving an id of an element, because the way you do it now is incorrect. I created a jsFiddle for you, so you can check it out yourself and play with it a bit.
Hope this helps!
The "in" function doesn't work for the array, since "in" is to be used with for loop, because it gives only index values.
So try using one simple for loop with it:
And here is the example demo:
https://jsfiddle.net/HimeshS/pqrtqtkv/1/
for(var i in output){
if(this.id == output[i]) {
$(this).remove();
}
}
How would I count the number of elements with the attribute of "selected" if the selected attribute is added dynamically on click?
Here is how I'm adding the "selected" attribute:
var $li = $('.swrt_checkbox_button');
$li.on('click', function(){
var $el = $(this);
$el.toggleClass('checkbox-selected');
$el.attr('selected', function(index, attr){
return attr == "selected" ? null : "selected";
});
});
So, what I want to achieve is, if all my elements have the selected attr, then I want to do something, in this case, disable another UI element.
The problem I'm having is this, if I check to see if the attr is selected within the click it works:
if($el.is("[selected]")) {
console.log('yes');
}
This logs inside the click function but not outside it. So how can I say:
If all elements have "selected" attr { do stuff }?
Obviously I can't do it within the click because the $el is pointing to "this".
Any help or advice you can offer would be much appreciated.
Thanks
Since $li refers to the entire list, just compare how many have the selected attribute:
var totalElems = $li.length;
var selectedElems = $('.swrt_checkbox_button[selected]').length;
if (totalElems == selectedElems) {
//All selected
}
You can stick this at the end of your click event, so it'll run each time.
You could add a little line at the ewnd of your click, after activating a selection. Just check if there are any unselected elements left, if not, then run whatever you need.
// Check if there are any unselected left.
if(!$('.swrt_checkbox_button:not([selected])').length){
// Do the all-are-selected thing
}
Here's a quick implementation:
$('li').click(function(e){
e.preventDefault();
$(this).toggleClass('selected');
if(!$('li:not(.selected)').length) alert('all are selected')
})
li {
display: block; widht: 100px; height: 100px;l
}
li.selected { background: red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
I would like to not that selected is not a prop that should be used on li elements. Just use a class here.
This is how I would do it:
$("#sel").click(function () {
$("input:not(:checked)").first().prop("checked", "checked");
if ($("input[type='checkbox']").length == $("input[type='checkbox']:checked").length) {
alert("All selected :)");
}
});
Here is the JSFiddle demo
Thanks to everyone who commented. Here is what I did to make it work using tymeJV's solution:
function addCheck() {
var $li = $('.swrt_checkbox_button');
$li.on('click', function(){
var $el = $(this);
$el.toggleClass('checkbox-selected');
$el.attr('selected', function(index, attr){
return attr == "selected" ? null : "selected";
});
var totalElems = $li.length;
var selectedElems = $('.swrt_checkbox_button[selected]').length;
if (totalElems == selectedElems) {
$('.checkboxes-btn').removeAttr("disabled");
} else {
$('.checkboxes-btn').attr("disabled", "disabled");
}
});
}
addCheck();
Probably could be cleaner but it works so thanks!
First of all I do not want to use jQuery, just pure javascript; please don't link to duplicate jQuery posts.
If I have a list like
<ul id="bulk">
<li id="one"></li>
<li id="bmw"></li>
</ul>
I want to get the id of the clicked list element.
I am aware I could add onClick="" to each element but the production list I have has 2000 entries and I think a better way exists.
For example:
If I had only one li element with id='singular' I could use the following javascript to get the ID clicked.
var li = document.getElementById('singular').onclick = function() { do something };
As there are thousands of li elements, this code won't work.
I have been able to get a list of the element names with the following javascript:
var bulk = document.getElementById('bulk');
var bulkli = tabs.getElementsByTagName('li');
//bulkli contains ["one", "bmw"];
but this does not tell me which one was clicked.
You could add an event listener to the parent ul and then use e.target.id to get the id of the clicked element. Just check to make sure that the clicked element is actually an li since it's possible you may not be clicking on one.
Example Here
var ul = document.getElementById('bulk'); // Parent
ul.addEventListener('click', function(e) {
if (e.target.tagName === 'LI'){
alert(e.target.id); // Check if the element is a LI
}
});
As pointed out in the comments, this approach won't work when the child of an li is clicked. To solve this, you would need to check to see if the parent element of the clicked element is the one that the click event is attached to.
Example Here
var ul = document.getElementById('bulk'); // Parent
ul.addEventListener('click', function (e) {
var target = e.target; // Clicked element
while (target && target.parentNode !== ul) {
target = target.parentNode; // If the clicked element isn't a direct child
if(!target) { return; } // If element doesn't exist
}
if (target.tagName === 'LI'){
alert(target.id); // Check if the element is a LI
}
});
You can use this:
var link = document.getElementById("bulk");
attachEvent(link, "click", EventHandler);
function attachEvent(element, type, handler) {
if (element.addEventListener) element.addEventListener(type, handler, false);
else element.attachEvent("on"+type, handler);
}
function EventHandler(e) {
console.log(e.target.id);
}
fiddle
This work if li has children` elements:
fiddle example with children
pass its id as parameter into the onclick-function.
this.getAttribute('id')