Solved

Javascript not loading in partial postback

Posted on 2014-04-17
9
889 Views
Last Modified: 2014-04-22
Hi all,

I have an aspx page with an update panel which i am loading usercontrols dynamically.
The JQuery file is added in the masterpage of the aspx file header;

<script type="text/javascript" src="http://code.jquery.com/jquery.js"></script>

Open in new window


Each usercontrol also has a specific set of js files. I load the js (one example) as follows (note LoadJS() is called in the UserControl pageload event);

    private void LoadJS()
    {
        //load the .js files
        ClientScriptManager cs = Page.ClientScript;
        Type cstype = this.GetType();

//added to try and resolve the issue
        if (!cs.IsClientScriptIncludeRegistered(cstype, "JqueryJS"))
            cs.RegisterClientScriptInclude(cstype, "JqueryJS", ResolveClientUrl("http://code.jquery.com/jquery.js"));

        if (!cs.IsClientScriptBlockRegistered(cstype, "loginClientID"))
        {
            string clientid = "";
            clientid += String.Format("var jutb = '#{0}';", myLogin.FindControl("UserName").ClientID);
            clientid += String.Format("var jptb = '#{0}';", myLogin.FindControl("Password").ClientID);

            cs.RegisterClientScriptBlock(cstype, "loginClientID", clientid, true);

        }

        if (!cs.IsClientScriptIncludeRegistered(cstype, "WatermarkJS"))
            cs.RegisterClientScriptInclude(cstype, "WatermarkJS", ResolveClientUrl("~/js/jquery.watermark.min.js"));

        if (!cs.IsClientScriptIncludeRegistered(cstype, "LoginJS"))
            cs.RegisterClientScriptInclude(cstype, "LoginJS", ResolveClientUrl("~/js/login.js"));
    }

Open in new window


now in my login.js I have (shortened to suit) the following code;

function pageLoad(){
    //alert('partial handler');

    $(jutb).watermark('Username or Email address');
    $(jptb).watermark('Password');

    Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(InitializeRequest);
    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
}


// Called when async postback begins
function InitializeRequest(sender, args) {
    // alert("You are in the InitializeRequestHandler function.");  // breakpoint here


}

// Called when async postback ends
function EndRequestHandler(sender, args) {
    // this function is run after an Ajax partial postback occurs

    //alert("You are in the EndRequestHandler function.");    // breakpoint here
 //   $(jutb).val("0test");
 //   alert(jutb);
 //   alert($(jutb).val());
//$(jutb).watermark('Username or Email address');
 //   $(jptb).watermark('Password');
 //   alert('afterwatermark');

    loadUsername();
    loadPassword();

    if (args.get_error() != undefined)
        alert("There was an error" + args.get_error().message);

    return;
}

Open in new window


now just to clarify. alert('partial handler'); IS firing when I load the next usercontrol.

Also, jutb is being assigned the .clientID as the alert in the end_request is showing this.

Finally, I have a validate() js method attached to a linkbutton. When I alert out  $(jutb).val() I am getting 'undefined' returned. I assume this means that JQuery is not being readded to the project?

function validate() {
   
    if (usernameValid && passwordValid)
        return true;
    else {
 
 if (!usernameValid) {
     alert('validating  :' + $(jutb).val() + ":");
     highlightField($(jutb), false);
            highlightFieldMessage($(jutb), false, "Enter your username or email.");

        }

        if (!passwordValid) {
            highlightField($(jptb), false);
            highlightFieldMessage($(jptb), false, "Enter your password.");
        }

        return false;
    }
}

Open in new window


Also to mention I had the .watermark code inside the end_request method, but this then meant that the fields were not watermarked at all. Moving into the pageLoad method fired and watermarked the fields, but only when loading the page (not a partial postback).

In conclusion does anyone have any ideas on whats going on here? It seems that the JQuery files (and maybe watermark too??) are not been loaded?
0
Comment
Question by:flynny
  • 5
  • 4
9 Comments
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 40006589
where is jutb defined?

It sounds like the partial load is not rebinding the JQuery event handlers - if you are downloading controls as part of your AJAX request you have to either

a) Rebind the event handlers after downloading the new content

OR

b) When you initially bind the event handlers use the .on() for dynamic binding.
0
 

Author Comment

by:flynny
ID: 40006637
Hi Julian,

many thanks for the reply.

jutb is bound in the .cs and is basically just the .clientID

string clientid = "";
            clientid += String.Format("var jutb = '#{0}';", myLogin.FindControl("UserName").ClientID);
            clientid += String.Format("var jptb = '#{0}';", myLogin.FindControl("Password").ClientID);

Open in new window


the issue is strange because it appear JQuery itself is not loading? (i.e. a .val() comes back undefined?).

i've created a test link here (I have only tested in firefox);

http://dev3.mfitonline.co.uk/Login.aspx

here login.aspx loads the login.ascx file.

as you can see the .watermark works. if you click the 'login' button you will see the alerts fire with the jutb values.

Now if you then click the 'forgotten password/username' link this will load another .ascx file (the js for this are not loaded either but I think it is part of the same issue).

If you then click the red cross to close this popup (and reload login.ascx) you will see that the js is not working.

If at this point you then click the 'login' button you can see that 'undefined' is returned for the .val() method.

Now I have also notice that if you click the 'forgotten password' link again just once, it reloads the js and the watermark appears???

It seems then that a second click is required to load the usercontrol popup? any ideas why this is happening?
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 40006706
the issue is strange because it appear JQuery itself is not loading? (i.e. a .val() comes back undefined?).
You will get undefined if the element attached to the .val() does not exist. The acid test is do you get
 
