Каковы типичные причины, по которым Javascript, разработанный в Firefox, терпит неудачу в IE?

Я разработал несколько улучшенных страниц javascript, которые отлично работают на последних Firefox и Safari. Я пропустил проверку в Internet Explorer, и теперь я считаю, что страницы не работают на IE 6 и 7 (пока). Сценарии каким-то образом не выполняются, страницы показывают, что javascript там не был, хотя выполняется какой-то javascript. Я использую собственные библиотеки с манипуляцией dom, из YUI 2 я использую YUI-Loader и XML-Http-Request, а на одной странице я использую "psupload", что зависит от JQuery.

Я устанавливаю Microsoft Script Editor из Office XP и теперь отлаживаю. Я также буду писать конкретные тесты.

Каковы типичные точки отказа IE? В каком направлении я могу держать глаза открытыми.

Я нашел эту страницу, которая показывает некоторые отличия. посетите: Quirksmode

Можете ли вы по своему опыту назвать некоторые типичные вещи, которые я должен искать в первую очередь?

Далее я задам дополнительные вопросы для конкретных задач, но на данный момент меня интересует ваш опыт, почему IE обычно терпит неудачу в сценариях, которые отлично работают в Firefox

Редактировать: Спасибо за все эти замечательные ответы!

Тем временем я адаптировал весь код, чтобы он также работал с Internet Explorer. Я интегрировал jQuery и теперь создал свои собственные классы. Это была моя основная ошибка, что с самого начала я не собирал все свои вещи на jQuery. Теперь у меня есть.

Также JSLint мне очень помог.

И многие из отдельных вопросов из разных ответов помогли.

Ответ 1

Пожалуйста, не стесняйтесь обновлять этот список, если вы видите ошибки/упущения и т.д.

Примечание. IE9 устраняет многие из следующих проблем, поэтому многие из них относятся только к IE8 и ниже, а также к IE7 в режиме quirks. Например, IE9 поддерживает SVG, <canvas>, <audio> и <video> изначально, однако вы должны включить режим соблюдения стандартов для них быть доступным.


Общие:

  • Проблемы с частично загруженными документами:. Хорошая идея добавить JavaScript в window.onload или подобное событие, поскольку IE не поддерживает много операций в частично загруженных документах.

  • Различные атрибуты. В CSS это elm.style.styleFloat в IE vs elm.style.cssFloat в Firefox. В тегах <label> к атрибуту for обращается с помощью elm.htmlFor в IE vs elm.for в Firefox. Обратите внимание, что for зарезервировано в IE, поэтому elm['for'], вероятно, является лучшей идеей остановить IE от создания исключения.


Основной язык JavaScript:

  • Доступ к символам в строках: 'string'[0] не поддерживается в IE, поскольку он не соответствует исходным спецификациям JavaScript. Используйте 'string'.charAt(0) или 'string'.split('')[0], отмечая, что доступ к элементам в массивах значительно быстрее, чем использование charAt со строками в IE (хотя при первом вызове split есть некоторые начальные накладные расходы).

  • Запятые до конца объектов:. {'foo': 'bar',} в IE не разрешены.


Вопросы, связанные с элементом:

  • Получение document IFrame:

    • Firefox и IE8 +: IFrame.contentDocument (IE начал поддерживать этот с версии 8.)
    • IE: IFrame.contentWindow.document
    • (IFrame.contentWindow относится к window в обоих браузерах.)

  • Canvas: Версии IE до IE9 не поддерживают элемент <canvas>. IE поддерживает VML, который аналогичен технологии, и explorercanvas может предоставить оболочку на месте для элементов <canvas> для многих операций. Имейте в виду, что IE8 в режиме соблюдения стандартов во много раз медленнее и имеет гораздо больше сбоев, чем в режиме quirks при использовании VML.

  • SVG: IE9 поддерживает SVG изначально. IE6-8 может поддерживать SVG, но только с внешние плагины только с некоторыми из этих плагинов, поддерживающих JavaScript-манипуляцию.

  • <audio> и <video>: поддерживаются только в IE9.

  • Динамическое создание переключателей: У IE < 8 есть ошибка, которая делает переключатели, созданные с помощью document.createElement неконтролируемой. См. Также Как вы динамически создаете переключатель в Javascript, который работает во всех браузерах?, чтобы обойти это.

  • Встроенный JavaScript в тегах <a href> и onbeforeunload конфликты в IE: Если встроенный JavaScript в теге href тега a (например, <a href="javascript: doStuff()">) IE всегда будет отображать сообщение, возвращенное из onbeforeunload, если обработчик onbeforeunload не будет удален заранее. См. Также Запросить подтверждение при закрытии вкладки.

    /li >
  • <script> различия между тегами: onsuccess и onerror не поддерживаются в IE и заменяются IE-специфическим onreadystatechange, который запускается независимо от того, загрузка прошла успешно или не удалась. См. Также JavaScript Madness для получения дополнительной информации.


