Внимание! Прочитайте, пожалуйста, текст в правой колонке (внизу).
Внимание! Прочитайте, пожалуйста, текст в правой колонке (внизу). Внимание! Прочитайте, пожалуйста, текст в правой колонке (внизу). Homepage Карта сайта Версия для печати

Джентльменский набор Web-разработчика   Ларри Уолл о Perl6   Наблы Система Orphus
 

58. Автоматический resize высоты IFRAME, загруженного с другого домена, или кое-что о кроссдоменной передаче данных

[20 декабря 2009 г.] обсудить статью в форуме

Лирическое отступление 
При создании этой статьи неоценимую помощь оказало сообщество Хабрахабра. Основные "кирпичики" решения были почерпнуты мной в комментариях в статье-вопросе, которую я там разместил. Спасибо!

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

Но вначале я приведу решение задачи автоматического изменения высоты IFRAME, загружаемого с другого домена. (Resize height of an IFRAME from a different domain.)

Автоматическое изменение высоты IFRAME с другого домена

Иногда приходится писать сервисы, которые работают не сами по себе, а вставляют контент на страницы других сервисов в IFRAME. (В основном это разнообразные виджеты.) Но высота IFRAME ограничена значением, которое указано в атрибуте height тэга <iframe> и не увеличивается автоматическ, если контент внутри IFRAME занимает больше места.

Листинг 1: Страница master.com/index.html
...
<iframe src="http://slave.com/frame.html" height="100"></iframe>
какой угодно JS, который мы пишем сами
...

Листинг 2: Страница slave.com/frame.html
...
какой угодно код, полностью нам подвластный
...

Проблема: высота slave.com/frame.html может меняться, ее нельзя указать "заведомо" в height IFRAME. Требуется сделать так, чтобы на master.com/index.html крутился какой-то JS, который "подгоняет" высоту IFRAME под контент. Главная сложность - то, что контент находится на другом домене.

Решение: автоматическое установление высоты IFRAME

Кроссбраузерное решение этой задачи приводится ниже. Его особенности:

  • не портится history браузера;
  • работает даже в Опере 7 и IE6;
  • для ускорения работы высота фрейма всегда делается кратной N=30 пикселям.

Чайник 

Фактически, там два алгоритма: для IE (через location.hash) и для "не-IE" (через window.name и "простукивание" возможных высот в цикле). См. также комментарии к статье на Хабрахабре, там разъяснения, почему сделано так, а не иначе.

Листинг 3: РЕШЕНИЕ: страница master.com/index.html
<body>
<iframe
src="http://slave.com/frame.html" height="150" 
style="padding:0; margin:0" scrolling="no"
onload="var th=this; setTimeout(function() { 
    var h=null;
    if (!h) if (location.hash.match(/^#h(\d+)/)) h=RegExp.$1;
    if (!h) for (var i=0; i<10000; i+=30) if (top.frames['h'+i]) { h=i; break; }
    if (h) th.style.height=h+'px';
}, 10)"
></iframe>
</body>

Листинг 4: РЕШЕНИЕ: страница slave.com/frame.html
<html>
<style>
html, body { padding: 0; margin: 0; }
</style>
<body>
    Header.
    <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
    Footer.
    <script>
    window.onload = function() {
        var h = Math.ceil(document.body.scrollHeight / 30) * 30;
        var ie = 0 /*@cc_on + @_jscript_version @*/;
        if (!ie) window.name = "h" + h;
        else top.location.replace("http://master.com/#h" + h);
    }
    </script>
</body>
</html>

Внимательный читатель заметит, что на странице slave.com/frame.html мы должны обладать знанием о том, откуда загрузили данную страницу. Т.е. нужно получить значение "http://master.com" (в демонстрационном листинге я для простоты вставил это значение вручную). Средствами только JavaScript этого сделать не получится, т.к. скрипт внутри IFRAME не имеет доступа к родительскому окну и не может прочитать его адрес. Тем не менее, вы всегда можете передать адрес родительского окна внутрь IFRAME через обыкновенный GET-параметр: <iframe src="http://slave.com/iframe.html?ret=http://master.com/" >

Общий случай запрещенной операции по кроссдоменному доступу

Например, у нас есть вот такая конструкция:

Листинг 5: Страница master.com/index.html
...
<iframe src="http://slave.com/frame.html"></iframe>
какой угодно JS, который мы пишем сами
...

Листинг 6: Страница slave.com/frame.html
...
какой угодно код, полностью нам подвластный
...

Не существует способа, который бы позволял JS-коду в slave.com/frame.html обратиться к данным (или запустить функцию) страницы master.com/index.html, а также наоборот.

Правда, из этого правила есть одно важное исключение: внутри slave.com/frame.html можно присваивать значение top.location и осуществлять, таким образом, редиректы окна верхнего уровня куда-то еще.

И все-таки есть хак для прямых поддоменов

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

Листинг 7: Страница master.com/index.html
...
<iframe src="http://subdomain.master.com/frame.html" height="100"></iframe>
<script>
document.domain = document.domain; // да-да, это обязательно нужно, иначе не заработает
// или можно напрямую написать: document.domain = "master.com", хотя это и не так весело
</script>
...

Листинг 8: Страница subdomain.master.com/frame.html
...
<script>
document.domain = "master.com"; 
</script>
...

Т.е. мы должны в обеих страницах присвоить свойству document.domain одинаковое значение, равное "родительскому" домену. Тогда обращение внутрь (или наружу) IFRAME возможно. Еще раз подчеркиваю, что это работает только в случае, если один домен является прямым поддоменом другого (именно прямым, потому что даже abc.subdomain.master.com здесь уже не сработает).

Ссылки

обсудить статью в форуме

 
Рекламный блок
   

На странице:
    58. Автоматический resize высоты IFRAME, загруженного с другого домена, или кое-что о кроссдоменной передаче данных
Автоматическое изменение высоты IFRAME с другого домена
     Решение: автоматическое установление высоты IFRAME
Общий случай запрещенной операции по кроссдоменному доступу
     И все-таки есть хак для прямых поддоменов
Ссылки

Важное объявление:
    автор категорически против копирования и распространения в Интернете всех статей «Куроводства» с возрастом, меньшим 6 месяцев. Печальный опыт «расползания» чрезвычайно устаревших ошибочных версий статьи про Apache действительно объясняет такое решение.

Орфография на «Куроводстве»:
    если вы заметили орфографическую, стилистическую или другую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Выделенный текст будет немедленно отослан вебмастеру, а Вы даже ничего и не заметите — настолько быстро все произойдет.

На заметку:
    если вы уже вскипели насчет дизайна этой страницы, то присмотритесь повнимательнее к названию, почитайте FAQ, сходите по лебедевским местам, как это уже предлагалось выше. Можно ли считать пародию плагиатом? Надеюсь, что нет.

Параметры этой страницы
   
GZip

Ссылки от спонсоров
   


Дмитрий Котеров | 20 декабря 2009 г. ©1999-2016 | Генеральный спонсор: Хостинг «Джино» | Контакт Вернуться к оглавлению