Как отследить изменение размера div'ов?

323
07 июля 2017, 04:04

У меня есть HTML код, в нём есть div, который имеет ширину в 100%. Он содержит несколько элементов. При изменении размера окна внутренние элементы могут быть перегруппированы, и размер div может измениться.

Можно ли подключить событие изменения размера div? И как это сделать?

В настоящее время я привязываю функцию обратного вызова к событию resize jQuery на нужный div, однако результат не выводится, см. Ниже:

<html>
<head>
    <script type="text/javascript" language="javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
    <script type="text/javascript" language="javascript">
            $('#test_div').bind('resize', function(){
                console.log('resized');
            });
    </script>
</head>
<body>
    <div id="test_div" style="width: 100%; min-height: 30px; border: 1px dashed pink;">
        <input type="button" value="button 1" />
        <input type="button" value="button 2" />
        <input type="button" value="button 3" />
    </div>
</body>
</html>
Answer 1

Самое простое решение:

var blockWidth = $('.block').outerWidth(); 
$(window).resize(function() { 
  if (blockWidth != $('.block').outerWidth()) { 
    console.log('resized') 
  } 
});
.block { 
  max-width:300px; 
  height:100px; 
  background:#000; 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
<div class="block"></div>

Конкретно на вашем примере:

var blockWidth = $('#test_div').outerWidth(); 
$(window).resize(function() { 
  if (blockWidth != $('#test_div').outerWidth()) { 
    console.log('resized') 
  } 
});
.block { 
  max-width: 300px; 
  height: 100px; 
  background: #000; 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="test_div" style="width: 100%; min-height: 30px; border: 1px dashed pink;"> 
  <input type="button" value="button 1" /> 
  <input type="button" value="button 2" /> 
  <input type="button" value="button 3" /> 
</div>

Answer 2

Существует очень эффективный метод определения того, был ли изменен размер элемента.

http://marcj.github.io/css-element-queries/

Код библиотеки:

/**
 * Copyright Marc J. Schmidt. See the LICENSE file at the top-level
 * directory of this distribution and at
 * https://github.com/marcj/css-element-queries/blob/master/LICENSE.
 */
;
(function(root, factory) {
  if (typeof define === "function" && define.amd) {
    define(factory);
  } else if (typeof exports === "object") {
    module.exports = factory();
  } else {
    root.ResizeSensor = factory();
  }
}(this, function() {
  // Make sure it does not throw in a SSR (Server Side Rendering) situation
  if (typeof window === "undefined") {
    return null;
  }
  // Only used for the dirty checking, so the event callback count is limited to max 1 call per fps per sensor.
  // In combination with the event based resize sensor this saves cpu time, because the sensor is too fast and
  // would generate too many unnecessary events.
  var requestAnimationFrame = window.requestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    function(fn) {
      return window.setTimeout(fn, 20);
    };
  /**
   * Iterate over each of the provided element(s).
   *
   * @param {HTMLElement|HTMLElement[]} elements
   * @param {Function}                  callback
   */
  function forEachElement(elements, callback) {
    var elementsType = Object.prototype.toString.call(elements);
    var isCollectionTyped = ('[object Array]' === elementsType ||
      ('[object NodeList]' === elementsType) ||
      ('[object HTMLCollection]' === elementsType) ||
      ('[object Object]' === elementsType) ||
      ('undefined' !== typeof jQuery && elements instanceof jQuery) //jquery
      ||
      ('undefined' !== typeof Elements && elements instanceof Elements) //mootools
    );
    var i = 0,
      j = elements.length;
    if (isCollectionTyped) {
      for (; i < j; i++) {
        callback(elements[i]);
      }
    } else {
      callback(elements);
    }
  }
  /**
   * Class for dimension change detection.
   *
   * @param {Element|Element[]|Elements|jQuery} element
   * @param {Function} callback
   *
   * @constructor
   */
  var ResizeSensor = function(element, callback) {
    /**
     *
     * @constructor
     */
    function EventQueue() {
      var q = [];
      this.add = function(ev) {
        q.push(ev);
      };
      var i, j;
      this.call = function() {
        for (i = 0, j = q.length; i < j; i++) {
          q[i].call();
        }
      };
      this.remove = function(ev) {
        var newQueue = [];
        for (i = 0, j = q.length; i < j; i++) {
          if (q[i] !== ev) newQueue.push(q[i]);
        }
        q = newQueue;
      }
      this.length = function() {
        return q.length;
      }
    }
    /**
     *
     * @param {HTMLElement} element
     * @param {Function}    resized
     */
    function attachResizeEvent(element, resized) {
      if (!element) return;
      if (element.resizedAttached) {
        element.resizedAttached.add(resized);
        return;
      }
      element.resizedAttached = new EventQueue();
      element.resizedAttached.add(resized);
      element.resizeSensor = document.createElement('div');
      element.resizeSensor.className = 'resize-sensor';
      var style = 'position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; z-index: -1; visibility: hidden;';
      var styleChild = 'position: absolute; left: 0; top: 0; transition: 0s;';
      element.resizeSensor.style.cssText = style;
      element.resizeSensor.innerHTML =
        '<div class="resize-sensor-expand" style="' + style + '">' +
        '<div style="' + styleChild + '"></div>' +
        '</div>' +
        '<div class="resize-sensor-shrink" style="' + style + '">' +
        '<div style="' + styleChild + ' width: 200%; height: 200%"></div>' +
        '</div>';
      element.appendChild(element.resizeSensor);
      if (element.resizeSensor.offsetParent !== element) {
        element.style.position = 'relative';
      }
      var expand = element.resizeSensor.childNodes[0];
      var expandChild = expand.childNodes[0];
      var shrink = element.resizeSensor.childNodes[1];
      var dirty, rafId, newWidth, newHeight;
      var lastWidth = element.offsetWidth;
      var lastHeight = element.offsetHeight;
      var reset = function() {
        expandChild.style.width = '100000px';
        expandChild.style.height = '100000px';
        expand.scrollLeft = 100000;
        expand.scrollTop = 100000;
        shrink.scrollLeft = 100000;
        shrink.scrollTop = 100000;
      };
      reset();
      var onResized = function() {
        rafId = 0;
        if (!dirty) return;
        lastWidth = newWidth;
        lastHeight = newHeight;
        if (element.resizedAttached) {
          element.resizedAttached.call();
        }
      };
      var onScroll = function() {
        newWidth = element.offsetWidth;
        newHeight = element.offsetHeight;
        dirty = newWidth != lastWidth || newHeight != lastHeight;
        if (dirty && !rafId) {
          rafId = requestAnimationFrame(onResized);
        }
        reset();
      };
      var addEvent = function(el, name, cb) {
        if (el.attachEvent) {
          el.attachEvent('on' + name, cb);
        } else {
          el.addEventListener(name, cb);
        }
      };
      addEvent(expand, 'scroll', onScroll);
      addEvent(shrink, 'scroll', onScroll);
    }
    forEachElement(element, function(elem) {
      attachResizeEvent(elem, callback);
    });
    this.detach = function(ev) {
      ResizeSensor.detach(element, ev);
    };
  };
  ResizeSensor.detach = function(element, ev) {
    forEachElement(element, function(elem) {
      if (!elem) return
      if (elem.resizedAttached && typeof ev == "function") {
        elem.resizedAttached.remove(ev);
        if (elem.resizedAttached.length()) return;
      }
      if (elem.resizeSensor) {
        if (elem.contains(elem.resizeSensor)) {
          elem.removeChild(elem.resizeSensor);
        }
        delete elem.resizeSensor;
        delete elem.resizedAttached;
      }
    });
  };
  return ResizeSensor;
}));

Эта библиотека имеет класс ResizeSensor, который можно использовать для определения размера.

Он основан на событиях, поэтому он чертовски быстро определяет и не нагружает процессор.

Пример:

new ResizeSensor(jQuery('#divId'), function(){ 
    console.log('content dimension changed');
});

Пожалуйста, не используйте плагин resize для jQuery, поскольку он использует цикл setTimeout() для проверки изменений.

READ ALSO
Письмо не отправляется на почту

Письмо не отправляется на почту

По какой причине письмо не отправляется на почту? Заранее благодарен

343
Изменить каждое число в тексте на заданную величину

Изменить каждое число в тексте на заданную величину

Есть файл стилейНужно изменить размер каждого шрифта на заданную величину

250
Можно ли установить кнопку для запуска WhatsApp на сайте

Можно ли установить кнопку для запуска WhatsApp на сайте

Есть ли возможность запуска чата WhatsApp со своей картинкой? Если да, то какое?

334
Как сделать широкий текстовый курсор в input type=text

Как сделать широкий текстовый курсор в input type=text

Нужно зделать широкий текстовый курсор в input type=text и чтобы при перемещении его назад он становился под буквой, а та окрашивалась в контрастный...

312