Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Dynamic Script Insertion Revisited

18 views
Skip to first unread message

Randy Webb

unread,
Aug 8, 2007, 12:56:17 PM8/8/07
to
In this thread:

<URL:
http://groups.google.com/group/comp.lang.javascript/browse_frm/thread/7e23f42490c301de/56d47ba8d4d73e30?lnk=gst&q=createtextnode+randy+webb&rnum=1#56d47ba8d4d73e30>

The problem was, and still is, that IE - no version - will allow you to
use createTextNode and then appendChild it to a Script element. It
throws a "Unexpected call to method or property access" error.

The only browsers, that I am aware of, that don't support createTextNode
on a SCRIPT element are IE/Win, IE/MAC, and iCAB3.0.3 (Is there a newer
iCAB?).

iCab and IE/mac support neither .text or .createTextNode so for this
code they have become part of the "Give up Randy, it won't work there"
group.

The browsers, again that I know of, that don't support the .text
property are:

IE/Mac
iCab3.0.3
Safari 1.3.2
Safari 2.0.4
Shiira 1.2.2
Sunrise 0.89

Safari surprised me on windows though as it supports .text, go figure.

Where it left me was wanting to use .createTextNode for support and then
falling back on the .text property.

What I ended up with is this:

var isIE = false;
/*@cc_on @*/
/*@if (@_jscript_version >= 4)
var isIE = true;
@end @*/

function executeJSString(stringToExecute){
var newScript = document.createElement('script');
newScript.type = "text/javascript";
if (isIE)
{
newScript.text = stringToExecute;
}
else
{
var s = document.createTextNode(stringToExecute);
newScript.appendChild(s);
}
document.getElementById("scriptDiv").appendChild(newScript);
}

Where "scriptDiv" is a container for script elements. The actual code
has code in it to empty the container so that I don't end up with
duplicate script blocks and/or excessive script elements.

The problem comes in if a browser, other than IE, supports .text and not
.createTextNode (or errors on it like IE does). That lead me to try to
set the .text property of a script element (on page load) to set a
variable and then branch on that variable. The problem there comes in
when the browser throws an error trying to set the .text property.

function insertScript(scriptContents) {
var useIt = false;
var newScript = document.createElement('script');
newScript.type = "text/javascript";
newScript.text = "var useText=true";
document.getElementById("myDiv").appendChild(newScript);
//end text insert section

var newScript = document.createElement('script');
newScript.type = "text/javascript";
if(useText){
newScript.text = scriptContents;
}
else{
var s = document.createTextNode(scriptContents);
newScript.appendChild(s);
}
document.getElementById("scriptDiv").appendChild(newScript);
}

I don't have a browser that doesn't support .text so I can't test it
thoroughly.

If anybody has any other ideas on a true feature detection approach
and/or that can test the above code on any non-windows browser I would
be gratefully appreciative.

Also, anybody that can test this page with a browser not listed (Other
than Netscape 4.xx series and lower) and give me the results of the 5
button clicks, I would again be gratefully appreciative.

<URL: http://members.aol.com/_ht_a/hikksnotathome/loadJSFile/>

--
Randy
Chance Favors The Prepared Mind
comp.lang.javascript FAQ - http://jibbering.com/faq/index.html
Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/

Stevo

unread,
Aug 8, 2007, 1:23:36 PM8/8/07
to
Randy Webb wrote:
> The problem was, and still is, that IE - no version - will allow you to
> use createTextNode and then appendChild it to a Script element. It
> throws a "Unexpected call to method or property access" error.

How about this:

var the_code = "alert('hello world');";
var newscript = document.createElement('script');
newscript.type = "text/javascript";
if(typeof newscript.text === 'string')
newscript.text = the_code;
else if(document.createTextNode)
newscript.appendChild(document.createTextNode(the_code));
document.getElementById("scriptDiv").appendchild(newscript);

Are there any browsers that don't support .text? I've just tried this
line in the address bar:

javascript:alert(typeof document.createElement('script').text)

in the following browsers and seen 'string' alerted.

Mac Safari 1.3
Win Safari 3.0
Win NS6.2
Win NS7.0
Win Firefox 2.0
Win IE7
Win Opera 9.2

[Steve]

Randy Webb

unread,
Aug 8, 2007, 3:53:04 PM8/8/07
to
Stevo said the following on 8/8/2007 1:23 PM:

> Randy Webb wrote:
>> The problem was, and still is, that IE - no version - will allow you
>> to use createTextNode and then appendChild it to a Script element. It
>> throws a "Unexpected call to method or property access" error.
>
> How about this:

The logic/testing is backwards from what I preferred and that is using
createTextNode if it can be successful and falling back on .text as a
second course. Even the code I posted goes about attempting .text first
and that logic may end up being the best route to go with.

> var the_code = "alert('hello world');";
> var newscript = document.createElement('script');
> newscript.type = "text/javascript";
> if(typeof newscript.text === 'string')
> newscript.text = the_code;
> else if(document.createTextNode)
> newscript.appendChild(document.createTextNode(the_code));
> document.getElementById("scriptDiv").appendchild(newscript);
>
> Are there any browsers that don't support .text? I've just tried this
> line in the address bar:

From my original post:

The browsers, again that I know of, that don't support the .text
property are:

IE/Mac
iCab3.0.3
Safari 1.3.2
Safari 2.0.4
Shiira 1.2.2
Sunrise 0.89

Can you test this page for me on a mac and either confirm or bust the
results for Safari?

<URL: http://members.aol.com/_ht_a/hikksnotathome/loadJSFile/>

The green/red/blue area scrolls but the scrollbars are not there. I need
to update it but can't get on AOL right now to upload a new one. The
results there say that Safari on a Mac doesn't execute scripts if you
assign it via the .text property. If that is true, and it shows that
string is typeof .text then it makes the test fallible and un-usable for me.

You should get an alert as the page loads that confirms the original
external file is loaded. Clicking each of the 5 buttons will do one of
three things:

1) Give you an alert telling you it was successful if the browser
supports that feature/method.
2) Throw an error.
3) Nothing. Indicating silent failure.

The five buttons, and what they attempt:

1) Change Source- attempts to change the .src property of a script element.
2) Change innerHMTL - inserts a script string via innerHTML.
3) createElement - uses createElement to create a script block with a
.src attribute.
4) Change .text - changes the .text property of a script element.
5) createTextNode - creates the text part of a script element using
createTextNode

RobG

unread,
Aug 8, 2007, 5:12:42 PM8/8/07
to
On Aug 9, 5:53 am, Randy Webb <HikksNotAtH...@aol.com> wrote:
[...]

> Can you test this page for me on a mac and either confirm or bust the
> results for Safari?
>
> <URL:http://members.aol.com/_ht_a/hikksnotathome/loadJSFile/>
>
> The green/red/blue area scrolls but the scrollbars are not there. I need
> to update it but can't get on AOL right now to upload a new one. The
> results there say that Safari on a Mac doesn't execute scripts if you
> assign it via the .text property. If that is true, and it shows that
> string is typeof .text then it makes the test fallible and un-usable for me.

That may be true for the version os Safari listed, Safari 3.0.3 on Mac
OS X 10.4.10 gives:

red, red, green, green, green.

which I think is consistent with what you reported for the Windows
version.

--
Rob

Stevo

unread,
Aug 8, 2007, 6:09:01 PM8/8/07
to
Randy Webb wrote:
> Stevo said the following on 8/8/2007 1:23 PM:
> The logic/testing is backwards from what I preferred and that is using
> createTextNode if it can be successful and falling back on .text as a
> second course.

OK. I thought maybe trying .text first was an alternative way to go.

> <URL: http://members.aol.com/_ht_a/hikksnotathome/loadJSFile/>


> You should get an alert as the page loads that confirms the original
> external file is loaded. Clicking each of the 5 buttons will do one of
> three things:

I'm not at work so can't try that on a Mac but I have tried it on IE and
Firefox on Windows and noticed something. Firstly, it's not the
createTextNode that fails. It's the appendChild right afterwards.
Something about that text node is un-appendchild-able. I compared the
properties of it between IE and Firefox and took a screenshot. I think
the textContent property of the textnode created could be a simple test.
For example, something like this might work:-

var the_code = "alert('hello world');";
var newscript = document.createElement('script');
newscript.type = "text/javascript";

var textnode=document.createTextNode(the_code);
if(textnode.textContent && textnode.textContent==the_code)
newscript.appendChild(textnode);
else if(typeof newscript.text === 'string')
newscript.text = the_code;
document.getElementById("scriptDiv").appendchild(newscript);

That if textnode.textContent test is checking for whether the text node
that was created is a good textnode and is appendchild-able. If it's
not, then try .text (if that property exists).

I'm sure your code won't end up looking anything like that, but it might
give you an idea for something inspired by it.

Here is the screenshot of the properties I saw:-

http://img513.imageshack.us/img513/169/createtextnodeoi9.jpg

You see IE on the left and Firefox on the right (with it's extra
property textContent). I put green blobs against the matching
properties. I hope this helps.

Richard Cornford

unread,
Aug 8, 2007, 7:01:04 PM8/8/07
to
Randy Webb wrote:
<snip>

> The problem was, and still is, that IE - no version - will
> allow you to use createTextNode and then appendChild it to
> a Script element.
<snip>

Internet Explorer Elements have a boolean - canHaveChildren - property.
For script elements it has a false value. It doesn't represent the whole
solution but I would think that if you found that a script element had
a - canHaveChildren - property of boolean type, and that it was false,
then attempting to add child nodes of any sort would look line a
non-viable activity.

Richard.

Randy Webb

unread,
Aug 8, 2007, 7:28:49 PM8/8/07
to
RobG said the following on 8/8/2007 5:12 PM:

Yes, it is consistent with the Windows version. I have added Safari
3.0.3 to the local file, thank you for the test.

Randy Webb

unread,
Aug 8, 2007, 7:47:09 PM8/8/07
to
Stevo said the following on 8/8/2007 6:09 PM:

> Randy Webb wrote:
>> Stevo said the following on 8/8/2007 1:23 PM:
>> The logic/testing is backwards from what I preferred and that is using
>> createTextNode if it can be successful and falling back on .text as a
>> second course.
>
> OK. I thought maybe trying .text first was an alternative way to go.

It might end up having to be.

