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

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>

Related

How can you trigger a focus event on a text node using jQuery

I have an html text node (an li tag in this case) that I am trying to trigger focus on using jQuery:
$('#branch').focus();
Or even:
$('#branch').trigger('focus');
I have attached an event listener:
$('#branch').on('focus', function() { console.log('focused'); });
But the event listener isn't firing. What do I need to do to fire this event listener?
If I listen for a 'hocus' event, and fire that event instead, the listener does indeed fire:
(I need this to unit test what happens when you focus on the node, I'm building an accessible tree)
As detailed by Shane Tomlinson here:
Text nodes are considered to be inert, and therefore cannot be
"focused" according to the w3c
Firing jQuery's .focus() method on a text node basically just gets swallowed up.
Instead, you have to use vanilla JS (works in Chrome, haven't tested other browsers):
$('#branch').on('focus', function () {
console.log('jquery listened');
});
var branch = document.getElementById('branch');
branch.addEventListener('focus', function() {
console.log('js listened');
});
// $('#branch').focus(); // this doesn't work! Use JS below instead...
var event = new Event('focus');
branch.dispatchEvent(event);
See jsbin of example

Click function not working in .each() function

I want to use click() as eventhandler and that event handler is not working you can see code below
$('.ajax-close').click(function( event ){
event.preventDefault();
alert('hi');
$( '.ajax-live-on' ).removeClass('ajax-live-on');
});
I have used all the code to initialize the jquery no problem , all right. But this piece of code not working
Here is the jsBin link
http://jsbin.com/doxeravizo/1/edit?html,css,js,output
The $('.ajax-close') collection doesn't contain the elements taking that class after the binding.
Change
$('.ajax-close').click(function( event ){
to
$(document.body).on('click', '.ajax-close', function( event ){
You should also move that binding outside of the loop, there's no reason to do it at every iteration.
Note also that in order to have your span clickable, it must have some content.
Demonstration (I added the jQuery library to make the fiddle work)
I'm guessing that because you're using ajax, your .ajax-close is not created when the event listener is being created.
You're going to want to delegate your click function:
$(document).on('click', '.ajax-close', function(event) {
event.preventDefault();
alert('hi');
$('.ajax-live-on').removeClass('ajax-live-on');
});
This article will help, but just for reference, this bit in particular:
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. This element could be the container element of a view in a Model-View-Controller design, for example, or document if the event handler wants to monitor all bubbling events in the document. The document element is available in the head of the document before loading any other HTML, so it is safe to attach events there without waiting for the document to be ready.
One option is to listen on the click event using a delegate, like so:
$(document).on('click', '.ajax-close', function( event ){
//your code
});
Another option might be to move your click listener inside the original click listener, which creates the "Close" button, while the reason the issue arises is that the click event on "ajax-close" is bound too soon (before the <span> is appended to the DOM even):
ajaxcontent.click(function(event) {
event.preventDefault();
$( '.ajax-live' ).addClass('ajax-live-on');
$( this ).after('<span class="ajax-close animated bounceInRight">Close</span>');
$('.ajaxshow').append().load(ajaxUrl);
$('.ajaxshow').addClass('animated bounceInUp');
// Move this section here, which was previously located below
$('.ajax-close').click(function( event ){
event.preventDefault();
alert('hi');
$( '.ajax-live' ).removeClass('ajax-live-on');
});
});
Make sure to include some content in your "ajax-close" span to be able to click it like the word "Close".
Add JQuery library to your HTML head :
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
In your given link you are adding element dynamically, so need to use event delegate for dynamically created elements event binding.
$(document).on('click', '.ajax-close', function( event ){
//your code
});

trigger event globally in jquery

I am binding a custom event on div. I want to trigger that event globally without specifying target element.
edit:
Right now I am binding my custom event with div but it can be bind with any of tag. So instead of trigger event with selector. I want to trigger it globally.
I want to avoid repetition like
$('p').trigger('customevent')
$('div').trigger('customevent')
var g= document.getElementsByTagName('div')
$('div').bind('alwaysListen',function(){
$(this).hide()
});
$('a').click(function(){
$.event.trigger('alwaysListen');
});
Here's the fiddle.
Event will be bubbling across DOM nodes up and down anyway, so in some way it;s anyway global;
That's why you can do :
$(document).on('alwaysListen', function(){
//do stuff
});
Here is a link to you updated jsfiddle: https://jsfiddle.net/fa1s9e0s/7/

Click event doesn't fire on element

I am building a Windows 8.1 Store application with WinJS. When the user queries some search results show up in a <p class="searchresults">content</p> tag.
I'd like to add an event handler to the .searchresults class. I've done the following:
$('.searchresults').on('click', function() {
console.log("clicked");
});
I've tried even without .on()
$('.searchresults').click(function() {
console.log("clicked");
});
However the event never gets fired. I've set up a breakpoint, so I can see when it fires - but that never happens
I've tried to add an event handler via the WinJS way:
Microsoft.Maps.Events.addHandler(document.getElementsByClassName("searchresults"), 'click', myfunc);
Without success.
Any ideas why this is happening?
I will guess that you are creating the <p class="searchresults">content</p> object AFTER you try to install the event handler (a common problem with dynamic content). That will not work with normal event handling because the DOM object does not exist when you try to add the event handler to it.
If this is the case, then you need to use delegated event handling like this:
$(document.body).on('click', '.searchresults', function() {
console.log("clicked");
});
This will allow you to dynamically create the searchresults content at any time and the event handler will still fire via event delegation (events propagate up to their parents).
You haven't shown the HTML around the search results content, but the most optimal way to do this is to select the closest static parent to the search results (a parent that is not dynamically created and already exists at the time you attach the event handler) and attach the event to that:
$(closest static parent selector).on('click', '.searchresults', function() {
console.log("clicked");
});

How do I unbind events properly when using allowSamePageTransition in jQuery Mobile?

I'm using the jQuery Mobile option allowSamePageTransition, which enables me to go from
page A > page A > page A ...
I need this to allow browsing through a catalogue of items. My problem is, the items need some form of interaction and I used to attach the interaction binding to document, because it is set before the elements affected are generated.
However, reloading the same page over and over again will re-bind my event handlers every time I reload.
My first idea was to use .off when the page is being hidden, but reloading a page #foo, will trigger pagehide on the same page being shown, so all bindings set on
$(document).on("pagebeforeshow.foo_events", "#foo", function(e) {
// bind when shown
});
will be unbound again by the previous #foo being hidden
$(document).on("pagehide", "#foo", function (e) {
$(this).off(".foo_events");
// removes bindings on #foo being hidden AND shown
});
The only solution I have come up with is plastering the document with classes, which I don't like doing:
priv.setBindings = function (param) {
var doc = $(document);
doc
.filter(function() { return $(this).is(".e_gallery") !== true; })
.on("pagebeforeshow.gallery", param.pageId, function (e) {
doc.addClass(".e_gallery");
// run stuff
});
};
But I'm no fan of attaching classes to the dom.
Question:
Is there a way to prevent multiple event bindings set on $(document) when going to the same page over and over again WITHOUT toggling classes?
Solution 1
Best solution would be to use pageinit to bind events. If you take a look at an official documentation you will find out that pageinit will trigger ONLY once, just like document ready, so there's no way events will be bound again. This is best solution because you don't have processing overhead like when removing events with off method.
Working jsFiddle example: http://jsfiddle.net/Gajotres/AAFH8/
Of course this will fail in case multiple HTML solution is used.
Solution 2
Remove event before you bind it:
$(document).on('pagebeforeshow', '#index', function(){
$(document).off('click', '#test-button').on('click', '#test-button',function(e) {
alert('Button click');
});
});
Working jsFiddle example: http://jsfiddle.net/Gajotres/K8YmG/
Solution 3
Use a jQuery Filter selector, like this:
$('#carousel div:Event(!click)').each(function(){
//If click is not bind to #carousel div do something
});
Because event filter is not a part of official jQuery framework it can be found here: http://www.codenothing.com/archives/2009/event-filter/
This is probably best solution because event is going to be bound ONLY once.
Solution 4
Probably an easiest of them all.
$(document).on('pagebeforeshow', '#index', function(){
$(document).on('click', '#test-button',function(e) {
if(e.handled !== true) // This will prevent event triggering more then once
{
alert('Clicked');
e.handled = true;
}
});
});
Working jsFiddle example: http://jsfiddle.net/Gajotres/Yerv9/
This is a 180 percent different solution then solution 3, in this case event is going to be bound numerous times but it will be allowed to execute only once.
More info
If you want to find more about this problem take a look at this article, working examples are included.

Categories