Why is my jQuery not allowing me to toggle classes? - javascript

I have a series of custom Chevron elements that I'm going to use as buttons on my site. I've managed to set up the jQuery so that the clicked chevron/button is given a class="selected" which I then use to add custom styles. If I click any other chevron then the selected class is removed from the first chevron and added to the last chevron that was clicked. All of this works fine. I have another link that can be clicked to remove the class from all of the chevrons. What I'm trying to do now is to enable the .toggle(Class) function on jQuery so that I can also remove the class="selected" by clicking the same element twice.
My jQuery code:
$(function () {
$('#chevrons > ul > li > a').click( function(){
$('#chevrons .selected').removeClass('selected');
$('#show-all').removeAttr("style");
$(this).toggleClass('selected');
});
});
$(function () {
$('#show-all').click( function(){
$('#chevrons .selected').removeClass('selected');
$(this).css('color', '#FECF2A');
});
});
I've tried the toggle without the rows:
$('#chevrons .selected').removeClass('selected');
$('#show-all').removeAttr("style");
And it works fine. I assumed (perhaps incorrectly) that the jQuery would execute line-by-line and therefore the last thing to execute. But perhaps the first line above is removing the "selected" attribute from all of the chevrons and then the last line will only ever add the class.
What am I doing wrong here?

JSFiddle: http://jsfiddle.net/oqs4nycj/1/
Just exclude the clicked item from the class removal using not():
$('#chevrons .selected').not(this).removeClass('selected');
Applying this fix to your own JSFiddle (looks very cool by the way) you get this:
http://jsfiddle.net/qsnkqhp8/1/

JSFiddle:
http://jsfiddle.net/gopj0hyj/
Edit. I did not read the question carefully enough. Sorry. I have edited the code to deselect by clicking twice.
jQuery(function ($) {
// Variables are your friends - the $ preface tells us its a jQuery object
var $chevrons = $("#chevrons");
var $buttons = $chevrons.find('a');
var $show_all = $('#show_all');
// We bind a handler to the parent $chevrons element
// this is good for performance
// It will also bind the handler to elements dynamically added with ajax.
$chevrons.on('click', 'a', function(e){
var $old_selection = $buttons.filter('.selected');
var $clicked = $(this);
// Ensure that no button is selected
$buttons.removeClass('selected');
// Checks if button already was selected.
if ($clicked.get(0) !== $old_selection.get(0)) {
// select the clicked button
$clicked.addClass('selected');
}
$show_all.removeClass('active');
// prevents the browser from scrolling to top.
e.preventDefault();
});
$show_all.on('click', function(){
$buttons.removeClass('selected');
$(this).addClass('active');
});
});

Related

click events in JavaScript

