Detect Document Height Change

2019-01-21 05:03发布

问题:

I'm trying to detect when my document height changes. Once it does, I need to run a few functions to help organize my page layout.

I'm not looking for window.onresize. I need the entire document, which is larger than the window.

How do I observe this change?

回答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');
});

LIVE DEMO



回答2:

You can use an absolute positioned iframe with zero width inside the element you want to monitor for height changes, and listen to resize events on its contentWindow. For example:

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 (using jQuery but could be adapted to pure JS)

$('.height-change-listener').each(function() {
  $(this.contentWindow).resize(function() {
    // Do something more useful
    console.log('doc height is ' + $(document).height());
  });
});

If for whatever reason you have height:100% set on body you'll need find (or add) another container element to implement this on. If you want to add the iframe dynamically you'll probably need to use the <iframe>.load event to attach the contentWindow.resize listener. If you want this to work in IE7 as well as browsers, you'll need to add the *zoom:1 hack to the container element and also listen to the 'proprietary' resize event on the <iframe> element itself (which will duplicate contentWindow.resize in IE8-10).

Here's a fiddle...



回答3:

Just my two cents. If by any chance you're using angular then this would do the job:

$scope.$watch(function(){ 
 return document.height();
},function onHeightChange(newValue, oldValue){
 ...
});


回答4:

As mentioned by vsync there is no event but you can use a timer or attach the handler somewhere else:

// 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);

Find the jsfiddle here.



回答5:

vsync's answer is completely fine. Just in case you don't like to use setTimeout and you can use requestAnimationFrame (see support) and of course you are still interested.

In the example below the body gets an extra event sizechange. And every time the height or width of the body changes it is triggered.

(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);
})();

A live demo

The code can be reduced much if you have an own triggerEvent function in your project. Therefore just remove the complete function trigger and replace the line trigger(document.body, 'sizechange'); with for example in jQuery $(document.body).trigger('sizechange');.



回答6:

The command watch() checks any change in a property.

See this link: How to detect when the height of your page changes?