Получение jQuery для распознавания .change () в IE

131

Я использую jQuery для скрытия и отображения элементов при изменении / нажатии группы переключателей. Он отлично работает в браузерах, таких как Firefox, но в IE 6 и 7 действие происходит только тогда, когда пользователь затем щелкает где-то еще на странице.

Чтобы уточнить, когда вы загружаете страницу, все выглядит нормально. В Firefox, если вы нажмете переключатель, одна строка таблицы будет скрыта, а другая отобразится немедленно. Однако в IE 6 и 7 вы щелкаете переключатель, и ничего не произойдет, пока вы не нажмете где-нибудь на странице. Только после этого IE перерисовывает страницу, скрывая и показывая соответствующие элементы.

Вот jQuery, который я использую:

$(document).ready(function () {
  $(".hiddenOnLoad").hide();

  $("#viewByOrg").change(function () {
    $(".visibleOnLoad").show();
    $(".hiddenOnLoad").hide();
  });

  $("#viewByProduct").change(function () {
    $(".visibleOnLoad").hide();
    $(".hiddenOnLoad").show();
  });
});

Вот часть XHTML, на которую это влияет. Вся страница проверяется как XHTML 1.0 Strict.

<tr>
  <td>View by:</td>
  <td>
    <p>
      <input type="radio" name="viewBy" id="viewByOrg" value="organisation"
      checked="checked" />Organisation</p>
    <p>
      <input type="radio" name="viewBy" id="viewByProduct" value="product" />Product</p>
  </td>
</tr>
<tr class="visibleOnLoad">
  <td>Organisation:</td>
  <td>
    <select name="organisation" id="organisation" multiple="multiple" size="10">
      <option value="1">Option 1</option>
      <option value="2">Option 2</option>
    </select>
  </td>
</tr>
<tr class="hiddenOnLoad">
  <td>Product:</td>
  <td>
    <select name="product" id="product" multiple="multiple" size="10">
      <option value="1">Option 1</option>
      <option value="2">Option 2</option>
    </select>
  </td>
</tr>

Если у кого-то есть идеи, почему это происходит и как это исправить, они были бы очень признательны!

Филип Мортон
источник

Ответы:

96

Попробуйте использовать .clickвместо .change.

Паоло Бергантино
источник
3
@samjudson, в моем тестировании это неверно, и щелчок jquery срабатывает, когда я выбираю следующий переключатель с помощью клавиш со стрелками. (vista, ie7)
svandragt
1
@Pacifika: Не для меня в IE7. По крайней мере, это правильно. «щелчок» - это совершенно другое событие, чем «изменение», и есть, по крайней мере, некоторые (если не все) случаи, когда это неуместная замена.
Бобби Джек,
3
@samjudson: события щелчка на переключателях и флажках также срабатывают при их выборе с помощью клавиатуры. Работает во всех браузерах
Philippe Leybaert 09
4
Я поправляюсь - это действительно так, как бы нелогично это ни было!
Бобби Джек,
2
Это кажется наиболее популярным ответом на этот конкретный вопрос, но он не совсем правильный! clickотличается от того, changeчто его обработчик событий также будет вызываться при нажатии уже выбранной опции, тогда как changeэтого не происходит. В этом ответе есть пример того, как использовать jQuery .dataдля сравнения старых и новых значений.
Laoujin
54

Проблема с использованием clickсобытия вместоchange заключается в том, что вы получаете событие, если выбран тот же переключатель (т.е. фактически не изменился). Это можно отфильтровать, если вы проверите, что новое значение отличается от старого. Меня это немного раздражает.

Если вы используете changeсобытие, вы можете заметить, что оно распознает изменение после того, как вы щелкнете любой другой элемент в IE. Если вы звоните blur()в clickслучае, это будет вызывать changeсобытие огня (только если коробки радио на самом деле имеют измененный).

Вот как я это делаю:

// This is the hack for IE
if ($.browser.msie) {
  $("#viewByOrg").click(function() {
    this.blur();
    this.focus();
  });
}

$("#viewByOrg").change(function() {
  // Do stuff here
});

Теперь вы можете использовать событие изменения как обычно.

Изменить: добавлен вызов focus () для предотвращения проблем с доступностью (см. Комментарий Бобби ниже).

