简体   繁体   English

$未定义[jQuery,MasterPage,UserControl,共享/静态事件处理程序,外部javascript]

[英]$ is not defined [jQuery,MasterPage,UserControl,Shared/static Event handler,external javascript]

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. 我有一个VS2012项目,可以将任何愿意看的人发送给我。 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 一个获取PageRequestManager对象并添加pageLoaded事件的javascript文件
    • The event handler checks the value of a hidden control and uses jquery to show/hide the message 事件处理程序检查隐藏控件的值,并使用jquery显示/隐藏消息
  • A master page with a scriptmanager and the user control wrapped in an updatepanel 包含脚本管理器和包含在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 带有带有div,按钮和文本框的updatepanel的页面
  • A css file 一个css文件

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 将文本复制到updatepanel中的div
    • calls the DisplayMessage method in the custom class to alert the master page 调用自定义类中的DisplayMessage方法以警告母版页
  • DisplayMessage instantiates and populates the custom event args and raises the event DisplayMessage实例化并填充自定义事件args并引发事件
  • the handler in the master page sets the properties of the usercontrol and calls Update on its UpdatePanel 母版页中的处理程序设置用户控件的属性,并在其UpdatePanel上调用Update
  • the page displays the overlay and trigger pageLoaded [1] 该页面显示叠加层和触发页面Loaded [1]
  • the javascript function evaluates the Value property of the hidden control and displays the message. javascript函数评估隐藏控件的Value属性并显示消息。
  • the user clicks the OK button 用户单击确定按钮
  • the click handler (server side) sets the hidden value and triggers an update on the usercontrol's updatepanel 单击处理程序(服务器端)设置隐藏值并触发用户控件的updatepanel上的更新
  • the message disappears 消息消失

What happens "in real life": 在“现实生活中”会发生什么:

  • at point [1], the javascript fails with $ is not defined 在[1]点,未定义$的javascript失败

The chrome console allows me to input jQuery and displays elements ok. chrome控制台允许我输入jQuery并显示确定。

There are no jq plugins involved, the scriptmanager is at the top of the form in the master. 没有涉及jq插件,脚本管理器位于主控窗体的顶部。 The jquery reference is in the of the master pointing to google with no "http/https". jQuery参考位于指向Google的主站点中,没有“ http / https”。

I have tried adding the external script in a ScriptManagerProxy but to no avail. 我曾尝试在ScriptManagerProxy中添加外部脚本,但无济于事。 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. 干杯,.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: 这是UserControl标记:

<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: 该javascript文件中的代码如下所示:

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: 我问是因为我将javascript更改为以下内容:

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. 所以我的理论是pageLoaded在另一个看不到jquery的线程上调用我的popup_msg_init函数,手动搜索dom导致的延迟使它有足够的时间在调用show / hide函数时加载cuz,这一切都是很麻烦的。

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? 对此有何评论?

The chrome console allows me to input jQuery and displays elements ok. chrome控制台允许我输入jQuery并显示确定。

Because by the time you're entering that code, jQuery is loaded. 因为在您输入该代码时,jQuery已加载。 But this error: 但是这个错误:

$ is not defined $未定义

indicates that at the time some other code runs, jQuery is not loaded. 表示在运行其他代码时, 尚未加载jQuery。

Note that JavaScript code is processed in the order in which it's loaded into the page. 请注意,JavaScript代码是按照加载到页面中的顺序进行处理的。 So the jQuery library needs to be loaded before any code which uses it. 因此,需要在使用它的任何代码之前加载jQuery库。 (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. 尽管您在问题中提供了很多信息,但您没有提供的一件事就是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>

There were errors in other javascripts being included. 其他JavaScript出现错误。 Not syntactic error but because of how ASP.NET was inserting them into the page, they were getting ahead of the Sys definition. 不是语法错误,而是因为ASP.NET将它们插入页面的方式,所以它们领先于Sys定义。 So I changed all my user controls with associated javascript to follow this pattern: 因此,我用关联的javascript更改了所有用户控件,以遵循以下模式:

-1- Use a Javascript helper class to add the script reference to the page. -1-使用Java语言帮助器类将脚本引用添加到页面。 (I'd use bullets here but the code formatter doesn't work in bulleted lists - headsup stackoverflow devs) (我在这里使用项目符号,但是代码格式化程序在项目符号列表中不起作用-headsup stackoverflow开发人员)

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 -2-添加脚本

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

-3- Run the setup function in the control markup depending on what's there -3-根据存在的内容在控制标记中运行设置功能

<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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM