jQuery bind click firing immediately - javascript

I have a drop down menu, and clicking the icon should add the class "Open" to its parent, and then clicking the menu anywhere should close it. But the function inside the bind fires when the icon is clicked. The effect being it adds the class Open, and then removes it straight away.
This is probably a simple issue, but I cannot seem to work out why the 'click' event fires straight away!?
This question may be similar but can't still can't work it out: jQuery bind event firing the event
$(function () {
$(".ui-dropdown-action").bind("click", function () {
$(this).parent()
.addClass("Open")
.bind("click", function () {
$(this).removeClass("Open");
});
});
});

I think you might have a problem with the click event bubbling up the DOM tree. Which is why click is also being fired on the parent.
if you pass in the event object as an argument for the first bind and call event.stopPropagation() as follows
$(function () {
$(".ui-dropdown-action").bind("click", function (event) {
event.stopPropagation();
$(this).parent()
.addClass("Open")
.bind("click", function () {
$(this).removeClass("Open");
});
});
});
should fix your issue.

You can pass the event argument and stop the bubbling of the event .. Try this
$(function () {
$(".ui-dropdown-action").bind("click", function () {
$(this).parent()
.addClass("Open")
.unbind().bind("click", function (e) {
$(this).removeClass("Open");
e.stopPropagation();
});
});
});
This will make sure the parent event will not fire when the icon is clicked..
Also every single time you click the icon the event for the parent is bound again which will create multiple click events .. Need to make sure you unbind and bind them again to avoid that..

It is firing right away because the click event is bubbling to the parent and then firing that selector. To fix this you could use a setTimeout() around the 2nd bind.
$(function () {
$(".ui-dropdown-action").bind("click", function () {
var parent = $(this).parent();
parent.addClass("Open");
setTimeout(function() {
parent.bind("click", function () {
$(this).removeClass("Open");
});
}, 0);
});
});
Another option would be to to a stopPropagation() on the event on your first bind, though that would prevent any other handlers from triggering on that event.

In my case, when I use something like this
$("#modal .button")[0].click(() => console.log('test'))
its doesnt work and seems like click firing immediately
Solution for me was:
const button = $("#modal .button")[0];
$(button).click(() => console.log('test'));

Related

How to wrap multiple dynamic eventListeners into one?

