Jquery datepicker не закрывается на выбранную дату в IE8 - PullRequest
19 голосов
/ 10 ноября 2009

У меня есть веб-форма с полем даты начала. Я привязал jquery datepicker к текстовому полю. Теперь, когда я выбираю дату в FF, выбранная дата заполняется в текстовом поле, и всплывающее окно календаря закрывается. Однако, когда я делаю то же самое в IE8, выбранная дата заполняется в текстовом поле, но всплывающее окно остается открытым. Я также заметил, что ошибка скрипта генерируется, как только я выбираю дату во всплывающем календаре.

Я использую jquery 1.3.2, jquery-ui 1.7.2 и .NET 3.5. Вот пример моего кода:

<script type="text/javascript">
  $(document).ready(function() {
    $("#<%=txtStartDate.ClientID%>").datepicker({
      changeMonth: true,
      changeYear: true,
      showButtonPanel: true,
      showOn: 'button',
      buttonImage: '/_layouts/images/CALENDAR.GIF',
      buttonImageOnly: true
    });
  });
</script>
<div id="stylized">
  <asp:ValidationSummary ID="vs" runat="server" CssClass="messages-error" HeaderText=" Action required before the form can be submitted." ForeColor="" ValidationGroup="sh" />
  <div class="formrow">
    <div class="ms-formlabel formlabel">
      <asp:Label ID="lblStartDate" runat="server" CssClass="ms-standardheader" AssociatedControlID="txtStartDate">Start Date:</asp:Label>
    </div>
    <div class="ms-formbody formfield">
      <asp:RequiredFieldValidator ID="reqStartDate" runat="server" ControlToValidate="txtStartDate" ErrorMessage="Start Date is a required field." Text="*" Display="Dynamic" ValidationGroup="sh"></asp:RequiredFieldValidator>
      <asp:CompareValidator ID="cvStartDate" runat="server" ControlToValidate="txtStartDate" ErrorMessage="Date must be in the format MM/DD/YYYY" Text="*" Display="Dynamic" ValidationGroup="sh" Operator="DataTypeCheck" Type="Date"></asp:CompareValidator>
      <asp:TextBox ID="txtStartDate" runat="server"></asp:TextBox>
      <span class="formMessage">ex. MM/DD/YYYY</span>
    </div>
  </div>
  <div id="buttonrow">
    <asp:Button ID="btnSubmit" runat="server" Text="Submit" CssClass="ms-ButtonHeightWidth" OnClick="Submit_Click" ValidationGroup="sh" />
    <asp:Button ID="btnCancel" runat="server" Text="Cancel" CssClass="ms-ButtonHeightWidth" OnClick="Cancel_Click" CausesValidation="false" />
  </div>
</div>

Вот ошибка скрипта, которую я получаю в IE при выборе даты:

'длина' равна нулю или не является объектом

WebResource.axd

Вот код, из которого выдается ошибка:

function ValidatorOnChange(event) {
  if (!event) {
    event = window.event;
  }
  Page_InvalidControlToBeFocused = null;
  var targetedControl;
  if ((typeof(event.srcElement) != "undefined") && (event.srcElement != null)) {
    targetedControl = event.srcElement;
  }
  else {
    targetedControl = event.target;
  }
  var vals;
  if (typeof(targetedControl.Validators) != "undefined") {
    vals = targetedControl.Validators;
  }
  else {
    if (targetedControl.tagName.toLowerCase() == "label") {
        targetedControl = document.getElementById(targetedControl.htmlFor);
        vals = targetedControl.Validators;
    }
  }
  var i;
  for (i = 0; i < vals.length; i++) {
    ValidatorValidate(vals[i], null, event);
  }
  ValidatorUpdateIsValid();
}

Это происходит на длине в цикле for в конце. Vals равен нулю и не найден в предыдущем if / else. Я прошел через JavaScript и if (typeof (targetControl.Validators)! = "Undefined") возвращает false, а затем if (targetControl.tagName.toLowerCase () == "label") тоже возвращает false. Таким образом, длина равна нулю или не является ошибкой объекта.

Теперь я не уверен, что всплывающее окно datepicker не закрывается в IE, а ошибка скрипта в файле WebResources.axd связана с ошибками, но я склоняюсь к этому. Может кто-нибудь сказать мне, почему всплывающее окно не закрывается?

Ответы [ 10 ]

27 голосов
/ 29 декабря 2009

