Two elements using the same event function - javascript

What is the best way to share one function between two different event handlers? I want the same outcome but some situation dependent variables will need to be defined within the function depending on which element was clicked.
I could hack a solution but want to know the best practice for such a scenario. Simple problem must have a simple answer.
EXAMPLE
var onMyEvent = function(e){
if(click triggered from 'a'){
//do that
}
if(click triggered from 'div'){
//do that
}
}
$('a').click(onMyEvent);
$('div').click(onMyEvent);
FIDDLE: http://jsfiddle.net/f6C92/

I guess there'd be several ways to achieve this, such as checking the e variable for target objects, etc, but for your scenario, the easiest and most readable would be using the is() function, to which you can pass any CSS selector to test if the object of interest matches it.
var onMyEvent = function(e){
if($(this).is('a')){
//do that
}
if($(this).is('div')){
//do that
}
}
$('a').click(onMyEvent);
$('div').click(onMyEvent);
There are those who would argue that the above takes an unnecessary round-trip to jQuery, when you could achieve the same by testing this.tagName == 'A', but I usually recommend to delegate these things to jQuery as well, for browser compatibility reasons.
Another neat way would be to pass the relevant information as event data:
var onMyEvent = function(e){
if(e.data.type == 'a'){
//do that
}
...
}
$('a').click({ type: 'a' }, onMyEvent);
$('div').click({ type: 'div' }, onMyEvent);

It depends how complicated the differences are, but I don't really like checking element type in the handler. I would probably do something like this:
function doSomething(...){
// do stuff
}
$('a').click(function(){
// set some variables and send them as parameters to doSomething
doSomething(...);
});
$('div').click(function(){
// set some variables and send them as parameters to doSomething
doSomething(...);
});
Where doSomething contains the common code.

The target property of the event will contain the element that was clicked. In this updated fiddle, I alert the id of the clicked element, using e.target.id.

This ought to do the trick:
var onMyEvent = function(e) {
if (this.tagName == "A") {
alert("a");
} else if (this.tagName == "DIV") {
alert("div");
}
}

var onMyEvent = function(e){
if(this.tagName == 'A'){
alert("a");
}
if(this.tagName == 'DIV'){
alert("div");
}
}
$('a').click(onMyEvent);
$('div').click(onMyEvent);
Even if this will work in my opinion it's better to set a different handler for each tag, and call the same function inside it, like kingjiv suggested

Related

Fire jQuery .on('change') always at least once

I often find myself using pieces of code like the following:
$('[name=myradio]').on('change', function(){
if($(this).val() == 0){
$('#div').toggle();
}
else if(....){
$('#div2').toggle();
}
//...and more code going on
});
However, often I want to execute these pieces of code always at least once (for example when validation fails)! Of course I could make a method of this code and then execute the method from within the change anonymous function, as wel as in a $(document).ready() method, but I wonder if there is an easy way to execute that code at least once but also keep that code only in the change method to keep everything nice and clean instead of making a method for something that would be used only twice.
you can just trigger change in $(document).ready(...)
$(document).ready(function() {
$('[name=myradio]').on('change', function() {
if ($(this).val() == 0) {
$('#div').toggle();
} else if (....) {
$('#div2').toggle();
}
//...and more code going on
}).trigger("change");
});
Use trigger() method. This way you can keep the code only in the change method and trigger it from anywhere.
$(selector).trigger("change");

Events depending on a dynamic variable at jQuery

I'm wondering which would be the proper way to deal with events which depend on the status of a variable.
Right now, I have a listener which it is only added if the option isTablet is set to true. (as if not, it breaks in old versions of IE). So it looks like this:
if(options.isTablet){
document.addEventListener('touchmove', function(e){
....
});
}
Now, I'm having troubles if I want to change the variable isTablet dynamically with a setter and It won't load the event touchmove.
$.fn.myPlugin.setIsTablet = function(value){
options.isTablet = value;
}
I guess the simple way is always adding the event and inside it deciding whether or not to execute the code:
document.addEventListener('touchmove', function(e){
if(options.isTablet){
....
}
});
But throws an error in IE 8:
Object doesn't support property or method 'addEventListener'
What would be the way of doing it?
Thanks.
Generally, I would always add the listener and check the condition inside. To avoid your error, since you're using jQuery, just use jQuery:
$(document).on('touchmove', function(e){
if(options.isTablet){
....
}
});
If you have a handler that is called very often, you could consider turning it off when not needed. Something like this:
function myHandler(e) { ... }
$.fn.myPlugin.setIsTablet = function(value){
options.isTablet = value;
if (value) {
$(document).off('touchmove').on('touchmove', myHandler);
} else {
$(document).off('touchmove');
}
}
Be careful not to bind the handler more than once (like if true is sent to setIsTablet more than once in a row). You could also use a flag instead of unbinding/binding like I've shown.

jQuery function in two events

