After reading some questions/answers about this subject I have tried to make it works for me but I can't.
The story line is that I have X elements (so it means no ID just class) and I want to change the background when I click in one.
So with JS I did:
'click .switch' (event) {
event.toElement.closest("li").css('background-color','black');
if(this.stateMachine == 'running'){
Meteor.call("switch", this.nameMachine);
}
},
to get the container (here a <li class="liMachine switch">) but I have this error:
event.toElement.closest(...).css is not a function
Despite the event.toElement.closest returns the right element:
So what am I doing wrong ?
$('.liContainer.switch').on('click', function() {
$(this).toggleClass('active');
});
.active {
background-color: powderblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="liContainer switch">one</li>
<li class="liContainer switch">two</li>
<li class="liContainer switch">three</li>
</ul>
If $(event.target) works for you then the problem was of course that you did not pass a jQuery object. So you can not use jQuery functions on non jQuery object.
Since you are using Meteor, you may prefer this syntax:
"click .switch": function(event){
$(event.target).css("background-color", "black");
}
Related
I'm trying to toggle the css of two buttons in a list. If one is clicked, the other one should have no border, and vice versa. Here's my code:
function navigate_menu(event, ec){
$(event).css("border-top", "3px solid rgba(102,205,0, 0.8)");
var search_id=$(event).attr("name");
var chartid = "pie_chart_"+$(event).attr("name");
var editid = "edit_"+$(event).attr("name");
if(ec=="c"){
$(".li-edit").css("border-top", "0px solid rgba(102,205,0, 0.8)");
$("#"+chartid).appendTo($("#chart_"+search_id+"_container"));
$("#"+editid).css("display","none");
$("#"+chartid).css("display","block");
}else{
$(".li-chart").css("border-top", "0px solid rgba(102,205,0, 0.8)");
$("#"+editid).appendTo($("#chart_"+search_id+"_container"));
$("#"+chartid).css("display","none");
$("#"+editid).css("display","block");
}
}
HTML:
+"<ul id=\"navigation_list\">"
+"<li onclick=\"navigate_menu(this,'c')\" class=\"li-chart\" name=\""+search_id+"\">Chart & Legend</li>"
+"<li onclick=\"navigate_menu(this,'e')\" class=\"li-edit\" name=\""+search_id+"\">Edit Chart\\Change Data</li>"
+"</ul>"
So, when I first click, nothing happens, and then after the second it works. Then when I click on the other button, same (first nothing, second works). I thought that maybe on the first click it thinks I click on the parent (ul), but I don't know how would I fix it. And sorry for the pluses, its because this "menu" gets added to multiple elements from a JS function.
I have also tried addClass() and removeClass(), still same outcome.
Thank you!
Give each a li a shared class, e.g. li-item:
<ul id="navigation_list">
<li onclick="navigate_menu(this,'c')" class="li-chart li-item" name="+search_id+">Chart & Legend</li>
<li onclick="navigate_menu(this,'e')" class="li-edit li-item" name="+search_id">Edit Chart Change Data</li>
</ul>
Then use a JQuery .on("click" function to detect the click and apply the border to the clicked and remove from all others:
$(document).ready(function() {
$(document).on("click", ".li-item", function() {
$(this).addClass("border");
$(".li-item").not($(this)).removeClass("border");
})
})
Make a CSS class with the style to apply:
.border {
border: 2px solid blue;
}
Fiddle: https://jsfiddle.net/w9bwq57m/
Create bordered class in your css. Then call this fn somewhere in your click handler by passing element and second argument (no idea how to name it) I just wrote context. Make sure that you have deleted obsolete staff from the code above , which is responsible for border change .
function toggleBorder(element, context){
if(context === 'c'){
if($(".li-chart").hasClass('bordered')){
$(".li-chart").removeClass('bordered');
}
$(".li-edit").addClass('bordered');
}else{
if($(".li-edit").hasClass('bordered')){
$(".li-edit").removeClass('bordered');
}
$(".li-chart").addClass('bordered');
}
}
I would suggest using jquery click instead of onlick on li elements. Also you'd need to add data-key="c" and data-key="e" to the li elements so those values can be passed to the function:
$("#navigation_list li").click(function () {
navigate_menu(this, $(this).data('key'));
});
I tried asking this before, but I guess I wasn't specific enough. Suppose I have HTML code that looks like this. How do I ONLY target the tags within the the horizontalNAV using pure JavaScript? Okay I know I could do this using jQuery like this...
<script type="text/javascript">
$(document).ready(function(){
$('#horizontalNAV li a').click(function(){
//jQuery code here...
});
});
</script>
However I do NOT want a jQuery answer, because I want to know how you target ('#horizontalNAV li a') using pure javaScript.
or you can tell me how to do it for the verticalNav portion, either way I'll get it, if I see an example or if its explained to me. If I'm not mistaken you would have to use the document.querySelectorAll method, if so, how does that work in the above example.
<div id="wrapper">
<div id="horizontalNav">
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
</div>
<div class="sideBar">
<div class="verticalNav">
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
</div>
</div>
</div>
Without jQuery it would look like this
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function(event) {
var elems = document.querySelectorAll('#horizontalNav li a');
for (var i = elems.length; i--;)
elems[i].addEventListener("click", handler, false);
}, false);
function handler(event) {
//javascript code here...
this.style.color = 'red';
}
</script>
FIDDLE
If #horizontalNAV is a UL or OL element, then it can only have LI element children so you can skip that part of the selector. The following doesn't use querySelectorAll so will work in browsers, that don't support it:
<script>
window.onload = function() {
var list = document.getElementById('#horizontalNAV');
var links = list && list.getElementsByTagName(‘a’);
if (links) {
for (var i=0, iLen=links.length; i<iLen; i++) {
links[i].onclick = listener;
}
}
}
function listener() {
// do stuff
}
</script>
If you want to include more than one listener for an event, you’ll need to use addEventListener or some other strategy instead of assigning the function directly to the element, but in most cases only one listener is required per event type and keeping things simple has its benefits.
The listener function is declared outside the function doing the assignment to avoid a closure and circular reference, so it should have less chance of creating a memory leak.
Suppose I have a List like the following
<ul>
<li id="slide-a" class="slide-li active-slide"><a href="#" >A</a></li>
<li id="slide-b" class="slide-li"><a href="#" >B</a></li>
<li id="slide-c" class="slide-li"><a href="#" >C</a></li
</ul>
Now , using Jquery I wanna Find out which Element has the class 'active-class'. One way would to have a nested if statement something like this:
if($("#slide-a").hasClass('active-slide'))
{
active = 'slide-a';
}
else
{
if($("#slide-b").hasClass('active-slide'))
{
active = 'slide-b';
}
else
{
if($("#slide-c").hasClass('active-slide'))
{
active = 'slide-c';
}
}
}
My question is if there exists any way to optimize the code above. Is there a generic way to achieve this such that even if I add 10 more li's in the ul the code just works fine without any modification.
Maybe just
var active = $(".active-slide").attr("id");
Demo
Use Attribute starts with selector and .each(). Try this:
$(document).ready(function(){
$('li[id^=slide]').each(function(){
if($(this).hasClass('active-slide'))
alert($(this).attr('id'));
});
});
DEMO
If you have more than one li with classactive-slide use this:
$(document).ready(function(){
var idVal = [];
$('li[id^=slide]').each(function(){
if($(this).hasClass('active-slide'))
idVal.push($(this).attr('id'));
});
console.log(idVal);
});
DEMO
You could a use jQuery $.each() on the ul to iterate through.
fiddle coming in a second.
I currently have a list of <li>'s. Each <li> will have a color class defined, example: .color-blue, .color-red, .color-green - like so:
<ul id="listings">
<li class="layer block color-blue" id="item-1"></li>
<li class="layer block color-red" id="item-2"></li>
<li class="layer block color-green" id="item-3"></li>
</ul>
How do I copy/get the color class of the specific <li> item that is clicked?
I have my click listener in place and also know how to get the <li "id"> however not sure on the specific class though.
/* Click listener */
document.getElementById("listings").addEventListener("click", function(e) {
//console.log(e.target.id + " was clicked");
});
Something like this:
document.getElementById("listings").addEventListener("click", function(e) {
var el = e.target;
if (el.tagName == "LI") { // Use only li tags
for (i=0; i < el.classList.length; i++) {
if (~el.classList[i].indexOf('color')) {
var color = el.classList[i];
console.log('color class found: '+color);
break;
}
}
}
});
http://jsfiddle.net/bHJ3n/
You can use (jQuery):
$('ul').find('li.layer block color-blue')
Or
$('ul#listings').find('li.layer block color-blue')
Or... you can not use jQuery as that wasn't in the original question and would be wasteful to include unnecessarily.
Here's a solution that works in vanilla JS:
jsFiddle Example
Essentially because you're lumping the colour among the other classes you have to split them into an array and iterate over them until you find the one that starts 'color-'. I would recommend you use a custom attribute instead, like data-color="blue" as that would mean you could just retrieve it with:
e.target.getAttribute('data-color');
Try
document.getElementById("listings").addEventListener("click", function(e) {
alert(e.srcElement.className);
});
DEMO
UPDATE(since it is not working in Firefox as pointed from Sai):
To work also in Firefox try this:
document.getElementById("listings").addEventListener("click", function(e) {
var target = e.target || e.srcElement;
alert(target.className);
});
DEMO2
I have a unordered list:
<ul id="sortable">
<li id="1" class="ui-state-default">First x</li>
<li id="2" class="ui-state-default">Second x</li>
<li id="3" class="ui-state-default">Third x</li>
</ul>
I want to remove the <li> from the <ul>. I have handled the click event of the class itemDelete where I try to do a remove but I assume its not working because I can't remove the <li> as a child is calling it?
$('.itemDelete').live("click", function() {
var id = $(this).parent().get(0).id;
$("#" + id).remove();
});
What's the best approach?
Assuming you're using a recent version of jQuery:
$('#sortable').on('click', '.itemDelete', function() {
$(this).closest('li').remove();
});
closest is a little more dynamic than parent (although parent works here as well.) It gets the li that is closest to the current element, upwards in the structure.
Actually, the way you have it as of now, id is going to be undefined, because none of the li's have ids.
why not just do
$(this).parent().remove()
also, don't forget to return false.
You don't have IDs on your <li>s
How about simply
$(this).parent().remove();
What wound up working for me:
Prefix your id attributes with a string or underscore (as others have pointed out)
Since frameworks like jQuery Mobile require that ids be unique across all pages (not just in one page, I prefix with the page name, an underscore, and the numerical id that lets me access records in a database.
Instead of binding to a class or the ul control, use 'on' to bind to the li of the parent list:
$('#sortable').on('dblclick', 'li' function() {
aval = $(this).attr('id').match(/\d+/g); // only want the numbers...
id = aval[0];
name = $(this).text(); // in case you need these for a post...
li = $(this); // so we can remove it from the list after the 'this' object changes inside the ajax call...
// make an ajax call to the server
var jqxhr = $.post( "somepage.php", {name: name, id: id},
function(data) {
li.remove();
$("#sortable").listview("refresh");
},'json').fail(function() { alert("error"); });
return false; // preventDefault doesn't seem to work as well...
});
It could also be looking for the index of the elements with event
$('#sortable').on('click', '.itemDelete', function(e) {
e.preventDefault();
$(e.target.parentElement).parent()[0].remove();
});