Rectangle 27 24

Although Chrome does not dispatch DOMAttrModified events, the more lightweighted mutation observers are supported since 2011 and these work for attribute changes, too.

Here is an example for the document body:

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

For a simple attribute change, the console.log statement would print:

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

It seems that this will currently not work in combination with the CSS3 "resize: both" property. The observer will not pick up changes to the element by the user dragging the resize handle.

Is there any way I can see where the change originated from? I've got an element whose class is being changed somewhere through JS, and I'm trying to figure out where from, but Chrome's stack trace of the event doesn't show the code that initiated the event.

it's worth noting that DOMAttrModified triggers immediately when the attribute changes, but mutation observers queue an event. So there's a not-so-subtle difference between the two.

Webkit

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 13

If you are happy with merely detecting calls to setAttribute() (as opposed to monitoring all attribute modifications) then you could over-ride that method on all elements with:

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

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 3

I had the same question and was thinking of modifying setAttribute, so seeing what Sean did, I copied that. Worked great, except that it was firing when an attribute was repeatedly set to the same value, so I added a check to my copy to skip firing the event if the value is not being changed. I also added val = String(val), based on the rationale that setAttribute will coerce numbers to strings, so the comparison should anticipate that.

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

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 24

Although Chrome does not dispatch DOMAttrModified events, the more lightweighted mutation observers are supported since 2011 and these work for attribute changes, too.

Here is an example for the document body:

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

For a simple attribute change, the console.log statement would print:

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

It seems that this will currently not work in combination with the CSS3 "resize: both" property. The observer will not pick up changes to the element by the user dragging the resize handle.

Is there any way I can see where the change originated from? I've got an element whose class is being changed somewhere through JS, and I'm trying to figure out where from, but Chrome's stack trace of the event doesn't show the code that initiated the event.

it's worth noting that DOMAttrModified triggers immediately when the attribute changes, but mutation observers queue an event. So there's a not-so-subtle difference between the two.

Webkit

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 13

If you are happy with merely detecting calls to setAttribute() (as opposed to monitoring all attribute modifications) then you could over-ride that method on all elements with:

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

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 3

I had the same question and was thinking of modifying setAttribute, so seeing what Sean did, I copied that. Worked great, except that it was firing when an attribute was repeatedly set to the same value, so I added a check to my copy to skip firing the event if the value is not being changed. I also added val = String(val), based on the rationale that setAttribute will coerce numbers to strings, so the comparison should anticipate that.

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

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 0

Although Chrome does not dispatch DOMAttrModified events, the more lightweighted mutation observers are supported since 2011 and these work for attribute changes, too.

Here is an example for the document body:

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

For a simple attribute change, the console.log statement would print:

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

It seems that this will currently not work in combination with the CSS3 "resize: both" property. The observer will not pick up changes to the element by the user dragging the resize handle.

Is there any way I can see where the change originated from? I've got an element whose class is being changed somewhere through JS, and I'm trying to figure out where from, but Chrome's stack trace of the event doesn't show the code that initiated the event.

it's worth noting that DOMAttrModified triggers immediately when the attribute changes, but mutation observers queue an event. So there's a not-so-subtle difference between the two.

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 0

The solution provided by @Filip is close (and may have worked at the time) but now you need to request delivery of the old attribute value.

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

Otherwise, you won't see the oldValues (you'll get null instead.) This was tested in Chrome 34.0.1847.131 (Official Build 265687) m.

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 0

The solution provided by @Filip is close (and may have worked at the time) but now you need to request delivery of the old attribute value.

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

Otherwise, you won't see the oldValues (you'll get null instead.) This was tested in Chrome 34.0.1847.131 (Official Build 265687) m.

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 0

Although Chrome does not dispatch DOMAttrModified events, the more lightweighted mutation observers are supported since 2011 and these work for attribute changes, too.

Here is an example for the document body:

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

For a simple attribute change, the console.log statement would print:

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

It seems that this will currently not work in combination with the CSS3 "resize: both" property. The observer will not pick up changes to the element by the user dragging the resize handle.

Is there any way I can see where the change originated from? I've got an element whose class is being changed somewhere through JS, and I'm trying to figure out where from, but Chrome's stack trace of the event doesn't show the code that initiated the event.

it's worth noting that DOMAttrModified triggers immediately when the attribute changes, but mutation observers queue an event. So there's a not-so-subtle difference between the two.

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 0

If you are happy with merely detecting calls to setAttribute() (as opposed to monitoring all attribute modifications) then you could over-ride that method on all elements with:

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

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 0

The solution provided by @Filip is close (and may have worked at the time) but now you need to request delivery of the old attribute value.

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

Otherwise, you won't see the oldValues (you'll get null instead.) This was tested in Chrome 34.0.1847.131 (Official Build 265687) m.

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 0

Please refer code: https://github.com/meetselva/attrchange/blob/master/attrchange.js 'DOMAttrModified' + ('propertychange' for IE) are used there like in your case. If it's not suitable for you, the "ugly" solution that can satisfy this demand should be setInterval(function(){}, delay) Otherwise see Sean Hogan post above.

URL is not valid

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 0

Please refer code: https://github.com/meetselva/attrchange/blob/master/attrchange.js 'DOMAttrModified' + ('propertychange' for IE) are used there like in your case. If it's not suitable for you, the "ugly" solution that can satisfy this demand should be setInterval(function(){}, delay) Otherwise see Sean Hogan post above.

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 0

If you are happy with merely detecting calls to setAttribute() (as opposed to monitoring all attribute modifications) then you could over-ride that method on all elements with:

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

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 0

The solution provided by @Filip is close (and may have worked at the time) but now you need to request delivery of the old attribute value.

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

Otherwise, you won't see the oldValues (you'll get null instead.) This was tested in Chrome 34.0.1847.131 (Official Build 265687) m.

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 0

I had the same question and was thinking of modifying setAttribute, so seeing what Sean did, I copied that. Worked great, except that it was firing when an attribute was repeatedly set to the same value, so I added a check to my copy to skip firing the event if the value is not being changed. I also added val = String(val), based on the rationale that setAttribute will coerce numbers to strings, so the comparison should anticipate that.

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

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 0

Please refer code: https://github.com/meetselva/attrchange/blob/master/attrchange.js 'DOMAttrModified' + ('propertychange' for IE) are used there like in your case. If it's not suitable for you, the "ugly" solution that can satisfy this demand should be setInterval(function(){}, delay) Otherwise see Sean Hogan post above.

URL is not valid

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 0

I had the same question and was thinking of modifying setAttribute, so seeing what Sean did, I copied that. Worked great, except that it was firing when an attribute was repeatedly set to the same value, so I added a check to my copy to skip firing the event if the value is not being changed. I also added val = String(val), based on the rationale that setAttribute will coerce numbers to strings, so the comparison should anticipate that.

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

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events
Rectangle 27 0

Please refer code: https://github.com/meetselva/attrchange/blob/master/attrchange.js 'DOMAttrModified' + ('propertychange' for IE) are used there like in your case. If it's not suitable for you, the "ugly" solution that can satisfy this demand should be setInterval(function(){}, delay) Otherwise see Sean Hogan post above.

URL is not valid

dom - is there an alternative to DOMAttrModified that will work in web...

dom webkit mutation-events