Когда дата выбрана, средство выбора даты запускает событие изменения элемента INPUT, но средство проверки ASP.Net вместо этого выбирает событие click с источником A и пытается найти средства проверки. на этом элементе A вместо INPUT. Это можно увидеть, проверив event.srcElement внутри функции ValidatorOnChange валидатора. В браузерах, отличных от IE, event.type - это «изменение», а event.target - это правильно INPUT.

Хотя функция no-op onSelect: function() { } предотвращает ошибку, переопределяя встроенную функцию .change() на значение по умолчанию onSelect средства выбора даты, она также предотвращает запуск валидаторов. Вот обходной путь для обоих:

onSelect: function() {
  this.fireEvent && this.fireEvent('onchange') || $(this).change();
}

Используется обычный триггер .change(), кроме IE, где требуется использовать .fireEvent, чтобы привязать объект события к изменению, а не к щелчку.

16 голосов
/ 12 ноября 2009

Кажется, это своего рода ошибка, но добавление этой строки в объявлении datepicker должно решить эту проблему:

onSelect: function() {}
3 голосов
/ 07 октября 2011

Решения, представленные выше, только предотвращают возникновение ошибки.

На указателе даты:

onSelect : function(dateText, inst){ inst.input.trigger('cValidate')

и привязать событие к элементу ввода календаря.

.bind('cValidate', function (event) { window.ValidatorOnChange(event); });

это вызовет событие validatoraged с правильными аргументами события (поле ввода).

2 голосов
/ 20 марта 2013

Причина

Ошибка root (я думаю, что это, скорее всего, функция, или может быть обходной путь для известной ошибки IE?) В ASP.Net ValidatorHookupEvent:

var func;
if (navigator.appName.toLowerCase().indexOf('explorer') > -1) {
    func = new Function(functionPrefix + " " + ev);
}
else {
    func = new Function("event", functionPrefix + " " + ev);
}

В результате, в случае по умолчанию, когда нет других зарегистрированных onchange, это устанавливает onchange для входа, эквивалентного

function() { ValidatorOnChange(event); }

в IE и

function(event) { ValidatorOnChange(event); }

в других браузерах. Поэтому, если вы используете IE, событие, переданное ValidatorOnChange, будет window.event (поскольку window является глобальным объектом).

Предлагаемое решение

Если вы не хотите взламывать скрипты ASP.Net, то я думаю, что самый хороший способ справиться с этим - обнаружить сломанный обработчик событий и заменить его. Как и в случае с другими предложениями, я предлагаю onSelect для включения в опции datepicker.

onSelect: function(dateStr, datePicker) {
    // http://stackoverflow.com/questions/1704398
    if (datePicker.input[0].onchange.toString().match(/^[^(]+\(\)\s*{\s*ValidatorOnChange\(event\);\s*}\s*$/)) {
        datePicker.input[0].onchange = ValidatorOnChange;
    }
    datePicker.input.trigger("change");
}

Я применяю это глобально с

$.datepicker.setDefaults({
    onSelect: function(dateStr, datePicker) {
        etc.
    }
});
1 голос
/ 27 августа 2010

изменить строку jquery.ui.datepicker.js 1504

'" href="#"  >' + printDate.getDate() + '</a>')

с

'" href="javascript:DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
       inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);"  >' + printDate.getDate() + '</a>')

тест работает ОК!

1 голос
/ 25 мая 2010

Это эндемическая проблема с датчиками jQuery и средствами проверки ASP. Как вы говорите, неправильный элемент вызывает перекрестную запуск подпрограммы проверки подлинности JavaScript NET NET, а затем M $ -код выдает ошибку, потому что запускающий элемент в подпрограмме не определен.

Я решил эту проблему иначе, чем кто-либо другой, которого я видел, - решив, что M $ должен был написать свой код более надежно, и, следовательно, переопределил часть кода валидатора M $, чтобы справиться с неопределенным элементом. Все остальное, что я видел, по сути является обходным путем на стороне jQuery и исключает возможную функциональность (например, использование события click вместо change).

Неудачный бит

   for (i = 0; i < vals.length; i++) {
        ValidatorValidate(vals[i], null, event);
    }

, который выдает ошибку, когда пытается получить длину для неопределенных 'vals'.

Я только что добавил

if (vals) {
    for (i = 0; i < vals.length; i++) {
        ValidatorValidate(vals[i], null, event);
    }
}