Размер элемента/положение/прокрутка и положение мыши:

  • Получение размера элемента/позиции: ширина/высота элементов иногда elm.style.pixelHeight/Width в IE, а не elm.offsetHeight/Width, но ни одна из них не является надежной в IE, особенно в режиме quirks, и иногда один дает лучший результат, чем другой.

    elm.offsetTop и elm.offsetLeft часто сообщаются неправильно, что приводит к неверному определению позиций элементов, поэтому во многих случаях во всплывающих панелях и т.д. несколько пикселей.

    Также обратите внимание, что если элемент (или родительский элемент) имеет display of none, тогда IE будет вызывать исключение при доступе к атрибутам size/position, а не возвращать 0, как это делает Firefox.

  • Получить размер экрана (получение области видимости экрана):

    • Firefox: window.innerWidth/innerHeight
    • Режим стандартов IE: document.documentElement.clientWidth/clientHeight
    • Режим IE quirks: document.body.clientWidth/clientHeight

  • Позиция прокрутки документа/позиция мыши. Этот файл на самом деле не определен w3c, поэтому он нестандартен даже в Firefox. Чтобы найти scrollLeft/scrollTop document:

    • Firefox и IE в режиме quirks: 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];
      };
      

    Чтобы получить позицию курсора мыши, события 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]];
     };
    };
    

Выбор/диапазонов:

  • <textarea> и <input> выборы: selectionStart и selectionEnd не реализованы в IE, и вместо этого на их месте имеется собственная система "диапазонов", см. также Позиция Caret в textarea, в символах с начала.

  • Получение текущего текста в документе:

    • Firefox: window.getSelection().toString()
    • IE: document.selection.createRange().text


Получение элементов по ID:

  • document.getElementById также может ссылаться на атрибут name в формах (в зависимости от того, что определено вначале в документе), поэтому лучше не иметь разных элементов, которые имеют те же name и id. Это относится ко времени, когда id не был стандартом w3c. document.all (проприетарное свойство, специфичное для IE) значительно быстрее, чем document.getElementById, но у него есть другие проблемы, так как он всегда выделяет приоритет name до 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;
     };
    };
    

Проблемы только с чтением innerHTML:

  • IE не поддерживает установку innerHTML из col, colGroup, frameSet, html, head, style, table, tBody, tFoot, tHead, title и tr. Здесь функция, которая работает вокруг этого для связанных с таблицами элементов:

    function setHTML(elm, html) {
     // Try innerHTML first
     try {
      elm.innerHTML = html;
     } catch (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'
       while (elm.children.length) {
        elm.removeChild(elm.firstChild);
       }
       // Add the new elements from 'elms' to 'elm'
       for (var x=0; x<elms.children.length; x++) {
        elm.appendChild(elms.children[x]);
       };
      };
      // 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 (['tbody', 'tfoot', 'thead'].indexOf(tn) != -1) {
       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;
      };
     };
    };
    

    Также обратите внимание, что 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
    

