2008-11-28 1 views
437

Я пишу фрейм-приложение, основанное на iframe. Теперь я хочу использовать одну и ту же страницу html для рендеринга обычного веб-сайта, а также страницы холста в facebook. Я хочу знать, могу ли я определить, была ли загружена страница внутри iframe или непосредственно в браузере?Как определить, загружается ли веб-страница внутри iframe или непосредственно в окне браузера?

ответ

815

Браузеры могут блокировать доступ к window.top из-за same origin policy. Ошибки IE также имеют место. Вот рабочий код:

function inIframe() { 
    try { 
     return window.self !== window.top; 
    } catch (e) { 
     return true; 
    } 
} 

top и self оба window объекты (наряду с parent), так что вы видите, если окно верхнее окно.

+3

Это, кажется, работает хорошо в Firefox. Работает ли он и в других браузерах? – akshat 2008-11-28 15:51:55

+5

Имея страницу с iframe в iframe, чтобы проверить из моего дочернего iframe, если мой родительский iframe был вставлен на страницу, я использовал if (parent === top) – sglessard 2012-03-27 14:31:30

+7

@sglessard Если дочерняя страница и родительские элементы из разных доменов то Firefox будет жаловаться на политику одинакового происхождения (www.w3.org/Security/wiki/Same_Origin_Policy), а код не будет работать – 2012-07-31 22:10:48

25

RoBorg правильно, но я хотел добавить примечание.

В IE7/IE8, когда Microsoft добавила вкладки в свой браузер, они сломали одну вещь, которая может привести к хаосу с вашим JS, если вы не будете осторожны.

Представьте себе эту страницу макета:

MainPage.html 
    IframedPage1.html (named "foo") 
    IframedPage2.html (named "bar") 
    IframedPage3.html (named "baz") 

Теперь в кадре «Баз» щелкнуть ссылку (без цели, нагрузки в «БАЗ» кадр) он работает отлично.

Если загружаемая страница позволяет называть ее special.html, использует JS для проверки наличия родительского фрейма с именем «bar», он вернет true (ожидается).

Теперь давайте говорить о том, что special.html страница, когда он загружает, проверяет родительский фрейм (для существования и его имя, и если это «бар» он перегружает себя в баре кадра. Например

if(window.parent && window.parent.name == 'bar'){ 
    window.parent.location = self.location; 
} 

Пока что появляется ошибка.

Скажем, вместо того, чтобы нажимать на исходную ссылку, как обычно, и загружать страницу special.html в рамке «baz», вы щелкнули ее по центру или выбрали откройте его в новой таблице.

Когда эта новая вкладка загружает (без каких-либо родительских кадров!) IE войдет в бесконечный цикл загрузки страницы! потому что IE «копирует» структуру фрейма в JavaScript, так что новая вкладка имеет родительский элемент, а у этого родителя имя «bar».

Хорошая новость в том, что проверка:

if(self == top){ 
    //this returns true! 
} 

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

1

Поскольку вы спрашиваете в контексте приложения facebook, вы можете подумать об обнаружении этого на сервере при первоначальном запросе. Facebook будет передавать кучу данных запроса, включая ключ fb_sig_user, если он вызывается из iframe.

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

1

Используйте эту функцию javascript как пример того, как это сделать.

function isNoIframeOrIframeInMyHost() { 
// Validation: it must be loaded as the top page, or if it is loaded in an iframe 
// then it must be embedded in my own domain. 
// Info: IF top.location.href is not accessible THEN it is embedded in an iframe 
// and the domains are different. 
var myresult = true; 
try { 
    var tophref = top.location.href; 
    var tophostname = top.location.hostname.toString(); 
    var myhref = location.href; 
    if (tophref === myhref) { 
     myresult = true; 
    } else if (tophostname !== "www.yourdomain.com") { 
     myresult = false; 
    } 
} catch (error) { 
    // error is a permission error that top.location.href is not accessible 
    // (which means parent domain <> iframe domain)! 
    myresult = false; 
} 
return myresult; 
} 
15

Принятый ответ не работает для меня в скрипте содержания Firefox 6.0 Extension (Аддон-SDK 1.0): Firefox выполняет скрипт контента в каждом: окне верхнего уровня и во всех фреймах.

Внутри скрипта содержания я получаю следующие результаты:

(window !== window.top) : false 
(window.self !== window.top) : true 

Странная вещь об этом выходе, что это всегда одинаково, независимо будет ли код работать внутри фрейма или окна верхнего уровня.

С другой стороны, Google Chrome, похоже, выполнил мой сценарий контента только один раз в окне верхнего уровня, так что вышеупомянутое не будет работать вообще.

Что, наконец, работал для меня в сценарии содержания в обоих браузерах это:

console.log(window.frames.length + ':' + parent.frames.length); 

Без фреймов печатается 0:0, в окне верхнего уровня, содержащего один кадр он печатает 1:1, и в единственном IFRAME документа, который он печатает 0:1.

Это позволяет моему расширению определять в обоих браузерах, если есть какие-либо iframes, а также в Firefox, если он запускается внутри одного из фреймов.

-1

Это древний кусок кода, который я использовал несколько раз:

if (parent.location.href == self.location.href) { 
    window.location.href = 'https://www.facebook.com/pagename?v=app_1357902468'; 
} 
5

Я использую это:

var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1); 
-3
if (window.frames.length != parent.frames.length) { page loaded in iframe } 

Но только если количество фреймов отличается вашу страницу и страницу, которые загружают вас в iframe. Не делайте IFrame на странице, чтобы иметь 100% гарантии результата этого кода

-3

Написать этот яваскрипт на каждой странице

if (self == top) 
    { window.location = "Home.aspx"; } 

Тогда он будет автоматически перенаправляет на главную страницу.

0

Если вы хотите узнать, обращается ли пользователь к вашему приложению со страницы вкладки facebook или проверки холста для подписанного запроса. Если вы этого не сделаете, возможно, пользователь не обращается к Facebook. Чтобы убедиться в подтверждении структуры и полей полей signed_request.

С PHP-SDK вы можете получить Подписанный запрос, как это:

$signed_request = $facebook->getSignedRequest(); 

Вы можете прочитать больше о Подписанный запрос здесь:

https://developers.facebook.com/docs/reference/php/facebook-getSignedRequest/

и здесь:

https://developers.facebook.com/docs/reference/login/signed-request/

61

window.frameElement Возвращает элемент (например, <iframe> или < объект >), в котором вставлено окно, или null, если окно находится на верхнем уровне. Таким образом, идентификационный код выглядит

if (window.frameElement) { 
    // in frame 
} 
else { 
    // not in frame 
} 

This is standard and rather new method. Это точно работает в Chrome и Firefox. Я не могу рекомендовать его как универсальное решение, но я должен здесь упомянуть.

1
if(typeof(parent) == 'undefined') { 
    console.log('Not Iframe'); 
} 
else { 
    console.log('iframe'); 
} 
1

Я не знаю, как этот пример работает для старых браузеров, но я использую это для IE, Firefox и Chrome без и вопрос:

var iFrameDetection = (window === window.parent) ? false : true; 
Смежные вопросы