I'm building a list of images dynamically. What I want to happen is when a user clicks the close text (inside my DIV element) the code will delete that particular image (list element). The code below does that the FIRST time the DIV is selected. After that it seems to ignore my div event listener and jump straight into the jquery on click function.
function removeItem(){
var test = document.querySelector('li > div').addEventListener('click', function(){
$(document).on('click', 'li', function () {
var photoId = (this.id);
$("#"+photoId).remove();
});
});
How can I make it so it will ALWAYS run when the DIV is selected instead of just the first time?
I'm new to learning about JavaScript so any help is appreciated!
When the user clicks on the DIV, you're not removing anything, you're just adding a new click listener on all LIs that removes that LI. Then the user needs to click again to trigger the second handler. It should simply be:
$(document).on('click', 'li > div', function() {
$(this).parent().remove();
});
BTW, there's no point in writing
var photoId = (this.id);
$("#"+photoId).remove();
It's simply $(this).remove(). Why go searching for an ID when you already have a reference to the element itself?

jQuery program not working

I am having a problem using jQuery, merely due to inexperience using it. My program is meant to give the CSS class current to the links in my navbar if they are clicked, and remove the class from the previous owner of it.
Keep in mind I am very inexperienced in javascript, only picking it up in a few minutes for the sake of a school assignment.The script is simply not doing anything.
My Code:
$(document).ready(function() {
$('a').click( function(i){
var $current = $('a.current');
$(this).addClass('current');
$current.removeClass('current');
});
});
Edit 1: Strange bug, current class is applied to the whole document if I do not click a link, but instead click the document.
You should first remove the class, and then add it. Otherwise you will not have a class added if you click an anchor twice.
$(function() {
$('a').click(function() {
$('a.current').removeClass('current');
$(this).addClass('current');
});
});
Try this:
$current.removeClass('current');
$(this).addClass('current');
You need to first remove the active class, then add the current class for the current element.
You need to narrow down your code to only affect the links in the nav bar, as currently, you are targetting all <a> tags.
var navLink = $('.nav a');
navLink.on('click', function(e){
navLink.removeClass('current');
$(this).addClass('current');
});
In this code, the variable gets all instances of the nav links, and if one of them is clicked, will remove the current class from all of the links before adding it onto the one that was clicked.
This jsfiddle will show you it in action: https://jsfiddle.net/td48vcqy/

Jquery only click once

I'm trying to disable a li click event after it has clicked the first time. Essentially to stop the array data being doubled. The click is working fine for each time. My current method doesn't appear to be working. I also need to disable the other li's from being clicked once the first one has :)
Thanks
JS code is:
$('#eventType ul li').click(function(e) {
e.preventDefault();
var value = $(this).attr('value');
answers.push(value);
// Below isn't working
$(this).click(function() {
return false;
});
console.log(answers);
});
you need to use one:
$('#eventType ul li').one('click',function(){
//your code here
});
this event will be fired only once
UPDATE
you can do that using $.off()
$('#eventType ul li').one('click',function(){
//your code here
$('#eventType ul li').off('click');
});
jQuery is just JavaScript so you can easily add behaviors that you want
// basic jQuery plugin boilerplate
$.fn.once = function once(eventType, f) {
// this = the selected elements
return this.each(idx, elem) {
// create reference to jQuery-wrapped elem
var $elem = $(elem);
// add event listener for eventType
$elem.on(eventType, function(event) {
// call the event handler
return f(event);
// remove the event handler
$elem.off(eventType, f);
});
});
};
Usage would look like this
$('#eventType ul li').once('click', function(event) {
console.log("you will only see this once");
});
However, this is obviously a common need so it exists in jQuery already. It's called $.one. As APIs grow, you may not know about the existence of such procedures. This answer exists to show you that you can use your brain to program the things that you want or that might be missing from a particular library. This lessens your dependence on the creator's of the lib to introduce the functionality you need.
EDIT
In a comment, you ask if the event handler can be disabled for all other LI elements after the first LI is clicked. The trouble here is that jQuery uses implicit iteration, which means that when you call $('li').on('click', ...), jQuery will bind an onclick event handler for each LI.
A better solution to this problem would be to use jQuery's event delegation
// only fire event handler for the first LI clicked
$('ul').one('click', 'li', function(event) {
console.log($(this).text());
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
This will delegate the event listener to the children LI, but once one of the LI is clicked, the event handler will be removed (because we delegated using the $.one procedure).
Try clicking one LI, you will see a message in the console. When you click the second LI, nothing will happen because the event handler was removed.
var used = false;
$('#eventType ul li').click(function(e) {
if (used == false) {
used = true;
e.preventDefault();
var value = $(this).attr('value');
answers.push(value);
console.log(answers);
}
});
the way you did it was just adding another on click handler, not removing or overriding the old ond.
You can use CSS classes; add the class 'disabled' to elements you don't need, and avoid adding elements that have the classe 'disabled'.
https://plnkr.co/edit/6aloNPETHGxfiP5oYZ9f?p=preview
$('ul li').click(function(e) {
if(!$(this).hasClass('disabled')) {
var value = $(this).text();
answers.push(value);
$('li').addClass('disabled');
}
console.log(answers);
});

Toggling if a condition is met on table elements

I have a table. Each column has a button at the top. If the td elements below within the column have content in them, then hide the button. If not then display the button and onClick add class active too the td element.
$(document).ready(function (){
$('.button-fill').on("click", function() {
var i=$(this).parent().index();
if($(this).closest("tr").siblings().find("td:eq("+i+")").text()=="")
$(this).hide();
else
$(this).show();
});
<!-- Fill in the td -->
$('.button-fill').on("click", function() {
var i=$(this).parent().index();
$(this).closest("tr").siblings().find("td:eq("+i+")").addClass("active");
//});
});
});
http://jsfiddle.net/ujw0u6au/
I've created a jsfiddle. I don't know what i'm doing wrong? Thank you
Since you have bind the button toggle logic inside button click - you will always have the button in the starting. When you will click on the button only then it will first hide the button and then make the content active.
In case you want this behavior in the starting as soon as the page loads, you should change below line (the 2nd line in your code) from your code -
$('.button-fill').on("click", function() {
to
$('.button-fill').each( function(i,e) {
also, you should not use <!-- Fill in the td --> style of commenting in JavaScript.
I can see you are having two "click" event handler on same class. Instead of it, you can merge it as well.
Here is the optimized version of your code :
JavaScript :
$(document).ready(function (){
$('.button-fill').on("click", function() { //Only one click event handler
var $this = $(this);
var i=$this.parent().index();
var $trSibling = $this.closest("tr").siblings();
$this.toggle($trSibling.find("td:eq("+i+")").addClass("active").text() != ""); //adds the class as well and check the text as well.
})
$(".button-fill").trigger("click");
// explicitly clicking on button to make sure that initially button should not be shown if column text is not empty
});
JSFiddle link : http://jsfiddle.net/ujw0u6au/1/
Is this the same what you want?
#Vijay has the right answer, but as a side note, you need to change this:
if($(this).closest("tr").siblings().find("td:eq("+i+")").text()=="")
to this
if($(this).closest("tr").siblings().find("td:eq("+i+")").text()!="")
if you want to hide the button when there is content, instead of the other way around (notice the != near the end).

Click event of 'a' tag in jquery

I need to trigger click events of "a" tags which are in "deletable" class. I saw some similar question in SO, but following code doesn't work for me. What i'm trying to do is to delete relevant <li> from <ul>.
$(document).ready(function () {
$('.deletable').live("click", function () {
alert("test"); // Debug
// Code to remove this <li> from <ul>
});
});
<form ...>
<ul>
<li>OneDelete</li>
<li>TwoDelete</li>
<li>ThreeDelete</li>
</ul>
</form>
I assume i'm using incorrect object hierarchy inside $('...') tag. But i don't have enough js/jquery/DOM knowladge to solve this problem. please help.
EDIT
Thanks for the answers, but none of them works for me. Actually i'm adding <li>s dynamically. There maybe a problem. Please check,
#sps - a listbox
#add - a button
#splist - another listbox
#remove - a button
$(document).ready(function() {
$('#add').click(function(e) {
var selectedOpts = $('#sps option:selected');
if (selectedOpts.length == 0) {
alert("Nothing to move.");
e.preventDefault();
}
$('#splist').append($(selectedOpts).clone());
$('ul').append('<li>' + selectedOpts.text() + 'Remove' + '</li>');
e.preventDefault();
});
$('#remove').click(function(e) {
var selectedOpts = $('#splist option:selected');
if (selectedOpts.length == 0) {
alert("Nothing to move.");
e.preventDefault();
}
$(selectedOpts).remove();
e.preventDefault();
});
});
The .live() method of jQuery has been deprecated. You can get similar functionality using $('body') and delegating to .deletable like I did in the following code:
$('body').on('click', '.deletable', function(e){
e.preventDefault();
// this is the li that was clicked
$(this).parent().remove();
});
The preventDefault method is used to keep the link from loading a new page should there be something targeted in the href attribute. If you keep the same HTML structure as you have in your example, then you can simply take the anchor element (this) and grab the parent, then remove it from the DOM.
It would be wise to, instead of using $('body'), target the container for the .deletable anchors, which, in this case, would be $('ul'). The function would look like this:
$('ul').on('click', '.deletable', function(e){
e.preventDefault();
// this is the li that was clicked
$(this).parent().remove();
});
Using $('body') means that every event on the page would have to be filtered to see if it originated from a .deletable anchor. By scoping it to the ul preceding your li's, you limit the number of times your function is called increasing performance.
Some things first: if you're using jQuery 1.9, the .live() function is not anymore supported. Versions prior, that particular function is deprecated anyway, so you shouldn't really use it.
That being said, your syntax looks about correct. So I'm assuming that it's your hierarchy inside the handler function that's incorrect.
Something like this should work if you're trying to delete the parent <li>:
$('.deletable').on('click', function (e) {
// since you're working with a link, it may be doing wonky default browser stuff
// so disable that for now
e.preventDefault();
// then we delete the parent li here:
$(this).parent('li').remove();
});
If you really want to make that into a delegate signature, something like this should work:
$('form').on('click', '.deletable', function (e) {
// same banana
});
you can use $('a.deletable') selector ... this finds the <a> with class deletable.
u can go through the on delegate events too.. here is the docs
try this
$('a.deletable').on("click",function(){
alert("test"); // Debug
// Code to remove this <li> from <ul>
$(this).parent("li").remove();
});
if in case your <li> is added dynamically..
$(document).on("click",'a.deletable',function(){ .... //even more better if u replace the document with closest elements to a.deletable ..like $(form)
live() is depricated..
$('a.deletable').live("click",function(){
alert("test"); // Debug
$(this).parent('li').remove();
});

Categories