2009-12-10 1 views
21

이 DOM 이벤트를 활용해야합니다. IE에는 onpropertychange가 있는데, 필요한 작업을 수행합니다. 그러나 Webkit은이 이벤트를 지원하지 않습니다. 내가 사용할 수있는 대안이 있습니까? (모든 수정 속성 모니터링 반대) 당신이 setAttribute()에 단순히 호출을 검출하여 만족하면거기에 웹 키트에서 작동하는 DOMAttrModified 대신 사용할 수 있습니다.

+0

나는이를 기반으로 뭔가를 가지고 올 수 있었다 [http://www.west-wind.com/Weblog/posts/453942.aspx](http : //www.west-wind.com/Weblog/posts/453942.aspx) – blockhead

+0

[David Walsh의 솔루션] (http://davidwalsh.name/detect-node-insertion)에 기반하여 나는 작은 라이브러리를 만들었습니다. DOM 삽입을 잡아라. 관심이있는 변경 후 요소와 일치하는 CSS 선택기를 작성할 수 있다면 이것이 유효한 해결책입니다. 그것은 DOM Mutation Observers보다 더 많은 브라우저를 다룹니다. 참조 : https : // github.com/naugtur/insertionQuery – naugtur

답변

24

크롬 DOMAttrModified 이벤트를 전달하지 않지만 2011 년부터 더 가벼운 돌연변이 관찰자가 지원되며, 이것 역시 속성 변경 작업에 사용됩니다. 여기

이 문서 본문에 대한 예입니다 간단한 속성 변경에 대한

var element = document.body, bubbles = false; 

var observer = new WebKitMutationObserver(function (mutations) { 
    mutations.forEach(attrModified); 
}); 
observer.observe(element, { attributes: true, subtree: bubbles }); 

function attrModified(mutation) { 
    var name = mutation.attributeName, 
    newValue = mutation.target.getAttribute(name), 
    oldValue = mutation.oldValue; 

    console.log(name, newValue, oldValue); 
} 

console.log 문은 인쇄 할 것이다 :

<body color="black"> 
<script type="text/html"> 
document.body.setAttribute("color", "red"); 
</script> 
</body> 

콘솔 :

> color red black

+2

현재 CSS3 "resize : both"속성과 함께 사용할 수없는 것으로 보입니다. 관찰자는 사용자가 크기 조정 핸들을 드래그하여 요소에 대한 변경 사항을 선택하지 않습니다. – cburgmer

+0

변경 사항의 출처를 확인할 수있는 방법이 있습니까? JS를 통해 어딘가에서 클래스가 변경되는 요소가 있는데 어디에서 왔는지 파악하려고하지만 Chrome의 이벤트 스택 추적에 이벤트를 시작한 코드가 표시되지 않습니다. –

+1

속성 변경시 즉시 DOMAttrModified가 트리거되지만 돌연변이 옵저버는 이벤트를 대기열에 추가합니다. 그래서 둘 사이에별로 다르지 않은 차이가 있습니다. –

13

당신은 지나치게 타고 수있는 방법으로 모든 요소에 :

Element.prototype._setAttribute = Element.prototype.setAttribute 
Element.prototype.setAttribute = function(name, val) { 
var e = document.createEvent("MutationEvents"); 
var prev = this.getAttribute(name); 
this._setAttribute(name, val); 
e.initMutationEvent("DOMAttrModified", true, true, null, prev, val, name, 2); 
this.dispatchEvent(e); 
} 
0

참조 코드 : https://github.com/meetselva/attrchange/blob/master/attrchange.js DOMAttrModified + ('propertychange'for IE)가 귀하의 경우에 사용됩니다. 그것이 당신에게 적합하지 않다면,이 요구를 만족시킬 수있는 "추악한"해결책은 setInterval (function(), delay) 이어야합니다. 그렇지 않으면 위의 Sean Hogan 게시물을보십시오.

+0

URL이 유효하지 않습니다. –

0

@Filip에서 제공하는 솔루션은 거의 완료되었지만 (당시에는 작동했을 수도 있음) 이제는 이전 속성 값의 전달을 요청해야합니다.

observer.observe(element, { attributes: true, subtree: bubbles }); 

이에 :

따라서, 변경할 수 있습니다

observer.observe(element, { attributes: true, attributeOldvalue:true, subtree: bubbles }); 

그렇지 않으면, 당신은 oldValues를 볼 수 없습니다. (대신 널거야)이이었다 Chrome 34.0.1847.131 (공식 빌드 265687)에서 테스트되었습니다. m.

3

나는 같은 질문을하고 setAttribute을 수정하려고 생각 했으므로 what Sean did을 보았습니다. 속성이 반복적으로 같은 값으로 설정되면 실행 중이라는 것을 제외하고는 훌륭하게 작동했습니다. 따라서 값이 변경되지 않으면 이벤트를 발생시키지 않으려면 사본에 체크를 추가했습니다. 또한 setAttribute이 숫자를 문자열에 강요한다는 이론적 근거에 기반하여 val = String(val)을 추가 했으므로 비교를 통해 예측할 수 있습니다.

내 수정 된 버전은 다음과 같습니다

var emulateDOMAttrModified = { 

    isSupportedNatively: function() { 
    var supported = false; 
    function handler() { 
     supported = true; 
    } 
    document.addEventListener('DOMAttrModified', handler); 
    var attr = 'emulateDOMAttrModifiedTEST'; 
    document.body.setAttribute(attr, 'foo'); // aka $('body').attr(attr, 'foo'); 
    document.removeEventListener('DOMAttrModified', handler); 
    document.body.removeAttribute(attr); 
    return supported; 
    }, 

    install: function() { 
    if (!this.isSupportedNatively() && 
     !Element.prototype._setAttribute_before_emulateDOMAttrModified) { 
     Element.prototype._setAttribute_before_emulateDOMAttrModified = Element.prototype.setAttribute 
     Element.prototype.setAttribute = function(name, val) { 
     var prev = this.getAttribute(name); 
     val = String(val); /* since attributes do type coercion to strings, 
      do type coercion here too; in particular, D3 animations set x and y to a number. */ 
     if (prev !== val) { 
      this._setAttribute_before_emulateDOMAttrModified(name, val); 
      var e = document.createEvent('MutationEvents'); 
      e.initMutationEvent('DOMAttrModified', true, true, null, prev, val, name, 2); 
      this.dispatchEvent(e); 
     } 
     }; 
    } 
    } 

}; 

// Install this when loaded. No other file needs to reference this; it will just make Chrome and Safari 
// support the standard same as Firefox does. 
emulateDOMAttrModified.install();