Animal
25 Oct 2006, 2:13 AM
Currently, when updateManager.prototype.update() executes, the callback function, and the onUpdate method are fired as soon as the renderer.render() function returns.
The DOM element in question may not have been updated by then.
I've changed the processSuccess function to defer the callback and onUpdate firing into a callback function which is passed to renderer.render().
The renderer passes this function on to UpdateManager.prototype.update() which I've changed to perform postprocessing on the updated element.
Usually, this just consists of calling the callback, but may process scripts if the flag is set.
The postprocessing waits until a special, additional element with a known ID is present in the element.
I think this works well, and makes the event and callback sequence more logical. Often, you do want to wait for the document to be complete before, say activating a TabPanelItem. I think it makes a good enhancement to the library - Jack, do you want to add it?
YAHOO.ext.UpdateManager.prototype.processSuccess = function(response){
this.transaction = null;
// The callback function, and onUpdate are invoked by the renderer.
this.renderer.render(this.el, response, this, function()
{
this.onUpdate.fireDirect(this.el, response);
if(typeof response.argument.callback == 'function'){
response.argument.callback(this.el, true);
}
}.createDelegate(this));
if(response.argument.form && response.argument.reset){
try{ // put in try/catch since some older FF releases had problems with this
response.argument.form.reset();
}catch(e){}
}
};
YAHOO.ext.UpdateManager.BasicRenderer.prototype.render = function(el, response, updateManager, callback){
// The callback function is called by Element.update() after the DOM has been updated
el.update(response.responseText, updateManager.loadScripts, callback);
};
YAHOO.ext.Element.prototype.update = function(html, loadScripts, callback)
{
var dom = this.dom;
// Id of additional element added at the end of the innerHTML so that we
// can wait for its presence
var waitForId = YAHOO.util.Dom.generateId();
var totalWait = 0;
var postProcessor = function(){
// If we've been waiting less than half a second, and renderer has not caught up, wait again
if ((totalWait < 500) && (dom.lastChild.id !== waitForId))
{
totalWait += 10;
setTimeout(postProcessor, 10);
return;
}
if (loadScripts)
{
var s = dom.getElementsByTagName("script");
var docHead = document.getElementsByTagName("head")[0];
// For browsers which discard scripts when inserting innerHTML, extract the scripts using a RegExp
if(s.length == 0){
var re = /(?:<script.*(?:src=[\"\'](.*)[\"\']).*>.*<\/script>)|(?:<script.*>([\S\s]*?)<\/script>)/ig; // assumes HTML well formed and then loop through it.
var match;
while(match = re.exec(html)){
var s0 = document.createElement("script");
if (match[1])
s0.src = match[1];
else if (match[2])
if (YAHOO.util.Dom.isSafari)
s0.innerHTML = match[2];
else
s0.text = match[2];
else
continue;
docHead.appendChild(s0);
}
}else {
for(var i = 0; i < s.length; i++){
var s0 = document.createElement("script");
s0.type = s[i].type;
if (s[i].text) {
if (YAHOO.util.Dom.isSafari)
s0.innerHTML = s[i].text;
else
s0.text = s[i].text;
} else {
s0.src = s[i].src;
}
docHead.appendChild(s0);
}
}
}
// Callback
if(typeof callback == 'function'){
callback(this.dom, true);
}
delete postProcessor;
};
dom.innerHTML = html + "<span style=\"display:none\" id=\"" + waitForId + "\"></span>";
// Post process - this waits for the renderer to render element 'waitForId'
postProcessor();
};
The DOM element in question may not have been updated by then.
I've changed the processSuccess function to defer the callback and onUpdate firing into a callback function which is passed to renderer.render().
The renderer passes this function on to UpdateManager.prototype.update() which I've changed to perform postprocessing on the updated element.
Usually, this just consists of calling the callback, but may process scripts if the flag is set.
The postprocessing waits until a special, additional element with a known ID is present in the element.
I think this works well, and makes the event and callback sequence more logical. Often, you do want to wait for the document to be complete before, say activating a TabPanelItem. I think it makes a good enhancement to the library - Jack, do you want to add it?
YAHOO.ext.UpdateManager.prototype.processSuccess = function(response){
this.transaction = null;
// The callback function, and onUpdate are invoked by the renderer.
this.renderer.render(this.el, response, this, function()
{
this.onUpdate.fireDirect(this.el, response);
if(typeof response.argument.callback == 'function'){
response.argument.callback(this.el, true);
}
}.createDelegate(this));
if(response.argument.form && response.argument.reset){
try{ // put in try/catch since some older FF releases had problems with this
response.argument.form.reset();
}catch(e){}
}
};
YAHOO.ext.UpdateManager.BasicRenderer.prototype.render = function(el, response, updateManager, callback){
// The callback function is called by Element.update() after the DOM has been updated
el.update(response.responseText, updateManager.loadScripts, callback);
};
YAHOO.ext.Element.prototype.update = function(html, loadScripts, callback)
{
var dom = this.dom;
// Id of additional element added at the end of the innerHTML so that we
// can wait for its presence
var waitForId = YAHOO.util.Dom.generateId();
var totalWait = 0;
var postProcessor = function(){
// If we've been waiting less than half a second, and renderer has not caught up, wait again
if ((totalWait < 500) && (dom.lastChild.id !== waitForId))
{
totalWait += 10;
setTimeout(postProcessor, 10);
return;
}
if (loadScripts)
{
var s = dom.getElementsByTagName("script");
var docHead = document.getElementsByTagName("head")[0];
// For browsers which discard scripts when inserting innerHTML, extract the scripts using a RegExp
if(s.length == 0){
var re = /(?:<script.*(?:src=[\"\'](.*)[\"\']).*>.*<\/script>)|(?:<script.*>([\S\s]*?)<\/script>)/ig; // assumes HTML well formed and then loop through it.
var match;
while(match = re.exec(html)){
var s0 = document.createElement("script");
if (match[1])
s0.src = match[1];
else if (match[2])
if (YAHOO.util.Dom.isSafari)
s0.innerHTML = match[2];
else
s0.text = match[2];
else
continue;
docHead.appendChild(s0);
}
}else {
for(var i = 0; i < s.length; i++){
var s0 = document.createElement("script");
s0.type = s[i].type;
if (s[i].text) {
if (YAHOO.util.Dom.isSafari)
s0.innerHTML = s[i].text;
else
s0.text = s[i].text;
} else {
s0.src = s[i].src;
}
docHead.appendChild(s0);
}
}
}
// Callback
if(typeof callback == 'function'){
callback(this.dom, true);
}
delete postProcessor;
};
dom.innerHTML = html + "<span style=\"display:none\" id=\"" + waitForId + "\"></span>";
// Post process - this waits for the renderer to render element 'waitForId'
postProcessor();
};