toggleClass() only toggling to one class - javascript

I'm having trouble with a jQuery/Angular function being executed on click.
<a ng-click="like()" href="#" class="like like--yes"></a>
Basically, when a click occurs on a like button, I want to toggle the like--yes and the like--no classes. I've inspected the DOM while clicking, and once it has been set to like--no, it refuses to change back.
$scope.like = function() {
$('.like--no').toggleClass('like--no like--yes');
$('.like--yes').toggleClass('like--yes like--no');
}
I need two different functions so to speak, as I'm adding different animations depending on whether it's a like/unlike.
Any idea where I'm going wrong? There's more to it, but I've stripped some of the unnecessary code out for clarity.
Thanks.

I see that you are using AngularJS so instead of using jQuery, why not use ngClass?
Like this:
<a ng-click="toggleLike()" ng-class="{'like--yes': like, 'like--no': !like}">Hello World!</a>
Plunkr

It seems there is a logical issue
$scope.like = function() {
$('.like--no').toggleClass('like--no like--yes');
$('.like--yes').toggleClass('like--yes like--no');
}
Case:- first line changes like--no to like--yes and after that second line changes like--yes to like-- no again.
You should try .hasClass() function to check whether element has class then use toggle.

It seems like the second line is overwritting the first one.
It sets the class to like--yes and the second line catches the like--yes and set it to like--no everytime.
Try something like:
$scope.like = function() {
if( $('.like').hasClass( 'like--yes' ) ) {
$('.like').removeClass( 'like--yes' );
$('.like').addClass( 'like--no' );
} else {
$('.like').removeClass('like--no');
$('.like').addClass('like--yes');
}
}
Maybe you need change $('.link') to $(this) to get the actually clicked element.

