Hi all,

I am trying to get an object to be aware of its own changes e.g. have it execute one of its functions but only when a variable has been changed from outside the object.

Google gave me lots of references to XMLHttpRequest.onreadystatechange and this resource at MSDN: http://msdn.microsoft.com/en-us/library/ms536957%28VS.85%29.aspx. However I tried it in the following:

var Register = {
            onreadystatechange : function() {
                window.alert("The object has changed state");
            },
            JsonToServer : {
                "targetElementId" : "registrationForm",
                "message" : "hello"
            },
            JsonFromServer : {},
            Effect : function() {
                JsonHttpRequest(this.JsonToServer);
            }
        }

... and it didn't work. The object itself works fine as after I've set Register.JsonFromServer via XMLHttpRequest() I can access it directly (and before XMLHttpRequest() is called, Register.JsonFromServer just returns a blank object). This to me suggests onreadystatechange isn't implemented by me correctly (but I'm not smart enough to know where I've gone wrong).

I'd be really grateful if someone with more experience could let me know of any workarounds/what I'm doing wrong.

Thanks in advance for any help/tips/pointers.

JRW,

I'm afraid ththe "onreadystatechange" approach is not generally applicable. It only applies to certain, very specific types of object.

You might be tempted to use setInterval(...) to monitor your object property but that's a very inefficient way of achieving your aim.

If I understand correctly, a better way to approach your problem is to create object(s) in which some or all properties (in particular the one you want to "monitor") can only be changed from outside the object via method(s) of the object. Thus you have a mechanism, by which other code (under your control) is guaranteed to be executed when the object is instructed to change these propert(ies).

Although it's not immediately obvious, Javascript objects can be forumulated to have private members and public members, which is what I'm suggesting here.

While public members in Javascript are pretty natural, private members are not. This article tells all.

Here are two commonly used patterns to implement public/private members :

// *****************************
// **** CONSTRUCTOR PATTERN ****
// with private a public members
// *****************************
function Thingy(x) {
	// ***********************
	// *** Private members ***
	// ***********************
	//Formal parameter x becomes a private property
	var y, z; //other private properties (can only be read/changed by public methods or other private methods)
	var a = function() { //A private method (can only be called by public methods or other private methods)
		// ..... code
		// ..... code
	};

	// **********************
	// *** Public members ***
	// **********************
	this.set_x = function(newX) { //a public method
		//...... code to exectute before x is set (as required).
		x = newX;
		//...... code to exectute after x is set (as required).
	};
	this.doSomethingClever = function() { //another public method
		// ..... code
		// ..... code
	}
	this.pr1 = null; //A public property
	this.pr2 = null; //A public property
}
var thingy = new Thingy(10);
var thing2 = new Thingy(25);
// *****************************
// ***** SINGLETON PATTERN *****
// with private a public members
// *****************************
var Thingy = function(x) {//Singleton pattern
	// ***********************
	// *** Private members ***
	// ***********************
	//Formal parameter x becomes a private property
	var y, z; //other private properties (can only be read/changed by public methods or other private methods)
	var a = function() { //A private method (can only be called by public methods or other private methods)
		// ..... code
		// ..... code
	};

	// **********************
	// *** Public members ***
	// **********************
	return {
		set_x : function(newX) { //a public method
			//...... code to exectute before x is set (as required).
			x = newX;
			//...... code to exectute after x is set (as required).
		},
		doSomethingClever : function() { //another public method
			// ..... code
			// ..... code
		}
	};
}();

Have fun.

Airshow

