Often there is situation when I need to add some event with some customizations and then apply those customizations on page ready.
Usually I was doing it like:
$(window).resize(function(){
//some code
}).resize(); //trigger it when event defined
Problem with this solution is that if I have many resize events, then if I trigger it like this - it will re-execute all previously defined events too.
So another solution could be:
var myCallback = function(){ /*some code*/ };
$(window).resize(function(){
myCallback();
});
myCallback();
And it does it correctly but I find it not so good looking code and also there is no this inside function changed to event target DOM element that is very useful quite often.
Great would be something like
$(window).addEventAndFireOnce("resize", function(){});
such function is not so hard to implement, but I'm wondering if there is something like this there already in js or jQuery.
I don't know if I'm alone in this, but if I need to do that (and it's not uncommon) I bind a custom event name (possibly with a scope) at the same time as I bind the real event ("click" or "change" or whatever):
var myCallback = function(ev) { ... };
$(window).on("resize my-resize", myCallback).trigger("my-resize");
That's particularly useful when you're handling something like a "click" event on a checkbox. Triggering the "click" will actually update the checkbox "checked" state, which is not generally what you'd want to do. There's the jQuery .triggerHandler() method, but for whatever reason that only works on the first element in the jQuery object, so you can't trigger the handlers for all the checkboxes in a form with one call.
I would write it like so:
var myCallback = function(){ /*some code*/ };
$(window).resize( myCallback );
myCallback();
I think what you are looking for here is namespaced handlers
var log = (function() {
var $log = $('#log');
return function(msg) {
$('<p/>', {
text: msg
}).appendTo($log)
}
})();
$(window).resize(function() {
log('handler 1');
});
$(window).resize(function() {
log('handler 2');
});
$(window).on('resize.myspecial', function() {
log('handler 3');
}).trigger('resize.myspecial');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="log"></div>
Related
I was wondering if Javascript or jQuery have a way to delete an event listener. Let's say I want to make a function that I want to trigger only once, for example let's say I want to have a button that shows some hidden elements on the document, I would make this function (assuming the hidden elements have a hidden class that hides them):
jQuery('#toggler').click(function() {
console.log('Hidden elements are now shown');
jQuery('.hidden').removeClass('hidden');
});
Simple enough, right ? Now, my actual problem comes in, I don't want jquery to run that function again and again each time the button is clicked, because the elements are already revealed, so is there a clean way to do it ? So, in this example after clicking the toggler multiple times I want to get only one console message.
I could do jQuery(this).unbind('click'), but this results into removing ALL triggers and I only want to remove the current trigger.
What I usually do when I face such scenarios is solve it like this (which is ugly and doesn't actually prevent code execution, but only handles the code's results) :
var toggler_clicked = false;
jQuery('#toggler').click(function() {
if(toggler_clicked) return;
toggler_clicked = true;
console.log('Hidden elements are now shown');
jQuery('.hidden').removeClass('hidden');
});
Also I don't want to use jQuery's one, because I will have the same problem when I'll need to delete the trigger conditionally, so if you can help please give me a dynamic answer.
Thanks in advance !
You have to name your function like that:
var myFunction = function() {
console.log('Hidden elements are now shown');
jQuery('.hidden').removeClass('hidden');
};
And bind it this way
jQuery('#toggler').click(myFunction);
Then you can unbind it with :
jQuery('#toggler').off('click',myFunction);
Without unbinding the other listeners
You can try this:
var myFunc = function() {
console.log('Hidden elements are now shown');
jQuery('.hidden').removeClass('hidden');
jQuery(this).unbind('click', myFunc);
};
jQuery('#toggler').click(myFunc);
This way of calling unbind is such that only the listener for myFunc handler is removed and not all the events connected to the click on the toggler.
I would use the .on() and its opposite .off() methods to attach/detach the event handler. It is the recommended way since 1.7 instead of the .bind() and .unbind() versions that became deprecated as of jQuery 3.0.
$("#toggler").on("click", function(event) {
console.log('Hidden elements are now shown');
$('.hidden').removeClass('hidden');
// if (/* Add your condition here */) {
$(this).off(event);
// }
});
$("#toggler").on("click", function(event) {
console.log('Hidden elements are now shown');
$('.hidden').removeClass('hidden');
// if (/* Add your condition here */) {
$(this).off(event);
// }
});
.hidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="toggler">Toggle</button>
<div class="hidden">
HIDDEN
</div>
Try this
var myFunction = function() {
console.log('Hidden elements are now shown');
jQuery('.hidden').removeClass('hidden');
};
Add the event listener like this:
jQuery('#toggler').addEventListener("click", myFunction);
And remove it like this:
jQuery('#toggler').removeEventListener("click", myFunction);
So all together this will do the trick:
var myFunction = function() {
console.log('Hidden elements are now shown');
jQuery('.hidden').removeClass('hidden');
jQuery('#toggler').removeEventListener("click", myFunction);
};
jQuery('#toggler').addEventListener("click", myFunction);
more about the HTML DOM removeEventListener() Method
Jquery unbind function takes 2 parameters eventType and handler
You can put your event listener into separate function like this:
var clickEventHandler = function(){
//your logic goes here
}
After you add listener as reference:
jQuery('#toggler').click(clickEventHandler);
And then, later, anytime, anywhere you want you can unbind that specific handler:
jQuery('#toggler').unbind('click', clickEventHandler);
What i used to do in the past is toggle the click behavior using css classes, ex i used to set a click listener on the parent and delegate to all of the children something that jquery is doing now by default i believe. Anyway based on the css class it will trigger an event for ex.
$('.some-parent-element').on(
'click',
'the-behavior-css-class',
function() { // do stuff here.... }
)
Now if you want to remove this behavior you can just toggle the class of the element and it should do the job. ex
$('.some-parent-element').on(
'click',
'hide-me-on-click-or-whatever',
function() {
$(this).toggleClass('hide-me-on-click-or-whatever')
// perform the action
}
)
You can check if the element has the class hidden
Trigger a Jquery function that has $this. on window load and on click
function get_div_id(){
var f_id = $(this).attr("id");
alert(f_id);
}
$(window).load(function(){
get_div_id();
});
$('.divs_same_class_diferent_id').click(function() {
get_div_id();
});
As you can deduce, this will not work, but you have an idea of what I'm trying to do, right?
Depending on where that code is it may be running prior to the DOM being created in which case you're attempting to bind event listeners to elements that do not yet exist. try this:
function get_div_id(){
var f_id = $(this).attr("id");
alert(f_id);
}
$(document).ready(function(){
$('.divs_same_class_diferent_id').click(get_div_id);
// notice no anonymous function, this works because
// we're passing in the function object for get_div_id
});
I would like to call function when slideUp or slideDown are performed on an element. Is this possible?
Something like:
$('#panel').on('slideUp', function() { open--; });
$('#panel').on('slideDown', function() { open++; });
Update: The problem is that there are a ton of slide calls (e.g.: $().slideUp()) all over the page, within ajax responses, hash link clicks, etc.. I was hoping to bind to the slide itself somehow rather than add code to each calling function.
You cannot bind to an event since there is no such.
But you can pass a handler that will be called after animation is finished
$('#panel').slideUp(function() { ... });
http://api.jquery.com/slideUp/
If you really want to do this, you can use custom events and your own little plugin, something like this:
$.fn.mySlideToggle = function() {
this.slideToggle();
this.trigger('mySlideToggle');
}
$('div').on('mySlideToggle', function(){ console.log('hey') });
$('button').on('click', function(){ $('div').mySlideToggle(); });
Here's a little demo (check console): http://jsbin.com/asejif/2/edit
In your case it is redundant though, since you can use the callback that the slide events provide, but it might be useful for other things...
In many cases, I need to bind a behaviour to an element after loading, and then after an event triggering (like "change").
I think the best way would be to make it in the same line:
$('#element_id').bind('load, change', function () {
...
});
But this works only for "change" and not for "load". There is a better way?
I stumbled across the same problem. Removing comma is not enough, at least not in this case:
$(document).ready(function(){
$('#element_id').bind('load change', function () {
... // (this DOESN'T get called on page load)
});
});
I guess load events get triggered before $(document).ready().
This is a simple solution:
$(document).ready(function(){
$('#element_id').bind('change', function () {
...
});
$('#element_id').trigger('change');
});
For already loaded content, when you want to run a function on an event and also straight away, you can use a custom event of your own naming to avoid triggering any existing bindings from libraries etc. on the built in events, e.g.
$(".my-selector").on("change rightnow", function() {
// do stuff...
}).triggerHandler("rightnow");
Don't you just need to remove the comma?
try it without the comma:
$('#element_id').bind('load change', function () {
...
});
http://api.jquery.com/bind/#multiple-events
I think I've been too much time looking at this function and just got stuck trying to figure out the nice clean way to do it.
It's a jQuery function that adds a click event to any div that has a click CSS class. When that div.click is clicked it redirects the user to the first link found in it.
function clickabledivs() {
$('.click').each(
function (intIndex) {
$(this).bind("click", function(){
window.location = $( "#"+$(this).attr('id')+" a:first-child" ).attr('href');
});
}
);
}
The code simply works although I'm pretty sure there is a fairly better way to accomplish it, specially the selector I am using: $( "#"+$(this).attr('id')+" a:first-child" ). Everything looks long and slow. Any ideas?
Please let me know if you need more details.
PS: I've found some really nice jQuery benchmarking reference from Project2k.de here:
http://blog.projekt2k.de/2010/01/benchmarking-jquery-1-4/
Depending on how many of these div.click elements you have, you may want to use event delegation to handle these clicks. This means using a single event handler for all divs that have the click class. Then, inside that event handler, your callback acts based on which div.click the event originated from. Like this:
$('#div-click-parent').click(function (event)
{
var $target = $(event.target); // the element that fired the original click event
if ($target.is('div.click'))
{
window.location.href = $target.find('a').attr('href');
}
});
Fewer event handlers means better scaling - more div.click elements won't slow down your event handling.
optimized delegation with jQuery 1.7+
$('#div-click-parent').on('click', 'div.click', function () {
window.location.href = $(this).find('a').attr('href');
});
Instead of binding all the clicks on load, why not bind them on click? Should be much more optimal.
$(document).ready(function() {
$('.click').click(function() {
window.location = $(this).children('a:first').attr('href');
return false;
});
});
I would probably do something like;
$('.click').click(function(e){
window.location.href = $(this).find('a').attr('href');
});