I am using ASP.NET 3.5 combined with the atrocious UpdatePanel, jQuery.delegate()
, and JavaScript object literals.
I use jQuery.delegate()
to persist the event handlers, which do get triggered after the PostBack, as expected.
The issue is with the jQuery objects stored in object literal properties on init()
where they keep the values they had prior to the ASP.NET PostBack.
Here is my JavaScript :
SFAIC
SFAIC =
{
masterPages: { cs: "CS_", cp: "CP_" },
contentPages: { cs: "CSContent_", cp: "CPContent_" },
isSecurePage : false,
$body : undefined,
$container : undefined,
$updatePanel : undefined,
$textBox : undefined,
$errorLabel : undefined
};
SFAIC.init()
SFAIC.init = function ()
{
log( "--> SFAIC.init() fired" );
var self = this;
self.$body = $( "body" );
self.$container = self.$body.find( "#container" );
self.$updatePanel = self.getCSMasterElement( "UpdatePanel1", self.$container );
self.$textBox = self.getContentElement( "TextBox1" );
self.$errorLabel = self.getContentElement( "ErrorLabel1" );
self.$updatePanel.delegate( self.$textBox.selector, "blur", function ()
{
self.validateRequired( self.$textBox, self.$errorLabel );
});
self.$textBox.focus();
};
SFAIC.validateRequired()
SFAIC.validateRequired = function ( $element, $errorLabel )
{
if ( $element.val().length === 0 ) { $errorLabel.text( "Required" ); }
else { $errorLabel.text( "" ); }
};
Given the above, when SFAIC.init()
is fired, self.textBox
is assigned to its jQuery object. I guess herein lies my confusion. I thought that when you call .val()
, it would return the value of what's in that element right then. In the case where you make a call to the server and change the value of the control which then comes back rendering the changed value of the element, it seems that the jQuery object doesn't know about that change?
Am I wrong here?
What do I need to do to keep a real-time reference to the element, so that I can get the current value after the page is posted back?
Edit request per @DaveLong :
SFAIC.getCSMasterElement()
SFAIC.getCSMasterElement = function ( id, $context )
{
return SFAIC.getElement( SFAIC.masterPages.cs, id, $context );
};
SFAIC.getCPMasterElement()
SFAIC.getCPMasterElement = function ( id, $context )
{
return SFAIC.getElement( SFAIC.masterPages.cp, id, $context );
};
SFAIC.getContentElement()
SFAIC.getContentElement = function ( id, $context )
{
return SFAIC.getElement
(
( SFAIC.isSecurePage )开发者_运维问答 ? SFAIC.contentPages.cp : SFAIC.contentPages.cs,
id,
$context
);
};
SFAIC.getElement()
SFAIC.getElement = function ( page, id, $context )
{
selector = SFAIC.getElementIdSelector( page, id );
return ( selector )
? ( $context && $context.length )
? $context.find( selector )
: SFAIC.$body.find( selector )
: undefined;
};
SFAIC.getElementIdSelector()
SFAIC.getElementIdSelector = function ( page, id )
{
var prefix = SFAIC.getElementPrefix( page );
return ( prefix && id ) ? "#" + prefix + id : undefined;
};
SFAIC.getElementPrefix()
SFAIC.getElementPrefix = function ( page )
{
switch ( page )
{
case SFAIC.masterPages.cs : return SFAIC.masterPages.cs;
case SFAIC.masterPages.cp : return SFAIC.masterPages.cp + SFAIC.masterPages.cs;
case SFAIC.contentPages.cs : return SFAIC.masterPages.cs + SFAIC.contentPages.cs;
case SFAIC.contentPages.cp : return SFAIC.masterPages.cp + SFAIC.masterPages.cs + SFAIC.contentPages.cs + SFAIC.contentPages.cp;
}
};
The UpdatePanel removes the entire target from the DOM and replaces it with new markup from the response. It isn't that your vars are holding old values, it is that they are holding references to the original markup. You need to "reinitialize" in order to obtain references to the new nodes in the DOM.
maybe you should re-init the objects when the ajax updatepanel request completes
<script type="text/javascript" language="javascript">
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(ReInitiate);
function ReInitiate(sender, args)
{
//re-initialize the objects
//add code here
}
</script>
Cheers, Nitin
For what it's worth, the solution I came up with was a customized version of Paul Irish's Markup-based unobtrusive comprehensive DOM-ready execution and @NitinJS' / @Ethan's answers.
At the bottom of my JavaScript I added:
UTIL = {
fire : function(func, funcname) {
var namespace = SFAIC;
funcname = (funcname === undefined) ? "init" : funcname;
if (func !== "" &&
namespace[func] &&
typeof namespace[func][funcname] == "function") {
namespace[func][funcname]();
}
},
loadEvents : function() {
var bodyId = document.body.id;
UTIL.fire("common");
UTIL.fire(bodyId);
}
};
// Fire events on initial page load.
UTIL.loadEvents();
// Fire events for partial postbacks.
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(UTIL.loadEvents);
In my MasterPage's aspx, I modified the body tag to:
<body id="<%=bodyId%>">
In my MasterPage's code-behind declarations, I added:
Public bodyId As String = String.Empty
In my MasterPage's code-behind Page.PreRender handler, I added:
bodyId = MyBase.GetType.BaseType.Name
精彩评论