Так приятно найти краткие руководства по срыву проблем веб-разработки, которые являются обычным явлением, но плохо документированы или их легко найти. Сегодня я нашел ответ на SO о разработке JavaScript для Firefox и IE, который может быть очень полезным для многих людей, если они смогут его найти. Я помещаю его в зону Web Builder, так что, надеюсь, его найдут другие веб-разработчики. Ответом стала вики сообщества, отредактированная
Дэвидом Моррисси ,
Марселем Корпелем ,
Крозиным и
Матиасом Биненсом . Остальная часть этого поста — вся их хорошая работа:
Примечание:IE9 устраняет многие из следующих проблем, поэтому многое из этого применимо только к IE8 и ниже и в определенной степени к IE9 в режиме причуд. Например, IE9 изначально поддерживает SVG, <canvas>, <audio> и <video>, однако для их доступности необходимо включить режим соответствия стандартам.
Генеральная:
-
Проблемы с частично загруженными документами. Рекомендуется добавить свой JavaScript в window.onload или подобное событие, так как IE не поддерживает много операций в частично загруженных документах.
-
Отличающиеся атрибуты : в CSS это elm.style.styleFloat в IE против elm.style.cssFloat в Firefox. В тегах <label> доступ к атрибуту for осуществляется с помощью elm.htmlFor в IE против elm.for в Firefox. Обратите внимание, что for зарезервировано в IE, поэтому elm [‘for’], вероятно, является лучшей идеей, чтобы не дать IE вызвать исключение.
Базовый язык JavaScript:
-
Доступ к символам в строках : ‘string’ [0] не поддерживается в IE, поскольку это не входит в исходные спецификации JavaScript. Используйте ‘string’.charAt (0) или’ string’.split (») [0], отметив, что массивы значительно быстрее, чем строки в IE.
-
Запятые перед концом объектов: например, {‘foo’: ‘bar’,} не допускаются в IE.
Вопросы, связанные с элементами:
-
Получение документа IFrame :
- Firefox: IFrame.contentWindow.document
- IE: IFrame.contentDocument
- (IFrame.contentWindow ссылается на окно в обоих браузерах.)
-
Canvas: версии IE до IE9 не поддерживают элемент <canvas>. Однако IE поддерживает VML, который является аналогичной технологией, и explorercanvas может предоставить встроенную оболочку для элементов <canvas> для многих операций. Имейте в виду, что IE8 в режиме соответствия стандартам в 10 раз медленнее и имеет гораздо больше сбоев, чем в режиме совместимости при использовании VML.
-
SVG: IE9 изначально поддерживает SVG. IE6-8 может поддерживать SVG, но только с внешними плагинами, причем только некоторые из этих плагинов поддерживают манипулирование JavaScript.
-
<audio> и <video>: поддерживаются только в IE9.
-
Динамическое создание переключателей: в IE <8 есть ошибка, из-за которой переключатели, созданные с помощью document.createElement, не проверяются. См. Также Как динамически создать переключатель в Javascript, который работает во всех браузерах? для способа обойти это.
-
Встроенный JavaScript в тегах <a href> и конфликтах onbeforeunload в IE: если в теге href есть встроенный JavaScript (например, <a href=»javascript: doStuff()»>, то IE всегда будет отображать сообщение, возвращенное из onbeforeunload если обработчик onbeforeunload не будет удален заранее, см. также функцию Javascript на закрытии веб-страницы .
-
Отличия событий тега <script>: onsuccess и onerror не поддерживаются в IE и заменяются специфичным для IE onreadystatechange, который запускается независимо от того, удалась загрузка или не удалась. Смотрите также JavaScript Madness для получения дополнительной информации.
Размер элемента / положение / прокрутка и положение мыши:
-
Получение размера / позиции элемента : ширина / высота элементов иногда равна elm.style.pixelHeight / Width в IE, а не elm.offsetHeight / Width, но ни один из них не является надежным в IE, особенно в режиме причуд, и иногда один дает лучший результат, чем другой.
elm.offsetTop и elm.offsetLeft часто сообщаются неверно, что приводит к нахождению неправильных позиций элементов, поэтому всплывающие элементы и т. д. во многих случаях отключаются на несколько пикселей.
Также обратите внимание, что если элемент (или родитель элемента) не имеет ни одного отображения, IE будет вызывать исключение при доступе к атрибутам размера / позиции, а не возвращать 0, как это делает Firefox.
-
Получить размер экрана (получение видимой области экрана):
- Firefox: window.innerWidth / innerHeight
- Режим стандартов IE: document.documentElement.clientWidth / clientHeight
- IE причудливый режим: document.body.clientWidth / clientHeight
-
Положение прокрутки документа / положение мыши : это на самом деле не определено w3c, поэтому является нестандартным даже в Firefox. Чтобы найти scrollLeft / scrollTop документа:
- Firefox и IE в режиме причуд: document.body.scrollLeft / scrollTop
- IE в стандартном режиме: document.documentElement.scrollLeft / scrollTop
-
ПРИМЕЧАНИЕ. Некоторые другие браузеры также используют pageXOffset / pageYOffset.
function getDocScrollPos() { var x = document.body.scrollLeft || document.documentElement.scrollLeft || window.pageXOffset || 0, y = document.body.scrollTop || document.documentElement.scrollTop || window.pageYOffset || 0; return [x, y]; };<span class="kwd"></span><span class="pun"></span><span class="pln"> </span>
Чтобы получить позицию курсора мыши, evt.clientX и evt.clientY в событиях mousemove будут указывать позицию относительно документа без добавления позиции прокрутки, поэтому необходимо будет включить предыдущую функцию:
var mousepos = [0, 0]; document.onmousemove = function(evt) { evt = evt || window.event; if (typeof evt.pageX != 'undefined') { // Firefox support mousepos = [evt.pageX, evt.pageY]; } else { // IE support var scrollpos = getDocScrollPos(); mousepos = [evt.clientX+scrollpos[0], evt.clientY+scrollpos[1]]; }; };<span class="kwd"></span><span class="pun"></span><span class="pln"> </span>
Выбор / диапазонов:
-
<textarea> и <input> selections : selectionStart и selectionEnd не реализованы в IE, и на их месте есть проприетарная система «диапазонов», см. также Как получить позицию курсора в textarea? ,
-
Получение текущего выделенного текста в документе:
- Firefox: window.getSelection (). ToString ()
- IE: document.selection.createRange (). Text
Получение элементов по ID:
-
document.getElementById также может ссылаться на атрибут name в формах (в зависимости от того, что определено первым в документе), поэтому не используйте разные элементы с одинаковыми именами и идентификаторами! Это восходит к тем дням, когда id не был стандартом w3c. document.all значительно быстрее, чем document.getElementById, но это еще более неприятно, так как он всегда расставляет приоритеты имени перед id. Я лично использую этот быстрый «гибридный» код, прибегая к дополнительным проверкам, чтобы быть уверенным:
function getById(id) { var e; if (document.all) { e = document.all[id]; if (e && e.tagName && e.id === id) { return e; }; }; e = document.getElementById(id); if (e && e.id === id) { return e; } else if (!e) { return null; } else { throw 'Element found by `name` instead of `id`: ' + id; }; };<span class="kwd"></span><span class="pun"></span><span class="pln"> </span>
Проблемы с доступом только для чтения innerHTML:
-
IE не поддерживает установку innerHTML элементов table, tbody, tfoot, thead и tr. Вот функция, которая работает вокруг этого:
function setHTML(elm, html) { // Try innerHTML first try { elm.innerHTML = html; } catch (exc) { // IE 6-8 don't support setting innerHTML for // TABLE, TBODY, TFOOT, THEAD, and TR directly var tn = elm.tagName.toLowerCase(); if (tn === 'table') { replace(getElm('<table>' + html + '</table>')); } else if (tn in {tbody:0, tfoot:0, thead:0}) { replace(getElm('<table><tbody>' + html + '</tbody></table>').firstChild); } else if (tn === 'tr') { replace(getElm('<table><tbody><tr>' + html + '</tr></tbody></table>').firstChild.firstChild); } else { throw exc; }; function getElm(html) { // Create a new element and return the first child var e = document.createElement('div'); e.innerHTML = html; return e.firstChild; }; function replace(elms) { // Remove the old elements from `elm` var x = elm.children.length, y = 0, c; while (c = elm.children[--x]) { elm.removeChild(c); }; // Add the new elements from `elms` to `elm` while (c = elms.children[y++]) { elm.appendChild(c); }; }; }; };
Также обратите внимание, что IE требует добавления <tbody> в <table> перед добавлением <tr> к этому элементу <tbody> при создании с использованием document.createElement, например:
var table = document.createElement('table'); var tbody = document.createElement('tbody'); var tr = document.createElement('tr'); var td = document.createElement('td'); table.appendChild(tbody); tbody.appendChild(tr); tr.appendChild(td); // and so on<span class="kwd"></span><span class="com"></span><span class="pln"> </span>
Различия в событиях:
-
Получение переменной события: события DOM не передаются функциям в IE и доступны как window.event. Один из распространенных способов получения события — использовать, например,
elm.onmouseover = function (evt) {evt = evt || window.event},
который по умолчанию равен window.event, если evt не определено. -
Основные различия в кодах событий: Коды ключевых событий сильно различаются, хотя, если вы посмотрите на Quirksmode или JavaScript Madness , вряд ли они специфичны для IE, Safari и Opera снова различаются.
-
Различия в событиях мыши: атрибут кнопки в IE является бит-флагом, который позволяет использовать несколько кнопок мыши одновременно:
- Слева: 1 (var isLeft = evt.button & 1)
- Справа: 2 (var isRight = evt.button & 2)
-
Центр: 4 (var isCenter = evt.button & 4)
Модель W3C (поддерживаемая Firefox) является менее гибкой, чем модель IE: допускается одновременное использование только одной кнопки: слева 0, справа 2 и центр 1. Обратите внимание, что, как упоминает Питер-Пол Кох , это очень нелогично, так как 0 обычно означает «нет кнопки».
offsetX и offsetY проблематичны, и, вероятно, лучше избегать их в IE. Более надежный способ получить offsetX и offsetY в IE — получить позицию относительно позиционированного элемента и вычесть его из clientX и clientY.
Также обратите внимание, что в IE, чтобы получить двойной щелчок в событии click, вам нужно зарегистрировать и функцию click, и событие dblclick для функции. Firefox запускает как щелчок, так и dblclick при двойном щелчке, поэтому для такого же поведения необходимо специфическое для IE обнаружение.
-
Различия в модели обработки событий: как собственная модель IE, так и модель Firefox поддерживают обработку событий снизу вверх, например, если есть события в обоих элементах <div> <span> </ span> </ div> then events будет вызывать в промежутке, а не div, а не порядок, в котором они связаны, если используется традиционный, например, elm.onclick = function (evt) {}.
События «захвата», как правило, поддерживаются только в Firefox и т. Д., Что вызывает события div и span в порядке сверху вниз. В IE есть elm.setCapture () и elm.releaseCapture () для перенаправления событий мыши из документа в элемент (в данном случае, elm) перед обработкой других событий, но они медленные и обычно их следует избегать.
-
Fire Fox:
Приложить : elm.addEventListener (тип, слушатель, useCapture [истина / ложь])
Отделить : elm.removeEventListener (тип, слушатель, useCapture)
(тип , например , ‘Mouseover’ без на) -
IE: в IE можно добавить только одно событие данного типа для элемента — исключение возникает, если добавлено более одного события одного типа. Также обратите внимание, что this относится к окну, а не к связанному элементу в функциях событий (так что это довольно бесполезно):
Приложить : elm.attachEvent (Sevent, fpNotify)
Отделить : elm.detachEvent (Sevent, fpNotify)
(Sevent является , например , ‘OnMouseOver’)
-
-
Отличия атрибутов события:
-
Остановить события от обработки любыми другими функциями прослушивания :
Firefox: evt.stopPropagation ()
IE: evt.cancelBubble = true -
Остановить, например, ключевые события от вставки символов или остановки проверки флажков:
Firefox: evt.preventDefault ()
IE: evt.returnValue = false
Примечание. Просто возвращая значение false при нажатии клавиш, нажатие клавиши, mousedown, mouseup, щелчок и сброс также будет предотвращать использование по умолчанию. -
Получите элемент, который вызвал событие:
Firefox: evt.target
IE: evt.srcElement -
Получение элемента, от которого курсор мыши отошел от: evt.fromElement в IE, — это evt.target в Firefox, если в событии onmouseout, в противном случае evt.relatedTarget
-
При получении элемента курсор мыши перемещается в: evt.toElement в IE — это evt.relatedTarget в Firefox, если в событии onmouseout, в противном случае evt.target
-
Примечание: evt.currentTarget (элемент, с которым было связано событие) не имеет эквивалента в IE.
-
Большая часть этой страницы воспроизводится из
этого ответа, созданного и переданного в
Stack Overflow и используемого в соответствии с условиями, описанными в
Лицензии на атрибуцию Creative Commons 3.0 .