Question

Unfortunately, I cannot reproduce this problem outside my application. I have a VS2012 project I can send anybody who's willing to take a look. It works for me in isolation but not in a larger app.

My objective is to have a common overlay control in the master page that pages can bubble display events during partial postbacks.

Here's what I have:

  • A user control that displays a message box in an overlay
  • A javascript file that gets the PageRequestManager object and adds a pageLoaded event
    • The event handler checks the value of a hidden control and uses jquery to show/hide the message
  • A master page with a scriptmanager and the user control wrapped in an updatepanel
  • A class containing a shared event to alert the master page that a message needs to be displayed
  • A page with an updatepanel containing a div, a button and a textbox
  • A css file

What happens in the test app:

  • text is entered in the box and the button clicked
  • the button click event
    • copies the text to the div in the updatepanel
    • calls the DisplayMessage method in the custom class to alert the master page
  • DisplayMessage instantiates and populates the custom event args and raises the event
  • the handler in the master page sets the properties of the usercontrol and calls Update on its UpdatePanel
  • the page displays the overlay and trigger pageLoaded [1]
  • the javascript function evaluates the Value property of the hidden control and displays the message.
  • the user clicks the OK button
  • the click handler (server side) sets the hidden value and triggers an update on the usercontrol's updatepanel
  • the message disappears

What happens "in real life":

  • at point [1], the javascript fails with $ is not defined

The chrome console allows me to input jQuery and displays elements ok.

There are no jq plugins involved, the scriptmanager is at the top of the form in the master. The jquery reference is in the of the master pointing to google with no "http/https".

I have tried adding the external script in a ScriptManagerProxy but to no avail. As it is, the test app works fine with the

<script src="blahblah.js"></script> 

at the bottom of the user control markup.

Any help you can offer would be very much appreciated.

Cheers, .pd.

EDIT:

Script references as requested:

This is the Master page:

<head runat="server">
<title>Untitled Page</title>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script type="text/javascript" src="/scripts/tabindex.js"></script>

<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body style="background-color: #cccccc;">
<form id="form1" runat="server">
    <asp:ToolkitScriptManager runat="Server" EnablePartialRendering="true" ID="ScriptMan1" EnablePageMethods="true">
    </asp:ToolkitScriptManager>

     <asp:UpdatePanel ID="updPopupMsg" runat="server" UpdateMode="Conditional">
        <ContentTemplate>
            <amis:PopupMsg ID="popMaster" runat="server" Hidden="true" />
        </ContentTemplate>
    </asp:UpdatePanel>   
</form>

And this is the UserControl markup:

<div id="divOverlay" runat="server" class="helpbox-overlay"></div>
<div id="divMessage" runat="server" class="helpbox">
<asp:HiddenField ID="hdnHidden" runat="server" Value="True" />
<asp:Panel ID="pnlHelpBox" CssClass="helpbox-popup" runat="server">
    <h1>
        <asp:Label ID="lblTitle" runat="server"></asp:Label></h1>
    <p>
        <asp:Label ID="lblMsg" runat="server"></asp:Label>
    </p>
    <p>&nbsp;</p>
    <p align="center">
        <asp:Button ID="btnClose" CausesValidation="false" Text="Close" runat="server"/>
    </p>
</asp:Panel>
</div>

<script type="text/javascript" src="/scripts/popup-msg.js"></script>

The code in that javascript file looks like this:

var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(popup_msg_init);

function popup_msg_init() {
    if ($('input[id*="hdnHidden"]').attr('value') == 'True')
        popup_msg_hide();
    else
        popup_msg_show();
}

function popup_msg_show() {
    $('div[id*="divOverlay"]').show();
    $('div[id*="divMessage"]').show();
}

function popup_msg_hide() {
    $('div[id*="divOverlay"]').hide();
    $('div[id*="divMessage"]').hide();
}

EDIT:

Hey - is it possible the scripts are being loaded asynchronously? Are there any tools I can use to verify what is happening when? I ask because I changed the javascript to the following:

var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(popup_msg_init);

function popup_msg_init() {
    var inputs = document.getElementsByTagName('input');
    for (var i = 0; i < inputs.length; i++) {
        var input = inputs[i];
        if (input.id.indexOf('hdnHidden') > 0) {
            if (input.value == 'True')
                popup_msg_hide();
            else
                popup_msg_show();
        }
    }
}

function popup_msg_show() {
    $('div[id*="divOverlay"]').show();
    $('div[id*="divMessage"]').show();
}       

function popup_msg_hide() {
    $('div[id*="divOverlay"]').hide();
    $('div[id*="divMessage"]').hide();
} 

And now it all works. So my theory is that pageLoaded is calling my popup_msg_init function on a different thread that can't see jquery and the delay caused by searching the dom manually gives it enough time to load cuz by the time the show/hide functions are called, everything's groovy.

So I thought I'd check that by sticking a timeout on there:

setTimeout(function () {
    if ($('input[id*="hdnHidden"]').attr('value') == 'True')
        popup_msg_hide();
    else
        popup_msg_show();
}, 5000);

But it goes back to "$ is undefined."

Any comment on that?

Was it helpful?

Solution 2

There were errors in other javascripts being included. Not syntactic error but because of how ASP.NET was inserting them into the page, they were getting ahead of the Sys definition. So I changed all my user controls with associated javascript to follow this pattern:

-1- Use a Javascript helper class to add the script reference to the page. (I'd use bullets here but the code formatter doesn't work in bulleted lists - headsup stackoverflow devs)

Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.HtmlControls

Public Class JSHelper
    Public Shared Sub Add(path As String, page As Page)
        Dim jsFile As New HtmlGenericControl("script")
        jsFile.Attributes.Add("type", "text/javascript")
        jsFile.Attributes.Add("language", "javascript")
        jsFile.Attributes.Add("src", page.ResolveUrl(path))
        page.Header.Controls.Add(jsFile)
    End Sub
End Class

-2- Add the script

JSHelper.Add("/scripts/myscript.js", Me.Page)

-3- Run the setup function in the control markup depending on what's there

<script type="text/javascript" lang="javascript">
    if (typeof (Sys) === 'undefined')
        $(function () { 
            init(); });
    else {
        if (typeof (Sys.WebForms) === 'undefined')
            alert('Sys.WebForms not defined!');
        else {
            Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(init);
        }
    }
</script>

OTHER TIPS

The chrome console allows me to input jQuery and displays elements ok.

Because by the time you're entering that code, jQuery is loaded. But this error:

$ is not defined

indicates that at the time some other code runs, jQuery is not loaded.

Note that JavaScript code is processed in the order in which it's loaded into the page. So the jQuery library needs to be loaded before any code which uses it. (That is, the engine isn't smart enough to load all of the code and then link the references to each other like a compiled language.)

While you provide a lot of information in your question, the one thing you don't provide is the script references in your HTML. As an example, though, consider the following which is incorrect:

<script type="text/javascript" src="someScriptThatUsesjQuery.js"></script>
<script type="text/javascript" src="jQuery.js"></script>

versus the following which is correct:

<script type="text/javascript" src="jQuery.js"></script>
<script type="text/javascript" src="someScriptThatUsesjQuery.js"></script>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top