JQuery DatePicker o controle empacotado não podem ser incluídos em outros controles
-
05-07-2019 - |
Pergunta
Eu fui encarregado de implementar um seletor de data / hora para diversas áreas de nosso projeto web, e instruído a usar um controle que outro desenvolvedor criado como parte dela. O controle que estou trabalhando é suposto para permitir que o usuário para selecionar uma data de um calendário, escolher um formato para a exibição dessa data (a partir de vários formatos pré-definidos, ou com uma substituição de texto simples) e, opcionalmente, uma string de hora (que é o texto realmente apenas de forma livre).
O controle fui instruído a utilização está documentado aqui: http: // www.west-wind.com/WebLog/posts/213015.aspx , e usa o DatePicker do jQuery.
Depois de implementado o meu controle e testou-o, comecei integrá-lo nas páginas que necessárias entradas de data e / ou tempo. Na minha análise dessas implementações, descobri um erro: quando eu incluir várias cópias do meu controle em uma página, apenas o primeiro recebe o calendário jQuery. Os outros não estão vinculados a ele.
Eu tentei alguns dos métodos sugeridos em uma questão aparentemente relacionada-(intitulado 'duplicando jquery datepicker'), como chamar o '.datepicker ()' função no controle oeste-vento (o que torna uma caixa de texto) via o $ ( "css-selector"). datepicker () sintaxe e ASP.NET está garantindo identificações exclusivas para todas as caixas de texto.
Assim, em resumo, parece que isso:
<page>
<mycontrol>
<west-windjQuerycontrol />
</mycontrol>
<mycontrol>
<west-windjQuerycontrol />
</mycontrol>
</page>
Agora, a parte estranha: Quando existem várias cópias do controle oeste-vento na página, sem outro controlo do utilizador que os contenham, eles funcionam corretamente. Outros do que o controle jQuery, meu controle não tem nada de incomum nisso: basta etiquetas, caixas de texto, painéis e menus suspensos. Algo sobre agregação de controle West-vento jQuery em um controle de usuário parece estar quebrando-o.
Qualquer conselho? Eu estive batendo a cabeça contra isso por um tempo, dificultada pelas minhas pobres habilidades javascript e exposição limitada a jQuery.
Como se verá mais adiante, é difícil dizer sem o HTML. Eu incluí-lo abaixo.
<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&t=633481894229838141" type="text/javascript"></script>
<script src="/SSO/DE/ScriptResource.axd?d=8KwRIGaNAD3hi2Loz3YV-uxgrdZpGe8nnwH5E3gxLW_lQpnYjRbyIYThTnHtD9rt0&t=633613004148118290" type="text/javascript"></script>
<script src="/SSO/DE/ScriptResource.axd?d=8KwRIGaNAD3hi2Loz3YV-uxgrdZpGe8nnwH5E3gxLW-K0Kuw-pGK1O3mE_r1y3sjKmhHtQjSXeMtYSim0bjyGA2&t=633613004148118290" type="text/javascript"></script>
<script src="/SSO/DE/ScriptResource.axd?d=Id5yAacLMZHF7TWlkgrrid30ZStmsXuLHcF6WQ404YLySP4Itj4qxv2wi9ffbsWQA86oLdnZPWkwDnu4NKxfG1Ue7qdGG1SbOfb4ooHVs7M1&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&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>
Solução
É difícil saber sem ver o HTML gerado, mas meu primeiro palpite seria que seu controle não está aplicando os nomes de classe diretamente para o campo <input>
... ou você está dependendo id
s de alguma forma (o que provavelmente mudar quando incorporado em um controle de usuário).
No HTML que você postou, estes parecem três partes relevantes:
bloco # 1 (controle: datePicker)
<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>
...
bloco # 2 (controle: date1)
<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>
...
bloco # 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>
O problema surge a partir deste último bloco. O seletor é específico para o primeiro controle, combinando por ID. Se ele foi modificado para incluir uma chamada separada para o segundo controle ...
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'});
... ou um de uso geral mais selector ...
// 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'});
... então as coisas devem funcionar como esperado.
Outras dicas
Eu descobri o problema.
O OnPreRender () do controle de servidor constrói o javascript encontrado acima, o chama o seguinte, onde sbStartupScript é um StringBuilder que contém o javascript gerado:
sbStartupScript.AppendLine("} );");
scriptProxy.RegisterStartupScript(this.Page, typeof(ControlResources), "_cal" + this.ID,
sbStartupScript.ToString(), true);
A forma correta deveria ter sido:
sbStartupScript.AppendLine("} );");
scriptProxy.RegisterStartupScript(this.Page, typeof(ControlResources), "_cal" + this.ClientID,
sbStartupScript.ToString(), true);
Agora, tendo o ClientId, o nome do script é único, e ambos vão render.