Event delegation on parent only works with some events - javascript

Why am I able to listen to certain events using event delegation on window.parent.document but not others? Specifically I found that I was able to listen to a button's click event, but trying to do the same for the jQueryUI's dialogbeforeclose event wouldn't trigger the event handler.
For example binding to a click event for a button like the following worked
$(window.parent.document).on('click', '#btnTest', function () {
alert('Button clicked');
});
However trying to listen to the custom jQuery UI event like the following doesn't (the same code works on the parent page itself when binding to the document)
$(window.parent.document).on('dialogbeforeclose', function () {
alert('Dialog closing');
});
But binding it to the parent's body instead does
window.parent.$('body').on("dialogbeforeclose", function(event, ui) {
alert('Bound on body');
});
For some additional context, I have a parent html page that has a jQuery UI dialog which has a iFrame within it.
Parent HTML
<div id="btnCnt">
<input type="button" id="btnTest" value="Test 2"/>
</div>
<div id="popUpCnt" >
<iframe id="frmTest">
</iframe>
</div>

When an event is triggered using .trigger() (which is the case for custom events) jQuery goes through and triggers the events that are stored in that instance of jQuery's data cache. Since you bound to the event with a different instance of jQuery than the one that triggered the event, your event handler was never triggered. For example, see this fiddle:
http://jsfiddle.net/EJg8b/
jq2 = $.noConflict();
jq1 = $;
jq1('body').on('click', function () {
console.log('jq1 click event!');
});
jq2('body').on('click', function () {
console.log('jq2 click event!');
});
jq1('body').on('myCustomEvent', function () {
console.log('jq1 myCustomEvent event!');
});
jq2('body').on('myCustomEvent', function () {
console.log('jq2 myCustomEvent event!');
});
function onButtonClick() {
jq1('button').trigger('myCustomEvent');
}
Because the custom event was triggered with jq1, only the event bound with jq1 was able to receive it. The click on the other hand was a native event, and therefore was picked up by both.

Related

IE: jQuery click listener fires on parent of disabled button

Is there a way to prevent firing of jQuery .click() listener on parent of button that is disabled?
e.g in this case:
<div>
<button disabled="disabled">click me</button>
</div>
<script>
// unfortunately this click handler is placed by 3rd party
// library and I can't edit it. Just add another handlers or css
$('div').on('click', function () {
alert('div is still clickable, probable you use IE');
});
</script>
In my project click event is placed with third-party library so I can't enable/disable itself or move binding to button.
ADD: I've found solution with not disabling the button, but proving it a "disabled" class, and adding event listener:
$('button').on('click', function (event) {
if ($(this).hasClass('disabled')) {
event.stopImmediatePropagation();
}
});
but what about disabled button? Is there a way to work with it?
Try this:
$('div').on('click', function (event) {
if ($(this).find('button').is(':disabled')) {
return false;
}
});
This might work for you
$('button').not(':disabled').parent().on('click',function(){});
You CAN remove the third-party click event and rebind them all on the page this way also with .off() or unbind()
$('div').unbind(); //or .off() depending on how the third-party set the handler
//then add your own click method after the unbinding.

jQuery: Cannot properly bind custom event with the same name on window and element

I am trying to bind a custom event with the same name on both $(window) and $('#slider'). Then I want to make the window event to trigger the element event.
So, the workflow would be:
1. Bind element event to say `Hello world` f.e.
2. Bind window event to trigger element event
3. Trigger window event
And the result:
1. Window event is triggered
2. Element event is triggered
Everything looks good, but once the window event is triggered, the whole thing goes into a crazy self-calling loop, until the browser crashes.
It simply looks as if the element event triggers back the event on window.
Here's my code:
$('#slider').bind('asd', function() {
console.log('asd called on slider');
});
$(window).bind('asd', function() {
console.log('asd called on window');
$('#slider').trigger('asd');
}).trigger('asd');
Events bubble. triggering an event on a child of the window will result in the event eventually reaching the window unless you stop propagation.
One way around this is to just trigger the handler, not the event.
$('#slider').bind('asd', function() {
console.log('asd called on slider');
});
$(window).bind('asd', function() {
console.log('asd called on window');
$('#slider').triggerHandler('asd');
}).trigger('asd');
And here's another way:
$('#slider').bind('asd', function(e) {
e.stopPropagation();
console.log('asd called on slider');
});
$(window).bind('asd', function() {
console.log('asd called on window');
$('#slider').trigger('asd');
}).trigger('asd');
Use event.stopPropagation() to stop DOM bubbling:
$('#slider').bind('asd', function(event) {
event.stopPropagation()
console.log('asd called on slider');
});
$(window).bind('asd', function() {
console.log('asd called on window');
$('#slider').trigger('asd');
}).trigger('asd');

Each submit button calls the same function

