87 votes

Détecter le changement de hauteur du document

J'essaie de détecter quand mon document changements de hauteur. Une fois que c'est fait, j'ai besoin d'exécuter quelques fonctions pour aider à organiser ma mise en page.

Je ne cherche pas à window.onresize . J'ai besoin du document entier, qui est plus grand que la fenêtre.

Comment puis-je observer ce changement ?

120voto

vsync Points 11280

Mise à jour (octobre 2020) :

resizeObserver est une merveilleuse API ( table de support )

// create an Observer instance
const resizeObserver = new ResizeObserver(entries => 
  console.log('Body height changed:', entries[0].target.clientHeight)
)

// start observing a DOM node
resizeObserver.observe(document.body)

// click anywhere to rnadomize height
window.addEventListener('click', () =>
  document.body.style.height = Math.floor((Math.random() * 5000) + 1) + 'px'
)

click anywhere to change the height

Vieille réponse :

Bien qu'il s'agisse d'un "hack", cette fonction simple "écoute" en permanence (par le biais de setTimeout) les modifications de la hauteur d'un élément et déclenche un callback lorsqu'une modification est détectée.

Il est important de prendre en compte les caractéristiques d'un élément. hauteur peut changer indépendamment de toute action entreprise par un utilisateur ( redimensionner , cliquez sur ) et donc, puisqu'il est impossible de savoir ce qui peut provoquer un changement de hauteur, tout ce que l'on peut faire pour garantir absolument une détection à 100% est de placer un contrôleur de hauteur à intervalles :

function onElementHeightChange(elm, callback) {
  var lastHeight = elm.clientHeight, newHeight;

  (function run() {
    newHeight = elm.clientHeight;
    if (lastHeight != newHeight)
      callback(newHeight)
    lastHeight = newHeight

    if (elm.onElementHeightChangeTimer)
      clearTimeout(elm.onElementHeightChangeTimer)

    elm.onElementHeightChangeTimer = setTimeout(run, 200)
  })()
}

// to clear the timer use:
// clearTimeout(document.body.onElementHeightChangeTimer);

// DEMO:
document.write("click anywhere to change the height")

onElementHeightChange(document.body, function(h) {
  console.log('Body height changed:', h)
})

window.addEventListener('click', function() {
  document.body.style.height = Math.floor((Math.random() * 5000) + 1) + 'px'
})

DÉMO EN DIRECT

28voto

user2511031 Points 41

Vous pouvez utiliser un absolute positionné sur iframe avec une largeur nulle à l'intérieur de l'élément que vous voulez surveiller pour les changements de hauteur, et écouter les resize sur son contentWindow . Par exemple :

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 (utilisant jQuery mais pouvant être adapté à du JS pur)

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

Si pour une raison quelconque, vous avez height:100% mis en place body vous devrez trouver (ou ajouter) un autre élément de conteneur pour l'implémenter. Si vous voulez ajouter l'élément iframe de manière dynamique, vous devrez probablement utiliser la fonction <iframe>.load pour attacher le contentWindow.resize écouteur. Si vous voulez que cela fonctionne dans IE7 ainsi que dans les autres navigateurs, vous devrez ajouter l'option *zoom:1 au niveau de l'élément conteneur et écoute également l'élément "propriétaire". resize sur l'événement <iframe> lui-même (qui dupliquera l'élément contentWindow.resize dans IE8-10).

Voici un violon ...

12voto

Dan Ochiana Points 56

Juste mes deux centimes. Si par hasard vous utilisez angular, ceci fera l'affaire :

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

12voto

jpschroeder Points 2615

Mise à jour : 2020

Il existe désormais un moyen d'y parvenir en utilisant la nouvelle fonction ResizeObserver . Cela vous permet d'écouter toute une liste d'éléments pour savoir quand leur élément change de taille. L'utilisation de base est assez simple :

const observer = new ResizeObserver(entries => {
  for (const entry of entries) {
    // each entry is an instance of ResizeObserverEntry
    console.log(entry.contentRect.height)
  }
})
observer.observe(document.querySelector('body'))

L'inconvénient est qu'il n'existe actuellement qu'un support pour Chrome/Firefox, mais vous pouvez trouver de solides polyfills sur le marché. Voici un exemple de codepen que j'ai écrit :

https://codepen.io/justin-schroeder/pen/poJjGJQ?editors=1111

4voto

Predator Points 4000

Comme mentionné par vsync, il n'y a pas d'événement mais vous pouvez utiliser une minuterie ou attacher le gestionnaire à un autre endroit :

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

Trouvez le jsfiddle ici .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X