jQuery 이벤트 : div의 HTML / 텍스트 변경 감지


265

나는 모든 시간을 변경의 내용이 사업부를 가지고, 그것을 수 ajax requests, jquery functions, blur등 등

어떤 시점에서 내 div의 변경 사항을 감지 할 수있는 방법이 있습니까?

간격이나 기본값을 확인하고 싶지 않습니다.

이와 같은 일이

$('mydiv').contentchanged() {
 alert('changed')
}


14
@Rob keypress이벤트를 contenteditable <div>요소에 바인딩합니다 . 거기에 솔루션이 적용되는지 확실하지 않습니다. 그들은 요소의 내용에 대한 프로그래밍 방식의 변화를 선택하지 않을 것입니다.
Anthony Grist

답변:


407

timer를 사용하고 innerHTML을 확인하지 않으려면이 이벤트를 시도 할 수 있습니다

$('mydiv').bind('DOMSubtreeModified', function(){
  console.log('changed');
});

자세한 내용과 브라우저 지원 데이터는 여기에 있습니다.

주의 : 최신 jQuery 버전에서는 bind ()가 더 이상 사용되지 않으므로 대신 on ()을 사용해야합니다.

$('body').on('DOMSubtreeModified', 'mydiv', function(){
  console.log('changed');
});

14
DOMSubtreeModified는 IE8 (및 이하)에서 지원되지 않습니다.
Gavin

56
이 이벤트는 더 이상 사용되지 않습니다 w3.org/TR/DOM-Level-3-Events/#glossary-deprecated
Isaiyavan Babu Karan

3
Mozilla 33 : <body> 요소의 재귀에 빠졌습니다. 다른 방법을 찾아야합니다
Chaki_Black

17
이 이벤트를 사용하지 마십시오. 항상 해고되는 모든 작업이 중단됩니다. 대신 $ ( '. myDiv'). bind ( 'DOMNodeInserted DOMNodeRemoved', function () {});
George SEDRA

19
이 방법은 더 이상 사용되지 않습니다! 대신 사용 :$("body").on('DOMSubtreeModified', "mydiv", function() { });
아시프

55

자바 스크립트 MutationObserver 사용

  //More Details https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
 // select the target node
var target = document.querySelector('mydiv')
// create an observer instance
var observer = new MutationObserver(function(mutations) {
  console.log($('mydiv').text());   
});
// 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);

6
이것은이 같은 정답이 지금 DOMSubtreeModified을 사용하여 이상 선호입니다
조엘 데비

3
올바른 선택기를 제공했지만이 오류가 발생합니다. "VM21504 : 819 Uncaught TypeError : 'MutationObserver'에서 'observe'을 (를) 실행하지 못했습니다. 매개 변수 1이 'Node'유형이 아닙니다."
사미르


42

당신은 이것을 시도 할 수 있습니다

$('.myDiv').bind('DOMNodeInserted DOMNodeRemoved', function() {

});

그러나 이것은 인터넷 익스플로러에서 작동하지 않을 수도 있습니다. 테스트하지 않았습니다.



3
참고! : 트리거에 이것을 사용하고 페이지에 많은 변경 사항이있는 경우 매우 비효율적 일 수있는 X 번 (X = 1,000 이상) 기능을 실행합니다. 간단한 해결책 중 하나는 "실행 중"부울 var를 정의하는 것입니다. 이미 실행중인 경우 코드를 실행하지 않고 if (running == true) {return} ... if 로직 바로 뒤에 running = true를 설정하고 함수가 종료되기 전에 running = false로 설정하십시오. 타이머를 사용하여 X 초마다 기능이 실행되도록 제한 할 수도 있습니다. running = true; setTimeout (function () {running = false}, 5000); (또는 더 나은 것)
JxAxMxIxN

옵션을 추가하고 제거하는 선택 상자에서 이것을 사용했습니다. 항목이 추가되었을 때 훌륭하게 작동했지만 제거는 1 항목 뒤에있는 것처럼 보였습니다. 마지막 옵션이 제거되면 실행되지 않습니다.
CodeMonkey

2
@JxAxMxIxN 또한 타임 아웃을 지우고 다시 설정하여 타임 아웃 타이머를 충돌시킬 수 있습니다.clearTimeout(window.something); window.something = setTimeout(...);
Ctrl-C

