Обнаружение, когда высота div изменяется с помощью jQuery - PullRequest
139 голосов
/ 06 октября 2008

У меня есть div, который содержит некоторый контент, который добавляется и удаляется динамически, поэтому его высота часто меняется. У меня также есть div, который абсолютно расположен непосредственно под javascript, поэтому, если я не могу определить, когда высота div изменяется, я не могу изменить положение div под ним.

Итак, как я могу определить, когда высота этого элемента изменяется? Я предполагаю, что есть какое-то событие jQuery, которое мне нужно использовать, но я не уверен, к какому из них подключиться.

Ответы [ 10 ]

63 голосов
/ 18 октября 2014

Использовать датчик изменения размера из библиотеки css-element-questions:

https://github.com/marcj/css-element-queries

new ResizeSensor(jQuery('#myElement'), function() {
    console.log('myelement has been resized');
});

Он использует подход, основанный на событиях, и не тратит время вашего процессора. Работает во всех браузерах вкл. IE7 +.

49 голосов
/ 06 августа 2013

Я когда-то писал плагин для attrchange слушателя, который в основном добавляет функцию слушателя при изменении атрибута. Несмотря на то, что я говорю это как плагин, на самом деле это простая функция, написанная как плагин jQuery ... так что, если хотите, удалите специальный код плагина и используйте основные функции.

Примечание: этот код не использует опрос

посмотрите это простое демо http://jsfiddle.net/aD49d/

$(function () {
    var prevHeight = $('#test').height();
    $('#test').attrchange({
        callback: function (e) {
            var curHeight = $(this).height();            
            if (prevHeight !== curHeight) {
               $('#logger').text('height changed from ' + prevHeight + ' to ' + curHeight);

                prevHeight = curHeight;
            }            
        }
    }).resizable();
});

Страница плагина: http://meetselva.github.io/attrchange/

Сокращенная версия: (1.68kb)

(function(e){function t(){var e=document.createElement("p");var t=false;if(e.addEventListener)e.addEventListener("DOMAttrModified",function(){t=true},false);else if(e.attachEvent)e.attachEvent("onDOMAttrModified",function(){t=true});else return false;e.setAttribute("id","target");return t}function n(t,n){if(t){var r=this.data("attr-old-value");if(n.attributeName.indexOf("style")>=0){if(!r["style"])r["style"]={};var i=n.attributeName.split(".");n.attributeName=i[0];n.oldValue=r["style"][i[1]];n.newValue=i[1]+":"+this.prop("style")[e.camelCase(i[1])];r["style"][i[1]]=n.newValue}else{n.oldValue=r[n.attributeName];n.newValue=this.attr(n.attributeName);r[n.attributeName]=n.newValue}this.data("attr-old-value",r)}}var r=window.MutationObserver||window.WebKitMutationObserver;e.fn.attrchange=function(i){var s={trackValues:false,callback:e.noop};if(typeof i==="function"){s.callback=i}else{e.extend(s,i)}if(s.trackValues){e(this).each(function(t,n){var r={};for(var i,t=0,s=n.attributes,o=s.length;t<o;t++){i=s.item(t);r[i.nodeName]=i.value}e(this).data("attr-old-value",r)})}if(r){var o={subtree:false,attributes:true,attributeOldValue:s.trackValues};var u=new r(function(t){t.forEach(function(t){var n=t.target;if(s.trackValues){t.newValue=e(n).attr(t.attributeName)}s.callback.call(n,t)})});return this.each(function(){u.observe(this,o)})}else if(t()){return this.on("DOMAttrModified",function(e){if(e.originalEvent)e=e.originalEvent;e.attributeName=e.attrName;e.oldValue=e.prevValue;s.callback.call(this,e)})}else if("onpropertychange"in document.body){return this.on("propertychange",function(t){t.attributeName=window.event.propertyName;n.call(e(this),s.trackValues,t);s.callback.call(this,t)})}return this}})(jQuery)
28 голосов
/ 06 октября 2008

Вы можете использовать событие DOMSubtreeModified

