代码之家  ›  专栏  ›  技术社区  ›  Jeff

jquery datepicker绑定控件不能包含在其他控件中

  •  1
  • Jeff  · 技术社区  · 16 年前

    我的任务是为我们的Web项目的几个区域实现一个日期/时间选择器,并指示使用另一个开发人员创建的控件作为它的一部分。我正在处理的控件应该允许用户从日历中选择一个日期,为该日期的显示选择一种格式(从几个预先定义的格式,或使用简单的文本覆盖),以及可选的时间字符串(实际上只是自由格式的文本)。

    我被指示使用的控制记录如下: http://www.west-wind.com/WebLog/posts/213015.aspx ,并使用jquery中的日期选择器。

    在我实现了我的控制并测试了它之后,我开始将它集成到需要日期和/或时间输入的页面中。在对这些实现的测试中,我发现了一个错误:当我在一个页面上包含多个控件副本时,只有第一个副本获得jquery日历。其他人都不受约束。

    我尝试过一个看似相关的问题(标题为“复制jquery datepicker”)中建议的一些方法,例如通过$(“css selector”).datepicker()语法调用West wind控件(它呈现文本框)上的“.datepicker()”函数,并且ASP.NET保证所有文本框的唯一ID。

    总而言之,它是这样的:

    <page>
      <mycontrol>
       <west-windjQuerycontrol />
      </mycontrol>
      <mycontrol>
       <west-windjQuerycontrol />
      </mycontrol>
    </page>
    

    现在,奇怪的是:当页面上有多个Westwind控件的副本,而其他用户控件不包含这些副本时,它们就会正常工作。除了jquery控件,我的控件没有什么特别之处:只是标签、文本框、面板和下拉列表。将west wind jquery控件捆绑到用户控件中的某些操作似乎正在破坏它。

    有什么建议吗?有一段时间,我一直在为此苦思冥想,因为我糟糕的JavaScript技能和有限的jQuery暴露。

    正如下面指出的,没有HTML很难说。我把它包括在下面。

    <form name="form1" method="post" action="ControlTest.aspx" id="form1">
    <div>
    <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
    <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
    <input type="hidden" name="__LASTFOCUS" id="__LASTFOCUS" value="" />
    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTU4NjEzMDEwOQ9kFgICAw9kFgQCAw9kFgRmD2QWAgIDD2QWAgIDDxBkZBYBZmQCAg9kFgICAw9kFgICAQ8QZGQWAWZkAgUPZBYEZg9kFgICAw9kFgICAw8QZGQWAWZkAgIPZBYCAgMPZBYCAgEPEGRkFgFmZGRDjfLpdb+XxaVaQYP2XkPil2Galw=="     />
    </div>
    
    <script type="text/javascript">
    //<![CDATA[
    var theForm = document.forms['form1'];
    if (!theForm) {
        theForm = document.form1;
    }
    function __doPostBack(eventTarget, eventArgument) {
        if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
                theForm.__EVENTTARGET.value = eventTarget;
            theForm.__EVENTARGUMENT.value = eventArgument;
            theForm.submit();
            }
    }
    //]]>
    </script>
    
    
            <script src="/SSO/DE/WebResource.axd?d=jMPpL-KK8_mPj_ssZzGblw2&amp;t=633481894229838141" type="text/javascript"></script>
    
    
    <script src="/SSO/DE/ScriptResource.axd?d=8KwRIGaNAD3hi2Loz3YV-uxgrdZpGe8nnwH5E3gxLW_lQpnYjRbyIYThTnHtD9rt0&amp;t=633613004148118290" type="text/javascript"></script>
    <script src="/SSO/DE/ScriptResource.axd?d=8KwRIGaNAD3hi2Loz3YV-uxgrdZpGe8nnwH5E3gxLW-K0Kuw-pGK1O3mE_r1y3sjKmhHtQjSXeMtYSim0bjyGA2&amp;t=633613004148118290" type="text/javascript"></script>
    <script src="/SSO/DE/ScriptResource.axd?d=Id5yAacLMZHF7TWlkgrrid30ZStmsXuLHcF6WQ404YLySP4Itj4qxv2wi9ffbsWQA86oLdnZPWkwDnu4NKxfG1Ue7qdGG1SbOfb4ooHVs7M1&amp;t=633481957084709567" type="text/javascript"></script>
    <script type="text/javascript">
    //<![CDATA[
    if (typeof(Sys) === 'undefined') throw new Error('ASP.NET Ajax client-side framework failed to load.');
    //]]>
    </script>
    
    <script src="/SSO/DE/ScriptResource.axd?d=Id5yAacLMZHF7TWlkgrrid30ZStmsXuLHcF6WQ404YLySP4Itj4qxv2wi9ffbsWQhT3MFELBAa2rFJZXnSlYAZIN7RT1npcBxJRsWGjJWIwTF0Es1m0vOd-xYnFqWJKz0&amp;t=633481957084709567" type="text/javascript"></script>
        <div style="margin:25px 10px;width:100%;">
            <script type="text/javascript">
    //<![CDATA[
    Sys.WebForms.PageRequestManager._initialize('stupidThing',     document.getElementById('form1'));
    Sys.WebForms.PageRequestManager.getInstance()._updateControls([], [], [], 90);
    //]]>
    </script>
    
            <div id="datePicker_Div0" class="AdminRowOdd DERow">
                <div id="datePicker_Div1" class="DELabel">
                    <span id="datePicker_DateLabel">Date</span>
                </div>
                <div id="datePicker_Div2" class="DEInput datePicker">
                    <input name="datePicker$DateSelector" type="text" onchange="javascript:setTimeout('__doPostBack(\'datePicker$DateSelector\',\'\')', 0)" onkeypress="if (WebForm_TextBoxKeyHandler(event) == false) return false;" id="datePicker_DateSelector" style="width:80px;" />
                    <select name="datePicker$languageSelector" onchange="javascript:setTimeout('__doPostBack(\'datePicker$languageSelector\',\'\')', 0)" id="datePicker_languageSelector">
        <option selected="selected" value="en-US">en-US</option>
        <option value="fr-CA">fr-CA</option>
        <option value="fr-FR">fr-FR</option>
        <option value="es-ES">es-ES</option>
        <option value="es-MX">es-MX</option>
    
    </select>
                </div>
            </div>
            <div id="datePicker_Div3" class="AdminRowEven DERow">
                <div id="datePicker_Div4" class="DELabel">
                    <span id="datePicker_FormatChoiceLabel">Choose your display format:    </span>
                </div>
                <div id="datePicker_Div5" class="DEInput">
                    <select name="datePicker$DateFormatSelector" onchange="javascript:setTimeout('__doPostBack(\'datePicker$DateFormatSelector\',\'\')', 0)" id="datePicker_DateFormatSelector">
        <option selected="selected" value="Choose a date first">Choose a date     first</option>
    
    </select>                
                </div>
            </div>
            <div id="datePicker_Div6" class="AdminRowOdd DERow">
                <div id="datePicker_Div7" class="DELabel">
                    <span id="datePicker_FormatOverrideLabel">Or enter your own     text</span>
                </div>
                <div id="datePicker_Div8" class="DEInput">
                    <input name="datePicker$DateFormatOverride" type="text"     onchange="javascript:setTimeout('__doPostBack(\'datePicker$DateFormatOverride\',\'\')', 0)" onkeypress="if (WebForm_TextBoxKeyHandler(event) == false) return false;"     id="datePicker_DateFormatOverride" />
                </div>
            </div>
    
            <br />
            <div id="date1_Div0" class="AdminRowOdd DERow">
                <div id="date1_Div1" class="DELabel">
                    <span id="date1_DateLabel">Date</span>
                </div>
                <div id="date1_Div2" class="DEInput datePicker">
                <input name="date1$DateSelector" type="text" onchange="javascript:setTimeout('__doPostBack(\'date1$DateSelector\',\'\')', 0)" onkeypress="if (WebForm_TextBoxKeyHandler(event) == false) return false;" id="date1_DateSelector" style="width:80px;" />
                    <select name="date1$languageSelector" onchange="javascript:setTimeout('__doPostBack(\'date1$languageSelector\',\'\')', 0)" id="date1_languageSelector">
        <option selected="selected" value="en-US">en-US</option>
        <option value="fr-CA">fr-CA</option>
        <option value="fr-FR">fr-FR</option>
        <option value="es-ES">es-ES</option>
        <option value="es-MX">es-MX</option>
    
    </select>
                </div>
            </div>
            <div id="date1_Div3" class="AdminRowEven DERow">
                <div id="date1_Div4" class="DELabel">
                    <span id="date1_FormatChoiceLabel">Choose your display format:</span>
                </div>
                <div id="date1_Div5" class="DEInput">
                    <select name="date1$DateFormatSelector" onchange="javascript:setTimeout('__doPostBack(\'date1$DateFormatSelector\',\'\')', 0)" id="date1_DateFormatSelector">
        <option selected="selected" value="Choose a date first">Choose a date first</option>
    
    </select>                
                </div>
            </div>
            <div id="date1_Div6" class="AdminRowOdd DERow">
                <div id="date1_Div7" class="DELabel">
                    <span id="date1_FormatOverrideLabel">Or enter your own text</span>
                </div>
                <div id="date1_Div8" class="DEInput">
                    <input name="date1$DateFormatOverride" type="text" onchange="javascript:setTimeout('__doPostBack(\'date1$DateFormatOverride\',\'\')', 0)" onkeypress="if (WebForm_TextBoxKeyHandler(event) == false) return false;" id="date1_DateFormatOverride" />
                </div>
            </div>
    
        </div>
    
    <div>
    
        <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWFQLr6MeTCwKb1Zr0AwKVt6utCQKIwaTjAQKdwYzzBwLiwsDhDQKIwdCLBAKHwbCtCgLRr42cCQKi9vj4DgK2lM6kBQLLrsUtAsaboRMC2+2u3QgCzu2GzQ4Cse7K3wQC2+3atQ0C1O26kwMCpdTivwwC1o2X2wsCoubqnQk8I1BK30Q/iVw/rExUww2Cs4bicw==" />
    </div>
    
    <script type="text/javascript">
    //<![CDATA[
    jQuery(document).ready( function() {
    var cal = jQuery('#datePicker_DateSelector').datepicker({yearRange: '-1500:+100',dateFormat: 'm/d/yy'});
    } );
    Sys.Application.initialize();
    //]]>
    </script>
    </form>
    
    2 回复  |  直到 16 年前
        1
  •  1
  •   Shog9    16 年前

    如果看不到生成的HTML,很难知道,但我的第一个猜测是,您的控件没有将类名直接应用于 <input> 田野…或者你依赖 id 以某种方式(嵌入到用户控件中时可能会发生变化)。


    在您发布的HTML中,这些内容显示为三个相关部分:

    块1(控件:日期选取器)

    <div id="datePicker_Div0" class="AdminRowOdd DERow">
        <div id="datePicker_Div1" class="DELabel">
            <span id="datePicker_DateLabel">Date</span>
        </div>
        <div id="datePicker_Div2" class="DEInput datePicker">
            <input name="datePicker$DateSelector" type="text" 
               onchange="javascript:setTimeout('__doPostBack(\'datePicker$DateSelector\',\'\')', 0)" 
               onkeypress="if (WebForm_TextBoxKeyHandler(event) == false) return false;" 
               id="datePicker_DateSelector" style="width:80px;" />
            <select name="datePicker$languageSelector" 
               onchange="javascript:setTimeout('__doPostBack(\'datePicker$languageSelector\',\'\')', 0)" 
               id="datePicker_languageSelector">
                    <option selected="selected" value="en-US">en-US</option>
                    <option value="fr-CA">fr-CA</option>
                    <option value="fr-FR">fr-FR</option>
                    <option value="es-ES">es-ES</option>
                    <option value="es-MX">es-MX</option>
            </select>
        </div>
    </div>
    

    块2(控件:日期1)

    <div id="date1_Div0" class="AdminRowOdd DERow">
       <div id="date1_Div1" class="DELabel">
           <span id="date1_DateLabel">Date</span>
       </div>
       <div id="date1_Div2" class="DEInput datePicker">
          <input name="date1$DateSelector" type="text" 
             onchange="javascript:setTimeout('__doPostBack(\'date1$DateSelector\',\'\')', 0)" 
             onkeypress="if (WebForm_TextBoxKeyHandler(event) == false) return false;" 
             id="date1_DateSelector" style="width:80px;" />
           <select name="date1$languageSelector" 
             onchange="javascript:setTimeout('__doPostBack(\'date1$languageSelector\',\'\')', 0)" 
             id="date1_languageSelector">
             <option selected="selected" value="en-US">en-US</option>
             <option value="fr-CA">fr-CA</option>
             <option value="fr-FR">fr-FR</option>
             <option value="es-ES">es-ES</option>
             <option value="es-MX">es-MX</option>
          </select>
       </div>
    </div>
    

    块3(jquery datepicker wireup)

    <script type="text/javascript">
       //<![CDATA[
       jQuery(document).ready( function() 
       {
          // matches input element for first control only (id selector)
          var cal = jQuery('#datePicker_DateSelector')
             .datepicker({yearRange: '-1500:+100',dateFormat: 'm/d/yy'});
       });
       Sys.Application.initialize();
       //]]>
    </script>
    

    问题出在最后一块。选择器特定于第一个控件,按ID匹配。如果它被修改为包含对第二个控件的单独调用…

          var cal = jQuery('#datePicker_DateSelector')
             .datepicker({yearRange: '-1500:+100',dateFormat: 'm/d/yy'});
          var cal2 = jQuery('#date1_DateSelector')
             .datepicker({yearRange: '-1500:+100',dateFormat: 'm/d/yy'});
    

    …或更通用的选择器…

          // matches all text input elements that are descendants of 
          // a div element with a class of datePicker
          var cal = jQuery('div.datePicker input:text')
             .datepicker({yearRange: '-1500:+100',dateFormat: 'm/d/yy'});
    

    …那么事情应该按预期进行。

        2
  •  1
  •   Jeff    16 年前

    我解决了问题。

    服务器控件的onprerender()生成上面找到的javascript,调用以下内容,其中sbstartupscript是包含生成的javascript的StringBuilder:

    sbStartupScript.AppendLine("} );");
    scriptProxy.RegisterStartupScript(this.Page, typeof(ControlResources), "_cal" + this.ID,
    sbStartupScript.ToString(), true);
    

    正确的形式应该是:

    sbStartupScript.AppendLine("} );");
    scriptProxy.RegisterStartupScript(this.Page, typeof(ControlResources), "_cal" + this.ClientID,
    sbStartupScript.ToString(), true);
    

    现在,有了clientID,脚本名是唯一的,两者都将呈现。