I just started to learn js and need a little help: I have the following function:
//SET CHAT BEHAVIOR
function chatSettings() {
console.log('ChatSettings called')
function BtnAndScrollBar(texteditor) {
console.log('BTNAndScrollBar called');
const sendBtn = $('.cl.active').find('.sendBtn');
const attachBtn = $('.cl.active').find('.attachBtn');
console.log(sendBtn)
}
function sendAndDeleteMessage(send) {
console.log(send);
}
var sendBtn = $('.cl.active').find('.sendBtn');
sendBtn.mousedown(function () {
sendAndDeleteMessage(this);
});
var textEditor1 = $('.cl.active').find('.chatTextarea');
textEditor1.on('focus change mousedown mouseout keyup mouseup', function (){
console.log(this);
BtnAndScrollBar(this)
});
}
$('document').ready(function () {
console.log('hello');
$('.tabs').tabs();
chatSettings();
});
I prepared a js.fiddle - As you can see from console.log when clicking into the textarea, the eventListener always listens to #cl1, even if .cl.active switches along with the according TAB.
The events in the textarea are just relevant, if .cl is active. My target is to wrap all three eventListener into one and apply the event to the textarea in the active stream, but all I tried went wrong... Can anyone help? #Dontrepeatyourself #DRY
$(".chatTextarea").on(
'focus change mousedown mouseout keyup mouseup',
function (this) {
//this.id can contain the unique id
greatFunction(this);
});
This will bind event individually with unique id found with this keyword and also wraps all event listener into one function but this is better when you want to process each event with same functionality
please let me know if this helps.
Peace
$(".cl textarea").on('focus change mousedown mouseout keyup mouseup', function () {
greatFunction(this)
});
Tada!
P.S. Is there a reason greatFunction is defined inside window.onload?
Try using $(document).ready function to load code when the page loads.
Also use $('textarea #cl1').on to get the textarea with the #cl1 or whichever id you want to use and then call the function after using the .on.
Hope this helps!
Let me know if it works!
$(document).ready(function () {
function greatFunction(elem) {
//do stuff
}
$('textarea').on('focus change mousedown mouseout keyup mouseup', function () {
greatFunction(this)
});
}
First off, I changed the onload to bind with jQuery, so all your logic is doing jQuery bindings, rather than swapping back and forth between jQuery and vanilla javascript. Also, doing an actual binding removes an inline binding.
Next, the binding has been condensed into a single delegate event listener. Since you eluded in your comments that it wasn't working for the active element after the active was moved or added, this reflected that you were dealing with dynamic elements. Delegate event listeners are one way to handle such things.
Delegate event listeners bind on a parent element of the elements that will change, or be created. It then waits for an event to happen on one of it's children. When it gets an event it is listening for, it then checks to see if the element that it originated from matches the child selector (second argument) for the listener. If it does match, it will then process the event for the child element.
Lastly, I added some buttons to swap around the active class, so you could see in the snippet that the event handler will start working for any element that you make active, regardless of it starting out that way.
$(window).on('load', function () {
function greatFunction (elem) {
console.log(elem.value);
}
$(document.body).on(
'focus change mousedown mouseout keyup mouseup',
'.cl.active .chatTextarea',
function () {
greatFunction(this);
}
);
$('.makeActive').on('click', function () {
$('.active').removeClass('active');
$(this).closest('div').addClass('active');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="cl1" class="cl active"><textarea class="chatTextarea">aa</textarea><button class="makeActive">Make Active</button></div>
<div id="cl2" class="cl"><textarea class="chatTextarea">bb</textarea><button class="makeActive">Make Active</button></div>
<div id="cl3" class="cl"><textarea class="chatTextarea">cc</textarea><button class="makeActive">Make Active</button></div>

Why I cannot change button event with JQuery .click() function?

Say I have a button whose id is "btn" and I add an event to the button as:
$(document).ready(function() {
$("#btn").click(function(){
$("#label1").html((new Date()).getSeconds());
$("#btn").click(function () {});
};
})
where #label1 is a label tap supposed to show the current second.
I wish by click the button at the first time, current second will shown in the label1. And for following click on this button, nothing happen. But what I got is every time the button is clicked, new current second is shown in label1. What's wrong?
Use one() to bind event
$("#btn").one('click', function(){
$("#label1").html((new Date()).getSeconds());
});
Note that $("#btn").click(function () {}); does not unbind the event. It binds click event on that element one more time, so next time when the button is clicked two event handlers will be called one to update the html and other empty function that does nothing.
To unbind the event, off() can be used, but in this case one() is preferred.
$("#btn").on('click', function () {
$("#label1").html((new Date()).getSeconds());
$(this).off('click');
});
You can simply use .one().
Attach a handler to an event for the elements. The handler is executed at most once per element per event type.
$(document).ready(function() {
$("#btn").one('click', function(){
$("#label1").html((new Date()).getSeconds());
});
})
At-present you are binding another click handler using $("#btn").click(function () {});
Hello you can remove the click Listener the following way.
$(document).ready(function() {
$("#btn").click(function(){
$("#label1").html((new Date()).getSeconds());
$('#btn').off('click');
});
})

Using .on to bind to dynamically generated content

I am using Infinite Scroll to display some content and I'm having trouble binding some mouseenter/mouseleave events to the newly generated items.
I know that I need to bind .on to a container already existing on the page, but I'm having trouble figuring out the syntax to alter the current jQuery that toggles.
This is the current js:
$(document).ready(function() {
$('.grid-box .actions').hide();
$('.grid-box').on({
mouseenter: function () {
$(this).find('.actions').show();
},
mouseleave: function () {
$(this).find('.actions').hide();
}
});
});
The main container is #grid-container and each individual item is .grid-box. How can I alter the above so that the actions show/hide upon entering/leaving .grid-box?
I think I need something along the lines of this:
$('#grid-container').on('mouseenter mouseleave', '.grid-box', function(e) {
// some action
});
Exactly, this is known as event delegation and it waits for the event to bubble up then matches the event based on the selector. This is much more efficient because there is only one handler registered rather than N times the number of elements. Also, you only have to bind once rather than every time the dynamic content is changed.
$('#grid-container').on('mouseenter', '.grid-box', function(e) {
// some action
}).on('mouseleave', '.grid-box', function(e) {
// some action
});
The selector as the second argument will still work:
$('#grid-container').on({ ...}, '.grid-box');
http://jsfiddle.net/QkFTz/1/
An alternate method would just be to bind them separately, which I personally think is clearer:
$("#grid-container").on('mouseenter', '.grid-box', function () {})
.on('mouseleave', '.grid-box', 'function () {});

click() firing multiple times

I am using a document.getElementById("val").click() to invoke a click event, but it keeps firing multiple times.
Here I add the eventHandler:
try {
//add mousedown event handler to navigation buttons
addEventHandler(oPrevArrow, "mousedown", handlePrevDayClick);
addEventHandler(oNextArrow, "mousedown", handleNextDayClick);
addEventHandler(oLogout, "mousedown", handleLogoutClick);
}
catch (err) {
}
In the click event I am performing a "auto click"
function handleNextDayClick(e) {
e = e || window.event;
stopEvent(e);
document.getElementById("btn_nextday").click();
}
I need help to figure out what is making it call multiple times and a possible fix.
NB: the button that is auto-clicked calls a method in the ASP.NET Code-Behind
Usually when you have an event firing multiple times it is because the event is attached to an element more than once or the element you are auto clicking is a child of another element with the same event attached. Check to see if they are wrapped by each other and if so you will need to detect that the current target is equal to the target to make sure it only happens once. Or you can stop the event propagation.
try hooking it up with JQuery:
$(document).ready(function() {
$('#oPrevArrow').click(function() {
$('#btn_prevday').trigger('click');
});
$('#oNextArrow').click(function() {
$('#btn_nextday').trigger('click');
});
$('#oLogout').click(function() {
$('#btn_logout').trigger('click');
});
});
This could be even more concise, depending on how your arrows and Buttons are laid out in the DOM. Potentially it could be a single line of jQuery.
Something like:
$(document).ready(function() {
$('.arrow').click(function() { //note css class selector
$('this + button').trigger('click');
});
});
It happens due to the particular event is bound multiple times to the same element.
The solution which worked for me is:
Kill all the events attached using .die() method.
And then attach your method listener.
Thus,
$('.arrow').click(function() {
// FUNCTION BODY HERE
}
should be:
$('.arrow').die("click")
$('.arrow').click(function() {
// FUNCTION BODY HERE
}

overriding previously-bound click events

When I use this code with an element whose id is "foobar":
$("#foobar").click(function () { alert("first"); });
$("#foobar").click(function () { alert("second"); });
I get two alerts: "first" and "second" second.
How do I specify a click event that also clears out any previous click events attached to the element? I want the last $("#foobar").click(...) to erase any previously bound events.
You can unbind the events already attached to that element, and then attach the second event handler, so it will be the only one (note the unbind method).
$("#foobar").unbind("click").click(function() { alert("second"); });
$("#foobar").click(function () { alert("first"); });
$("#foobar").unbind('click').click(function () { alert("second"); });
Notice the unbind() method. It does exactly what it sounds like.

Categories