jquery отримує висоту вмісту iframe при завантаженні


84

У мене є сторінка довідки, help.php, яку я завантажую всередині iframe в main.php Як я можу отримати висоту цієї сторінки, як тільки вона завантажиться в iframe?

Я прошу це, тому що я не можу встановити висоту для iframe до 100% або авто. Ось чому я думаю, що мені потрібно використовувати javascript .. Я використовую jQuery

CSS:

body {
    margin: 0;
    padding: 0;
}
.container {
    width: 900px;
    height: 100%;
    margin: 0 auto;
    background: silver;
}
.help-div {
    display: none;
    width: 850px;
    height: 100%;
    position: absolute;
    top: 100px;
    background: orange;
}
#help-frame {
    width: 100%;
    height: auto;
    margin:0;
    padding:0;
}

JS:

$(document).ready(function () {
    $("a.open-help").click(function () {
        $(".help-div").show();
        return false;
    })
})

HTML:

<div class='container'>
    <!-- -->
    <div class='help-div'>
        <p>This is a div with an iframe loading the help page</p>
        <iframe id="help-frame" src="../help.php" width="100%" height="100%" frameborder="1"></iframe>
    </div>  <a class="open-help" href="#">open Help in iFrame</a>

    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
</div>

Чи вміст iFrame надходить із того самого домену, що і сторінка, на якій він знаходиться?
Ендрю

так це andrew, я хочу використовувати iFrame, оскільки я використовую прив'язки на сторінці довідки
FFish

Відповіді:


102

добре, нарешті я знайшов хороше рішення:

$('iframe').load(function() {
    this.style.height =
    this.contentWindow.document.body.offsetHeight + 'px';
});

Оскільки деякі веб-переглядачі (старіші Safari та Opera) повідомляють про завантаження, виконане перед відтворенням CSS, вам потрібно встановити мікротаймаут, а також очистити та перепризначити src iframe.

$('iframe').load(function() {
    setTimeout(iResize, 50);
    // Safari and Opera need a kick-start.
    var iSource = document.getElementById('your-iframe-id').src;
    document.getElementById('your-iframe-id').src = '';
    document.getElementById('your-iframe-id').src = iSource;
});
function iResize() {
    document.getElementById('your-iframe-id').style.height = 
    document.getElementById('your-iframe-id').contentWindow.document.body.offsetHeight + 'px';
}

це рішення чудово працює, оскільки вищезазначене просто отримує розмір із вмісту фреймів у контейнері, тоді як воно отримує realрозмір
rickyduck

2
Я вважаю, що подія навантаження спрацьовує в тому ж циклі події, тому setTimout в 1 мілісекунду спрацює так само добре
Джордж Мауер

hhmmm Будь-хто знає, як отримати висоту iframe, яка прихована під час завантаження батьків. Цей метод повертає 0.
JT ...

1
Можливо, вам потрібна documentвисота, а не bodyвисота. За допомогою jQuery ви можете захопити його $(this.contentWindow.document).height().
vpiTriumph

Для старих, тобто iframe.contentDocument.body.offsetHeight буде працювати. stackoverflow.com/questions/2684693 / ...
user1087079

50

Менш складна відповідь - використовувати, .contents()щоб отримати в iframe. Цікаво, що, однак, він повертає інше значення, ніж те, що я отримую, використовуючи код у моїй оригінальній відповіді, через відступ на тілі, я вважаю.

$('iframe').contents().height() + 'is the height'

Ось як я це зробив для міждоменного спілкування, тому боюся, що це може бути надмірно складним. По-перше, я б помістив jQuery всередину документа iFrame; це споживає більше пам'яті, але це не повинно збільшувати час завантаження, оскільки сценарій потрібно завантажувати лише один раз.

Використовуйте jQuery iFrame, щоб якомога раніше виміряти висоту тіла вашого iframe (onDOMReady), а потім встановити хеш URL-адреси на цю висоту. А в батьківському документі додайте onloadподію до тегу iFrame, яка буде шукати розташування iframe та витягувати потрібне вам значення. Оскільки onDOMReady завжди відбуватиметься до події завантаження документа, ви можете бути впевнені, що значення буде передано коректно, не спричиняючи ситуації, що ускладнює ситуацію.

Іншими словами:

... у Help.php:

var getDocumentHeight = function() {
    if (location.hash === '') { // EDIT: this should prevent the retriggering of onDOMReady
        location.hash = $('body').height(); 
        // at this point the document address will be something like help.php#1552
    }
};
$(getDocumentHeight);

... а в батьківському документі:

var getIFrameHeight = function() {
    var iFrame = $('iframe')[0]; // this will return the DOM element
    var strHash = iFrame.contentDocument.location.hash;
    alert(strHash); // will return something like '#1552'
};
$('iframe').bind('load', getIFrameHeight );

Привіт, Ендрю, поки що тут дуже хороша допомога. contents () чудово працює, але мені все одно потрібно протестувати його за допомогою дроселя пропускної здатності. Можливо, ви можете використовувати властивість innerHeight (). У мене проблема в FF (OSX) із використанням вашого рішення, що встановлює висоту в хеш. FF, здається, продовжує завантажувати функцію getDocumentHeight () у інфінітивний цикл? Сафарі в порядку ..
FFish

