Учитывая следующий код:
<html>
<head>
<script>
function updateTabIndex() {
setTimeout(function() {
var elem = document.getElementById("id1")
elem.setAttribute("tabIndex", 2)
elem.setAttribute("value", "now: tabindex 2")
}, 100)
}
</script>
</head>
<body>
<h1>Weird Behaviour When Changing the tabindex in onchange Handler in Internet
Explorer</h1>
<p><input id="id1" tabindex="-1" value="tabindex: (-1)"/></p>
<p><select tabindex="1" size="1" onchange="updateTabIndex()" onpropertychange="updateTabIndex()">
<option>tabindex 1 - an option</option>
<option>tabindex 1 - another option</option>
</select></p>
<p><input tabIndex="3" value="tabindex 3"/></p>
<h2>Instructions</h2>
<ol>
<li>Open this page in IE. To be precise, the problem is reproducible in
(at least):
<ul>
<li>IE 8, Version 8.0.6001.18702CO on Windows XP and</li>
<li>IE 9, Version 9.0.8112.16421 on Windows 7 Professional, 64 bit</li>
</ul>
<li>Use the <em>mouse</em> to change the value of the select box.</li>
<li>As you can see, the onchange handler is called and changes the tabindex
of the first input element.</li>
<li>If you now tab out of the select box, you can see that the tab order is
adhered to correctly: you go from the select box to the first input element
and then to the last element on the page.</li>
<li>Close the page and open it again.</li>
<li>Click on the third input element and press Shift + Tab to enter the select
box.</li>
<li>Use the down arrow key on the keyboard to change the selected value in the
select box.</li>
<li>Now tab out of the select box.</li>
<li>As you can see, the onchange handler is called, as before (the text in
the first input field has changed).</li>
<li>However, if you tab around now, you will see that the tabindex attribute
is ignored. Instead the order of the elements in the document source is used
as the tab order.</li>
<li>Even if you change the select box value with the mouse now, the tab
order remains broken. To test again, you need to close the page and open
it again or reload it by entering the url bar and pressing enter. Hitting
F5 will not be enough.</li>
</ol>
</body>
</html>
IE игнорирует измененный порядок табуляции, когда значение поля выбора (которое запускает изменение атрибута tabindex) изменяется некоторым действием клавиатуры (клавиши со стрелками), но не игнорирует изменение tabindex, когда значение поля выбора изменяется с помощью мыши (см. более подробное объяснение ожидаемого и воспринимаемого поведения в html выше).
Почему IE так себя ведет? В частности, почему поведение при использовании мыши и при использовании клавиш отличается. Это ошибка в IE? Прямо сейчас я почти уверен, что это ошибка в IE, но, конечно, есть вероятность, что я делаю что-то не так, что просто происходит, как ожидалось, в FF.
Я уже немного погуглил, но, насколько я могу судить, об этой ошибке (если она есть) до сих пор нигде не сообщалось и не обсуждалось.
Некоторые замечания
Во-первых, Firefox не демонстрирует такого странного поведения.
Чтобы не быть неправильно понятым, ясно, что, когда я выхожу из поля выбора, я перехожу к вводу с tabindex 3, потому что асинхронный код в обработчике onchange, возможно, еще не был выполнен. Но после этого (когда текст в первом вводе изменился) я ожидаю, что будет установлен новый порядок табуляции. Так себя ведет FF.
Кажется, что IE уже запускает событие onchange каждый раз, когда я использую клавишу со стрелкой вверх / вниз, а не когда я выхожу из поля выбора (как это делает FF). Я не уверен, связано ли это с проблемой.
Добавлен бонус: если вы откроете инструменты разработчика IE, вы увидите, что атрибут tabIndex установлен правильно в DOM, также при изменении значения поля выбора без мыши. Но tabindex игнорируется при переходе по табуляции.
Мое (наивное) предположение состоит в том, что IE сохраняет внутреннее представление taborder и что это внутреннее представление не пересчитывается правильно в этом случае.
Еще одна странность: вы можете удалить строки 5 и 9 этого файла (вызов setTimeout и закрывающая фигурная скобка), чтобы изменение tabindex больше не вызывалось асинхронно. Затем он будет работать правильно, если вы введете выделение с помощью мыши и оставите его, выполнив табуляцию. Он по-прежнему ломается, если вы перейдете к выбору, измените значение с помощью клавиши со стрелкой и табуляции.