>> <URL: http://members.aol.com/_ht_a/hikksnotathome/loadJSFile/>
>> You should get an alert as the page loads that confirms the original
>> external file is loaded. Clicking each of the 5 buttons will do one of
>> three things:
>
> I'm not at work so can't try that on a Mac but I have tried it on IE and
> Firefox on Windows and noticed something. Firstly, it's not the
> createTextNode that fails. It's the appendChild right afterwards.

Yes. It is because IE falls down on itself when you try to appendChild a
textNode created with createTextNode to a SCRIPT element.

> Something about that text node is un-appendchild-able.

It isn't the text node itself, but the container you are trying to
appendChild it to. IE just won't let you appendChild it to a SCRIPT
element. You can appendChild it to scriptDiv and it works flawlessly. It
is only when you appendChild it to a SCRIPT element that IE barfs all
over itself.


> I compared the properties of it between IE and Firefox and took a screenshot.
> I think the textContent property of the textnode created could be a simple test.
> For example, something like this might work:-
>
> var the_code = "alert('hello world');";
> var newscript = document.createElement('script');
> newscript.type = "text/javascript";
> var textnode=document.createTextNode(the_code);
> if(textnode.textContent && textnode.textContent==the_code)
> newscript.appendChild(textnode);

Internet Explorer 7 passes both of those tests and then barfs all over
the appendChild line.

> else if(typeof newscript.text === 'string')
> newscript.text = the_code;
> document.getElementById("scriptDiv").appendchild(newscript);
>
> That if textnode.textContent test is checking for whether the text node
> that was created is a good textnode and is appendchild-able. If it's
> not, then try .text (if that property exists).
> I'm sure your code won't end up looking anything like that, but it might
> give you an idea for something inspired by it.
> Here is the screenshot of the properties I saw:-
>
> http://img513.imageshack.us/img513/169/createtextnodeoi9.jpg
>
> You see IE on the left and Firefox on the right (with it's extra
> property textContent). I put green blobs against the matching
> properties. I hope this helps.

It did. If nothing else it told me another property that I can't test :(

Thanks for the help though.

Randy Webb

unread,
Aug 8, 2007, 8:27:04 PM8/8/07
to
Richard Cornford said the following on 8/8/2007 7:01 PM:

> Randy Webb wrote:
> <snip>
>> The problem was, and still is, that IE - no version - will
>> allow you to use createTextNode and then appendChild it to
>> a Script element.
> <snip>
>
> Internet Explorer Elements have a boolean - canHaveChildren - property.

Is IE the only one that implements canHaveChildren?

> For script elements it has a false value. It doesn't represent the whole
> solution but I would think that if you found that a script element had a
> - canHaveChildren - property of boolean type, and that it was false,
> then attempting to add child nodes of any sort would look line a
> non-viable activity.

if ((typeof(newScript.canHaveChildren) === 'boolean') &&
(newScript.canHaveChildren === false))

I don't think a test to see if it is false or not would be required but
probably wouldn't hurt to include it just in case some other browser is
out or comes out that implements canHaveChildren.

I have it noted in a Notes file I have on script insertion so that I can
go back to it and give it some more thought later.

Thanks Richard.

Richard Cornford

unread,
Aug 8, 2007, 9:09:31 PM8/8/07
to
Randy Webb wrote:
> Richard Cornford said the following on 8/8/2007 7:01 PM:
>> Randy Webb wrote:
>> <snip>
>>> The problem was, and still is, that IE - no version -
>>> will allow you to use createTextNode and then
>>> appendChild it to a Script element.
>> <snip>
>>
>> Internet Explorer Elements have a boolean - canHaveChildren -
>> property.
>
> Is IE the only one that implements canHaveChildren?

It is the only one I have noticed, but some manufacturers strive to
imitate IE and if they notice that the property exists they may well
reproduce it, but whilst doing so may not restrict the ability of the
script element to have children.

>> For script elements it has a false value. It doesn't represent
>> the whole solution but I would think that if you found that a
>> script element had a - canHaveChildren - property of boolean
>> type, and that it was false, then attempting to add child nodes
>> of any sort would look line a non-viable activity.
>
> if ((typeof(newScript.canHaveChildren) === 'boolean') &&
> (newScript.canHaveChildren === false))

Having verified that the property is of boolean type I would not bother
with the comparison in the second test. Just NOT - canHaveChildren -
would do.

> I don't think a test to see if it is false or not would be
> required but probably wouldn't hurt to include

I would say that the second test is necessary to complete the logic of
the test.

> it just in case some other browser is out or comes out that implements
> canHaveChildren.

And that as well.

> I have it noted in a Notes file I have on script insertion
> so that I can go back to it and give it some more thought later.

<snip>

If I had time to look at this properly I might look at putting a script
element on a page that had code contents and then examining it to see
what type of children it did have (if any). If Text node(s) then that
may be good grounds for particular actions. Though logically you could
suspect that some would (or may) have CDATASection nodes (nodeType ==
4), given that in HTML the contents of a scirpt are interpreted as
CDATA.

Richard.

Peter Michaux

unread,
Aug 8, 2007, 9:28:04 PM8/8/07
to
Hi Randy,

What is wrong with just trying the different approaches like below? No
sniffing, it can deal with errors and it checks if the insertion can
be successful. It is efficient after the first use.

Peter

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">

<html lang="en">
<head>
<title>Script Insertion Test</title>

<script type="text/javascript">