и ей хорошо идти. Окончательный код, который заново объявляет всю нарушающую функцию, приведен ниже. Я поставил его как сценарий включения в внизу моей главной страницы или страницы (так что это происходит после объявлений по умолчанию и заменяет более раннюю версию).

Да, это нарушает совместимость, если M $ решит изменить свой код валидатора в будущем. Но можно надеяться, что они исправят это, и тогда мы сможем полностью избавиться от этого патча.

//  Fix issue with datepicker and ASPNET validators: redeclare MS validator code with fix
 function ValidatorOnChange(event) {
    if (!event) {
        event = window.event;
    }
    Page_InvalidControlToBeFocused = null;
    var targetedControl;
    if ((typeof (event.srcElement) != "undefined") && (event.srcElement != null)) {
        targetedControl = event.srcElement;
    }
    else {
        targetedControl = event.target;
    }
    var vals;
    if (typeof (targetedControl.Validators) != "undefined") {
        vals = targetedControl.Validators;
    }
    else {
        if (targetedControl.tagName.toLowerCase() == "label") {
            targetedControl = document.getElementById(targetedControl.htmlFor);
            vals = targetedControl.Validators;
        }
    }
    var i;
    if (vals) {
        for (i = 0; i < vals.length; i++) {
            ValidatorValidate(vals[i], null, event);
        }
    }
    ValidatorUpdateIsValid();
}
1 голос
/ 09 декабря 2009

Исправление ...

onSelect: function () {}

.. не работает, если проблема связана с CustomValidator, который использует валидатор сторонних событий servewr для проверки ввода.

Есть несколько других исправлений, упомянутых здесь ...

http://dev.jqueryui.com/ticket/4071

Проблема заключается в том, что обработка событий в IE отличается от других браузеров и код проверки на стороне клиента, предоставленный ASP Net, не реагирует корректно на ситуацию, не предусмотренную его авторами.

1 голос
/ 12 ноября 2009

Не похоже, что вы делаете что-то не так, поскольку код ValidatorOnChange создан для вас; что-то не так в том, что он создает свой vals объект, который, по-видимому, обнуляется на ie8.

Это было задано до , и решение заключается в переопределении функции onSelect функцией no-op.

Это не единственная проблема с валидатором. Вот неопределенно похожая проблема с функцией автозаполнения.

0 голосов
/ 21 декабря 2012

Опираясь на приведенные выше ответы и предоставив дополнительную информацию в мой комментарий выше,

По-видимому, в IE9 + и других браузерах, теперь вы должны использовать dispatchEvent для запуска события изменения. ( Почему .fireEvent () не работает в IE9? )

Функция OnSelect в указателе даты фактически имеет 2 аргумента:

  1. Значение текстового поля, связанного с указателем даты
  2. Объект со свойством id, совпадающим со значением текстового поля

    mytextbox.datepicker({
        defaultDate: null,
        numberOfMonths: 1,
        dateFormat: DisplayDateFormat,
        onSelect: function (value, source) {
        }
    });
    

Все примеры, которые я видел, использовали document.getElementById() для извлечения текстового поля, которое, я думаю, не понадобилось бы, поскольку исходный объект имеет тот же идентификатор, что и текстовое поле. При ближайшем рассмотрении выясняется, что источником является объект, а не элемент текстового поля. Я обнаружил, что следующий код решил проблему:

    mytextbox.datepicker({
        defaultDate: null,
        numberOfMonths: 1,
        dateFormat: DisplayDateFormat,
        onSelect: function (value, source) {

            var ctrl = document.getElementById(source.id);

            if ("dispatchEvent" in ctrl) {

                // IE9
                var evt = document.createEvent("HTMLEvents");
                evt.initEvent("change", false, true);
                ctrl.dispatchEvent(evt);
            } else if ("fireEvent" in ctrl) {

                // IE7/IE8
                ctrl.fireEvent("onchange");
            } else {

                $(ctrl).change();
            }
        }
    });

Обновление: похоже, что этот подход больше не работает - не знаю, почему. Он останавливает выдачу ошибки, но не вызывает событие изменения.

0 голосов
/ 12 ноября 2009

Я не знаю, в чем проблема, но я заметил, что у вас нет набора ValidationGroup, и оба ваших валидатора имеют это значение. Вы можете попробовать установить ValidationGroup = "sh" в вашем TextBox и посмотреть, поможет ли это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...