У меня есть div, который содержит некоторый контент, который добавляется и удаляется динамически, поэтому его высота часто меняется. У меня также есть div, который абсолютно позиционируется непосредственно под ним с помощью javascript, поэтому, если я не могу определить, когда изменяется высота div, я не могу переместить div под ним.
Итак, как я могу определить, когда изменяется высота этого div? Я предполагаю, что мне нужно использовать какое-то событие jQuery, но я не уверен, к какому из них подключиться.
javascript
jquery
Боб Сомерс
источник
источник
Ответы:
Используйте датчик изменения размера из библиотеки css-element-query:
https://github.com/marcj/css-element-queries
new ResizeSensor(jQuery('#myElement'), function() { console.log('myelement has been resized'); });
Он использует подход, основанный на событиях, и не тратит ваше время на процессор. Работает во всех браузерах, в т.ч. IE7 +.
источник
Когда-то я написал плагин для прослушивателя 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)
источник
Вы можете использовать событие DOMSubtreeModified
$(something).bind('DOMSubtreeModified' ...
Но это сработает, даже если размеры не изменятся, а переназначение позиции при срабатывании может снизить производительность. По моему опыту использования этого метода, проверка того, изменились ли размеры, менее затратна, поэтому вы можете подумать об их объединении.
Или, если вы напрямую изменяете div (а не изменяете div непредсказуемым образом, например, если он является contentEditable), вы можете просто запускать настраиваемое событие всякий раз, когда вы это делаете.
Обратная сторона: IE и Opera не реализуют это событие.
источник
Вот как я недавно справился с этой проблемой:
$('#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'); }
Я знаю, что опаздываю на вечеринку на несколько лет, просто думаю, что мой ответ может помочь некоторым людям в будущем, без необходимости загружать какие-либо плагины.
источник
Вы можете использовать
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();
источник
Есть плагин jQuery, который отлично справляется с этим.
http://www.jqui.net/jquery-projects/jquery-mutate-official/
вот его демонстрация с различными сценариями изменения высоты, если вы измените размер div с красной рамкой.
http://www.jqui.net/demo/mutate/
источник
setTimeout
, так что это будет 1 мс + [время, необходимое для выполнения проверок] вкратце, но идея заключалась в том, чтобы постоянно слушать, как только вы сделаете это снова, это похоже на очередь. Я уверен, что смогу сделать это намного лучше, но не так много времени.В ответ на 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()); });
источник
Вы можете сделать простой 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.log(Height); }; setTimeout(updateHeight, 2000); });
источник
Довольно простой, но работает:
function dynamicHeight() { var height = jQuery('').height(); jQuery('.edito-wrapper').css('height', editoHeight); } editoHeightSize(); jQuery(window).resize(function () { editoHeightSize(); });
источник