this.inserter = function(stringToExecute) {
// first time through do the initialization

// candidate inserters
var inserters = [
function(ste) {


var newScript = document.createElement('script');
newScript.type = "text/javascript";

newScript.text = ste;
document.getElementById("scriptDiv").appendChild(newScript);
},
function(ste) {


var newScript = document.createElement('script');
newScript.type = "text/javascript";

var s = document.createTextNode(ste);
newScript.appendChild(s);
document.getElementById("scriptDiv").appendChild(newScript);
}
];

// try the each candidate
for (var i=inserters.length; i--;) {
var inserter = inserters[i];
try {
inserter('this.testVar=true;');
if (window.testVar == true) {
// set window.insterter to the successful candidate
window.inserter = inserter;
return window.inserter(stringToExecute);
}
}
catch (e) {}
}

// none of the candidates worked
(window.inserter = function() {
throw new Error('Blame Randy.');
})();

}
</script>

<script type="text/javascript">
function testcase() {
window.inserter('alert("hi");');
}
</script>

</head>
<body>

<p onclick="testcase();">click me to see a hi alert</p>

<div id="scriptDiv"></div>

</body>
</html>

David Mark

unread,
Aug 8, 2007, 9:32:32 PM8/8/07
to
On Aug 8, 8:27 pm, Randy Webb <HikksNotAtH...@aol.com> wrote:
> Richard Cornford said the following on 8/8/2007 7:01 PM:
>
> > Randy Webb wrote:
> > <snip>
> >> The problem was, and still is, that IE - no version - will
> >> allow you to use createTextNode and then appendChild it to
> >> a Script element.
> > <snip>
>
> > Internet Explorer Elements have a boolean - canHaveChildren - property.
>
> Is IE the only one that implements canHaveChildren?

I believe it is IE5.5 and up. Other may have copied it, but it seems
doubtful.

>
> > For script elements it has a false value. It doesn't represent the whole
> > solution but I would think that if you found that a script element had a
> > - canHaveChildren - property of boolean type, and that it was false,
> > then attempting to add child nodes of any sort would look line a
> > non-viable activity.
>
> if ((typeof(newScript.canHaveChildren) === 'boolean') &&
> (newScript.canHaveChildren === false))
>
> I don't think a test to see if it is false or not would be required but
> probably wouldn't hurt to include it just in case some other browser is
> out or comes out that implements canHaveChildren.

I think you need to check the value unless you are just using it to
infer IE.

This seems like the solution:

function executeJSString(stringToExecute) {
var newScript = document.createElement('script');
newScript.type = "text/javascript";

if (document.createTextNode && (typeof(newScript.canHaveChildren) ==
'undefined' || (typeof(newScript.canHaveChildren) == 'Boolean' &&
newScript.canHaveChildren))) {


var s = document.createTextNode(stringToExecute);
newScript.appendChild(s);
}

else {
newScript.text = stringToExecute;
}

var div = document.getElementById("scriptDiv");
if (div) div.appendChild(newScript);
}

I tried it in IE6/7, Opera 9, FireFox 2, Windows Safari and Netscape
6.2. All but IE used createTextNode.

Randy Webb

unread,
Aug 8, 2007, 10:09:34 PM8/8/07
to
Peter Michaux said the following on 8/8/2007 9:28 PM:

> Hi Randy,
>
> What is wrong with just trying the different approaches like below? No
> sniffing, it can deal with errors and it checks if the insertion can
> be successful. It is efficient after the first use.

Main objection from me? I am still stuck in my old ways and don't care
for try/catch. Too many possible browsers that may still not support it.
I know my cell phone doesn't. Part of the reason I lovingly refer to it
as the "abomination I call my cell phone".