Thanks for the response Airshow! Before you posted I had managed to figure out that it was best to call an object method direct rather than have it wait for an event in another (and also learned pretty quickly that onreadystatechange wasn't as flexibly as I thought it might be). If it's any use to anyone visiting this page with a similar query, the following suited the purpose of my original post (i.e. for one object to respond when another object had done something):

var Register = {
    Request : {
        "targetElementId" : "test",
        "message" : true
    },
    Effect : function() {
        JsonHttpRequest(this.Request, Register);
    },
    JhrResponseHandler : function(Response) {
        document.getElementById(Register.Request.targetElementId).innerHTML = JSON.stringify(Response);
    },
    JhrErrorHandler : function(JhrStatus, JhrStatusText) {
        window.alert("Server error: "+JhrStatus+" "+JhrStatusText)
    }
}

function JsonHttpRequest(JavaScriptObjectForServer, CallingObjectName) {
    var JsonHttpRequest = new XMLHttpRequest();
    JsonHttpRequest.onreadystatechange = function() {
        switch(JsonHttpRequest.readyState) {
            case 0:
                break;
            case 1:
                JsonHttpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                JsonHttpRequest.send("JSON="+JSON.stringify(JavaScriptObjectForServer));
                break;
            case 2:
            case 3:
                // Loading pinwheel?
                break;
            case 4:
                if(JsonHttpRequest.status == 200) {
                    CallingObjectName.JhrResponseHandler(JSON.parse(JsonHttpRequest.responseText));
                } else {
                    CallingObjectName.JhrErrorHandler(JsonHttpRequest.status, JsonHttpRequest.statusText);
                }
                JsonHttpRequest.abort();
        }
    };
    JsonHttpRequest.open("POST", "classes/ObjectMaker.php", true);    
}

Thanks also for the heads up on that excellent Crockford resource.

JRW,

I'm afraid ththe "onreadystatechange" approach is not generally applicable. It only applies to certain, very specific types of object.

You might be tempted to use setInterval(...) to monitor your object property but that's a very inefficient way of achieving your aim.

If I understand correctly, a better way to approach your problem is to create object(s) in which some or all properties (in particular the one you want to "monitor") can only be changed from outside the object via method(s) of the object. Thus you have a mechanism, by which other code (under your control) is guaranteed to be executed when the object is instructed to change these propert(ies).

Although it's not immediately obvious, Javascript objects can be forumulated to have private members and public members, which is what I'm suggesting here.

While public members in Javascript are pretty natural, private members are not. This article tells all.

Here are two commonly used patterns to implement public/private members :

// *****************************
// **** CONSTRUCTOR PATTERN ****
// with private a public members
// *****************************
function Thingy(x) {
	// ***********************
	// *** Private members ***
	// ***********************
	//Formal parameter x becomes a private property
	var y, z; //other private properties (can only be read/changed by public methods or other private methods)
	var a = function() { //A private method (can only be called by public methods or other private methods)
		// ..... code
		// ..... code
	};

	// **********************
	// *** Public members ***
	// **********************
	this.set_x = function(newX) { //a public method
		//...... code to exectute before x is set (as required).
		x = newX;
		//...... code to exectute after x is set (as required).
	};
	this.doSomethingClever = function() { //another public method
		// ..... code
		// ..... code
	}
	this.pr1 = null; //A public property
	this.pr2 = null; //A public property
}
var thingy = new Thingy(10);
var thing2 = new Thingy(25);
// *****************************
// ***** SINGLETON PATTERN *****
// with private a public members
// *****************************
var Thingy = function(x) {//Singleton pattern
	// ***********************
	// *** Private members ***
	// ***********************
	//Formal parameter x becomes a private property
	var y, z; //other private properties (can only be read/changed by public methods or other private methods)
	var a = function() { //A private method (can only be called by public methods or other private methods)
		// ..... code
		// ..... code
	};

	// **********************
	// *** Public members ***
	// **********************
	return {
		set_x : function(newX) { //a public method
			//...... code to exectute before x is set (as required).
			x = newX;
			//...... code to exectute after x is set (as required).
		},
		doSomethingClever : function() { //another public method
			// ..... code
			// ..... code
		}
	};
}();

Have fun.

Airshow

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.