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

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

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

Интересно, почему бы не использовать плагин при использовании jQuery.

Andre Calil 02.08.2013 17:16

@ user007 Что меняет размер ваших элементов?

A. Wolff 02.08.2013 21:28

@roasted моя высота div изменяется, когда к нему добавляется какой-то элемент, добавление выполняется jquery

user007 03.08.2013 15:00

@ user007, поэтому, когда вы добавляете что-то в DIV, вы можете инициировать настраиваемое событие изменения размера для DIV. Другой способ (худший IMO) может заключаться в использовании пользовательского метода для добавления контента, который просто расширяет собственный метод jquery append (), используйте его с обратным вызовом, например

A. Wolff 03.08.2013 15:15

@roasted Спасибо за подсказку.

user007 07.08.2013 09:13
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
141
5
203 151
11

Ответы 11

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

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

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

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

Оборотная сторона: IE и Opera не реализуют это событие.

IE и Opera не реализуют это событие: quirksmode.org/dom/events/index.html

DEfusion 10.10.2009 19:10

DomSubtreeModified устарел

Adonis K. Kakoulidis 14.02.2013 09:11

Современный способ сделать это - использовать MutationObserver: developer.mozilla.org/en-US/docs/Web/API/MutationObserver

Christian Bankester 30.09.2015 16:08

Есть плагин jQuery, который отлично справляется с этим.

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

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

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

Это красиво, но разве он по умолчанию не опрашивает пользовательский интерфейс каждую миллисекунду на предмет изменений? Это эффективно?

Michael Scott Cuthbert 17.08.2014 18:44

@MichaelScottCuthbert Это было написано очень давно, но я использовал setTimeout, так что это будет 1 мс + [время, необходимое для выполнения проверок] вкратце, но идея заключалась в том, чтобы постоянно слушать, как только вы снова его активируете, это как очередь. Я уверен, что смог бы сделать это намного лучше, но не так много времени.

Val 20.08.2014 14:23

Ах, да, я вижу, что вы были примерно за год до решения Vega (которое я в конечном итоге использовал) и до того, как все слушатели DOMSubtreeModified и т. д. Получили широкую поддержку. Я многому научился, читая ваш код, поэтому думаю, что стоит поддерживать ссылки.

Michael Scott Cuthbert 20.08.2014 18:03

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

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

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

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

andyface 12.07.2013 13:51

Что именно делает ваш код? Почему мы не можем просто использовать код, который вы пишете внутри события привязки, в функции привязки и запуска?

user1447420 19.06.2015 15:25

Но это не происходит автоматически, не так ли?

Albert Català 09.09.2015 13:19

В ответ на 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());
});

Некоторое время назад я написал плагин для слушателя 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.68кб)

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

Это решает проблему, если вы изменяете размер div вручную, это не решает исходный вопрос, нет? Если вы добавляете контент динамически, изменение высоты не обнаруживается: jsfiddle.net/aD49d/25

smets.kevin 11.09.2013 10:37

Мне также было бы интересно узнать, есть ли способ заставить эту работу работать с динамическим контентом.

EricP 22.09.2013 22:28

@JoeCoder Этот код attrchange полагается на события DOM, запускаемые браузером, когда есть действие пользователя. Однако динамическое содержимое в этом примере включено программно, что, к сожалению, не вызывает никаких событий. «Опрос» кажется здесь еще одним более простым вариантом ... другой вариант можно было бы запускать вручную после включения динамического содержимого.

Selvakumar Arumugam 23.09.2013 00:12

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

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

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

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

хорошее решение, он использует невидимый новый элемент в качестве наложения на желаемую цель и использует событие «прокрутки» на наложении, чтобы инициировать изменения.

Eike Thies 20.11.2014 20:59

Это единственное решение, которое работает во всех случаях, в том числе когда содержимое и атрибуты не меняются, а размеры меняются (пример: процентные измерения с использованием CSS)

FF_Dev 18.02.2015 14:42

Лучшее решение на сегодняшний день.

dlsso 22.04.2016 21:45

Это не самый популярный ответ - трагедия. Это действительно работает на 100%.

Jimbo Jonny 27.05.2016 11:47

Похоже, это не работает для элементов, которые начинаются как скрытые.

greatwitenorth 23.02.2017 23:11

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

Tarun Gupta 11.07.2017 15:52

This doesn't seem to work for elements which start off hidden Тем временем работает с v1.0.5.

Marc J. Schmidt 22.10.2018 12:09

Вы можете использовать класс 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.info(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();

Это правильный ответ. Также обратите внимание на MutationSummary, библиотеку, основанную на MutationObservers: github.com/rafaelw/mutation-summary

Christian Bankester 30.09.2015 16:10

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

Обновлено:

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

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

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

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

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

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

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

Fanie Void 28.02.2019 16:35

В наши дни вы также можете использовать веб-API ResizeObserver.

Простой пример:

const resizeObserver = new ResizeObserver(() => {
    console.info('size changed');
});

resizeObserver.observe(document.querySelector('#myElement'));

Другие вопросы по теме