It's generally frown upon to deal with DOM jQuery-style inside an Angular's controller, which is what you attempted to do and the other answers suggested.
Just have a variable that reflects the like state (you can set it directly in the View or inside the $scope.like() function and use ng-class to toggle the class:
<a ng-click="like=!like" href="#" ng-class="like ? 'like--yes':'like--no'"></a>

try this
$('.like').on('click',function(e){
e.preventDefault();
$(this).toggleClass('like--no like--yes');
if($(this).text() == 'like'){
$(this).text('unlike');
}else{
$(this).text('like');
}
});
and html
like
JSFIDDLE

Related

jQuery doesn't recognise that the class changed, although the Browser does

I have been trying out to create a Dropdown-menu with jQuery. I have 3 Sub-folders with 3 sub-sub-folders each (correct me if this is the wrong term). Depending on wether the Sub-folder is collapsed (Sub-subs invisible) or expanded (Sub-subs visible) there´s a little arrow pointing downwards when expanded and to the right when collapsed. I´m a Newbie and don´t want to use many external scripts, so I remove the Subshown_arrow Class and add the Subhidden_arrow Class when clicked (or the other way).
<img id="arrow" class="Subshown_arrow" /> Sub-forum 1
<li class="sub-sub"> <a href="#"> Sub-sub-forum 1 <li>
<li class="sub-sub"> <a href="#"> Sub-sub-forum 2 <li>
<li class="sub-sub"> <a href="#"> Sub-sub-forum 3 <li>
I removed the scr here ^, normally it´s there.
var main = function() {
$(".Subshown_arrow").click(function() {
alert("Subshown_arrow clicked!");
$(this).removeClass("Subshown_arrow").addClass("Subhidden_arrow");
});
$(".Subhidden_arrow").click(function() {
alert("Subhidden_arrow clicked!");
$(this).removeClass("Subhidden_arrow").addClass("Subshown_arrow");
});
};
$(document).ready(main);
However, when I click the Arrow for the first time, it rotates as expected. But when I click it another time, jQuery reacts as if it was clicked for the first time. The alerts print out "Subshown_arrow clicked!" every time.
But when I tried it out in the Browser and used Chrome´s built-in tools to view the Code, the Class changed. That means that changing the Class works, but my jQuery script ignores it.
What have i done wrong? Or is there a better way to do it?
Your problem has already been solved thousands of times, you are binding to .Subhidden_arrow and .Subshown_arrow classes when the first doesn't exist yet. You need to bind the events differently:
$('body').on('click', '.Subhidden_arrow', function ( e ) {});
This will work also on dynamically created (changed) elements.
If you use .on it will work when classes changes as new handler will be assigned to it. but when you use .click it is assigend to the object that had the matching class at first and although the class has changed but still the old handler is assigned to it.
var main = function() {
$("body").on("click",".Subshown_arrow",function() {
alert("Subshown_arrow clicked!");
$(this).removeClass("Subshown_arrow").addClass("Subhidden_arrow");
});
$("body").on("click","Subhidden_arrow",function() {
alert("Subhidden_arrow clicked!");
$(this).removeClass("Subhidden_arrow").addClass("Subshown_arrow");
});
};
You are using an img without any src and if you have more images then i would mention to not to use same ids.
So, what you can do is give a common class name to the element:
<img class="arrow Subshown_arrow" />
<!----------^^^^^-------like this one---->
Now you can use the class arrow to bind the click event and you can use toggleClass() method to change the classes:
$(".arrow").click(function() {
$(this).toggleClass("Subshown_arrow Subhidden_arrow");
});
As mentioned the problem is that the click is bound on document load, at which time there are no elements with a class subhidden_arrow. This can indeed be solved by using a parent elements click and a filter on the class using (on). However, the original bound click event can also be reused to toggle the classes:
$(".Subshown_arrow").click(function() {
$(this).toggleClass("Subshown_arrow").toggleClass("Subhidden_arrow");
});
The click is bound to the element on load and reacts on both 'states', regardless of which class it holds then.
An example Fiddle with a slight alteration to make the containing anchor react to the click event.
Better way
var main = function() {
$("#arrow").click(function() {
$(this).toggleClass("Subshown_arrow").toggleClass("Subhidden_arrow");
});
};
$(document).ready(main);

change div class onclick on another div, and change back on body click

Let me define the problem a little bit more:
i have
<div class="contact">
<div id="form"></div>
<div id="icon"></div>
</div>
i want onclick on #icon, to change the class of .contact to .contactexpand( or just append it).
Then i want that the on body click to change the class back, but of course that shouldnt happen when clicking on the new class .contactexpand, and if possible that clicking on icon again changes the class back again.
I tried numerous examples and combinations but just couldn't get the right result and behavior.
Check this: Working example
Let's go step by step
I want onclick on #icon, to change the class of .contact to .contactexpand( or just append it). […] and if possible that clicking on icon again changes the class back again.
You want to use the toggleClass() method to achieve this. Simply:
$('#icon').on('click', function(e){
$(this).parent()
.toggleClass('contact')
.toggleClass('contactexpand');
});
Then i want that the on body click to change the class back
You will have to make sure that body removes contactexpand class and adds contact. At this point I would just give the container element an id (or class if you prefer), just to make things simpler. Then what you do is pretty simple:
$('body').on('click', function(e){
$('#thisdiv')
.removeClass('contactexpand')
.addClass('contact');
});
but of course that shouldnt happen when clicking on the new class .contactexpand.
This is the step that the other answers missed, I think. Since everywhere you click, you also click on the body element, you will always trigger the click event on the body, hence removing the contactexpand class and adding the contact one.
Enter event.stopPropagation(). This method will make sure that the events doesn't bubble up the DOM, and will not trigger the body click.
$('#thisdiv').on('click', function(e){
e.stopPropagation();
});
Working example
You can add a class to parent element like the following code.
$(".contact #icon").click(function(){
var element = $(this).parent(".contact");
element.removeClass("contact").addClass("contactexpand");
});
I like to the jQuerys toggleClass function like so:
$('#icon').click(function(){
$('#contactbox').toggleClass('contact');
$('#contactbox').toggleClass('contactexpand');
});
Or you could use addClass('className') and removerClass('className') if you would like to apend it rather than toggle it :)
Here is an example: http://jsfiddle.net/aUUkL/
You can also add an onclick event to the body of the page and use hasClass('className') to see whether or not to toggle the class when the body is clicked. You could use something like this (Although I havent tested this bit!):
$('body').click(function(){
if( $('#contactbox').hasClass('contactexpand') ){
$('#contactbox').addClass('contact');
$('#contactbox').removeClass('contactexpand');
}
});
You can do this
$('body').on('click', function(event) {
if ($(event.target).attr('id') == 'icon') {
$(event.target).parent().toggleClass('contactexpand');
} else {
$('.contact').removeClass('contactexpand');
}
});
Check out this jsfiddle
var $contact = $('.contact');
$contact.find('#icon').click(function(e, hide) {
e.stopPropagation();
$contact[hide ? 'removeClass' : 'toggleClass']('contactexpand');
});
$(document).on('click', function(e) {
if (e.srcElement === $contact[0]) return;
$contact.find('#icon').trigger('click', true);
});
http://jsfiddle.net/kZkuH/2/

Disabling element in jQuery