동의-당신의 방법은 갈 길입니다-파이썬을 배우기 때문에 여러 언어 (많은 것은 아니지만 많은)에 걸쳐 저의 나쁜 코딩 관행을 많이 정리했습니다.
JxAxMxIxN

33

MutationObserver 또는 Mutation Events를 찾고 있습니다. 어느 곳에서나 지원되지 않으며 개발자 세계가 너무 좋아하지 않습니다.

div의 크기가 변경 될 것임을 알고 (확실하게 확인할 수있는 경우) 크로스 브라우저 resize 이벤트 를 사용할 수 있습니다 .


1
이것은 하나입니다. 특히, DOMSubtreeModified 입니다. 돌연변이 요약 라이브러리와이 DOM 트리 이벤트 목록이 도움 이 될 수 있습니다 .
BenjaminRH

1
이 이벤트는 더 이상 사용되지 않습니다. developer.mozilla.org/en-US/docs/Web/Guide/Events/…
Adrien Be

9
다른 사람이 모든 곳에서 모든 것을 읽으려고 시도한 경우, 이것이 정답입니다. Mutation Events는 이전 브라우저에서 지원되었으며 Mutation Observer는 최신 브라우저에서 지원되며 향후 지원 될 예정입니다. 지원 링크를 참조하십시오 : CANIUSE Mutation Observer
Josh Mc

20

다음 코드는 저에게 효과적입니다.

$("body").on('DOMSubtreeModified', "mydiv", function() {
    alert('changed');
});

그것이 누군가를 도울 수 있기를 바랍니다 :)


이것은 @Artley
Black

@ 블랙 감사합니다! 방금 Artley 답변을 확인했습니다. 다음에이 문제를 처리하겠습니다.
Sanchit Gupta

17

이 문제에 대한 해결책은 내장되어 있지 않으며, 이는 디자인 및 코딩 패턴에 문제가 있습니다.

게시자 / 구독자 패턴을 사용할 수 있습니다. 이를 위해 jQuery 사용자 정의 이벤트 또는 자체 이벤트 메커니즘을 사용할 수 있습니다.

먼저,

function changeHtml(selector, html) {
    var elem = $(selector);
    jQuery.event.trigger('htmlchanging', { elements: elem, content: { current: elem.html(), pending: html} });
    elem.html(html);
    jQuery.event.trigger('htmlchanged', { elements: elem, content: html });
}

이제 다음과 같이 divhtmlchanging / divhtml 변경된 이벤트를 구독 할 수 있습니다.

$(document).bind('htmlchanging', function (e, data) {
    //your before changing html, logic goes here
});

$(document).bind('htmlchanged', function (e, data) {
    //your after changed html, logic goes here
});

자, 이것을 통해 div 컨텐츠 변경을 변경해야합니다. changeHtml() 기능을 합니다. 따라서 정보를 포함하는 바인딩 콜백 데이터 인수 때문에 그에 따라 필요한 변경을 모니터하거나 수행 할 수 있습니다.

div의 HTML을 다음과 같이 변경해야합니다.

changeHtml('#mydiv', '<p>test content</p>');

또한 입력 요소를 제외한 모든 html 요소에 사용할 수 있습니다. 어쨌든 모든 요소와 함께 사용하도록 수정할 수 있습니다.