> // none of the candidates worked
> (window.inserter = function() {
> throw new Error('Blame Randy.');

I like that!

Randy Webb

unread,
Aug 8, 2007, 10:28:41 PM8/8/07
to
David Mark said the following on 8/8/2007 9:32 PM:

> On Aug 8, 8:27 pm, Randy Webb <HikksNotAtH...@aol.com> wrote:
>> Richard Cornford said the following on 8/8/2007 7:01 PM:
>>
>>> Randy Webb wrote:
>>> <snip>
>>>> The problem was, and still is, that IE - no version - will
>>>> allow you to use createTextNode and then appendChild it to
>>>> a Script element.
>>> <snip>
>>> Internet Explorer Elements have a boolean - canHaveChildren - property.
>> Is IE the only one that implements canHaveChildren?
>
> I believe it is IE5.5 and up. Other may have copied it, but it seems
> doubtful.
>
>>> For script elements it has a false value. It doesn't represent the whole
>>> solution but I would think that if you found that a script element had a
>>> - canHaveChildren - property of boolean type, and that it was false,
>>> then attempting to add child nodes of any sort would look line a
>>> non-viable activity.
>> if ((typeof(newScript.canHaveChildren) === 'boolean') &&
>> (newScript.canHaveChildren === false))
>>
>> I don't think a test to see if it is false or not would be required but
>> probably wouldn't hurt to include it just in case some other browser is
>> out or comes out that implements canHaveChildren.
>
> I think you need to check the value unless you are just using it to
> infer IE.

That is part of what I am trying to get away from is detecting/inferring IE.

> This seems like the solution:

It is a possible solution. I don't think there is a single one that can
be referred to as "the solution" though. As soon as it is, and a browser
mimics canHaveChildren or doesn't support createTextNode (itself or on a
SCRIPT Element), then you are back at the drawing board. If I knew,
without a doubt, that IE was the only one with a problem with
createTextNode then I would just keep using conditionals to trap IE and
let it go. Well, until some browser copies that as well.

> function executeJSString(stringToExecute) {
> var newScript = document.createElement('script');
> newScript.type = "text/javascript";
>
> if (document.createTextNode && (typeof(newScript.canHaveChildren) ==
> 'undefined' || (typeof(newScript.canHaveChildren) == 'Boolean' &&
> newScript.canHaveChildren))) {
> var s = document.createTextNode(stringToExecute);
> newScript.appendChild(s);
> }
> else {
> newScript.text = stringToExecute;

This branch as well is apt to fail as well. That is the other side of
the feature detection that I am working on. The only way I have come up
with to know - for sure - is to try to insert it with .text and see what
happens with it. I don't remember what the results were on mac browsers
that didn't support the .text avenue. Whether they threw errors or
failed silently.

The silent failure is why the data page that I keep doesn't have any
feature detection in it at all. That way you get a more accurate picture
of where a browser is failing.

> }
>
> var div = document.getElementById("scriptDiv");
> if (div) div.appendChild(newScript);
> }
>
> I tried it in IE6/7, Opera 9, FireFox 2, Windows Safari and Netscape
> 6.2. All but IE used createTextNode.

I think that testing on a mac is going to bear out those same results
with the exceptions of IE5.2 and iCab which support neither .text or
.createTextNode. The only saving grace with those two are that they
support inserting script elements via innerHTML and they will execute
them. Just another headache for me to work around :)

Thanks for the input and insight.

David Mark

unread,
Aug 8, 2007, 11:01:49 PM8/8/07
to

If it mimics it incorrectly then you would have problems, but if it
tells the truth about a node's ability to append a child, it will
work.

> SCRIPT Element), then you are back at the drawing board. If I knew,

If it doesn't support document.createTextNode then you end up trying
to use the text method. If it fails like IE and has no
canHaveChildren property, then you've got problems. I suspect IE is
the only one that will fail in this way, so it is lucky that it has
canHaveChildren to check.

> without a doubt, that IE was the only one with a problem with
> createTextNode then I would just keep using conditionals to trap IE and
> let it go. Well, until some browser copies that as well.

I don't think anyone will copy conditional comments or compilation It
would seem an insane thing to do as those features are specifically
designed to work around IE quirks. If they set out to write a quirky
IE-like browser, then perhaps. Regardless, it seems the
canHaveChildren feature test covers more bases than IE conditionals.

