Статьи

ObjectSwap: обход проблемы активации ActiveX в IE

Недавнее решение Microsoft изменить способ обработки объектов ActiveX в Internet Explorer, следуя иску EOLAS о патентном праве, создало серьезную проблему для сообщества разработчиков.

Все элементы управления ActiveX в Internet Explorer, включая Flash и Shockwave, необходимо активировать щелчком мыши (или нажатием клавиши Tab и клавиши Enter), прежде чем пользователь сможет взаимодействовать с элементом управления. Это неизбежно ухудшит взаимодействие с пользователем любого веб-сайта, на котором встроен Flash, и разработчики Flash и HTML должны устранить проблему.

Доступные решения

Вы можете обойти требование активации, используя сценарий с внешней связью, такой как JavaScript, для встраивания содержимого ActiveX. В настоящее время доступны решения для Flash, такие как FlashObject и UFO .

Они хорошо работают для встраивания нового содержимого Flash с использованием JavaScript. Но как насчет существующих тегов объектов, которые нужно будет переписать, или браузеров с отключенным JavaScript? Эти ситуации требуют альтернативного решения.

ObjectSwap

Решение ObjectSwap, представленное в этой статье, учитывает все эти проблемы. Он захватывает все существующие теги объектов и заменяет их на … самих себя. Это вызывает автоматическую активацию в Internet Explorer, оставляя другие браузеры в покое. Подобные решения были разработаны параллельно, но эта статья будет касаться только ObjectSwap.

Хотя это решение было разработано в первую очередь с учетом Flash, оно также должно работать с другими элементами управления ActiveX, такими как Shockwave. Сценарий влияет на все теги объектов на странице, но разработчик может исключить конкретный объект, установив для его имени класса значение «noswap».

Реализация

ObjectSwap был написан с целью сделать реализацию максимально простой, с минимальным нарушением существующего кода. Единственное изменение, которое вам нужно внести в свою HTML-страницу, — это связать скрипт в <head> для каждой страницы, содержащей объекты ActiveX, например:

 <script type="text/javascript" src="objectSwap.js"> </script> 

Как только вы это сделаете, вы можете продолжать использовать свой любимый метод для встраивания содержимого ActiveX. Для Flash это означает либо настройку Adobe / Macromedia по умолчанию с использованием тегов объекта / встраивания, либо совместимую со стандартами методику, которая использует только тег объекта (более известный как Flash Satay ).

Обнаружение вспышки

Все идет нормально. Но так как мы уже используем JavaScript, почему бы не воспользоваться возможностью добавить в микс Flash-детекцию? Мы можем добиться этого, добавив новое определение параметра в объект Flash, например:

 <param name="flashVersion" value="7" /> 

Скрипт ищет этот param и, если он существует, преобразует объект в div который отображает альтернативное содержимое. Это содержимое не создается сценарием, но вместо этого уже должно находиться внутри тега объекта и отображать альтернативный текст, изображения, ссылки на установщик Flash и т. Д. Internet Explorer обычно игнорирует этот контент, если присутствует Flash. Это также верно для других браузеров, когда вы используете метод Flash Satay, так что вы можете просто добавить содержимое в любом месте тела объекта.

С другой стороны, если используется метод object / embed, браузеры на основе Gecko, такие как Firefox и Netscape, будут отображать альтернативный контент вместе со встроенным фильмом. Решение состоит в том, чтобы заключить содержимое в комментарии HTML, которые будут удалены сценарием при отображении содержимого. Между тегами комментариев и содержимым должен быть пробел или разрыв строки, чтобы избежать конфликтов с любыми условными комментариями IE, которые оказываются внутри тега объекта:

 <!--  <p>You need <a href= "http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash">Flash</a> to view this content.</p>  --> 

Конечно, вы также можете игнорировать опцию обнаружения Flash или использовать экспресс-установку Adobe для Flash 8.

Поддержка браузера

Проблема активации объектов ActiveX затрагивает только Internet Explorer, поэтому большая часть кода также затрагивает только IE. Однако код обнаружения Flash должен работать и с другими браузерами. Это означает, что функция objectSwap будет вызываться для всех браузеров для выполнения службы обнаружения Flash, если это необходимо, но будет только выполнять обмен объектов в IE, оставляя другие браузеры без изменений.
Это все, что вам нужно знать, чтобы начать использовать скрипт. Вы можете скачать скрипт и примеры здесь .

Однако, если вы хотите узнать больше о том, как работает ObjectSwap, в следующих разделах будет раскрыта внутренняя работа скрипта.

Как это устроено