Различия в событиях:

  • Получение переменной event: DOM-события не передаются в функции IE и доступны как window.event. Одним из распространенных способов получения события является использование, например,
    elm.onmouseover = function(evt) {evt = evt||window.event}
    который по умолчанию равен window.event, если evt равен undefined.

  • Различия в ключевых событиях кода: Коды ключевых событий сильно различаются, но если вы посмотрите на Quirksmode или JavaScript Madness, это вряд ли специфично для IE, Safari и Opera отличаются друг от друга.

  • Различия в событиях мыши: атрибут button в 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. Обратите внимание, что, как упоминает Peter-Paul Koch , это очень противоречиво, поскольку 0 обычно означает "нет кнопки".

      offsetX и offsetY являются проблематичными, и, вероятно, лучше избегать их в IE. Более надежный способ получить offsetX и offsetY в IE будет получить позицию относительно позиционированного элемента и вычесть его из clientX и clientY.

      Также обратите внимание, что в IE для двойного щелчка в событии click вам необходимо зарегистрировать событие click и dblclick для функции. Firefox срабатывает click, а также dblclick при двойном щелчке, поэтому для определения того же поведения требуется определение, специфичное для IE.

  • Различия в модели обработки событий:И проприетарная модель IE, и модель Firefox поддерживают обработку событий снизу вверх, например. если есть события в обоих элементах <div><span></span></div>, тогда события будут запускаться в span, затем в div, а не в порядке, который они связаны, если традиционный, например, elm.onclick = function(evt) {}.

    События "Capture" обычно поддерживаются только в Firefox и т.д., Которые вызывают события div и span в порядке сверху вниз. IE имеет elm.setCapture() и elm.releaseCapture() для перенаправления событий мыши из документа в элемент (elm в этом случае) перед обработкой других событий, но у них есть ряд характеристик производительности и других проблем, поэтому, вероятно, этого следует избегать.

    • Firefox:

      Прикрепить: elm.addEventListener(type, listener, useCapture [true/false])
      Отсоединить: elm.removeEventListener(type, listener, useCapture)
      (type является, например, 'mouseover' без on)

    • IE: В IE может быть добавлено только одно событие определенного типа в элементе - исключение возникает, если добавлено более одного события того же типа. Также обратите внимание, что this относится к window, а не к связанному элементу в функциях событий (поэтому менее полезно):

      Прикрепить: 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 в keydown, keypress, mousedown, mouseup, click и reset также предотвратит по умолчанию.

    • Получить элемент, вызвавший событие:

      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.

Ответ 2

Проверьте также запятые, такие как эти или подобные, если они есть в вашем коде

var o={
'name1':'value1',
'name2':'value2',
} 

последняя запятая (следующее значение2) будет допущена Firefox, но не IE

Ответ 3

Если вы придерживаетесь использования jQuery или YUI, поскольку ваше сообщение помечено, вы должны иметь минимальные различия между браузерами... для чего нужны рамки, чтобы заботиться об этих различиях между браузерами для вас.

В качестве примера рассмотрим страницу quirksmode DOM traversal, согласно которой IE не поддерживает большинство вещей... в то время как true, фреймворки делают, например, IE не поддерживает elem.childElementCount, но в jQuery: $(elem).children().size() работает, чтобы получить это значение в каждом браузере. Вы найдете там что-то в библиотеке, чтобы обрабатывать 99% неподдерживаемых случаев в браузерах, по крайней мере, с помощью script... с CSS, возможно, вам придется перейти к плагинам для библиотеки, общий пример этого - получить закругленные углы, работающие в IE... поскольку у него нет поддержки CSS для таких.

Если вы начинаете делать что-то прямо, например document.XXX(thing), то вы не в библиотеке, вы делаете javascript напрямую (весь javascript, но вы получаете точку:), и это может или не может вызывают проблемы, в зависимости от того, насколько пьяна команда IE при реализации этой конкретной функции.

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

Ответ 4

getElementbyID также будет сопоставляться с атрибутом name в IE, но не с другими браузерами, а IE выберет тот, который он найдет первым.

Пример:

<script>
 var foo = document.getElementById('bar');
</script>

....
<input name="bar" type="text" />  //IE will get this element
<span id="bar"> Hello, World! </span>  //FF,Safari,Chrome will get this element

Ответ 5

Есть много вещей, но одна ловушка, которую я использовал, заключалась в том, что многие браузеры принимают JSON без цитируемых имен, тогда как ie6 и ie7 этого не делают.

{ name: "Jakob" } // will often work, but not in ie6/ie7
{ "name": "Jakob" } // Better!

Изменить. Чтобы уточнить, это только проблема, когда требуется фактический JSON, в отличие от литерала объекта. JSON является подмножеством синтаксиса литерала объекта и подразумевается как формат обмена данными (например, XML), поэтому он предназначен для выбора.

Ответ 6