Марк А. Николози
источник
2
Это очень опасный прием, потому что он не позволяет вашим пользователям перемещаться с помощью клавиатуры, потому что фокус исчезает после выбора переключателя.
Philippe Leybaert, 09
5
Это здорово, но вызывает проблемы с доступностью клавиатуры. После запуска события blur () переключатель больше не фокусируется, поэтому перемещение между переключателями с помощью клавиатуры становится чрезвычайно неудобным. Мое текущее решение - добавить вызов "this.focus ();" сразу после оператора blur ().
Бобби Джек,
1
Я думаю, что это худшее из представленных решений из-за проблем с доступностью.
Philippe Leybaert 09
11
Но проблему доступности можно решить с помощью вызова focus (). По крайней мере, это так же хорошо, как использовать click () для всего.
Бобби Джек,
Спасибо, Бобби, я добавлю это к ответу.
Mark A. Nicolosi
33

Вы пробовали событие IE onpropertychange? Не знаю, имеет ли это значение, но, вероятно, стоит попробовать. IE не запускает событие изменения, когда значения обновляются с помощью JS-кода, но, возможно, в этом случае будет работать onpropertychange.

$("#viewByOrg").bind($.browser.msie? 'propertychange': 'change', function(e) {
  e.preventDefault(); // Your code here 
}); 
Kevin
источник
Похоже, что «щелкнуть» не сработало, а «изменение свойства» - сработало. Спасибо!
Джеймс Кингсбери
Я пробовал это в IE8, это не работает. Это не входит в функцию.
ARUN
14

Это тоже должно работать:

$(document).ready(function(){
   $(".hiddenOnLoad").hide();
   $("#viewByOrg, #viewByProduct").bind(($.browser.msie ? "click" : "change"), function () {
                        $(".visibleOnLoad").show();
                        $(".hiddenOnLoad").hide();
                    });
});

Спасибо, Пьер. Это было очень полезно.


источник
Это, по крайней мере, гораздо лучший ответ, чем текущий принятый / получивший наибольшее количество голосов. Это "только" нарушает доступность клавиатуры в IE, а не во всех хороших браузерах.
Бобби Джек,
... хотя, разве это не просто копия ответа Пьера?
Бобби Джек,
Согласен, это немного менее читаемая версия Пьера, но оба селектора связаны за один вызов.
Тристан Уорнер-Смит,
Замените clickна, click keyup keypressчтобы добавить поддержку клавиатуры.
aloisdg переходит на codidact.com
6

В IE вы должны использовать событие click, в других браузерах onchange. Ваша функция может стать

$(document).ready(function(){
   $(".hiddenOnLoad").hide();
   var evt = $.browser.msie ? "click" : "change";
   $("#viewByOrg").bind(evt, function () {
                        $(".visibleOnLoad").show();
                        $(".hiddenOnLoad").hide();
                    });

   $("#viewByProduct").bind(evt, function () {
                        $(".visibleOnLoad").hide();
                        $(".hiddenOnLoad").show();
                    });     
});
Пьер Луиджи
источник
Замените clickна, click keyup keypressчтобы добавить поддержку клавиатуры.
aloisdg переходит на codidact.com
6

добавить этот плагин

jQuery.fn.radioChange = function(newFn){
    this.bind(jQuery.browser.msie? "click" : "change", newFn);
}

затем

$(function(){
    $("radioBtnSelector").radioChange(function(){
        //do stuff
    });
});
dovidweisz
источник
4

У меня была такая же проблема с вводимым текстом.

Я изменился:

$("#myinput").change(function() { "alert('I changed')" });

в

$("#myinput").attr("onChange", "alert('I changed')");

и у меня все работает нормально!

Фабрис
источник
2

Это простой способ указать IE запускать событие изменения при щелчке по элементу:

if($.browser.msie) {
    $("#viewByOrg").click(function() {
        $(this).change();
    });
}

Вы можете расширить это до чего-то более общего, чтобы работать с большим количеством элементов формы:

if($.browser.msie) {
    $("input, select").click(function() {
        $(this).change();
    });
    $("input, textarea").keyup(function() {
        $(this).change();
    });
}
Павел
источник
1

Я почти уверен, что это известная проблема с IE. Добавление обработчика onclickсобытия должно решить проблему:

$(document).ready(function(){

    $(".hiddenOnLoad").hide();

    $("#viewByOrg").change(function () {
        $(".visibleOnLoad").show();
        $(".hiddenOnLoad").hide();
    });

    $("#viewByOrg").click(function () {
        $(".visibleOnLoad").show();
        $(".hiddenOnLoad").hide();
    });

    $("#viewByProduct").change(function () {
        $(".visibleOnLoad").hide();
        $(".hiddenOnLoad").show();
    });     

    $("#viewByProduct").click(function () {
        $(".visibleOnLoad").hide();
        $(".hiddenOnLoad").show();
    });     
});
Крис Цвирик
источник
1

В IE принудительно установите радио и флажки для запуска события "изменения":

if($.browser.msie && $.browser.version < 8)
  $('input[type=radio],[type=checkbox]').live('click', function(){
    $(this).trigger('change');
  });
Джефф Уилкс
источник
1

с jquery 1.6 это больше не проблема .. не уверен, когда это было исправлено .. Слава богу, хотя

Baz1nga
источник
1

Если вы измените версию jQuery на 1.5.1, вам не придется корректировать код. Тогда IE9 будет идеально слушать:

$(SELECTOR).change(function() {
    // Shizzle
});

http://code.jquery.com/jquery-1.5.1.min.js

Bas Matthee
источник
1

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

(function($) {
    $('input[type=checkbox], input[type=radio]').live('click', function() {
       var $this = $(this);
       setTimeout(function() {
          $this.trigger('changeIE'); 
       }, 10) 
    });
})(jQuery);

$(selector).bind($.browser.msie && $.browser.version <= 8 ? 'changeIE' : 'change', function() {
  // do whatever you want
})
не останавливайся
источник
0

imo использование щелчка вместо изменения делает поведение IE другим. Я бы предпочел эмулировать поведение события изменения с помощью таймера (setTimout).

что-то вроде (предупреждение - код блокнота):

if ($.browser.msie) {
  var interval = 50;
  var changeHack = 'change-hac';
  var select = $("#viewByOrg");
  select.data(changeHack) = select.val();
  var checkVal=function() {
    var oldVal = select.data(changeHack);
    var newVal = select.val();
    if (oldVal !== newVal) {
      select.data(changeHack, newVal);
      select.trigger('change')
    }
    setTimeout(changeHack, interval);
  }
  setTimeout(changeHack, interval);
}

$("#viewByOrg").change(function() {
  // Do stuff here
});
Кен Эгози
источник
ого ... немного деспотичный, нет?
orip
0

попробуйте это, это работает для меня

$("#viewByOrg")
        .attr('onChange', $.browser.msie ? "$(this).data('onChange').apply(this)" : "")
        .change( function(){if(!$.browser.msie)$(this).data('onChange').apply(this)} )
        .data('onChange',function(){alert('put your codes here')});
RainChen
источник
0

Это может кому-то помочь: вместо того, чтобы начинать с идентификатора формы, выберите идентификатор выбора и отправьте форму при изменении, например:

<form id='filterIt' action='' method='post'>
  <select id='val' name='val'>
    <option value='1'>One</option>
    <option value='2'>Two</option>
    <option value='6'>Six</option>
  </select>
  <input type="submit" value="go" />
</form>

и jQuery:

$('#val').change(function(){
  $('#filterIt').submit();
});

(Очевидно, что кнопка отправки необязательна, если javascript отключен)

Jongosi
источник
0

Попробуйте следующее:

.bind($.browser.msie ? 'click' : 'change', function(event) {
Билал Джалил
источник
0

Избегайте использования .focus () или .select () перед .Кнопкой () функция JQuery для IE, то он работает нормально, им использовать его на моем сайте.

Спасибо

muhammadanish
источник
0
//global
var prev_value = ""; 

$(document).ready(function () {

 if (jQuery.browser.msie && $.browser.version < 8)
      $('input:not(:submit):not(:button):not(:hidden), select, textarea').bind("focus", function () { 
         prev_value = $(this).val();

       }).bind("blur", function () { 
         if($(this).val() != prev_value)
         has_changes = true;
       });
}
Киев
источник
0

Пожалуйста, попробуйте использовать каждый вместо изменения / щелчка , который отлично работает даже в первый раз в IE, а также в других браузерах.

Не работает в первый раз

$("#checkboxid").**change**(function () {

});

Работает нормально даже с первого раза

$("#checkboxid").**each**(function () {

});
Даянанд Рупанавар
источник