0

I'm sure there is some really easy solution to this problem, at least it seems like there should be. But I haven't been able to find it...

I have an object (it's not part of the DOM) and its properties are periodically getting updated:

var myobject;
//wait 10 seconds
myobject.property1 = "abc";

I want to trigger an action when this property gets changed (it's not just 1, but many different properties). How do I go about doing this in JQuery?

Ryan Ogle
  • 726
  • 1
  • 7
  • 16
  • possible duplicate of [javascript property change event](http://stackoverflow.com/questions/4169524/javascript-property-change-event) – Felix Kling Jun 28 '12 at 02:54

5 Answers5

2

You could trigger custom event.

function changeProperty(obj, prop, value) {
  if (prop in obj && obj[prop] !== value) {
     obj[prop] = value;
     // trigger on document is just an example.
     $(document).trigger('PropertyChange', [obj, prop]);
  }
}


var myobject;
// use the function to change property.
changeProperty(myobject, 'property1', 'abc');

// bind this custom event
$(document).on('PropertyChange', function(obj, prop) {
  console.log(obj, prop);
});
xdazz
  • 158,678
  • 38
  • 247
  • 274
0

Use setInterval and check the properties value against an array of previously checked values. If they've changed call a function ...

var previousVals = [],
    checkinterval = setInterval(function(){
        for(var i in myobject) {
            if(/* comparison logic true */) valchanged(myobject[i]);
        }
    }, 4000); /* check every 4 seconds */


function valchanged(value) { /* ... do something */ }
Alex
  • 34,899
  • 5
  • 77
  • 90
0

I can say about a solution. This is, in large part, a very easy problem to solve, without a DOM event, using a recursive check of my element utilizing setTimeout(). The problem with this solution is it’s sheer bloat and constant DOM traversing to check my selected element’s attributes every second. So, in light of this solutions pitfalls, we can use a little known DOM event called DOMAttrModified (you can read more about this and all other standard DOM events here: http://www.w3.org/TR/DOM-Level-2-Events/events.html)

The Best Solution

This event is not commonly used most likely because it is not yet supported by all browsers. That said, IE does support a similar event called “propertychange”, and, at the very least, we can always fall back on our initial setTimeout() solution if we’re dealing with all other browsers that don’t support anything (I’m looking at you Chrome/Safari). You can see a list of browsers and event compatibility here: http://www.quirksmode.org/dom/events/index.html

Since jQuery is a defacto go-to Javascript Library for developers these days, I created a plugin for it which mimics the DOMAttrModified event across all browsers.

Code

$.fn.watch = function(props, callback, timeout){
    if(!timeout)
        timeout = 10;
    return this.each(function(){
        var el      = $(this),
            func    = function(){ __check.call(this, el) },
            data    = { props:  props.split(","),
                        func:   callback,
                        vals:   [] };
        $.each(data.props, function(i) { data.vals[i] = el.css(data.props[i]); });
        el.data(data);
        if (typeof (this.onpropertychange) == "object"){
            el.bind("propertychange", callback);
        } else if ($.browser.mozilla){
            el.bind("DOMAttrModified", callback);
        } else {
            setInterval(func, timeout);
        }
    });
    function __check(el) {
        var data    = el.data(),
            changed = false,
            temp    = "";
        for(var i=0;i < data.props.length; i++) {
            temp = el.css(data.props[i]);
            if(data.vals[i] != temp){
                data.vals[i] = temp;
                changed = true;
                break;
            }
        }
        if(changed && data.func) {
            data.func.call(el, data);
        }
    }
}

Initialization Code

jQuery(function($){
    $(".demo span").watch('width,height', function(){
        if(parseFloat($(this).width()) >= 150){
            $(this).css({'background':'green'});
        }
        if(parseFloat($(this).height()) >= 200){
            $(this).css({'background':'blue'});
        }
    });
    $('.demo a').toggle(function(){
        $('.demo span').animate({'width':'400px','height':'200px'}, 1000);
    }, function(){
        $('.demo span').css({'width':'50px','height':'50px','background':'red'});
    });
});

Live Demo

This plugin lets you specify which attributes to “watch” for changes. It will fire your callback function when one of the attributes has changed. http://darcyclarke.me/dev/watch/

Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
0
setInterval(function() {
  // Do something every 2 seconds
  $('#myObject').attr('anyAttribute',value);
}, 2000);
Carls Jr.
  • 3,088
  • 7
  • 37
  • 57
0

Try this @Ryan

Hope this will help.

Sample code

$("#myObject").bind("input propertychange", function (evt) {
    // If it's the propertychange event, make sure it's the value that changed.
    if (window.event && event.type == "propertychange" && event.propertyName != "value")
        //do whatever

    // or if you want to use .prop api to get the attribute
        // Do your thing here
    }, 2000)); <---- delay here 2 seconds
});
Tats_innit
  • 33,991
  • 10
  • 71
  • 77