Event handler sequence in jQuery - javascript

I'm dynamically binding event to a text element. This is my code:
<input type="text" id="myTxt" />
<script type="text/javascript">
function attachEvent1(element){
element.keyup(function(){
console.log("Event:"+event.keyCode);
});
}
function attachEvent2(element){
element.keyup(function(){
console.log("Value:"+this.value);
});
}
attachEvent1($('#myTxt'));
attachEvent2($('#myTxt'));
</script>
What I need it, I want the second event handler (attched by attachEvent2) to get called first, even if it is binded after attachEvent1.
Is it possible in jQuery?

What about something like this:
function handler1()
{
console.log("Event:"+event.keyCode);
}
function handler2()
{
console.log("Value:"+this.value);
}
function attachEvent1(element)
{
element.keyup(handler1);
}
function attachEvent2(element)
{
element.unbind('keyup', handler1);
element.keyup(handler2);
element.bind('keyup', handler1);
}
attachEvent1($('#myTxt'));
attachEvent2($('#myTxt'));
If you want something fancier, you could keep a list of the handlers, and do the rebinding in a loop, etc. but this basic idea of re-binding the events, has the desired effect.

Related

removeeventlistner not working on button click

document.getElementById('divv').addEventListener("click",func)
function func(a){
alert("oooo");
}
function abc(){
document.getElementById('divv').removeEventListener("click",function(){func()});
}
<div id="divv">This is vivek</div>
<button onclick="abc()">Remove</button>
I have a button and I want to remove the onclick event on a div after I click on the button.
Just like that:
document.getElementById('divv').removeEventListener("click", func);
See the explanation about removeEventListener
document.getElementById('divv').addEventListener("click", func)
function func(a) {
alert("oooo");
}
function abc() {
document.getElementById('divv').removeEventListener("click", func);
}
<div id="divv">This is vivek</div>
<button onclick="abc()">Remove</button>
You are not adding and removing the same function, and that is why it doesn't work.
You are adding like this: .addEventListener("click", func")
And you are removing like this: .removeEventListener("click", function(){func()})
func and function(){func()} do not refer to the same function, even though they have the same result, when called.
You need to remove exactly the same way as you remove; otherwise removing won't "find" the original function you added:
function abc(){
document.getElementById('divv').removeEventListener("click",func);
}

Prevent element from animating based on previous class

$('.example').hover(
function () {
$(this).css('background','red');
},
function () {
$(this).css('background','yellow');
}
);
$('.test').click(function(){
$(this).css('marginTop','+=20px').removeClass('example');
}
);
<div class="text example"></div>
Although the class example was seemingly removed, the hover actions for it are still being applied to the element that once had that class. How can I prevent this?
http://jsfiddle.net/gSfc3/
Here it is in jsFiddle. As you can see, after executing the click function to remove the class, the background still changes on hover.
Event handlers are bound to a Node, so it doesn't matter if that Node doesn't own a specific className anymore. You would need to .unbind() those events manually, or better, use jQuerys .off() method.
So, if you can be sure that there aren't any other event handlers bound to that node, just call
$(this).css('marginTop','+=20px').removeClass('example').off();
This will remove any event handler from that Node. If you need to be specific, you can use jQuerys Event namespacing, like so
$('.example').on( 'mouseenter.myNamespace'
function () {
$(this).css('background','red');
}
).on('mouseleave.myNamespace'
function() {
$(this).css('background','yellow');
}
);
and use this call to only unbind any event that is within the namespace .myNamespace
$(this).css('marginTop','+=20px').removeClass('example').off('.myNamespace');
$('.example').unbind('mouseenter').unbind('mouseleave')
In your code, $('.example').hover attaches a mouseenter and mouseleave directly to each element.
-or-
A better solution might be to use delegation with on
$(document.body).on('mouseenter', '.example', function() { ... });
$(document.body).on('mouseleave', '.example', function() { ... });
Using that code, removing the example class will work as expected, because the handlers are based on css selector, while .hover attaches directly to the elements.
$('.example').live({
mouseenter:function () {
$(this).css('background','red');
},
mouseleave:function () {
$(this).css('background','yellow');
}
});
demo: http://jsfiddle.net/gSfc3/1/
Try this:
$('.test').hover(
function () {
$('.example').css('background','red');
},
function () {
$('.example').css('background','yellow');
}
);

jQuery unbind click event function and re-attach depending on situation

The code below I use to create a sliding menu. I need to know how to unbind the function attached to the click event and re-attach it some other time. (using jQuery 1.7.2)
$(document).ready(function(){
$('.section').hide();
$('.header').click(function(){
if($(this).next('.section').is(':visible'))
{
$('.section:visible').slideUp()
$('.arrows:visible').attr("src","right.gif")
}
else
{
$('.section').slideUp();
$(this).next('.section').slideToggle();
$(this).find('.arrows').attr("src","down.gif")
});
});
The code below is what I have so far
$('#printVers').click(function(){
if($('#formVersion').val() != "Print")
{
$('.header').unbind('click');
}
else
{
//else re-attach functionality?
}
});
Thanks
Simply make a named function. You can go low tech here and back to basics to unbind and reattach specific events.
function doStuff()
{
if($(this).,next('.section').is(':visible'))
...
}
$('.header').on('click', doStuff);
$('.header').off('click', doStuff);
Instead of unbind and re-bind, I suggest you to add a simple class to .header and check for the class in the click handler. See below,
$('#printVers').click(function(){
if($('#formVersion').val() != "Print")
{
$('.header').addClass('dontClick');
} else {
$('.header').removeClass('dontClick');
}
});
And in your .header click handler,
$('.header').click(function(){
if ($(this).hasClass('dontClick')) {
return false;
}
//rest of your code
If you insist on having a unbind and bind, then you can move the handler to a function and unbind/bind the function any number of time..
You can try something like this.
$('#printVers').click(function(){
if($('#formVersion').val() != "Print")
{
$('.header').addClass('clickDisabled');
}
else
{
$('.header').removeClass('clickDisabled');
}
});
And then in the click handler check for this class.
$(document).ready(function(){
$('.section').hide();
$('.header').click(function(){
if(!$(this).hasClass('clickDisabled')){
...
...
}
});
});
Why not make that top section a function, and then call it in your else statement?
You could try setting a variable as a flag. var canClick = ($('#formVersion').val() != 'Print'); Then in the click handler for your .header elements check to see if canClick is true before executing your code.
If you still want to remove the handler you can assign the events object to a variable. var eventObj = #('.header').data('events'); That will give you an object with all the handlers assigned to that object. To reassign the click event it would be like $('.header').bind('click', eventObj.click[0]);
After trying so hard with bind, unbind, on, off, click, attr, removeAttr, prop I made it work.
So, I have the following scenario: In my html i have NOT attached any inline onclick handlers.
Then in my Javascript i used the following to add an inline onclick handler:
$(element).attr('onclick','myFunction()');
To remove this at a later point from Javascript I used the following:
$(element).prop('onclick',null);
This is the way it worked for me to bind and unbind click events dinamically in Javascript. Remember NOT to insert any inline onclick handler in your elements.
You could put all the code under the .click in a separated function
function headerClick(){
if($(this).next('.section').is(':visible'))
{
$('.section:visible').slideUp()
$('.arrows:visible').attr("src","right.gif")
}
else
{
$('.section').slideUp();
$(this).next('.section').slideToggle();
$(this).find('.arrows').attr("src","down.gif")
}
}
and then bind it like this:
$(document).ready(function(){
$('.section').hide();
$('.header').click(headerClick);
});
$('#printVers').click(function(){
if($('#formVersion').val() != "Print")
{
$('.header').unbind('click');
}
else
{
$('.header').click(headerClick);
}
});

JavaScript click has different behavior than manual one

With prototype I'm listening for a click event on several checkboxes. On checkbox click I want to disable all <select> elements. I'm using prototype. So, I have this code:
$$('.silhouette-items input[type="checkbox"]').invoke('observe', 'click', function(event) {
var liItem = this.up('li.item');
if(this.checked) {
alert('checked');
liItem.removeClassName('inactive');
var selectItem = liItem.select('select');
for(i=0;i<selectItem.length;i++) {
selectItem[i].disabled=false;
if (selectItem[i].hasClassName('super-attribute-select')) {
selectItem[i].addClassName('required-entry');
}
}
} else {
alert('unchecked');
liItem.addClassName('inactive');
var selectItem = liItem.select('select');
for(i=0;i<selectItem.length;i++){
selectItem[i].disabled=true;
if (selectItem[i].hasClassName('super-attribute-select')) {
selectItem[i].removeClassName('required-entry');
}
}
}
calculatePrice();
});
When I manually click on the checkbox, everything seems to be fine. All elements are disabled as wanted.
However, I have also this button which on click event it fires one function which fires click event on that checkbox.
In Opera browser it works. In others, not. It's like Opera first (un)check and then executes event. Firefox first fires event, then (un)check element.
I don't know how to fix it.
The HTML:
<ul class="silhouette-items">
<li>
<input type="checkbox" checked="checked" id="include-item-17" class="include-item"/>
<select name="super_attribute[17][147]">(...)</select>
<select name="super_group[17]">(...)</select>
<button type="button" title="button" onclick="addToCart(this, 17)">Add to cart</button>
</li>
<!-- Repeat li few time with another id -->
</ul>
Another JS:
addToCart = function(button, productId) {
inactivateItems(productId);
productAddToCartForm.submit(button);
}
inactivateItems = function(productId) {
$$('.include-item').each(function(element) {
var itemId = element.id.replace(/[a-z-]*/, '');
if (itemId != productId && element.checked) {
simulateClickOnElement(element);
}
if (itemId == productId && !element.checked) {
simulateClickOnElement(element);
}
});
}
simulateClickOnElement = function(linkElement) {
fireEvent(linkElement, 'click');
}
Where fireEvent is a Magento function that triggers an event
Don't bother simulating a onclick if you can get away with not doing so. Having a separate function that can be called from within the event handler and from outside should work in your case.
var handler = function(){
//...
}
var nodeW = $('#node');
handler.call(nodeW);
Of course, this doesn't trigger all onclick handlers there might be but it is simpler so it should work all right. Points to note for when you use .call to call a function:
Whatever you pass as the first parameter is used as the this inside the call. I don't recall exactly what JQuery sets the this too but you should try passing the same thing for consistency.
The other parameters become the actual parameters of the function. In my example I don't pass any since we don't actually use the event object and also since I don't know how to emulate how JQuery creates that object as well.
replacing
fireEvent(linkElement, 'click');
with
linkElement.click();
works in firefox 5 and safari 5.1, so maybe the problem lies in the fireEvent() method.

How can I bind events to the appended element?

I tried to show an error message using the jquery effect fadeTo and tried to hide the message by appending a button and using fadeout but doesn't seem to work.
What I did was:
$("#sub_error")
.fadeTo(200, 0.1, function()
{
$("#sub_error")
.html(error.join("<br/><br/>"))
.append('<br/><input type="button" name="err_ok" id="err_ok" value="ok">')
.addClass('subboxerror')
.fadeTo(900,1);
});
$("#err_ok").click(function()
{
$("#sub_error").fadeOut("slow");
});
What am I doing wrong, could someone help me?
the #err_ok element doesn't exist at first so the .click() handler is not applied to it.
You can solve this by putting
$("#err_ok").click(function () {
$("#sub_error").fadeOut("slow");
});
in a function and call the function after creating the element in the DOM.
Edit: This should be a full solution:
$("#sub_error").fadeTo(200, 0.1, function() {
$("#sub_error")
.html(error.join("<br/><br/>"))
.append('<br/><input type="button" name="err_ok" id="err_ok" value="ok">')
.addClass('subboxerror')
.fadeTo(900, 1);
bindEvents();
});
function bindEvents() {
$("#err_ok").click(function() {
$("#sub_error").fadeOut("slow");
});
}
There is also a "live" function that binds events to future created DOM elements too.
FWIW, there are filed tickets about fadeTo/fadeOut bugs on the JQuery bug tracker.
There are a couple of ways to do this. One, you can append the click handler to the element after it is inserted:
$("#sub_error").fadeTo(200, 0.1, function() {
$("#sub_error")
.html(error.join("<br/><br/>"))
.append('<br/><input type="button" name="err_ok" id="err_ok" value="ok">')
.addClass('subboxerror')
.fadeTo(900, 1)
.find('#err_ok')
.click( function() {
$("#sub_error").fadeOut("slow");
});
});
Or two, you can use the live event handler so that any element with the "err_ok" id will get the click handler whenever it's created.
$('#err_ok').live('click', function() {
$('#sub_error').fadeOut('slow');
});

Categories

Resources