К большому огорчению веб-дизайнеров повсюду, рекомендации W3C по HTML 4.0 Strict и XHTML 1.0 Strict больше не включают атрибут target
тега <a>
. Переходные версии спецификаций все еще включают его, но по определению эти спецификации находятся на выходе.
Каковы бы ни были ваши личные ощущения на практике, наиболее распространенное приложение для этого атрибута — открытие ссылки в новом окне браузера с target="_blank"
— все еще полезно в современном Интернете. Так что, если стандарты говорят, что мы не должны его использовать, как нам следует создавать ссылки в новом окне, следуя последним веб-стандартам?
Прикладной идеализм
Веб-стандарты написаны с учетом множества идеалов. Во многих случаях устоявшаяся практика отходит на второй план в пользу «правильного поведения». Один из идеалов, который выражается в удалении атрибута target
из строгих стандартов, заключается в том, что (X) HTML должен касаться только информации, отображаемой в окне браузера.
Следовательно, как только мы начинаем говорить об открытии новых окон браузера, идеалистическим понятием является то, что мы превысили обязанности (X) HTML и вошли в мир сценариев на стороне клиента (то есть JavaScript).
Но прежде чем мы углубимся в код JavaScript, необходимый для открытия ссылки в новом окне браузера, нам еще предстоит решить фундаментальную проблему. Нам все еще нужен способ пометить ссылки, которые должны быть открыты в новом окне, и если мы не можем использовать для этого атрибут target
, нам нужно найти какой-то другой способ — способ, который соответствует идеалам, стоящим за последними ( X) стандарты HTML.
Новые отношения
Спецификация HTML 4.0 target
атрибут target
, но добавила еще один атрибут: rel
. Этот атрибут предназначен для указания взаимосвязи между документом, содержащим ссылку, и целью ссылки. Спецификация определяет набор стандартных значений для этого атрибута (например, next
, previous
, chapter
, section
), большинство из которых связано со связями между небольшими разделами большого документа. Тем не менее, спецификация оставляет разработчику право использовать нестандартные значения для конкретных сайтов.
Здесь, в SitePoint, мы приняли пользовательское значение для rel
чтобы пометить ссылки, ведущие на другие сайты. Это те самые ссылки, которые мы хотим открыть в новом окне браузера. Для этих ссылок мы устанавливаем атрибут rel
как external
.
Перед:
<a href="document.html" target="_blank" >external link</a>
После:
<a href="document.html" rel="external" >external link</a>
Итак, теперь, когда у нас есть ссылки на новое окно, помеченные в соответствии со стандартами, нам нужно написать JavaScript, который будет фактически открывать их в новом окне.
Деконструкция сценария
Работа нашего скрипта, который будет запущен после загрузки документа, будет заключаться в том, чтобы найти все гиперссылки в документе и изменить те, которые имеют наш специальный (но совместимый со стандартами!) Атрибут rel="external"
, чтобы они открыть в новом окне.
Звучит устрашающе? Не волнуйтесь — код не так уж плох. Первый шаг — убедиться, что браузер справился с задачей:
if (!document.getElementsByTagName) return;
getElementsByTagName
— удобный метод стандарта Document Object Model 1.0 (DOM1), поддерживаемый современными браузерами. Так как некоторые из старых браузеров, которые по-прежнему работают, такие как Netscape 4 и Internet Explorer 4, не поддерживают DOM1, мы должны отсеять их, проверив наличие этой функции. В этих браузерах мы просто возвращаемся и позволяем открывать внешние ссылки в одном и том же окне браузера — в большинстве случаев никаких больших потерь.
Далее мы используем метод getElementsByTagName
чтобы получить список всех тегов <a>
в документе:
var anchors = document.getElementsByTagName("a");
anchors
будут содержать массив JavaScript после того, как метод выполнит свою работу. Каждый элемент в массиве будет представлять тег <a>
в документе.
Теперь нам нужно просмотреть все теги <a>
мы только что нашли, и изменить те, которые представляют ссылки в новом окне. Вы можете использовать цикл JavaScript for
работы с каждым из тегов по очереди:
for (var i=0; i < anchors.length; i++) { var anchor = anchors[i];
Для каждого элемента в массиве anchors
мы создаем переменную внутри цикла, называемую anchor
чтобы изолировать тег, с которым мы сейчас имеем дело.
Теперь нам нужно проверить, представляет ли anchor
ссылку в новом окне. Как я уверен, вы знаете, тег <a>
используется не только для создания гиперссылок. С помощью атрибута name
вы можете создать цель для ссылок, которые ведут в определенное место на странице. Только теги <a>
с атрибутом href
считаются гиперссылками. Поэтому наш код должен проверить, что anchor
имеет атрибут href
а также атрибут rel
который имеет значение external
.
if (anchor.getAttribute("href") && anchor.getAttribute("rel") == "external")
Теперь, когда мы подтвердили, что имеем дело со ссылкой в новом окне, мы можем установить для ее target
атрибута значение "_blank"
:
anchor.target = "_blank";
И это должно сделать это! Читайте полный код и еще несколько слов о том, почему это решение приемлемо…
Тонкая линия
Как немного перфекционист, мой первый импульс, когда я узнал об этом решении, состоял в том, чтобы спросить: «Есть ли на самом деле разница?» И да, я часто разговариваю сам с собой во время исследования.
Я имею в виду, что если target
атрибут тега <a>
постепенно удаляется, действительно ли имеет значение, устанавливаем ли мы его с помощью JavaScript вместо HTML? Несомненно, страница будет проверяться на соответствие определениям типов документов HTML 4.0 Strict и XHTML 1.0 Strict, но разве мы не технически обманываем?
Ответ — нет. Объектная модель документа (DOM), которая управляет объектами и атрибутами документа, доступными для кода JavaScript, является совершенно отдельным стандартом от (X) HTML. Также учтите, что стандарт DOM 2.0, который был опубликован в январе 2003 года (намного позже XHTML 1.0, не говоря уже о HTML 4.0), все еще включает этот атрибут. Кажется очевидным, что, хотя этот атрибут планируется исключить из (X) HTML, он будет доступен для JavaScript через DOM в обозримом будущем.
В ряде других совместимых со стандартами сценариев ссылок для нового окна предлагается использовать window.open()
для загрузки документа в новом окне. Хотя этот подход, как правило, хорошо работает на поверхности, его недостатком является то, что большинство браузеров неправильно отображают URL-адрес ссылки в запросе на новую страницу, что может быть серьезной проблемой, особенно в ссылках между сайтами.
Полный сценарий
Как и было обещано, вот полный сценарий. Обратите внимание на последнюю строку, которая назначает функцию externalLinks
обработчику события onload
окна. Это вызывает функцию, когда документ закончил загрузку.
function externalLinks() { if (!document.getElementsByTagName) return; var anchors = document.getElementsByTagName("a"); for (var i=0; i<anchors.length; i++) { var anchor = anchors[i]; if (anchor.getAttribute("href") && anchor.getAttribute("rel") == "external") anchor.target = "_blank"; } } window.onload = externalLinks;
Поскольку этот тип сценария вы хотите развернуть на всем сайте, вы должны скопировать этот код в отдельный файл (например, external.js
), а затем загрузить его на каждую страницу вашего сайта с помощью следующего кода, который должен появляться в <head>
каждого документа:
<script type="text/javascript" src="/external.js"> </script>
Проблема решена!