12

I want to know, if it's possible, how to check in javascript if an element has changed or an attribute of it?

I mean something like window.onhashchange for an element something like:

document.getElementById("element").onElementChange = function();

As I know onchange is something like this, but will it work if I want to know in this way:

var element = {};
element.attribute = result;

element.attribute.onchange = function();
Adam Halasz
  • 57,421
  • 66
  • 149
  • 213
  • Could you kindly confirm whether you are looking to track change in the object's attribute or change in the attribute of a DOM element?Thanks – Philar Nov 27 '10 at 17:13
  • Duplicate of http://stackoverflow.com/questions/4266852/how-do-i-play-a-sound-when-an-element-changes-like-so-chat-does – alexia Nov 27 '10 at 17:16
  • @Nyuszika7H I don't think so :P this is a general question. – Adam Halasz Nov 27 '10 at 17:49

5 Answers5

9

As far as I understand you want onChange on javascript object Properties. The answer is no, it doesn't exist as far as I know.

But you can make a setter function like this (As a proof of concept):

var element = {};

element.setProperty = function(property, value) {
  if (typeof(element.onChange) === 'function') {
    element.onChange(property, element[property], value);
  }

  element[property] = value;
};



element.onChange = function(property, oldValue, newValue) {
  alert(property + ' changed from ' + oldValue + ' to ' + newValue);
};

element.setProperty('something', 'Hello world!');

now you get an alert box with 'something changed from undefined to Hello World!'. And (element.something === 'Hello World!') will return true.

if you now call:

element.setProperty('something', 'Goodbye world!');

you get an alert box with 'something changed from Hello World! to Goodbye World!'.

Off course you have to set the property only via the setProperty method in all of your code if you want to capture this event!

Edit:

At some time in the future, you might be able to use Object.observe().

Edit 2:

Now there's also proxies.

Jan
  • 8,011
  • 3
  • 38
  • 60
  • I believe only input fields fire the onChange event once their value is changed... is this code tested? if so, does it work under all browsers? – Zathrus Writer Nov 27 '10 at 16:50
  • as far as I understand this question has nothing to do with DOM elements. It is about javascript objects. I tested this in the Chrome console. I'm pretty sure it works on other browsers too. – Jan Nov 27 '10 at 16:55
  • Object.observe() is now deprecated and shouldn't be used anymore. – Plagiatus Mar 30 '22 at 19:30
4

You might consider a mutation observer.

to do this you first create a callback (fired when the dom element changes)

assign it to an observer var observer = new MutationObserver(callback);

Then tell the observer what to watch observer.observe('<div></div>', observerOptions);

From: Mozilla page on Mutation Observers

lucsan
  • 712
  • 9
  • 10
  • 1
    This is the most up-to-date and relevant answer - you might add some simple code to make this more visible https://jsfiddle.net/wg4ahtf6/ – Jacksonkr Feb 25 '21 at 22:36
1

I guess you'd need a way to capture the event which triggered the change in attribute rather than the change in attribute. The change in attribute could only either be due to your CSS or your javascript, both being manifestations of the user's actions.

Philar
  • 3,887
  • 1
  • 24
  • 19
  • Yeah, you should capture the event that change the attribute. There is no event listener for "changes of attribute" – timdream Nov 27 '10 at 16:50
  • @timdream yes there isn't be a need to home in on such changes because either way (CSS or javascript), we can tie these up with the existing event model. Thanks – Philar Nov 27 '10 at 16:53
  • -1, This question is not about the DOM, see: `var element = {};` – Jan Nov 27 '10 at 17:02
  • @Jan, seems like I may have misinterpreted it. However that begs the question, does this scenario actually warrant the use of an event model? – Philar Nov 27 '10 at 17:24
  • Why not, what's wrong with events? Javascript is a very good language for working with events. – Jan Nov 27 '10 at 19:01
  • It's better to incorporate the logic in the setters itself. Just because events work does not mean it's good design to employ them all the time. – Philar Nov 28 '10 at 10:29
  • Nobody said he has to use it all the time. There are use cases where an event system is perfectly valid. – Jan Nov 28 '10 at 14:52
  • What are you talking about? He hasn't explained his usecase. If he wants to react on changes in an object from outside of its context it is a valid usecase. If you want to do databinding like in wpf this pattern a must. – Jan Dec 01 '10 at 18:39
1

I believe there is no such event. However, you can use setInterval or setTimeout to watch for element changes and use it to react accordingly.

TGrif
  • 5,725
  • 9
  • 31
  • 52
Zathrus Writer
  • 4,311
  • 5
  • 27
  • 50
0

I did this. It works pretty well. I would have used the setProperty method if I had known.

function searchArray(searchValue, theArray, ChangeValue){
    for (var i=0; i < theArray.length; i++) {
        if (theArray[i].id === searchValue) {
            theArray[i].changed = ChangeValue;
        }
    }
}

function getArrayIindex(elementid, theArray){
    for (var i=0; i < theArray.length; i++) {
        if (theArray[i].id === elementid) {
            return i;
        }
    }
}

function setInputEvents(hiddenObject) {

        var element;

        for (var i = 0; i < document.forms[0].length; i++) {
            element = document.forms[0].elements[i];

            //Check to see if the element is of type input
            if (element.type in { text: 1, password: 1, textarea: 1 }) {

                arrFieldList.push({
                    id: element.id,
                    changed:false,
                    index: i,                    
                });

                element.onfocus = function () {
                    if (!arrFieldList[getArrayIindex(this.id, arrFieldList)].changed) {
                        hiddenObject.value = this.value;
                        this.value = '';
                    }
                }

                element.onblur = function () {
                    if (this.value == '') {
                        this.value = hiddenObject.value;
                    }
                }

                element.onchange = function () {
                    searchArray(this.id, arrFieldList, true);
                }
            }

        }
Welshboy
  • 318
  • 4
  • 10