Цікаво. Я додав перевірку, яка запобігає встановленню хешу, якщо там уже є значення. Можливо, вам доведеться налаштувати це, якщо ви завантажуєте Help.php із хеш-значенням (наприклад <iframe src="../Help.php#introduction" />)
Ендрю

До речі, якщо припустити, що ви можете налаштувати різницю у висоті, вам, ймовірно, не потрібно використовувати хеш для спілкування поза рамкою. Якщо ви все-таки використовуєте хеш-метод, розміщення sleep(5)у вашому Help.php також має бути хорошим способом тестування на будь-які умови гонки. Якщо iframe якось спрацьовує onLoadраніше onDOMReady, він повинен з'явитися тут.
Ендрю

23

Я виявив, що в Chrome, Firefox та IE11 працює наступне:

$('iframe').load(function () {
    $('iframe').height($('iframe').contents().height());
});

Коли завантаження вмісту Iframes завершиться, подія спрацює, і вона встановить висоту IFrames до рівня її вмісту. Це буде працювати лише для сторінок з тим самим доменом, що і в IFrame.


працює нормально, але для ширини я повинен робити це так, або вміст вирізається $ ('iframe'). width ($ ('iframe'). contents (). width () + 30);
Geomorillo

@AminGhaderi чудово працює для мене у firefox 40.0.3
mixkat

@mixkat я завантажую веб-сайт у iframe за допомогою цього рішення та всіх рішень у цій темі, але для мене це не працює! Я думаю, що ці рішення працюють для однієї сторінки і не працюють, коли ми завантажуємо повний веб-сайт у iframe. моя англійська дуже погана, сподіваюся, ви зрозумієте.
Амін Гадері

@AminGhaderi, якщо я отримав це право, ви очікуєте, що це буде працювати на кожній сторінці вашого сайту, але, звичайно, це не буде працювати на всіх сторінках, оскільки воно запускається лише один раз, коли ви завантажуєте фрейм. Отже, це буде працювати для першої сторінки нормально, але тоді, якщо ви хочете, щоб вона працювала для довших сторінок, вам доведеться це зробити знову, або завантаживши фрейм знову на нову сторінку, або зателефонувавши вмісту. ваш потік
mixkat

9

Код, щоб зробити це без jQuery, сьогодні є тривіальним:

const frame = document.querySelector('iframe')
function syncHeight() {
  this.style.height = `${this.contentWindow.document.body.offsetHeight}px`
}
frame.addEventListener('load', syncHeight)

Щоб від'єднати подію:

frame.removeEventListener('load', syncHeight)

3
Приємно і просто! На жаль, не працює для міждоменних фреймів :(
TimoSolo

3
Так, там не пощастило. Для цього я використав би бібліотеку iframe-resizer. Звичайно, вам потрібно контролювати обидва домени, щоб це працювало.
камерлен

6

Для цього вам не потрібен jquery всередині iframe, але я використовую його, оскільки код набагато простіший ...

Помістіть це в документ всередині вашого iframe.

$(document).ready(function() {
  parent.set_size(this.body.offsetHeight + 5 + "px");  
});

додав п’ять вище, щоб усунути смугу прокрутки на маленьких вікнах, вона ніколи не ідеальна за розміром.

І це всередині вашого батьківського документа.

function set_size(ht)
{
$("#iframeId").css('height',ht);
}

Це також не буде працювати, якщо ви відображаєте PDF-файл у внутрішньому кадрі.
Jason Foglia

Вибачте, але ваш приклад "усередині кадру" явно заснований на jQuery.
T-moty

4

це правильна відповідь, яка спрацювала для мене

$(document).ready(function () {
        function resizeIframe() {
            if ($('iframe').contents().find('html').height() > 100) {
                $('iframe').height(($('iframe').contents().find('html').height()) + 'px')
            } else {
                setTimeout(function (e) {
                    resizeIframe();
                }, 50);
            }
        }
        resizeIframe();
    });

4

простий однокласник починається з мінімальної висоти за замовчуванням і збільшується до розміру вмісту.

<iframe src="http://url.html" onload='javascript:(function(o){o.style.height=o.contentWindow.document.body.scrollHeight+"px";}(this));' style="height:200px;width:100%;border:none;overflow:hidden;"></iframe>



1

Це безкоштовне рішення jQuery, яке може працювати зі SPA всередині iframe

document.getElementById('iframe-id').addEventListener('load', function () {
  let that = this;
  setTimeout(function () {
    that.style.height = that.contentWindow.document.body.offsetHeight + 'px';
  }, 2000) // if you're having SPA framework (angularjs for example) inside the iframe, some delay is needed for the content to populate
});

1

Це мій дружній прийом без використання j6

document.querySelector('iframe').addEventListener('load', function() {
    const iframeBody = this.contentWindow.document.body;
    const height = Math.max(iframeBody.scrollHeight, iframeBody.offsetHeight);
    this.style.height = `${height}px`;
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.