On mouse down change class but revert it on mouseup - javascript

When i click on a class i want to remove the class and add a new class to the element. Now when i release the mouse from the class i want to remove the new class added and replace with the old class.
This is only adding the new class but is not reversing the change when i take the mouse of.
<i class="fa fa-arrows"></i>
$('.fa-arrows').mousedown(function(){
$(this).removeClass('fa-arrows').addClass('fa-random');
});
$('.fa-random').on('mouseup',function(){
$(this).removeClass('fa-random').addClass('fa-arrows');
});
https://jsfiddle.net/873k5pgg/

You can use event delegation:
$(document).on('mousedown', '.fa-arrows', function () {
$(this).removeClass('fa-arrows').addClass('fa-random');
});
$(document).on('mouseup', '.fa-random', function () {
$(this).removeClass('fa-random').addClass('fa-arrows');
});
jsFiddle example

What your jQuery does when this code is executed is: it looks for all .fa-arrows and binds the function to mousedown and it looks for all .fa-random and binds the other function to mouseup. This happens once, it is not magically re-evaluated everytime any class/the DOM changes. (That is where React/AngularJS/... come into play.)
You either have to re-evaluate the binds manually whenever the classes change (in the bound functions), or bind both to the same elements (I'd go with the latter):
$('.fa-arrows')
.on('mousedown', function() {
$(this).removeClass('fa-arrows').addClass('fa-random');
})
.on('mouseup', function() {
$(this).removeClass('fa-random').addClass('fa-arrows');
});
.fa-arrows { text-decoration: underline; }
.fa-random { color: red; text-decoration: line-through; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="fa-arrows">mousedown me</p>
Edit: that said, why not just use css?
p { text-decoration: underline }
p:active { color: red; text-decoration: line-through; }
<p>mousedown me</p>

You could set a variable to be true/false if it is clicked or not. Script will need to be altered if you're doing this multiple times on the same page.
var clicked = false;
$(document).on('mousedown', '.fa-arrows', function(){
$(this).removeClass('fa-arrows').addClass('fa-random');
clicked = true;
});
$(document).on('mouseup', function(){
if (clicked) {
clicked = false;
$('.fa-random').removeClass('fa-random').addClass('fa-arrows');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<i class="fa fa-arrows"></i>

The reason this doesn't work is because the events are set at the start, and the mouseup event is set to .fa-random which doesn't exist at that moment.
Like j08691 said you can use event delegation from the document, or you could put the event ons .fa and it should work too:
$('.fa').mousedown(function(){
$(this).removeClass('fa-arrows').addClass('fa-random');
});
$('.fa').mouseup(function(){
$(this).removeClass('fa-random').addClass('fa-arrows');
});

Related

Click body but not two divs

Here's my function:
document.querySelector('body').addEventListener('click',e=>{getRandomImagePair()});
When I click anywhere on the body something happens. I have two divs .more and .wd and if I click on them the function getRandomImagePair() executes. How can I make so that if I click the links the function doesn't fire?
I tried this below, it works but then the .more div won't trigger another needed different function.
$('.more, .wd').on('click', function(event) {
event.stopPropagation();
});
Using event delegation, just check the className of the event.target element. Use an if statement in your event handler callback to prevent getRandomImagePair from being called a link was clicked on:
function getRandomImagePair() {
console.log('getRandomImagePair called');
}
//using event delegation
document.querySelector('body').addEventListener('click', e => {
if (e.target.className !== 'wd' && e.target.className !== 'more') {
getRandomImagePair();
}
});
.wd,
.more {
color: blue;
text-decoration: underline;
}
<body>
<div class="more">.more</div>
<div class="wd">.wd</div>
<p>Here is some other stuff</p>
<p>that when clicked on should still fire event handler</p>
</body>
Try excluding the items you don't want to be affected by the click :
const getRandomImagePair = () => {
alert("clicked")
}
$('body :not(".more, .wd")').on('click', getRandomImagePair);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Yep</button>
<button class="more">Nope</button>
<button class="wd">Nope</button>
<button>Yep</button>

jQuery: Click on element excluding clicks on child elements

I'm struggling to get the right jQuery selectors for clicking on a certain element. Here is the HTML that I have:
<label class="title-label" for="me">Some Title<i class="fa fa-times del-class"></i></label>
I have two separate jQuery listeners:
$(document).on("click", ".title-label", function (e) { //magic happens here
and another one:
$(document).on("click", ".del-class", function (e) { //the whole label gets deleted
When I click on the label I send .ajax request to the server and magic happens. There is also a little i icon for deleting the whole label which also works. However, when I click on the .del-class icon, it first triggers the click on the .title-label which sends the request to the server, the magic happens and then the label gets deleted. The icon needs to stay within the label but when I click on it, it should not trigger the click on the label and the magic but delete the label right away.
I tried various attempts to include the :not selector like this:
:not('.del-class') .title-label
But both always get triggered. Any clue what the right selector would be in this case?
You can use e.stopPropagation() to prevent the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event.
$(document).on("click", ".title-label", function(e) {
console.log('title-label click');
});
$(document).on("click", ".del-class", function(e) {
e.stopPropagation(); //Add
console.log('del-class click');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label class="title-label" for="me">Some Title<i class="fa fa-times del-class"> Other text </i></label>
You can check if the event.target is or not the icon and do your stuff in the if/else statement.
See below
$(document).on("click", ".title-label", function(e) {
let tgt = e.target
if (!$(tgt).is('.del-class ') ) {
console.log('do magic now')
}
else {
console.log('delete label straight away')
}
//or
!$(tgt).is('.del-class ') ? console.log('do magic now') : console.log('delete label straight away')
})
i {
width: 20px;
height: 20px;
background: Red;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label class="title-label" for="me">Some Title<i class="fa fa-times del-class"></i></label>
If I get it right, you have 2 elements and one of them is inside the other one, if you need 2 separate listeners, you need to use event.stopPropagation() on the child one.
Example:
https://jsfiddle.net/xpvt214o/239539/
$('.parent_div_click').on('click',function(event){
console.log('click in parent');
});
$('.child_i_click').on('click',function(event){
event.stopPropagation();
console.log('click in child');
});
hope this helps

Create Toggle Button Using jQuery

I want to use just ONE button to control Opening and Closing an Off-Canvas Menu. So I created a Button with OpenButton class which open menu, after clicking, I remove OpenButton class and add CloseButton class, These all work like a charm, But When I call Click Event on CloseButton It doesn't work, What is the problem ?
This is my code :
$('.OpenButton').click(function() {
$(this).addClass('CloseButton');
$(this).removeClass('OpenButton');
});
$('.CloseButton').click(function() {
alert('Close');
});
Since you're adding the class dynamically, you need to use event delegation to register the same with the event handler mechanism,
$(document).on('click', ".CloseButton", function() {
alert('Close');
});
Hope this helps!
That is because the click event is bound at runtime. Since .CloseButton does not exist when the code is executed, no click event will be bound to it. One solution is to use $(document).on('click', '.CloseButton', function() {...}) to do that, but that is considered resource intensive and unnecessarily heavyhanded.
I would recommend that you do not change the class of the button instead. If you want to modify the style or appearance of the button when it's open/close, you can do it by adding classes instead of swapping classes, for example:
$('.button').click(function() {
$(this).toggleClass('is-open');
});
In this case, you can you also store the state of the button in jQuery's data object. That will abstract reading the state of an object from the DOM based on it's class:
$(function() {
$('.button').click(function() {
// Store state
if ($(this).data('is-open')) {
$(this).data('is-open', false);
alert('closing!');
} else {
$(this).data('is-open', true);
alert('opening!');
}
// Toggle class
$(this).toggleClass('is-open');
$('.toggleTarget').toggleClass('is-hidden');
});
});
.is-hidden {
display: none;
}
.button {
background-color: steelblue;
color: #fff;
display: inline-block;
padding: 10px;
}
.button.is-open {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Toggle
<div class="toggleTarget is-hidden">I am content that is toggled.</div>

jQuery .on() doesn't fire on click but instantly

When I click a button, I change its ID and apply a new style to it by adding a class toMenu. What I wanted to do is, when I click the button with the new ID menu, that it adds another class menuTransition. But what now happens is that it already adds the class menuTransition when I click the button with the old ID #button. But what it's supposed to do, is not add the class menuTransition until the button with the new ID #menu is clicked.
Here's my code:
$(document).ready(function() {
$("#button").click(function(){
$("#button").addClass("toMenu")
$("#button").attr("id","menu");
});
});
$(document).on("click", "#menu", function() {
$("#menu").addClass("menuTransition");
});
What you're seeing is a bit of a race condition. With your button click event handler you're adding a class and an ID to your button. Then with your delegated event handler you're looking for any clicks on the document, even those that bubble up from descendant elements, and adding a class there as well. One way to handle this is to add a small (~ 1 msec) delay to short-circuit this race that would normally occur with your example code.
$(document).ready(function() {
$("#button").click(function() {
$("#button").addClass("toMenu")
setTimeout(function() {
$("#button").attr("id", "menu");
}, 1)
});
});
$(document).on("click", "#menu", function() {
$("#menu").addClass("menuTransition");
});
.toMenu {
font-weight: bold;
}
.menuTransition {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button">
button
</button>
By adding the 1 millisecond delay, the ID is added after the click on the button has reached the document event handler, so that event handler only fires after the first click on the button.
You should not be changing the ID. Element IDs are intended to be static. You can use a class to tag the current state of the button / menu and make it behave accordingly (and at the same time avoid the inefficient delegated event handler on $(document):
$(document).ready(function() {
$("#menubutton").on('click', function() {
var $this = $(this);
if ($this.hasClass('toMenu')) {
$this.addClass('menuTransition');
} else {
$this.addClass('toMenu');
}
});
});

Add more code to inherited event with jQuery

I have an inherited jQuery code where the scroll event has been set:
$(window).on('scroll', function(event) {
// Whatever
});
Now I need to add some more functionality to the previous code when a click event is fired, but this new code must be removed when another element is clicked, something similar to the below code:
$('#element1').on('click', function(){
$(window).on('scroll', function(event) {
// Add my code to the inherited one
});
});
$('#element2').on('click', function(){
$(window).on('scroll', function(event) {
// Unbind my code and leave the original behaviour
});
});
However, I cannot rewrite the inherited code. Is there any way to achieve this?
Thank you very much in advance
You can use event.namespace to bind the event. then you can use .off() to remove an event handler using namespace
$('#element1').on('click', function(){
$(window).off('scroll.element').on('scroll.element', function(event) {
// Add my code to the inherited one
});
});
$('#element2').on('click', function(){
$(window).off('scroll.element');
});
Using the above approach, default scroll event handler will have no impact.
Instead of binding scroll event to body you can bind it to body specific class. Clicking button will swap classes.
$(document).ready(function() {
$('.btn').click(function() {
$('.body')
.removeClass($(this).data('passive-class'))
.addClass($(this).data('active-class'));
});
});
.origin {
color: red;
}
.custom {
color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="body">
Some content
<button class="btn" data-active-class="origin" data-passive-class="custom">Scroll origin</button>
<button class="btn" data-active-class="custom" data-passive-class="origin">Scroll custom</button>
</div>
Place all code inside function and use flag to execute as needed.
var additionalCode = false;
function usefulCode(event) {
// here is your default code
if (additionalCode) {
// here is additional code
}
}
$(window).on('scroll', usefulCode);
$('#element1').on('click', function(){
additionalCode = true;
});
$('#element2').on('click', function(){
additionalCode = false;
});

Categories