undefined

in the console OR
$.val() is not a function

If the former - then JQuery is loading - it is the element that is not defined. If JQuery is not loading you will get the latter.

What appears to be happening is when you regenerate the login page (not sure why you are doing that rather than just hidding the popup), however, the controls are comming back with different id's

When the page loads the username has an id of
#ctl00_ContentPlaceHolder1_ctl01_myLogin_UserName
When you close the popup it has an id of
#ctl00_ContentPlaceHolder1_ctl02_myLogin_UserName

That is why you are getting the undefined.

To solve this problem you need to look at why your callback is generating a different ID.

Also, consider managing the popup client side instead of posting back to restore the login when you close the popup. The popup should just be an overlay over your existing page. By removing it the original page should be restored.

Nice balloons by the way :)
0
 

Author Comment

by:flynny
ID: 40006794
Thanks Julian,

I read your article following on from the question I posed and it give a nice effect doesn't it :). I've been tinkering with a little random movement on the x axis as well but thats another story.

1. Not sure if i've done it right but i've added $(jutb).val() to the watch var window in firebug and this becomes 'undefined'. So it does appear that jquery is loading.

2. The LoadJS is called regardless of postback from the pageload event of the acsx control, but I would have thought that the name stay the same? From looking at breakpoints the cs.RegisterClientScriptBlock(cstype, "loginClientID", clientid, true); is firing so this should overwrite with the new id? could the id be being changed after this call?
private void LoadJS()
    {
        //load the .js files
        ClientScriptManager cs = Page.ClientScript;
        Type cstype = this.GetType();

        if (!cs.IsClientScriptIncludeRegistered(cstype, "JqueryJS"))
            cs.RegisterClientScriptInclude(cstype, "JqueryJS", "http://code.jquery.com/jquery.js");

       // if (!cs.IsClientScriptBlockRegistered(cstype, "loginClientID"))
       // {
            string clientid = "";
            clientid += String.Format("var jutb = '#{0}';", myLogin.FindControl("UserName").ClientID);
            clientid += String.Format("var jptb = '#{0}';", myLogin.FindControl("Password").ClientID);

            cs.RegisterClientScriptBlock(cstype, "loginClientID", clientid, true);

       // }
        if (!cs.IsClientScriptIncludeRegistered(cstype, "WatermarkJS"))
            cs.RegisterClientScriptInclude(cstype, "WatermarkJS", ResolveClientUrl("~/js/jquery.watermark.min.js"));

        if (!cs.IsClientScriptIncludeRegistered(cstype, "LoginJS"))
            cs.RegisterClientScriptInclude(cstype, "LoginJS", ResolveClientUrl("~/js/login.js"));
    }

Open in new window


2. Any ideas on the 2 clicks issue? As the click seems ot revert the id back to the original id?

Finally, I do agree with calling the popup clientside. Its more a proof of concept that I can use this methodology later in the site. As I'll have a number of wizard style forms broken down into usercontrols, each utilising javascript and jquery on the fly.
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 51

Accepted Solution

by:
Julian Hansen earned 500 total points
ID: 40006867
JQuery is definitely loading - it loads with the initial page load - and will remain there for the lifetime of the page.

is firing so this should overwrite with the new id? could the id be being changed after this call?

The problem is definitely related to the id's in the controls changing.

The double click to close - I noticed that - have not had a chance to debug that one yet - was focusing on the undefined issue.

I am not really a big fan of the Microsoft model of building pages - I agree it makes it easier from a developer perspecitve to do certain things but sometimes I find the methodology to be counter productive to what I would intuitively like my clientside code to do.

Having said that we have two potential avenues to pursue.

1. Find out why the id's are being recreated with different values.
2. Move to a client side popup.

On 1 - I noticed once you have done the popup once it does not change the id for successive popups - will look at it more and get back to you if I find anything.
0
 

Author Comment

by:flynny
ID: 40007242
OK,

I had a look at the reason for the second click as I was thinking it may be causing the control naming issues.

The first time a button inside the user control is clicked the following happens;

1. the page_load of the login.aspx.cs is called.
2.which invokes the reload of the usercontrol.
3.as the button click has not fired the control being loaded is the existing control.
4.the user control page_load is fired

the same happens as above but on the second click the button click method is fired at the end??
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 40010186
Sounds like one of the vagaries in Microsoft's way of doing things that is responsible. Without seeing full code difficult to diagnose.
0
 

Author Comment

by:flynny
ID: 40014304
Hi Julian,

just for info I have managed to solve the issue with jscript loading.

        using (ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page))
        {
         scriptManager.RegisterPostBackControl(ForgotDetails);
        }

Open in new window


However it still doesn't solve the two click being required to launch the button. I have tried numerous things including triggering the button click from jscript to see if it perfomed a full postback that way.

I'll mark this as answered and open a serperate question for this issue.

Thanks for all your time and effort on this. Its appreciated.
0
 
LVL 51

Expert Comment

by:Julian Hansen
ID: 40014397
You are welcome - thanks for the points.
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

OverviewThis article demonstrates a simple search form using AJAX. The purpose of the article is to demonstrate how to use the same code to render a page and javascript (JQuery) and AJAX to make subsequent calls to refine the results. The princip…
Introduction A frequently asked question goes something like this:  "I am running a long process in the background and I want to alert my client when the process finishes.  How can I send a message to the browser?"  Unfortunately, the short answer …
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now