Визначення, коли висота Div змінюється за допомогою jQuery


141

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

Отже, як я можу виявити, коли висота цього діва змінюється? Я припускаю, що мені потрібно скористатись подією jQuery, але я не впевнений, до якого підключити.


4
Цікаво, чому б не хотілося використовувати плагін при використанні jQuery.
Андре Каліл

1
@ user007 Що дозволяє змінити розмір елементів?
А. Вольф

@roasted мій Div зростає, коли якийсь елемент додається до нього, додавання робиться jquery
user007

1
@ user007, тож додавши щось до DIV, ви можете викликати події для зміни розміру для DIV. Іншим способом (найгіршим IMO) може бути використання спеціального методу для додавання вмісту, який просто розширює нативний метод jquery append (), використання його з зворотним дзвоном, наприклад
А. Вольф

@roasted Дякую за пораду.
user007

Відповіді:


64

Використовуйте датчик розміру з бібліотеки css-element-queries:

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

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

Він використовує підхід, заснований на подіях, і не витрачає ваш процесорний час. Працює у всіх браузерах, включаючи IE7 +.


5
Приємне рішення, він використовує новий невидимий елемент як накладення на потрібну ціль і використовує подію "прокрутки" на накладанні, щоб викликати зміни.
Eike Thies

2
Це єдине рішення, яке працює у всіх випадках, у тому числі, коли вміст та атрибути не змінюються, але змінюються розміри (наприклад: відсоткові розміри за допомогою css)
FF_Dev

2
Найкраще рішення на сьогоднішній день.
dlsso

1
Це не найкраща відповідь на це питання - це трагедія. Це справді працює на 100%.
Джимбо Джоні

Це, здається, не працює для елементів, які починаються приховано.
greatwitenorth

48

Я написав плагін колись назад для слухача 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)

25
Це вирішує проблему, якщо змінити розмір діва вручну, це не вирішує оригінальне запитання ні? Якщо ви додаєте вміст динамічно, він не визначає зміни висоти: jsfiddle.net/aD49d/25
smets.kevin

Мені також було б цікаво дізнатись, чи існував спосіб зробити цю роботу динамічним контентом.
EricP

4
@JoeCoder Цей код attrchange покладається на події DOM, викликані браузером, коли відбувається дія користувача. Однак динамічний вміст у цьому прикладі включений програмно, що, на жаль, не викликає жодних подій. Тут, здається, ще один простіший варіант "опитування". Інший варіант зможе запустити вручну після включення динамічного вмісту.
Selvakumar Arumugam

28

Ви можете використовувати подію DOMSubtreeModified

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

Але це спрацює, навіть якщо розміри не зміняться, і переназначення позиції кожного разу, коли воно буде створено, може спричинити показник продуктивності. На моєму досвіді використання цього методу перевіряє, чи змінилися розміри менш дорого, і тому ви можете розглянути можливість комбінування цих двох.

Або якщо ви безпосередньо змінюєте div (замість того, щоб div змінювався введенням користувача непередбачуваними способами, як, наприклад, якщо це contentEditable), ви можете просто запустити користувацьку подію, коли ви це зробите.

Знизу: IE і Opera не реалізують цю подію.


12
IE & Opera не реалізують цю подію: quirksmode.org/dom/events/index.html
DEfusion

14
DomSubtreeModified отримав депримікацію
Адоніс К. Какулідіс,

2
Сучасний спосіб зробити це - використовувати MutationObserver: developer.mozilla.org/en-US/docs/Web/API/MutationObserver
Christian Bankester

21

Ось як я нещодавно вирішив цю проблему:

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

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


1
Я певно певним чином це не найкращий спосіб зробити, але мені це дуже подобається, оскільки це означає, що ви можете викликати його як зворотний виклик в кінці анімації. Плагін змінної розміру триватиме протягом усієї анімації, що може бути корисним, але також може спричинити проблеми. Цей метод принаймні дає вам контроль, коли слід проводити перевірку висоти.
andyface

Що саме робить ваш код? Чому ми не можемо просто використовувати код, який ви пишете всередині події прив'язки, у функції, яка вказує на прив'язку та запуск?
користувач1447420

Але це не автоматично, чи не так?
Альберт Катала

17

Ви можете використовувати 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();

Це правильна відповідь. Також погляньте на MutationSummary, бібліотеку, яка будується на MutationObservers: github.com/rafaelw/mutation-summary
Christian Bankester

9

Є плагін jQuery, який може дуже добре впоратися з цим

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

тут демонструється демонстрація цього сценарію з різними сценаріями щодо зміни висоти, якщо ви зміните розмір червоного облямованого діла.

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


Це красиво, але хіба це не за замовчуванням опитувати інтерфейс користувача кожну мілісекунд на зміни? Це ефективно?
Майкл Скотт Катберт

1
@MichaelScottCuthbert Це було написано давно, але я використовував setTimeout, так що це було би 1 мс + [час, який потрібно робити на перевірку], коротше, але ідея полягала в тому, щоб слухати постійно, як тільки ви це зробите, це знову черга. Я впевнений, що міг би зробити це набагато краще, але не багато часу.
Вал

Ага, так, я бачу, що ти був приблизно за рік до рішення Vega (яке я в кінцевому рахунку використав) і до того, як усі слухачі DOMSubtreeModified тощо отримали широку підтримку. Я навчився тонни, читаючи ваш код, тому я думаю, що варто продовжувати зв'язки.
Майкл Скотт Катберт

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

2

Ви можете зробити простий набірInterval.

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

Редагувати:

Це приклад з класом. Але ти можеш зробити щось найпростіше.


0

Ви можете використовувати це, але він підтримує лише Firefox та Chrome.

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


0

Досить базовий, але працює:

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

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

це буде запущено лише в тому випадку, якщо вікно буде змінено, але ОП хочуть прив'язати подію зміни розміру до конкретного контейнера
Fanie Void
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.