Xpoint
   [напомнить пароль]

Способы открытия нового окна с помощью JS

Оглавление

Несмотря на заявления юзабилистов о том, что новые окна браузера должен открывать только пользователь, в реальности довольно часто возникает необходимость открыть новое окно, например для того, что бы показать увеличенную версию картинки или форму обратной связи. Даже на этом сайте карта форумов открывается в новом окне.

Ниже перечислены несколько способов открытия нового окна, а также указаны их достоинства и недостатки.

href="javascript:…"

<a href="javascript:window.open('popup.html','','…')">Новое окно</a>

Это самый старый (известный мне) способ. Его минусы:

  • при отключении JS ссылка не работает;
  • не индексируется поисковиками;
  • в статусной строке вместо ссылке отображается JavaScript-код;
  • „грязный“ код.

onclick="…"

<a href="popup.html" onclick="window.open('popup.html','…','…'); return false">Новое окно</a>
<a href="popup.html" onclick="window.open(this.href,'…','…'); return false">Новое окно</a>

Именно этот способ чаще всего используется на сайтах. Он лишён первых двух минусов предыдущего способа, и если на сайте открытие новых окон не является частым действием (например, на этом сайте я нашёл только одну такую ссылку), то этот способ является оптимальным.

Если же на сайте приходиться открывать много новых однотипных окон (например увеличенное изображение товаров в интернет-магазине), то этот способ выливается в большое количество лишнего кода. Возможно, в этом случае лучше еще раз продумать как следует интерфейс. Владимир Палант[досье]

сlass="popup", window.onload

Идея проста, обозначим каким-либо образом ссылки, которые нужно открывать в новом окне (в данном случае присвоив им класс), а после загрузки документа присвоим этим ссылкам обработчик события onclick.

<a href="popup.html" class="popup">Новое окно</a>
function handlePopupClick() {
  window.open(this.href,'…','…');
  return false;
}

window.onload = function() {
  var lnks = document.getElementsByTagName('A')
  for(var i = 0; i < lnks.length; i++)
    if(/\bpopup\b/.test(lnks[i].className))
      lnks[i].onclick = handlePopupClick;
}

В данном примере параметры нового окна (размеры, имя окна и т.д.) будут одинаковыми у всех ссылок, но при желании это можно изменить — к примеру, определить стандартные параметры, и отклонения от них указывать атрибутами ссылки. Основной же минус в том, что эти ссылки будут открывать новые окна только после полной загрузки документа, а до этого они будут работать как обычные ссылки. Кроме того, если на странице много ссылок, то на их проверку уйдет некоторое время, что выражается в "подвисании" браузера при окончании загрузки страницы.

сlass="popup", document.onclick

Вспомним, что события всплывают, и отловить их можно на самом верхнем уровне (почти © Владимир Палант[досье]). Поэтому будем перехватывать все клики в документе, и если это клик по ссылке с class="popup", то будем открывать новое окно.

<a href="popup.html" class="popup">Новое окно</a>
document.onclick = function(e) {
  e = e || event;
  var t = e.target || e.srcElement;
  if (t.tagName.toLowerCase() == 'a' && /\bpopup\b/.test(t.className)) {
    window.open(t.href,'…','…');
    return false;
  }
  return true;
}

Здесь отсутствуют минусы предыдущего способа. При сложной разметке сайта следует, однако, учитывать, что клик может произойти не на самой ссылке, а на одном из его дочерних элементов (на картинке, к примеру). В этом случае нужно переходить от t к родительским элементам по цепочке, пока не будет найдена ссылка:

document.onclick = function(e) {
  e = e || event;
  var t = e.target || e.srcElement;
  while (t && t.nodeType == 1 && t.tagName.toLowerCase() != 'a')
     t = t.parentNode;

  if (t && t.nodeType == 1 && /\bpopup\b/.test(t.className)) {
    window.open(t.href,'…','…');
    return false;
  }
  return true;
}

Разумеется, в двух последних способах не обязательно определять ссылки, которые должны открывать новые окна, с помощью класса. Вариантов может быть много. Например, если на вашем сайте все попапы открываются по адресу /popup/что-то…, то можно определять проверять наличие этого пути в атрибуте href ссылки.

Идея последнего способа взята из Присвоить ссылке "disabled".

Поправки и отзывы приветствуются :)

Комментарии

2007-01-29 12:23:42 [обр] Илья Cтpeльцын aka SelenIT[досье]
По-моему, в способе 2 еще есть смысл указывать target="_blank", чтобы при отключенном JS ссылка все равно открывалась в новом окне, пусть и не таком "красивом" (если, конечно, doctype не Strict и это позволяет).
спустя 1 час 43 минуты [обр] Lynn «Кофеман»[досье]
На самом деле это «способ №0» :)
А вообще, с одной стороны, это имеет смысл во всех способах, кроме первого, а с другой, кнопку «назад» в браузере никто не отменял.
спустя 2 дня 3 часа [обр] Илья Cтpeльцын aka SelenIT[досье]
Lynn «Кофеман»[досье], еще интересный для меня вопрос про способ 4: при обходе предков target-а на что лучше ориентироваться — на имя тега "A" или на наличие атрибута href? Имхо, второе удобнее — ведь A не обязательно ссылка, так что проверить href все равно надо бы (а то еще откроется окно со словом "undefined"...), заодно не придется менять код в случае <area href=...> графической карты... Может, я чего-то недопонимаю?
спустя 18 часов [обр] Lynn «Кофеман»[досье]
A без атрибута href устарел и не рассматривается.
Да, можно ориентироваться и на наличие атрибута, не вопрос. Я в данной статье хотел просто показать идею, а детали реализации разумеется могут отличаться.
Powered by POEM™ Engine Copyright © 2002-2005