jQuery를 사용하여 div의 높이가 변경되는 경우 감지


141

동적으로 추가 및 제거되는 일부 콘텐츠가 포함 된 div가 있으므로 높이가 자주 변경됩니다. 또한 자바 스크립트로 직접 바로 아래에있는 div가 있으므로 div의 높이가 변경되는 시점을 감지 할 수 없으면 div를 그 아래로 재배치 할 수 없습니다.

그렇다면 해당 div의 높이가 언제 변하는 지 어떻게 알 수 있습니까? 사용해야 할 jQuery 이벤트가 있다고 가정하지만 어느 것을 연결해야하는지 잘 모르겠습니다.


4
jQuery를 사용할 때 왜 플러그인을 사용하고 싶지 않은지 궁금합니다.
Andre Calil

1
@ user007 요소의 크기를 어떻게 변경합니까?
A. Wolff

여기에 추가 된 일부 항목이, APPEND가 JQuery와에 의해 수행 될 때 내 DIV 높이 변화를 @roasted
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');
});

이벤트 기반 접근 방식을 사용하며 CPU 시간을 낭비하지 않습니다. 모든 브라우저에서 작동 IE7 +.


5
좋은 해결책은 보이지 않는 새로운 요소를 원하는 대상의 오버레이로 사용하고 오버레이의 "스크롤"이벤트를 사용하여 변경을 트리거합니다.
Eike Thies

2
이것은 내용과 속성이 변경되지 않지만 크기가 변경되는 경우를 포함하여 모든 경우에 작동하는 유일한 솔루션입니다 (예 : CSS를 사용한 비율 차원)
FF_Dev

2
지금까지 최고의 솔루션.
dlsso

1
여기에서 가장 많이 투표 된 답변이 아닌 것은 비극입니다. 이것은 실제로 100 % 작동합니다.
Jimbo Jonny

숨겨진 것으로 시작하는 요소에는 작동하지 않는 것 같습니다.
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
div의 크기를 수동으로 조정하면 문제가 해결되지만 원래의 질문 no는 해결되지 않습니까? 컨텐츠를 동적으로 추가하면 높이 변화가 감지되지 않습니다. jsfiddle.net/aD49d/25
smets.kevin

또한 동적 컨텐츠에 대해이 작업을 수행 할 수있는 방법이 있는지 알고 싶습니다.
EricP

4
@JoeCoder이 attrchange 코드는 사용자 작업이있을 때 브라우저에 의해 트리거되는 DOM 이벤트에 의존합니다. 그러나이 예제의 동적 내용은 프로그래밍 방식으로 포함되어있어 불행히도 이벤트를 트리거하지 않습니다. "폴링"은 여기서 또 다른 쉬운 옵션 인 것 같습니다. 다른 옵션은 동적 컨텐츠가 포함 된 후 수동으로 트리거 할 수 있습니다.
Selvakumar Arumugam

28

DOMSubtreeModified 이벤트를 사용할 수 있습니다

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

그러나 치수가 변경되지 않더라도 발사되며, 발사 될 때마다 위치를 재 할당하면 성능이 저하 될 수 있습니다. 이 방법을 사용한 경험에서 치수가 변경되었는지 확인하는 것이 저렴하므로 두 가지를 결합하는 것이 좋습니다.

또는 div를 contentEditable과 같이 예측할 수없는 방식으로 사용자 입력으로 변경하지 않고 div를 직접 변경하는 경우 언제든지 사용자 정의 이벤트를 발생시킬 수 있습니다.

단점 : IE와 Opera는이 이벤트를 구현하지 않습니다.


12
IE & Opera는이 이벤트를 구현하지 않습니다 : quirksmode.org/dom/events/index.html
Defusion

14
DomSubtreeModified는 depricated있어
아도니스 K. Kakoulidis을

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

정확히 코드는 무엇입니까? 바인딩 및 트리거와 관련된 함수에서 바인드 이벤트 내에 작성하는 코드를 사용할 수없는 이유는 무엇입니까?
user1447420 2016 년

그러나 이것은 자동적이지 않습니까?
Albert Català

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

이것이 정답입니다. 또한 MutationObservers에 빌드 된 라이브러리 인 MutationSummary를 살펴보십시오. github.com/rafaelw/mutation-summary
Christian Bankester

9

이것을 잘 처리 할 수있는 jQuery 플러그인이 있습니다.

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

빨간색 테두리가있는 div의 크기를 조정하면 높이가 변경되는 시점에 대한 다양한 시나리오가있는 데모가 있습니다.

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


아름답지만 기본적으로 변경을 위해 밀리 초마다 UI를 폴링하지 않습니까? 효율적입니까?
Michael Scott Cuthbert

1
@MichaelScottCuthbert 그것은 오래 전에 쓰여졌지만을 사용 setTimeout했기 때문에 1ms + [확인을 수행하는 데 걸리는 시간]이 짧지 만 아이디어는 끊임없이 듣고, 다시 트리거하면 다시 시작하는 것과 같습니다. 대기열. 나는 더 잘 할 수 있지만 많은 시간을 할애 할 수 없다고 확신합니다.
Val

아, 네, Vega의 솔루션 (최종 내가 사용했던)과 DOMSubtreeModified 등 모든 청취자가 널리 지원되기 약 1 년 전인 것을 알았습니다. 그래도 코드를 읽음으로써 많은 것을 배웠으므로 링크를 유지하는 것이 좋습니다.
마이클 스캇 커스버트

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

간단한 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();

편집하다:

이것은 클래스의 예입니다. 그러나 가장 쉬운 일을 할 수 있습니다.


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

창 크기가 조정 된 경우에만 실행되지만 OP는 크기 조정 이벤트를 특정 컨테이너에 바인딩하려고합니다.
Fanie Void
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.