How to better handle events - javascript

If I have multiple events on an element I am currently handling those events as written here:
$("body").on("click", ".element", function(e) {
// Do something on click
});
$("body").on("change", ".element", function(e) {
// Do something on change
});
Is there a way to combine all the events on an element in one on() call? What is the best practice if there are multiple events associated with one element?
$("body").on("change click", ".element", function(e) {
// Can I detect here if it was change or click event and perform an action accordingly?
});

You can use the type property of the event to determine which logic to execute:
$('body').on('change click', '.element', function(e) {
if (e.type == 'click') {
// do something...
}
else if (e.type == 'change') {
// do something else...
}
});
Alternatively you can provide an object to on which contains the functions to bind with the event type names as the keys:
$('body').on({
click: function() {
// do something on click...
},
change: function() {
// do something on change...
}
}, '.element');
Personally I would use the latter method. The whole point of having a unified on() handler is negated when using a rather ugly if statement to split the event types.

Yes! jQuery passes the event object which contain the event information:
$("body").on("change click", ".element", function(e) {
console.log(e.type);
});

You can use the event.type. Some will say it's bad practice and others may find it useful.
$("body").on("change click", ".element", function(event) {
switch (event.type) {
case 'click':
break;
case 'change':
break;
default:
}
});
jQuery event.type

