Событие при изменении размеров блочного элемента — resize

Иногда нужно отслеживать поведение блочного элемента и при изменении его размеров запускать дополнительный код. Актуально при адаптивной вёрстке или подгрузке контента через AJAX, когда размеры блочного элемента заранее не известны. Например у меня адаптивная вёрстка, нужно чтобы при уменьшении ширины окна некоторые пункты основного горизонтального меню перемещались в дополнительное вертикальное меню, которое открывается при наведении мышкой. В моём случае учитываются border, padding, scrollbar и content блочного элемента, но вы можете изменить код исходя из ваших задач.

P.S. Все браузеры, кроме IE 9 включительно.

<html>
<head>
  <meta charset="UTF-8">
</head>
<body onload="javascript:res(0,0,0,0)">

<script type="text/javascript">
function res(width, height, timeout, validation) {
  var item = document.getElementById('test_two');
	
  if((width == item.offsetWidth) && (height == item.offsetHeight)) {
	
    if(validation) {
      // Сработает при изменении размеров блочного элементов, для тестирования можно раскомментировать нижнюю строку.
      // document.getElementById('test').innerHTML = Date();
    } else {
      timeout = 500;
    }		
    window.setTimeout(res, timeout, width, height, timeout, 0);
		
  } else {
    width = item.offsetWidth;
    height = item.offsetHeight;
    timeout = 200;
    window.setTimeout(res, timeout, width, height, timeout, 1);
  }
	
}
</script>

  <div id="test"></div>
  <div id="test_two"><p>Test JavaScript.</p></div>
	
</body>
</html>

Similar posts

Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 12

    +2
    По таймеру проверять размеры не лучшее решение.
    Можно фрейм кинуть внутрь элемента и подписаться на событие resize

    https://codepen.io/AHDPEu/pen/ALvawa
      0

      Фреймы — очень тяжеловесные штуки. Как по памяти так и по времени создания.

        +2
        Хорошо, пусть это будет тег object
        Ещё надо проверить, что тяжелее по памяти, времени создания и тд, пустой фрейм с одним событием или таймер раз в 200 / 500 мс который опрашивает размеры и тем самым запускает не менее тяжелые операции для браузера.

        Так в этом коде нужно добавить проверку, что элемент существует. Получить утечку неопытному программисту проще простого.
          0
          Вообще задача автора решается на чистом css, можно посмотреть примеры многих css фреймворков, где от ширины окна меню прячется под иконку с бургером. Задав каждому элементу max-width одинаковый, можно прятать нужное количество таких элементов и одновременно показывать из в меню под бургер иконкой.

          Я сначала подумал, что требуется событие действительно на блочный элемент (например, с position:absolute), а не на окно браузера.
            0
            Событие требуется именно на блочный элемент, потому что размеры окна могут не изменится. В моём случае количество элементов меню и ширина каждого элемента заранее не известна, мне не нужно из горизонтального меню делать вертикальное. У меня имеется горизонтальное и вертикальное меню, когда в горизонтальное меню элементы больше не помещается, они перемещаются в вертикальное меню. Я низнаю решения такой задачи с адаптивной вёрсткой на CSS, поэтому предложил такое.
            0

            Если в доме ничего не менялось, то reflow происходить не будет. Браузеры не настолько тупые. А вот фрейм — это полноценное окно с полным фаршем — свой дом, свои js объекты, свои события и тп.

        +2
        На мой взгляд, лучше отслеживать глобальное событие resize, но стартовать обработчик не на каждый тик, а с ограничением количества срабатываний.
        Пример: MDN resize
        А уже внутри этого обработчика производить необходимые действия на всю разметку.
          0
          https://habrahabr.ru/post/312536/#comment_9857266
          0
          window.resize нужно делать в вашем случае.
            0
            Я не зря сделал акцент, что отслеживаем размеры блочного элемента, потому что window.resize может не изменится.
            0
            https://github.com/marcj/css-element-queries
              +3
              И зачем это на хабре? До проверки через timeout даже junior сам дойдет и подобных решений в гугле куча.
              Относительно нормальное решение:
              let target = document.getElementById(divId);
              let $target = $(target);
              let lastHeight = $target.height();
              
              let observer = new MutationObserver(() => {
                  let newHeight = $target.height();
                  if (lastHeight !== newHeight) {
                     // делаем что то
                      lastHeight = newHeight;
                  }
              });
              
              observer.observe(target, { attributes: true, subtree: true });
              

              П.с полифил для MutationObserver искать на гитхабе

              Only users with full accounts can post comments. Log in, please.