Обнаружение изменения высоты документа
Я пытаюсь определить, когда изменяется высота document
. Как только это произойдет, мне нужно запустить несколько функций, чтобы помочь организовать макет страницы.
Я не ищу window.onresize
. Мне нужен весь документ, который больше окна.
Как я могу наблюдать это изменение?
Ответы
Ответ 1
function onElementHeightChange(elm, callback){
var lastHeight = elm.clientHeight, newHeight;
(function run(){
newHeight = elm.clientHeight;
if( lastHeight != newHeight )
callback();
lastHeight = newHeight;
if( elm.onElementHeightChangeTimer )
clearTimeout(elm.onElementHeightChangeTimer);
elm.onElementHeightChangeTimer = setTimeout(run, 200);
})();
}
onElementHeightChange(document.body, function(){
alert('Body height changed');
});
Ответ 2
Вы можете использовать absolute
расположенный iframe
с нулевой шириной внутри элемента, который вы хотите отслеживать для изменений высоты, и слушать resize
события на своем contentWindow
. Например:
HTML
<body>
Your content...
<iframe class="height-change-listener" tabindex="-1"></iframe>
</body>
CSS
body {
position: relative;
}
.height-change-listener {
position: absolute;
top: 0;
bottom: 0;
left: 0;
height: 100%;
width: 0;
border: 0;
background-color: transparent;
}
JavaScript (с использованием jQuery, но может быть адаптирован к чистому JS)
$('.height-change-listener').each(function() {
$(this.contentWindow).resize(function() {
// Do something more useful
console.log('doc height is ' + $(document).height());
});
});
Если по какой-либо причине у вас есть height:100%
, установленный на body
, вам понадобится найти (или добавить) другой элемент контейнера для его реализации. Если вы хотите добавить iframe
динамически, вам, вероятно, понадобится использовать событие <iframe>.load
для подключения слушателя contentWindow.resize
. Если вы хотите, чтобы это работало в IE7, а также в браузерах, вам нужно добавить хакер *zoom:1
к элементу контейнера, а также прослушать "проприетарное" событие resize
самого элемента <iframe>
(который будет duplicate contentWindow.resize
в IE8-10).
Здесь скрипка...
Ответ 3
Просто мои два цента. Если вы случайно используете angular, то это выполнит задание:
$scope.$watch(function(){
return document.height();
},function onHeightChange(newValue, oldValue){
...
});
Ответ 4
Как упоминалось vsync, нет события, но вы можете использовать таймер или присоединить обработчик где-то еще:
// get the height
var refreshDocHeight = function(){
var h = $(document).height();
$('#result').html("Document height: " + h);
};
// update the height every 200ms
window.setInterval(refreshDocHeight, 200);
// or attach the handler to all events which are able to change
// the document height, for example
$('div').keyup(refreshDocHeight);
Найдите jsfiddle здесь.
Ответ 5
Ответ vsync полностью прекрасен. На всякий случай вам не нравится использовать setTimeout
, и вы можете использовать requestAnimationFrame
(см. Поддержку), и, конечно же, вы все еще интересно.
В приведенном ниже примере тело получает дополнительное событие sizechange
. И каждый раз, когда изменяется высота или ширина тела, он срабатывает.
(function checkForBodySizeChange() {
var last_body_size = {
width: document.body.clientWidth,
height: document.body.clientHeight
};
function checkBodySizeChange()
{
var width_changed = last_body_size.width !== document.body.clientWidth,
height_changed = last_body_size.height !== document.body.clientHeight;
if(width_changed || height_changed) {
trigger(document.body, 'sizechange');
last_body_size = {
width: document.body.clientWidth,
height: document.body.clientHeight
};
}
window.requestAnimationFrame(checkBodySizeChange);
}
function trigger(element, event_name, event_detail)
{
var evt;
if(document.dispatchEvent) {
if(typeof CustomEvent === 'undefined') {
var CustomEvent;
CustomEvent = function(event, params) {
var evt;
params = params || {
bubbles: false,
cancelable: false,
detail: undefined
};
evt = document.createEvent("CustomEvent");
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
};
CustomEvent.prototype = window.Event.prototype;
window.CustomEvent = CustomEvent;
}
evt = new CustomEvent(event_name, {"detail": event_detail});
element.dispatchEvent(evt);
}
else {
evt = document.createEventObject();
evt.eventType = event_name;
evt.eventName = event_name;
element.fireEvent('on' + event_name, evt);
}
}
window.requestAnimationFrame(checkBodySizeChange);
})();
Живая демонстрация
Код может быть значительно уменьшен, если в вашем проекте есть собственная функция triggerEvent
. Поэтому просто удалите полную функцию trigger
и замените строку trigger(document.body, 'sizechange');
на, например, в jQuery $(document.body).trigger('sizechange');
.
Ответ 6
Я использую решение @vsync, вот так. Я использую его для автоматической прокрутки на странице, как твиттер.
const scrollInterval = (timeInterval, retry, cb) => {
let tmpHeight = 0;
const myInterval = setInterval(() => {
console.log('interval');
if (retry++ > 3) {
clearInterval(this);
}
const change = document.body.clientHeight - tmpHeight;
tmpHeight = document.body.clientHeight;
if (change > 0) {
cb(change, (retry * timeInterval));
scrollBy(0, 10000);
}
retry = 0;
}, timeInterval);
return myInterval;
};
const onBodyChange = (change, timeout) => {
console.log('document.body.clientHeight, changed: ${change}, after: ${timeout}');
}
const createdInterval = scrollInterval(500, 3, onBodyChange);
// stop the scroller on some event
setTimeout(() => {
clearInterval(createdInterval);
}, 10000);
Вы также можете добавить минимальное изменение и многое другое... Но это работает для меня
Ответ 7
Команда watch() проверяет любое изменение свойства.
Смотрите эту ссылку: Как определить, когда изменяется высота страницы?