Различная поддержка JavaScript

IE не поддерживает (большинство) расширений, добавленных в JavaScript с версии 1.5.

Новое в версии 1.6

  • Методы массива - indexOf(), lastIndexOf(), every(), filter(), forEach(), map(), some()
  • for each ... in - итерации значений вместо имен свойств.

Новое в 1.7

Новое в 1.8

  • Методы массива - reduce(), reduceRight()
  • Ярлыки для определения функций.

Некоторые из этих вещей требуют от вас указать номер версии JavaScript для запуска (который будет разбит под IE), но некоторые вещи, такие как [1,2,3].indexOf(2), могут показаться не такими большими сделками, пока вы не попытаетесь запустить его в IE

Ответ 7

Основные различия между JavaScript в IE и JavaScript в современных браузерах (например, Firefox) можно отнести к тем же причинам, что и различия в CSS/(X) HTML-перекрестном браузере. Еще в тот день не было стандартного де-факто; IE/Netscape/Opera сражались с торфяной войной, реализуя большинство спецификаций, но также опуская некоторые, а также делая проприетарные спецификации для получения преимуществ друг перед другом. Я мог бы продолжить подробно, но позволяет перейти к выпуску IE8: JavaScript избегали/презирали в течение многих лет, а с ростом FF и неуважением к webcomm IE решил сосредоточиться в основном на продвижении своих CSS с IE6. И в основном оставил поддержку DOM. Поддержка IE8 DOM также может быть IE6, которая развернулась в 2001 году.... поэтому поддержка IE DOM почти десятилетие отстает от современных браузеров. Если у вас есть расхождения JavaScript, характерные для механизма компоновки, лучше всего нападать на него так же, как и на проблемы CSS; Ориентация на этот браузер. НЕ ИСПОЛЬЗУЙТЕ СЪЕМКУ BROWSER, используйте функцию обнаружения, чтобы вынюхать ваш браузер/уровень поддержки DOM.

JScript не является IE собственной реализацией ECMAScript; JScript был ответом IE на Netscape JavaScript, оба из которых появились до ECMAScript.

В отношении атрибутов типа в элементе script type = "text/javascript" является стандартом по умолчанию (по крайней мере, в HTML5), поэтому вам не нужен атрибут типа, если ваш script isn ' t JavaScript.

Поскольку IE не поддерживает innerHTML... innerHTML был изобретен IE и до сих пор не является стандартом DOM. Другие браузеры приняли это, потому что это полезно, поэтому вы можете использовать его в кросс-браузере. Что касается динамически изменяющихся таблиц, MSDN говорит "из-за конкретной структуры, требуемой таблицами, innerText и innerHTML свойства таблицы и tr-объекты доступны только для чтения." Я не знаю, сколько изначально было правдой, но, очевидно, современные браузеры разобрались в этом, имея дело со сложностями табличного макета.

Я очень рекомендую читать PPK на JavaScript Джереми Кейт DOM Scripting Douglas Crockford JavaScript: хорошие детали и Христиан Хеллман. Начало JavaScript с DOM Scripting и Ajax, чтобы получить сильное представление о JavaScript.

Что касается рамок/библиотек, если у вас пока нет сильного понимания JavaScript, вы должны их избегать. 2 года назад я попал в ловушку jQuery, и, хотя мне удалось снять великолепные подвиги, я никогда не узнал про чертовски правильное кодирование JavaScript. Оглядываясь назад, jQuery - злой удивительный инструмент DOM Toolkit, но моя неудача узнать правильные закрытия, прототипное наследование и т.д. Не только вернула мои личные знания, но и моя работа начала принимать огромные хиты производительности, потому что у меня не было никакой подсказки, которую я делал.

JavaScript - это язык браузера; если вы являетесь специалистом на стороне клиента/фронт-менеджером, вам крайне важно, чтобы вы выполняли JavaScript. Node.js привносит JavaScript с полным наклоном, я вижу огромные успехи, предпринимаемые ежедневно в его разработке; Серверный JavaScript будет стандартом в самом ближайшем будущем. Я упоминаю об этом, чтобы еще раз подчеркнуть, насколько важен JavaScript и будет.

JavaScript будет делать больше волн, чем Rails.

Счастливые сценарии!

Ответ 8

