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.