PDA

View Full Version : Element.update()


Animal
10-10-2006, 09:20 AM
Using innerHTML to insert dynamically loaded code doesn't execute any <script> elements in that code.

Is it possible/worthwhile to search for scripts in the text?

A lot of the content of our system is going to be dynamically loaded into tabs or other containers by code which has no idea about the contents or functionality of the loaded content.

Those loaded pages themselves may need to use YUI, or yui-ext widgets.

As it stands now, dynamically loaded pages cannot use javascript widgets.

Would something like:


YAHOO.ext.Element.update = function(html)
{
this.dom.innerHTML = html;
var s = this.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])
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)
{
s0.text = s[i].text;
}
else
s0.src = s[i].src;
docHead.appendChild(s0);
}
}
};


work?

jack.slocum
10-10-2006, 11:39 AM
You might want to take a look at this page.

http://www.jackslocum.com/blog/examples/mixed-template.htm

Then you could define a renderer:

var MixedRenderer = {
render : function(el, response){
var tpl = new MixedTemplate(response.responseText);
tpl.overwrite(el, []);
tpl.evalScripts();
}
};

Then in your actual code, you'd assign the MixedRenderer to your update manager.

Animal
10-10-2006, 11:43 AM
Yes, I could write my own renderer which examines the received HTML for scripts. As you see from my example, I'd like to find scripts which have an src attribute too, as well as the ones with embedded source code.

jack.slocum
10-10-2006, 11:56 AM
Ok the first time I read your point I had just woken up. I re-read it again, this time going over the code line by line. I like it. That is a nice solution. I like where it is located too, since it will work on non-UpdateManager code as well.

There is only 1 change I would make:
YAHOO.ext.Element.update = function(html, loadScripts){...}

loadScripts being a boolean as to whether or not to parse for scripts.

This way, 1) existing code doesn't break, esp if someone already did a workaround, 2) it only spends the cpu cycles if needed.

I will also add a property to UpdateManager to toggle whether or not this is used.

Overall I really like the solution. Thanks for the great contribution.

Animal
10-10-2006, 12:01 PM
It probably needs more testing than I've been able to give it. It works on FF and IE with all the configurations of the <script> tag that I thought of. The RegExp is a bit tortured in order to try to cover all bases.

Animal
10-10-2006, 12:05 PM
Also, it might be a good idea, to delay the attempt to grab <script> elements from the dom element to give the parser time to create the DOM tree from the string. I don't know if that's done asynchronously or not.

jack.slocum
10-10-2006, 12:06 PM
Yes, a setTimeout is a good idea for FF.