Во-первых, скрипт циклически перебирает все теги объектов в исходном коде HTML и извлекает их значения outerHTML:

 var objects = document.getElementsByTagName('object');  for (var i=0; i<objects.length; i++) {  var o = objects[i];  var h = o.outerHTML; 

Поскольку Internet Explorer не включает какие-либо теги param объекта в свой outerHTML (или innerHTML ), их необходимо извлекать отдельно в строку:

 var params = "";  for (var j = 0; j<o.childNodes.length; j++) {  var p = o.childNodes[j];  if (p.tagName == "PARAM"){      ....     params += p.outerHTML;  }  } 

Сгенерированная строка "params" outerHTML код outerHTML :

 var tag = h.split(">")[0] + ">";  var newObject = tag + params + o.innerHTML + " </OBJECT>"; 

И, наконец, новый сгенерированный HTML заменяет оригинальный:

 o.outerHTML = newObject; 

Сокрытие объектов

Есть еще несколько вещей, которые нужно сделать. Прежде всего, мы хотим предотвратить загрузку объектов дважды — один раз, когда они инициируются в HTML-коде, и снова после их замены. Мы достигаем этого, записывая новую таблицу стилей в документ перед загрузкой страницы. Стиль использует display: none, чтобы вывести объекты из потока документов, задерживая их загрузку до завершения обмена:

 document.write ("<style id='hideObject'> object {display: none;} </style>"); 

После свопинга стиль отключается и объекты могут загружаться:

 document.getElementById("hideObject").disabled = true; 

Обнаружение вспышки

Поскольку он циклически перебирает список параметров для каждого объекта, функция objectSwap проверяет наличие параметра flashVersion и, если он найден, выполняет метод обнаружения Flash:

 if (p.name == "flashVersion") {  hasFlash = detectFlash(p.value); 

Метод ищет Flash в двух типах браузеров. Сначала проверяется, присутствует ли плагин в массиве navigator.plugins , который применяется к браузерам на основе gecko:

 detectFlash = function(version) {  if(navigator.plugins && navigator.plugins.length){    var plugin = navigator.plugins["Shockwave Flash"];    if (plugin == undefined){      return false;    } 

Если плагин найден, код все равно должен проверить установленную версию. Это достигается путем извлечения третьего элемента в свойстве description плагина и проверки его по переданному параметру version:

 var ver = navigator.plugins["Shockwave Flash"].description.split(" ")[2];  return (Number(ver) >= Number(version)) 

Далее скрипт проверяет наличие плагина в Internet Explorer. В JavaScript это достигается путем попытки создания нового объекта Flash ActiveX с переданной версией. Если JavaScript не может создать объект, он выдаст исключение, поэтому все выражение должно быть заключено в блок try-catch:

 } else if (ie && typeof (ActiveXObject) == "function") {  try {    var flash = new ActiveXObject("ShockwaveFlash.ShockwaveFlash." + version);    return true;  }  catch(e) {    return false;  }  } 

На всякий случай, если какой-то другой браузер имеет другой способ обработки Flash, метод возвращает true в конце, как сеть безопасности. Если браузер не имеет массива navigator.plugins и не является Internet Explorer, он все равно попытается отобразить Flash-фильм.

Вернемся к методу objectSwap , если сценарий не находит правильную версию, идентификатор объекта извлекается (или назначается новый) и добавляется в очередь:

 if (!hasFlash){  o.id = (o.id == "") ? ("stripFlash"+i) : o.id;  stripQueue.push(o.id);  Later on, the queue is passed to the stripFlash method:  if (stripQueue.length) {  stripFlash(stripQueue)  } 

Зачистка вспышки

Этот метод перебирает идентификаторы в очереди и извлекает innerHTML каждого объекта:

 for (var i=0; i<stripQueue.length; i++){  var o = document.getElementById(stripQueue[i]);  var newHTML = o.innerHTML; 

Для метода object / embed, где альтернативное содержимое было скрыто от Firefox и Netscape с комментариями, необходимы регулярные выражения для удаления комментариев из innerHTML , чтобы новое содержимое могло отображаться в браузере:

 newHTML = newHTML.replace(/<!--s/g, "");  newHTML = newHTML.replace(/s-->/g, ""); 

Другое регулярное выражение используется для нейтрализации тега embed путем замены его на span :

 newHTML = newHTML.replace(/<embed/gi, "span"); 

Чтобы преобразовать объект в div, проще всего было бы изменить outerHTML объекта. Тем не менее, это не работает в Firefox; вместо этого создается новый элемент div которому присваиваются тот же innerHTML , id и className что и у объекта:

 var d = document.createElement("div");  d.innerHTML = newHTML;  d.className = o.className;  d.id = o.id; 

Наконец, объект заменяется на новый div :

 o.parentNode.replaceChild(d, o); 

Инициирование ObjectSwap

  ObjectSwap должен быть выполнен после того, как все объекты загружены, путем привязки функции objectSwap к событию window.onload .  Проблема в том, что другие связанные скрипты на вашей странице могут иметь свои функции, связанные с тем же событием;  последний скрипт, который сделает это, переопределит все предыдущие привязки, что приведет к сбою других скриптов.  Это решается путем перехвата существующих функций, связанных с событием, и вызова их также: 

 var tempFunc = window.onload;  window.onload = function(){  if (typeof (tempFunc) == "function"){    try{      tempFunc();    } catch(e){}  }  objectSwap();  } 

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

Вывод
  ObjectSwap предлагает полное одношаговое решение проблемы, возникшей в результате решения Microsoft в результате судебного иска EOLAS.  Единственный файл JavaScript, связанный с <head> вашей страницы, - это все, что вам нужно, чтобы избежать требования активации Internet Explorer.  Более того, вы можете воспользоваться данной ситуацией и улучшить взаимодействие с пользователем, добавив простое обнаружение Flash на свою страницу.