I have this code:
$('#email').keyup(function() {
if(true || false)) {
} else {
}
});
I need include this function also in blur event.
I've tried to create a jquery function but I could not. Somebody give me a light.
You can do this -
$('#email').on('keyup blur',function() {
http://api.jquery.com/on/
Use the on method to attach multiple events, which are specified in the first argument passed to the function.
$('#email').on('keyup blur', function() {
if(true || false) { //there was an extra ) here
} else {
}
});
Working Example http://jsfiddle.net/nv39M/
One thing to be aware of, the keyup event is going to fire prior to the blur event firing.
Make a separate function as follows
function funcName(){
//Your code
}
Now,use jQuery on
$("#email").on("keyup",funcName);
$("#email").on("blur",funcName);
For reference,check
http://api.jquery.com/on/
There are (at least) two ways you could achieve this.
Specify multiple, space separated events as the first argument:
$('#email').on('keyup blur',function() {
// your logic
});
Use a named function:
function yourFunction() {
// your logic
}
$('#email').on('keyup', yourFunction);
$('#email').on('blur', yourFunction);
Option 1 is probably the best choice assuming you don't want to use the function anywhere else, and that you want to bind the event handlers at the same time. If, however, you wanted to bind the blur event at a later point (perhaps in response to another event), or to a different element, then the named function method would be the best choice.

Attach function with parameters to dynamically created div with jQuery

I am creating some divs dynamically and Im attaching onclick functions to them.
Is there any way to attach functions which take parameters in this way?
If I just create the div in html I can attach a function and it works perfectly. I can also attach simple functions without parameters dynamically and they work perfectly.
How could I attach this function which takes 'this' as a parameter to my div??
Would anyone have any suggestions???
onclick="playSound(this)"
function playSound(el){
var soundId = $(el).html();
if ( soundId == ('d')){
d.playclip()
}
else if ( soundId == ('a')){
a.playclip()
}
else if ( soundId == ('n')){
n.playclip()
}
I can attach a function like this and it works fine.
$(".myDiv").live("click", function(){
alert('hello');
});
Any help would be hugely appreciated!!!
Thanks!!
For this specific case you could use something like:
$(".myDiv").click(function(){
playSound(this);
});
If you refactor your code dropping el and using this in this way:
function playSound() {
var soundId = $(this).html();
if (soundId == ('d')) {
d.playclip()
} else if (soundId == ('a')) {
a.playclip()
} else if (soundId == ('n')) {
n.playclip()
}
}
You could use it directly.
$(".myDiv").click(playSound);
You can attach some data to your elements using $(el).data('some-key', 'some-value') and
$(".myDiv").live("click", function() {
alert($(this).data('some-key'));
})
In this way you can attach data to an element and make use of it later.
absolutely. It's called javascript's bind function:
playSound.bind(this, arg1, arg2, ...)
Another useful function that is similar is jquery's proxy function. This only keeps track of the scope though and doesn't allow you to send other parameters:
$.proxy(playSound, this)

Can I run nest a $('element.class').each() function within the change() function for the same $('element.class')?

Specifically, I want to iterate over every element on the page, each time the value of one changes.
So to paraphrase my code I have:
$('select.filterbox').change(function() {
// stuff
$('select.filterbox').each(function() {
// other stuff
});
});
'stuff' all executes just fine, but 'other stuff' doesn't happen
Here's the full code
// On Filterbox Change
$j('select.filterbox').change(function() {
// Show All Rows
$j('#table1 tr').show();
// For Each Filterbox
$j('select.filterbox').each(function() {
var selVal = $j(this).attr('value');
var col = $j(this).closest('th').parent().children().index($j(this).closest('th'));
alert('Column '+val+' : '+selVal);
// If Selected Value Not Empty
if(selVal != "") {
// For Each Row
$j('#table1 tr').each(function() {
var $tds = $j(this).find('td');
var cellVal = $tds.eq(col).text();
cellVal = $j.trim(cellVal);
// If td text != selected
if( cellVal != selVal ) {
// Hide this row
$j(this).hide();
}
});
}
});
});
Answer: yes you can. I've done a lot of stuff like that recently. Indeed, your code should do it. It is likely that you've made some small but significant error in your code that will need to be hunted down and fixed. I've done a lot of stuff stuff like that recently, too.
More helpful answer: do things to figure out where the breakdown is. replace the "$('select.filterbox').each()" call with something obvious - say, calling .hide() on large chunks of your page. Make sure that line of code is even being called. If it is being called, put the "$('select.filterbox').each()" call back, then move the hide() call inside of it. If that works, then you know that it's running at least once. Change the hide() call to a (this).hide(), and see if you can see which one it's identified. Once you've narrowed down where it's failing you, it'll be a lot easier to figure out what you've done wrong.
You can do this, but it's not optimal to attach separate event handlers to a lot of elements. You can take advantage of event bubbling and just attach a single handler to their parent container. For example:
$("#filters").change(function (evt) {
// evt.target will give you actual element that changed
$("#filters select.filterbox").each(function () {
// other stuff
});
});

Categories

Resources