This is my first post on stackoverflow, so please don't flame me too hard if I come across like a total nitwit or if I'm unable ot make myself perfectly clear. :-)
Here's my problem: I'm trying to write a javascript function that "ties" two functions to another by checking the first one's completion and then executing the second one.
The easy solution to this obviously would be to write a meta function that calls both functions within it's scope. However, if the first function is asynchronous (specifically an AJAX call) and the second function requires the first one's result data, that simply won't work.
My idea for a solution was to give the first function a "flag", i.e. making it create a public property "this.trigger" (initialized as "0", set to "1" upon completion) once it is called; doing that should make it possible for another function to check the flag for its value ([0,1]). If the condition is met ("trigger == 1") the second function should get called.
The following is an abstract example code that I have used for testing:
<script type="text/javascript" >
/**/function cllFnc(tgt) { //!! first function
this.trigger = 0 ;
var trigger = this.trigger ;
var _tgt = document.getElementById(tgt) ; //!! changes the color of the target div to signalize the function's execution
_tgt.style.background = '#66f' ;
alert('Calling! ...') ;
setTimeout(function() { //!! in place of an AJAX call, duration 5000ms
trigger = 1 ;
},5000) ;
}
/**/function rcvFnc(tgt) { //!! second function that should get called upon the first function's completion
var _tgt = document.getElementById(tgt) ; //!! changes color of the target div to signalize the function's execution
_tgt.style.background = '#f63' ;
alert('... Someone picked up!') ;
}
/**/function callCheck(obj) {
//alert(obj.trigger ) ; //!! correctly returns initial "0"
if(obj.trigger == 1) { //!! here's the problem: trigger never receives change from function on success and thus function two never fires
alert('trigger is one') ;
return true ;
} else if(obj.trigger == 0) {
return false ;
}
}
/**/function tieExc(fncA,fncB,prms) {
if(fncA == 'cllFnc') {
var objA = new cllFnc(prms) ;
alert(typeof objA + '\n' + objA.trigger) ; //!! returns expected values "object" and "0"
}
//room for more case definitions
var myItv = window.setInterval(function() {
document.getElementById(prms).innerHTML = new Date() ; //!! displays date in target div to signalize the interval increments
var myCallCheck = new callCheck(objA) ;
if( myCallCheck == true ) {
if(fncB == 'rcvFnc') {
var objB = new rcvFnc(prms) ;
}
//room for more case definitions
window.clearInterval(myItv) ;
} else if( myCallCheck == false ) {
return ;
}
},500) ;
}
</script>
The HTML part for testing:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/strict.dtd >
<html>
<head>
<script type="text/javascript" >
<!-- see above -->
</script>
<title>
Test page
</title>
</head>
<body>
<!-- !! testing area -->
<div id='target' style='float:left ; height:6em ; width:8em ; padding:0.1em 0 0 0; font-size:5em ; text-align:center ; font-weight:bold ; color:#eee ; background:#fff;border:0.1em solid #555 ; -webkit-border-radius:0.5em ;' >
Test Div
</div>
<div style="float:left;" >
<input type="button" value="tie calls" onmousedown="tieExc('cllFnc','rcvFnc','target') ;" />
</div>
<body>
</html>
I'm pretty sure that this is some issue with javascript scope as I have checked whether the trigger gets set to "1" correctly and it does. Very likely the "checkCall()" function does not receive the updated object but instead only checks its old instance which obviously never flags completion by setting "this.trigger" to "1". If so I don't know how to address that issue.
Anyway, hope someone has an idea or experience with this particular kind of problem.
Thanks for reading!
FK
I've worked it out and it seems to work perfectly well now. I will post my code later after I have sorted it out. In the meantime, thanks a lot for you assistance!
Update
Tried the code in Webkit (Safari, Chrome), Mozilla and Opera. Seems to work just fine. Looking forward to any replies.
Update 2
I changed the tieExc() method to integrate Anurag's chained function call syntax. Now you can call as many functions as you want upon completion check by passing them as arguments.
If you are not inclined to read the code, try it: http://jsfiddle.net/UMuj3/ (btw, JSFiddle is a really neat site!).
JS-Code:
/**/function meta() {
var myMeta = this ;
/** **/this.cllFnc = function(tgt,lgt) { //!! first function
this.trigger = 0 ; //!! status flag, initially zero
var that = this ; //!! required to access parent scope from inside nested function
var _tgt = document.getElementById(tgt) ; //!! changes the color of the target div to signalize the function's execution
_tgt.style.background = '#66f' ;
alert('Calling! ...') ;
setTimeout(function() { //!! simulates longer AJAX call, duration 5000ms
that.trigger = 1 ; //!! status flag, one upon completion
},5000) ;
} ;
/** **/this.rcvFnc = function(tgt) { //!! second function that should get called upon the first function's completion
var _tgt = document.getElementById(tgt) ; //!! changes color of the target div to signalize the function's execution
_tgt.style.background = '#f63' ;
alert('... Someone picked up!') ;
} ;
/** **/this.callCheck = function(obj) {
return (obj.trigger == 1) ? true
: false
;
} ;
/** **/this.tieExc = function() {
var functions = arguments ;
var myItv = window.setInterval(function() {
document.getElementById('target').innerHTML = new Date() ; //!! displays date in target div to signalize the interval increments
var myCallCheck = myMeta.callCheck(functions[0]) ; //!! checks property "trigger"
if(myCallCheck == true) {
clearInterval(myItv) ;
for(var n=1; n < functions.length; n++) {
functions[n].call() ;
}
} else if(myCallCheck == false) {
return ;
}
},100) ;
} ;
}
HTML:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/strict.dtd >
<html>
<head>
<script type='text/javascript' >
<!-- see above -->
</script>
<title>
Javascript Phased Execution Test Page
</title>
</head>
<body>
<div id='target' style='float:left ; height:7.5em ; width:10em ; padding:0.5em 0 0 0; font-size:4em ; text-align:center ; font-weight:bold ; color:#eee ; background:#fff;border:0.1em solid #555 ; -webkit-border-radius:0.5em ;' >
Test Div
</div>
<div style="float:left;" >
<input type="button" value="tieCalls()" onmousedown="var myMeta = new meta() ; var myCll = new myMeta.cllFnc('target') ; new myMeta.tieExc(myCll, function() { myMeta.rcvFnc('target') ; }, function() { alert('this is fun stuff!') ; } ) ;" /><br />
</div>
<body>
</html>