JQuery kullanarak div'in yüksekliğinin ne zaman değiştiğini algılama


141

Dinamik olarak eklenen ve kaldırılan bazı içerikler içeren bir div var, bu yüzden yüksekliği sık sık değişiyor. Ayrıca kesinlikle javascript ile doğrudan altına yerleştirilmiş bir div var, bu yüzden div yüksekliği değiştiğinde tespit edemezseniz, altındaki div yeniden konumlandıramıyorum.

Peki, bu div'in yüksekliği değiştiğinde nasıl tespit edebilirim? Kullanmam gereken bazı jQuery olayı olduğunu varsayıyorum, ancak hangisini takacağımdan emin değilim.


4
Neden bir jQuery kullanırken bir eklenti kullanmak istemiyorum merak ediyorum.
Andre Calil

1
@ user007 Öğelerinizin boyutunu ne değiştirir?
A. Wolff

@ kavrulmuş benim div yüksekliği bazı öğe eklendiğinde değişir, ekleme jquery tarafından yapılır
user007

1
@ user007 Böylece DIV'ye bir şey eklediğinizde, DIV için özel bir yeniden boyutlandırma olayı tetikleyebilirsiniz. Başka bir yol (en kötü IMO), yerel jquery append () yöntemini genişleten içerik eklemek için özel bir yöntem kullanmak, bir geri arama ile kullanmak olabilir, örneğin
A. Wolff

@roasted Bahşiş için teşekkürler.
user007

Yanıtlar:


64

Css-element-queries kütüphanesinden bir yeniden boyutlandırma sensörü kullanın:

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

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

Etkinlik tabanlı bir yaklaşım kullanır ve işlemci zamanınızı boşa harcamaz. Dahil tüm tarayıcılarda çalışır. IE7 +.


5
hoş bir çözüm, görünmez yeni bir öğe istenen hedefe bindirme olarak kullanır ve değişiklikleri tetiklemek için bindirme "kaydırma" olayını kullanır.
Eike Thies

2
Bu, içerik ve niteliklerin değişmediği, ancak boyutların değiştiği (örneğin: css kullanarak boyutların yüzdesi) dahil olmak üzere tüm durumlarda çalışan tek çözümdür
FF_Dev

2
Şimdiye kadar en iyi çözüm.
dlsso

1
Burada en çok oy alan cevap bu bir trajedi. Bu gerçekten% 100 çalışıyor.
Jimbo Jonny

Bu, gizli olarak başlayan öğeler için işe yaramaz gibi görünüyor.
greatwitenorth

48

Temelde öznitelik değişikliğine bir dinleyici işlevi ekleyen attrchange dinleyici için bir eklenti yazdım . Bir eklenti olarak söylesem bile, aslında bir jQuery eklentisi olarak yazılmış basit bir işlevdir ... yani isterseniz .. eklenti özel kodunu çıkarın ve çekirdek işlevlerini kullanın.

Not: Bu kod yoklama kullanmaz

bu basit demoya göz atın 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();
});

Eklenti sayfası: http://meetselva.github.io/attrchange/