I'm calling function for selecting component ID after page refresh:
$(document).ready(
function() {
document.getElementById('form:#{myBDE.componentId}').focus();
document.getElementById('form:#{myBDE.componentId}').select();
}
)
My submit button example:
<h:form id="form">
<h:commandButton id="btnSubmit" action="#{myBDE.save}" type="submit" >
<f:ajax execute="#form" render="#form"/>
</h:commandButton>
...
</form>
How can I create the same function to be called each time I click any submit button (I'm using ajax, so I'm working without page reloading, document.ready is not enough for me). Is it possible?
update (partially functional solution):
var myFunc = function() {
document.getElementById('form:#{myBDE.componentId}').focus();
document.getElementById('form:#{myBDE.componentId}').select();
};
$(document).ready(function() {
myFunc();
$('input[type=submit]').click(myFunc);
});
I can call the function adding onclick="return myFunc();" to h:commandButton, problem is, that <f:ajax> render the form after calling the function, so the select and focus is cleared :(
Give the function a name (currently, its an anonymous function), and then call the function as and when you need.
$(document).ready(
onPageLoad(); // call it when page loads
$('form').submit(onPageLoad); // also call whenever a form is submitted
)
function onPageLoad() {
document.getElementById('form:#{myBDE.componentId}').focus();
document.getElementById('form:#{myBDE.componentId}').select();
return true;
}
This should work
$('input[type="submit"]').click(function(){
document.getElementById('form:#{myBDE.componentId}').focus();
document.getElementById('form:#{myBDE.componentId}').select();
});
In fact you can bind a function to any events. In this case it is the click event for the input tag with the attribute type=submit
You should delegate the handler to a higher-level dom element:
$(document).ready(function() {
$('h:body').on('click', 'input[type=submit]', function() {
document.getElementById('form:#{myBDE.componentId}').focus();
document.getElementById('form:#{myBDE.componentId}').select();
});
});
See jQuery.on().
When a selector is provided, the event handler is referred to as
delegated. The handler is not called when the event occurs directly on
the bound element, but only for descendants (inner elements) that
match the selector. jQuery bubbles the event from the event target up
to the element where the handler is attached (i.e., innermost to
outermost element) and runs the handler for any elements along that
path matching the selector.
And then later:
Delegated events have the advantage that they can process events from
descendant elements that are added to the document at a later time. By
picking an element that is guaranteed to be present at the time the
delegated event handler is attached, you can use delegated events to
avoid the need to frequently attach and remove event handlers.
So the event will be handled for all elements of that type, even if they are added later via ajax. Note that I used h:body here as the element to delegate to but you can use any element that exists at document.ready time and is guaranteed to be an ancestor of all submit inputs.
If you have different ID or Name on them it's just to do somthing like
$(document).ready(function(){
$('#btn1, #btn2, #btn3').on('click', function(evt){
evt.preventDefault();
//your code
$(this).submit(); // or not submit, your choice
});
});
Try this thing
$(document).ready( function (){
$('input[type=submit]').click( function (){
// Whatever you want on submit button click option.
}
});
This will grab every submit button on the page and will bind click event to it, and this code will be called on any submit button click.

Click event not firing with dynamically create buttons

I have dynamically created the buttons in a div. And binding the click and other events for the buttons. But the problem is, click event fired only one for first clicked button. It happens same for the other binding events. The sample code is
$('#divButtons input[type=button]').each(function () {
$(this).bind('mouseover', function (e) {
// some work
}).bind('mouseout', function (e) {
// some work
}).bind('click', function (e) {
// some work
});
});
It works good when bind it on document.ready() But in my case buttons created far after DOM ready.
I also want to know why it behaves like this...?
If using jQuery 1.7+ go for on(), and there's really no need for each() :
$(document).on({
mouseover: function(e) {
// some work
},
mouseout: function(e) {
// some work
},
click: function(e) {
// some work
}
}, '#divButtons input[type=button]');
replace document with nearest non dynamic element for delegated event handler.

Why do my input elements not retain focus/blur events after postback?

I am using jQuery to set the focus/blur events of some input textbox controls via
$(function() {
..
});
But whenever a postback occurs, my controls no longer perform these events. I tried removing them from the document ready event and placing the code at the bottom of document, hoping it would load it each time, but that didn't work. How can I get these controls to retain there focus/blur events after postbacks?
Didn't think it mattered, but these postbacks are taking place in an ajax:UpdatePanel
You are attaching the events once to the elements, and they are removed later which means the events are also removed. You could attach the events again and again but you can simply attach the events to a higher level parent node and not worry about it:
$(function () {
$(document).on('focusin', 'input.userTxtA_center', function () {
this.value = '';
this.className = 'userTxtB_center';
});
});
I am using the focusin event instead of focus because focus doesn't bubble.
Isolated demo: http://jsfiddle.net/TUqsE/
Bind your methods using .live()
$('selector').live('EVENT', function() { });
Where EVENT is blur/focus/etc... Then it won't matter when your controls are created in the DOM, jQuery will automatically re-hookup the handler.
http://api.jquery.com/live/
OR Re-connect the events after the postback is complete
See - ASP.NET - UpdatePanel and JavaScript - for how to do it.
yes, it is because the updatepannel,
use this pageload event instead of $(document).ready or $(function() {});
exmaple:
<script type="text/javascript" language="javascript">
function pageLoad() {
$('#MyId').bind("mouseover", function(e) {
// Do something exciting
});
}
</script>

Categories