Okay so I want to click an item, then have that item become unclickable, and not execute the jQuery attached to it. I am currently using this
$(clicked_id).prop('disabled', true);
However that is not working.
Any help is much appreciated!
EDIT:
This is the HTML:
<img src="imgs/card.jpg" id="card0" name="card0" onclick="getCard(this.id); ">
disabled is only for disabling input elements (and it doesn't change the clickability of the object -- just that the default animation isn't executed).
To make it so that the click event is removed from an object, use .off()
$(clicked_id).off('click')
But this only works if the onclick was added via jquery
Instead, you may do this:
$(clicked_id)[0].onclick=false
Since your handler is assigned as an attribute, you can just nullify the property for that event handler.
document.getElementById(clicked_id).onclick = null;
just make sure you don't have a leading # on the ID.
Or us jQuery like this:
$(clicked_id).prop("onclick", null);
Or you can pass the element itself instead of passing the ID.
<img src="imgs/card.jpg" id="card0" name="card0" onclick="getCard(this); ">
And then change your function so that it receives the element instead of the ID of the element. Once you do that, you can access the element directly.
elem.onclick = null;
There is another solution:
function getCard(objId){
if( !($('#'+objId).attr('used') == '1') )
{
alert('Click is working for '+objId);
// do something
$('#'+objId).attr('used', '1');
}
}
Here is a working example:
http://jsfiddle.net/HqHut/

toggling between two classes jQuery = works but extra click

Sort
$(".sort").click(function (event) {
$(this).toggle(function() {
$(this).toggleClass("sortUp","sortDown");
}, function() {
$(this).toggleClass("sortDown","sortUp");
});
});
it works but I need to click once before it works.
so -
click (nothing happens), click (sortUP), click (sortDown)
I would like to remove first click.
Thank you community for the help !
Firstly, you're using toggleClass incorrectly. You appear to want to toggle sortDown and sortUp on each click. That's done with toggleClass("sortDown sortUp").
Secondly, you need your class .sort to either have sortUp or sortDown set in its class property when you load the page. e.g. <a href="#" class="sort sortDown">. This makes sure you can reason about your code (i.e. it's always true that exactly one of sortUp, sortDown are set on your div).
Thirdly, $(this).click(function() { /* code */ }) means "when somebody clicks, do /*code*/". You've wrapped your
$(this).click(function() { $(this).toggleClass("sortUp sortDown"); })
which sets up the click behaviour, in a $(".sort").click(function () { which means you are requiring an initial click on "sort" just to start the behaviour.
So the correct version is:
Sort
$(document).ready(function () {
$(".sort").click(function() {
$(this).toggleClass("sortUp sortDown");
});
});
if you dont' want to begin with a sortUp or sortDown class, do this:
Sort
$(".sort").click(function (event) {
if($(this).hasClass("sortUp") || $(this).hasClass("sortDown")){
$(this).toggleClass("sortUp sortDown");
}else{
$(this).addClass("sortUp");
}
});
It looks like you are adding the click events on the first click, also if you want to switch between sortUp and sortDown you can simply specify them both. As long as the element starts with one or the other (not both and not neither), it will swap them each time.
$(".sort").click(function() {
$(this).toggleClass('sortUp sortDown');
});
You can see this running on JSFiddle.

check if element class have changed

i've got some JS library, thats on click to the html element changes its class. I would like to write function, that would check if class had been changed, and then add image to this element. Can you help me with this?
thanks!
If you're using jQuery try this:
$(document).ready(function() {
// get the class that's set on page load
var current = $('#element').attr('class');
$('#element').click(function(e) {
if ($(this).attr('class') != current) {
// class has been changed, do something
}
});
});
Here is an example at jsFiddle.net.
Disclaimer: Without more details about which elements have onclick event listeners that change which elements` class, I cannot give you real working code for you situation. Instead, I can only give you some logic which I just did.
$("#elemID").click(function() {
$("#div").removeClass('a');
$("#div").addClass('b');
if ($("#div").attr('class') == 'b') {
$("#div").append("<p>Hello</p>");
}
});
Or
$("#elemID").click(function() {
$("#div").removeClass('a');
$("#div").addClass('b');
if ($("#div").hasClass('b')) {
$("#div").append("<p>Hello</p>");
}
});
What you can proceed with Krystian is that everytine u click on an element, add a class "say classClicked" to it. Then with the the help of hasClass u can find out the class attached to that element. If is satisfies your condition, add image.
Or if the class changes on each click and you know the name of the changed class, just check using
if($(this).hasClass("b")){
do your action
}
Hope this helps.

Categories

Resources