특정 요소의 변경 사항을 관찰하고 조치하려면 'jQuery.event.trigger (...)'대신 'elem.trigger (...)'를 사용하도록 changeHtml 함수를 수정 한 다음 다음과 같은 요소에 바인딩하십시오. $ ( '# my_element_id'). on ( 'htmlchanged', function (e, data) {...}
KenB

8
"이것은 디자인 및 코딩 패턴에 문제가 있습니다", 타사 스크립트를 포함하면 소스 코드를 제어 할 수없는 경우 어떻게해야합니까? 그러나 하나의 div에 대한 변경 사항을 감지해야합니까?
DrLightman

@DrLightman 엄지 손가락의 규칙이 제공 콜백 이벤트 제 3 자와 lib 디렉토리 선택하는 것입니다
마르셀 Djaman

8

Mozilla 에서 제공 하고이 블로그 게시물 에서 수정 한이 스 니펫에 표시된대로 MutationObserver 를 사용하십시오.

또는 이 링크에서 볼 수있는 JQuery 예제를 사용할 수 있습니다

Chrome 18 세 이상, Firefox 14 이상, IE 11 이상, Safari 6 이상

// Select the node that will be observed for mutations
var targetNode = document.getElementById('some-id');

// Options for the observer (which mutations to observe)
var config = { attributes: true, childList: true };

// Callback function to execute when mutations are observed
var callback = function(mutationsList) {
    for(var mutation of mutationsList) {
        if (mutation.type == 'childList') {
            console.log('A child node has been added or removed.');
        }
        else if (mutation.type == 'attributes') {
            console.log('The ' + mutation.attributeName + ' attribute was modified.');
        }
    }
};

// Create an observer instance linked to the callback function
var observer = new MutationObserver(callback);

// Start observing the target node for configured mutations
observer.observe(targetNode, config);

// Later, you can stop observing
observer.disconnect();

3

div의 이전 innerHTML을 변수에 저장할 수 있습니다. 이전 컨텐츠가 현재 컨텐츠와 일치하는지 확인하는 간격을 설정하십시오. 이것이 사실이 아닌 경우 무언가를하십시오.


1

MutationObserver를 사용해보십시오.

브라우저 지원 : http://caniuse.com/#feat=mutationobserver

<html>
  <!-- example from Microsoft https://developer.microsoft.com/en-us/microsoft-edge/platform/documentation/dev-guide/dom/mutation-observers/ -->

  <head>
    </head>
  <body>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script type="text/javascript">
      // Inspect the array of MutationRecord objects to identify the nature of the change
function mutationObjectCallback(mutationRecordsList) {
  console.log("mutationObjectCallback invoked.");

  mutationRecordsList.forEach(function(mutationRecord) {
    console.log("Type of mutation: " + mutationRecord.type);
    if ("attributes" === mutationRecord.type) {
      console.log("Old attribute value: " + mutationRecord.oldValue);
    }
  });
}
      
// Create an observer object and assign a callback function
var observerObject = new MutationObserver(mutationObjectCallback);

      // the target to watch, this could be #yourUniqueDiv 
      // we use the body to watch for changes
var targetObject = document.body; 
      
// Register the target node to observe and specify which DOM changes to watch
      
      
observerObject.observe(targetObject, { 
  attributes: true,
  attributeFilter: ["id", "dir"],
  attributeOldValue: true,
  childList: true
});

// This will invoke the mutationObjectCallback function (but only after all script in this
// scope has run). For now, it simply queues a MutationRecord object with the change information
targetObject.appendChild(document.createElement('div'));

// Now a second MutationRecord object will be added, this time for an attribute change
targetObject.dir = 'rtl';


      </script>
    </body>
  </html>


0

jQuery를 통해 또는 DOM-API를 통해 직접 컨텐츠를 div에 추가하면 기본적으로 .appendChild()함수로 설정됩니다. 당신이 할 수있는 일은 .appendChild()현재 객체 의 기능 을 재정의하고 관찰자를 구현하는 것입니다. 이제 .appendChild()함수 를 재정의 했으므로 내용을 추가 할 수 있도록 다른 객체에서 해당 함수를 빌려야합니다. 따라서 우리 .appendChild()는 다른 div를 호출하여 최종적으로 내용을 추가합니다. 물론 이것은에도 적용 .removeChild()됩니다.

var obj = document.getElementById("mydiv");
    obj.appendChild = function(node) {
        alert("changed!");

        // call the .appendChild() function of some other div
        // and pass the current (this) to let the function affect it.
        document.createElement("div").appendChild.call(this, node);
        }
    };

여기에 순진한 예가 있습니다. 당신은 내가 생각하는대로 스스로 확장 할 수 있습니다. http://jsfiddle.net/RKLmA/31/

그건 그렇고 : 이것은 JavaScript가 OpenClosed 원칙을 준수 함을 보여줍니다. :)


그것은 자식 추가와 함께 작동하지 않습니다 ... 실제로 다른 기능을 통해 HTML을 수정합니다.
BoqBoq

removeChild () replaceChild () 등과 비슷하지만 innerHTML에 적합합니다. 어떻게 든 피해야합니다.
Andries
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.