Обнаружение при изменении высоты div с помощью jQuery

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

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

Ответ 1

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

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

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

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

Ответ 2

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

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

ознакомьтесь с этой простой демонстрацией 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)

Ответ 3

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

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

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

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

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

Ответ 4

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

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

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

Ответ 5

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

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

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

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

Ответ 6

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

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

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

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

Ответ 7

В ответ на user007:

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

Как в:

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

$('.class1').click(function () {
    $('.class1').append("<div class='newClass'><h1>This is some content</h1></div>");
    $('.class2').css('top', $('.class1').offset().top + $('.class1').outerHeight());
});

Ответ 8

Вы можете сделать простой 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();

Ответ 9

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

$(element).bind('DOMSubtreeModified', function () {
  var $this = this;
  var updateHeight = function () {
    var Height = $($this).height();
    console.log(Height);
  };
  setTimeout(updateHeight, 2000);
});

Ответ 10

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

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

jQuery(window).resize(function () {
    editoHeightSize();
});