$(something).bind('DOMSubtreeModified' ...

Но это сработает, даже если размеры не изменятся, и переназначение позиции при каждом срабатывании может нанести удар по производительности. По моему опыту, используя этот метод, проверка того, изменились ли размеры, обходится дешевле, и поэтому вы можете рассмотреть возможность их объединения.

Или, если вы напрямую изменяете div (вместо того, чтобы div изменялся пользовательским вводом непредсказуемым образом, например, если это contentEditable), вы можете просто вызывать пользовательское событие, когда вы это делаете.

Недостаток: IE и Opera не реализуют это событие.

20 голосов
/ 20 мая 2013

Вот как я недавно решил эту проблему:

$('#your-resizing-div').bind('getheight', function() {
    $('#your-resizing-div').height();
});

function your_function_to_load_content() {
    /*whatever your thing does*/
    $('#your-resizing-div').trigger('getheight');
}

Я знаю, что опоздал на вечеринку на несколько лет, но думаю, что мой ответ может помочь некоторым людям в будущем без необходимости загружать какие-либо плагины.

16 голосов
/ 25 октября 2014

Вы можете использовать MutationObserver класс.

MutationObserver предоставляет разработчикам способ реагировать на изменения в DOM. Он предназначен для замены событий мутации, определенных в спецификации событий DOM3.

Пример ( источник )

// select the target node
var target = document.querySelector('#some-id');

// create an observer instance
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.type);
  });    
});

// configuration of the observer:
var config = { attributes: true, childList: true, characterData: true };

// pass in the target node, as well as the observer options
observer.observe(target, config);

// later, you can stop observing
observer.disconnect();
9 голосов
/ 20 сентября 2012

Существует плагин jQuery, который может справиться с этим очень хорошо

http://www.jqui.net/jquery-projects/jquery-mutate-official/

Вот демонстрация с различными сценариями изменения высоты, если вы измените размер div с красной рамкой.

http://www.jqui.net/demo/mutate/

7 голосов
/ 05 августа 2013

В ответе пользователю 007:

Если высота вашего элемента изменяется из-за элементов, добавляемых к нему с помощью .append(), вам не нужно обнаруживать изменение высоты. Просто добавьте репозицию вашего второго элемента в ту же функцию, где вы добавляете новый контент в свой первый элемент.

Как в:

Рабочий пример

$('.class1').click(function () {
    $('.class1').append("<div class='newClass'><h1>This is some content</h1></div>");
    $('.class2').css('top', $('.class1').offset().top + $('.class1').outerHeight());
});
2 голосов
/ 02 июня 2015

Вы можете сделать простой setInterval.

function someJsClass()
{
  var _resizeInterval = null;
  var _lastHeight = 0;
  var _lastWidth = 0;
  
  this.Initialize = function(){
    var _resizeInterval = setInterval(_resizeIntervalTick, 200);
  };
  
  this.Stop = function(){
    if(_resizeInterval != null)
      clearInterval(_resizeInterval);
  };
  
  var _resizeIntervalTick = function () {
    if ($(yourDiv).width() != _lastWidth || $(yourDiv).height() != _lastHeight) {
      _lastWidth = $(contentBox).width();
      _lastHeight = $(contentBox).height();
      DoWhatYouWantWhenTheSizeChange();
    }
  };
}

var class = new someJsClass();
class.Initialize();

EDIT:

Это пример с классом. Но вы можете сделать что-нибудь самое простое.

0 голосов
/ 16 февраля 2018

Довольно простой, но работает:

function dynamicHeight() {
    var height = jQuery('').height();
    jQuery('.edito-wrapper').css('height', editoHeight);
}
editoHeightSize();

jQuery(window).resize(function () {
    editoHeightSize();
});
0 голосов
/ 01 сентября 2017

Вы можете использовать это, но он поддерживает только Firefox и Chrome.

$(element).bind('DOMSubtreeModified', function () {
  var $this = this;
  var updateHeight = function () {
    var Height = $($this).height();
    console.log(Height);
  };
  setTimeout(updateHeight, 2000);
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...