Küçültülmüş sürüm: (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
Bu, div'i manuel olarak yeniden boyutlandırırsanız sorunu çözer, bu orijinal soruyu çözmez mi? Dinamik olarak içerik eklerseniz, yükseklik değişikliğini algılamaz: jsfiddle.net/aD49d/25
smets.kevin

Ayrıca, dinamik içerik için bu işi yapmanın bir yolu olup olmadığını bilmek isterim.
EricP

4
@JoeCoder Bu yıpratma kodu, bir kullanıcı eylemi olduğunda tarayıcı tarafından tetiklenen DOM olaylarına dayanır. Ancak, bu örnekteki dinamik içerik maalesef herhangi bir olayı tetiklemeyen programlı olarak dahil edilmiştir. "Yoklama" burada daha kolay bir seçenek gibi görünüyor. Dinamik içerik eklendikten sonra diğer seçenek manuel olarak tetiklenebilir.
Selvakumar Arumugam

28

DOMSubtreeModified olayını kullanabilirsiniz

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

Ancak bu, boyutlar değişmese bile tetiklenir ve her ateş açıldığında konumu yeniden atamak bir performans isabeti alabilir. Bu yöntemi kullanma deneyimime göre, boyutların değişip değişmediğini kontrol etmek daha ucuzdur ve bu nedenle ikisini birleştirmeyi düşünebilirsiniz.

Veya div'ı doğrudan değiştiriyorsanız (div, contentEditable gibi, kullanıcı girdisi tarafından öngörülemeyen şekillerde değiştirilmek yerine), özel bir etkinliği her yaptığınızda tetikleyebilirsiniz.

Dezavantajı: IE ve Opera bu etkinliği uygulamıyor.


12
IE ve Opera bu etkinliği uygulamıyor: quirksmode.org/dom/events/index.html
DEfusion

14
Değiştirilmiş var
Adonis K. Kakoulidis

2
Bunu yapmanın modern yolu bir MutationObserver kullanmaktır: developer.mozilla.org/en-US/docs/Web/API/MutationObserver
Christian Bankester

21

Bu sorunu son zamanlarda şu şekilde ele aldım:

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

Partiye birkaç yıl geç kaldığımı biliyorum, cevabımın herhangi bir eklenti indirmeden gelecekte bazı insanlara yardımcı olabileceğini düşünüyorum.


1
Sanırım bazı açılardan bunu yapmanın en iyi yolu bu değil, ama aslında çok hoşuma gidiyor, çünkü bir animasyonun sonunda geri arama olarak tetikleyebileceğiniz anlamına geliyor. Yeniden boyutlandırma eklentisi, bir animasyon boyunca tetiklenmeye devam eder, bu da yardımcı olabilir, ancak sorunlara da neden olabilir. Bu yöntem en azından yükseklik kontrolünün ne zaman tetikleneceğini kontrol etmenizi sağlar.
andyface

Kodunuz tam olarak ne yapıyor? Neden sadece bağlama olayına yazdığınız kodu bağlama ve tetikleme fonksiyonunda kullanamıyoruz?
user1447420

Ama bu otomatik değil, değil mi?
Albert Català

17

MutationObserverSınıfı kullanabilirsiniz .

MutationObservergeliştiricilere bir DOM'daki değişikliklere tepki verme yolu sağlar. DOM3 Olayları belirtiminde tanımlanan Mutasyon Olaylarının yerine kullanılmak üzere tasarlanmıştır.

Örnek ( kaynak )

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

Bu doğru cevap. Ayrıca MutationObservers üzerine kurulmuş bir kitaplık olan MutationSummary'ya da göz atın: github.com/rafaelw/mutation-summary
Christian Bankester

9

Bu çok iyi başa çıkabilen bir jQuery eklentisi var

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

Burada, kırmızı kenarlı div'ı yeniden boyutlandırırsanız, yükseklik ne zaman değiştiğine dair farklı senaryolarla bir demo.

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


Çok güzel, ama varsayılan olarak kullanıcı arayüzünü değişiklikler için her milisaniyede yoklamıyor mu? Bu verimli mi?
Michael Scott Cuthbert

1
@MichaelScottCuthbert Uzun zaman önce yazılmıştı, ama kullandım setTimeout, bu yüzden kısaca 1ms + [çekleri yapmak için gereken süre] olurdu, ama fikir sürekli dinlemekti, bunu bir kez daha tetikledikten sonra, sanki sıra. Ben çok daha iyi ama çok zaman yapabilirim eminim.
Val

Ah, evet, Vega'nın çözümünden (sonuçta kullandığım) yaklaşık bir yıl önce ve tüm DOMSubtreeModified vb. Dinleyicilerden önce yaklaşık bir yıl geçtiğini görüyorum. Kodunuzu okuyarak bir ton öğrendim, bu yüzden bağlantıları devam ettirmeye değer.
Michael Scott Cuthbert

7

User007'ye yanıt olarak:

Öğenizin yüksekliği, öğeye eklendiği öğeler nedeniyle değişiyorsa .append(), yükseklik değişikliğini tespit etmeniz gerekmez. İkinci öğenin konumunu, yeni içeriği ilk öğenize eklediğiniz işlevle aynı işleve eklemeniz yeterlidir.

De olduğu gibi:

Çalışma Örneği

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

2

Basit bir setInterval yapabilirsiniz.

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

DÜZENLE:

Bu bir sınıf örneğidir. Ama en kolayı yapabilirsiniz.


0

Bunu kullanabilirsiniz, ancak yalnızca Firefox ve Chrome'u destekler.

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


0

Oldukça basit ama çalışıyor:

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

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

bu yalnızca pencere yeniden boyutlandırıldığında tetiklenir, ancak OP yeniden boyutlandırma etkinliğini belirli bir kapsayıcıya bağlamak ister
Fanie Void
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.