Выставление автоматической высоты для iFrame

Автор: "Чулан", оригинал: http://habrahabr.ru/post/78845/, использовал на одном сайте - реально работает.

Прочитав статейку Дмитрия Котерова о ресайзе ифрэймов решился поделиться своим решением.

Этим решением пользуемся на продуктивном сайте.

Итак, дано:
1. Нужно показывать в ифрэйме страницы с других доменов без скроллбара
2. Внутри ифрэйма могут совершаться переходы
3. Сайты в ифрэйме могут менять высоту без перегрузки (AJAX или просто раскрытие каких-нибудь невидимых элементов)
4. Во включаемые страницы должно включаться кода по минимуму
5. Решение не должно портить историю посещение браузера и должно работать в актуальных версиях популярных браузеров
6. Решение должно работать в обоих случаях master.site и www.master.site

Решение:

Нам нужно на основном сайте master.site создать два файлика iframe_height.js и height.html.

На самой странице создаем ифрэйм с id=«iframe». Во включаемую страницу с домена slave.site в head добавляем ссылку на жаваскрипт http://master.site/iframe_height.js

iframe_height.js:

var __hc = {
  i: null, // используется для периодической проверки высоты
  h: 0, // предыдущая установленная высота
  iframes: [null, null], // создаем два ифрэйма
  path: 'master.com/height.html#', // путь до height.html
  // созание невидимых ифрэймов для установки высоты
  setHeight: function(height) {
    var ifr,i;
    for (i=0;i<2;i++) {
      if (this.iframes[i]) this.iframes[i].parentNode.removeChild(this.iframes[i]);
      ifr = document.createElement('IFRAME');
      ifr.style.display = 'none';
      this.iframes[i] = ifr;
      document.body.appendChild(this.iframes[i]);
      ifr.src = 'http://' + (i ? 'www.' : '') + this.path + height;
    }
  },
  // выполняется после загрузки окна — устанавливаем высоту и запускаем периодическую проверку
  onLoad: function(full) {
    this.checkHeight();
    if (full) {
      this.i = window.setInterval(this.bind(this.checkHeight), 100);
    }
  },
  // проверка высоты, если не изменилась с прошлой проверки
  checkHeight: function() {
    var h = this.getDocHeight();
    if (this.h == h) return;
 
    this.h = h;
    this.setHeight(this.h);
  },
  // если определена функция для определения высоты используем ее, иначе ползуемся общей реализацией
  getDocHeight: function() {
    if (window.GetDocumentHeight) return window.GetDocumentHeight();
    var D = document;
    return Math.max(
      D.body.scrollHeight, D.documentElement.scrollHeight,
      D.body.offsetHeight, D.documentElement.offsetHeight,
      D.body.clientHeight, D.documentElement.clientHeight
    );
  },
  // служебные методы
  addEvent: function(o, t, h) {
    if (o.addEventListener) o.addEventListener(t, h, false);
    else if (o.attachEvent) o.attachEvent('on'+t, h);
  },
  bind: function (method) {
    var context = this, args = arguments;
    return function() {
      return method.apply(context, Array.prototype.slice.call(args, 1));
    };
  },
  // инициализация
  init: function(full) {
    this.addEvent(window, 'load', this.bind(this.onLoad, full));
  }
};
 
__hc.init(true);

height.html:

<html><head>
<script type="text/javascript">
  // весь location.hash – это высота
  var l = location.hash.replace('#', '');
  if (l) {
    // используем try catch чтобы браузер не матерился
    try {
      parent.parent.document.getElementById('iframe').style.height = l + 'px';
    } catch(e) {}
  }
</script>
</head>
</html>

Смысл в том, что ифрэйм внутри ифрэйма имеет доступ к главному окну, если он располагается на том же домене.

Открываю я два ифрэйма, потому как решение с document.domain имеет свои недостатки, которые на моем сайте довольно тяжело устранить.

При этом решении не портится история браузера, т.к. рабочие ифрэймы каждый раз заново создаются.

height.html – не достается каждый раз с сервака, а берется из кэша браузера

Насчет определения высоты документа в ифрэйме, кроссбраузерного решения я не нашел. При уменьшении контента в ифрэйме, сам ифрэйм не уменьшается, потому как, например, в вебкитовких браузерах и document.body, и document.documentElement разворачиваются по высоте ифрэйма. Для этого я проверяю, если определена функция GetDocumentHeight, используем ее. Т.е. Если на каком-то сайте не устраивает подсчет высоты, то можно реализовать свою функцию — для конкретных случаев это намного проще, чем использовать универсальную.

Комментарии

Артур 08.12.2014 - 18:33

Помогла статья очень,во всех браузерах кроме IE выглядит хорошо,жаль что расширение только в одну сторону ,в IE - бесконечное выделение высоты,- это очень плохо,учитывая что сейчас ещё и на всех мобильных системах IE изначально стоит ,может есть какой то фикс? Не очень разбираюсь в js,может поможете? и есть какая то возможность в этом скрипте дать отступ,скажем на 20px,от низа ,облазил свой css - решение не нашёл,у меня просто там стоит тень,а тень как элемент не воспринимается. У меня всё стоит на одном хосте,но надо внедрить свою заготовку с кучей файлов в wordpress.Мучаюсь.Помогло только это решение.

Добавить комментарий