>
> > function executeJSString(stringToExecute) {
> > var newScript = document.createElement('script');
> > newScript.type = "text/javascript";
>
> > if (document.createTextNode && (typeof(newScript.canHaveChildren) ==
> > 'undefined' || (typeof(newScript.canHaveChildren) == 'Boolean' &&
> > newScript.canHaveChildren))) {
> > var s = document.createTextNode(stringToExecute);
> > newScript.appendChild(s);
> > }
> > else {
> > newScript.text = stringToExecute;
>
> This branch as well is apt to fail as well. That is the other side of
> the feature detection that I am working on.

Right. I didn't consider that part of it.

The only way I have come up
> with to know - for sure - is to try to insert it with .text and see what
> happens with it. I don't remember what the

That seems like a valid test to me, despite the creation of a dummy
variable. If the dummy variable is not set by the test then you are
left with innerHTML as a last resort.

results were on mac browsers
> that didn't support the .text avenue. Whether they threw errors or
> failed silently.

I would guess that they fail silently as the technique probably just
creates a new text property on the script element object. One
scenario that would error is if these Mac browsers support a read-only
text property for script elements. I guess you will have to try them,
but I thought your posted chart had test results for these browsers.

As for using try/catch, at the very least you could use it for your
initial test, which could reside in its own file. That way if it
fails to parse, the dummy variable is undefined, which would indicate
failure, but would not affect the other scripts on the page.

David Mark

unread,
Aug 9, 2007, 2:21:15 AM8/9/07
to
On Aug 8, 10:28 pm, Randy Webb <HikksNotAtH...@aol.com> wrote:
> David Mark said the following on 8/8/2007 9:32 PM:
>
>
>
>
>
> > On Aug 8, 8:27 pm, Randy Webb <HikksNotAtH...@aol.com> wrote:

[snip]

>
> Thanks for the input and insight.
>

No problem. I was sufficiently intrigued by this problem that I gave
it another go with the third branch included.

I think this should cover "everything" without resorting to try/
catch. I tested with the usual suspects. Other than the single dummy
variable, it is unobtrusive and results in a function that returns a
success flag.

BTW, I tried short-circuiting all but the innerHTML method and found
that it didn't work on Windows browsers at all (inserted script
doesn't execute.) I'm surprised it works on Mac versions.

var executeJSString, passed;
var oldOnLoad = window.onload;

window.onload = function() {
var div, scr;

function createScript() {
scr = document.createElement('script');
scr.type = 'text/javascript';
return scr;
}

function addScript() {
div.appendChild(scr);
scr = null;
}

function tryAdd() {
executeJSString('passed = true;');
}

if (document.getElementById) {


div = document.getElementById('scriptDiv');

var oldOnError = window.onerror;
window.onerror = function() {return true;};
if (div) {
if (document.createElement && div.appendChild) {
scr = createScript();
if (scr.appendChild && document.createTextNode &&
(typeof(scr.canHaveChildren) == 'undefined' ||
(typeof(scr.canHaveChildren) == 'Boolean' && scr.canHaveChildren))) {
executeJSString = function(stringToExecute) {
scr = createScript();
scr.appendChild(document.createTextNode(stringToExecute));
addScript();
return true;
}
tryAdd();
}
if (!passed) {
executeJSString = function(stringToExecute) {
scr = createScript();
scr.text = stringToExecute;
addScript();
return true;
}
tryAdd();
}
}
if (!passed && typeof(div.innerHTML) == 'string') {
executeJSString = function(stringToExecute) {
div.innerHTML = '<script type="text/javascript">' +
stringToExecute + '<\/script>';
return true;
}
tryAdd();
}
window.onerror = oldOnError;
}
}
if (!passed) {
executeJSString = function(stringToExecute) { return false; };
}
if (oldOnLoad) oldOnLoad();
};

David Mark

unread,
Aug 9, 2007, 5:30:46 AM8/9/07
to
On Aug 9, 2:21 am, David Mark <dmark.cins...@gmail.com> wrote:
> On Aug 8, 10:28 pm, Randy Webb <HikksNotAtH...@aol.com> wrote:
>
> > David Mark said the following on 8/8/2007 9:32 PM:
>
> > > On Aug 8, 8:27 pm, Randy Webb <HikksNotAtH...@aol.com> wrote:
>
> [snip]
>
>
>
> > Thanks for the input and insight.
>
> No problem. I was sufficiently intrigued by this problem that I gave
> it another go with the third branch included.

Oops. I just realized that my window.onerror afterthought has a
flaw. It should define the executeJSString the same as if all three
tests fail (and put the old error handler back.) And of course, if
one of the three fail with an error (something I tried to avoid with
feature detection throughout), the other tests won't be tried.

The only real value of the window.onerror handler in this example is
to prevent a script error from being reported to the user. The
alternative of using try/catch clauses for the tests you think might
cause an error (and putting the whole thing in its own file) is
looking like a better idea.

Richard Cornford

unread,
Aug 9, 2007, 4:40:17 PM8/9/07
to
David Mark wrote:

> On Aug 8, 8:27 pm, Randy Webb wrote:
>> Richard Cornford said the following on 8/8/2007 7:01 PM:
>>> Randy Webb wrote:
>>> <snip>
>>>> The problem was, and still is, that IE - no version - will
>>>> allow you to use createTextNode and then appendChild it to
>>>> a Script element.
>>> <snip>
>>
>>> Internet Explorer Elements have a boolean - canHaveChildren -
>>> property.
>>
>> Is IE the only one that implements canHaveChildren?
>
> I believe it is IE5.5 and up.

Your belief is false. Windows IE 5 certainly had this property. IE 4 may
also have had the property, as it was the browser that had 'children'
collections and the name of the property is not 'canHaveChildNodes'.

> Other may have copied it, but it seems
> doubtful.

It would not matter if they did, so long as they did not implement them
irrationally and attach true values to elements that would reject
attempts to add children.

<snip>


> This seems like the solution:
>
> function executeJSString(stringToExecute) {
> var newScript = document.createElement('script');
> newScript.type = "text/javascript";
>
> if (document.createTextNode && (
> typeof(newScript.canHaveChildren) == 'undefined' ||
> (typeof(newScript.canHaveChildren) == 'Boolean' &&
> newScript.canHaveChildren))) {

I don't see much point in testing the type of the property more than
once. It only seems worth checking that it is boolean and then branching
on its trueness if it is.

Though I would expect to see a test for an - appendChild - (and
possibly - insertBefore - ) method on the element, as the absence of
either might also be taken a good grounds for expecting the failure of
the attempt to add a new child.

Richard.

David Mark

unread,
Aug 9, 2007, 7:57:38 PM8/9/07
to
On Aug 9, 4:40 pm, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:

> David Mark wrote:
> > On Aug 8, 8:27 pm, Randy Webb wrote:
> >> Richard Cornford said the following on 8/8/2007 7:01 PM:
> >>> Randy Webb wrote:
> >>> <snip>
> >>>> The problem was, and still is, that IE - no version - will
> >>>> allow you to use createTextNode and then appendChild it to
> >>>> a Script element.
> >>> <snip>
>
> >>> Internet Explorer Elements have a boolean - canHaveChildren -
> >>> property.
>
> >> Is IE the only one that implements canHaveChildren?
>
> > I believe it is IE5.5 and up.
>
> Your belief is false. Windows IE 5 certainly had this property. IE 4 may
> also have had the property, as it was the browser that had 'children'
> collections and the name of the property is not 'canHaveChildNodes'.

Who said it was "canHaveChildNodes?"

>
> > Other may have copied it, but it seems
> > doubtful.
>
> It would not matter if they did, so long as they did not implement them
> irrationally and attach true values to elements that would reject
> attempts to add children.

Right.

>
> <snip>
>
> > This seems like the solution:
>
> > function executeJSString(stringToExecute) {
> > var newScript = document.createElement('script');
> > newScript.type = "text/javascript";
>
> > if (document.createTextNode && (
> > typeof(newScript.canHaveChildren) == 'undefined' ||
> > (typeof(newScript.canHaveChildren) == 'Boolean' &&
> > newScript.canHaveChildren))) {
>
> I don't see much point in testing the type of the property more than
> once. It only seems worth checking that it is boolean and then branching
> on its trueness if it is.

If it is undefined (all but IE) then you want to try createTextNode as
it often works. If it is boolean and true, then you also want to try
it, though this scenario never seems to come up and probably won't
until IE adds the ability to add children to a script element.

>
> Though I would expect to see a test for an - appendChild - (and
> possibly - insertBefore - ) method on the element, as the absence of
> either might also be taken a good grounds for expecting the failure of
> the attempt to add a new child.

I didn't add all of the feature testing needed to this snippet. I did
address all of the issues you mention in the next post. I think the
"full" solution covers everything, but I admittedly botched the
window.onerror handling.

I may post one more revision to this as I did come up with a way to
make the window.onerror trick work. I'll wait to see if try/catch is
deemed viable for the solution.

Randy Webb

unread,
Aug 11, 2007, 10:53:35 AM8/11/07
to
David Mark said the following on 8/9/2007 2:21 AM:

> On Aug 8, 10:28 pm, Randy Webb <HikksNotAtH...@aol.com> wrote:
>> David Mark said the following on 8/8/2007 9:32 PM:
>>> On Aug 8, 8:27 pm, Randy Webb <HikksNotAtH...@aol.com> wrote:
> [snip]
>> Thanks for the input and insight.
>>
>
> No problem. I was sufficiently intrigued by this problem that I gave
> it another go with the third branch included.

Welcome to HikkScript, I have been intrigued with dynamic JS insertion
for a very long time :) If it will give you some idea of how long, I can
load JS dynamically in Netscape 4.

> I think this should cover "everything" without resorting to try/
> catch. I tested with the usual suspects. Other than the single dummy
> variable, it is unobtrusive and results in a function that returns a
> success flag.
>
> BTW, I tried short-circuiting all but the innerHTML method and found
> that it didn't work on Windows browsers at all (inserted script
> doesn't execute.) I'm surprised it works on Mac versions.

I discovered it in very early versions of Netscape 6 in testing why
people couldn't get it to work in IE when it "works in Netscape". The
finding of it working in Mac browsers was a by product of me knowing it
worked on NS6/Win and giving it a whirl in Mac browsers by having the
innerHTML button on the test/date page.

I have been out of town the last 2 days and will give this a thorough
testing/lookover this weekend. The major thing this thread has found me
is the canHaveChildren property.

Randy Webb

unread,
Aug 11, 2007, 10:56:31 AM8/11/07
to
David Mark said the following on 8/9/2007 7:57 PM:

> On Aug 9, 4:40 pm, "Richard Cornford" <Rich...@litotes.demon.co.uk>
> wrote:
>> David Mark wrote:
>>> On Aug 8, 8:27 pm, Randy Webb wrote:
>>>> Richard Cornford said the following on 8/8/2007 7:01 PM:
>>>>> Randy Webb wrote:
>>>>> <snip>
>>>>>> The problem was, and still is, that IE - no version - will
>>>>>> allow you to use createTextNode and then appendChild it to
>>>>>> a Script element.
>>>>> <snip>
>>>>> Internet Explorer Elements have a boolean - canHaveChildren -
>>>>> property.
>>>> Is IE the only one that implements canHaveChildren?
>>> I believe it is IE5.5 and up.
>> Your belief is false. Windows IE 5 certainly had this property. IE 4 may
>> also have had the property, as it was the browser that had 'children'
>> collections and the name of the property is not 'canHaveChildNodes'.
>
> Who said it was "canHaveChildNodes?"

It is an inference. IE5 had childNodes. If IE4 had childNodes and not
the children collection, then the property would probably have been
named canHaveChildNodes, since it is named canHaveChildren then it
reasons that IE4 had the canHavechildren property and that is how it got
named.

dhtmlk...@gmail.com

unread,
Aug 30, 2007, 11:47:52 PM8/30/07
to
On Aug 8, 9:56 am, Randy Webb <HikksNotAtH...@aol.com> wrote:
> In this thread:
>
> <URL:http://groups.google.com/group/comp.lang.javascript/browse_frm/thread...>

>
> The problem was, and still is, that IE - no version - will allow you to
> use createTextNode and then appendChild it to aScriptelement. It

> throws a "Unexpected call to method or property access" error.
>
> The only browsers, that I am aware of, that don't support createTextNode
> on aSCRIPTelement are IE/Win, IE/MAC, and iCAB3.0.3 (Is there a newer
> Where "scriptDiv" is a container forscriptelements. The actual code

> has code in it to empty the container so that I don't end up with
> duplicatescriptblocks and/or excessivescriptelements.
>
> The problem comes in if a browser, other than IE, supports .text and not
> .createTextNode (or errors on it like IE does). That lead me to try to
> set the .text property of ascriptelement (on page load) to set a
Randy,

Can you include tests for scripts that have defer attribute?

That will have different results for innerHTML

_________________+ safari2/Mac | webkit/Mac(419.3)
change src | n | n |
change innerHTML | n | n |
createElement | Y | n |
change .text | n | Y |
createTextNode | Y | Y |


The chart will be more complete with testing the defer attribute on
innerHTML injections.

Garrett

Randy Webb

unread,
Aug 31, 2007, 1:12:42 AM8/31/07
to
dhtmlk...@gmail.com said the following on 8/30/2007 11:47 PM:

> On Aug 8, 9:56 am, Randy Webb <HikksNotAtH...@aol.com> wrote:

<snip>

>> <URL:http://members.aol.com/_ht_a/hikksnotathome/loadJSFile/>
>>
> Randy,
>
> Can you include tests for scripts that have defer attribute?

Are you saying that you get different results for Safari with and
without a defer attribute? The page, as written, has a defer attribute
in the script that it tries to insert via innerHTML.

> That will have different results for innerHTML
>
> _________________+ safari2/Mac | webkit/Mac(419.3)
> change src | n | n |
> change innerHTML | n | n |
> createElement | Y | n |
> change .text | n | Y |
> createTextNode | Y | Y |
>
>
> The chart will be more complete with testing the defer attribute on
> innerHTML injections.

I will add one in the next day or so that doesn't have a defer attribute
and see if any testing shows different results for them.

--
Randy
Chance Favors The Prepared Mind

comp.lang.javascript FAQ - http://jibbering.com/faq/index.html
Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/

Answer:It destroys the order of the conversation
Question: Why?
Answer: Top-Posting.
Question: Whats the most annoying thing on Usenet?

dhtmlk...@gmail.com

unread,
Aug 31, 2007, 4:27:18 PM8/31/07
to
On Aug 30, 10:12 pm, Randy Webb <HikksNotAtH...@aol.com> wrote:
> dhtmlkitc...@gmail.com said the following on 8/30/2007 11:47 PM:

>
> > On Aug 8, 9:56 am, Randy Webb <HikksNotAtH...@aol.com> wrote:
>
> <snip>
>
> >> <URL:http://members.aol.com/_ht_a/hikksnotathome/loadJSFile/>
>
> > Randy,
>
> > Can you include tests for scripts that have defer attribute?
>
> Are you saying that you get different results for Safari with and
> without a defer attribute? The page, as written, has a defer attribute
> in the script that it tries to insert via innerHTML.
>
no, I didn't actually look at your source code to see the defer
attribute.

> > That will have different results for innerHTML
>
> > _________________+ safari2/Mac | webkit/Mac(419.3)
> > change src | n | n |
> > change innerHTML | n | n |
> > createElement | Y | n |
> > change .text | n | Y |
> > createTextNode | Y | Y |
>

The column on the left represents a button in your test.

The other columns represent browsers. You can see that changing
".text" deosn't work in Safari 2, but does work in Webkit.

Webkit nightlies has lots of improvements over safari. Lots.

Garrett

> > The chart will be more complete with testing the defer attribute on
> > innerHTML injections.
>
> I will add one in the next day or so that doesn't have a defer attribute
> and see if any testing shows different results for them.
>
> --
> Randy
> Chance Favors The Prepared Mind

> comp.lang.javascript FAQ -http://jibbering.com/faq/index.html
> Javascript Best Practices -http://www.JavascriptToolbox.com/bestpractices/

Randy Webb

unread,
Aug 31, 2007, 5:29:03 PM8/31/07
to
dhtmlk...@gmail.com said the following on 8/31/2007 4:27 PM:

> On Aug 30, 10:12 pm, Randy Webb <HikksNotAtH...@aol.com> wrote:
>> dhtmlkitc...@gmail.com said the following on 8/30/2007 11:47 PM:
>>
>>> On Aug 8, 9:56 am, Randy Webb <HikksNotAtH...@aol.com> wrote:
>> <snip>
>>
>>>> <URL:http://members.aol.com/_ht_a/hikksnotathome/loadJSFile/>
>>> Randy,
>>> Can you include tests for scripts that have defer attribute?
>> Are you saying that you get different results for Safari with and
>> without a defer attribute? The page, as written, has a defer attribute
>> in the script that it tries to insert via innerHTML.
>>
> no, I didn't actually look at your source code to see the defer
> attribute.

I don't think it will ever matter but I am adding another button so that
there are two innerHTML buttons - one with and one without a defer
attribute. I am going to have to work on the layout of the page for
alignment so it may be a few days or so before I get an updated version
uploaded.

>>> That will have different results for innerHTML
>>> _________________+ safari2/Mac | webkit/Mac(419.3)
>>> change src | n | n |
>>> change innerHTML | n | n |
>>> createElement | Y | n |
>>> change .text | n | Y |
>>> createTextNode | Y | Y |
>
> The column on the left represents a button in your test.
>
> The other columns represent browsers. You can see that changing
> ".text" deosn't work in Safari 2, but does work in Webkit.
>
> Webkit nightlies has lots of improvements over safari. Lots.

Is Webkit a browser or an engine? Sounds like an ignorant question but I
honestly don't know what it is. Right now, I have it listed locally like
this:

WebKit 419.3 OS X 10.3.9

Is your OS different? Or, should it be listed differently?

Also, do you have any other browser/OS combinations that are not listed
on that page?

--
Randy
Chance Favors The Prepared Mind

0 new messages