0

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

Jacob
  • 77,566
  • 24
  • 149
  • 228
Nick Rolando
  • 25,879
  • 13
  • 79
  • 119
  • 1
    When you say "postback," are you, by chance, using an `UpdatePanel`? – Jacob May 03 '12 at 18:03
  • Yes, I am using an UpdatePanel <_<; – Nick Rolando May 03 '12 at 18:04
  • Brendan has a good answer. But to explain why the code doesn't run after a partial page postback, it's because you're running the code in the document ready event, which means it will only run once, after the document is ready for the first time. Doing a postback in an `UpdatePanel` (which is an AJAX request) will not re-trigger that event. – Jacob May 03 '12 at 18:10
  • Even with Brendan's answer, would it still not work because I'm using an updatepanel? – Nick Rolando May 03 '12 at 18:29
  • `live` should work, or `on` if you use the current jQuery recommendation. If it's not working correctly, then maybe you're setting up the event handler incorrectly. – Jacob May 03 '12 at 18:35

3 Answers3

4

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/

Esailija
  • 138,174
  • 23
  • 272
  • 326
  • Thank you sir. What is the difference between attaching to parent node and using a selector argument vs attaching to the node directly? I don't get it. I see that the former retains the event binding after a postback, but why doesn't the latter? – Nick Rolando May 03 '12 at 18:49
  • @Shredder whenever an element gets an event (that is a bubbling event), that event also bubbles to the element's parents. For example, when you think about it, when you click an element, you are clicking all of its parents as well. If you attach an event to a node directly, and that node is removed, you will also lose all the events you attached to that node. So we use the principle above to bind the events to a more persistent node that is not removed during the course of a page lifetime. – Esailija May 03 '12 at 18:53
  • You can get more information by googling javascript event delegation and/or reading http://unitstep.net/blog/2009/02/19/javascript-event-delegation/ – Esailija May 03 '12 at 18:57
  • Hey Esailija, if you have the time, just out of curiosity, how *would* I go about attaching the events "again and again"? j/w because before I asked the question, that's what I tried doing by taking it out of the document ready function and placing the js at the end of the form, think it would reload, but it didn't. – Nick Rolando May 03 '12 at 20:45
  • @Shredder I know nothing about `ASP.NET` which is responsible for removing the elements. You would need to reattach the events after the elements are recreated - to do this you will need to hook into the `UpdatePanel` stuff and take it from there. The document ready event fires only once at the start of a new page load. Making an ajax request (that's what `UpdatePanel` does it seems) doesn't load a new page, which is kinda the point of ajax. – Esailija May 03 '12 at 21:17
0

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.

Community
  • 1
  • 1
Brendan
  • 3,415
  • 24
  • 26
  • Using an UpdatePanel, your changing the DOM without reloading the page and hooking up the events. Use the "live" method to wire up the dynamically change DOM elements. – Zachary May 03 '12 at 18:07
  • The live method is being deprecated. Use `$(document).on( "EVENT", "selector", function(){})` for equivalent behavior, though one probably wants the closest common parent. – Esailija May 03 '12 at 18:08
  • If you're using the latest jQuery, you should use `.on()` instead, `.live()` has been deprecated. – Erik Funkenbusch May 03 '12 at 18:08
  • @Brendan no this is not even close to what `.live` used to do now. It doesn't even use event delegation. – Esailija May 03 '12 at 18:10
  • I am saying they don't. `live` is event delegation to `document` node, this is simply normal even binding directly to the element. – Esailija May 03 '12 at 18:14
  • Can you please elaborate? Let's say I have some `
    ` elements of a class, some are created on load, some are brought in via AJAX calls, if i use `$('div.myclass').live('click', function () { alert('hello'); });` OR `$('div.myclass').on('click', function () { alert('hello'); });` .. what will be the functional difference? I am not trying to troll or anything here, I am curious.
    – Brendan May 03 '12 at 18:16
  • `$('div.myclass').on('click', function () { alert('hello'); });` finds all `div.myclass` **currently** in the document, and binds the event directly to them. If more `div.myclass` are added to the document later, you will need to add it again. Where as with `live` everything is delegated to `document`. The equivalent of `live` with `on` is `$(document).on( "EVENT", "selector", function(){})`, as I said in the beginning. – Esailija May 03 '12 at 18:19
  • Your explanation of event delegation is also wrong, jQuery doesn't automatically re-hookup any handlers, they were never hooked up to the elements in the first place. They are hooked up to a higher level node (in the case of `live`, it's the `document` node ), and that higher level node catches events on all of its children, which are then checked for match with `"selector"`. – Esailija May 03 '12 at 18:29
  • Thanks Brendan, it is not working for me though. My code is: `$(function(){ $('input[class="userTxtA_center"]').on('focus', function() { if(this.getAttribute('class') == 'userTxtA_center') { this.value = ''; this.setAttribute('class', 'userTxtB_center'); } }); });` -in the head tag. Note also the postbacks are in updatepanel (not sure if that changes things) – Nick Rolando May 03 '12 at 18:30
  • @Shredder, either use .live() (in place of .on()) or see the alternative I posted. – Brendan May 03 '12 at 18:33
  • @Brendan The point is just that you have to move the selector between direct binding and delegated binding. Rather than `$(selector).on(event, callback);`, it should be `$(anchor).on(event, selector, callback);` for delegation, where the `anchor` is a constant or at least longer-living ancestor of the elements you're binding to. `.live()` uses the latter with the `document` as the `anchor`. – Jonathan Lonowski May 03 '12 at 18:39
  • @Brendan Oh it was because I was using jquery 1.6. I just updated my jquery. thx – Nick Rolando May 03 '12 at 18:47
-1

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>
ahaliav fox
  • 2,217
  • 22
  • 21