$('#element').on('keyup keypress blur change', function(event) {
alert(event.type); // keyup OR keypress OR blur OR change
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="element" />

Related

How to prevent BLUR event from firing multiple times?

I have certain text input fields where if users change a value and then blur away from that text field, the js will fire an ajax request to update that value in the db. The problem is that I wrote a test to get such an event to fire and I notice that the inner 'blur' event usually fires between two and five times after I tab out of the input field:
$('input[type=text]').on('input propertychange paste', function() {
$(this).on('blur', function () {
console.log('blur');
});
});
Even if I turn off the blur event handler right after catching it, it still fires two or three times. How do I get this to happen only once?
Just keep track of a hasFired boolean:
var hasFired = false;
$('input[type=text]').on('input propertychange paste', function() {
$(this).on('blur', function () {
if(!hasFired){
hasFired = true;
console.log('blur');
}
});
});
Actually, the real problem here is that you're binding the blur event multiple times. You can use a boolean like above to prevent that:
var isBound = false;
$('input[type=text]').on('input propertychange paste', function() {
if(!isBound){
isBound = true;
$(this).on('blur', function () {
console.log('blur');
});
}
});
Another solution would be is to create a class for those elements that already bound by that event.
$('input[type=text]').on('input propertychange paste', function() {
if(!$(this).hasClass("bound")) {
$(this).on('blur', function () {
$(this).addClass("bound");
console.log('blur');
});
}
});

check multiple events - jQuery

Suppose I want to run a function myFunction at each of the events $(document).ready, $(sometag).on('click',....). How can I construct a function that checks if any of those two events are triggered, and then run the method. Can I pass $(document) as an argument and then check $(document).isReady or check $(document).click(function(e){if (e.target.is($(some tag))) ...}). Is this correct ?
It's not easy to understand what the heck you are talking about, but it sounds like you're trying to attach an event handler and trigger it on document ready, and if so you'd do that like this :
$(document).ready(function() {
$(sometag).on('click', function() {
// do stuff
}).trigger('click');
});
If I understand you correctly:
function myFunc(event) {
if (event.type == 'ready')
console.log('It is a document.ready');
else if (event.type == 'click')
console.log('It is a click');
}
$(document).on('ready', myFunc).on('click', 'a', myFunc);
jsfiddle
from what i could understand from your question...
Jsfiddle: http://jsfiddle.net/patelmilanb1/eR4wG/1/
$('.checkbox').change(function (e) {
if (e.isTrigger) {
alert('not a human');
} else {
alert("manual check by human");
}
});
$('.checkbox').trigger('change'); //alert not a human because it is automatically triggered.
I may not understand your question very much, but try this:
$(function(){
$('div1,div2,#id1,#id2,.class1,.class2').click(function(){
// do something
yourFunction();
});
});
triggering function on multiple events of an element, you may try:
$('#element').on('keyup keypress blur change', function() {
...
});
and multiple function on multiple elements, try:
$('#element #element1 #element2').on('keyup keypress blur change', function() {
...
});

How to combine keypress & on click function in JavaScript?

I have the following two functions:
$("input").keypress(function(event) {
if (event.which == 13) {
//code
}
});
$('#login_submit').click(function () {
//code
});
The code which is being used in the functions are EXACTLY the same code, basically code dublication. So i was wondering if there is a way to combine these functions with an OR statement??
Create your own callback and pass that to the event handlers.
var callback = function() {...};
$("input").keypress(function() {
if (event.which == 13) callback();
});
$('#login_submit').click(callback);
Add a class to your HTML
<input class="myClass">
<div id="login_submit" class="myClass" ></div>
Now you can write:
$(".myClass").bind("keypress click", function(){});
Or do this:
$("input").add("#login_submit").bind("keypress click", function(){});
Be aware that clicking on the input will also trigger this.
Why don't you do it like this?
$("input").keypress(function(event) {
if (event.which == 13) {
foospace.yourfunction();
}
});
$('#login_submit').click(function () {
foospace.yourfunction();
});
var foospace={};
foospace.yourfunction=function() {
alert("your code goes here!");
}
Edit:
The callback solution by #David is slightly more elegant.
I would chain the events like:
var watchCurrentCursorPosition = function (){
console.log("foo");
}
$("input").keypress(
watchCurrentCursorPosition
).click(
watchCurrentCursorPosition
);
For those who still are looking for an answer to the #Sino's question.
The code which is being used in the functions are EXACTLY the same code, basically code dublication. So i was wondering if there is a way to combine these functions with an OR statement??
JQuery .on() method is the way to go.
Description: Attach an event handler function for one or more events to the selected elements.
So your code could go like this:
$("input").on("click keypress", function(event) {
if (event.which === 13) {
event.preventDefault();
//code
}
});

Mastering event bubbling

Lets say we have a HTML structure like this
<div id="container">
<div id="nested">
<span id="someElement"></span>
</div>
</div>
...and our goal is to have an event listener on the #container only ! So, we bind a listener (jQuery code)
$("#container").on('click', function(event) {
alert("container was clicked");
});
That works of course, but my problem with this approach is that, since events usually bubble up, that listener will also fire if we actually click on #nested or #someElement. My current solution to only handle the click when the #container is clicked is to compare this with event.target
$("#container").on('click', function(event) {
if(this === event.target) {
alert("container was clicked");
}
});
My question: Is that considered "best practice" ? Is there a better way with jQuery to accomplish the same result "out of the box" ?
Example in action: http://jsfiddle.net/FKX7p/
An alternative way to prevent events from bubbling up is to use event.stopPropagation();
$("#container").on('click', function(event) {
alert("container was clicked");
})
.children().on('click', function(event) {
event.stopPropagation();
});
I think the advantage of using this approach is that if you want to attach another event to the nested div, you can just use
$("#nested").on('click', function(event) {
event.stopPropagation();
// some action
});
$("#container").on('click', function(event) {
alert("container was clicked");
});​
I'm not sure which one work's faster but it make sense that the next code will be better:
$("#container").click(function (e) {
if (e.target.id && e.target.id !== "container") return false;
});
Alternative solution:
$("#container").click(function(){
alert("container was clicked");
}).children().click(function(e) {
return false;
});
But your solution is better. jsfiddle.net/FKX7p/2/ (with return false) OR jsfiddle.net/FKX7p/3/ (using stopPropagation)
I prefer use return in your example (code becomes easier to read):
if(this !== event.target) return;

Can I determine what event triggered an event handler in jQuery if I bind multiple ones?

Check this example:
$('button').bind('click focus', function() {
// Did I click or focus?
});
Is there a way to work that out when binding multiple events to one handler?
This may work, but it is kind of ugly:
var eventType;
$('button').click(function() {
eventType = 'click';
do();
});
$('button').focus(function() {
eventType = 'focus';
do();
});
function do() {
alert(eventType);
}
You can use event.type on the event object (the first param passed to the handler), like this:
$('button').bind('click focus', function(e) {
if(e.type == "click") {
//do something, it was a click
}
});

Categories

Resources