Трейлинг-запятые в массивах и объектных литералах были проблемой, недавно не проверялись (что означает IE8):

var a = [ 1, 2, 3, ];
var o = { a:1, b:2, c:3, };

Это приведет к появлению некоторого дополнительного кода при создании таких структур на стороне сервера.

Ответ 9

Некоторые собственные объекты доступны только для чтения, но не кажутся такими (вы можете писать им, но это не имеет никакого эффекта). Например, общий расширенный javascript основан на расширении объекта Element, переопределяя системные методы, скажем, изменяя Element.prototype.appendChild(), чтобы делать больше, чем добавлять дочерний элемент node - скажем, инициализировать его родительскими данными. Это не сработает на IE6 - исходный метод будет вызываться для новых объектов вместо нового.

Некоторые браузеры (я не помню, что сейчас) рассматривают новые строки между тегами HTML как текстовые узлы, а другие - нет. Таким образом, childNodes (n), nextSibling(), firstChild() и т.д. Будут вести себя по-разному.

Ответ 10

Я только что нашел это утром, сотрудник установил тег script как: <script type="application/javascript">, потому что у его автозаполнения было то, что перед "text/javascript"

Но, оказывается, IE просто игнорирует весь script, если вы используете "application/javascript", вам нужно использовать "text/javascript"

Ответ 11

На днях я обнаружил странную причуду с Internet Explorer. Я использовал YUI и заменил содержимое тела таблицы(), установив innerHTML

Y.one('#elementId').set('innerHTML', '<tr><td>Column 1</td></tr>');

Это будет работать во всех браузерах EXCEPT IE. Наконец я обнаружил, что вы не можете заменить innerHTML таблицы в IE. Мне пришлось создать node с помощью YUI, а затем добавить node.

var myNode = Y.node.create('<tr><td>Column 1</td></tr>');
Y.one('#elementId').append(myNode);

Это было весело, чтобы понять!

Ответ 12

Дополнительные запятые и отсутствующие запятые были обычной проблемой для IE, когда она работает плавно на FF.

Ответ 13

IE очень строг в отношении отсутствия ";" так обычно бывает.

Ответ 14

Для чего это стоило, я просто наткнулся на эту неприятную проблему в < IE9

скажем, у вас есть html, как это:

<table><tr><td>some content...</td></tr></table>

и по какой-то причине (у меня был хороший) вам нужно получить все HTML в таблице до последнего закрытия TR, вы можете попробовать что-то вроде этого:

var tableHtml = document.getElementById('thetable').innerHTML;
var fragment = tableHtml.substring(0, tableHtml.lastIndexOf('</tr>'));

< IE9 ничего не вернет (-1), потому что переменная tableHtml содержит все html-теги с верхним расположением, а lastIndexOf чувствителен к регистру. Чтобы обойти это, я должен был вставить toLowerCase() до lastIndexOf.

Ответ 15

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

Ответ 16

Вы упомянули jQuery, с которым я менее знаком, но для общей ссылки, и в частности с Prototype, одна вещь, на которую нужно обратить внимание, - это зарезервированные слова/имена методов в IE. Я знаю, что часто получает меня, это такие вещи, как:

someElement.appendChild(new Element('label',{ **for**: someInput.id }).update( someLabelText );

(новый элемент (tagName, propertyHash) - это то, как в Protitype создаются новые элементы). В IE for: должен быть 'for':, потому что for является зарезервированным словом. Что имеет смысл, но FireFox будет терпеть это.

Другой пример:

someElement.wrap('div').addClassName('someClass')

(метод wrap в Prototype обертывает один элемент в другом). В IE, в textareas, wrap является свойством, а Element.wrap() следует использовать вместо методической версии

Это два примера, которые приходят мне в голову из моего опыта. Они основаны на прототипе, но основная проблема не такова: следите за любыми методами/ярлыками/идентификаторами, которые IE считает зарезервированными словами, но FireFox или Safari будут терпеть.

Ответ 17

Дело в том, что IE не поддерживает JavaScript... Он поддерживает собственную реализацию ECMAScript: JScript..., который является своего рода...

Ответ 18

Использование console.log() для вывода ошибок в консоль ошибок Firefox приведет к сбою ваших сценариев в IE. Не забудьте взять их, когда вы тестируете в IE.