Как узнать, загружена ли веб-страница внутри iframe или напрямую в окно браузера?
Я разрабатываю приложение для Facebook на основе iframe. Теперь я хочу использовать одну и ту же HTML-страницу для отображения как обычного веб-сайта, так и страницы приложения (canvas) внутри Facebook. Я хочу узнать, могу ли я определить, была ли страница загружена внутри iframe или непосредственно в браузере?
5 ответ(ов)
Данный код выполняет проверку, находится ли текущая страница в iframe.
Если window
не равен window.parent
, это значит, что страница загружена внутри iframe. В этом случае выполняется блок кода для работы с iframe.
В противном случае, если window
равен window.parent
, это указывает на то, что страница загружена непосредственно в окно браузера и не находится внутри iframe. В этом случае выполняется блок кода для работы с обычной страницей.
Вот как это выглядит на русском:
if ( window !== window.parent )
{
// Страница находится в iframe
}
else
{
// Страница не находится в iframe
}
В вашем примере код для определения, находится ли текущий документ в iFrame, выглядит корректно и должен работать в современных браузерах, таких как IE, Firefox и Chrome.
Вот как это работает:
var iFrameDetection = (window === window.parent) ? false : true;
Эта строка кода сравнивает текущий объект window
с объектом window.parent
. Если они равны, это значит, что текущий документ не находится внутри iFrame, и переменная iFrameDetection
будет false
. В противном случае, если window
отличается от window.parent
, это указывает на то, что текущий документ загружен в iFrame, и iFrameDetection
будет true
.
Код должен работать во всех современных браузерах, однако стоит учитывать, что в старых версиях Internet Explorer могут быть некоторые особенности. Например, некоторые версии могут не поддерживать определенные функции или методы, которые могут использоваться в более новых реализациях. Поэтому, если требуется поддержка очень старых браузеров, стоит дополнительно протестировать код в них.
Если вам нужно конкретное решение для старых версий IE, дайте знать, и мы можем обсудить дополнительные меры предосторожности или альтернативные методы.
RoBorg прав, но я хотел бы добавить несколько замечаний.
В IE7/IE8, когда Microsoft добавила вкладки в свой браузер, они сломали одну вещь, которая может вызвать проблемы с вашим JS, если вы не будете осторожны.
Представьте себе такую структуру страницы:
MainPage.html
IframedPage1.html (назван "foo")
IframedPage2.html (назван "bar")
IframedPage3.html (назван "baz")
Теперь, если на фрейме "baz" вы нажмете ссылку (без цели, загружается в фрейм "baz"), все работает нормально.
Если загружаемая страница, назовем ее special.html, использует JS для проверки, есть ли у нее родительский фрейм с именем "bar", это вернет true (что и ожидается).
Теперь допустим, что страница special.html при загрузке проверяет родительский фрейм (на предмет существования и его названия), и если это "bar", она перезагружает себя в фрейме bar, например:
if(window.parent && window.parent.name == 'bar'){
window.parent.location = self.location;
}
Пока что все в порядке. Теперь переходим к ошибке.
Допустим, вместо того чтобы кликнуть по исходной ссылке, как обычно, и загрузить страницу special.html в фрейме "baz", вы средним кликом открыли ее в новой вкладке.
Когда эта новая вкладка загрузится (без родительских фреймов вообще!) IE попадет в бесконечный цикл загрузки страницы! Потому что IE "копирует" структуру фреймов в JavaScript так, что у новой вкладки есть родитель, и этот родитель имеет имя "bar".
Хорошая новость в том, что проверка:
if(self == top){
// это вернет true!
}
в новой вкладке действительно возвращает true, и таким образом вы можете протестировать это странное условие.
В ответ на вопрос о том, как отличить контентный скрипт, запущенный в верхнем окне, от того, который запущен внутри iframe, обратите внимание, что ответ, принятый ранее, может не сработать в контексте расширения для Firefox 6.0 (Addon-SDK 1.0).
Как показали мои тесты, Firefox выполняет контентный скрипт как в верхнем окне, так и во всех iframe. Внутри контентного скрипта я получил такие результаты:
(window !== window.top) : false
(window.self !== window.top) : true
Странно, но эти значения остаются неизменными независимо от того, выполняется ли код внутри iframe или в верхнем окне. Однако в Google Chrome контентный скрипт выполняется только один раз в верхнем окне, что делает вышеуказанный подход неэффективным.
Для решения моей задачи я использовал следующий код, который сработал в обоих браузерах:
console.log(window.frames.length + ':' + parent.frames.length);
Если iframe отсутствуют, вывод будет 0:0
. В верхнем окне с одним iframe вывод будет 1:1
, а в единственном iframe документа он покажет 0:1
.
Такой метод позволяет моему расширению определить наличие iframe в обоих браузерах, а также дополнительно в Firefox выяснить, запущен ли скрипт внутри одного из iframe.
Вы можете использовать следующий код для определения, запущен ли ваш скрипт в iFrame:
var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);
Этот код проверяет, есть ли у текущего контекста frameElement
, и если да, то проверяет, является ли он элементом HTMLIFrameElement
. Если условие выполняется, переменная isIframe
будет равна true
, что означает, что скрипт выполняется внутри iFrame.
Обратите внимание, что данная проверка может не учитывать другие типы фреймов, такие как iframe
с помощью contentWindow
. Если вам нужно более надежное определение, рассмотрите использование следующего кода:
var isIframe = window !== window.parent;
Такой способ будет работать с iFrame и определит, если текущий контент загружен внутри какого-либо фрейма.
Как получить доступ к содержимому iframe с помощью JavaScript/jQuery?
SecurityError: Заблокирован доступ к фрейму из-за политики CORS
Автоматическая настройка высоты iframe в зависимости от содержимого без использования полосы прокрутки?
Как перенаправить на другую веб-страницу?
Как перемешать (сделать случайным) массив в JavaScript?