Использование относительного URL для window.location в дочернем iframe - PullRequest
3 голосов
/ 17 февраля 2010

У меня проблемы с фреймом.

У меня есть документ (родительский) с iframe (дочерний). Если родительский документ вызывает функцию в дочернем элементе, которая изменяет дочерний URL-адрес с помощью window.location на относительный URL-адрес, этот URL-адрес становится относительно родительского документа. Позвольте мне проиллюстрировать.

Родительский документ: /test/parent.html

Дочерний документ: /projects/child.html

Код ребенка:

function moveOn(){
    window.location.href = "newPage.html";
}

Родительский код:

childDocument.contentWindow.moveOn();

Результат: Дочерний документ пытается получить доступ к / test / newPage.html вместо / projects / newPage.html

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

Спасибо, Nik

Edit:

Это фактический код

В родительском (/testr/testr.html):

testr.appHolder = $("childIframe"); 
testr.appHolder.src = "../projects/test.html"; 
testr.functionName = "moveOn"; 
testr.appHolder.contentWindow[testr.functionName]();

В детях (/projects/test.html):

function moveOn(){ 
  window.location.href = "newPage.html"; 
}

Это фактический код

В родительском (/testr/testr.html):

testr.appHolder = $("childIframe"); 
testr.appHolder.src = "../projects/test.html"; 
testr.functionName = "moveOn"; 
testr.appHolder.contentWindow[testr.functionName]();

Для детей (/projects/test.html):

function moveOn(){ 
  window.location.href = "newPage.html"; 
}

Ответы [ 3 ]

4 голосов
/ 24 апреля 2012

Наконец, полное решение!

childDocument.contentWindow.setTimeout( childDocument.contentWindow.moveOn, 0 );

Это требует, чтобы дочерний документ выполнил заданную функцию (moveOn) за ноль миллисекунд, и он выполняется в контекстеребенка даже в Internet Exploder.

Booyah.

0 голосов
/ 24 апреля 2012

Aha. Я нашел baseURI свойство. Теперь мы говорим.

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

Короче, было бы здорово сказать:

var originalURI = document.baseURI; // store for setting back after the move
document.baseURI = childDocument.location; // setting parent's baseURI (NO EFFECT!)
childDocument.contentWindow.moveOn();
document.baseURI = originalURI; // restore original baseURI

К сожалению, свойство baseURI имеет значение только для чтения . К счастью, его значение взято из тега <base>, который вы можете изменить с помощью скрипта. Вы можете получить желаемую функциональность для данного потомка, установив базовый тег родителя для ссылки на childUrl:

<head>
<base href="/path/to/child.html" />
</head>

К сожалению, это делает любые относительные ссылки в вашем родителе относительно ребенка, а это не то, что вам нужно. Мы должны установить это сразу после нажатия на ссылку и вернуть его обратно после того, как ребенку сказали moveOn().

Если вы включите пустой тег <base /> в <head> вашего родителя, он не повлияет на baseURI по умолчанию. Поэтому, когда вы хотите выполнить функцию moveOn() в дочернем элементе, вы можете сказать что-то вроде:

var baseElement = document.getElementsByTagName("base")[0];

// adopt the child's location as baseURI
baseElement.href = childDocument.location; 

childDocument.contentWindow.moveOn();

// revert back to the parent's original baseURI
baseElement.removeAttribute("href"); 

(надеюсь, это как-то поможет - через два года ... га)

Edit:

Еще раз Internet Exploder - участник вечеринки. Кажется, что изменения в любом теге после загрузки не принимаются. Поэтому, если вам не нужно поддерживать IE (HA!), Это решение не будет работать, если вы не будете рады жестко закодировать местоположение ребенка в теге родителя. Опять же, это большие ifs.

0 голосов
/ 24 апреля 2012

Спецификация HTML гласит:

Когда [свойство местоположения установлено], [браузер] должен разрешить аргумент относительно базового URL-адреса сценария входа и, если это успешно, долженПерейдите в контексте просмотра по указанному URL.

Один (хакерский) способ получить поведение, к которому вы стремитесь, это непосредственное редактирование свойства pathname location: эффективная реализация разрешенияотносительного URL самостоятельно.

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

Решение Dotdot

Один «умный» способ сделать это - добавить косую черту, чтобы превратить имя файла в «каталог», затем стереть его с помощью «точки», а затем указать относительный URL-адрес.

childDocument.contentWindow.location.pathname += "/../newPage.html";

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

Проверьте, как это работает.

Путь начинается как/projects/child.html

Затем вы добавляете к нему, чтобы получить/projects/child.html/../newPage.html

Браузер разрешает это/projects/newPage.html

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

Если дочерние страницы названы предсказуемым образом, и вы знаете общее количество страниц, а также знаете базовый URL дочернего каталога, вы могли бы иметь родительский контроль над дочерним объектом правильно.Это очень много если.

Sidenote: Я ищу более элегантное и надежное решение.Скрестив пальцы.

...